diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..ea1f951 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,8 @@ +{ + "permissions": { + "allow": [ + "Bash(wc:*)", + "Bash(git -C /workspaces/ai.interactive.fiction log --oneline -15)" + ] + } +} diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..2bd5a0a --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22 diff --git a/CLIENT_TODO.md b/CLIENT_TODO.md index 2fba969..a2922d3 100644 --- a/CLIENT_TODO.md +++ b/CLIENT_TODO.md @@ -1,165 +1,367 @@ -# Client Architecture Refactoring TODO List +# Client Specification And Progress Report -## Phase 1: Cleanup and Removal of Redundant Components +This file is the single living technical specification, implementation checklist, and progress report for the web client. Usage instructions and changelog live in `README.md`. -### High Priority Removals +## Product Goal -1. **TTSPlayerModule - Complete Removal** - - [X] Mark entire module for removal (completely redundant with SentenceQueueModule) - - [ ] Identify all references to TTSPlayerModule across the codebase - - [ ] Plan migration path for any UI components directly using TTSPlayerModule - - [ ] Update any event listeners that expect TTSPlayerModule events +Build an AI-assisted interactive fiction client that feels like a carefully typeset illustrated novel rather than a chat window. The game server owns game state and narrative generation. The client renders incoming narrative as synchronized animated prose with optional speech, sound effects, music, future image blocks, and persistent player options. -2. **UIDisplayHandlerModule Cleanup** - - [ ] Remove `pendingParagraphs` queue - - [ ] Remove `processNextParagraph()` method - - [ ] Refactor `displayText()` to be a thin wrapper for SentenceQueue +The production client must tolerate TTS being unavailable. The safe default TTS provider is `none`; a game, user preference, or explicit option can select another provider. -3. **KokoroTTSModule Cleanup** - - [ ] Remove `pendingGenerations` Map - - [ ] Refactor `generateSpeech()` to work directly with SentenceQueue - - [ ] Update iframe message handling to support the new architecture +## Current Status -4. **LayoutRendererModule Cleanup** - - [ ] Remove TTS triggering from `renderParagraph()` method - - [ ] Remove animation scheduling from rendering logic - - [ ] Separate layout rendering from animation timing +- Done: native ES module loader with dependency graph, module states, progress overlay, cache-busted development loading, and ordered async initialization. +- Done: responsive book layout that scales page, font sizes, and word positions relative to page size. +- Done: story parser for chapters, text blocks, Markdown emphasis, image blocks, sound effect cues, and music cues. +- Done: SmartyPants punctuation, language-aware Hyphenopoly integration, and Knuth-Plass paragraph line breaking. +- Done: paragraph rules for normal paragraphs, chapter-first paragraphs, textblock-first paragraphs, drop caps, and first-line indentation. +- Done: sentence queue and playback coordinator for preparing text and TTS before synchronized playback. +- Done: TTS providers for none, browser speech synthesis, Kokoro, ElevenLabs, and OpenAI, with status reporting in options. +- Done: TTS cache keyed by request parameters rather than text alone. +- Done: persisted speech enable state, provider, voice, speed, language, and volume preferences. +- Done: top-bar and options controls for speech and speed synchronization after recent fixes. +- Done: command input focus behavior and global typing redirection into the command input while a game is running. +- Done: fast-forward by page click or space, including animation completion and TTS fade/stop. +- Done: mouse cursor state reporting by process state. +- Done: placeholder game API for new/load/save/running state. +- Done: sound effect and music folders, sound effect playback, music playback, and music ducking during TTS. +- Partial: image markup is parsed and queued, but actual image rendering is still future work. +- Partial: save-game API is a placeholder; saves are per socket session and do not survive reload. +- Pending: deeper automated tests for layout, playback timing, TTS provider switching, and media cue timing. -### Additional Obsolete Components +## Module System Specification -1. **TextBufferModule Redundancies** - - [ ] Remove sentence preparation logic that will move to SentenceQueue - - [ ] Remove any temporary sentence storage mechanisms - - [ ] Identify and mark for removal any text processing that duplicates SentenceQueue functionality +The client uses native browser ES modules. No bundler is required for the web client modules in `public/js/`. -2. **AnimationQueueModule Overlaps** - - [ ] Identify animation scheduling that will be handled by SentenceQueue - - [ ] Remove redundant animation timing calculations - - [ ] Refactor to work as a service for SentenceQueue +Required module rules: -3. **TTSFactoryModule Redundancies** - - [ ] Remove any temporary audio storage that duplicates SentenceQueue functionality - - [ ] Refactor speech generation methods to work with SentenceQueue - - [ ] Streamline caching to avoid duplication with SentenceQueue +- Every app module extends `BaseModule`. +- Every app module registers with `moduleRegistry`. +- Every app module declares all required dependencies in its `dependencies` list. +- The loader loads module scripts, resolves the dependency graph, initializes modules in dependency order, awaits async initialization, and only then hides the loading overlay. +- Modules must rely on the loader for dependency readiness. Do not add fallback paths for missing dependencies inside modules. +- Module states are `PENDING`, `LOADING`, `WAITING`, `INITIALIZING`, `FINISHED`, and `ERROR`. +- Modules must report real state transitions. A module must not report `FINISHED` until its critical initialization is actually ready. +- `setTimeout` must not be used to paper over dependency or async ordering bugs. It is acceptable inside isolated scheduling systems such as animation timing, debounce, throttle, or browser rendering workarounds when documented by context. -4. **Event System Cleanup** - - [ ] Identify and remove redundant TTS-related events - - [ ] Remove text animation events that will be handled by SentenceQueue - - [ ] Consolidate playback state events +Core loader components: -## Phase 2: Enhanced SentenceQueueModule Implementation +- `loader.js`: dynamic import orchestration, dependency order, loading UI, cache-busted module URLs in development. +- `module-registry.js`: module registration, dependency metadata, readiness promises. +- `base-module.js`: shared lifecycle, state changes, event listener tracking, progress reporting. -### Core Structure and Design +The loader is deliberately the conductor, not the orchestra. Module-specific configuration, resource loading, and progress detail belong inside the module that owns the work. -1. **Design the Sentence Object Structure** - - [ ] Define comprehensive sentence object with fields for: - - Unique ID - - Original text - - Processed text (hyphenated, typeset) - - Layout information (breaks, nodes, typography) - - Audio component (player, duration, data, type) - - Status tracking (pending, processing, ready, playing, complete) +## Current Module Responsibilities -2. **Implement Basic Queue Management** - - [ ] Create methods for adding sentences to the queue - - [ ] Implement queue processing logic that maintains order - - [ ] Add status tracking for each sentence in the queue - - [ ] Implement priority handling for urgent sentences +- `markup-parser-module.js`: converts story text into text blocks, inline styled spans, image blocks, sound cues, and music cues. +- `text-processor-module.js`: applies SmartyPants and Hyphenopoly according to active language. +- `paragraph-layout-module.js`: measures text and computes Knuth-Plass layout. +- `layout-renderer-module.js`: turns layout data into page DOM with stable word positions and animation metadata. +- `sentence-queue-module.js`: prepares sentence objects and coordinates layout/TTS readiness. +- `playback-coordinator-module.js`: starts synchronized text/audio playback in the right order. +- `animation-queue-module.js`: schedules and fast-forwards visual text animation. +- `audio-manager-module.js`: owns sound effects, music tracks, music ducking, volume application, and speech audio playback helpers. +- `tts-factory-module.js`: selects provider, applies preferences, generates/preloads speech, caches speech data, and exposes unified TTS operations. +- `tts-handler-module.js`: common TTS handler base. +- `browser-tts-module.js`: Web Speech API provider. +- `kokoro-tts-module.js`: Kokoro provider and loading bridge. +- `elevenlabs-tts-module.js`: ElevenLabs provider. +- `openai-tts-module.js`: OpenAI speech provider with fixed supported voices. +- `persistence-manager-module.js`: browser preferences and durable client state. +- `localization-module.js`: language state used by UI, hyphenation, and TTS selection. +- `options-ui-module.js`: options modal, persisted controls, provider status displays. +- `ui-controller-module.js`: top-bar commands, global input behavior, game API control wiring. +- `ui-display-handler-module.js`: book page display, startup prompt, text insertion, and media block dispatch. +- `ui-input-handler-module.js`: command entry, history, fast-forward key handling. +- `socket-client-module.js`: socket connection and game API request wrapper. +- `game-loop-module.js`: high-level client/game flow. -### Text Processing Integration +## Text Layout Specification -1. **Integrate with Paragraph Layout** - - [ ] Connect to ParagraphLayoutModule for text processing - - [ ] Implement hyphenation and typesetting in the queue - - [ ] Store layout information in the sentence object - - [ ] Ensure layout processing happens in parallel with audio +The right page must look like typeset book text: -2. **Text Animation Preparation** - - [ ] Calculate animation timing based on text length and settings - - [ ] Prepare animation data for each word in the sentence - - [ ] Store animation timing in the sentence object - - [ ] Create animation player function for the sentence +- Paragraphs are laid out by paragraph, not as one continuous text run. +- Normal following paragraphs have a first-line indent. +- There is no blank line between ordinary paragraphs. +- A chapter marker creates a centered italic heading and makes the first following paragraph special. +- A textblock/section marker creates one line of vertical separation and makes the first following paragraph special. +- Special first paragraphs after chapter or textblock markers have no horizontal first-line indent. +- Chapter-first paragraphs use a drop cap aligned to an exact multiple of the body line height. Current target is a two-line drop cap unless visual testing justifies three lines. +- Lines are justified so line starts and line ends touch the intended measure. Final lines are not force-justified. +- Hyphenation must be real language-aware hyphenation from Hyphenopoly, not a fallback-only emergency split. +- Line breaking uses the Knuth-Plass algorithm over the full paragraph. +- Punctuation and short marks should not visually break the measure; optical margin handling is desirable future polish. +- The page must scale as a fixed-aspect book page. Font sizes and word positions scale with page size, preserving the composition when the window is resized. -### Audio Processing Integration +Processing order: -1. **TTS System Integration** - - [ ] Implement audio generation for Kokoro TTS - - [ ] Implement browser TTS handling with duration estimation - - [ ] Implement "none" TTS option with duration calculation - - [ ] Create consistent player interface for all TTS types +1. Parse block and inline story markup. +2. Remove media markers from display and TTS text while keeping cue positions. +3. Convert Markdown emphasis to inline style spans. +4. Apply SmartyPants typographic punctuation. +5. Apply Hyphenopoly for the active language. +6. Measure words/spans. +7. Run Knuth-Plass line breaking. +8. Render stable positioned spans. +9. Animate spans in sync with audio duration or estimated duration. -2. **Audio Data Management** - - [ ] Implement audio data storage in sentence objects - - [ ] Connect with TTSFactoryModule's IndexedDB for persistent caching - - [ ] Add audio preloading capabilities - - [ ] Implement audio resource cleanup +## Prototype Lessons To Preserve -### Playback Coordination +The prototype in `prototype/` and the former `PROTOTYPE_ANALYSIS.md` proved the target text pipeline. Any future layout refactor should preserve these details: -1. **Synchronized Playback** - - [ ] Implement coordinated text animation and audio playback - - [ ] Create timing adjustment based on speed settings - - [ ] Add event handling for playback states (start, pause, resume, complete) - - [ ] Implement sentence transition handling +- Hyphenopoly must emit pipe markers for hyphenation points through the `.hyphenatePipe` configuration. +- The layout measurement function must treat the pipe marker as zero width. +- `knuth-and-plass.js` must split text on spaces, punctuation separators, HTML tags, and pipe markers. +- Pipe markers become penalty nodes, not visible text. +- A visible hyphen is emitted only when the chosen line break uses a hyphenation penalty. +- Text measurement should use the same real CSS font, size, and style that the book page uses. +- Justification is applied through the Knuth-Plass break ratio by stretching or shrinking glue nodes. +- Hyphenated syllables after a penalty must be rendered as one visual word group, preserving the prototype's no-overlap behavior. +- The prototype used percentage-based positions so rendered text stayed proportional when the page scaled. -2. **User Interaction Handling** - - [ ] Add support for fast-forwarding text/audio - - [ ] Implement pause/resume functionality - - [ ] Handle user interruptions gracefully - - [ ] Support skipping to next sentence +Known inherited implementation note: the old `linked-list.js` analysis identified `get last()` returning `this.last` instead of `this.tail`, which can recurse if used. The current implementation should be checked and corrected before future line-breaking refactors rely on `last`. -## Phase 3: Module Interface Updates +## Story Markup Specification -1. **Update Module Interfaces** - - [ ] Create consistent interfaces for interacting with SentenceQueue - - [ ] Update event system to work with sentence objects - - [ ] Implement progress reporting for sentence processing - - [ ] Add debugging and monitoring capabilities +Markdown emphasis: -2. **Documentation and Examples** - - [ ] Document the new architecture and interfaces - - [ ] Create usage examples for common scenarios - - [ ] Update developer guidelines - - [ ] Add migration guide for existing code +```text +*italic* or _italic_ +**bold** or __bold__ +***bold italic*** or ___bold italic___ +``` -## Phase 4: Testing and Validation +Chapter: -1. **Unit Testing** - - [ ] Create tests for SentenceQueue core functionality - - [ ] Test text processing integration - - [ ] Test audio processing integration - - [ ] Test playback coordination +```text +::chapter[The Mysterious Mansion] -2. **Integration Testing** - - [ ] Test interaction between SentenceQueue and other modules - - [ ] Validate timing and synchronization - - [ ] Test error handling and recovery - - [ ] Verify performance under load +The first paragraph has a drop cap and no first-line indent. +``` -3. **User Experience Testing** - - [ ] Validate text animation quality - - [ ] Test audio playback quality - - [ ] Verify synchronization from user perspective - - [ ] Test accessibility features +The heading is centered, italic, and uses the body font size. Following ordinary paragraphs return to normal first-line indentation. -## Implementation Strategy +Section or text block: -1. **Phased Rollout** - - [ ] Complete cleanup of redundant components - - [ ] Implement SentenceQueue core structure - - [ ] Add text processing integration - - [ ] Add audio processing integration - - [ ] Implement playback coordination - - [ ] Gradually replace existing components +```text +::section -2. **Backward Compatibility** - - [ ] Maintain support for existing interfaces during transition - - [ ] Implement adapter patterns where needed - - [ ] Add feature flags for enabling/disabling new architecture - - [ ] Create fallback mechanisms for error recovery +The first paragraph is vertically separated from previous content and has no first-line indent. +``` -3. **Performance Optimization** - - [ ] Implement parallel processing where possible - - [ ] Optimize memory usage for sentence objects - - [ ] Add resource management for audio data - - [ ] Implement efficient queue processing algorithms +`::textblock` is an alias. Following ordinary paragraphs return to normal indentation. + +Images: + +```text +::image[widescreen](file-name.jpg) +::image[portrait](file-name.jpg) +``` + +File names resolve relative to `public/images/`. `widescreen` means full page width and half page height. `portrait` means full page width and full page height. Parsing is implemented; visual rendering is pending. + +Sound effects: + +```text +The old door opens {{sfx:squeaky-door.ogg}} into the dark. +``` + +File names resolve relative to `public/sounds/`. The marker is not displayed and is not sent to TTS. Playback starts when animation reaches the marker position. + +Music: + +```text +::music[crossfade, loop, lead=4](track.ogg) +{{music:cut:track.ogg}} +``` + +File names resolve relative to `public/music/`. Modes: + +- `queue`: wait until the current track ends. +- `crossfade`: fade from the current track into the new track. +- `cut`: stop the current track and start the new one immediately. +- `loop`: repeat the track. +- `once`: do not repeat the track. +- `lead=`: for block music, let music play alone before the following text/TTS paragraph starts. + +## TTS And Playback Specification + +The playback system must keep text animation and audio synchronized. + +- Complete sentences enter a preparation queue. +- TTS generation/preload starts as soon as possible, including while previous prepared sentences are playing. +- Text layout and TTS generation can be prepared in parallel. +- Playback of a sentence starts only when the required audio duration is known, or when TTS is disabled/unavailable and an estimated duration has been calculated. +- With measured TTS audio, animation duration follows the measured audio length. +- With TTS `none` or unavailable providers, duration is estimated from text length and speed. +- The speed slider is persisted and has normal speed at the center. +- Provider-specific speed ranges must be converted from the app-level speed value: + - OpenAI speech speed uses `1.0` as normal and supports a bounded multiplier. + - ElevenLabs speed must be clamped to its accepted range. + - Browser speech synthesis uses utterance rate. + - Kokoro uses its provider-supported speed option. + - `none` uses the same app-level speed to scale estimated animation duration. +- Switching provider, voice, language, or speed during gameplay should apply to the next not-yet-generated sentence. +- Kokoro is special: loading is expensive, so it should be loaded on startup only when selected and may require reload to switch into it. +- Fast-forward completes visible animation and fades/stops active TTS playback so the next sentence can start earlier. +- Music ducks to 70% of its configured volume while TTS playback is active, then fades back when the TTS playback queue is empty. + +TTS cache keys must include: + +- provider +- voice +- provider speed value +- language +- exact input string after markup/media removal + +When all cache parameters match, cached audio should be played instead of regenerated. + +OpenAI voices for the current speech endpoint are: + +- `nova` +- `shimmer` +- `echo` +- `onyx` +- `fable` +- `alloy` +- `ash` +- `sage` +- `coral` + +## Cursor And Interaction States + +The mouse cursor, not the text insertion caret, indicates process state. The command input caret keeps its normal text-editing appearance. + +Required states: + +- ready for new command +- command sent, waiting for game server answer +- waiting silently for required TTS generation before animation can continue +- audio and animation playing while another sentence is being generated +- audio and animation playing while no further generation is needed + +State changes should also be logged to the console during development. + +Typing behavior: + +- While a game is running, printable keyboard input should go to the command input regardless of the clicked element. +- Enter sends the command when input is non-empty. +- Space still inserts a space in the input, but if playback is active it also fast-forwards current playback. +- Clicking on the book while playback is active fast-forwards current playback. + +## Game API Specification + +The client/server game API supports: + +```text +newGame() +loadGame(slot) +saveGame(slot) +hasSaveGame(slot) +getSaveGames() +isGameRunning() +``` + +`slot` is a positive integer from `1` to the number of save slots exposed by the UI. + +Current placeholder behavior: + +- `newGame()` starts the demo game and emits the introduction/current room description. +- `saveGame(slot)` records a placeholder save for the current socket session. +- `hasSaveGame(slot)` checks that session-local placeholder save. +- `getSaveGames()` returns the saved slot numbers for the session. +- `loadGame(slot)` requires a placeholder save and then starts the demo game like `newGame()`. +- Saves do not persist across reloads yet. +- `isGameRunning()` returns true after a game starts and until the session ends. + +UI requirements before a game starts: + +- Command input is hidden. +- Right page shows the startup prompt. +- `new game` is enabled. +- `load` is enabled only when `hasSaveGame(slot)` is true. +- `save` is disabled. + +UI requirements after a game starts: + +- Command input is visible and focused. +- `save` is enabled. +- `load` reflects save availability. +- `new game` remains enabled and restarts the game. + +## Server And World Model + +The TypeScript server serves the web client and owns socket communication. The CLI and web modes use `GameRunner` and a YAML world file. + +Current development world: + +- Default file: `./data/worlds/example_world.yml` +- Server-side command handling is currently mirrored for UI testing: entered commands are sent to the server and returned as narrative text through the socket response path. + +Longer-term goal: + +- Keep a deterministic world model for rooms, objects, actions, state changes, and validation. +- Use the LLM to translate natural language player intent into game actions. +- Use the LLM to render state changes as prose without allowing hallucinated state. + +## Quality Rules + +- Preserve existing module boundaries when changing code. +- Prefer event-driven and Promise-based coordination over timing hacks. +- Do not use loader fallbacks to hide bad dependency declarations. +- Keep the book page visually stable under resizing. +- Validate typography visually after layout changes. +- Validate TTS timing with real provider playback and with TTS `none`. +- Treat the ad-blocker console error `onpage-dialog.preload.js:121 Uncaught ReferenceError: browser is not defined` as unrelated noise. + +## Progress Checklist + +### Completed + +- [x] Split monolithic prototype concepts into focused client modules. +- [x] Added loader, registry, base module, states, dependency declarations, and ordered initialization. +- [x] Added development cache busting and no-cache static file serving. +- [x] Added socket-backed game API wrapper. +- [x] Added manual game start flow for browser audio policies. +- [x] Added SmartyPants support. +- [x] Added Hyphenopoly support. +- [x] Added Knuth-Plass paragraph layout. +- [x] Fixed overfull words, incorrect spacing, and hyphenation integration regressions from the prototype migration. +- [x] Added chapter heading and dropcap markup. +- [x] Added section/textblock markup. +- [x] Added Markdown emphasis parsing. +- [x] Added image markup parsing for future image rendering. +- [x] Added sound effect markup and playback. +- [x] Added music markup, playback modes, loop/once, and lead-in. +- [x] Added music ducking during TTS. +- [x] Added TTS `none` mode. +- [x] Added OpenAI TTS support and restricted OpenAI voice list. +- [x] Added ElevenLabs speed clamping. +- [x] Added persisted speed and speech state. +- [x] Added speech toggle synchronization between top bar and options. +- [x] Added volume controls for speech, music, and sound effects. +- [x] Added command input focus and global typing behavior. +- [x] Added command mirroring through the server path for UI testing. +- [x] Added fast-forward for animation and TTS fade/stop. + +### In Progress + +- [ ] Keep validating provider-specific speed conversion for all TTS providers against real API behavior. +- [ ] Tighten automated checks around top-bar/options state initialization after reload. +- [ ] Improve automated visual regression coverage for page scaling, dropcap line-height alignment, and paragraph indentation. +- [ ] Improve automated audio tests for music ducking, sound effect timing, and fast-forward fadeout. + +### Pending + +- [ ] Implement image rendering for `::image[widescreen]` and `::image[portrait]`. +- [ ] Replace placeholder save implementation with durable save files or server-side save storage. +- [ ] Replace command mirroring with the full LLM/world-model command loop when typography/audio testing no longer needs mirroring. +- [ ] Add optical margin alignment or punctuation protrusion support for line endings. +- [ ] Add more provider readiness tests and richer diagnostics in options. +- [ ] Add unit tests for `SentenceQueue`, markup parsing, TTS cache key generation, and game API methods. +- [ ] Add browser integration tests for module loading, new-game startup, command input behavior, and playback controls. + +## Consolidation Notes + +The durable content from the former root and `references/` documents has been merged here or into `README.md`. The old reference files should remain untouched until the user approves cleanup, but they are no longer intended as the source of truth. diff --git a/PROTOTYPE_ANALYSIS.md b/PROTOTYPE_ANALYSIS.md new file mode 100644 index 0000000..d02de86 --- /dev/null +++ b/PROTOTYPE_ANALYSIS.md @@ -0,0 +1,311 @@ +# Prototype Text Pipeline Analysis + +## Overview +The prototype uses a sophisticated text processing pipeline that achieves professional typography through: +1. SmartyPants (typographic punctuation) +2. Hyphenopoly (hyphenation with pipe markers) +3. Knuth-Plass algorithm (optimal line breaking) +4. Precise character-by-character width measurement +5. Justification ratio application + +## Complete Text Flow (Prototype) + +``` +User Text + ↓ +SmartyPants.smartypantsu(text, 1) + ↓ [Converts quotes, dashes to typographic characters] +hyphenator_en(..., '.hyphenatePipe') + ↓ [Inserts | at hyphenation points] +kap(..., measureText, measure.toReversed(), true) + ↓ [Knuth-Plass line breaking] +typesetParagraph(paragraph_data, delay, measure) + ↓ [DOM creation with justification] +Rendered paragraph with proper spacing +``` + +## Key Components + +### 1. Text Preprocessing (game.js:698) + +```javascript +var preview_data = kap( + hyphenator_en( + SmartyPants.smartypantsu(text, 1), + '.hyphenatePipe' // ← CRITICAL: Uses pipe character + ), + measureText, + measure.toReversed(), + true // ← hyphenation enabled +); +``` + +**Purpose**: Creates nodes with accurate widths and hyphenation points + +### 2. Character Width Measurement (game.js:380-406) + +```javascript +function measureText(str) { + // Special cases + if(str.substr(0, 2) == ')/u).forEach(function (fragment) { + if (fragment === ' ') { + // Create glue with stretch/shrink + nodes.push(linebreak.glue(spaceWidth, stretch, shrink)); + } else if (fragment === '|') { + // Create penalty node for hyphenation point + nodes.push(linebreak.penalty(hyphenWidth * 0.25, 100, 1)); + } else { + // Create box node for word + nodes.push(linebreak.box(fragmentWidth, fragment)); + } + }); + + // Run Knuth-Plass algorithm + let breaks = linebreak(nodes, measure, { tolerance: 3, demerits }); + + return { nodes, breaks }; +} +``` + +**Node Types**: +- **box**: Word with fixed width (cannot break) +- **glue**: Space with stretch/shrink (for justification) +- **penalty**: Potential break point (like hyphen) with cost + +### 5. Rendering with Justification (game.js:295-378) + +```javascript +function typesetParagraph(paragraph_data, delay = 0, measure = []) { + // Create paragraph container + let p = document.createElement("p"); + p.style.position = 'relative'; + p.style.height = lineHeight * (paragraph_data.breaks.length - 1) + 'px'; + + // Iterate through lines + for(let i = 1; i < paragraph_data.breaks.length; i++) { + let left = 0; + let ratio = paragraph_data.breaks[i].ratio; // ← JUSTIFICATION RATIO + + // Iterate through nodes on this line + for(let j = paragraph_data.breaks[i-1].position; j <= paragraph_data.breaks[i].position; j++) { + let node = paragraph_data.nodes[j]; + + if(node.type === 'box') { + // Handle hyphenated syllables (lines 316-320) + if(j > paragraph_data.breaks[i-1].position + 1 && + paragraph_data.nodes[j-1].type === 'penalty' && lastChild) { + // Combine with previous syllable + syllable += '\u200c' + node.value; // Zero-width non-joiner + lastChild.innerHTML = syllable; + left += node.width; + } else { + // Create new word span + let word = document.createElement("span"); + word.style.position = 'absolute'; + word.style.top = lineHeight * (i - 1) * 100 / paragraph_height + '%'; + word.style.left = left * 100 / line_width + '%'; + word.innerHTML = node.value; + p.appendChild(word); + left += node.width; + } + } + else if(node.type === 'glue') { + // ← CRITICAL: Apply justification ratio to glue + if(ratio > 0) { + left += node.width + ratio * node.stretch; + } else { + left += node.width + ratio * node.shrink; + } + } + else if(node.type === 'penalty' && node.penalty === 100 && j === breaks[i].position) { + // Add hyphen at line break + let word = document.createElement("span"); + word.innerHTML = "-"; + p.appendChild(word); + } + } + } + + return [p, delay]; +} +``` + +**Key Points**: +1. **Justification**: Glue widths are adjusted by `ratio * stretch` or `ratio * shrink` +2. **Hyphenation**: Syllables after penalty nodes are combined with previous word using zero-width non-joiner +3. **Positioning**: All words use `position: absolute` with percentage-based coordinates + +## Current Implementation Issues + +### Issue 1: Text Processing Pipeline + +**Current** (sentence-queue-module.js:266): +```javascript +const processedText = textProcessor ? await textProcessor.process(text) : text; +``` + +**Problem**: +- `textProcessor.process()` may not pass the correct selector to Hyphenopoly +- Hyphenopoly needs `.hyphenatePipe` selector to use pipe characters + +**Fix Needed**: +```javascript +const processedText = textProcessor ? + await textProcessor.hyphenate( + textProcessor.smartyPants(text), + '.hyphenatePipe' + ) : text; +``` + +### Issue 2: Hyphenation with Pipe Character + +**Current** (text-processor-module.js:275-286): +```javascript +hyphenate(text) { + if (!this.isHyphenationAvailable()) return text; + try { + return this.hyphenator(text); // ← No selector parameter + } catch (error) { + console.error("Error hyphenating text:", error); + return text; + } +} +``` + +**Fix Needed**: Add selector parameter +```javascript +hyphenate(text, selector = null) { + if (!this.isHyphenationAvailable()) return text; + try { + return selector ? + this.hyphenator(text, selector) : + this.hyphenator(text); + } catch (error) { + console.error("Error hyphenating text:", error); + return text; + } +} +``` + +### Issue 3: Knuth-Plass Not Using Pipe Characters + +**Current** (public/js/knuth-and-plass.js): +- May not properly split on pipe characters +- May not create penalty nodes + +**Fix Needed**: Ensure knuth-and-plass.js matches prototype implementation + +### Issue 4: Syllable Combination in Rendering + +**Current** (layout-renderer-module.js): +- Does NOT combine hyphenated syllables +- Missing logic for `if(nodes[j-1].type === 'penalty' && lastChild)` + +**Fix Needed**: Add syllable combination logic when rendering box nodes after penalty nodes + +### Issue 5: Missing #ruler Element + +**Current**: No `#ruler` element for text measurement + +**Fix Needed**: +1. Add `
` to HTML +2. Use ruler for character width measurement in paragraph-layout-module.js + +## Implementation Plan + +### Phase 1: Fix Text Processing Pipeline + +1. **Update text-processor-module.js**: + - Add `selector` parameter to `hyphenate()` method + - Update `process()` to pass `.hyphenatePipe` selector + +2. **Update sentence-queue-module.js**: + - Pass `.hyphenatePipe` selector when calling text processor + - Ensure processedText includes pipe characters + +### Phase 2: Fix Knuth-Plass Integration + +1. **Verify knuth-and-plass.js**: + - Ensure it splits on `\|` character + - Creates `penalty` nodes with cost 100 + - Handles HTML tags properly + +2. **Update paragraph-layout-module.js**: + - Ensure `measureText()` returns 0 for `|` character + - Use `#ruler` element for measurement + - Handle HTML tag stack properly + +### Phase 3: Fix Rendering with Justification + +1. **Update layout-renderer-module.js**: + - Add syllable combination logic for hyphenated words + - Apply justification ratios to glue widths correctly + - Add hyphens at line breaks when penalty node is at break position + +2. **Fix spacing issues**: + - Create space spans with adjusted widths + - Use zero-width non-joiner for syllable combination + +### Phase 4: Testing & Refinement + +1. **Test with simple text**: "This is a test." +2. **Test with hyphenation**: Long words that span lines +3. **Test with justification**: Full paragraphs +4. **Test with special characters**: Quotes, dashes, etc. + +## Success Criteria + +✅ SmartyPants converts quotes correctly +✅ Hyphenopoly inserts pipe characters +✅ Knuth-Plass creates proper breaks with hyphenation +✅ Words don't overlap +✅ Words have proper spacing (not smushed) +✅ Justification works (even spacing across line width) +✅ Hyphens appear at line breaks +✅ Drop caps and indentation work diff --git a/README.md b/README.md index 6096679..ae06ab4 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,186 @@ -# AI Interactive Fiction - -A modern take on classic text adventures that combines traditional world modeling with Large Language Models (LLMs) to create natural language interactive fiction experiences. - -## Project Overview - -This application reimagines the classic text adventure game genre by replacing the traditional parser with an LLM. The system consists of: - -1. **World Model**: A traditional game engine that manages rooms, objects, actions, and game state - similar to old-school Infocom games. - -2. **LLM Interface**: An AI layer that processes natural language input from players and translates it into actions the game engine can understand. - -3. **Narrative Generation**: The LLM converts the world state changes into rich, contextual prose for the player. - -## Key Features - -- **Natural Language Understanding**: Players can express their intent in plain language without worrying about specific command syntax. -- **Rich Narrative**: Dynamic descriptions that adapt to the current game state and player history. -- **Consistent World Model**: The underlying game engine enforces world rules to prevent hallucinations or inconsistencies. -- **Modular Design**: Easily swap between different world models, including YAML-based custom worlds or integrations with classic Z-machine games. - -## How It Works - -1. Player enters natural language input -2. LLM analyzes input and translates it into game actions -3. Game engine processes valid actions and updates the game state -4. LLM receives the state change information and generates narrative prose -5. Player receives the beautifully written response - -## Technical Structure - -- YAML-based world definition (rooms, objects, actions) -- OpenRouter API integration for accessing suitable LLMs -- Modular design allowing for Z-machine integration in the future - -## Getting Started - -[Installation and running instructions will be added here] \ No newline at end of file +# AI Interactive Fiction + +AI Interactive Fiction is a web and CLI text adventure prototype that combines a deterministic world model with LLM-assisted command interpretation and narrative output. The web client presents the story as an animated, novel-like book page with synchronized text animation, optional TTS, music, and sound effects. + +## Quick Start + +Use Node.js 22 LTS for development. The project accepts Node >= 18.17, but current development has been done on Node 22. + +```powershell +nvm install 22 +nvm use 22 +npm install +npm run build +npm run dev +``` + +The web app starts on `http://localhost:3000` when launched through `src/index.ts` or `dist/index.js`. The lower-level server module defaults to `3001` when started directly. Set `PORT` to choose a port; the server will try the next few ports if the requested one is already in use. + +## Commands + +```powershell +npm run dev # Start the web UI through ts-node/nodemon +npm run start # Run the compiled web server from dist/ +npm run build # Compile TypeScript +npm run test # Run Jest tests +npm run lint # Run ESLint on src/ +npm run start:cli # Run the CLI interface +npm run dev:cli # Run the CLI interface through ts-node/nodemon +``` + +## Configuration + +Environment variables are loaded from `.env`. + +- `PORT`: preferred web server port. +- `DEFAULT_WORLD_FILE`: YAML world file to load. Defaults to `./data/worlds/example_world.yml`. +- `OPENROUTER_API_KEY`: API key for LLM command interpretation. +- `OPENROUTER_MODEL`: OpenRouter model name. + +TTS provider settings are configured in the browser options menu and persisted in browser storage. Providers currently include `none`, browser speech synthesis, Kokoro, ElevenLabs, and OpenAI. Production should not assume a universal TTS default; the game or player state selects the active mode, and `none` is the safe fallback. + +## Starting A Game + +The web client no longer starts the game automatically. Browsers require a user gesture before audio playback, so the right page initially shows a start prompt and the command input is hidden. Use `new game` or `load` in the top bar to start. + +The placeholder server API supports: + +- `newGame()` +- `loadGame(slot)` +- `saveGame(slot)` +- `hasSaveGame(slot)` +- `getSaveGames()` +- `isGameRunning()` + +Save slots are positive integers. In the current placeholder implementation, save availability is per socket session and is lost on reload. Loading a save starts the demo content like `newGame()`. + +## Web Client + +The browser app is built from native ES modules in `public/js/`. The loader dynamically imports modules, applies a cache-busting query string during development, resolves declared dependencies, and awaits module initialization in dependency order before the UI becomes usable. + +Major modules: + +- `module-registry.js`, `base-module.js`, `loader.js`: module lifecycle, dependency graph, progress overlay, state reporting. +- `text-processor-module.js`, `paragraph-layout-module.js`, `layout-renderer-module.js`: SmartyPants, language-aware hyphenation, Knuth-Plass line breaking, DOM rendering. +- `markup-parser-module.js`: story markup for chapters, sections, Markdown emphasis, images, SFX, and music. +- `sentence-queue-module.js`, `playback-coordinator-module.js`, `animation-queue-module.js`: sentence preparation, synchronized playback, timing, fast-forward. +- `tts-factory-module.js` plus provider modules: TTS provider selection, voice settings, speed mapping, caching, and playback. +- `audio-manager-module.js`: master, speech, music, and sound effect volume, music playback, sound effects, and music ducking. +- `ui-controller-module.js`, `ui-display-handler-module.js`, `ui-input-handler-module.js`, `options-ui-module.js`: book UI, command input, options, top-bar controls, and game API calls. + +The static server sends no-cache headers for local development so stale ES modules do not mask changes. If the browser console shows `onpage-dialog.preload.js:121 Uncaught ReferenceError: browser is not defined`, ignore it; that comes from the installed ad blocker, not this project. + +## Story Markup + +Plain paragraphs are rendered paragraph by paragraph. Normal following paragraphs are horizontally indented and do not get a blank line between them. Special block markers change the treatment of the next paragraph. + +Inline Markdown emphasis: + +```text +*italic* or _italic_ +**bold** or __bold__ +***bold italic*** or ___bold italic___ +``` + +Chapter: + +```text +::chapter[The Mysterious Mansion] + +The first paragraph uses a drop cap and no first-line indent. + +Following paragraphs use the normal paragraph indent. +``` + +The heading is centered, italic, and uses the same text face as the body. The first paragraph after a chapter marker is unindented and receives the drop cap treatment. + +Section or text block: + +```text +::section + +The first paragraph starts a separated block without horizontal indent. + +The following paragraph returns to the normal indent. +``` + +`::textblock` is treated the same way. The first paragraph after the marker is separated from previous content by one line of vertical space. + +Images are parsed for future rendering: + +```text +::image[widescreen](mansion-rain.jpg) +::image[portrait](portrait-letter.jpg) +``` + +Image file names are relative to `public/images/`. `widescreen` means 100% page width and 50% page height. `portrait` means 100% page width and 100% page height. + +Sound effects can be placed inline: + +```text +The door opens {{sfx:squeaky-door.ogg}} and the hall exhales. +``` + +The marker is removed from display text and TTS text. It becomes a timed media cue that fires when the text animation reaches that point. Sound effect paths are relative to `public/sounds/`. + +Music can be placed as a block: + +```text +::music[crossfade, loop, lead=4](rain-theme.ogg) +``` + +Music can also be placed inline: + +```text +The candles gutter. {{music:cut:danger.ogg}} Something moves upstairs. +``` + +Music paths are relative to `public/music/`. Supported modes are `queue`, `crossfade`, and `cut`. Use `loop` or `once` to control repetition. `lead=` delays the following text/TTS paragraph so the music can play alone before narration continues. + +## Assets + +- `public/sounds/`: sound effects referenced by `{{sfx:file}}`. +- `public/music/`: background music referenced by `::music[...]` or `{{music:mode:file}}`. +- `public/images/`: story images referenced by `::image[...]`. +- `public/fonts/`: font assets used by the book UI. + +Keep third-party assets licensed for local redistribution, and document source and license in the folder README or alongside the file. + +## Typography And Playback Behavior + +The renderer is designed to behave like a scaled static book page. The page keeps its aspect ratio, and text sizes and word positions scale relative to the page instead of reflowing unpredictably at small browser sizes. + +Text processing order: + +1. Parse story markup and remove non-display media markers. +2. Apply Markdown emphasis spans. +3. Run SmartyPants for typographic punctuation. +4. Apply Hyphenopoly for the selected language. +5. Calculate line breaks with the Knuth-Plass algorithm. +6. Render absolutely positioned word spans and animate them in sync with audio or estimated duration. + +When real TTS audio is available, animation duration is driven by measured audio length. With TTS disabled or unavailable, duration is estimated from text length and the persisted speed setting. + +Fast-forwarding by page click or space completes the active animation and fades/stops current TTS playback so queued content can proceed. + +## Changelog + +### 2026-05-14 + +- Consolidated usage, markup, and architecture documentation into `README.md` and `CLIENT_TODO.md`. +- Added no-cache static serving and module URL cache busting so browser reloads pick up JS changes reliably during development. +- Fixed module loader dependency ordering so modules are initialized only after their declared dependencies are ready. +- Added the placeholder game API for `newGame`, `loadGame`, `saveGame`, `hasSaveGame`, `getSaveGames`, and `isGameRunning`. +- Changed the web UI to require a manual game start before showing the command input, which keeps browser audio autoplay restrictions manageable. +- Implemented story markup for chapters, text blocks, Markdown emphasis, image placeholders, sound effects, and music cues. +- Added music block parameters for playback mode, loop/once behavior, and lead-in delay. +- Added sound and music asset folders and playback plumbing for sound effects and background music. +- Added music ducking while TTS is active. +- Reworked book typography around Knuth-Plass line breaking, Hyphenopoly hyphenation, SmartyPants, paragraph indentation rules, drop caps, and responsive page scaling. +- Reworked TTS provider behavior, speed mapping, persistence, caching keys, top-bar/options synchronization, and OpenAI voice validation. +- Added development notes for ignoring the unrelated ad-blocker console error. + +### Earlier Prototype Work + +- Established the original animated fiction prototype with inkjs, SmartyPants, Hyphenopoly, Knuth-Plass line breaking, custom animation scheduling, save/load concepts, and media tags. +- Split the client from a monolithic prototype into focused modules for text processing, layout, animation, audio, persistence, TTS, and UI control. diff --git a/data/worlds/example_world.yml b/data/worlds/example_world.yml index 8668b0e..e2841d7 100644 --- a/data/worlds/example_world.yml +++ b/data/worlds/example_world.yml @@ -2,10 +2,15 @@ title: The Mysterious Mansion author: AI Interactive Fiction version: 1.0.0 introduction: | - You find yourself standing outside an old, abandoned mansion on a hill. - Rain patters gently on the gravel path leading to the front door. - A strange letter in your pocket invited you here, but you can't remember who sent it. - Perhaps the answers lie within... + ::music[crossfade, loop, lead=10](Dark Jodler.mp3) + + ::chapter[The Mysterious Mansion] + + The last thing you remember is the letter: heavy paper, black wax, your name written in a hand you almost recognized. + It asked you to come after dusk, alone, and promised that the house would answer what the sender could not. + + Now you stand beyond the wrought iron gate, with rain cooling your face and the hill rising before you. + At its crest waits the old Victorian mansion, every dark window turned toward the path as if the building has been expecting you. # Room definitions rooms: @@ -13,9 +18,11 @@ rooms: front_yard: name: Front Yard description: | - You stand on a gravel path leading to an imposing Victorian mansion. - The rain has softened to a drizzle, and moonlight peeks through gaps in the clouds. + You follow the gravel path up the hill. + The rain softens to a drizzle, and moonlight peeks through gaps in the clouds. Ancient oak trees frame the property, their branches swaying in the gentle breeze. + At the top of three worn stone steps, the mansion's front door waits under a sagging porch roof. + When you reach for the handle, it turns before your fingers touch it, and the door opens {{sfx:squeaky-door.ogg}} with a long, complaining squeak. exits: - direction: north targetRoomId: entrance_hall @@ -678,4 +685,4 @@ initialState: hasMetButler: false hasFoundSecret: false counters: - moveCount: 0 \ No newline at end of file + moveCount: 0 diff --git a/dist/server.js b/dist/server.js index 1cd5f01..d0b42dc 100644 --- a/dist/server.js +++ b/dist/server.js @@ -62,30 +62,103 @@ exports.io = io; const DEFAULT_PORT = 3001; const PORT = process.env.PORT ? parseInt(process.env.PORT) : DEFAULT_PORT; const PORT_RANGE = 10; // Try up to 10 ports starting from the default -// Serve static files from the public directory -app.use(express_1.default.static(path_1.default.join(__dirname, '../public'))); +// Serve static files from the public directory. During local development the +// browser must not keep stale ES modules, otherwise UI fixes appear to do +// nothing until a hard cache clear. +app.use(express_1.default.static(path_1.default.join(__dirname, '../public'), { + etag: false, + lastModified: false, + setHeaders: (res) => { + res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); + res.setHeader('Pragma', 'no-cache'); + res.setHeader('Expires', '0'); + } +})); // Set up game sessions const gameSessions = new Map(); +function normalizeSaveSlot(slot) { + const value = Number(slot); + return Number.isInteger(value) && value > 0 ? value : 1; +} +async function startDemoGameForSocket(socket) { + const gameRunner = new game_runner_1.GameRunner(); + const worldFile = process.env.DEFAULT_WORLD_FILE || './data/worlds/example_world.yml'; + await gameRunner.initialize(worldFile); + gameSessions.set(socket.id, gameRunner); + const gameState = gameRunner.getGameState(); + socket.emit('gameIntroduction', { + introduction: gameState.world.introduction, + initialRoomDescription: gameRunner.getCurrentRoomDescription(), + currentRoomId: gameState.currentRoomId + }); + return gameRunner; +} +async function handleGameApi(socket, method, args = []) { + const saveGames = socket.data.saveGames || new Map(); + socket.data.saveGames = saveGames; + switch (method) { + case 'newGame': + case 'newGame()': + await startDemoGameForSocket(socket); + return { success: true, result: true, running: true, canLoad: saveGames.size > 0 }; + case 'loadGame': + case 'loadGame()': { + const slot = normalizeSaveSlot(args[0]); + if (!saveGames.has(slot)) { + return { success: false, error: 'missing_save', result: false }; + } + await startDemoGameForSocket(socket); + socket.emit('gameLoaded', { slot }); + return { success: true, result: true, running: true, slot }; + } + case 'saveGame': + case 'saveGame()': { + const gameRunner = gameSessions.get(socket.id); + if (!gameRunner) { + return { success: false, error: 'game_not_running', result: false }; + } + const slot = normalizeSaveSlot(args[0]); + saveGames.set(slot, gameRunner.getGameState()); + socket.emit('gameSaved', { slot }); + return { success: true, result: true, slot }; + } + case 'hasSaveGame': + case 'hasSaveGame()': { + const slot = normalizeSaveSlot(args[0]); + return { success: true, result: saveGames.has(slot), slot }; + } + case 'getSaveGames': + case 'getSaveGames()': + return { success: true, result: Array.from(saveGames.keys()).sort((a, b) => a - b) }; + case 'isGameRunning': + case 'isGameRunning()': + return { success: true, result: gameSessions.has(socket.id) }; + default: + return { success: false, error: `unknown_method:${method}` }; + } +} // Handle socket connections io.on('connection', (socket) => { console.log(`New client connected: ${socket.id}`); + socket.data.saveGames = new Map(); + socket.on('gameApi', async (request, respond) => { + try { + const response = await handleGameApi(socket, String(request?.method || ''), Array.isArray(request?.args) ? request.args : []); + if (typeof respond === 'function') { + respond(response); + } + } + catch (error) { + console.error('Game API error:', error); + if (typeof respond === 'function') { + respond({ success: false, error: error instanceof Error ? error.message : String(error) }); + } + } + }); // Start a new game socket.on('startGame', async () => { try { - // Initialize game runner - const gameRunner = new game_runner_1.GameRunner(); - const worldFile = process.env.DEFAULT_WORLD_FILE || './data/worlds/example_world.yml'; - // Initialize the game - await gameRunner.initialize(worldFile); - // Store game session - gameSessions.set(socket.id, gameRunner); - // Send introduction to client - const gameState = gameRunner.getGameState(); - socket.emit('gameIntroduction', { - introduction: gameState.world.introduction, - initialRoomDescription: gameRunner.getCurrentRoomDescription(), - currentRoomId: gameState.currentRoomId - }); + await handleGameApi(socket, 'newGame', []); } catch (error) { console.error('Error starting game:', error); @@ -100,11 +173,11 @@ io.on('connection', (socket) => { socket.emit('error', { message: 'Game session not found. Please start a new game.' }); return; } - // Process command and get response - const response = await gameRunner.processCommand(data.command); - // Send narrative response to client + const command = String(data?.command || '').trim(); + // During typography and animation work, mirror the command back through + // the real socket path so the UI pipeline can be tested end to end. socket.emit('narrativeResponse', { - text: response, + text: command, gameState: { currentRoomId: gameRunner.getGameState().currentRoomId }, @@ -124,8 +197,7 @@ io.on('connection', (socket) => { socket.emit('error', { message: 'Game session not found. Please start a new game.' }); return; } - // Store save data in session - socket.data.savedGame = gameRunner.getGameState(); + socket.data.saveGames.set(1, gameRunner.getGameState()); socket.emit('gameSaved'); } catch (error) { @@ -134,7 +206,7 @@ io.on('connection', (socket) => { } }); // Load game state - socket.on('loadGame', () => { + socket.on('loadGame', async () => { try { const gameRunner = gameSessions.get(socket.id); if (!gameRunner) { @@ -142,17 +214,11 @@ io.on('connection', (socket) => { return; } // Check if there's a saved game - if (!socket.data.savedGame) { + if (!socket.data.saveGames?.has(1)) { socket.emit('error', { message: 'No saved game found.' }); return; } - // Load saved game - gameRunner.loadGameState(socket.data.savedGame); - // Send current state to client - socket.emit('gameLoaded', { - currentRoomDescription: gameRunner.getCurrentRoomDescription(), - currentRoomId: gameRunner.getGameState().currentRoomId - }); + await handleGameApi(socket, 'loadGame', [1]); } catch (error) { console.error('Error loading game:', error); @@ -175,6 +241,8 @@ function ensureDirectories() { path_1.default.join(__dirname, '../public/js'), path_1.default.join(__dirname, '../public/css'), path_1.default.join(__dirname, '../public/images'), + path_1.default.join(__dirname, '../public/music'), + path_1.default.join(__dirname, '../public/sounds'), path_1.default.join(__dirname, '../public/fonts') ]; for (const dir of dirs) { diff --git a/dist/server.js.map b/dist/server.js.map index f059cfa..b9f4592 100644 --- a/dist/server.js.map +++ b/dist/server.js.map @@ -1 +1 @@ -{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkQH,kCAoDC;AApTD,gDAAwB;AACxB,sDAA8B;AAC9B,gDAAwB;AACxB,yCAAqD;AACrD,+CAAiC;AACjC,mDAA+C;AAC/C,2BAAyD;AAEzD,6BAA6B;AAC7B,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,6BAA6B;AAC7B,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AAkTb,kBAAG;AAjTZ,MAAM,MAAM,GAAG,cAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;AAiTxB,wBAAM;AAhTpB,MAAM,EAAE,GAAG,IAAI,kBAAc,CAAC,MAAM,CAAC,CAAC;AAgThB,gBAAE;AA9SxB,qDAAqD;AACrD,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;AAC1E,MAAM,UAAU,GAAG,EAAE,CAAC,CAAC,+CAA+C;AAEtE,6EAA6E;AAC7E,0EAA0E;AAC1E,oCAAoC;AACpC,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,MAAM,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE;IACxD,IAAI,EAAE,KAAK;IACX,YAAY,EAAE,KAAK;IACnB,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE;QAClB,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,uDAAuD,CAAC,CAAC;QACxF,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACpC,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC;CACF,CAAC,CAAC,CAAC;AAEJ,uBAAuB;AACvB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAsB,CAAC;AAEnD,SAAS,iBAAiB,CAAC,IAAa;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,KAAK,UAAU,sBAAsB,CAAC,MAAW;IAC/C,MAAM,UAAU,GAAG,IAAI,wBAAU,EAAE,CAAC;IACpC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,iCAAiC,CAAC;IAEtF,MAAM,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACvC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAExC,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC;IAC5C,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE;QAC9B,YAAY,EAAE,SAAS,CAAC,KAAK,CAAC,YAAY;QAC1C,sBAAsB,EAAE,UAAU,CAAC,yBAAyB,EAAE;QAC9D,aAAa,EAAE,SAAS,CAAC,aAAa;KACvC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,MAAW,EAAE,MAAc,EAAE,OAAkB,EAAE;IAC5E,MAAM,SAAS,GAAqB,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,GAAG,EAAe,CAAC;IACpF,MAAM,CAAC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAElC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS,CAAC;QACf,KAAK,WAAW;YACd,MAAM,sBAAsB,CAAC,MAAM,CAAC,CAAC;YACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QAErF,KAAK,UAAU,CAAC;QAChB,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;YAClE,CAAC;YACD,MAAM,sBAAsB,CAAC,MAAM,CAAC,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC9D,CAAC;QAED,KAAK,UAAU,CAAC;QAChB,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC/C,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;YACtE,CAAC;YACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACnC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC/C,CAAC;QAED,KAAK,aAAa,CAAC;QACnB,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;QAC9D,CAAC;QAED,KAAK,cAAc,CAAC;QACpB,KAAK,gBAAgB;YACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAEvF,KAAK,eAAe,CAAC;QACrB,KAAK,iBAAiB;YACpB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;QAEhE;YACE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,MAAM,EAAE,EAAE,CAAC;IACjE,CAAC;AACH,CAAC;AAED,4BAA4B;AAC5B,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE;IAC7B,OAAO,CAAC,GAAG,CAAC,yBAAyB,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;IAElD,MAAM,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,EAAe,CAAC;IAE/C,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QAC9C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC9H,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;gBAClC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;YACxC,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;gBAClC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC7F,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,mBAAmB;IACnB,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;QAChC,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAE7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,yCAAyC,EAAE,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,yBAAyB;IACzB,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAE/C,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,kDAAkD,EAAE,CAAC,CAAC;gBACtF,OAAO;YACT,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAEnD,wEAAwE;YACxE,oEAAoE;YACpE,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE;gBAC/B,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE;oBACT,aAAa,EAAE,UAAU,CAAC,YAAY,EAAE,CAAC,aAAa;iBACvD;gBACD,WAAW,EAAE,UAAU,CAAC,cAAc,EAAE;aACzC,CAAC,CAAC;QAEL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;YAClD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,8CAA8C,EAAE,CAAC,CAAC;QACpF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,kBAAkB;IAClB,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;QACzB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAE/C,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,kDAAkD,EAAE,CAAC,CAAC;gBACtF,OAAO;YACT,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;YAExD,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,wCAAwC,EAAE,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,kBAAkB;IAClB,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE;QAC/B,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAE/C,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,kDAAkD,EAAE,CAAC,CAAC;gBACtF,OAAO;YACT,CAAC;YAED,gCAAgC;YAChC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC;gBAC1D,OAAO;YACT,CAAC;YAED,MAAM,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAE/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,wCAAwC,EAAE,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,uBAAuB;IACvB,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;QAC3B,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QAEjD,wBAAwB;QACxB,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YAChC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,sCAAsC;AACtC,SAAS,iBAAiB;IACxB,MAAM,IAAI,GAAG;QACX,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC;QACjC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC;QACpC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC;QACrC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC;QACxC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC;QACvC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC;QACxC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC;KACxC,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,IAAA,eAAU,EAAC,GAAG,CAAC,EAAE,CAAC;YACrB,IAAA,cAAS,EAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;AACH,CAAC;AAED,kEAAkE;AAClE,SAAS,cAAc;IACrB,MAAM,MAAM,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,yCAAyC,CAAC,CAAC;IAC/E,MAAM,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,2BAA2B,CAAC,CAAC;IAEtE,IAAI,IAAA,eAAU,EAAC,MAAM,CAAC,IAAI,CAAC,IAAA,eAAU,EAAC,WAAW,CAAC,EAAE,CAAC;QACnD,IAAA,iBAAY,EAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,yBAAyB,MAAM,OAAO,WAAW,EAAE,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAED,sCAAsC;AAC/B,KAAK,UAAU,WAAW,CAAC,WAAmB,EAAE,KAAa;IAClE,IAAI,WAAW,GAAG,WAAW,CAAC;IAC9B,MAAM,OAAO,GAAG,WAAW,GAAG,KAAK,CAAC;IAEpC,mCAAmC;IACnC,OAAO,WAAW,GAAG,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,2BAA2B;YAC3B,iBAAiB,EAAE,CAAC;YAEpB,6BAA6B;YAC7B,IAAI,CAAC;gBACH,cAAc,EAAE,CAAC;YACnB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;YACnD,CAAC;YAED,8CAA8C;YAC9C,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,EAAE;oBAC9B,OAAO,CAAC,GAAG,CAAC,iEAAiE,WAAW,EAAE,CAAC,CAAC;oBAC5F,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;gBAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAA4B,EAAE,EAAE;oBAClD,mCAAmC;oBACnC,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;wBAChC,OAAO,CAAC,GAAG,CAAC,QAAQ,WAAW,iCAAiC,CAAC,CAAC;wBAClE,MAAM,CAAC,KAAK,EAAE,CAAC;wBACf,WAAW,EAAE,CAAC;wBACd,MAAM,EAAE,CAAC;oBACX,CAAC;yBAAM,CAAC;wBACN,mCAAmC;wBACnC,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;wBACtC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAChB,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,gDAAgD;YAChD,OAAO;QAET,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0DAA0D;YAC1D,IAAI,WAAW,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,mCAAmC,WAAW,OAAO,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC;YACtF,CAAC;YAED,8BAA8B;YAC9B,mEAAmE;QACrE,CAAC;IACH,CAAC;AACH,CAAC;AAED,oDAAoD;AACpD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;QAC1C,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/dist/test-server.js b/dist/test-server.js index 1c432b7..872f94d 100644 --- a/dist/test-server.js +++ b/dist/test-server.js @@ -60,8 +60,17 @@ exports.io = io; const DEFAULT_PORT = 3001; const PORT = process.env.PORT ? parseInt(process.env.PORT) : DEFAULT_PORT; const PORT_RANGE = 10; // Try up to 10 ports starting from the default -// Serve static files from the public directory -app.use(express_1.default.static(path_1.default.join(__dirname, '../public'))); +// Serve static files from the public directory. Keep browser modules uncached +// during local development so fixes are visible without a hard cache clear. +app.use(express_1.default.static(path_1.default.join(__dirname, '../public'), { + etag: false, + lastModified: false, + setHeaders: (res) => { + res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); + res.setHeader('Pragma', 'no-cache'); + res.setHeader('Expires', '0'); + } +})); // Test paragraphs to send to the client const TEST_PARAGRAPHS = [ "You stand at the entrance of a mysterious cave. The air is cool and damp, carrying the scent of earth and ancient stone. Shadows dance on the walls as your torch flickers in the gentle breeze.", @@ -72,16 +81,87 @@ const TEST_PARAGRAPHS = [ io.on('connection', (socket) => { console.log(`New client connected: ${socket.id}`); let currentParagraphIndex = 0; + let gameRunning = false; + const saveGames = new Set(); + const startDemoGame = () => { + gameRunning = true; + currentParagraphIndex = 0; + socket.emit('gameIntroduction', { + introduction: "::chapter[Interactive Fiction Test]\n\nWelcome to the Interactive Fiction Test. This is a simplified version that sends predefined paragraphs instead of using an LLM.", + initialRoomDescription: TEST_PARAGRAPHS[0], + currentRoomId: "test-room" + }); + }; + const normalizeSaveSlot = (slot) => { + const value = Number(slot); + return Number.isInteger(value) && value > 0 ? value : 1; + }; + socket.on('gameApi', (request, respond) => { + try { + const method = String(request?.method || ''); + const args = Array.isArray(request?.args) ? request.args : []; + let response; + switch (method) { + case 'newGame': + case 'newGame()': + startDemoGame(); + response = { success: true, result: true, running: true, canLoad: saveGames.size > 0 }; + break; + case 'loadGame': + case 'loadGame()': { + const slot = normalizeSaveSlot(args[0]); + if (!saveGames.has(slot)) { + response = { success: false, error: 'missing_save', result: false }; + break; + } + startDemoGame(); + socket.emit('gameLoaded', { slot }); + response = { success: true, result: true, running: true, slot }; + break; + } + case 'saveGame': + case 'saveGame()': { + if (!gameRunning) { + response = { success: false, error: 'game_not_running', result: false }; + break; + } + const slot = normalizeSaveSlot(args[0]); + saveGames.add(slot); + socket.emit('gameSaved', { slot }); + response = { success: true, result: true, slot }; + break; + } + case 'hasSaveGame': + case 'hasSaveGame()': { + const slot = normalizeSaveSlot(args[0]); + response = { success: true, result: saveGames.has(slot), slot }; + break; + } + case 'getSaveGames': + case 'getSaveGames()': + response = { success: true, result: Array.from(saveGames).sort((a, b) => a - b) }; + break; + case 'isGameRunning': + case 'isGameRunning()': + response = { success: true, result: gameRunning }; + break; + default: + response = { success: false, error: `unknown_method:${method}` }; + } + if (typeof respond === 'function') + respond(response); + } + catch (error) { + if (typeof respond === 'function') { + respond({ success: false, error: error instanceof Error ? error.message : String(error) }); + } + } + }); // Start a new game socket.on('startGame', async () => { try { console.log('Starting test game session'); - // Send introduction to client - socket.emit('gameIntroduction', { - introduction: "Welcome to the Interactive Fiction Test. This is a simplified version that sends predefined paragraphs instead of using an LLM.", - initialRoomDescription: TEST_PARAGRAPHS[0], - currentRoomId: "test-room" - }); + startDemoGame(); } catch (error) { console.error('Error starting game:', error); @@ -92,11 +172,9 @@ io.on('connection', (socket) => { socket.on('playerCommand', async (data) => { try { console.log(`Received command: ${data.command}`); - // Move to the next paragraph - currentParagraphIndex = (currentParagraphIndex + 1) % TEST_PARAGRAPHS.length; // Send narrative response to client socket.emit('narrativeResponse', { - text: TEST_PARAGRAPHS[currentParagraphIndex], + text: data.command, gameState: { currentRoomId: "test-room" }, @@ -120,6 +198,8 @@ function ensureDirectories() { path_1.default.join(__dirname, '../public/js'), path_1.default.join(__dirname, '../public/css'), path_1.default.join(__dirname, '../public/images'), + path_1.default.join(__dirname, '../public/music'), + path_1.default.join(__dirname, '../public/sounds'), path_1.default.join(__dirname, '../public/fonts') ]; for (const dir of dirs) { diff --git a/dist/test-server.js.map b/dist/test-server.js.map index e645a6d..398e836 100644 --- a/dist/test-server.js.map +++ b/dist/test-server.js.map @@ -1 +1 @@ -{"version":3,"file":"test-server.js","sourceRoot":"","sources":["../src/test-server.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"test-server.js","sourceRoot":"","sources":["../src/test-server.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/package.json b/package.json index 6b69bf3..e7388c1 100644 --- a/package.json +++ b/package.json @@ -4,18 +4,29 @@ "description": "A modern take on classic text adventures that combines traditional world modeling with Large Language Models (LLMs) to create natural language interactive fiction experiences.", "main": "index.js", "scripts": { + "check:node": "node scripts/check-node-version.js", + "prestart": "npm run check:node", "start": "node dist/index.js", + "prestart:web": "npm run check:node", "start:web": "node dist/index.js", + "prestart:cli": "npm run check:node", "start:cli": "node dist/index.js --cli", - "dev": "nodemon --watch 'src/**' --ext 'ts,json' --exec 'ts-node src/index.ts'", - "dev:web": "nodemon --watch 'src/**' --ext 'ts,json' --exec 'ts-node src/index.ts'", - "dev:cli": "nodemon --watch 'src/**' --ext 'ts,json' --exec 'ts-node src/index.ts --cli'", + "predev": "npm run check:node", + "dev": "nodemon --watch src --ext ts,json --exec \"ts-node src/index.ts\"", + "predev:web": "npm run check:node", + "dev:web": "nodemon --watch src --ext ts,json --exec \"ts-node src/index.ts\"", + "predev:cli": "npm run check:node", + "dev:cli": "nodemon --watch src --ext ts,json --exec \"ts-node src/index.ts --cli\"", + "pretest-server": "npm run check:node", "test-server": "ts-node src/test-server.ts", "build": "tsc", "test": "jest", "lint": "eslint --ext .ts src/", "lint:fix": "eslint --ext .ts src/ --fix" }, + "engines": { + "node": ">=18.17" + }, "keywords": [], "author": "", "license": "ISC", diff --git a/prototype/.gitignore b/prototype/.gitignore new file mode 100644 index 0000000..de963f0 --- /dev/null +++ b/prototype/.gitignore @@ -0,0 +1,2 @@ +node_modules +speech_cache \ No newline at end of file diff --git a/prototype/11labs.http b/prototype/11labs.http new file mode 100644 index 0000000..d4aa2fb --- /dev/null +++ b/prototype/11labs.http @@ -0,0 +1,2 @@ +GET https://api.elevenlabs.io/v1/voices +xi-api-key: d191e27c2e5b07573b39fe70f0783f48 diff --git a/prototype/EBGaramond-Bold.otf b/prototype/EBGaramond-Bold.otf new file mode 100644 index 0000000..98a8f79 Binary files /dev/null and b/prototype/EBGaramond-Bold.otf differ diff --git a/prototype/EBGaramond-Bold.ttf b/prototype/EBGaramond-Bold.ttf new file mode 100644 index 0000000..a31cb9b Binary files /dev/null and b/prototype/EBGaramond-Bold.ttf differ diff --git a/prototype/EBGaramond-BoldItalic.otf b/prototype/EBGaramond-BoldItalic.otf new file mode 100644 index 0000000..2a6fe6c Binary files /dev/null and b/prototype/EBGaramond-BoldItalic.otf differ diff --git a/prototype/EBGaramond-BoldItalic.ttf b/prototype/EBGaramond-BoldItalic.ttf new file mode 100644 index 0000000..4468f39 Binary files /dev/null and b/prototype/EBGaramond-BoldItalic.ttf differ diff --git a/prototype/EBGaramond-Italic-VariableFont_wght.ttf b/prototype/EBGaramond-Italic-VariableFont_wght.ttf new file mode 100644 index 0000000..187e040 Binary files /dev/null and b/prototype/EBGaramond-Italic-VariableFont_wght.ttf differ diff --git a/prototype/EBGaramond-Italic.otf b/prototype/EBGaramond-Italic.otf new file mode 100644 index 0000000..ec4bcec Binary files /dev/null and b/prototype/EBGaramond-Italic.otf differ diff --git a/prototype/EBGaramond-Italic.ttf b/prototype/EBGaramond-Italic.ttf new file mode 100644 index 0000000..269ce51 Binary files /dev/null and b/prototype/EBGaramond-Italic.ttf differ diff --git a/prototype/EBGaramond-Regular.otf b/prototype/EBGaramond-Regular.otf new file mode 100644 index 0000000..9d533b0 Binary files /dev/null and b/prototype/EBGaramond-Regular.otf differ diff --git a/prototype/EBGaramond-Regular.ttf b/prototype/EBGaramond-Regular.ttf new file mode 100644 index 0000000..c86defb Binary files /dev/null and b/prototype/EBGaramond-Regular.ttf differ diff --git a/prototype/EBGaramond-VariableFont_wght.ttf b/prototype/EBGaramond-VariableFont_wght.ttf new file mode 100644 index 0000000..ec0d53c Binary files /dev/null and b/prototype/EBGaramond-VariableFont_wght.ttf differ diff --git a/prototype/EBGaramond12-Italic.otf b/prototype/EBGaramond12-Italic.otf new file mode 100644 index 0000000..81845af Binary files /dev/null and b/prototype/EBGaramond12-Italic.otf differ diff --git a/prototype/EBGaramond12-Regular.otf b/prototype/EBGaramond12-Regular.otf new file mode 100644 index 0000000..6f26875 Binary files /dev/null and b/prototype/EBGaramond12-Regular.otf differ diff --git a/prototype/Froschkönig.js b/prototype/Froschkönig.js new file mode 100644 index 0000000..0301e0f --- /dev/null +++ b/prototype/Froschkönig.js @@ -0,0 +1 @@ +var storyContent = {"inkVersion":20,"root":[[{"#":"title: Der Froschkönig"},{"#":"author: Die Gebrüder Grimm"},"\n",{"->":"froschkönig"},["done",{"#f":5,"#n":"g-0"}],null],"done",{"froschkönig":[["^In alten Zeiten, als das Wünschen noch geholfen hat, lebte einmal ein König, der hatte wunderschöne Töchter. Die jüngste von ihnen war so schön, daß die Sonne selber, die doch so vieles schon gesehen hat, sich verwundene, sooft sie ihr ins Gesicht schien. Nahe bei dem Schlosse war ein großer, dunkler Wald, und mitten darin, unter einer alten Linde, war ein Brunnen. Wenn nun der Tag recht heiß war, ging die jüngste Prinzessin hinaus in den Wald und setzte sich an den Rand des kühlen Brunnens. Und wenn sie Langeweile hatte, nahm sie eine goldene Kugel, warf sie in die Höhe und fing sie wieder auf. Das war ihr liebstes Spiel.","\n","^Nun trug es sich einmal zu, daß die goldene Kugel der Königstochter nicht in die Händchen fiel, sondern auf die Erde schlug und gerade in den Brunnen hineinrollte. Die Königstochter folgte ihr mit den Augen nach, aber die Kugel verschwand, und der Brunnen war tief, so tief, daß man keinen Grund sah.","\n","^Da fing die Prinzessin an zu weinen und weinte immer lauter und konnte sich gar nicht trösten. Als sie so klagte, rief ihr plötzlich jemand zu: »Was hast du nur, Königstochter? Du schreist ja, daß sich ein Stein erbarmen möchte.«","\n","^Sie sah sich um, woher die Stimme käme, da erblickte sie einen Frosch, der seinen dicken, häßlichen Kopf aus dem Wasser streckte. »Ach, du bist's, alter Wasserpatscher«, sagte sie. »Ich weine über meine goldene Kugel, die mir in den Brunnen hinabgefallen ist.«","\n","^»Sei still und weine nicht«, antwortete der Frosch, »ich kann wohl Rat schaffen. Aber was gibst du mir, wenn ich dein Spielzeug wieder heraufhole?«","\n","^»Was du haben willst, lieber Frosch«, sagte sie,","\n",["ev",{"^->":"froschkönig.0.12.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^»meine Kleider?«",{"->":"$r","var":true},null]}],["ev",{"^->":"froschkönig.0.13.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^»meine Perlen und meine Edelsteine?«",{"->":"$r","var":true},null]}],["ev",{"^->":"froschkönig.0.14.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-2","flg":18},{"s":["^»die goldene Krone, die ich trage?«",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"froschkönig.0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.12.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["ev",{"^->":"froschkönig.0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.13.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["ev",{"^->":"froschkönig.0.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.14.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Der Frosch antwortete: »Deine Kleider, deine Perlen und Edelsteine und deine goldene Krone, die mag ich nicht. Aber wenn du mich liebhaben willst und ich dein Geselle und Spielkamerad sein darf, wenn ich an deinem Tischlein neben dir sitzen, von deinem goldenen Tellerlein essen, aus deinem Becherlein trinken, in deinem Bettlein schlafen darf, dann will ich hinuntersteigen und dir die goldene Kugel heraufholen.«","\n","^»Ach, ja«, sagte sie, »ich verspreche dir alles, was du willst, wenn du mir nur die Kugel wiederbringst.« Sie dachte aber, der einfältige Frosch mag schwätzen, was er will, der sitzt doch im Wasser bei seinesgleichen und quakt und kann keines Menschen Geselle sein!","\n","^Als der Frosch das Versprechen der Königstochter erhalten hatte, tauchte er seinen Kopf unter, sank hinab, und über ein Weilchen kam er wieder heraufgerudert, hatte die Kugel im Maul und warf sie ins Gras. Die Königstochter war voll Freude, als sie ihr schönes Spielzeug wiedererblickte, hob es auf und sprang damit fort.","\n","^»Warte, warte!« rief der Frosch. »Nimm mich mit, ich kann nicht so laufen wie du!« Aber was half es ihm, daß er ihr sein Quak-quak so laut nachschrie, wie er nur konnte! Sie hörte nicht darauf, eilte nach Hause und hatte den Frosch bald vergessen.","\n","^Am andern Tag, als sie sich mit dem König und allen Hofleuten zur Tafel gesetzt hatte und eben von ihrem goldenen Tellerlein aß, da kam, plitsch platsch, plitsch platsch, etwas die Marmortreppe heraufgekrochen. Als es oben angelangt war, klopfte es an die Tür und rief. »Königstochter, jüngste, mach mir auf«","\n","^Sie lief und wollte sehen, wer draußen wäre. Als sie aber aufmachte, saß der Frosch vor der Tür. Da warf sie die Tür hastig zu, setzte sich wieder an den Tisch, und es war ihr ganz ängstlich zumute.","\n","^Der König sah wohl, daß ihr das Herz gewaltig klopfte, und sprach: »Mein Kind, was fürchtest du dich? Steht etwa ein Riese vor der Tür und will dich holen?«","\n","^»Ach, nein«, antwortete sie, »es ist kein Riese, sondern ein garstiger Frosch.«","\n","^»Was will der Frosch von dir?«","\n","^»Ach, lieber Vater, als ich gestern im Wald bei dem Brunnen saß und spielte, fiel meine goldene Kugel ins Wasser. Als ich deshalb weinte, hat sie mir der Frosch heraufgeholt. Und weil er es durchaus verlangte, versprach ich ihm, er sollte mein Spielgefährte werden. Ich dachte aber nimmermehr, daß er aus seinem Wasser käme. Nun ist er draußen und will zu mir herein.«","\n","^Da klopfte es zum zweiten Mal, und eine Stimme rief:","\n","^»Königstochter, jüngste,","\n","^Mach mir auf!","\n","^Weißt du nicht, was gestern","\n","^Du zu mir gesagt","\n","^Bei dem kühlen Brunnenwasser?","\n","^Königstochter, jüngste,","\n","^Mach mir auf!«","\n","^Da sagte der König: »Was du versprochen hast, das mußt du auch halten! Geh nur und mach ihm auf!«","\n","^Sie ging und öffnete die Tür. Da hüpfte der Frosch herein und hüpfte ihr immer nach bis zu ihrem Stuhl. Dort blieb er sitzen und rief: »Heb mich hinauf zu dir!« Sie zauderte, bis es endlich der König befahl. Als der Frosch auf dem Stuhl war, wollte er auf den Tisch, und als er da saß, sprach er: »Nun schieb mir dein goldenes Tellerlein näher, damit wir mitsammen essen können.« Der Frosch ließ sich's gut schmecken, ihr aber blieb fast jeder Bissen im Halse stecken.","\n","^Endlich sprach der Frosch: »Ich habe mich satt gegessen und bin müde. Nun trag mich in dein Kämmerlein und mach dein seidenes Bettlein zurecht!« Die Königstochter fing an zu weinen und fürchtete sich vor dem kalten Frosch, den sie sich nicht anzurühren getraute und der nun in ihrem schönen, reinen Bettlein schlafen sollte.","\n","^Der König aber wurde zornig und sprach: »Wer dir geholfen hat, als du in Not warst, den sollst du hernach nicht verachten!«","\n","^Da packte sie den Frosch mit zwei Fingern, trug ihn hinauf in ihr Kämmerlein und setzte ihn dort in eine Ecke. Als sie aber im Bette lag, kam er gekrochen und sprach: »Ich will schlafen so gut wie du. Heb mich hinauf, oder ich sag's deinem Vater!«","\n","^Da wurde sie bitterböse, holte ihn herauf und warf ihn gegen die Wand. »Nun wirst du Ruhe geben«, sagte sie, »du garstiger Frosch!« Als er aber herabfiel, war er kein Frosch mehr, sondern ein Königssohn mit schönen freundlichen Augen. Der war nun nach ihres Vaters Willen ihr lieber Geselle und Gemahl. Er erzählte ihr, er wäre von einer bösen Hexe verwünscht worden, und niemand hätte ihn aus dem Brunnen erlösen können als sie allein, und morgen wollten sie mitsammen in sein Reich gehen.","\n","^Und wirklich, am anderen Morgen kam ein Wagen herangefahren, mit acht weißen Pferden bespannt, die hatten weiße Straußfedern auf dem Kopf und gingen in goldenen Ketten. Hinten auf dem Wagen aber stand der Diener des jungen Königs, das war der treue Heinrich.","\n","^Der treue Heinrich hatte sich so gekränkt, als sein Herr in einen Frosch verwandelt worden war, daß er drei eiserne Bänder um sein Herz hatte legen lassen, damit es ihm nicht vor Weh und Traurigkeit zerspränge.","\n","^Der Wagen sollte nun den jungen König in sein Reich holen. Der treue Heinrich hob ihn und seine junge Gemahlin hinein, stellte sich wieder hinten hinauf und war voll Freude über die Erlösung seines Herrn. Als sie ein Stück des Weges gefahren waren, hörte der Königssohn, daß es hinter ihm krachte, als ob etwas zerbrochen wäre. Da drehte er sich um und rief:","\n","^»Heinrich, der Wagen bricht!«","\n","^»Nein, Herr, der Wagen nicht,","\n","^Es ist ein Band von meinem Herzen,","\n","^Das da lag in großen Schmerzen,","\n","^Als Ihr in dem Brunnen saßt","\n","^Und in einen Frosch verzaubert wart.«","\n","^Noch einmal und noch einmal krachte es auf dem Weg, und der Königssohn meinte immer, der Wagen bräche. Doch es waren nur die Bänder, die vom Herzen des treuen Heinrich absprangen, weil sein Herr nun erlöst und glücklich war.","\n","end",{"#f":5}]}],{"#f":1}],"start":[["^There once was a multiple choice story.","\n","^It had two choices.","\n",["ev",{"^->":"start.0.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^The first choice was good.",{"->":"$r","var":true},null]}],["ev",{"^->":"start.0.5.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^The second choice was bad.",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"start.0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["ev",{"^->":"start.0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.5.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Both choices lead to the end.","\n","end",{"#f":5}]}],{"#f":1}],"state_reached":[{"temp=":"state"},"ev","void","/ev","~ret",{"#f":1}],"move_to_state":[{"temp=":"state"},"ev","void","/ev","~ret",{"#f":1}],"state_between":[{"temp=":"last_state"},{"temp=":"first_state"},"ev","void","/ev","~ret",{"#f":1}],"set":[{"temp=":"amount"},{"temp=":"variable"},"ev",100,{"VAR?":"variable"},{"VAR?":"variable"},{"VAR?":"amount"},100,"/","*","+","MIN","/ev",{"temp=":"variable","re":true},"\n","ev",{"VAR?":"variable"},"/ev","~ret",{"#f":1}],"opposed":[{"temp=":"negative"},{"temp=":"positive"},"ev",{"VAR?":"positive"},{"VAR?":"negative"},"/",100,"*","/ev","~ret",{"#f":1}],"print_num":[{"temp=":"x"},["ev",{"VAR?":"x"},1000,">=","/ev",{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},1000,"/",{"f()":".^.^.^"},"out","/ev","^ thousand ","ev",{"VAR?":"x"},1000,"%",0,">","/ev",[{"->":".^.b","c":true},{"b":["ev",{"VAR?":"x"},1000,"%",{"f()":"print_num"},"out","/ev",{"->":".^.^.^.17"},null]}],"nop","\n",{"->":".^.^.^.5"},null]}],["ev",{"VAR?":"x"},100,">=","/ev",{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},100,"/",{"f()":".^.^.^"},"out","/ev","^ hundred ","ev",{"VAR?":"x"},100,"%",0,">","/ev",[{"->":".^.b","c":true},{"b":["^and ","ev",{"VAR?":"x"},100,"%",{"f()":"print_num"},"out","/ev",{"->":".^.^.^.17"},null]}],"nop","\n",{"->":".^.^.^.5"},null]}],["ev",{"VAR?":"x"},0,"==","/ev",{"->":".^.b","c":true},{"b":["\n","^zero","\n",{"->":".^.^.^.5"},null]}],[{"->":".^.b"},{"b":["\n","ev",{"VAR?":"x"},20,">=","/ev",[{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},10,"/","/ev",["du","ev",2,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^twenty","\n",{"->":".^.^.^.15"},null]}],["du","ev",3,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^thirty","\n",{"->":".^.^.^.15"},null]}],["du","ev",4,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^forty","\n",{"->":".^.^.^.15"},null]}],["du","ev",5,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^fifty","\n",{"->":".^.^.^.15"},null]}],["du","ev",6,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^sixty","\n",{"->":".^.^.^.15"},null]}],["du","ev",7,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^seventy","\n",{"->":".^.^.^.15"},null]}],["du","ev",8,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eighty","\n",{"->":".^.^.^.15"},null]}],["du","ev",9,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^ninety","\n",{"->":".^.^.^.15"},null]}],"pop","nop","\n","ev",{"VAR?":"x"},10,"%",0,">","/ev",[{"->":".^.b","c":true},{"b":["\n","<>","^-","<>","\n",{"->":".^.^.^.25"},null]}],"nop","\n",{"->":".^.^.^.7"},null]}],"nop","\n","ev",{"VAR?":"x"},10,"<",{"VAR?":"x"},20,">","||","/ev",[{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},10,"%","/ev",["du","ev",1,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^one","\n",{"->":".^.^.^.16"},null]}],["du","ev",2,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^two","\n",{"->":".^.^.^.16"},null]}],["du","ev",3,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^three","\n",{"->":".^.^.^.16"},null]}],["du","ev",4,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^four","\n",{"->":".^.^.^.16"},null]}],["du","ev",5,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^five","\n",{"->":".^.^.^.16"},null]}],["du","ev",6,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^six","\n",{"->":".^.^.^.16"},null]}],["du","ev",7,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^seven","\n",{"->":".^.^.^.16"},null]}],["du","ev",8,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eight","\n",{"->":".^.^.^.16"},null]}],["du","ev",9,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^nine","\n",{"->":".^.^.^.16"},null]}],"pop","nop","\n",{"->":".^.^.^.20"},null]}],[{"->":".^.b"},{"b":["\n","ev",{"VAR?":"x"},"/ev",["du","ev",10,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^ten","\n",{"->":".^.^.^.15"},null]}],["du","ev",11,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eleven","\n",{"->":".^.^.^.15"},null]}],["du","ev",12,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^twelve","\n",{"->":".^.^.^.15"},null]}],["du","ev",13,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^thirteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",14,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^fourteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",15,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^fifteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",16,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^sixteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",17,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^seventeen","\n",{"->":".^.^.^.15"},null]}],["du","ev",18,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eighteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",19,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^nineteen","\n",{"->":".^.^.^.15"},null]}],"pop","nop","\n",{"->":".^.^.^.20"},null]}],"nop","\n",{"->":".^.^.^.5"},null]}],"nop","\n",{"#f":1}],"#f":1}],"listDefs":{}}; \ No newline at end of file diff --git a/prototype/Herrenhaus.ink.json b/prototype/Herrenhaus.ink.json new file mode 100644 index 0000000..9a380dd --- /dev/null +++ b/prototype/Herrenhaus.ink.json @@ -0,0 +1 @@ +{"inkVersion":21,"root":[["#","^title: Das Herrenhaus","/#","#","^author: Georg Tomitsch","/#","#","^subtitle: Ein interaktiver Roman","/#","\n","\n",{"->":"Intro"},["done",{"#f":5,"#n":"g-0"}],null],"done",{"Intro":["ev",{"VAR?":"loc_in_front_of_gate"},"/ev",{"VAR=":"current_location","re":true},{"->":"in_front_of_gate"},{"#f":1}],"in_front_of_gate":[["#","^CHAPTER: 1. Das Herrenhaus","/#","#","^LOCATION: In front of gate","/#","^Du stehst vor dem nicht ganz so imposanten, eisernen Gittertor des Anwesens der Familie von Schönberg, welches majestätisch von steinernen Mauern bewacht wird. Sie bilden stumme Schildwachen im schleichenden, herbstlichen Dunst, der das Land in eine andere Welt verwandelt. Ein kühler Schauer kriecht durch die feinen Stoffe deines prächtigen Kleides, lässt eine Gänsehaut über deine Arme tanzen.","\n","^Jenseits des Tores erhebt sich das Herrenhaus, ein Juwel des Jugendstils. Seine geschwungenen Linien und verschnörkelten Ornamente verschmelzen mit dem Nebel zu einem fast unwirklichen Anblick. Jede Fassade, jedes Fenster, jede Skulptur scheint Geschichten zu erzählen – Geschichten von glanzvollen Bällen, unausgesprochenen Geheimnissen und dem gewundenen Labyrinth des Adelslebens.","\n","^Die Einladung des Barons und seiner Familie liegt schwer in deiner Hand, ein Gewicht, das über bloße Tinte und Papier hinausgeht. Es ist ein Wahrzeichen deines Standes, ein Symbol deiner Wichtigkeit.","\n",["ev","str","^lese die Einladung erneut","/str","/ev",{"*":".^.c-0","flg":20},["ev",{"^->":"in_front_of_gate.0.top.6.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^öffne das Tor","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["#","^EXIT: behind_gate ","/#",{"->":"$r","var":true},null]}],["ev",{"^->":"in_front_of_gate.0.top.7.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^Tor","/str","/ev",{"*":".^.^.c-2","flg":22},{"s":["#","^ACTION: examine ","/#",{"->":"$r","var":true},null]}],["ev",{"^->":"in_front_of_gate.0.top.8.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^Tor","/str","/ev",{"*":".^.^.c-3","flg":22},{"s":["#","^ACTION: ask ","/#",{"->":"$r","var":true},null]}],["ev",{"^->":"in_front_of_gate.0.top.9.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^Tor","/str","/ev",{"*":".^.^.c-4","flg":22},{"s":["#","^ACTION: comment ","/#",{"->":"$r","var":true},null]}],{"c-0":["\n","^In deiner Hand, schwerer als das dünne Pergament vermuten lässt, liegt die Einladung. Deine Augen gleiten über die fein geschwungene Handschrift. \"Geehrte Frau Isabella König, Diplomatin Ihrer kaiserlichen Majestät und verehrtes Medium,\" beginnt der Brief. Jedes Wort scheint mit größter Sorgfalt gewählt, jede Formulierung mit Bedacht gewählt, um deinen Status und deine Fähigkeiten zu ehren.","\n","^\"Wir laden Sie ein, uns auf unserem Anwesen zu besuchen und uns bei einer delikaten Angelegenheit zu beraten, die sowohl Ihre diplomatischen Fähigkeiten als auch Ihre einzigartigen Gaben erfordert. In der Hoffnung auf Ihre geschätzte Anwesenheit, Baron von Schönberg und Familie.\"","\n","^Als Informantin für den Hof ist es deine Aufgabe, die subtilen Strömungen des Adelslebens zu lesen, aber in deiner Rolle als Medium trittst du in Kontakt mit jenen, die diese Welt bereits verlassen haben. Eine Einladung wie diese ist ein Versprechen für das Unerwartete, eine Herausforderung, die nur du bewältigen kannst. Du faltest das Pergament sorgfältig zusammen und steckst es zurück in die Tasche deines Kleides. Mit einem tiefen Atemzug bereitest du dich auf das vor, was dich im Hause von Schönberg erwartet. ",{"->":".^.^"},"\n",{"->":".^.^.^.done"},{"#f":5}],"c-1":["ev",{"^->":"in_front_of_gate.0.top.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.6.s"},[{"#n":"$r2"}],"\n","^Ein Augenblick des Zögerns ergreift dich, bevor du das Gittertor aufstößt. Der metallische Klang hallt in der Stille wider, wie der erste Ton einer ungeschriebenen Symphonie, in der du nun die Hauptrolle spielst. Mit einem letzten, eindringlichen Blick auf das neblige Panorama vor dir, atmest du tief durch und betrittst die Welt der von Schönbergs, bereit, dein Schicksal zu treffen. ",{"->":"behind_gate"},"\n",{"->":".^.^.^.done"},{"#f":5}],"c-2":["ev",{"^->":"in_front_of_gate.0.top.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.7.s"},[{"#n":"$r2"}],"^ Nun, in seiner Nähe, kannst du die filigranen Details erkennen, die in das Material eingearbeitet wurden. Ranken und Blumenmuster winden sich um die senkrechten Stangen, ein Wirbel aus Eisen, der Geschichten von einer vergangenen Ära des Kunsthandwerks erzählt. Jedes Detail scheint handgefertigt, jede Linie sorgfältig in das harte Material gemeißelt.","\n","^Eine plötzliche Brise lässt das Tor leicht knarren, eine stumme Erinnerung daran, dass es trotz seiner scheinbaren Immobilität noch immer Teil der lebenden, atmenden Welt ist. ",{"->":".^.^"},"\n",{"->":".^.^.^.done"},{"#f":5}],"c-3":["ev",{"^->":"in_front_of_gate.0.top.c-3.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.8.s"},[{"#n":"$r2"}],"^ ... ",{"->":".^.^"},"\n",{"->":".^.^.^.done"},{"#f":5}],"c-4":["ev",{"^->":"in_front_of_gate.0.top.c-4.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.9.s"},[{"#n":"$r2"}],"^ ... ",{"->":".^.^"},"\n",{"->":".^.^.^.done"},{"#f":5}],"#f":5,"#n":"top"}],{"done":["done",{"#f":5}]}],{"#f":1}],"behind_gate":[["^Das eiserne Tor fällt hinter dir ins Schloss und lässt einen hallenden Klang durch die Luft zittern. Du stehst nun auf der anderen Seite der Wirklichkeit, eingetaucht in die Welt der von Schönbergs. Die Atmosphäre ist spürbar verändert, die Luft ist dick mit Erwartung und dem süß-sauren Duft des herbstlichen Verfalls.","\n","^Vor dir erstreckt sich ein langer Anfahrtsweg, gesäumt von einer majestätischen Allee. Hohe, alte Bäume erheben sich zu beiden Seiten des Weges, ihre Äste wie verschränkte Arme, die ein dichtes Dach über dem Pfad bilden. Der Nebel webt sich durch ihre Wipfel, fängt das letzte schwache Licht des Tages ein und verwandelt die Allee in einen mystischen Korridor.","\n","^Die Gartenanlagen, einst sicherlich sorgfältig gepflegt und akribisch geplant, wirken nun teilweise verwildert. Büsche und Hecken haben ihre strikte Form verloren und recken ihre Zweige ungestüm in den Himmel. Blätter, die einmal sorgfältig geharkt wurden, bedecken nun den Boden in einem Teppich aus Orange und Braun, knistern unter deinen Füßen. Es ist, als hätten die Gärten beschlossen, sich dem langsamen, unaufhaltsamen Verlauf der Natur zu ergeben.","\n",["#","^SEPARATOR","/#","end",{"#f":5,"#n":"g-0"}],null],{"#f":1}],"state_reached":[{"temp=":"state"},"ev","void","/ev","~ret",{"#f":1}],"move_to_state":[{"temp=":"state"},"ev","void","/ev","~ret",{"#f":1}],"state_between":[{"temp=":"last_state"},{"temp=":"first_state"},"ev","void","/ev","~ret",{"#f":1}],"set":[{"temp=":"amount"},{"temp=":"variable"},"ev",100,{"VAR?":"variable"},{"VAR?":"variable"},{"VAR?":"amount"},100,"/","*","+","MIN","/ev",{"temp=":"variable","re":true},"\n","ev",{"VAR?":"variable"},"/ev","~ret",{"#f":1}],"opposed":[{"temp=":"negative"},{"temp=":"positive"},"ev",{"VAR?":"positive"},{"VAR?":"negative"},"/",100,"*","/ev","~ret",{"#f":1}],"print_num":[{"temp=":"x"},["ev",{"VAR?":"x"},1000,">=","/ev",{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},1000,"/",{"f()":".^.^.^"},"out","/ev","^ thousand ","ev",{"VAR?":"x"},1000,"%",0,">","/ev",[{"->":".^.b","c":true},{"b":["ev",{"VAR?":"x"},1000,"%",{"f()":"print_num"},"out","/ev",{"->":".^.^.^.17"},null]}],"nop","\n",{"->":".^.^.^.5"},null]}],["ev",{"VAR?":"x"},100,">=","/ev",{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},100,"/",{"f()":".^.^.^"},"out","/ev","^ hundred ","ev",{"VAR?":"x"},100,"%",0,">","/ev",[{"->":".^.b","c":true},{"b":["^and ","ev",{"VAR?":"x"},100,"%",{"f()":"print_num"},"out","/ev",{"->":".^.^.^.17"},null]}],"nop","\n",{"->":".^.^.^.5"},null]}],["ev",{"VAR?":"x"},0,"==","/ev",{"->":".^.b","c":true},{"b":["\n","^zero","\n",{"->":".^.^.^.5"},null]}],[{"->":".^.b"},{"b":["\n","ev",{"VAR?":"x"},20,">=","/ev",[{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},10,"/","/ev",["du","ev",2,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^twenty","\n",{"->":".^.^.^.15"},null]}],["du","ev",3,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^thirty","\n",{"->":".^.^.^.15"},null]}],["du","ev",4,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^forty","\n",{"->":".^.^.^.15"},null]}],["du","ev",5,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^fifty","\n",{"->":".^.^.^.15"},null]}],["du","ev",6,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^sixty","\n",{"->":".^.^.^.15"},null]}],["du","ev",7,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^seventy","\n",{"->":".^.^.^.15"},null]}],["du","ev",8,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eighty","\n",{"->":".^.^.^.15"},null]}],["du","ev",9,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^ninety","\n",{"->":".^.^.^.15"},null]}],"pop","nop","\n","ev",{"VAR?":"x"},10,"%",0,">","/ev",[{"->":".^.b","c":true},{"b":["\n","<>","^-","<>","\n",{"->":".^.^.^.25"},null]}],"nop","\n",{"->":".^.^.^.7"},null]}],"nop","\n","ev",{"VAR?":"x"},10,"<",{"VAR?":"x"},20,">","||","/ev",[{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},10,"%","/ev",["du","ev",1,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^one","\n",{"->":".^.^.^.16"},null]}],["du","ev",2,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^two","\n",{"->":".^.^.^.16"},null]}],["du","ev",3,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^three","\n",{"->":".^.^.^.16"},null]}],["du","ev",4,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^four","\n",{"->":".^.^.^.16"},null]}],["du","ev",5,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^five","\n",{"->":".^.^.^.16"},null]}],["du","ev",6,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^six","\n",{"->":".^.^.^.16"},null]}],["du","ev",7,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^seven","\n",{"->":".^.^.^.16"},null]}],["du","ev",8,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eight","\n",{"->":".^.^.^.16"},null]}],["du","ev",9,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^nine","\n",{"->":".^.^.^.16"},null]}],"pop","nop","\n",{"->":".^.^.^.20"},null]}],[{"->":".^.b"},{"b":["\n","ev",{"VAR?":"x"},"/ev",["du","ev",10,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^ten","\n",{"->":".^.^.^.15"},null]}],["du","ev",11,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eleven","\n",{"->":".^.^.^.15"},null]}],["du","ev",12,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^twelve","\n",{"->":".^.^.^.15"},null]}],["du","ev",13,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^thirteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",14,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^fourteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",15,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^fifteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",16,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^sixteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",17,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^seventeen","\n",{"->":".^.^.^.15"},null]}],["du","ev",18,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eighteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",19,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^nineteen","\n",{"->":".^.^.^.15"},null]}],"pop","nop","\n",{"->":".^.^.^.20"},null]}],"nop","\n",{"->":".^.^.^.5"},null]}],"nop","\n",{"#f":1}],"locationMenu":[{"temp=":"back"},["ev",{"VAR?":"back"},"/ev","thread",{"->":"items"},["done",{"#f":5,"#n":"g-0"}],null],{"#f":1}],"itemAtLocation":[{"temp=":"item"},"ev",{"VAR?":"current_location"},{"VAR?":"item"},"?","/ev","~ret",{"#f":1}],"items":[{"temp=":"back"},["ev","str","^Tor öffnen","/str",{"VAR?":"current_location"},{"VAR?":"loc_in_front_of_gate"},"==","/ev",{"*":".^.c-0","flg":21},{"c-0":["\n","^Du öffnest das Tor.","\n",{"->":"back","var":true},{"#f":5}]}],{"#f":1}],"global decl":["ev",{"list":{},"origins":["locations"]},{"VAR=":"locations"},{"list":{},"origins":["it_items"]},{"VAR=":"it_items"},{"VAR?":"loc_in_front_of_gate"},{"VAR=":"current_location"},"/ev","end",null],"#f":1}],"listDefs":{"locations":{"loc_in_front_of_gate":1,"loc_behind_gate":2,"loc_driveway":3,"loc_in_front_of_manor":4,"loc_on_top_of_front_porch":5},"it_items":{"it_gate":1}}} \ No newline at end of file diff --git a/prototype/Herrenhaus.js b/prototype/Herrenhaus.js new file mode 100644 index 0000000..9f5eccf --- /dev/null +++ b/prototype/Herrenhaus.js @@ -0,0 +1 @@ +{"inkVersion":21,"root":[["#","^title: Das Herrenhaus","/#","#","^author: Georg Tomitsch","/#","\n",{"->":"Herrenhaus"},["done",{"#f":5,"#n":"g-0"}],null],"done",{"Herrenhaus":[["#","^Chapter: Start","/#","ev",{"CNT?":".^.^"},"/ev",{"VAR=":"location","re":true},"^Du stehst vor einem Herrenhaus. ","#","^First line.","/#","\n","^Die zweite Zeile.","\n","^Die dritte Zeile. ","#","^Third line.","/#","\n",["ev",{"^->":"Herrenhaus.0.19.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^Aktion 1 ","#","^1","/#",{"->":"$r","var":true},null]}],["ev",{"^->":"Herrenhaus.0.20.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^Aktion 2 ","#","^2","/#",{"->":"$r","var":true},null]}],["ev",{"^->":"Herrenhaus.0.21.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-2","flg":18},{"s":["^Aktion 3 ","#","^3","/#",{"->":"$r","var":true},null]}],["ev",{"^->":"Herrenhaus.0.22.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-3","flg":18},{"s":["^Ligaturen testen",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"Herrenhaus.0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.19.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["ev",{"^->":"Herrenhaus.0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.20.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["ev",{"^->":"Herrenhaus.0.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.21.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"c-3":["ev",{"^->":"Herrenhaus.0.c-3.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.22.s"},[{"#n":"$r2"}],"\n","^Theo fliegt finnisch fhy mit dem Schiff. fb fh fj ffb Laufband, aufjagen, Sauerstofflasche fb fh fj ffb","\n","^st ct sp sk","\n","^qy qg gg gj Qy Gy s as es is us","\n","^Qui Quis Quo IRAQ","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["end",{"#f":5}]}],{"#f":1}],"state_reached":[{"temp=":"state"},"ev","void","/ev","~ret",{"#f":1}],"move_to_state":[{"temp=":"state"},"ev","void","/ev","~ret",{"#f":1}],"state_between":[{"temp=":"last_state"},{"temp=":"first_state"},"ev","void","/ev","~ret",{"#f":1}],"set":[{"temp=":"amount"},{"temp=":"variable"},"ev",100,{"VAR?":"variable"},{"VAR?":"variable"},{"VAR?":"amount"},100,"/","*","+","MIN","/ev",{"temp=":"variable","re":true},"\n","ev",{"VAR?":"variable"},"/ev","~ret",{"#f":1}],"opposed":[{"temp=":"negative"},{"temp=":"positive"},"ev",{"VAR?":"positive"},{"VAR?":"negative"},"/",100,"*","/ev","~ret",{"#f":1}],"print_num":[{"temp=":"x"},["ev",{"VAR?":"x"},1000,">=","/ev",{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},1000,"/",{"f()":".^.^.^"},"out","/ev","^ thousand ","ev",{"VAR?":"x"},1000,"%",0,">","/ev",[{"->":".^.b","c":true},{"b":["ev",{"VAR?":"x"},1000,"%",{"f()":"print_num"},"out","/ev",{"->":".^.^.^.17"},null]}],"nop","\n",{"->":".^.^.^.5"},null]}],["ev",{"VAR?":"x"},100,">=","/ev",{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},100,"/",{"f()":".^.^.^"},"out","/ev","^ hundred ","ev",{"VAR?":"x"},100,"%",0,">","/ev",[{"->":".^.b","c":true},{"b":["^and ","ev",{"VAR?":"x"},100,"%",{"f()":"print_num"},"out","/ev",{"->":".^.^.^.17"},null]}],"nop","\n",{"->":".^.^.^.5"},null]}],["ev",{"VAR?":"x"},0,"==","/ev",{"->":".^.b","c":true},{"b":["\n","^zero","\n",{"->":".^.^.^.5"},null]}],[{"->":".^.b"},{"b":["\n","ev",{"VAR?":"x"},20,">=","/ev",[{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},10,"/","/ev",["du","ev",2,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^twenty","\n",{"->":".^.^.^.15"},null]}],["du","ev",3,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^thirty","\n",{"->":".^.^.^.15"},null]}],["du","ev",4,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^forty","\n",{"->":".^.^.^.15"},null]}],["du","ev",5,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^fifty","\n",{"->":".^.^.^.15"},null]}],["du","ev",6,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^sixty","\n",{"->":".^.^.^.15"},null]}],["du","ev",7,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^seventy","\n",{"->":".^.^.^.15"},null]}],["du","ev",8,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eighty","\n",{"->":".^.^.^.15"},null]}],["du","ev",9,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^ninety","\n",{"->":".^.^.^.15"},null]}],"pop","nop","\n","ev",{"VAR?":"x"},10,"%",0,">","/ev",[{"->":".^.b","c":true},{"b":["\n","<>","^-","<>","\n",{"->":".^.^.^.25"},null]}],"nop","\n",{"->":".^.^.^.7"},null]}],"nop","\n","ev",{"VAR?":"x"},10,"<",{"VAR?":"x"},20,">","||","/ev",[{"->":".^.b","c":true},{"b":["\n","ev",{"VAR?":"x"},10,"%","/ev",["du","ev",1,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^one","\n",{"->":".^.^.^.16"},null]}],["du","ev",2,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^two","\n",{"->":".^.^.^.16"},null]}],["du","ev",3,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^three","\n",{"->":".^.^.^.16"},null]}],["du","ev",4,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^four","\n",{"->":".^.^.^.16"},null]}],["du","ev",5,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^five","\n",{"->":".^.^.^.16"},null]}],["du","ev",6,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^six","\n",{"->":".^.^.^.16"},null]}],["du","ev",7,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^seven","\n",{"->":".^.^.^.16"},null]}],["du","ev",8,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eight","\n",{"->":".^.^.^.16"},null]}],["du","ev",9,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^nine","\n",{"->":".^.^.^.16"},null]}],"pop","nop","\n",{"->":".^.^.^.20"},null]}],[{"->":".^.b"},{"b":["\n","ev",{"VAR?":"x"},"/ev",["du","ev",10,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^ten","\n",{"->":".^.^.^.15"},null]}],["du","ev",11,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eleven","\n",{"->":".^.^.^.15"},null]}],["du","ev",12,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^twelve","\n",{"->":".^.^.^.15"},null]}],["du","ev",13,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^thirteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",14,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^fourteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",15,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^fifteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",16,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^sixteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",17,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^seventeen","\n",{"->":".^.^.^.15"},null]}],["du","ev",18,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^eighteen","\n",{"->":".^.^.^.15"},null]}],["du","ev",19,"==","/ev",{"->":".^.b","c":true},{"b":["pop","\n","^nineteen","\n",{"->":".^.^.^.15"},null]}],"pop","nop","\n",{"->":".^.^.^.20"},null]}],"nop","\n",{"->":".^.^.^.5"},null]}],"nop","\n",{"#f":1}],"global decl":["ev",0,{"VAR=":"location"},"/ev","end",null],"#f":1}],"listDefs":{}} \ No newline at end of file diff --git a/prototype/Hyphenopoly.js b/prototype/Hyphenopoly.js new file mode 100644 index 0000000..eab4e66 --- /dev/null +++ b/prototype/Hyphenopoly.js @@ -0,0 +1,931 @@ +/** + * @license Hyphenopoly 5.2.0-beta.1 - client side hyphenation for webbrowsers + * ©2023 Mathias Nater, Güttingen (mathiasnater at gmail dot com) + * https://github.com/mnater/Hyphenopoly + * + * Released under the MIT license + * http://mnater.github.io/Hyphenopoly/LICENSE + */ + +/* globals Hyphenopoly:readonly */ +((w, o) => { + "use strict"; + const SOFTHYPHEN = "\u00AD"; + + /** + * Event + */ + const event = ((H) => { + const knownEvents = new Map([ + ["afterElementHyphenation", []], + ["beforeElementHyphenation", []], + ["engineReady", []], + [ + "error", [ + (e) => { + if (e.runDefault) { + w.console.warn(e); + } + } + ] + ], + ["hyphenopolyEnd", []], + ["hyphenopolyStart", []] + ]); + if (H.hev) { + const userEvents = new Map(o.entries(H.hev)); + knownEvents.forEach((eventFuncs, eventName) => { + if (userEvents.has(eventName)) { + eventFuncs.unshift(userEvents.get(eventName)); + } + }); + } + return { + "fire": ((eventName, eventData) => { + eventData.runDefault = true; + eventData.preventDefault = () => { + eventData.runDefault = false; + }; + knownEvents.get(eventName).forEach((eventFn) => { + eventFn(eventData); + }); + }) + }; + })(Hyphenopoly); + + /** + * Register copy event on element + * @param {Object} el The element + * @returns {undefined} + */ + function registerOnCopy(el) { + el.addEventListener( + "copy", + (e) => { + e.preventDefault(); + const sel = w.getSelection(); + const div = document.createElement("div"); + div.appendChild(sel.getRangeAt(0).cloneContents()); + e.clipboardData.setData("text/plain", sel.toString().replace(RegExp(SOFTHYPHEN, "g"), "")); + e.clipboardData.setData("text/html", div.innerHTML.replace(RegExp(SOFTHYPHEN, "g"), "")); + }, + true + ); + } + + /** + * Convert settings from H.setup-Object to Map + * This is a IIFE to keep complexity low. + */ + ((H) => { + /** + * Create a Map with a default Map behind the scenes. This mimics + * kind of a prototype chain of an object, but without the object- + * injection security risk. + * + * @param {Map} defaultsMap - A Map with default values + * @returns {Proxy} - A Proxy for the Map (dot-notation or get/set) + */ + function createMapWithDefaults(defaultsMap) { + const userMap = new Map(); + + /** + * The get-trap: get the value from userMap or else from defaults + * @param {Sring} key - The key to retrieve the value for + * @returns {*} + */ + function get(key) { + return (userMap.has(key)) + ? userMap.get(key) + : defaultsMap.get(key); + } + + /** + * The set-trap: set the value to userMap and don't touch defaults + * @param {Sring} key - The key for the value + * @param {*} value - The value + * @returns {*} + */ + function set(key, value) { + userMap.set(key, value); + } + return new Proxy(defaultsMap, { + "get": (_target, prop) => { + if (prop === "set") { + return set; + } + if (prop === "get") { + return get; + } + return get(prop); + }, + "ownKeys": () => { + return [ + ...new Set( + [...defaultsMap.keys(), ...userMap.keys()] + ) + ]; + } + }); + } + + const settings = createMapWithDefaults(new Map([ + ["defaultLanguage", "en-us"], + [ + "dontHyphenate", (() => { + const list = "abbr,acronym,audio,br,button,code,img,input,kbd,label,math,option,pre,samp,script,style,sub,sup,svg,textarea,var,video"; + return createMapWithDefaults( + new Map(list.split(",").map((val) => { + return [val, true]; + })) + ); + })() + ], + ["dontHyphenateClass", "donthyphenate"], + ["exceptions", new Map()], + ["keepAlive", true], + ["normalize", false], + ["processShadows", false], + ["safeCopy", true], + ["substitute", new Map()], + ["timeout", 1000] + ])); + o.entries(H.s).forEach(([key, value]) => { + switch (key) { + case "selectors": + // Set settings.selectors to array of selectors + settings.set("selectors", o.keys(value)); + + /* + * For each selector add a property to settings with + * selector specific settings + */ + o.entries(value).forEach(([sel, selSettings]) => { + const selectorSettings = createMapWithDefaults(new Map([ + ["compound", "hyphen"], + ["hyphen", SOFTHYPHEN], + ["leftmin", 0], + ["leftminPerLang", 0], + ["minWordLength", 6], + ["mixedCase", true], + ["orphanControl", 1], + ["rightmin", 0], + ["rightminPerLang", 0] + ])); + o.entries(selSettings).forEach( + ([selSetting, setVal]) => { + if (typeof setVal === "object") { + selectorSettings.set( + selSetting, + new Map(o.entries(setVal)) + ); + } else { + selectorSettings.set(selSetting, setVal); + } + } + ); + settings.set(sel, selectorSettings); + }); + break; + case "dontHyphenate": + case "exceptions": + o.entries(value).forEach(([k, v]) => { + settings.get(key).set(k, v); + }); + break; + case "substitute": + o.entries(value).forEach(([lang, subst]) => { + settings.substitute.set( + lang, + new Map(o.entries(subst)) + ); + }); + break; + default: + settings.set(key, value); + } + }); + H.c = settings; + })(Hyphenopoly); + + ((H) => { + const C = H.c; + let mainLanguage = null; + + event.fire( + "hyphenopolyStart", + { + "msg": "hyphenopolyStart" + } + ); + + /** + * Factory for elements + * @returns {Object} elements-object + */ + function makeElementCollection() { + const list = new Map(); + + /* + * Counter counts the elements to be hyphenated. + * Needs to be an object (Pass by reference) + */ + const counter = [0]; + + /** + * Add element to elements + * @param {object} el The element + * @param {string} lang The language of the element + * @param {string} sel The selector of the element + * @returns {Object} An element-object + */ + function add(el, lang, sel) { + const elo = { + "element": el, + "selector": sel + }; + if (!list.has(lang)) { + list.set(lang, []); + } + list.get(lang).push(elo); + counter[0] += 1; + return elo; + } + + /** + * Removes elements from the list and updates the counter + * @param {string} lang - The lang of the elements to remove + */ + function rem(lang) { + let langCount = 0; + if (list.has(lang)) { + langCount = list.get(lang).length; + list.delete(lang); + counter[0] -= langCount; + if (counter[0] === 0) { + event.fire( + "hyphenopolyEnd", + { + "msg": "hyphenopolyEnd" + } + ); + if (!C.keepAlive) { + window.Hyphenopoly = null; + } + } + } + } + + return { + add, + counter, + list, + rem + }; + } + + /** + * Get language of element by searching its parents or fallback + * @param {Object} el The element + * @param {string} parentLang Lang of parent if available + * @param {boolean} fallback Will falback to mainlanguage + * @returns {string|null} The language or null + */ + function getLang(el, parentLang = "", fallback = true) { + // Find closest el with lang attr not empty + el = el.closest("[lang]:not([lang=''])"); + if (el && el.lang) { + return el.lang.toLowerCase(); + } + if (parentLang) { + return parentLang; + } + return (fallback) + ? mainLanguage + : null; + } + + /** + * Collect elements that have a selector defined in C.selectors + * and add them to elements. + * @param {Object} [parent = null] The start point element + * @param {string} [selector = null] The selector matching the parent + * @returns {Object} elements-object + */ + function collectElements(parent = null, selector = null) { + const elements = makeElementCollection(); + + const dontHyphenateSelector = (() => { + let s = "." + C.dontHyphenateClass; + o.getOwnPropertyNames(C.dontHyphenate).forEach((tag) => { + if (C.dontHyphenate.get(tag)) { + s += "," + tag; + } + }); + return s; + })(); + const matchingSelectors = C.selectors.join(",") + "," + dontHyphenateSelector; + + /** + * Recursively walk all elements in el, lending lang and selName + * add them to elements if necessary. + * @param {Object} el The element to scan + * @param {string} pLang The language of the parent element + * @param {string} sel The selector of the parent element + * @param {boolean} isChild If el is a child element + * @returns {undefined} + */ + function processElements(el, pLang, sel, isChild = false) { + const eLang = getLang(el, pLang); + const langDef = H.cf.langs.get(eLang); + if (langDef === "H9Y") { + elements.add(el, eLang, sel); + if (!isChild && C.safeCopy) { + registerOnCopy(el); + } + } else if (!langDef && eLang !== "zxx") { + event.fire( + "error", + Error(`Element with '${eLang}' found, but '${eLang}.wasm' not loaded. Check language tags!`) + ); + } + el.childNodes.forEach((n) => { + if (n.nodeType === 1 && !n.matches(matchingSelectors)) { + processElements(n, eLang, sel, true); + } + }); + } + + /** + * Searches the DOM for each sel + * @param {object} root The DOM root + * @returns {undefined} + */ + function getElems(root) { + C.selectors.forEach((sel) => { + root.querySelectorAll(sel).forEach((n) => { + processElements(n, getLang(n), sel, false); + }); + }); + } + + if (parent === null) { + if (C.processShadows) { + w.document.querySelectorAll("*").forEach((m) => { + if (m.shadowRoot) { + getElems(m.shadowRoot); + } + }); + } + getElems(w.document); + } else { + processElements(parent, getLang(parent), selector); + } + return elements; + } + + const wordHyphenatorPool = new Map(); + + /** + * Factory for hyphenatorFunctions for a specific language and selector + * @param {Object} lo Language-Object + * @param {string} lang The language + * @param {string} sel The selector + * @returns {function} The hyphenate function + */ + function createWordHyphenator(lo, lang, sel) { + const poolKey = lang + "-" + sel; + if (wordHyphenatorPool.has(poolKey)) { + return wordHyphenatorPool.get(poolKey); + } + + const selSettings = C.get(sel); + lo.cache.set(sel, new Map()); + + /** + * HyphenateFunction for non-compound words + * @param {string} word The word + * @returns {string} The hyphenated word + */ + function hyphenateNormal(word) { + if (word.length > 61) { + event.fire( + "error", + Error("Found word longer than 61 characters") + ); + } else if (!lo.reNotAlphabet.test(word)) { + return lo.hyphenate( + word, + selSettings.hyphen.charCodeAt(0), + selSettings.leftminPerLang.get(lang), + selSettings.rightminPerLang.get(lang) + ); + } + return word; + } + + /** + * HyphenateFunction for compound words + * @param {string} word The word + * @returns {string} The hyphenated compound word + */ + function hyphenateCompound(word) { + const zeroWidthSpace = "\u200B"; + let parts = null; + let wordHyphenator = null; + if (selSettings.compound === "auto" || + selSettings.compound === "all") { + wordHyphenator = createWordHyphenator(lo, lang, sel); + parts = word.split("-").map((p) => { + if (p.length >= selSettings.minWordLength) { + return wordHyphenator(p); + } + return p; + }); + if (selSettings.compound === "auto") { + word = parts.join("-"); + } else { + word = parts.join("-" + zeroWidthSpace); + } + } else { + word = word.replace("-", "-" + zeroWidthSpace); + } + return word; + } + + /** + * Checks if a string is mixed case + * @param {string} s The string + * @returns {boolean} true if s is mixed case + */ + function isMixedCase(s) { + return [...s].map((c) => { + return (c === c.toLowerCase()); + }).some((v, i, a) => { + return (v !== a[0]); + }); + } + + /** + * HyphenateFunction for words (compound or not) + * @param {string} word The word + * @returns {string} The hyphenated word + */ + function hyphenator(word) { + let hw = lo.cache.get(sel).get(word); + if (!hw) { + if (lo.exc.has(word)) { + hw = lo.exc.get(word).replace( + /-/g, + selSettings.hyphen + ); + } else if (!selSettings.mixedCase && isMixedCase(word)) { + hw = word; + } else if (word.indexOf("-") === -1) { + hw = hyphenateNormal(word); + } else { + hw = hyphenateCompound(word); + } + lo.cache.get(sel).set(word, hw); + } + return hw; + } + wordHyphenatorPool.set(poolKey, hyphenator); + return hyphenator; + } + + const orphanControllerPool = new Map(); + + /** + * Factory for function that handles orphans + * @param {string} sel The selector + * @returns {function} The function created + */ + function createOrphanController(sel) { + if (orphanControllerPool.has(sel)) { + return orphanControllerPool.get(sel); + } + const selSettings = C.get(sel); + + /** + * Function template + * @param {string} ignore unused result of replace + * @param {string} leadingWhiteSpace The leading whiteSpace + * @param {string} lastWord The last word + * @param {string} trailingWhiteSpace The trailing whiteSpace + * @returns {string} Treated end of text + */ + function controlOrphans( + ignore, + leadingWhiteSpace, + lastWord, + trailingWhiteSpace + ) { + if (selSettings.orphanControl === 3 && leadingWhiteSpace === " ") { + // \u00A0 = no-break space (nbsp) + leadingWhiteSpace = "\u00A0"; + } + return leadingWhiteSpace + lastWord.replace(RegExp(selSettings.hyphen, "g"), "") + trailingWhiteSpace; + } + orphanControllerPool.set(sel, controlOrphans); + return controlOrphans; + } + + const wordRegExpPool = new Map(); + + /** + * Hyphenate an entitiy (text string or Element-Object) + * @param {string} lang - the language of the string + * @param {string} sel - the selectorName of settings + * @param {string} entity - the entity to be hyphenated + * @returns {string | null} hyphenated str according to setting of sel + */ + function hyphenate(lang, sel, entity) { + const lo = H.languages.get(lang); + const selSettings = C.get(sel); + const minWordLength = selSettings.minWordLength; + + + const regExpWord = (() => { + const key = lang + minWordLength; + if (wordRegExpPool.has(key)) { + return wordRegExpPool.get(key); + } + + /* + * Transpiled RegExp of + * /[${alphabet}\p{Mn}Subset\p{Letter}\00AD-] + * {${minwordlength},}/gui + */ + const reWord = RegExp( + `[${lo.alphabet}a-z\u0300-\u036F\u0483-\u0487\u00DF-\u00F6\u00F8-\u00FE\u0101\u0103\u0105\u0107\u0109\u010D\u010F\u0111\u0113\u0117\u0119\u011B\u011D\u011F\u0123\u0125\u012B\u012F\u0131\u0135\u0137\u013C\u013E\u0142\u0144\u0146\u0148\u014D\u0151\u0153\u0155\u0159\u015B\u015D\u015F\u0161\u0165\u016B\u016D\u016F\u0171\u0173\u017A\u017C\u017E\u017F\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u0219\u021B\u02BC\u0390\u03AC-\u03CE\u03D0\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF\u03F2\u0430-\u044F\u0451-\u045C\u045E\u045F\u0491\u04AF\u04E9\u0561-\u0585\u0587\u0905-\u090C\u090F\u0910\u0913-\u0928\u092A-\u0930\u0932\u0933\u0935-\u0939\u093D\u0960\u0961\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A85-\u0A8B\u0A8F\u0A90\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B60\u0B61\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60\u0D61\u0D7A-\u0D7F\u0E01-\u0E2E\u0E30\u0E32\u0E33\u0E40-\u0E45\u10D0-\u10F0\u1200-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u1E0D\u1E37\u1E41\u1E43\u1E45\u1E47\u1E6D\u1F00-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB2-\u1FB4\u1FB6\u1FB7\u1FC2-\u1FC4\u1FC6\u1FC7\u1FD2\u1FD3\u1FD6\u1FD7\u1FE2-\u1FE7\u1FF2-\u1FF4\u1FF6\u1FF7\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CC9\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\u00AD\u200B-\u200D-]{${minWordLength},}`, "gui" + ); + wordRegExpPool.set(key, reWord); + return reWord; + })(); + + /** + * Hyphenate text according to setting in sel + * @param {string} text - the strint to be hyphenated + * @returns {string} hyphenated string according to setting of sel + */ + function hyphenateText(text) { + if (C.normalize) { + text = text.normalize("NFC"); + } + let tn = text.replace( + regExpWord, + createWordHyphenator(lo, lang, sel) + ); + if (selSettings.orphanControl !== 1) { + tn = tn.replace( + /(\u0020*)(\S+)(\s*)$/, + createOrphanController(sel) + ); + } + return tn; + } + + /** + * Hyphenate element according to setting in sel + * @param {object} el - the HTMLElement to be hyphenated + * @returns {undefined} + */ + function hyphenateElement(el) { + event.fire( + "beforeElementHyphenation", + { + el, + lang + } + ); + el.childNodes.forEach((n) => { + if ( + n.nodeType === 3 && + (/\S/).test(n.data) && + n.data.length >= minWordLength + ) { + n.data = hyphenateText(n.data); + } + }); + H.res.els.counter[0] -= 1; + event.fire( + "afterElementHyphenation", + { + el, + lang + } + ); + } + let r = null; + if (typeof entity === "string") { + r = hyphenateText(entity); + } else if (entity instanceof HTMLElement) { + hyphenateElement(entity); + } + return r; + } + + /** + * Creates a language-specific string hyphenator + * @param {String} lang - The language this hyphenator hyphenates + */ + function createStringHyphenator(lang) { + return ((entity, sel = ".hyphenate") => { + if (typeof entity !== "string") { + event.fire( + "error", + Error("This use of hyphenators is deprecated. See https://mnater.github.io/Hyphenopoly/Hyphenators.html") + ); + } + return hyphenate(lang, sel, entity); + }); + } + + /** + * Creates a polyglot HTML hyphenator + */ + function createDOMHyphenator() { + return ((entity, sel = ".hyphenate") => { + collectElements(entity, sel).list.forEach((els, l) => { + els.forEach((elo) => { + hyphenate(l, elo.selector, elo.element); + }); + }); + return null; + }); + } + + H.unhyphenate = () => { + H.res.els.list.forEach((els) => { + els.forEach((elo) => { + const n = elo.element.firstChild; + n.data = n.data.replace(RegExp(C[elo.selector].hyphen, "g"), ""); + }); + }); + return Promise.resolve(H.res.els); + }; + + /** + * Hyphenate all elements with a given language + * @param {string} lang The language + * @param {Array} elArr Array of elements + * @returns {undefined} + */ + function hyphenateLangElements(lang, elements) { + const elArr = elements.list.get(lang); + if (elArr) { + elArr.forEach((elo) => { + hyphenate(lang, elo.selector, elo.element); + }); + } else { + event.fire( + "error", + Error(`Engine for language '${lang}' loaded, but no elements found.`) + ); + } + if (elements.counter[0] === 0) { + w.clearTimeout(H.timeOutHandler); + H.hide(0, null); + event.fire( + "hyphenopolyEnd", + { + "msg": "hyphenopolyEnd" + } + ); + if (!C.keepAlive) { + window.Hyphenopoly = null; + } + } + } + + /** + * Convert the exceptions from user input to Map + * @param {string} lang - The language for which the Map is created + * @return {Map} + */ + function createExceptionMap(lang) { + let exc = ""; + if (C.exceptions.has(lang)) { + exc = C.exceptions.get(lang); + } + if (C.exceptions.has("global")) { + if (exc === "") { + exc = C.exceptions.get("global"); + } else { + exc += ", " + C.exceptions.get("global"); + } + } + if (exc === "") { + return new Map(); + } + return new Map(exc.split(", ").map((e) => { + return [e.replace(/-/g, ""), e]; + })); + } + + /** + * Setup lo + * @param {string} lang The language + * @param {function} hyphenateFunction The hyphenateFunction + * @param {string} alphabet List of used characters + * @param {number} leftmin leftmin + * @param {number} rightmin rightmin + * @returns {undefined} + */ + function prepareLanguagesObj( + lang, + hyphenateFunction, + alphabet, + patternLeftmin, + patternRightmin + ) { + C.selectors.forEach((sel) => { + const selSettings = C.get(sel); + if (selSettings.leftminPerLang === 0) { + selSettings.set("leftminPerLang", new Map()); + } + if (selSettings.rightminPerLang === 0) { + selSettings.set("rightminPerLang", new Map()); + } + selSettings.leftminPerLang.set(lang, Math.max( + patternLeftmin, + selSettings.leftmin, + Number(selSettings.leftminPerLang.get(lang)) || 0 + )); + + selSettings.rightminPerLang.set(lang, Math.max( + patternRightmin, + selSettings.rightmin, + Number(selSettings.rightminPerLang.get(lang)) || 0 + )); + }); + if (!H.languages) { + H.languages = new Map(); + } + alphabet = alphabet.replace(/\\*-/g, "\\-"); + H.languages.set(lang, { + alphabet, + "cache": new Map(), + "exc": createExceptionMap(lang), + "hyphenate": hyphenateFunction, + "ready": true, + "reNotAlphabet": RegExp(`[^${alphabet}]`, "i") + }); + H.hy6ors.get(lang).resolve(createStringHyphenator(lang)); + event.fire( + "engineReady", + { + lang + } + ); + if (H.res.els) { + hyphenateLangElements(lang, H.res.els); + } + } + + const decode = (() => { + const utf16ledecoder = new TextDecoder("utf-16le"); + return ((ui16) => { + return utf16ledecoder.decode(ui16); + }); + })(); + + /** + * Setup env for hyphenateFunction + * @param {ArrayBuffer} buf Memory buffer + * @param {function} hyphenateFunc hyphenateFunction + * @returns {function} hyphenateFunction with closured environment + */ + function encloseHyphenateFunction(buf, hyphenateFunc) { + const wordStore = new Uint16Array(buf, 0, 64); + return ((word, hyphencc, leftmin, rightmin) => { + wordStore.set([ + ...[...word].map((c) => { + return c.charCodeAt(0); + }), + 0 + ]); + const len = hyphenateFunc(leftmin, rightmin, hyphencc); + if (len > 0) { + word = decode( + new Uint16Array(buf, 0, len) + ); + } + return word; + }); + } + + /** + * Instantiate Wasm Engine + * @param {string} lang The language + * @returns {undefined} + */ + function instantiateWasmEngine(heProm, lang) { + const wa = window.WebAssembly; + + /** + * Register character substitutions in the .wasm-hyphenEngine + * @param {number} alphalen - The length of the alphabet + * @param {object} exp - Export-object of the hyphenEngine + */ + function registerSubstitutions(alphalen, exp) { + if (C.substitute.has(lang)) { + const subst = C.substitute.get(lang); + subst.forEach((substituer, substituted) => { + const substitutedU = substituted.toUpperCase(); + const substitutedUcc = (substitutedU === substituted) + ? 0 + : substitutedU.charCodeAt(0); + alphalen = exp.subst( + substituted.charCodeAt(0), + substitutedUcc, + substituer.charCodeAt(0) + ); + }); + } + return alphalen; + } + + /** + * Instantiate the hyphenEngine + * @param {object} res - The fetched ressource + */ + function handleWasm(res) { + const exp = res.instance.exports; + // eslint-disable-next-line multiline-ternary + let alphalen = (wa.Global) ? exp.lct.value : exp.lct; + alphalen = registerSubstitutions(alphalen, exp); + heProm.l.forEach((l) => { + prepareLanguagesObj( + l, + encloseHyphenateFunction( + exp.mem.buffer, + exp.hyphenate + ), + decode(new Uint16Array(exp.mem.buffer, 1408, alphalen)), + /* eslint-disable multiline-ternary */ + (wa.Global) ? exp.lmi.value : exp.lmi, + (wa.Global) ? exp.rmi.value : exp.rmi + /* eslint-enable multiline-ternary */ + ); + }); + } + heProm.w.then((response) => { + if (response.ok) { + if ( + wa.instantiateStreaming && + (response.headers.get("Content-Type") === "application/wasm") + ) { + return wa.instantiateStreaming(response); + } + return response.arrayBuffer().then((ab) => { + return wa.instantiate(ab); + }); + } + return Promise.reject(Error(`File ${lang}.wasm can't be loaded from ${H.paths.patterndir}`)); + }).then(handleWasm, (e) => { + event.fire("error", e); + H.res.els.rem(lang); + }); + } + + H.main = () => { + H.res.DOM.then(() => { + mainLanguage = getLang(w.document.documentElement, "", false); + if (!mainLanguage && C.defaultLanguage !== "") { + mainLanguage = C.defaultLanguage; + } + const elements = collectElements(); + H.res.els = elements; + elements.list.forEach((ignore, lang) => { + if (H.languages && + H.languages.has(lang) && + H.languages.get(lang).ready + ) { + hyphenateLangElements(lang, elements); + } + }); + }); + + H.res.he.forEach(instantiateWasmEngine); + + Promise.all( + // Make sure all lang specific hyphenators and DOM are ready + [...H.hy6ors.entries()]. + reduce((accumulator, value) => { + if (value[0] !== "HTML") { + return accumulator.concat(value[1]); + } + return accumulator; + }, []). + concat(H.res.DOM) + ).then(() => { + H.hy6ors.get("HTML").resolve(createDOMHyphenator()); + }, (e) => { + event.fire("error", e); + }); + }; + H.main(); + })(Hyphenopoly); +})(window, Object); diff --git a/prototype/Hyphenopoly_Loader.js b/prototype/Hyphenopoly_Loader.js new file mode 100644 index 0000000..ecab413 --- /dev/null +++ b/prototype/Hyphenopoly_Loader.js @@ -0,0 +1,347 @@ +/** + * @license Hyphenopoly_Loader 5.2.0-beta.1 - client side hyphenation + * ©2023 Mathias Nater, Güttingen (mathiasnater at gmail dot com) + * https://github.com/mnater/Hyphenopoly + * + * Released under the MIT license + * http://mnater.github.io/Hyphenopoly/LICENSE + */ +/* globals Hyphenopoly:readonly */ +window.Hyphenopoly = {}; + +((w, d, H, o) => { + "use strict"; + + /** + * Shortcut for new Map + * @param {any} init - initialiser for new Map + * @returns {Map} + */ + const mp = (init) => { + return new Map(init); + }; + + const scriptName = "Hyphenopoly_Loader.js"; + const thisScript = d.currentScript.src; + const store = sessionStorage; + let mainScriptLoaded = false; + + /** + * The main function runs the feature test and loads Hyphenopoly if + * necessary. + */ + const main = (() => { + const shortcuts = { + "ac": "appendChild", + "ce": "createElement", + "ct": "createTextNode" + }; + + /** + * Create deferred Promise + * + * From http://lea.verou.me/2016/12/resolve-promises-externally-with- + * this-one-weird-trick/ + * @return {promise} + */ + const defProm = () => { + let res = null; + let rej = null; + const promise = new Promise((resolve, reject) => { + res = resolve; + rej = reject; + }); + promise.resolve = res; + promise.reject = rej; + return promise; + }; + + H.ac = new AbortController(); + const fetchOptions = { + "credentials": H.s.CORScredentials, + "signal": H.ac.signal + }; + + let stylesNode = null; + + /** + * Define function H.hide. + * This function hides (state = 1) or unhides (state = 0) + * the whole document (mode == 0) or + * each selected element (mode == 1) or + * text of each selected element (mode == 2) or + * nothing (mode == -1) + * @param {integer} state - State + * @param {integer} mode - Mode + */ + H.hide = (state, mode) => { + if (state) { + let vis = "{visibility:hidden!important}"; + stylesNode = d[shortcuts.ce]("style"); + let myStyle = ""; + if (mode === 0) { + myStyle = "html" + vis; + } else if (mode !== -1) { + if (mode === 2) { + vis = "{color:transparent!important}"; + } + o.keys(H.s.selectors).forEach((sel) => { + myStyle += sel + vis; + }); + } + stylesNode[shortcuts.ac](d[shortcuts.ct](myStyle)); + d.head[shortcuts.ac](stylesNode); + } else if (stylesNode) { + stylesNode.remove(); + } + }; + + const tester = (() => { + let fakeBody = null; + return { + + /** + * Append fakeBody with tests to document + * @returns {Object|null} The body element or null, if no tests + */ + "ap": () => { + if (fakeBody) { + d.documentElement[shortcuts.ac](fakeBody); + return fakeBody; + } + return null; + }, + + /** + * Remove fakeBody + * @returns {undefined} + */ + "cl": () => { + if (fakeBody) { + fakeBody.remove(); + } + }, + + /** + * Create and append div with CSS-hyphenated word + * @param {string} lang Language + * @returns {undefined} + */ + "cr": (lang) => { + if (H.cf.langs.has(lang)) { + return; + } + fakeBody = fakeBody || d[shortcuts.ce]("body"); + const testDiv = d[shortcuts.ce]("div"); + const ha = "hyphens:auto"; + testDiv.lang = lang; + testDiv.style.cssText = `visibility:hidden;-webkit-${ha};-ms-${ha};${ha};width:48px;font-size:12px;line-height:12px;border:none;padding:0;word-wrap:normal`; + testDiv[shortcuts.ac]( + d[shortcuts.ct](H.lrq.get(lang).wo.toLowerCase()) + ); + fakeBody[shortcuts.ac](testDiv); + } + }; + })(); + + /** + * Checks if hyphens (ev.prefixed) is set to auto for the element. + * @param {Object} elm - the element + * @returns {Boolean} result of the check + */ + const checkCSSHyphensSupport = (elmStyle) => { + const h = elmStyle.hyphens || + elmStyle.webkitHyphens || + elmStyle.msHyphens; + return (h === "auto"); + }; + + H.res = { + "he": mp() + }; + + /** + * Load hyphenEngines to H.res.he + * + * Make sure each .wasm is loaded exactly once, even for fallbacks + * Store a list of languages to by hyphenated with each .wasm + * @param {string} lang The language + * @returns {undefined} + */ + const loadhyphenEngine = (lang) => { + const fn = H.lrq.get(lang).fn; + H.cf.pf = true; + H.cf.langs.set(lang, "H9Y"); + if (H.res.he.has(fn)) { + H.res.he.get(fn).l.push(lang); + } else { + H.res.he.set( + fn, + { + "l": [lang], + "w": w.fetch(H.paths.patterndir + fn + ".wasm", fetchOptions) + } + ); + } + }; + H.lrq.forEach((value, lang) => { + if (value.wo === "FORCEHYPHENOPOLY" || H.cf.langs.get(lang) === "H9Y") { + loadhyphenEngine(lang); + } else { + tester.cr(lang); + } + }); + const testContainer = tester.ap(); + if (testContainer) { + testContainer.querySelectorAll("div").forEach((n) => { + if (checkCSSHyphensSupport(n.style) && n.offsetHeight > 12) { + H.cf.langs.set(n.lang, "CSS"); + } else { + loadhyphenEngine(n.lang); + } + }); + tester.cl(); + } + const hev = H.hev; + if (H.cf.pf) { + H.res.DOM = new Promise((res) => { + if (d.readyState === "loading") { + d.addEventListener( + "DOMContentLoaded", + res, + { + "once": true, + "passive": true + } + ); + } else { + res(); + } + }); + H.hide(1, H.s.hide); + H.timeOutHandler = w.setTimeout(() => { + H.hide(0, null); + // eslint-disable-next-line no-bitwise + if (H.s.timeout & 1) { + H.ac.abort(); + } + // eslint-disable-next-line no-console + console.info(scriptName + " timed out."); + }, H.s.timeout); + if (mainScriptLoaded) { + H.main(); + } else { + // Load main script + fetch(H.paths.maindir + "Hyphenopoly.js", fetchOptions). + then((response) => { + if (response.ok) { + response.blob().then((blb) => { + const script = d[shortcuts.ce]("script"); + script.src = URL.createObjectURL(blb); + d.head[shortcuts.ac](script); + mainScriptLoaded = true; + URL.revokeObjectURL(script.src); + }); + } + }); + } + H.hy6ors = mp(); + H.cf.langs.forEach((langDef, lang) => { + if (langDef === "H9Y") { + H.hy6ors.set(lang, defProm()); + } + }); + H.hy6ors.set("HTML", defProm()); + H.hyphenators = new Proxy(H.hy6ors, { + "get": (target, key) => { + return target.get(key); + }, + "set": () => { + // Inhibit setting of hyphenators + return true; + } + }); + (() => { + if (hev && hev.polyfill) { + hev.polyfill(); + } + })(); + } else { + (() => { + if (hev && hev.tearDown) { + hev.tearDown(); + } + w.Hyphenopoly = null; + })(); + } + (() => { + if (H.cft) { + store.setItem(scriptName, JSON.stringify( + { + "langs": [...H.cf.langs.entries()], + "pf": H.cf.pf + } + )); + } + })(); + }); + + H.config = (c) => { + /** + * Sets default properties for an Object + * @param {object} obj - The object to set defaults to + * @param {object} defaults - The defaults to set + * @returns {object} + */ + const setDefaults = (obj, defaults) => { + if (obj) { + o.entries(defaults).forEach(([k, v]) => { + // eslint-disable-next-line security/detect-object-injection + obj[k] = obj[k] || v; + }); + return obj; + } + return defaults; + }; + + H.cft = Boolean(c.cacheFeatureTests); + if (H.cft && store.getItem(scriptName)) { + H.cf = JSON.parse(store.getItem(scriptName)); + H.cf.langs = mp(H.cf.langs); + } else { + H.cf = { + "langs": mp(), + "pf": false + }; + } + + const maindir = thisScript.slice(0, (thisScript.lastIndexOf("/") + 1)); + const patterndir = maindir + "patterns/"; + H.paths = setDefaults(c.paths, { + maindir, + patterndir + }); + H.s = setDefaults(c.setup, { + "CORScredentials": "include", + "hide": "all", + "selectors": {".hyphenate": {}}, + "timeout": 1000 + }); + // Change mode string to mode int + H.s.hide = ["all", "element", "text"].indexOf(H.s.hide); + if (c.handleEvent) { + H.hev = c.handleEvent; + } + + const fallbacks = mp(o.entries(c.fallbacks || {})); + H.lrq = mp(); + o.entries(c.require).forEach(([lang, wo]) => { + H.lrq.set(lang.toLowerCase(), { + "fn": fallbacks.get(lang) || lang, + wo + }); + }); + + main(); + }; +})(window, document, Hyphenopoly, Object); diff --git a/prototype/Ink Export.code-workspace b/prototype/Ink Export.code-workspace new file mode 100644 index 0000000..876a149 --- /dev/null +++ b/prototype/Ink Export.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/prototype/LICENSE.md b/prototype/LICENSE.md new file mode 100644 index 0000000..b823bcc --- /dev/null +++ b/prototype/LICENSE.md @@ -0,0 +1,39 @@ +CC0 1.0 Universal +================== + +Statement of Purpose +--------------------- + +The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. +-------------------------------- +A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: + +i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; +ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; +iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; +v. rights protecting the extraction, dissemination, use and reuse of data in a Work; +vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and +vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. +----------- +To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. +---------------------------- +Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. +-------------------------------- + +a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. +b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. +c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. +d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. diff --git a/prototype/OFL.txt b/prototype/OFL.txt new file mode 100644 index 0000000..7436817 --- /dev/null +++ b/prototype/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2017 The EB Garamond Project Authors (https://github.com/octaviopardo/EBGaramond12) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/prototype/OpenSans-Italic-VariableFont_wdth,wght.ttf b/prototype/OpenSans-Italic-VariableFont_wdth,wght.ttf new file mode 100644 index 0000000..5bda9cc Binary files /dev/null and b/prototype/OpenSans-Italic-VariableFont_wdth,wght.ttf differ diff --git a/prototype/OpenSans-VariableFont_wdth,wght.ttf b/prototype/OpenSans-VariableFont_wdth,wght.ttf new file mode 100644 index 0000000..e4142bf Binary files /dev/null and b/prototype/OpenSans-VariableFont_wdth,wght.ttf differ diff --git a/prototype/Quattrocento-Bold.ttf b/prototype/Quattrocento-Bold.ttf new file mode 100644 index 0000000..2767744 Binary files /dev/null and b/prototype/Quattrocento-Bold.ttf differ diff --git a/prototype/Quattrocento-Regular.ttf b/prototype/Quattrocento-Regular.ttf new file mode 100644 index 0000000..73b7278 Binary files /dev/null and b/prototype/Quattrocento-Regular.ttf differ diff --git a/prototype/README.md b/prototype/README.md new file mode 100644 index 0000000..24acad8 --- /dev/null +++ b/prototype/README.md @@ -0,0 +1,40 @@ +# electron-quick-start + +**Clone and run for a quick way to see Electron in action.** + +This is a minimal Electron application based on the [Quick Start Guide](https://electronjs.org/docs/latest/tutorial/quick-start) within the Electron documentation. + +A basic Electron application needs just these files: + +- `package.json` - Points to the app's main file and lists its details and dependencies. +- `main.js` - Starts the app and creates a browser window to render HTML. This is the app's **main process**. +- `index.html` - A web page to render. This is the app's **renderer process**. +- `preload.js` - A content script that runs before the renderer process loads. + +You can learn more about each of these components in depth within the [Tutorial](https://electronjs.org/docs/latest/tutorial/tutorial-prerequisites). + +## To Use + +To clone and run this repository you'll need [Git](https://git-scm.com) and [Node.js](https://nodejs.org/en/download/) (which comes with [npm](http://npmjs.com)) installed on your computer. From your command line: + +```bash +# Clone this repository +git clone https://github.com/electron/electron-quick-start +# Go into the repository +cd electron-quick-start +# Install dependencies +npm install +# Run the app +npm start +``` + +Note: If you're using Linux Bash for Windows, [see this guide](https://www.howtogeek.com/261575/how-to-run-graphical-linux-desktop-applications-from-windows-10s-bash-shell/) or use `node` from the command prompt. + +## Resources for Learning Electron + +- [electronjs.org/docs](https://electronjs.org/docs) - all of Electron's documentation +- [Electron Fiddle](https://electronjs.org/fiddle) - Electron Fiddle, an app to test small Electron experiments + +## License + +[CC0 1.0 (Public Domain)](LICENSE.md) diff --git a/prototype/TheIntercept.ink.json b/prototype/TheIntercept.ink.json new file mode 100644 index 0000000..b750bea --- /dev/null +++ b/prototype/TheIntercept.ink.json @@ -0,0 +1 @@ +{"inkVersion":21,"root":[["#","^title: The Intercept","/#","#","^author: inkle Ltd.","/#","ev",{"VAR?":"DEBUG"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^IN DEBUG MODE!","\n","ev","str","^Beginning...","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Framing Hooper...","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^In with Hooper...","/str","/ev",{"*":".^.c-2","flg":20},{"->":"0.11"},{"c-0":["^\t",{"->":"start"},"\n",{"#f":5}],"c-1":["^ ",{"->":"claim_hooper_took_component"},"\n",{"#f":5}],"c-2":["^ ",{"->":"inside_hoopers_hut"},"\n",{"#f":5}]}]}],[{"->":".^.b"},{"b":["\n",{"->":"start"},{"->":"0.11"},null]}],"nop","\n",["done",{"#f":5,"#n":"g-0"}],null],"done",{"lower":[{"temp=":"x"},"ev",{"VAR?":"x"},1,"-","/ev",{"temp=":"x","re":true},{"#f":1}],"raise":[{"temp=":"x"},"ev",{"VAR?":"x"},1,"+","/ev",{"temp=":"x","re":true},{"#f":1}],"start":[["#","^CHAPTER: 1. The intercept","/#",["^They are keeping me waiting.","\n",["ev",{"^->":"start.0.g-0.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^Hut 14",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"start.0.g-0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"^. The door was locked after I sat down. ","\n","^I don't even have a pen to do any work. There's a copy of the morning's intercept in my pocket, but staring at the jumbled letters will only drive me mad.","\n","^I am not a machine, whatever they say about me.","\n",{"->":".^.^.^.opts"},{"#f":5}],"#f":5,"#n":"g-0"}],{"opts":[["ev","visit",2,"MIN","/ev","ev","du",0,"==","/ev",{"->":".^.s0","c":true},"ev","du",1,"==","/ev",{"->":".^.s1","c":true},"ev","du",2,"==","/ev",{"->":".^.s2","c":true},"nop",{"s0":["pop",{"->":".^.^.23"},null],"s1":["pop","^I rattle my fingers on the field table.",{"->":".^.^.23"},null],"s2":["pop",{"->":".^.^.23"},null],"#f":5}],"\n","ev","str","^Think","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Plan","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Wait","/str","/ev",{"*":".^.c-3","flg":20},{"c-1":["^ ","\n","^They suspect me to be a traitor. They think I stole the component from the calculating machine. They will be searching my bunk and cases.","\n","^When they don't find it, ","ev",{"CNT?":".^.^.c-2"},"/ev",[{"->":".^.b","c":true},{"b":["^then",{"->":".^.^.^.9"},null]}],"nop","^ they'll come back and demand I talk.","\n",{"->":".^.^"},{"->":".^.^.^.g-1"},{"#f":5}],"c-2":["\n","ev",{"CNT?":".^.^.c-1"},"!","/ev",[{"->":".^.b","c":true},{"b":["^What I am is",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^I am",{"->":".^.^.^.7"},null]}],"nop","^ a problem-solver. Good with figures, quick with crosswords, excellent at chess.","\n","^But in this scenario — in this trap — what is the winning play?","\n",["ev","str","^Co—operate","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Dissemble","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Divert","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^I must co—operate. My credibility is my main asset. To contradict myself, or another source, would be fatal.","\n","^I must simply hope they do not ask the questions I do not want to answer.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":"start.0.g-1"},{"#f":5}],"c-1":["^ ","\n","^Misinformation, then. Just as the war in Europe is one of plans and interceptions, not planes and bombs.","\n","^My best hope is a story they prefer to the truth.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":"start.0.g-1"},{"#f":5}],"c-2":["^ ","\n","^Avoidance and delay. The military machine never fights on a single front. If I move slowly enough, things will resolve themselves some other way, my reputation intact.","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":"start.0.g-1"},{"#f":5}]}],{"#f":5}],"c-3":["^\t\t","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":[{"->":"start.waited"},{"#f":5}]}],{"waited":[[["^Half an hour goes by before Commander Harris returns. He closes the door behind him quickly, as though afraid a loose word might slip inside.","\n","^\"Well, then,\" he begins, awkwardly. This is an unseemly situation.","\n",["ev",{"^->":"start.waited.0.g-0.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^\"Commander.\"",{"->":"$r","var":true},null]}],["ev",{"^->":"start.waited.0.g-0.5.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str",{"CNT?":"start.0.opts.c-2.12.c-2"},"!","/ev",{"*":".^.^.c-1","flg":19},{"s":["^\"Tell me what this is about.\"",{"->":"$r","var":true},null]}],"ev","str","^Wait","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["ev",{"^->":"start.waited.0.g-0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"\n","^He nods. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-1":["ev",{"^->":"start.waited.0.g-0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.5.s"},[{"#n":"$r2"}],"\n","^He shakes his head.","\n","^\"Now, don't let's pretend.\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-2":["\n","^I say nothing.","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5,"#n":"g-0"}],{"g-1":["^He has brought two cups of tea in metal mugs: he sets them down on the tabletop between us.","\n","ev","str","^Deny","/str",{"CNT?":".^.^.g-0.c-1"},"/ev",{"*":".^.c-3","flg":21},"ev","str","^Take one","/str","/ev",{"*":".^.c-4","flg":20},["ev",{"^->":"start.waited.0.g-1.15.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str",{"CNT?":".^.^.^.g-0.c-1"},"!","/ev",{"*":".^.^.c-5","flg":19},{"s":["^\"What's going on?\"",{"->":"$r","var":true},null]}],"ev","str","^Wait","/str","/ev",{"*":".^.c-6","flg":20},{"c-3":["^ \"I'm not pretending anything.\"","\n","ev",{"CNT?":"start.0.opts.c-2.12.c-0"},"/ev",[{"->":".^.b","c":true},{"b":["^I'm lying already, despite my good intentions.",{"->":".^.^.^.6"},null]}],"nop","\n","^Harris looks disapproving. ",{"->":".^.^.c-6.3.pushes_cup"},"\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-4":["\n","ev",true,"/ev",{"VAR=":"teacup","re":true},"^I take a mug and warm my hands. It's ","<>","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-5":["ev",{"^->":"start.waited.0.g-1.c-5.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.15.s"},[{"#n":"$r2"}],"\n","^\"You know already.\"","\n",{"->":".^.^.c-6.3.pushes_cup"},{"->":".^.^.^.g-2"},{"#f":5}],"c-6":["\n","^I wait for him to speak.","\n",[["^He pushes one mug halfway towards me: ","<>","\n",{"->":".^.^.^.^.^.g-2"},{"#f":5,"#n":"pushes_cup"}],null],{"#f":5}],"#f":5}],"g-2":["^a small gesture of friendship.","\n","^Enough to give me hope?","\n","ev","str","^Take it","/str",{"VAR?":"teacup"},"!","/ev",{"*":".^.c-7","flg":21},"ev","str","^Don't take it","/str",{"VAR?":"teacup"},"!","/ev",{"*":".^.c-8","flg":21},"ev","str","^Drink","/str",{"VAR?":"teacup"},"/ev",{"*":".^.c-9","flg":21},"ev","str","^Wait","/str",{"VAR?":"teacup"},"/ev",{"*":".^.c-10","flg":21},{"c-7":["^ ","\n","^I ","ev",{"CNT?":".^.^.^.g-1.c-4"},"/ev",[{"->":".^.b","c":true},{"b":["^lift the mug",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["^take the mug,",{"->":".^.^.^.8"},null]}],"nop","^ and blow away the steam. It is too hot to drink.","\n","^Harris picks his own up and just holds it.","\n","ev",true,"/ev",{"VAR=":"teacup","re":true},"ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-8":["^ ","\n","^Just a cup of insipid canteen tea. I leave it where it is.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-9":["^ ","\n","^I raise the cup to my mouth but it's too hot to drink.","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-10":["^ \t\t","\n","^I say nothing as ",{"->":".^.^.c-7"},"\n",{"->":".^.^.^.g-3"},{"#f":5}],"#f":5}],"g-3":["^\"Quite a difficult situation,\" ","ev",{"CNT?":".^.^.g-2.c-7"},"/ev",[{"->":".^.b","c":true},{"b":["^he",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["^Harris",{"->":".^.^.^.6"},null]}],"nop","^ begins","ev",{"VAR?":"forceful"},0,"<=","/ev",[{"->":".^.b","c":true},{"b":["^, sternly",{"->":".^.^.^.14"},null]}],"nop","^. I've seen him adopt this stiff tone of voice before, but only when talking to the brass. \"I'm sure you agree.\"","\n","ev","str","^Agree","/str","/ev",{"*":".^.c-11","flg":20},"ev","str","^Disagree","/str","/ev",{"*":".^.c-12","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-13","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-14","flg":20},{"c-11":["^ ","\n","^\"Awkward,\" I reply","\n",{"->":".^.^.^.g-4"},{"#f":5}],"c-12":["^ ","\n","^\"I don't see why,\" I reply","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.^.g-4"},{"#f":5}],"c-13":["^ ",{"->":".^.^.c-12"},"\n",{"->":".^.^.^.g-4"},{"#f":5}],"c-14":["^ ","\n","^\"I'm sure you've handled worse,\" I reply casually","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.^.g-4"},{"#f":5}],"#f":5}],"g-4":["ev",{"VAR?":"teacup"},"/ev",[{"->":".^.b","c":true},{"b":["\n","ev",true,"/ev",{"VAR=":"drugged","re":true},"<>","^, sipping at my tea as though we were old friends","\n",{"->":".^.^.^.4"},null]}],"nop","\n","<>","^.","\n",["ev","str","^Watch him","/str","/ev",{"*":".^.c-15","flg":20},"ev","str","^Wait","/str","/ev",{"*":".^.c-16","flg":20},"ev","str","^Smile","/str",{"CNT?":".^.^.^.g-3.c-12"},"!","/ev",{"*":".^.c-17","flg":21},{"c-15":["\n","^His face is telling me nothing. I've seen Harris broad and full of laughter. Today he is tight, as much part of the military machine as the device in Hut 5.","\n",{"->":".^.^.^.^.g-6"},{"#f":5}],"c-16":["\n","^I wait to see how he'll respond.","\n",{"->":".^.^.^.^.g-6"},{"#f":5}],"c-17":["\n","^I try a weak smile. It is not returned.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":".^.^.^.^.g-6"},{"#f":5}],"#f":5,"#n":"g-5"}],{"#f":5}],"g-6":["^\"We need that component,\" he says.","\n",["ev",{"CNT?":"missing_reel"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n",{"->t->":"missing_reel"},{"->":"harris_demands_component"},{"->":".^.^.^.5"},null]}],"nop","\n",["ev","str","^Yes","/str","/ev",{"*":".^.c-18","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-19","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-20","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-21","flg":20},{"c-18":["\n","^\"Of course I do,\" I answer.","\n",{"->":".^.^.^.^.^.g-9"},{"#f":5}],"c-19":["\n","^\"No I don't. And I've got work to do...\"","\n","^\"Work that will be rather difficult for you to do, don't you think?\" Harris interrupts.","\n",{"->":".^.^.^.^.^.g-9"},{"#f":5}],"c-20":["\n",{"->":"here_at_bletchley_diversion"},{"->":".^.^.^.^.^.g-9"},{"#f":5}],"c-21":["^ ","\n",{"->":".^.^.c-19"},{"->":".^.^.^.^.^.g-9"},{"#f":5}],"#f":5,"#n":"g-8"}],{"#f":5,"#n":"g-7"}],{"#f":5}],"g-9":[{"->t->":"missing_reel"},{"->":"harris_demands_component"},{"#f":5}]}],{"#f":1}],"#f":1}],"missing_reel":[["ev","str","^The stolen component...","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Shrug","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["\n","^I shrug.","\n","ev","void","/ev","->->",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^The reel went missing from the Bombe this afternoon. The four of us were in the Hut, working on the latest German intercept. The results were garbage. It was Russell who found the gap in the plugboard.","\n",["^Any of us could have taken it; and no one else would have known its worth.","\n","ev","str","^Panic","/str",{"VAR?":"forceful"},0,"<=","/ev",{"*":".^.c-2","flg":21},"ev","str","^Calculate","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Deny","/str",{"VAR?":"evasive"},0,">=","/ev",{"*":".^.c-4","flg":21},{"c-2":["^ They will pin it on me. They need a scapegoat so that the work can continue. I'm a likely target. Weaker than the rest. ","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":".^.^.^.^.g-2"},{"#f":5}],"c-3":["^ My odds, then, are one in four. Not bad; although the stakes themselves are higher than I would like.","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.^.^.g-2"},{"#f":5}],"c-4":["^ But this is still a mere formality. The work will not stop. A replacement component will be made and we will all be put back to work. We are too valuable to shoot. ","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.^.^.g-2"},{"#f":5}],"#f":5,"#n":"g-1"}],{"#f":5}],"g-2":["ev","void","/ev","->->",{"#f":5}]}],{"#f":1}],"here_at_bletchley_diversion":[["^\"Here at Bletchley? Of course.\"","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","^\"Here, now,\" Harris corrects. \"We are not talking to everyone. I can imagine you might feel pretty sore about that. I can imagine you feeling picked on. ","ev",{"VAR?":"forceful"},0,"<","/ev",[{"->":".^.b","c":true},{"b":["^You're a sensitive soul.",{"->":".^.^.^.21"},null]}],"nop","^\"","\n",["ev",{"^->":"here_at_bletchley_diversion.0.24.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str","/ev",{"*":".^.^.c-0","flg":22},{"s":["^\"I'm fine",{"->":"$r","var":true},null]}],["ev",{"^->":"here_at_bletchley_diversion.0.25.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str",{"VAR?":"forceful"},0,"<","/ev",{"*":".^.^.c-1","flg":19},{"s":["^\"What do you mean by that?\"",{"->":"$r","var":true},null]}],["ev",{"^->":"here_at_bletchley_diversion.0.26.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str",{"VAR?":"forceful"},0,">=","/ev",{"*":".^.^.c-2","flg":23},{"s":["^\"Damn right",{"->":"$r","var":true},null]}],"ev","str","^Be honest","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-4","flg":20},{"c-0":["ev",{"^->":"here_at_bletchley_diversion.0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.24.s"},[{"#n":"$r2"}],"^,\" I reply. \"This is all some misunderstanding and the quicker we have it cleared up the better.\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","^\"I couldn't agree more.\" And then he comes right out with it, with an accusation.","\n",{"->":".^.^.done"},{"#f":5}],"c-1":["ev",{"^->":"here_at_bletchley_diversion.0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.25.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.done"},{"#f":5}],"c-2":["ev",{"^->":"here_at_bletchley_diversion.0.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.26.s"},[{"#n":"$r2"}],"^ I'm sore. Was it one of the others who put you up to this? Was it Hooper? He's always been jealous of me. He's...\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n","ev",true,"/ev",{"VAR=":"hooper_mentioned","re":true},"^The Commander moustache bristles as he purses his lips. \"Has he now? Of your achievements, do you think?\"","\n","^It's difficult not to shake the sense that he's ","ev",{"VAR?":"evasive"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^mocking",{"->":".^.^.^.28"},null]}],[{"->":".^.b"},{"b":["^simply humouring",{"->":".^.^.^.28"},null]}],"nop","^ me.","\n","^\"Or of your brain? Or something else?\"","\n",[["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-0","flg":22},{"s":["^\"Of my genius.",{"->":"$r","var":true},null]}],["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["^\"Of my standing.",{"->":"$r","var":true},null]}],"ev","str","^Evade","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"^ Hooper simply can't stand that I'm cleverer than he is. We work so closely together, cooped up in that Hut all day. It drives him to distraction. To worse.\"","\n","^\"You're suggesting Hooper would sabotage this country's future simply to spite you?\" Harris chooses his words like the military man he is, each lining up to create a ring around me.","\n",["ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ \t\t\t","\n","^\"","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^He's petty enough, certainly",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^I wouldn't put it past him",{"->":".^.^.^.10"},null]}],"nop","^. He's a creep.\" ","ev",{"VAR?":"teacup"},"/ev",[{"->":".^.b","c":true},{"b":["^ I set the teacup down.",{"->":".^.^.^.17"},null]}],[{"->":".^.b"},{"b":["^I wipe a hand across my forehead.",{"->":".^.^.^.17"},null]}],"nop","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n","ev",false,"/ev",{"VAR=":"teacup","re":true},{"->":".^.^.suggest_its_a_lie"},{"#f":5}],"c-1":["^ \t\t\t","\n","^\"No, ","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^of course not",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^I suppose not",{"->":".^.^.^.10"},null]}],"nop","^.\" ","ev",{"VAR?":"teacup"},"/ev",[{"->":".^.b","c":true},{"b":["^I put the teacup back down on the table",{"->":".^.^.^.17"},null]}],[{"->":".^.b"},{"b":["^I push the teacup around on its base",{"->":".^.^.^.17"},null]}],"nop","^.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","ev",false,"/ev",{"VAR=":"teacup","re":true},{"->":".^.^.suggest_its_a_lie"},{"#f":5}],"c-2":["^ \t\t","\n","^\"I don't know what I'm suggesting. I don't understand what's going on.\"","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n","^\"But of course you do.\" Harris narrows his eyes.","\n",{"->":".^.^.^.^.^.^.done"},{"->":".^.^.suggest_its_a_lie"},{"#f":5}],"suggest_its_a_lie":["^\"All I can say is, ever since I arrived here, he's been looking to ways to bring me down a peg. I wouldn't be surprised if he set this whole affair up just to have me court—martialled.\"","\n","^\"We don't court—martial civilians,\" Harris replies. \"Traitors are simply hung at her Majesty's pleasure.\"","\n",["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-0.10.suggest_its_a_lie.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str","/ev",{"*":".^.^.c-3","flg":22},{"s":["^\"Quite right",{"->":"$r","var":true},null]}],["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-0.10.suggest_its_a_lie.5.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str","/ev",{"*":".^.^.c-4","flg":22},{"s":["^\"I'm no traitor",{"->":"$r","var":true},null]}],"ev","str","^Lie","/str","/ev",{"*":".^.c-5","flg":20},{"c-3":["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-0.10.suggest_its_a_lie.c-3.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"^,\" I answer smartly.","\n",{"->":".^.^.^.g-0"},{"#f":5}],"c-4":["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-0.10.suggest_its_a_lie.c-4.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.5.s"},[{"#n":"$r2"}],"^,\" I answer","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^smartly",{"->":".^.^.^.14"},null]}],[{"->":".^.b"},{"b":["^, voice quivering. \"For God's sake!\"",{"->":".^.^.^.14"},null]}],"nop","\n",{"->":".^.^.^.g-0"},{"#f":5}],"c-5":["^ ",{"->":".^.^.c-4"},"\n",{"->":".^.^.^.g-0"},{"#f":5}],"#f":5}],"g-0":["^He stares back at me.","\n",{"->":".^.^.^.^.^.^.done"},{"#f":5}]}],{"#f":5}],"c-1":["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"^ My reputation.\" ","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^I'm aware of how arrogant I must sound but I plough on all the same.",{"->":".^.^.^.14"},null]}],[{"->":".^.b"},{"b":["^I don't like to talk of myself like this, but I carry on all the same.",{"->":".^.^.^.14"},null]}],"nop","^ \"Hooper simply can't bear knowing that, once all this is over, I'll be the one receiving the knighthood and he...\"","\n","^\"No—one will be getting a knighthood if the Germans make landfall,\" Harris answers sharply. He casts a quick eye to the door of the Hut to check the latch is still down, then continues in more of a murmur: \"Not you and not Hooper. Now answer me.\"","\n","^For the first time since the door closed, I wonder what the threat might be if I do not.","\n",{"->":".^.^.^.^.done"},{"#f":5}],"c-2":["^ \t\t\t\t","\n","ev",false,"/ev",{"VAR=":"teacup","re":true},"ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n","^\"How should I know?\" I reply, defensively. ","ev",{"VAR?":"teacup"},"/ev",[{"->":".^.b","c":true},{"b":["^I set the teacup back on the table.",{"->":".^.^.^.17"},null]}],"nop","^ ",{"->":".^.^.c-0.10.suggest_its_a_lie"},"\n",{"->":".^.^.^.^.done"},{"#f":5}]}],{"#f":5}],"c-3":["^ \t",{"->":".^.^.c-2"},"\n",{"->":".^.^.done"},{"#f":5}],"c-4":["^ \t\t",{"->":".^.^.c-0"},"\n",{"->":".^.^.done"},{"#f":5}],"done":[{"->":"harris_demands_component"},{"#f":5}]}],{"#f":1}],"harris_demands_component":[["^\"","ev",{"CNT?":"here_at_bletchley_diversion"},"/ev",[{"->":".^.b","c":true},{"b":["^Please",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["^So",{"->":".^.^.^.6"},null]}],"nop","^. Do you have it?\" Harris is ","ev",{"VAR?":"forceful"},3,">","/ev",[{"->":".^.b","c":true},{"b":["^sweating slightly",{"->":".^.^.^.15"},null]}],[{"->":".^.b"},{"b":["^wasting no time",{"->":".^.^.^.15"},null]}],"nop","^: Bletchley is his watch. \"Do you know where it is?\"","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["\n","^\"I do.\"","\n",{"->":"admitted_to_something"},{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ \"I have no idea.\" ","\n",{"->":".^.^.silence"},{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ \t\t",{"->":".^.^.c-1"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-3":["^ \t\t","\n","^\"The component?\"","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","^\"Don't play stupid,\" he replies. \"","ev",{"CNT?":"missing_reel"},"!","/ev",[{"->":".^.b","c":true},{"b":["^The component that went missing this afternoon. ",{"->":".^.^.^.22"},null]}],"nop","^Where is it?\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["ev",{"CNT?":"missing_reel"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n",{"->t->":"missing_reel"},{"->":".^.^.^.5"},null]}],"nop","\n","ev","str","^Co-operate","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^Delay","/str","/ev",{"*":".^.c-5","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-6","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-7","flg":20},{"c-4":["^ \"I know where it is.\"","\n",{"->":"admitted_to_something"},{"->":".^.^.^.silence"},{"#f":5}],"c-5":["^ \"I know nothing about it.\" My voice shakes","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^ with anger",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["^; I'm unaccustomed to facing off against men with holstered guns",{"->":".^.^.^.8"},null]}],"nop","^. ","\n",{"->":".^.^.^.silence"},{"#f":5}],"c-6":["^ ",{"->":".^.^.c-5"},"\n",{"->":".^.^.^.silence"},{"#f":5}],"c-7":["^ ","\n","^\"I don't know what gives you the right to pick on me. ","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^I demand a lawyer.",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^I want a lawyer.",{"->":".^.^.^.10"},null]}],"nop","^\"","\n","^\"This is time of war,\" Harris answers. \"And by God, if I have to shoot you to recover the component, I will. Understand?\" He points at the mug, ",{"->":".^.^.^.silence.drinkit"},"\n",{"->":".^.^.^.silence"},{"#f":5}],"#f":5}],"silence":["^There's an icy silence. ","ev",{"VAR?":"forceful"},2,">","/ev",[{"->":".^.b","c":true},{"b":["^I've cracked him a little.",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["ev",{"VAR?":"evasive"},2,">","/ev",[{"->":".^.b","c":true},{"b":["^He's tiring of my evasiveness.",{"->":".^.^.^.6"},null]}],"nop",{"->":".^.^.^.8"},null]}],"nop","\n",["^\"Now drink your tea and talk.\"","\n","ev","str","^Drink","/str",{"VAR?":"teacup"},"/ev",{"*":".^.c-8","flg":21},"ev","str","^Put the cup down","/str",{"VAR?":"teacup"},"/ev",{"*":".^.c-9","flg":21},"ev","str","^Take the cup","/str",{"VAR?":"teacup"},"!","/ev",{"*":".^.c-10","flg":21},"ev","str","^Don't take it","/str",{"VAR?":"teacup"},"!","/ev",{"*":".^.c-11","flg":21},{"c-8":["^ \t\t\t",{"->":".^.^.c-10.2.drinkfromcup"},"\n",{"->":".^.^.^.^.g-1"},{"#f":5}],"c-9":["^ ","\n","^I set the cup carefully down on the table once more.","\n","ev",false,"/ev",{"VAR=":"teacup","re":true},"ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.c-11.10.whatsinit"},{"->":".^.^.^.^.g-1"},{"#f":5}],"c-10":["^ ","\n",[["^I lift the cup ","ev",{"VAR?":"teacup"},"/ev",[{"->":".^.b","c":true},{"b":["^to my lips ",{"->":".^.^.^.5"},null]}],"nop","^and sip. He waits for me to swallow before speaking again.","\n","ev",true,"/ev",{"VAR=":"drugged","re":true},"ev",true,"/ev",{"VAR=":"teacup","re":true},{"->":".^.^.^.^.^.^.g-1"},{"#f":5,"#n":"drinkfromcup"}],null],{"#f":5}],"c-11":["^ ","\n","^I leave the cup where it is.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",[["^\"Why?\" I ask coldly. \"What's in it?\"","\n",{"->":".^.^.^.^.^.^.g-1"},{"#f":5,"#n":"whatsinit"}],null],{"#f":5}],"#f":5,"#n":"drinkit"}],{"#f":5}],"g-1":["^\"Lapsang Souchong,\" he ","ev",{"CNT?":".^.^.silence.drinkit.c-10.2.drinkfromcup"},"/ev",[{"->":".^.b","c":true},{"b":["^remarks",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["^replies",{"->":".^.^.^.6"},null]}],"nop","^, placing his own cup back on the table untouched. \"Such a curious flavour. It might almost not be tea at all. You might say it hides a multitude of sins. As do you. Isn't that right?\"","\n","ev","str","^Agree","/str","/ev",{"*":".^.c-12","flg":20},"ev","str","^Disagree","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-13","flg":21},"ev","str","^Disagree","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-14","flg":21},"ev","str","^Lie","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-15","flg":21},"ev","str","^Lie","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-16","flg":21},"ev","str","^Evade","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-17","flg":21},"ev","str","^Evade","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-18","flg":21},{"c-12":["^ ","\n","^\"I suppose so,\" I reply. \"I've done things I shouldn't have done.\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":"harris_presses_for_details"},{"#f":5}],"c-13":["\n","^\"I've done nothing that I'm ashamed of.\"","\n",{"->":"harris_asks_for_theory"},{"#f":5}],"c-14":["^ ","\n","^I open my mouth to disagree, but the words I want won't come. It is like Harris has taken a screwdriver to the sides of my jaw.","\n",{"->":"admitted_to_something.ive_done_things"},{"#f":5}],"c-15":["^ \t",{"->":".^.^.c-14"},"\n",{"#f":5}],"c-16":["^ \t",{"->":".^.^.c-13"},"\n",{"#f":5}],"c-17":["^ ",{"->":".^.^.c-14"},"\n",{"#f":5}],"c-18":["^ ","\n","^\"None of us are blameless, Harris. ","ev",{"VAR?":"forceful"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^But you're not my priest and I'm not yours",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^But I've done nothing to deserve this treatment",{"->":".^.^.^.10"},null]}],"nop","^. Now, please. Let me go. I'll help you find this damn component, of course I will.\"","\n","^He appears to consider the offer.","\n",{"->":"harris_asks_for_theory"},{"#f":5}],"#f":5}]}],{"#f":1}],"harris_presses_for_details":[["^\"You mean you've left yourself open,\" Harris answers. \"To pressure. Is that what you're saying?\"","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^No","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-2","flg":21},"ev","str","^Evade","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-3","flg":21},"ev","str","^Evade","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-4","flg":21},{"c-0":["^ ",{"->":".^.^.^.admit_open_to_pressure"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"I'm not saying anything of the sort,\" I snap back. \"What is this, Harris? You're accusing me of treachery but I don't see a shred of evidence for it! Why don't you put your cards on the table?\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^I shake my head violently, to say no, that's not it, but whatever is wrong with tongue is wrong with neck too. I look across at the table at Harris' face and realise with a start how sympathetic he is. Such a kind, generous man. How can I hold anything back from him?","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","^I take another mouthful of the bitter, strange—tasting tea before answering.","\n",{"->":".^.^.^.admit_open_to_pressure"},{"->":".^.^.g-0"},{"#f":5}],"c-3":["^ ","\n","^\"You're the one applying pressure here,\" I answer ","ev",{"VAR?":"forceful"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^smartly",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^somewhat miserably",{"->":".^.^.^.10"},null]}],"nop","^. \"I'm just waiting until you tell me what is really going on.\"","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.g-0"},{"#f":5}],"c-4":["^ \t\t\t\t ","\n","^\"We're all under pressure here.\"","\n","^He looks at me with pity. ",{"->":"harris_has_seen_it_before"},"\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"It's simple enough,\" Harris says. ",{"->":"harris_has_seen_it_before"},"\n",{"#f":5}]}],{"admit_open_to_pressure":["^\"That's it,\" I reply. \"There are some things... which a man shouldn't do.\"","\n","ev",true,"/ev",{"VAR=":"admitblackmail","re":true},"^Harris doesn't stiffen. Doesn't lean away, as though my condition might be infectious. I had thought they trained them in the army to shoot my kind on sight.","\n","^He offers no sympathy either. He nods, once. His understanding of me is a mere turning cog in his calculations, with no meaning to it.","\n",{"->":"harris_has_seen_it_before"},{"#f":1}],"#f":1}],"admitted_to_something":[["ev",{"VAR?":"drugged"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^Harris stares back at me. ","ev",{"VAR?":"evasive"},0,"==","/ev",[{"->":".^.b","c":true},{"b":["^He cannot have expected it to be so easy to break me.",{"->":".^.^.^.8"},null]}],"nop","\n",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["\n","^Harris smiles with satisfaction, as if your willingness to talk was somehow his doing.","\n",{"->":".^.^.^.6"},null]}],"nop","\n","^\"I see.\"","\n","^There's a long pause, like the delay between feeding a line of cypher into the Bombe and waiting for its valves to warm up enough to begin processing.","\n","^\"You want to explain that?\"","\n","ev","str","^Explain","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't explain","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^Lie","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-2","flg":21},"ev","str","^Evade","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-3","flg":21},"ev","str","^Say nothing","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-4","flg":21},{"c-0":["^ ","\n","^I pause a moment, trying to choose my words. To just come out and say it, after a lifetime of hiding... that is a circle I cannot square.","\n",["ev","str","^Explain","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Say nothing","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-1","flg":21},"ev","str","^Lie","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-2","flg":21},{"c-0":["^ \t",{"->":".^.^.^.^.^.ive_done_things"},"\n",{"#f":5}],"c-1":["^ \t",{"->":".^.^.^.^.c-4"},"\n",{"#f":5}],"c-2":["^ \t",{"->":"claim_hooper_took_component"},"\n",{"#f":5}]}],{"#f":5}],"c-1":["\n","^\"There's nothing to explain,\" I reply stiffly. ",{"->":".^.^.^.i_know_where"},"\n",{"#f":5}],"c-2":["^ ",{"->":"claim_hooper_took_component"},"\n",{"#f":5}],"c-3":["\n","^\"Explain what you should be doing, do you mean, rather than bullying me? Certainly.\" I fold my arms. ",{"->":".^.^.^.i_know_where"},"\n",{"#f":5}],"c-4":["\n","^I fold my arms, intended firmly to say nothing. But somehow, watching Harris' face, I cannot bring myself to do it. I want to confess. I want to tell him everything I can, to explain myself to him, to earn his forgiveness. The sensation is so strong my will is powerless in the face of it.","\n","^Something is wrong with me, I am sure of it. There is a strange, bitter flavour on my tongue. I taste it as words start to form.","\n",{"->":".^.^.^.ive_done_things"},{"#f":5}]}],{"i_know_where":["^\"I know where your component is because it's obvious where your component is. That doesn't mean I took it, just because I can figure out a simple problem, any more than it means I'm a German spy because I can crack their codes.\"","\n",{"->":"harris_asks_for_theory"},{"#f":1}],"ive_done_things":["^\"I've done things,\" I begin","ev",{"CNT?":"harris_demands_component.0.g-1.c-14"},"/ev",[{"->":".^.b","c":true},{"b":["^ helplessly",{"->":".^.^.^.5"},null]}],"nop","^. \"Things I didn't want to do. I tried not to. But in the end, it felt like cutting off my own arm to resist.\"","\n",{"->":"harris_presses_for_details"},{"#f":1}],"#f":1}],"harris_asks_for_theory":[["^\"Tell me, then,\" he asks. \"What's your theory? You're a smart fellow — as smart as they come around here, and that's saying something. What's your opinion on the missing component? Accident, perhaps? Or do you blame one of the other men? ","ev",{"VAR?":"hooper_mentioned"},"/ev",[{"->":".^.b","c":true},{"b":["^Hooper?",{"->":".^.^.^.5"},null]}],"nop","^\"","\n","ev","str","^Blame no—one","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Blame someone","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n",{"->":".^.^.^.an_accident"},{"#f":5}],"c-1":["^ ",{"->":"claim_hooper_took_component"},"\n",{"#f":5}]}],{"an_accident":[["^\"An accident, naturally.\" I risk a smile. \"That damned machine is made from spare parts and string. Even these Huts leak when it rains. It wouldn't take more than one fellow to trip over a cable to shake out a component. Have you tried looking under the thing?\"","\n","^\"Do you believe we haven't?\"","\n","^In a sudden moment I understand that his reply is a threat.","\n","^\"Now,\" he continues. \"Are you sure there isn't anything you want to tell me?\"","\n","ev","str","^Co-operate","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Evade","/str",{"VAR?":"evasive"},0,">","/ev",{"*":".^.c-1","flg":21},{"c-0":["\n","^\"All right.\" With a sigh, your defiance collapses. \"If you're searched my things then I suppose you've found ","ev",{"VAR?":"evasive"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^ what you need",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["^my letters. Haven't you? In fact, if you haven't, don't tell me",{"->":".^.^.^.9"},null]}],"nop","^.","\n","ev",true,"/ev",{"VAR=":"admitblackmail","re":true},"^Harris nods once.","\n","<>","^ ",{"->":"harris_has_seen_it_before"},"\n",{"#f":5}],"c-1":["^ \"Only that you're being unreasonable, and behaving like a swine.\"","\n","^\"You imbecile,\" Harris replies, with sudden force. He is half out of his chair. \"You know the situation as well as I do. Why the fencing? The Hun are poised like rats, ready to run all over this country. They'll destroy everything. You understand that, don't you? You're not so locked up inside your crossword puzzles that you don't see that, are you? This machine we have here — you men — you are the best and only hope this country has. God help her.\"","\n","ev",true,"/ev",{"VAR=":"losttemper","re":true},"^I sit back, startled by the force of his outburst. His carefully sculpted expression has curled to angry disgust. He really does hate me, I think. He'll have my blood for the taste of it.","\n",["ev","str","^Placate","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Mock","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Dismiss","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["\n","^\"Now steady on,\" I reply, gesturing for him to be calm.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"I can imagine how being surrounded by clever men is pretty threatening for you, Commander,\" I reply with a sneer. \"They don't train you to think in the Armed Forces.\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["\n","^\"Then I'll be going, on and getting on with my job of saving her, shall I?\" I even rise half to my feet, before he slams the tabletop.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"Talk,\" Harris demands. \"Talk now. Tell me where you've hidden it or who you passed it to. Or God help me, I'll take your wretched pansy body to pieces looking for it.\"","\n",{"->":"harris_demands_you_speak"},{"#f":5}]}],{"#f":5}]}],{"#f":1}],"#f":1}],"harris_has_seen_it_before":[["^\"I've seen it before. A young man like you — clever, removed. The kind that doesn't go to parties. Who takes himself too seriously. Who takes things too far.\"","\n","^He slides his thumb between two fingers.","\n","^\"Now they own you.\"","\n","ev","str","^Agree","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Disagree","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-2","flg":21},"ev","str","^Apologise","/str",{"VAR?":"drugged"},{"VAR?":"forceful"},0,"<","&&","/ev",{"*":".^.c-3","flg":21},{"c-0":["^ ","\n","^\"What could I do?\" I'm shaking now. The night is cold and the heat—lamp in the Hut has been removed. \"","ev",{"VAR?":"forceful"},2,">","/ev",[{"->":".^.b","c":true},{"b":["^I won't",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^I don't want to",{"->":".^.^.^.10"},null]}],"nop","^ go to prison.\"","\n","^\"Smart man,\" he replies. \"You wouldn't last.","\n",{"->":".^.^.tell_me_now"},{"#f":5}],"c-1":["^ ","\n","^\"I can still fix this.\"","\n","^Harris shakes his head. \"You'll do nothing. This is beyond you now. You may go to prison or may go to firing squad - or we can change your name and move you somewhere where your indiscretions can't hurt you. But right now, none of that matters. What happens to you doesn't matter. All that matters is where that component is.","\n",{"->":".^.^.tell_me_now"},{"#f":5}],"c-2":["^ ","\n","^\"I wanted to tell you,\" I tell him. \"I thought I could find out who they were. Lead you to them.\"","\n","^Harris looks at me with contempt. \"You wretch. You'll pay for what you've done to this country today. If a single man loses his life because of your pride and your perversions then God help your soul.","\n",{"->":".^.^.tell_me_now"},{"#f":5}],"c-3":["\n","^\"Harris, I...\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","^\"Stop it,\" he interrupts. \"There's no jury here to sway. And there's no time.","\n",{"->":".^.^.tell_me_now"},{"#f":5}],"tell_me_now":["<>","^ So why don't you tell me, right now. Where is it?\"","\n",{"->":"harris_demands_you_speak"},{"#f":5}]}],{"#f":1}],"harris_demands_you_speak":[["^His eyes bear down like carbonised drill—bits.","\n","ev","str","^Confess","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Dissemble","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^Dissemble","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-2","flg":21},{"c-0":["^ ","\n","ev",{"VAR?":"forceful"},1,">","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"You want me to tell you what happened? You'll be disgusted.\"","\n",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["\n","^\"All right. I'll tell you what happened.\" And never mind my shame.","\n",{"->":".^.^.^.9"},null]}],"nop","\n","^\"I can imagine how it starts,\" he replies.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ",{"->":"claim_hooper_took_component"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["\n","^My plan now is to blame Hooper, but I cannot seem to tell the story. Whatever they put in my tea, it rules my tongue. ","ev",{"VAR?":"forceful"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^I fight it as hard as I can but it does no good.",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["^I am desperate to tell him everything. I am weeping with shame.",{"->":".^.^.^.9"},null]}],"nop","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":[{"->":"i_met_a_young_man"},{"#f":5}]}],{"#f":1}],"i_met_a_young_man":[["ev","str","^Talk","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n","^\"There was a young man. I met him in the town. A few months ago now. We got to talking. Not about work. And I used my cover story, but he seemed to know it wasn't true. That got me wondering if he might be one of us.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Harris is not letting me off any more.","\n","^\"You seriously entertained that possibility?\"","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-3","flg":20},{"c-1":["\n","^\"Yes, I considered it. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-2":["^ ","\n","^\"No. Not for more than a moment, of course. Everyone here is marked out by how little we would be willing to say about it.\"","\n","^\"Only you told this young man more than a little, didn't you?\"","\n","^I nod. \"","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-3":["^ ","\n","^\"I was quite certain, after a while. After we'd been talking. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^He seemed to know all about me. He... he was quite enchanted by my achievements.\"","\n","^The way Harris is staring I expect him to strike me, but he does not. He replies, \"I can see how that must have been attractive to you,\" with such plain—spokeness that I think I must have misheard.","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^No","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-5","flg":21},"ev","str","^No","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-6","flg":21},"ev","str","^Lie","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-7","flg":21},{"c-4":["^ \"It's a lonely life in this place,\" I reply. \"Lonely - and still one never gets a moment to oneself.\"","\n","^\"That's how it is in the Service,\" Harris answers.","\n",["ev","str","^Argue","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Agree","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ \"I'm not in the Service.\"","\n","^Harris shakes his head. \"Yes, you are.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ \"Perhaps. But I didn't choose this life.\" ","\n","^Harris shakes his head. \"No. And there's plenty of others who didn't who are suffering far worse.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Then he waves the thought aside.","\n",{"->":".^.^.^.^.^.g-2"},{"#f":5}]}],{"#f":5}],"c-5":["^ \"The boy was a pretty simpleton. Quite inferior. His good opinion meant nothing to be. Harris, do not misunderstand. I was simply after his body.\"","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n","^Harris, to his credit, doesn't flinch; but I can see he will have nightmares of this moment later tonight. I'm tempted to reach out and take his hand to worsen it for him.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-6":["^ ","\n","^\"It wasn't,\" I reply. \"But I doubt you'd understand.\"","\n","^He simply nods.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-7":["^ ",{"->":".^.^.c-5"},"\n",{"->":".^.^.^.g-2"},{"#f":5}],"#f":5}],"g-2":["^\"Go on with your confession.\"","\n",["ev",{"CNT?":".^.^.^.g-1.c-5"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^That gives me pause. I hadn't thought of it as such. But I suppose he's right. I am about to admit what I did.","\n",{"->":".^.^.^.5"},null]}],"nop","\n","^\"There's not much else to say. I took the part from Bombe computing device. You seem to know that already. I had to. He was going to expose me if I didn't.\"","\n","^\"This young man was blackmailing you over your affair?\"","\n","ev",{"VAR?":"drugged"},"/ev",{"temp=":"harris_thinks_youre_drugged"},"ev",{"VAR?":"drugged"},"/ev",[{"->":".^.b","c":true},{"b":["\n","ev",false,"/ev",{"VAR=":"drugged","re":true},"^As Harris speaks I find myself suddenly sharply aware, as if waking from a long sleep. The table, the corrugated walls of the hut, everything seems suddenly more tangible than a moment before.","\n","^Whatever it was they put in my drink is wearing off.","\n",{"->":".^.^.^.19"},null]}],"nop","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-8","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-9","flg":20},"ev","str","^Tell the truth","/str","/ev",{"*":".^.c-10","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-11","flg":20},{"c-8":["^ ","\n","^\"Yes. I suppose he was their agent. I should have realised but I didn't. Then he threatened to tell you. I thought you would have me locked up: I couldn't bear the thought of it. I love working here. I've never been so happy, so successful, anywhere before. I didn't want to lose it.\"","\n","^\"So what did you do with the component?\" Harris talks urgently. He grips his gloves tightly in one hand, perhaps prepared to lift them and strike if it is required. \"Have you passed it to this man already? Have you left it somewhere for him to find?\"","\n",["ev","str","^I have it","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^I don't have it","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Tell the truth","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["^ \t","\n","^\"I still have it. Not on me, of course. ",{"->":"reveal_location_of_component"},"\n",{"#f":5}],"c-1":["^ \t",{"->":".^.^.^.^.^.^.^.i_dont_have_it"},"\n",{"#f":5}],"c-2":["^ \t\t\t\t\t\t\t",{"->":".^.^.c-1"},"\n",{"#f":5}],"c-3":["^ \t\t\t\t",{"->":".^.^.c-0"},"\n",{"#f":5}]}],{"#f":5}],"c-9":["^ ","\n","^\"No, Harris. The young man wasn't blackmailing me.\" I take a deep breath. \"It was Hooper.\"","\n","ev",{"VAR?":"hooper_mentioned"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Hooper!\" Harris exclaims, in surprise. ","ev",{"VAR?":"harris_thinks_youre_drugged"},"/ev",[{"->":".^.b","c":true},{"b":["^He does not doubt me for a moment.",{"->":".^.^.^.6"},null]}],"nop","\n",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["\n","^\"Now look here,\" Harris interrupts. \"Don't start that again.\"","\n",{"->":".^.^.^.10"},null]}],"nop","\n","^\"It's the truth, Harris. If I'm going to jail, so be it, but I won't hang at Traitor's Gate. Hooper was the one who told the boy about our work. Hooper put the boy on to me. ","ev",{"VAR?":"forceful"},2,"<","/ev",[{"->":".^.b","c":true},{"b":["^I should have realised, of course. These things don't happen by chance. I was a fool to think they might.",{"->":".^.^.^.19"},null]}],"nop","^ And then, once he had me compromised, he demanded I steal the part from the machine.\"","\n","ev",true,"/ev",{"VAR=":"revealedhooperasculprit","re":true},"^\"Which you did.\" Harris leans forward. \"And then what? You still have it? You've stashed it somewhere?\"","\n",["ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["^ ","\n","^\"Yes. I only had a moment. ",{"->":"reveal_location_of_component"},"\n",{"#f":5}],"c-1":["^ ",{"->":".^.^.^.^.^.^.^.passed_onto_hooper"},"\n",{"#f":5}],"c-2":["^ \t\t\t",{"->":".^.^.c-1"},"\n",{"#f":5}],"c-3":["^ \t\t","\n","^\"I can't remember.\"","\n","^He draws his gun and lays it lightly on the field table.","\n","^\"I'm sorry to threaten you, friend. But His Majesty needs that brain of yours, and that brain alone. There are plenty of other parts to you that our country could do better without. Now I'll ask you again. Did you hide the component?\"","\n",["ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["^ ",{"->":".^.^.^.^.c-0"},"\n",{"#f":5}],"c-1":["^ ","\n","^\"Very well then.\" I swallow nervously, to make it look more genuine. ",{"->":"i_met_a_young_man.passed_onto_hooper"},"\n",{"#f":5}],"c-2":["^ ",{"->":".^.^.c-1"},"\n",{"#f":5}],"c-3":["^ ",{"->":"i_met_a_young_man.i_dont_have_it"},"\n",{"#f":5}]}],{"#f":5}]}],{"#f":5}],"c-10":["^ \t",{"->":".^.^.c-8"},"\n",{"#f":5}],"c-11":["^ \t\t\t\t",{"->":".^.^.c-9"},"\n",{"#f":5}],"#f":5,"#n":"paused"}],{"#f":5}]}],{"i_dont_have_it":[["^\"I don't have it any more. I passed it through the fence to my contact straight after taking it, before it was discovered to be missing. It would have been idiocy to do differently. It's long gone, I'm afraid.\"","\n","^\"You fool, Manning,\" Harris curses, getting quickly to his feet. \"You utter fool. Do you suppose you will be any better off living under Hitler? It's men like you who will get us all killed. Men too feeble, too weak in their hearts to stand up and take a man's responsibility for the world. You're happier to stay a child all your life and play with your little childish toys.\"","\n","ev","str","^Answer back","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Say nothing","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["\n","^\"Really, Commander,\" I reply. \"It rather sounds like you want to spank me.\"","\n","^\"For God's sake,\" he declares with thick disgust, then swoops away out of the room.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^I say nothing. It's true, isn't it? I can't deny that I know there is a world out there, a complicated world of pain and suffering. And I can't deny that I don't think about it a moment longer than I have to. What use is thinking on a problem that cannot be solved? It is precisely our ability to avoid such endless spirals that makes us human and not machine.","\n","^\"God have mercy on your soul,\" Harris says finally, as he gets to his feet and heads for the door. \"I fear no—one else will.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":[{"->":"left_alone"},{"#f":5}]}],{"#f":1}],"passed_onto_hooper":[["ev",true,"/ev",{"VAR=":"hooper_mentioned","re":true},"^\"No. I passed it on to Hooper.\"","\n","^\"I see. And what did he do with it?\"","\n","ev","str","^Evade","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Tell the truth","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^\"I don't know.\"","\n","^\"You can do better than that. Remember, there's a hangman's noose waiting for traitors.\"","\n",["ev","str","^Theorise","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Shrug","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"Well, then,\" I answer, nervously. \"What would he do? Either get rid of it straight away — or if that wasn't possible, which it probably wouldn't be, since he'd have to arrange things with his contacts — so most likely, he'd hide it somewhere and wait, until you had the rope around my neck and he could be sure he was safe.\"","\n",{"->":"claim_hooper_took_component.harris_being_convinced"},{"#f":5}],"c-1":["^ ",{"->":"claim_hooper_took_component.its_your_problem"},"\n",{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n","^\"I don't think Hooper could have planned this in advance. So he'd need to get word to whoever he's working with, and that would take time. So I think he would have hidden it somewhere, and be waiting to make sure I soundly take the fall. That way, if anything goes wrong, he can arrange for the part to be conveniently re—found.\"","\n",{"->":"claim_hooper_took_component.harris_being_convinced"},{"#f":5}],"c-2":["\n","^\"I'm sure I saw him this evening, talking to someone by the fence on the woodland side of the compound. He's probably passed it on already. You'll have to ask him.\"","\n",{"->":"claim_hooper_took_component.harrumphs"},{"#f":5}]}],{"#f":1}],"#f":1}],"claim_hooper_took_component":[["^\"I saw Hooper take it.\"","\n","ev",true,"/ev",{"VAR=":"hooper_mentioned","re":true},"ev",{"VAR?":"losttemper"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Did you?\"","\n","^The worst of his rage is passing; he is now moving into a kind of contemptuous despair. I can imagine him wrapping up our interview soon, leaving the hut, locking the door, and dropping the key down the well in the yard.","\n","^And why wouldn't he? With my name tarnished they will not let me back to work on the Bombe — if there is the slightest smell of treachery about my name I would be lucky not be locked up for the remainder of the war.","\n",{"->":".^.^.^.11"},null]}],[{"->":".^.b"},{"b":["\n","^\"I see.\" He is starting to lose his patience. I have seen Harris angry a few times, with lackeys and secretaries. But never with us. With the 'brains' he has always been cautious, treating us like children.","\n","^And now I see that, like a father, he wants to smack us when we disobey him.","\n",{"->":".^.^.^.11"},null]}],"nop","\n","^\"Just get to the truth, man. Every minute matters.\"","\n","ev","str","^Persist with this","/str",{"VAR?":"admitblackmail"},"/ev",{"*":".^.c-0","flg":21},"ev","str","^Tell the truth","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Persist with this","/str",{"VAR?":"admitblackmail"},"!","/ev",{"*":".^.c-2","flg":21},{"c-0":["\n","^\"I know what you're thinking. If I've transgressed once then I must be guilty of everything else... But I'm not. We were close to cracking the 13th's intercept. We were getting correlations in the data. Then Hooper disappeared for a moment, and next minute the machine was down.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"Very well. I see there's no point in covering up. You know everything anyway.\"","\n","^Harris nods, and waits for me to continue.","\n",{"->":"i_met_a_young_man"},{"->":".^.^.g-0"},{"#f":5}],"c-2":["\n","^\"This is the truth.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I have become, somehow, an accustomed liar — the words roll easily off my tongue. Perhaps I am a traitor, I think, now that I dissemble as easily as one.","\n","^\"Go on,\" Harris says, giving me no indication of whether he believes my tale.","\n","ev","str","^Assert","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Imply","/str","/ev",{"*":".^.c-4","flg":20},{"c-3":["^ \"I saw him take it,\" I continue. \"Collins was outside having a cigarette. Peterson was at the table. But I was at the front of the machine. I saw Hooper go around the side. He leant down and pulled something free. I even challenged him. I said, 'What's that? Someone put a nail somewhere they shouldn't have?' He didn't reply.\"","\n","^Harris watches me for a long moment.","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-4":["^ \"At the moment the machine halted, Peterson was at the bench and Collins was outside having a smoke. I was checking the dip—switches. Hooper was the only one at the back of the Bombe. No—one else could have done it.\"","\n","^\"That's not quite the same as seeing him do it,\" Harris remarks.","\n",["ev","str","^Logical","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Persuasive","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Confident","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["\n","^\"When you have eliminated the impossible...\" I begin, but Harris cuts me off.","\n",{"->":".^.^.^.^.^.g-1"},{"#f":5}],"c-1":["^ ","\n","^\"You have to believe me.\"","\n","^\"We don't have to believe anyone,\" Harris returns. \"I will only be happy with the truth, and your story doesn't tie up. We know you've been leaving yourself open to pressure. We've been watching your activities for some time. But we thought you were endangering the reputation of this site; not risking the country herself. Perhaps I put too much trust in your intellectual pride.\"","\n","^He pauses for a moment, considering something. Then he continues:","\n","^\"It might have been Hooper. It might have been you. ",{"->":".^.^.^.^.^.we_wont_guess"},"\n",{"->":".^.^.^.^.^.g-1"},{"#f":5}],"c-2":["^ ","\n","^\"Ask the others,\" I reply, leaning back. \"They'll tell you. If they haven't already, that's only because they're protecting Hooper. Hoping he'll come to his senses and stop being an idiot. I hope he does too. And if you lock him up in a freezing hut like you've done me, I'm sure he will.\"","\n","^\"We have,\" Harris replies simply.","\n","^It's all I can do not to gape.","\n",{"->":".^.^.^.^.^.g-1.hoopers_hut_3"},{"->":".^.^.^.^.^.g-1"},{"#f":5}]}],{"#f":5}],"#f":5}],"g-1":["^\"We are left with two possibilities. You, or Hooper.\" The Commander pauses to smooth down his moustache. ","<>","\n",["^\"Hooper's in Hut 3 with the Captain, having a similar conversation.\"","\n",["ev",{"^->":"claim_hooper_took_component.0.g-1.hoopers_hut_3.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-5","flg":22},{"s":["^\"And the other men?",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.g-1.hoopers_hut_3.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-6","flg":22},{"s":["^\"Then you know I'm right.",{"->":"$r","var":true},null]}],{"c-5":["ev",{"^->":"claim_hooper_took_component.0.g-1.hoopers_hut_3.c-5.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"^ Do we have a hut each? Are there enough senior officers to go round?\"","\n","^\"Collins was outside when it happened, and Peterson can't get round the machine in that chair of his,\" Harris replies. \"That leaves you and Hooper.","\n",{"->":".^.^.^.^.we_wont_guess"},{"#f":5}],"c-6":["ev",{"^->":"claim_hooper_took_component.0.g-1.hoopers_hut_3.c-6.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"^ You knew all along. Why did you threaten me?\"","\n","^\"All we know is that we have a traitor, holding the fate of the country in his hands.","\n",{"->":".^.^.^.^.we_wont_guess"},{"#f":5}],"#f":5,"#n":"hoopers_hut_3"}],{"#f":5}],"we_wont_guess":["<>","^ We're not in the business of guessing here at Bletchley. We are military intelligence. We get answers.\" Harris points a finger. \"And if that component has left these grounds, then every minute is critical.\"","\n","ev","str","^Co-operate","/str","/ev",{"*":".^.c-7","flg":20},"ev","str","^Block","/str","/ev",{"*":".^.c-8","flg":20},{"c-7":["^ ","\n","^\"I'd be happy to help,\" I answer, leaning forwards. \"I'm sure there's something I could do.\"","\n","^\"Like what, exactly?\"","\n",[["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^\"Put me in with Hooper.\"",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["^\"Tell Hooper I've confessed.",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.^.^.^.^.putmein"},{"#f":5}],"c-1":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"^ Better yet. Let him see you marching me off in handcuffs. Then let him go, and see what he does. Ten to one he'll go straight to wherever he's hidden that component and his game will be up.\"","\n","^Harris nods slowly, chewing over the idea. It isn't a bad plan even — except, of course, Hooper has not hidden the component, and won't lead them anywhere. But that's a problem I might be able to solve once I'm out of this place; and once they're too busy dogging Hooper's steps from hut to hut.","\n","^\"Interesting,\" the Commander muses. \"But I'm not so sure he'd be that stupid. And if he's already passed the part on, the whole thing will only be a waste of time.\"","\n",[["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-0","flg":22},{"s":["^\"Trust me. He hasn't.",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["^\"You're right. Let me talk to him",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-2","flg":18},{"s":["^\"You're right.\" ",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"^ If I know that man, and I do, he'll be wanting to keep his options open as long as possible. If the component's gone then he's in it up to his neck. He'll take a week at least to make sure he's escaped suspicion. Then he'll pass it on.\"","\n","^\"And if we keep applying pressure to him, you think the component will eventually just turn up?\"","\n",[["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-0","flg":22},{"s":["^\"Yes.",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^\"Or be thrown into the river.\" ",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"^ Probably under my bunk.\"","\n","^Harris smiles wryly. \"We'll know that for a fake, then. We've looked there already.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"\n","^\"Hmm.\" Harris chews his moustache thoughtfully. \"Well, that would put us in a spot, seeing as how we'd never know for certain. We'd have to be ready to change our whole approach just in case the part had got through to the Germans.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["<>","^ I don't mind telling you, this is a disaster, this whole thing. What I want is to find that little bit of mechanical trickery. I don't care where. In your luncheon box or under Hooper's pillow. Just somewhere, and within the grounds of this place.\"","\n",["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.g-0.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-2","flg":22},{"s":["^\"Then let him he think he's off the hook.",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.g-0.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str","/ev",{"*":".^.^.c-3","flg":22},{"s":["^\"Then you'd better get searching",{"->":"$r","var":true},null]}],{"c-2":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.g-0.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"^ Make a show of me. And then you'll get your man.\"","\n","^Somehow, I think. But that's the part I need to work.","\n",{"->":"harris_takes_you_to_hooper"},{"#f":5}],"c-3":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.g-0.c-3.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"^,\" I reply, tiring of his complaining. A war is a war, you have to expect an enemy. ",{"->":".^.^.^.^.^.^.^.^.^.^.^.its_your_problem"},"\n",{"#f":5}],"#f":5}]}],{"#f":5}],"c-1":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"^, then. As a colleague. Maybe I can get something useful out of him.\"","\n",{"->":".^.^.^.^.^.^.^.^.putmein"},{"#f":5}],"c-2":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],{"->":".^.^.^.^.^.^.^.^.shake_head"},"\n",{"#f":5}]}],{"#f":5}]}],{"#f":5}],"c-8":["^ ",{"->":".^.^.^.^.its_your_problem"},"\n",{"#f":5}],"#f":5}]}],{"harris_being_convinced":[["^\"Makes sense,\" Harris agrees, cautiously. ","ev",{"VAR?":"evasive"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^I can see he's still not entirely convinced by my tale, as well he might not be — I've hardly been entirely straight with him.",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["^I can see he's still not certain whether he can trust me.",{"->":".^.^.^.8"},null]}],"nop","^ \"Which means the question is, what can we do to rat him out?\"","\n","ev","str","^Offer to help","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't offer to help","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"Maybe I can help with that.\"","\n","^\"Oh, yes? And how, exactly?\"","\n",[["ev",{"^->":"claim_hooper_took_component.harris_being_convinced.0.c-0.6.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^\"I'll talk to him.\" ",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.harris_being_convinced.0.c-0.6.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["^\"We'll fool him.",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"claim_hooper_took_component.harris_being_convinced.0.c-0.6.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"\n","^\"What?\"","\n","^\"Put me in with Hooper with him. Maybe I can get something useful out of him.\"","\n",{"->":".^.^.^.^.^.^.putmein"},{"#f":5}],"c-1":["ev",{"^->":"claim_hooper_took_component.harris_being_convinced.0.c-0.6.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"^ He's waiting to be sure that I've been strung up for this, so let's give him what he wants. If he sees me taken away, clapped in irons — he'll go straight to that component and set about getting rid of it.\"","\n",{"->":"harris_takes_you_to_hooper"},{"#f":5}]}],{"#f":5}],"c-1":["\n","^I lean back. ",{"->":".^.^.^.^.its_your_problem"},"\n",{"#f":5}]}],{"#f":1}],"putmein":[["^Harris shakes his head.","\n","^\"He despises you. I don't see why he'd give himself up to you.\"","\n","ev","str","^Insist","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Give in","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ \"Try me. Just me and him.\" ","\n",{"->":".^.^.^.^.go_in_alone"},{"#f":5}],"c-1":["^ \"You're right.\" ","\n",{"->":".^.^.^.^.shake_head"},{"#f":5}]}],{"#f":1}],"shake_head":["<>","^ I shake my head. \"You're right. I don't see how I can help you. So there's only one conclusion.\"","\n","^\"Oh, yes? And what's that?\"","\n",{"->":".^.^.its_your_problem"},{"#f":1}],"its_your_problem":["^\"It's your problem. Your security breach. So much for your careful vetting process.\"","\n","^I lean back in my chair and fold my arms so the way they shake will not be visible.","\n","^\"You'd better get on with solving it, instead of wasting your time in here with me.\"","\n",{"->":".^.^.harrumphs"},{"#f":1}],"harrumphs":[["^Harris harrumphs. He's thinking it all over.","\n","ev","str","^Wait","/str",{"CNT?":".^.^.^.putmein"},"/ev",{"*":".^.c-0","flg":21},"ev","str","^Wait","/str",{"CNT?":".^.^.^.putmein"},"!","/ev",{"*":".^.c-1","flg":21},{"c-0":["^ ","\n","^\"All right,\" he declares, gruffly. \"We'll try it. But if this doesn't work, I might just put the both of you in front of a firing squad and be done with these games. Worse things happen in time of war, you know.\"","\n","^\"Alone,\" I add.","\n",{"->":".^.^.^.^.go_in_alone"},{"#f":5}],"c-1":["^ ","\n","^\"No,\" Harris declares, finally. \"I think you're lying about Hooper. I think you're a clever, scheming young man — that's why we hired you — and you're looking for the only reasonable out this situation has to offer. But I'm not taking it. We know you were in the room with the machine, we know you're of a perverted persuasion, we know you have compromised yourself. There's nothing more to say here. Either you tell me what you've done with that component, or we will hang you and search just as hard. It's your choice.\"","\n",{"->":"harris_threatens_lynching"},{"#f":5}]}],{"#f":1}],"go_in_alone":[["^\"Alone?\"","\n","^\"Alone.\"","\n","^Harris considers it. I watch his eyes, flicking backwards and forwards over mine, like a ribbon—reader loading its program.","\n","ev","str","^Patient","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Impatient","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ \"Well?\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ \"For God's sake, man, what do you have to lose?\" ","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"We'll be outside the door,\" Harris replies, seriously. \"The first sign of any funny business and we'll have you both on the floor in minutes. You understand? The country needs your brain, but it's not too worried about your legs. Remember that.\"","\n","^Then he gets to his feet, and opens the door, and marches me out across the yard. The evening is drawing in and there's a chill in the air. My mind is racing. I have one opportunity here — a moment in which to put the fear of God into Hooper and make him do something foolish that places him in harm's way. But how to achieve it?","\n","^\"You ready?\" Harris demands.","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-4","flg":20},{"c-2":["\n","^\"Absolutely.\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-3":["\n","^\"No.\"","\n","^\"Too bad.\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-4":["^ ",{"->":".^.^.c-2"},"\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":[{"->":"inside_hoopers_hut"},{"#f":5}]}],{"#f":1}],"#f":1}],"harris_takes_you_to_hooper":[["^Harris gets to his feet. \"All right,\" he says. \"I should know better than to trust a clever man, but we'll give it a go.\"","\n","^Then, he smiles, with all his teeth, like a wolf.","\n","ev",{"CNT?":"claim_hooper_took_component.0.g-1.hoopers_hut_3"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Especially since this is a plan that involves keeping you in handcuffs. I don't see what I have to lose.\"","\n",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["\n","^\"Hooper's in Hut 3 being debriefed by the Captain. Let's see if we can't get his attention somehow.\"","\n",{"->":".^.^.^.9"},null]}],"nop","\n","^He raps on the door for the guard and gives the man a quick instruction. He returns a moment later with a cool pair of iron cuffs.","\n","^\"Put 'em up,\" Harris instructs, and I do so. The metal closes around my wrists like a trap. I stand and follow Harris willingly out through the door.","\n","^But whatever I'm doing with my body, my mind is scheming. Somehow, I'm thinking, I have to get away from these men long enough to get that component behind Hut 2 and put it somewhere Hooper will go. Or, otherwise, somehow get Hooper to go there himself...","\n","^Harris marches me over to Hut 3, and gestures for the guard to stand aside. Pushing me forward, he opens the door nice and wide.","\n","^\"Captain. Manning talked. If you'd step out for a moment?\"","\n","ev","str","^Play the part, head down","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Look inside the hut","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Call to Hooper","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["\n","^From where he's sitting, I know Hooper can see me, so I keep my head down and look guilty as sin. The bastard is probably smiling.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["\n","^I look in through the door and catch Hooper's expression. I had half expected him to be smiling be he isn't. He looks shocked, almost hurt. \"Iain,\" he murmurs. \"You couldn't...\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^I have a single moment to shout something to Hooper before the door closes.","\n","^\"I'll get you Hooper, you'll see!\" I cry. Then:","\n",[["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^\"Queen to rook two, checkmate!\"",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"^ I call, then laugh viciously, as if I am damning him straight to hell.","\n","ev",2,"/ev",{"VAR=":"hooperClueType","re":true},{"->":".^.^.only_catch"},{"#f":5}],"only_catch":["^I only catch Hooper's reaction for a moment — his eyebrow lifts in surprise and alarm. Good. If he thinks it is a threat then he just might be careless enough to go looking for what it might mean.","\n",["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.only_catch.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^\"Ask not for whom the bell tolls!\"",{"->":"$r","var":true},null]}],["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.only_catch.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-2","flg":18},{"s":["^\"Two words: messy, without one missing!\"",{"->":"$r","var":true},null]}],{"c-1":["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.only_catch.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"\n","^He stares back at me, as if were a madman and perhaps for a split second I see him shudder.","\n",{"->":".^.^.^.^.^.g-0"},{"#f":5}],"c-2":["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.only_catch.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"^ I cry, laughing. It isn't the best clue, hardly worthy of The Times, but it will have to do.","\n","ev",3,"/ev",{"VAR=":"hooperClueType","re":true},{"->":".^.^"},{"->":".^.^.^.^.^.g-0"},{"#f":5}],"#f":5}]}],{"#f":5}],"g-0":["^The Captain comes outside, pulling the door to. \"What's this?\" he asks. \"A confession? Just like that?\"","\n","^\"No,\" the Commander admits, in a low voice. \"I'm afraid not. Rather more a scheme. The idea is to let Hooper go and see what he does. If he believes we have Manning here in irons, he'll try to shift the component.\"","\n","^\"If he has it.\"","\n","^\"Indeed.\"","\n","^The Captain peers at me for a moment, like I was some kind of curious insect.","\n","^\"Sometimes, I think you people are magicians,\" he remarks. \"Other times you seem more like witches. Very well.\"","\n","^With that he opens the door to the Hut and goes back inside. The Commander uses the moment to hustle me roughly forward.","\n","ev",{"CNT?":".^.^.c-2"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^\"And what was all that shouting about?\" he hisses in my ear as we move towards the barracks. \"Are you trying to pull something? Or just make me look incompetent?\"","\n",{"->":".^.^.^.19"},null]}],[{"->":".^.b"},{"b":["\n","^\"This scheme of yours had better come off,\" he hisses in my ear. \"Otherwise the Captain is going to start having men tailing me to see where I go on Saturdays.\"","\n",{"->":".^.^.^.19"},null]}],"nop","\n","ev","str","^Reassure","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Dissuade","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-5","flg":20},"ev","str","^Say nothing","/str","/ev",{"*":".^.c-6","flg":20},{"c-3":["^ ","\n","ev",{"CNT?":".^.^.^.c-2"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"It will. Hooper's running scared,\" I reply, hoping I sound more confident than I feel.","\n",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["\n","^\"Just adding to the drama,\" I tell him, confidently. \"I'm sure you can understand that.\"","\n",{"->":".^.^.^.8"},null]}],"nop","\n","^\"I think we've had enough drama today already,\" Harris replies. \"Let's hope for a clean kill.\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-4":["^ ","\n","ev",{"CNT?":".^.^.^.c-2"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"The Captain thought it was a good scheme. You'll most likely get a promotion.\"","\n",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["\n","^\"I'm not trying to do anything except save my neck.\"","\n",{"->":".^.^.^.8"},null]}],"nop","\n","^\"Let's hope things work out,\" Harris agrees darkly.","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-5":["^ ","\n","^\"We're still in ear—shot if they let Hooper go. Best get us inside and then we can talk, if we must.\"","\n","^\"I've had enough of your voice for one day,\" Harris replies grimly. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-6":["\n","^I let him have his rant. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^He hustles me up the steps of the barracks, keeping me firmly gripped as if I had any chance of giving him, a trained military man, the slip. It's all I can do not to fall into the room.","\n",{"->":"slam_door_shut_and_gone"},{"#f":5}]}],{"#f":1}],"inside_hoopers_hut":[[["^Harris opens the door and pushes me inside. \"Captain,\" he calls. \"Could I have a moment?\"","\n","^The Captain, looking puzzled, steps out. The door is closed. Hooper stares at me, open—mouthed, about to say something. I probably have less than a minute before the Captain storms back in and declares this plan to be bunkum.","\n","ev","str","^Threaten","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Bargain","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Plead","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["\n","^\"Listen to me, Hooper. We were the only men in that hut today, so we know what happened. But I want you to know this. I put the component inside a breeze—block in the foundations of Hut 2, wrapped in one of your shirts. They're going to find it eventually, and that's going to be what tips the balance. And there's nothing you can do to stop any of that from happening.\"","\n","ev",1,"/ev",{"VAR=":"hooperClueType","re":true},"^His eyes bulge with terror. \"What did I do, to you? What did I ever do?\"","\n",["ev","str","^Tell the truth","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^\"You treated me like vermin. Like something abhorrent.\"","\n","^\"You are something abhorrent.\"","\n","^\"I wasn't. Not when I came here. And I won't be, once you're gone.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"Nothing,\" I reply. \"You're just the other man in the room. One of us has to get the blame.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^\"It doesn't matter. Just remember what I said. I've beaten you, Hooper. Remember that.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I get to my feet and open the door of the Hut. The Captain storms back inside and I'm quickly thrown out. ",{"->":".^.^.^.^.^.^.hustled_out"},"\n",{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n","^\"Hooper, I'll make a deal with you. We both know what happened in that hut this afternoon. I know because I did it, and you know because you know you didn't. But once this is done I'll be rich, and I'll split that with you. I'll let you have the results, too. Your name on the discovery of the Bombe. And it won't hurt the war effort — you know as well as me that the component on its own is worthless, it's the wiring of the Bombe, the usage, that's what's valuable. So how about it?\"","\n","^Hooper looks back at me, appalled. \"You're asking me to commit treason?\"","\n",["ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["\n","^\"Yes, perhaps. But also to ensure your name goes down in the annals of mathematics. ",{"->":".^.^.^.^.^.^.back_of_hut_2"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"No. It's not treason. It's a trade, plain and simple.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^\"I'm suggesting you save your own skin. I've wrapped that component in one of your shirts, Hooper. They'll be searching this place top to bottom. They'll find it eventually, and when they do, that's the thing that will swing it against you. So take my advice now. Hut 2.\"","\n","ev",1,"/ev",{"VAR=":"hooperClueType","re":true},{"->":".^.^.g-0"},{"#f":5}],"c-3":["^ ",{"->":".^.^.c-2"},"\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":[{"->":".^.^.^.^.^.^.no_chance"},{"#f":5}]}],{"#f":5}],"c-2":["^ ","\n","^\"Please, Hooper. You don't understand. They have information on me. I don't need to tell you what I've done, you know. Have a soul. And the component — it's nothing. It's not the secret of the Bombe. It's just a part. The German's think it's a weapon — a missile component. Let them have it. Please, man. Just help me.\"","\n","^\"Help you?\" Hooper stares. \"Help you? You're a traitor. A snake in the grass. And you're queer.\"","\n",["ev","str","^Deny","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Accept","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^\"I'm no traitor. You know I'm not. How much work have I done here against the Germans? I've given my all. And you know as well as I do, if the Reich were to invade, I would be a dead man. Please, Hooper. I'm not doing any of this lightly.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["\n","^\"I am what I am,\" I reply. \"I'm the way I was made. But they'll hang me unless you help, Hooper. Don't let them hang me.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^\"That's not important now. What matters is what you do, this evening.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"Assuming I wanted to help you,\" he replies, carefully. \"Which I don't. What would I do?\"","\n","^\"Nothing. Almost nothing.","\n",{"->":".^.^.^.^.^.^.back_of_hut_2"},{"#f":5}]}],{"#f":5}],"#f":5,"#n":"g-0"}],null],{"back_of_hut_2":["<>","^ All you have to do is go to the back of Hut 2. There's a breeze—block with a cavity. That's where I've put it. I'll be locked up overnight. But you can pick it up and pass it to my contact. He'll be at the south fence around two AM.\"","\n","ev",1,"/ev",{"VAR=":"hooperClueType","re":true},{"->":".^.^.no_chance"},{"#f":1}],"no_chance":["^\"If you think I'll do that then you're crazy,\" Hooper replies.","\n","^At that moment the door flies open and the Captain comes storming back inside.","\n",{"->":".^.^.hustled_out"},{"#f":1}],"hustled_out":["^Harris hustles me over to the barracks. \"I hope that's the end of it,\" he mutters.","\n","^\"Just be sure to let him out,\" I reply. \"And then see where he goes.\"","\n",{"->":"slam_door_shut_and_gone"},{"#f":1}],"#f":1}],"slam_door_shut_and_gone":[["^Then they slam the door shut, and it locks.","\n","ev",{"VAR?":"hooperClueType"},0,"==","/ev",[{"->":".^.b","c":true},{"b":["\n","<>","^ How am I supposed to manage anything from in here?","\n","ev","str","^Try the door","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Try the windows","/str","/ev",{"*":".^.c-1","flg":20},{"->":".^.^.^.9"},{"c-0":["^ ",{"->":".^.^.^.^.^.try_the_door"},"\n",{"#f":5}],"c-1":["^ ",{"->":".^.^.^.^.^.try_the_windows"},"\n",{"#f":5}]}]}],[{"->":".^.b"},{"b":["\n","^I can only hope that Hooper bites. If he thinks I'm bitter enough to have framed him, and arrogant enough to have taunted him with ","ev",{"VAR?":"hooperClueType"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^a clue to",{"->":".^.^.^.8"},null]}],"nop","^ where the damning evidence is hidden...","\n","^If he hates me enough, and is paranoid enough, then he might ","ev",{"VAR?":"hooperClueType"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^unravel my little riddle and",{"->":".^.^.^.18"},null]}],"nop","^ go searching around Hut 2.","\n",{"->":".^.^.^.9"},null]}],"nop","\n","ev","str","^Wait","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["^ \t",{"->":"night_falls"},"\n",{"#f":5}]}],{"try_the_door":["^I try the door. It's locked, of course.","\n",{"->":".^.^.from_outside_heard"},{"#f":1}],"from_outside_heard":[["^From outside, I hear a voice. Hooper's. He's haranguing someone.","\n",["ev","str","^Listen at the keyhole","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Try the window","/str",{"CNT?":".^.^.^.^.try_the_windows"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^Try the door","/str",{"CNT?":".^.^.^.^.try_the_door"},"!",{"CNT?":".^.c-0"},"&&","/ev",{"*":".^.c-2","flg":21},"ev","str","^Smash the window","/str",{"CNT?":".^.^.^.^.try_the_windows"},"/ev",{"*":".^.c-3","flg":21},"ev","str","^Wait","/str",{"CNT?":".^.^.^.^.try_the_door"},{"CNT?":".^.^.^.^.try_the_windows"},"&&","/ev",{"*":".^.c-4","flg":21},{"c-0":["^ ","\n","^I put my ear down to the keyhole, but there's nothing now. Probably still a guard outside, of course, but they're keeping mum.","\n",{"->":".^.^"},{"#f":5}],"c-1":["^ ",{"->":".^.^.^.^.^.try_the_windows"},"\n",{"#f":5}],"c-2":["^ ",{"->":".^.^.^.^.^.try_the_door"},"\n",{"#f":5}],"c-3":["^ ",{"->":".^.^.^.^.^.try_to_smash_the_window"},"\n",{"#f":5}],"c-4":["^ ","\n","^It's useless. There's nothing I can do but hope. I sit down on one corner of the bunk to wait.","\n",{"->":"night_falls"},{"#f":5}],"#f":5,"#n":"opts"}],null],{"#f":1}],"try_the_windows":["^I go over to the window and try to jimmy it open. Not much luck, but in my struggling I notice this window only backs on the thin little brook that runs down the back of the compound. Which means, if I smashed it, I might get away with no—one seeing.","\n",{"->":".^.^.from_outside_heard"},{"#f":1}],"try_to_smash_the_window":[["^The window is my only way out of here. I just need a way to smash it.","\n","ev","str","^Punch it","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Find something","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Use something you've got","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^I suppose my fist would do a good enough job. But I'd cut myself to ribbons, most likely. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","ev",2,"/ev",{"VAR=":"smashingWindowItem","re":true},"^I cast around the small room. There's a bucket in one corner for emergencies — I suppose I could use that. I pick it up but it's not very easy to heft. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^I pat down my pockets but all I'm carrying is the intercept, which is no good at all.","\n",["ev","str","^Something you're wearing?","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Look around","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^Ah, but of course! I slip off one shoe and heft it by the toe. The heel will make a decent enough hammer, if I give it enough wallop.","\n","ev",1,"/ev",{"VAR=":"smashingWindowItem","re":true},"^But I'll cut my hand to ribbons doing it. ","<>","\n",{"->":".^.^.^.^.g-0"},{"#f":5}],"c-1":["^ ",{"->":".^.^.^.^.c-1"},"\n",{"->":".^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"g-0":["^And the noise would be terrible. There must be a way of making this easier. I'm supposed to be a thief now. What would a burglar do?","\n","ev","str","^Work slowly","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Find something to help","/str","/ev",{"*":".^.c-4","flg":20},{"c-3":["^ ","\n","^Work carefully? It's difficult to work carefully when all one's has is ","ev",{"VAR?":"smashingWindowItem"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["^a bucket. It's rather like the sledgehammer for the proverbial nut",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["ev",{"VAR?":"smashingWindowItem"},1,"==","/ev",[{"->":".^.b","c":true},{"b":["^a shoe",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^nothing but brute force",{"->":".^.^.^.7"},null]}],"nop",{"->":".^.^.^.10"},null]}],"nop","^.","\n",["ev","str","^Just do it","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Look around for something","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ",{"->":".^.^.^.^.^.^.^.time_to_move_now"},"\n",{"->":".^.^.^.^.^.g-1"},{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.^.^.^.g-1"},{"#f":5}]}],{"#f":5}],"c-4":["^ ","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":[{"->":".^.^.^.^.find_something_to_smash_window"},{"#f":5}]}],{"#f":1}],"time_to_move_now":[["^Enough of this. There isn't any time to lose. Right now they'll be following Hooper as he goes to bed, and goes to sleep; and then that's it. The minute he closes his eyelids and drifts off that's the moment that this trap swings shut on me.","\n","^So I punch out the glass with my ","ev",{"VAR?":"smashingWindowItem"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["^bucket",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["ev",{"VAR?":"smashingWindowItem"},1,"==","/ev",[{"->":".^.b","c":true},{"b":["^shoe",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^fist",{"->":".^.^.^.7"},null]}],"nop",{"->":".^.^.^.10"},null]}],"nop","^ and it shatters with a terrific noise. Then I stop, and wait, to see if anyone will come in through the door.","\n","^Nothing.","\n","ev","str","^Wait a little longer","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Clear the frame of shards","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^I pause for a moment longer. It doesn't do to be too careless...","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["\n","^With my jacket wrapped round my arm, I sweep out the remaining shards of glass. It's not a big window, but I'm not a big man. If I was Harris, I'd be stuffed, but as it is...","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Then the door locks turns. The door opens. Then Jeremy — one of the guards, rather — sticks his head through the door. \"I thought I heard...\"","\n","^He stops. Looks for a moment. ","ev",{"VAR?":"smashingWindowItem"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["^Sees the bucket in my hand.",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^Sees the broken window.",{"->":".^.^.^.10"},null]}],"nop","^ Then without a moment's further thought he blows his shrill whistles and hustles into the hut, grabbing me roughly by my arms.","\n","ev",{"CNT?":".^.^.c-0"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^I'll never know if I hadn't have waited that extra moment — maybe I still could have got away. But, how far?","\n",{"->":".^.^.^.17"},null]}],"nop","\n","^I'm hustled into one of the huts. Nowhere to sleep, but they're not interested in my comfort any longer. Harris comes in with the Captain.","\n","^\"So,\" Harris remarks. \"Looks like your little trap worked. Only it worked to show you out for what you are.\"","\n","ev","str","^Tell the truth","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-4","flg":20},{"c-2":["^ ","\n","ev",{"CNT?":"i_met_a_young_man"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Please, Harris. You can't understand the pressure they put me under. You can't understand what it's like, to be in love but be able to do nothing about it...\"","\n",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["\n","^\"Harris. They were blackmailing me. They knew about... certain indiscretions. You can understand, can't you, Harris? I was in an impossible bind...\"","\n",{"->":".^.^.^.7"},null]}],"nop","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-3":["\n","^\"I had to get out, Harris. I had to provoke Hooper into doing something that would incriminate himself fully. He's too clever, you see...\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-4":["^ ","\n","^\"This proves nothing,\" I reply stubbornly. \"You still don't have the component and without it, I don't see what you can hope to prove.\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^\"Be quiet, man. We know all about your and your sordid affairs.\" The Captain curls his lip. \"Don't you know there's a war on? Do you know the kind of place they would have sent you if it haven't had been for that brain of yours? Don't you think you owe it to your country to use it a little more?\"","\n","^Do I, I wonder? Do I owe this country anything, this country that has spurned who and what am I since the day I became a man?","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-5","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-6","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-7","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-8","flg":20},{"c-5":["^ ","\n","^My anger deflates like a collapsing equation, all arguments cancelling each other out. The world, of course, owes me nothing; and I owe it everything.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-6":["^ ","\n","^Of course not. I am alone; that is what they wanted me to be, because of who and what I love. So I have no nation, no country.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-7":["^ \t",{"->":".^.^.c-6"},"\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-8":["^ \t","\n","^But what is a country, after all? A country is not a concept, not an ideal. Every country falls, its borders shift and move, its language disappears to be replaced by another. Neither the Reich nor the British Empire will survive forever, so what use is my loyalty to either? ","\n","^I may as well, therefore, look after myself. Something I have attempted, but failed miserably, to do.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"#f":5}],"g-2":["^\"I'm afraid we have only one option, Manning,\" Harris says. \"Please, man. Tell us where the component is.\"","\n","ev",true,"/ev",{"VAR=":"notraitor","re":true},"ev",false,"/ev",{"VAR=":"losttemper","re":true},"ev","str","^Tell them","/str","/ev",{"*":".^.c-9","flg":20},"ev","str","^Say nothing","/str","/ev",{"*":".^.c-10","flg":20},{"c-9":["\n","ev",false,"/ev",{"VAR=":"revealedhooperasculprit","re":true},"^\"All right.\" I am beaten, after all. \"","<>",{"->":"reveal_location_of_component"},"\n",{"#f":5}],"c-10":["^ ",{"->":"my_lips_are_sealed"},"\n",{"#f":5}],"#f":5}]}],{"#f":1}],"find_something_to_smash_window":[["^Let me see. There's the bunk, ","ev",{"VAR?":"smashingWindowItem"},"!",2,"==","/ev",[{"->":".^.b","c":true},{"b":["^a bucket,",{"->":".^.^.^.8"},null]}],"nop","^ nothing else. I have my jacket but nothing in the pockets — no handkerchief, for instance.","\n",["ev","str","^The bunk","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^The jacket","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^The bucket","/str",{"VAR?":"smashingWindowItem"},"!",2,"==","/ev",{"*":".^.c-2","flg":21},{"c-0":["^ \t","\n","^The bunk has a solid metal frame, a blanket, a pillow, nothing more.","\n",[["ev","str","^The frame","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^The blanket","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^The pillow","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Something else","/str",{"CNT?":".^"},1,">","/ev",{"*":".^.c-3","flg":21},{"c-0":["\n","^The frame is heavy and solid. I couldn't lift it or shift it without help from another man. And it wouldn't do me any good here anyway. I can reach the window perfectly well.","\n",{"->":".^.^"},{"#f":5}],"c-1":["^ ","\n","^The blanket. Perfect. I scoop it up off the bed and hold it in place over the window. ",{"->":"smash_the_window"},"\n",{"#f":5}],"c-2":["^ ","\n","^The pillow is fat and fluffy. I could put it over the window and it would muffle the sound of breaking glass, certainly; but I wouldn't be able to break any glass through it either.","\n",{"->":".^.^"},{"#f":5}],"c-3":["^ ",{"->":".^.^.^.^.^"},"\n",{"#f":5}],"#f":5,"#n":"bunk_opts"}],null],{"#f":5}],"c-1":["^ ","\n","^I slip off my jacket and hold it with one hand over the glass. ",{"->":"smash_the_window"},"\n",{"#f":5}],"c-2":["^ ","\n","^The bucket? Hardly. The bucket might do some good if I wanted to sweep up the glass afterwards, but it won't help me smash the glass quietly.","\n",{"->":".^.^"},{"#f":5}],"#f":5,"#n":"opts"}],null],{"#f":1}],"#f":1}],"smash_the_window":[["^Then I heft ","ev",{"VAR?":"smashingWindowItem"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["^up the bucket — this really is quite a fiddly thing to be doing in cuffs — ",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["ev",{"VAR?":"smashingWindowItem"},1,"==","/ev",[{"->":".^.b","c":true},{"b":["^ my shoe by its toe, ",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^back my arm, ",{"->":".^.^.^.7"},null]}],"nop",{"->":".^.^.^.8"},null]}],"nop","^ and take a strong swing, trying to imagine it's Harris' face on the other side.","\n","ev",true,"/ev",{"VAR=":"smashedglass","re":true},"ev",0,"/ev",{"VAR=":"smashingWindowItem","re":true},"ev","str","^Smash!","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^The sound of the impact is muffled. With my arm still covered, I sweep out the remaining glass in the frame.","\n",["^I'm ready to escape. The only trouble is — when they look in on me in the morning, there will be no question what has happened. It won't help me one jot with shifting suspicion off my back.","\n","ev","str","^Wait","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Slip out","/str","/ev",{"*":".^.c-2","flg":20},{"c-1":["\n","^So perhaps I should wait it out, after all. Who knows? I might have a better opportunity later.","\n",{"->":"night_passes"},{"->":".^.^.^.^.g-2"},{"#f":5}],"c-2":["^ ","\n","^Moving quickly and quietly, I hoist myself up onto the window—frame and worm my way outside into the freezing night air. Then I am away, slipping down the paths between the Huts, sticking to the shadows, on my way to Hut 2.","\n",{"->":".^.^.^.^.g-2"},{"#f":5}],"#f":5,"#n":"g-1"}],{"#f":5}],"g-2":["ev","str","^Go the shortest way","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Take a longer route","/str","/ev",{"*":".^.c-4","flg":20},{"c-3":["^ ","\n","^There's no time to lose. Throwing caution to the wind I make my way quickly to Hut 2, and around the back. I don't think I've been seen but if I have it is too late. My actions are suspicious enough for the noose. I have no choice but to follow through.","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-4":["\n","^In case I'm being followed, I divert around the perimeter of the compound. It's a much longer path, and it takes me across some terrain that's difficult to negotiate in the dark — muddy, and thick with thistles and nestles.","\n","ev",true,"/ev",{"VAR=":"muddyshoes","re":true},"^Still, I can be confident no—one is behind me. I crouch down behind the rear wall of Hut 2. ","<>","\n",{"->":".^.^.^.g-3"},{"#f":5}],"#f":5}],"g-3":["^The component is still there, wrapped in a tea—towel and shoved into a cavity in a breeze—block at the base of the Hut wall.","\n","ev","str","^Take it","/str","/ev",{"*":".^.c-5","flg":20},"ev","str","^Leave it","/str","/ev",{"*":".^.c-6","flg":20},{"c-5":["^ ","\n","^Quickly, I pull it free, and slip it into the pocket of my jacket.","\n","ev",true,"/ev",{"VAR=":"gotcomponent","re":true},{"->":".^.^.^.g-4"},{"#f":5}],"c-6":["^ ","\n","^Still there means no—one has found it, which means it is probably well—hidden. And short of skipping the compound now, I can afford to leave it hidden there a while longer. So I leave it in place.","\n",{"->":".^.^.^.g-4"},{"#f":5}],"#f":5}],"g-4":["^Where now?","\n","ev","str","^Back to the barracks","/str","/ev",{"*":".^.c-7","flg":20},"ev","str","^Go to Hooper's dorm","/str",{"VAR?":"gotcomponent"},"/ev",{"*":".^.c-8","flg":21},"ev","str","^Escape the compound","/str","/ev",{"*":".^.c-9","flg":20},{"c-7":["^ ",{"->":"return_to_room_after_excursion"},"\n",{"#f":5}],"c-8":["^ ",{"->":"go_to_hoopers_dorm"},"\n",{"#f":5}],"c-9":["^ ","\n","^Enough of this place. Time for me to get moving. I can get to the train station on foot, catch the postal train to Scotland and be somewhere else before anyone realises that I'm gone.","\n","^Of course, then they'll be looking for me in earnest. ","ev",{"VAR?":"framedhooper"},"!","/ev",[{"->":".^.b","c":true},{"b":["^As a confirmed traitor.",{"->":".^.^.^.11"},null]}],[{"->":".^.b"},{"b":["^Perhaps not as a traitor — they might take the idea that Hooper was involved with the theft — but certainly as a valuable mind, one containing valuable secrets and all too easily threatened. They will think I am running away because of my indiscretions. I suppose, in fairness, that I am.",{"->":".^.^.^.11"},null]}],"nop","\n",["ev","str","^Go","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't go","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ \t\t\t",{"->":"live_on_the_run"},"\n",{"#f":5}],"c-1":["^ ","\n","^It's no good. That's only half a solution. I couldn't be happy with that.","\n",["ev","str","^Back to the barracks","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^To Hooper's dorm","/str",{"VAR?":"gotcomponent"},{"CNT?":"go_to_hoopers_dorm"},"!","&&","/ev",{"*":".^.c-1","flg":21},{"c-0":["^ \t\t\t",{"->":"return_to_room_after_excursion"},"\n",{"#f":5}],"c-1":["^ ",{"->":"go_to_hoopers_dorm"},"\n",{"#f":5}]}],{"#f":5}]}],{"#f":5}],"#f":5}]}],{"#f":1}],"go_to_hoopers_dorm":[["^I creep around the outside of the huts towards Hooper's dorm. Time to wrap up this little game once and for all. A few guards patrol the area at night but not many — after all, very few know this place even exists.","\n","^Our quarters are arranged away from the main house; where we sleep is of less importance than where we work. We each have our own hut, through some are less permanent than others. Hooper's is a military issue tent: quite a large canopy, with two rooms inside and a short porch area where he insists people leave their shoes. It's all zipped up for the night and no light shines from inside.","\n","^I hang back for a moment. If Harris is keeping to the terms of our deal then someone will be watching this place. But I can see no—one.","\n","ev","str","^Open the outer zip","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Look for another opening","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Hide the component somewhere","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^I creep forward to the tent, intent on lifting the zip to the front porch area just a little — enough to slip the component inside, and without the risk of the noise waking Hooper from his snoring.","\n","^The work is careful, and more than little fiddly — Hooper has tied the zips down on the inside, the fastidious little bastard! — but after a little work I manage to make a hole large enough for my hand.","\n",["ev","str","^Slip in the component","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No, some other way","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ \t\t","\n","^I slide the component into the tent, work the zip closed, and move quickly away into the shadows. It takes a few minutes for my breath to slow, and my heart to stop hammering, but I see no other movement. If anyone is watching Hooper's tent, they are asleep at their posts.","\n","ev",true,"/ev",{"VAR=":"putcomponentintent","re":true},"ev",false,"/ev",{"VAR=":"gotcomponent","re":true},{"->":"return_to_room_after_excursion"},{"#f":5}],"c-1":["^ \t\t\t","\n","^Then pause. This is too transparent. Too blatant. If I leave it here, like this, Hooper will never be seen to go looking for it: he will stumble over it in plain sight, and the men watching will wonder why it was not there when he went to bed.","\n","^No, I must try something else — or nothing at all.","\n",["ev","str","^On top of the tent","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Throw the component into the long grass","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Give up","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ",{"->":".^.^.^.^.^.^.^.put_component_on_tent"},"\n",{"#f":5}],"c-1":["^ ","\n","^From inspiration — or desperation, I am not certain — a simple approach occurs to me. ",{"->":".^.^.^.^.^.^.^.toss_component_into_bushes"},"\n",{"#f":5}],"c-2":["^ ","\n","^There is nothing to be gained here. I have the component now; maybe it will be of some value tomorrow.","\n",["ev","str","^Return to my barrack","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Escape the compound","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ",{"->":"return_to_room_after_excursion"},"\n",{"#f":5}],"c-1":["^ ",{"->":"live_on_the_run"},"\n",{"#f":5}]}],{"#f":5}]}],{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n","^Making a wide circuit I creep around the tent. It has plenty of other flaps and openings, tied down with Gordian complexity. But nothing afford itself to slipping the component inside.","\n",["ev","str","^Try the porch zip","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Try on top of the tent","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Give up","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ \t\t\t",{"->":".^.^.^.^.c-0"},"\n",{"#f":5}],"c-1":["^ \t\t",{"->":".^.^.^.^.^.put_component_on_tent"},"\n",{"#f":5}],"c-2":["^ \t\t\t\t\t\t","\n","^It's no good. Nothing I can do will be any less than obvious — something appearing where something was not there before. The men watching Hooper will know it is a deception and Hooper's protestations will be taken at face value.","\n","^If I can't find a way for Hooper to pick the component up, as if from a hiding place of his own devising, and be caught doing it, then I have no plan at all.","\n",["ev","str","^Return to my barrack","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Escape the compound","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Toss the component into the bushes","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ",{"->":"return_to_room_after_excursion"},"\n",{"#f":5}],"c-1":["^ ",{"->":"live_on_the_run"},"\n",{"#f":5}],"c-2":["^ ",{"->":".^.^.^.^.^.^.^.toss_component_into_bushes"},"\n",{"#f":5}]}],{"#f":5}]}],{"#f":5}],"c-2":["^ ","\n","^If I leave the component here somewhere it should be somewhere I can rely on Hooper finding it, but no—one before Hooper. In particular.","\n",["ev","str","^Behind the tent","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Inside the porch section","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^On top of the canvas","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^\t\t\t \t",{"->":".^.^.^.^.c-1"},"\n",{"#f":5}],"c-1":["^ \t\t",{"->":".^.^.^.^.c-0"},"\n",{"#f":5}],"c-2":["^ \t\t\t",{"->":".^.^.^.^.^.put_component_on_tent"},"\n",{"#f":5}]}],{"#f":5}]}],{"put_component_on_tent":["^A neat idea strikes me. If I could place it on top of the canvas, somewhere in the middle where it would bow the cloth inwards, then it would be invisible to anyone passing by. But to Hooper, it would be above him: a shadow staring him in the face as he awoke. What could be more natural than getting up, coming out, and looking to see what had fallen on him during the night?","\n","^It's the work of a moment. I was once an excellent bowler for the second XI back at school. This time I throw underarm, of course, but I still land the vital missing component exactly where I want it to go.","\n","ev",true,"/ev",{"VAR=":"framedhooper","re":true},"ev",false,"/ev",{"VAR=":"gotcomponent","re":true},"^For a second I hold my breath, but nothing and no—one stirs. ",{"->":"return_to_room_after_excursion"},"\n",{"#f":1}],"toss_component_into_bushes":["^I toss the component away into the bushes behind Hooper's tent and return to my barrack, wishing myself a long sleep followed by a morning, free of this business.","\n","ev",false,"/ev",{"VAR=":"gotcomponent","re":true},"ev",true,"/ev",{"VAR=":"throwncomponentaway","re":true},{"->":"return_to_room_after_excursion"},{"#f":1}],"#f":1}],"live_on_the_run":["^Better to live on the run than die on the spit. Creeping around the edge of the compound","ev",{"VAR?":"gotcomponent"},"/ev",[{"->":".^.b","c":true},{"b":["^, the Bombe component heavy in my pocket",{"->":".^.^.^.5"},null]}],"nop","^, I make my way to the front gate. As always, it's manned by two guards, but I slip past their box by crawling on my belly.","\n","^And then I'm on the road. Walking, not running. Silent. Free.","\n","^For the moment, at least.","\n","end",{"#f":1}],"return_to_room_after_excursion":[["ev",{"VAR?":"gotcomponent"},"/ev",[{"->":".^.b","c":true},{"b":["^The weight of the Bombe component safely in my jacket",{"->":".^.^.^.5"},null]}],[{"->":".^.b"},{"b":["^Satisfied",{"->":".^.^.^.5"},null]}],"nop","^, I return the short way up the paths between the huts to the barrack block and the broken window.","\n","^It's a little harder getting back through — the window is higher off the ground than the floor inside — but after a decent bit of jumping and hauling I manage to get my elbows up, and then one leg, and finally I collapse inside, quite winded and out breath.","\n","ev","str","^Wait","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["^ \t",{"->":"night_passes"},"\n",{"#f":5}]}],{"#f":1}],"night_passes":[["^The rest of the night passes slowly. I sleep a little, dozing mostly. Then I'm woken by the rooster in the yard. The door opens, and Harris comes in. He takes one look at the broken window and frowns with puzzlement.","\n","ev",{"VAR?":"putcomponentintent"},"/ev",[{"->":".^.b","c":true},{"b":["^ ",{"->":".^.^.^.^.put_component_inside_tent"},{"->":".^.^.^.6"},null]}],"nop","\n","^\"What happened there?\"","\n","ev","str","^Confess","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Deny","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Show him the component","/str",{"VAR?":"gotcomponent"},"/ev",{"*":".^.c-2","flg":21},{"c-0":["^ ","\n","^\"I broke it,\" I reply. There doesn't seem any use in trying to lie. \"I thought I could escape. But I couldn't get myself through.\"","\n","^The Commander laughs. ",{"->":".^.^.^.glad_youre_here"},"\n",{"#f":5}],"c-1":["^ ","\n","^\"I'm not sure. I was asleep: I woke up when someone broke the window. I looked out to see who it was, but they were already gone.\"","\n","^Harris looks at me with puzzlement. \"Someone came by to break the window, and then ran off? That's absurd. That's utterly absurd. Admit it, Manning. You tried to escape and you couldn't get through.\"","\n",["ev","str","^Admit it","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Deny it","/str",{"VAR?":"framedhooper"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^Deny it","/str",{"VAR?":"framedhooper"},"/ev",{"*":".^.c-2","flg":21},{"c-0":["\n","^\"All right. ","ev",{"VAR?":"forceful"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^Damn you.",{"->":".^.^.^.8"},null]}],"nop","^ That's exactly it.\"","\n",{"->":".^.^.^.^.^.glad_youre_here"},{"#f":5}],"c-1":["\n","^\"If I wanted to escape, I would have made damn sure that I could,\" I tell him sternly.","\n",{"->":"harris_certain_is_you"},{"#f":5}],"c-2":["^ ","\n","^\"I tell you, someone broke it. Someone wanted to threaten me, I think.\"","\n","^Harris shakes his head. \"Well, we can look into that matter later. For now, you probably want to hear the more pressing news. ",{"->":".^.^.^.^.^.found_missing_component"},"\n",{"#f":5}]}],{"#f":5}],"c-2":["^ ",{"->":".^.^.^.someone_threw_component"},"\n",{"#f":5}]}],{"put_component_inside_tent":[["^He takes one look around, and sighs, a deep, wistful sigh.","\n","^\"Things just get worse and worse for you, Manning,\" he remarks. \"You are your own worst enemy.\"","\n","ev","str","^Agree","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Disagree","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^\"I've thought so before.\" ","ev",{"VAR?":"admitblackmail"},"/ev",[{"->":".^.b","c":true},{"b":["^Certainly in the matter of getting blackmailed.",{"->":".^.^.^.7"},null]}],"nop","\n","^\"Let me tell you what happened this morning. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["\n","^\"Right now, I think you take that role, Harris,\" I reply coolly.","\n",[["^\"Very droll,\" he replies. \"Let me tell you what happened this morning. It will take the smile off your face. ","<>","\n",{"->":".^.^.^.^.g-0"},{"#f":5,"#n":"droll"}],null],{"#f":5}],"c-2":["^ ","\n","^\"I'm looking forward to having a wash and a change of clothes; which should make me a little less evil to be around.\"","\n",{"->":".^.^.c-1.3.droll"},{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Our men watching Hooper's tent saw Hooper wake up, get dressed, clamber out of his tent and then step on something in at the entrance of his tent.\"","\n","ev",true,"/ev",{"VAR=":"piecereturned","re":true},"ev","str","^Be interested","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Be dismissive","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^Say nothing","/str","/ev",{"*":".^.c-5","flg":20},{"c-3":["^ ","\n","^\"You mean he didn't even hide it? He put it in his shoe?\"","\n",[["^\"No,\" Harris replies. \"That isn't really what I mean. ","<>","\n",{"->":".^.^.^.^.^.g-1"},{"#f":5,"#n":"not_that"}],null],{"#f":5}],"c-4":["\n","^\"So he's an idiot, and he hid it in his shoe.\"","\n",{"->":".^.^.c-3.4.not_that"},{"->":".^.^.^.g-1"},{"#f":5}],"c-5":["^ ","\n","^I say quiet, listening, not sure how this will go.","\n","^\"In case I'm not making myself clear,\" Harris continues, \"","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^I mean, he managed to find it, by accident, somewhere where it wasn't the night before. And at the same time, you're sitting here with your window broken. So, I rather think you've played your last hand and lost. It's utterly implausible that Hooper stole that component and then left it lying around in the doorway of his tent. So I came to tell you that the game is up, for you.\"","\n","^He nods and gets to his feet. ",{"->":"left_alone"},"\n",{"#f":5}]}],{"#f":1}],"someone_threw_component":[["^\"Someone threw this in through the window over night,\" I reply, and open my jacket to reveal the component from the Bombe. \"I couldn't see who, it was too dark. But I know what it is.\"","\n","^He reaches out and takes it. \"Well, I'll be damned,\" he murmurs. \"That's it all right. And you didn't have it on you when we put you in here. But it can't have been Hooper — I had men watching him all night. And there's no—one else it could have been.\"","\n","^He turns the component over in his hands, bemused.","\n","ev",true,"/ev",{"VAR=":"piecereturned","re":true},"ev","str","^Suggest something","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Suggest nothing","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"Perhaps Hooper had an accomplice. Someone else who works on site.\"","\n","^Harris shakes his head, distractedly. \"That doesn't make sense,\" he says. \"Why go to all the trouble of stealing it only to give it back? And why like this?\"","\n",["ev","str","^Suggest something","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Suggest nothing","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"Perhaps the accomplice thought it was Hooper being kept in here. Maybe they saw the guard...\"","\n",{"->":"all_too_farfetched"},{"->":".^.^.^.^.g-0"},{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I shrug, eloquently.","\n",[{"->":"all_too_farfetched"},{"#f":5,"#n":"g-1"}],{"#f":5}]}],{"#f":1}],"glad_youre_here":[["^\"Shame,\" he remarks. \"I should have left that window open and put a guard on you. Might have been interesting to see where you went. Anyway, I'm glad you're still here, even if you do smell like a dog.\"","\n","ev","str","^Be optimistic","/str",{"VAR?":"framedhooper"},"!","/ev",{"*":".^.c-0","flg":21},"ev","str","^Be pessimistic","/str",{"VAR?":"framedhooper"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^Be optimistic","/str",{"VAR?":"framedhooper"},"/ev",{"*":".^.c-2","flg":21},"ev","str","^Be pessimistic","/str",{"VAR?":"framedhooper"},"/ev",{"*":".^.c-3","flg":21},{"c-0":["^ ","\n",{"->":"night_falls.morning_not_saved.0.c-0"},{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n",{"->":"night_falls.morning_not_saved.0.c-1"},{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^\"I'm looking forward to having a bath.\"","\n","^\"Well, you should enjoy it. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"c-3":["\n","^\"I imagine I'll smell worse after another couple of days of this.\"","\n","^\"That won't be necessary. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":[{"->":".^.^.^.^.found_missing_component"},{"#f":5}]}],{"#f":1}],"found_missing_component":[["^We found the missing component. Or rather, Hooper found it for us. He snuck out and retrieved it from on top. Of all the damnest places — you would never have known it was there. He claimed ignorance when we jumped him, of course. But it's good enough for me.\"","\n","ev","str","^Approve","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Disapprove","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["\n","^\"I can't tell you enough, I'm glad to hear it. I've had a devil of a night.\"","\n","^His gaze flicks to the broken window, but only for a moment. I think he genuinely cannot believe I could have done it.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"You should never have hired him. A below-average intelligence can't be expected to cope with the pressure of our work.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Harris rolls his eyes, but he might almost be smiling. \"You'd better get along, ","ev",{"CNT?":".^.^.c-0"},"/ev",[{"->":".^.b","c":true},{"b":["^and work through your devils",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["^Mr Intelligent",{"->":".^.^.^.6"},null]}],"nop","^. There's a 24—hour—late message to be tackled and we're a genius short. So you'd better be ready to work twice as hard.\"","\n","ev","str","^Thank him","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Argue with him","/str","/ev",{"*":".^.c-3","flg":20},{"c-2":["^ \t","\n","^\"I'll enjoy it. Thank you for helping me clear this up.\"","\n","^\"Don't thank me yet. There's still a war to fight. Now get a move on.\"","\n","^I nod, and hurry out of the door. The air outside has never tasted fresher and more invigorating. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-3":["^ ","\n","^\"I'll work as hard as I work.\"","\n","^\"Get out,\" Harris growls. \"Before I decide to arrest you as an accessory.\"","\n","^I do as he says. Outside the barrack, the air has never smelt sweeter.","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":[{"->":"head_for_my_dorm_free"},{"#f":5}]}],{"#f":1}],"#f":1}],"night_falls":[["^Night falls. The clockwork of the heavens keeps turning, whatever state I might be in. No—one can steal the components that make the sun go down and the stars come out. I watch it performing its operations. I can't sleep.","\n","ev",{"VAR?":"hooperClueType"},0,">","/ev",[{"->":".^.b","c":true},{"b":["\n","^Has Hooper taken my bait?","\n",{"->":".^.^.^.8"},null]}],"nop","\n","ev","str","^Look of out the window","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Listen at the door","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Wait","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^I peer out of the window, but it looks out onto the little brook at the back of the compound, with no view of the other huts or the House. Who knows if there are men up, searching the base of Hut 2, following one another with flashlights...","\n","ev",{"CNT?":"inside_hoopers_hut.back_of_hut_2"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^Perhaps Hooper is there, in the dark, trying to help me after all?","\n",{"->":".^.^.^.8"},null]}],"nop","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ \t","\n","^I put my ear to the keyhole but can make out nothing. Are there still guards posted? ","ev",{"VAR?":"hooperClueType"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^Perhaps, if Hooper has managed to incriminate himself, the guards have been removed?",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^Perhaps the component has been found and the crisis is over.",{"->":".^.^.^.10"},null]}],"nop","\n","^Perhaps the door is unlocked and they left me to sleep?","\n",["ev","str","^Try it","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Leave it","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ I try the handle. No such luck.","\n",{"->":".^.^.^.^.g-0"},{"#f":5}],"c-1":["^ I don't touch it. I don't want anyone outside thinking I'm trying to escape.","\n",{"->":".^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"c-2":["^ \t\t\t\t\t","\n","^There is nothing I can do to speed up time.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^The night moves at its own pace. I suppose by morning I will know my fate.","\n","ev","str","^Wait","/str",{"VAR?":"hooperClueType"},0,">","/ev",{"*":".^.c-3","flg":21},"ev","str","^Wait","/str",{"VAR?":"hooperClueType"},0,"==","/ev",{"*":".^.c-4","flg":21},{"c-3":["^ ","\n","^Morning comes. I'm woken by a rooster calling from the yard behind the House. I must have slept after all. I pull myself up from the bunk, shivering slightly. There is condensation on the inside of the window. I have probably given myself a chill.","\n","^Without knocking, Harris comes inside. \"You're up,\" he remarks, and then, \"You smell like an animal.\"","\n",["ev","str","^Be friendly","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Be cold","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"I suppose I do rather.\" I laugh, but Harris does not.","\n","^\"This damn business gets worse and worse,\" he says, talking as he goes over to unlock and throw open the window. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"So would you,\" I reply tartly. Harris shrugs.","\n","^\"I've been through worse than this,\" he replies matter—of—factly. \"It's hardly my fault if you sleep in your clothes.\"","\n","^I glare back. He goes over to the window, unlocks it and throws it open, relishing the fresh air from outside.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"Hooper's confessed, you know.\"","\n","ev","str","^Be eager","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Be cautious","/str","/ev",{"*":".^.c-3","flg":20},{"c-2":["^ ","\n","^\"He has? I knew he would. The worm.\"","\n","^\"Steady now. Matters aren't over yet. ","<>","\n",{"->":".^.^.^.hooper_didnt_give_himself_up"},{"#f":5}],"c-3":["^ ","\n","^\"Oh, yes?\"","\n","^\"Yes. For what that's worth. ","<>","\n",{"->":".^.^.^.hooper_didnt_give_himself_up"},{"#f":5}],"#f":5}],"hooper_didnt_give_himself_up":["^There's still the issue of the component. It hasn't turned up. He didn't lead us to it. I guess he figured you must have had something on him. I don't know.\"","\n","^He looks quite put out by the whole affair. He is not the kind of man to deal well with probabilities.","\n","ev","str","^Be interested","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^Be disinterested","/str","/ev",{"*":".^.c-5","flg":20},{"c-4":["^ ","\n","^\"You mean he confessed of his own accord? You didn't catch him?\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-5":["^ ","\n","^\"Well, I'm glad his conscience finally caught up with him,\" I reply dismissively.","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^\"The Captain went back into that hut and he confessed immediately. We were so surprised we didn't let you go.\" He wrinkles his nose. \"I'm rather sorry about that now. I suggest you have a wash.\"","\n","^And with that he gestures to the doorway.","\n","ev","str","^Go","/str","/ev",{"*":".^.c-6","flg":20},"ev","str","^Wait","/str","/ev",{"*":".^.c-7","flg":20},{"c-6":["^ ","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-7":["^ ","\n","^I hang back a moment. Something does not seem quite right. After all, Hooper did not steal the component. He has no reason to confess to anything. Perhaps this is another trap?","\n","^\"Well?\" Harris asks. \"What are you waiting for? Please don't tell me you want to confess now as well, I don't think my head could stand it.\"","\n",["ev","str","^Confess","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't confess","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^After a chance like this? A chance — however real — to save my neck? To hand it over — what, to save Hooper's worthless skin?","\n",["ev","str","^Confess","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't confess","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^I see. Perhaps you think I bullied the man into giving himself up. Perhaps he understood my little clue far enough to know it was a threat against him, but not well enough to understand where he should look to find it. So he took the easy route out and folded. Gave me the hand.","\n","ev",true,"/ev",{"VAR=":"hooperConfessed","re":true},"^Hardly sporting, of course.","\n",["ev","str","^Confess","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't confess","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["\n","^Well, then. I suppose this must be what it feels like to have a conscience. I suppose I had always wondered.","\n","^\"Harris, sir. I don't know what Hooper's playing at, sir. But I can't let him do this.\"","\n","^\"Do what?\"","\n","^\"Take the rope for this. I took it, sir.","\n","ev",false,"/ev",{"VAR=":"revealedhooperasculprit","re":true},"ev",false,"/ev",{"VAR=":"losttemper","re":true},{"->":"reveal_location_of_component"},{"->":".^.^.^.^.^.^.g-0"},{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"I certainly don't. But still, I'm surprised. I had Hooper down for a full—blown double agent, a traitor. He knows he'll face the rope, doesn't he?\"","\n","^\"Don't ask me to explain why he did what he did,\" Harris sighs. \"Just be grateful that he did, and you're now off the hook.\"","\n",{"->":".^.^.^.^.^.g-2"},{"#f":5}]}],{"#f":5}],"#f":5}],"g-2":["^Curiouser and curiouser. I nod once to Harris and slip outside into the cold morning air.","\n","ev",{"VAR?":"hooperClueType"},0,"==","/ev",[{"->":".^.b","c":true},{"b":["\n","^Hooper's confession only makes sense in one fashion","ev",{"VAR?":"hooperConfessed"},"/ev",[{"->":".^.b","c":true},{"b":["^, and that is his being dim—witted and slow",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^ — if I successfully implied to him that I had him framed, but he did not unpack my little clue well enough to go looking for the component. Well, I had figured him for a more intelligent opponent, but a resignation from the game will suffice",{"->":".^.^.^.7"},null]}],"nop","^. Or perhaps he knew he would be followed if he went to check, and decided he would be doomed either way.","\n",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["\n","^Hooper's confession only makes sense in one way — and that's that he believed me. He reasoned that he would be followed. To try and uncover the component would have got him arrested, and to confess was the same.","\n","^He simply caved, and threw in his hand.","\n",{"->":".^.^.^.9"},null]}],"nop","\n","^Of course, however, there is only one way to be certain that Harris is telling the truth, and that is to check the breeze—block at the back of Hut 2.","\n","ev","str","^Check","/str","/ev",{"*":".^.c-8","flg":20},"ev","str","^Don't check","/str","/ev",{"*":".^.c-9","flg":20},{"c-8":["^ ",{"->":"go_to_where_component_is_hidden"},"\n",{"#f":5}],"c-9":["\n","^But there will time for that later. If there is nothing there, then Hooper discovered the component after all and Harris' men will have swooped on him, and the story about his confession is just a ruse to test me out.","\n","^And if the component is still there — well. It will be just as valuable to my contact in a week's time, and his deadline of the 31st is not yet upon us.","\n",{"->":"head_for_my_dorm_free"},{"#f":5}],"#f":5}]}],{"#f":5}],"c-4":["^ ",{"->":".^.^.^.^.morning_not_saved"},"\n",{"#f":5}],"#f":5}]}],{"morning_not_saved":[["^Morning comes with the call of a rooster from the yard of the House. I must have slept after all. I pull myself up off the bunk, shivering slightly. There is condensation on the inside of the window. I have probably given myself a chill.","\n","^It's not long after that Harris enters the hut. He closes the door behind him, careful as ever, then takes a chair across from me.","\n","^\"You smell like a dog,\" he remarks.","\n","ev","str","^Be optimistic","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Be pessimistic","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"I'm looking forward to a long bath,\" I reply. \"And getting back to work.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"So would you after the night I've had.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":[{"->":"harris_certain_is_you"},{"#f":5}]}],{"#f":1}],"#f":1}],"harris_certain_is_you":["^\"Well, I'm afraid it is going to get worse for you,\" Harris replies soberly. \"We followed Hooper, and he took himself neatly to bed and slept like a boy scout. Which puts us back to square one, and you firmly in the frame. And I'm afraid I don't have time for any more games. I want you to tell me where that component is, or we will hang you as a traitor.\"","\n","ev",false,"/ev",{"VAR=":"revealedhooperasculprit","re":true},"ev",false,"/ev",{"VAR=":"losttemper","re":true},{"->":"harris_threatens_lynching"},{"#f":1}],"head_for_my_dorm_free":[["^I head for my dorm, intent on a bath, breakfast, a glance at the crossword before the other men get to it, and then on with work. They should have replaced the component in the Bombe by now. We will only be a day behind.","\n","ev",{"VAR?":"framedhooper"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^And then everything will proceed as before. The component will mean nothing to the Germans — this is the one fact I could never have explained to a man like Harris, even though the principle behind the Bombe is the same as the principle behind the army. The individual pieces — the men, the components — do not matter. They are identical. It is how they are arranged that counts.","\n",{"->":".^.^.^.7"},null]}],"nop","\n","^I bump into Russell in the dorm hut.","\n","^\"Did you hear?\" he whispers. \"Terrible news about Hooper. Absolutely terrible.\"","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["^ ","\n","^\"Quite terrible. I would never have guessed.\"","\n","^\"Well.\" Russell harrumphs.","\n",[["^\"Quince was saying this morning, apparently his grandfather was German. So perhaps it's to be expected. See you there?\"","\n",{"->":".^.^.^.^.g-0"},{"#f":5,"#n":"quince"}],null],{"#f":5}],"c-1":["\n","^\"Heard what?\"","\n",[["^\"Hooper's been taken away. They caught him, uncovering that missing Bombe component from a hiding place somewhere, apparently about to take it to his contact.\" Russell harrumphs. ",{"->":".^.^.^.^.c-0.6.quince"},"\n",{"->":".^.^.^.^.g-0"},{"#f":5,"#n":"hooper_taken"}],null],{"#f":5}],"c-2":["^ ","\n","^\"I don't know what you're talking about.\"","\n",{"->":".^.^.c-1.3.hooper_taken"},{"->":".^.^.g-0"},{"#f":5}],"c-3":["\n","^\"If you'll excuse me, Russell. I was about to take a bath.\"","\n","^\"Oh, of course. Worked all night, did you? Well, you'll hear soon enough. Can hardly hide the fact there'll only be three of us from now on.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I wave to him and move away, my thoughts turning to the young man in the village. My lover. My contact. My blackmailer. Hooper may have taken the fall for the missing component, but ","ev",{"VAR?":"framedhooper"},"!","/ev",[{"->":".^.b","c":true},{"b":["^if he did recover it from Hut 2 then ",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^ its recovery does mean ",{"->":".^.^.^.7"},null]}],"nop","^I have nothing to sell to save my reputation","ev",{"CNT?":"i_met_a_young_man"},"/ev",[{"->":".^.b","c":true},{"b":["^, if I have any left",{"->":".^.^.^.13"},null]}],"nop","^.","\n","ev",{"VAR?":"framedhooper"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^If he didn't, of course, and Harris was telling the truth about his sudden confession, then I will be able to buy my freedom once and for all.","\n",{"->":".^.^.^.21"},null]}],"nop","\n","ev","str","^Get the component","/str",{"VAR?":"framedhooper"},"!","/ev",{"*":".^.c-4","flg":21},"ev","str","^Leave it","/str",{"VAR?":"framedhooper"},"!","/ev",{"*":".^.c-5","flg":21},"ev","str","^Act normal","/str","/ev",{"*":".^.c-6","flg":20},{"c-4":["^ ",{"->":"go_to_where_component_is_hidden"},"\n",{"#f":5}],"c-5":["^ ","\n","^I will have to leave that question for another day. To return there now, when they're probably watching my every step, would be suicide. After all, if Hooper ","ev",{"VAR?":"hooperClueType"},1,"==","/ev",[{"->":".^.b","c":true},{"b":["^followed",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^understood",{"->":".^.^.^.10"},null]}],"nop","^ my clue, he will have explained it to them to save his neck. They won't believe him — but they won't quite disbelieve him either. We're locked in a cycle now, him and me, of half—truth and probability. There's nothing either of us can do to put the other entirely into blame.","\n",{"->":"ending_return_to_normal"},{"#f":5}],"c-6":["^ ","\n","^But there is nothing to be done about it. ",{"->":"ending_return_to_normal"},"\n",{"#f":5}],"#f":5}]}],{"#f":1}],"ending_return_to_normal":[["^Nothing, that is, except to act as if there is no game being played. I'll have a bath, then start work as normal. I've got a week to find something to give my blackmailer","ev",{"CNT?":"i_met_a_young_man"},"/ev",[{"->":".^.b","c":true},{"b":["^ — or give him nothing: it seems my superiors know about my indiscretions now already",{"->":".^.^.^.5"},null]}],"nop","^.","\n","ev","str","^Co-operate","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Dissemble","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["^ ","\n","^Something will turn up. It always does. An opportunity will present itself, and more easily now that Hooper is out of the way.","\n","^But for now, there's yesterday's intercept to be resolved.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^Or perhaps I might hand my young blackmailer over my superiors instead for being the spy he is.","\n","^Perhaps that would be the moral thing to do, even, and not just the most smart.","\n","^But not today. Today, there's an intercept to resolve.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["\n","^In a week's time, this whole affair will be in the past and quite forgotten. I'm quite sure of that. ",{"->":".^.^.c-3"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-3":["^ I've more important problems to think about now. There's still yesterday's intercept to be resolved. ","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^The Bombe needs to be set up once more and set running.","\n","^It's time I tackled a problem I can solve.","\n","end",{"#f":5}]}],{"#f":1}],"go_to_where_component_is_hidden":[["^It won't take a moment to settle the matter. I can justify a walk past Hut 2 as part of my morning stroll. It will be obvious in a moment if the component is still there.","\n","^On my way across the paddocks, between the huts and the House, I catch sight of young Miss Lyon, arriving for work on her bicycle. She giggles as she sees me and waves.","\n","ev","str","^Wave back","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Ignore her","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^I wave cheerily back and she giggles, almost drops her bicycle, then dashes away inside the House. Judging by the clock on the front gable, she's running a little late this morning.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^I give no reaction. She sighs to herself, as if this kind of behaviour is normal, and trots away inside the House to begin her duties.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I turn the corner of Hut 3 and walk down the short gravel path to Hut 2. It was a good spot to choose — Hut 2 is where the electricians work, and they're generally focussed on what they're doing. They don't often come outside to smoke a cigarette so it's easy to slip past the doorway unnoticed.","\n","ev","str","^Check inside","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Go around the back","/str","/ev",{"*":".^.c-3","flg":20},{"c-2":["^ \t\t","\n","^I hop up the steps and put my head inside all the same. Nobody about. Still too early in the AM for sparks, I suppose. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-3":["^ ","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^I head on around the back of the hut. The breeze—block with the cavity is on the left side.","\n","ev","str","^Check","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^Look around","/str","/ev",{"*":".^.c-5","flg":20},{"c-4":["^ \t\t","\n","^No time to waste. I drop to my knees and check the breeze—block. Sure enough, there's nothing there. Hooper took the bait.","\n","^Suddenly, there's a movement behind me. I look up to see, first a snub pistol, and then, Harris.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-5":["^ ","\n","^I pause to glance around, and catch a glimpse of movement. Someone ducking around the corner of the hut. Or a canvas sheet flapping in the light breeze. Impossible to be sure.","\n",["ev","str","^Check the breeze—block","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Check around the side of the hut","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ",{"->":".^.^.^.^.c-4"},"\n",{"->":".^.^.^.^.^.g-2"},{"#f":5}],"c-1":["^ ","\n","^But too important to guess. I move back around the side of the hut.","\n","^Harris is there, leaning in against the wall. He holds a stub pistol in his hand.","\n",{"->":".^.^.^.^.^.g-2"},{"#f":5}]}],{"#f":5}],"#f":5}],"g-2":["ev",{"VAR?":"hooperClueType"},1,">","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"","ev",{"VAR?":"hooperClueType"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["^Queen to rook two",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["^Messy without one missing whatever it was",{"->":".^.^.^.9"},null]}],"nop","^,\" he declares. \"I wouldn't have fathomed it but Hooper did. Explained it right after we sprung him doing what you're doing now. We weren't sure what to believe but now, you seem to have resolved that for us.\"","\n",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["\n","^\"Hooper said you'd told him where to look. I didn't believe him. Or, well. I wasn't sure what to believe. Now I rather think you've settled it.\"","\n",{"->":".^.^.^.7"},null]}],"nop","\n","ev","str","^Agree","/str","/ev",{"*":".^.c-6","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-7","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-8","flg":20},{"c-6":["^ ","\n","^\"I have, rather.\" I put my hands into my pockets. \"I seem to have done exactly that.\"","\n","^\"I'm afraid my little story about Hooper confessing wasn't true. I wanted to see if you'd go to retrieve the part.\" Harris gestures me to start walking. \"You were close, Manning, I'll give you that. I wanted to believe you. But I'm glad I didn't.\"","\n",{"->":".^.^.^.g-3.done"},{"->":".^.^.^.g-3"},{"#f":5}],"c-7":["^ ","\n","^\"I spoke to Russell. He said he saw Hooper doing something round here. I wanted to see what it was.\"","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-8":["^ ","\n","^\"Harris, you'd better watch out. He's planted a time—bomb here.\"","\n","^Harris stares at me for a moment, then laughs. \"Oh, goodness. That's rich.\"","\n","^I almost wish I had a way to make the hut explode, but of course I don't.","\n",{"->":".^.^.^.g-3"},{"#f":5}],"#f":5}],"g-3":["^\"Enough.\" Harris gestures for me to start walking. \"This story couldn't be simpler. You took it to cover your back. You hid it. You lied to get Hooper into trouble, and when you thought you'd won, you came to scoop your prize. A good hand but ultimately, ","ev",{"VAR?":"hooperClueType"},1,"<=","/ev",[{"->":".^.b","c":true},{"b":["^if it hadn't have been you who hid the component, then you wouldn't be here now",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["^you told Hooper where to look with your little riddle",{"->":".^.^.^.8"},null]}],"nop","^.\"","\n",["^He leads me across the yard. Back towards Hut 5 to be decoded, and taken to pieces, once again.","\n","end",{"#f":5,"#n":"done"}],{"#f":5}]}],{"#f":1}],"harris_threatens_lynching":[["ev",{"CNT?":"harris_certain_is_you"},"/ev",[{"->":".^.b","c":true},{"b":["^He passes a hand across his eyes with a long look of despair.",{"->":".^.^.^.5"},null]}],[{"->":".^.b"},{"b":["^He gets to his feet, and gathers his gloves from the table top.",{"->":".^.^.^.5"},null]}],"nop","\n","^\"I'm going to go outside and organise a rope. That'll take about twelve minutes. That's how long you have to decide.\"","\n","ev","str","^Protest","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Confess","/str",{"VAR?":"gotcomponent"},"!",{"VAR?":"throwncomponentaway"},"!","&&","/ev",{"*":".^.c-1","flg":21},"ev","str","^Stay silent","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Show him the component","/str",{"VAR?":"gotcomponent"},"/ev",{"*":".^.c-3","flg":21},{"c-0":["^ ","\n","^\"You can't do this!\" I cry. \"It's murder! I demand a trial, a lawyer; for God's sake, man, you can't just throw me overboard, we're not barbarians...!\"","\n",[["^\"You leave me no choice,\" Harris snaps back, eyes cold as gun—metal. \"You and your damn cyphers. Your damn clever problems. If men like you didn't exist, if we could just all be straight with one another.\" He gets to his feet and heads for the door. \"I fear for the future of this world, with men like you in. Reich or no Reich, Mr Manning, people like you simply complicate matters.\"","\n",{"->":"left_alone"},{"->":".^.^.^.^.g-0"},{"#f":5,"#n":"too_clever"}],null],{"#f":5}],"c-1":["^ ","\n","^I nod. \"I don't need twelve minutes. ",{"->":"reveal_location_of_component"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ",{"->":"my_lips_are_sealed"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-3":["^ ","\n","^\"I don't need twelve minutes. Here it is.\"","\n","^I open my jacket and pull the Bombe component out of my pocket. Harris takes it from me, whistling, curious.","\n","^\"Well, I'll be. That's it all right.\"","\n","^\"That's it.\"","\n","^\"But you didn't have it on you yesterday.\"","\n",["ev","str","^Explain","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't explain","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"I climbed out of the window overnight,\" I explain. \"I went and got this from where it was hidden, and brought it back here.\"","\n",{"->":".^.^.^.^.g-0"},{"#f":5}],"c-1":["\n","^\"No. I didn't.\"","\n",{"->":".^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"g-0":[{"->":"all_too_farfetched"},"ev","str","^Confess","/str",{"VAR?":"throwncomponentaway"},"/ev",{"*":".^.c-4","flg":21},"ev","str","^Frame Hooper","/str",{"VAR?":"throwncomponentaway"},"/ev",{"*":".^.c-5","flg":21},{"c-4":["\n","^\"I don't need twelve minutes. The component is in the long grass behind Hooper's tent. I threw it there hoping to somehow frame him, but now I see that won't be possible. I was naive, I suppose.\"","\n","ev",true,"/ev",{"VAR=":"piecereturned","re":true},{"->":"reveal_location_of_component.harris_believes"},{"#f":5}],"c-5":["^ ","\n","^\"Look, I know where it is. The missing piece of the Bombe is in the long grasses behind Hooper's tent. I saw him throw it there right after we finished work. He knew you'd scour the camp but I suppose he thought you'd more obvious places first. I suppose he was right about that. Look there. That proves his guilt.\"","\n","ev",true,"/ev",{"VAR=":"longgrasshooperframe","re":true},"ev",true,"/ev",{"VAR=":"piecereturned","re":true},"^\"That doesn't prove anything,\" Harris returns sharply. \"But we'll check what you say, all the same.\" He gets to his feet and heads out of the door.","\n",{"->":"left_alone"},{"#f":5}],"#f":5}]}],{"#f":1}],"reveal_location_of_component":["<>","^ The missing component of the Bombe computer is hidden in a small cavity in a breeze—block supporting the left rear post of Hut 2. I put in there anticipating a search. I intended to ","ev",{"VAR?":"revealedhooperasculprit"},"/ev",[{"->":".^.b","c":true},{"b":["^pass it to Hooper",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^dispose of it",{"->":".^.^.^.7"},null]}],"nop","^ once the fuss had died down. I suppose I was foolish to think that it might.\"","\n","ev",true,"/ev",{"VAR=":"piecereturned","re":true},{"->":".^.harris_believes"},{"harris_believes":["ev",{"CNT?":"night_falls.0.g-0.c-3.6.hooper_didnt_give_himself_up"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Indeed. And Mr Manning: God help you if you're lying to me.\"","\n",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["\n","^\"I thought as much. I hadn't expected you to give it out so easily, however. You understand, Hooper has said nothing, of course. In fact, he went to Hut 2 directly after we released him and uncovered the component. But he told us you had instructed him where to go. Hence my little double bluff. Frankly, I'll be glad when I'm shot of the lot of you mathematicians.\"","\n",{"->":".^.^.^.6"},null]}],"nop","\n","^Harris stands, and slips away smartly. ",{"->":"left_alone"},"\n",{"#f":1}],"#f":1}],"my_lips_are_sealed":["^I say nothing, my lips tightly, firmly sealed. It's true I am a traitor, to the very laws of nature. The world has taught me that since a very early age. But not to my country — should the Reich win this war, I would hardly be treated as an honoured hero. I was doomed from the very start.","\n","ev",true,"/ev",{"VAR=":"notraitor","re":true},"^I explain none of this. How could a man like Harris understand?","\n","^The Commander takes one look back from the doorway as he pulls it to.","\n","^\"It's been a pleasure working with you, Mr Manning,\" he declares. \"You've done a great service to this country. If we come through, I'm sure they'll remember you name. I'm sorry it had to end this way and I'll do my best to keep it quiet. No—one need know what you did.\"","\n",{"->":"left_alone"},{"#f":1}],"all_too_farfetched":["^\"This is all too far—fetched,\" Harris says. \"I'm glad to have this back, but I need to think.\"","\n","^Getting to his feet, he nods once. \"You'll have to wait a little longer, I'm afraid, Manning.\"","\n","^Then he steps out of the door, muttering to himself.","\n",{"->":"make_your_peace"},{"#f":1}],"left_alone":["ev",{"CNT?":"slam_door_shut_and_gone.time_to_move_now"},"/ev",[{"->":".^.b","c":true},{"b":["^The Commander holds the door for his superior, and follows him out.",{"->":".^.^.^.4"},null]}],"nop","^ Then the door closes. I am alone again, as I have been for most of my short life.","\n",{"->":"make_your_peace"},{"#f":1}],"make_your_peace":[["ev","str","^Make your peace","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I am waiting again. I have no God to make my peace with. I find it difficult to believe in goodness of any kind, in a world such as this.","\n","ev",{"VAR?":"notraitor"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","ev",true,"/ev",{"VAR=":"notraitor","re":true},"^But I am no traitor. Not to my country. To my sex, perhaps. But how could I support the Reich? If the Nazis were to come to power, I would be worse off than ever.","\n",{"->":".^.^.^.7"},null]}],"nop","\n","ev",{"CNT?":"harris_threatens_lynching.0.c-0.4.too_clever"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^In truth, it is men like Harris who are complex, not men like me. I live to make things ordered, systematic. I like my pencils sharpened and lined up in a row. I do not deal in difficult borders, or uncertainties, or alliances. If I could, I would reduce the world to something easier to understand, something finite.","\n","^But I cannot, not even here, in our little haven from the horrors of the war.","\n",{"->":".^.^.^.13"},null]}],"nop","\n","^I have no place here. No way to fit. I am caught, in the middle, cryptic and understood only thinly, through my machines.","\n",["ev",{"^->":"make_your_peace.0.g-0.17.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^I must seem very calm. \t\t\t",{"->":"$r","var":true},null]}],["ev",{"^->":"make_your_peace.0.g-0.18.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-2","flg":18},{"s":["^Perhaps I should try to escape.",{"->":"$r","var":true},null]}],{"c-1":["ev",{"^->":"make_your_peace.0.g-0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.17.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-2":["ev",{"^->":"make_your_peace.0.g-0.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.18.s"},[{"#n":"$r2"}],"^ But escape to where? I am already a prisoner. Jail would be a blessing. ",{"->":".^.^.^.g-1.monastic"},"\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["<>","^ I suppose I do not believe they will hang me. They will lock me up and continue to use my brain, if they can. I wonder what they will tell the world — perhaps that I have taken my own life. That would be simplest. The few who know me would believe it.","\n","^Well, then. Not a bad existence, in prison. Removed from temptation.","\n",["^A monastic life, with plenty of problems to keep me going.","\n","^I wonder what else I might yet unravel before I'm done?","\n",["ev",{"^->":"make_your_peace.0.g-1.monastic.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-3","flg":18},{"s":["^The door is opening.",{"->":"$r","var":true},null]}],{"c-3":["ev",{"^->":"make_your_peace.0.g-1.monastic.c-3.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"^ Harris is returning. Our little calculation here is complete. ","ev",{"VAR?":"piecereturned"},"!","/ev",[{"->":".^.b","c":true},{"b":["^ I can only hope one of the others will be able to explain to him that the part I stole will mean nothing to the Germans.",{"->":".^.^.^.13"},null]}],[{"->":".^.b"},{"b":["^We are just pieces in this machine; interchangeable and prone to wear.",{"->":".^.^.^.13"},null]}],"nop","\n",{"->":".^.^.^.^.g-2"},{"#f":5}],"#f":5,"#n":"monastic"}],{"#f":5}],"g-2":["^That is the true secret of the calculating engine, and the source of its power. It is not the components that matter, they are quite repetitive. What matters is how they are wired; the diversity of the patterns and structures they can form. Much like people — it is how they connect that determines our victories and tragedies, and not their genius.","\n","^Which makes me wonder. Should I give ","ev",{"CNT?":"i_met_a_young_man"},"/ev",[{"->":".^.b","c":true},{"b":["^up my beautiful young man",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["^the young man who put me in this spot",{"->":".^.^.^.8"},null]}],"nop","^ to them as well as myself?","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-5","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-6","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-7","flg":20},{"c-4":["^ ","\n","^But of course I will. ","ev",{"VAR?":"forceful"},2,">","/ev",[{"->":".^.b","c":true},{"b":["^Perhaps I can persuade them to put him in my cell.",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^A little vengeance, disguised as doing something good.",{"->":".^.^.^.10"},null]}],"nop","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-5":["^ ","\n","^No. What would be the use? He will be long gone, and the name he told me is no doubt hokum. No: I was alone before in guilt, and I am thus alone again.","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-6":["^ ","\n","^No. Why would I? He is no doubt an innocent himself, trapped by some dire circumstance. Forced to act the way he did. I have every sympathy for him.","\n","^Of course I do.","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-7":["^ ","\n","^It depends, perhaps, on what his name his worth. If it were to prove valuable, well; perhaps I can concoct a few more such lovers with which to ease my later days.","\n","ev",{"VAR?":"hooper_mentioned"},"/ev",[{"->":".^.b","c":true},{"b":["^ Hooper, perhaps. He wouldn't like that. ",{"->":".^.^.^.8"},null]}],"nop","\n",{"->":".^.^.^.g-3"},{"#f":5}],"#f":5}],"g-3":["ev",{"VAR?":"longgrasshooperframe"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^Harris put the cuffs around my wrists. \"I still have the intercept in my pocket,\" I remark. \"Wherever we're going, could I have a pencil?\"","\n",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["\n","^\"We recovered the part, just where you said it was,\" Harris reports, as he puts the cuffs around my wrists. \"Of course, a couple of the men swear blind they searched there yesterday, so I'm afraid, what with the broken window... we've formed a perfectly good theory which doesn't bode well for you.\"","\n",{"->":".^.^.^.6"},null]}],"nop","\n","ev",true,"/ev",{"VAR=":"piecereturned","re":true},"ev",{"VAR?":"longgrasshooperframe"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^\"I see.\" It doesn't seem worth arguing any further. \"I still have the intercept in my pocket,\" I remark. \"Wherever we're going, could I have a pencil?\"","\n",{"->":".^.^.^.16"},null]}],"nop","\n","^He looks me in the eye.","\n","ev",{"VAR?":"losttemper"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Of course. And one of your computing things, if I get my way. And when we're old, and smoking pipes together in The Rag like heroes, I'll explain to you the way that decent men have affairs.","\n",{"->":".^.^.^.26"},null]}],[{"->":".^.b"},{"b":["\n","^\"I'll give you a stone to chisel notches in the wall. And that's all the calculations you'll be doing. And as you sit there, pissing into a bucket and growing a beard down to your toes, you have a think about how a smart man would conduct his illicit affairs. With a bit of due decorum you could have learnt off any squaddie.","\n",{"->":".^.^.^.26"},null]}],"nop","\n","<>","^ You scientists.\"","\n","^He drags me up to my feet.","\n","^\"You think you have to re—invent everything.\"","\n","^With that, he hustles me out of the door and I can't help thinking that, with a little more strategy, I could still have won the day. But too late now, of course.","\n","end",{"#f":5}]}],{"#f":1}],"global decl":["ev",0,{"VAR=":"forceful"},0,{"VAR=":"evasive"},false,{"VAR=":"teacup"},false,{"VAR=":"gotcomponent"},false,{"VAR=":"drugged"},false,{"VAR=":"hooper_mentioned"},false,{"VAR=":"losttemper"},false,{"VAR=":"admitblackmail"},0,{"VAR=":"hooperClueType"},false,{"VAR=":"hooperConfessed"},0,{"VAR=":"smashingWindowItem"},false,{"VAR=":"notraitor"},false,{"VAR=":"revealedhooperasculprit"},false,{"VAR=":"smashedglass"},false,{"VAR=":"muddyshoes"},false,{"VAR=":"framedhooper"},false,{"VAR=":"putcomponentintent"},false,{"VAR=":"throwncomponentaway"},false,{"VAR=":"piecereturned"},false,{"VAR=":"longgrasshooperframe"},false,{"VAR=":"DEBUG"},"/ev","end",null],"#f":1}],"listDefs":{}} \ No newline at end of file diff --git a/prototype/TheIntercept.js b/prototype/TheIntercept.js new file mode 100644 index 0000000..aabd144 --- /dev/null +++ b/prototype/TheIntercept.js @@ -0,0 +1 @@ +var storyContent = {"inkVersion":20,"root":[[{"#":"title: The Intercept"},{"#":"author: inkle Ltd."},"ev",{"VAR?":"DEBUG"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^IN DEBUG MODE!","\n","ev","str","^Beginning...","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Framing Hooper...","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^In with Hooper...","/str","/ev",{"*":".^.c-2","flg":20},{"->":"0.7"},{"c-0":["^\t",{"->":"start"},"\n",{"#f":5}],"c-1":["^ ",{"->":"claim_hooper_took_component"},"\n",{"#f":5}],"c-2":["^ ",{"->":"inside_hoopers_hut"},"\n",{"#f":5}]}]}],[{"->":".^.b"},{"b":["\n",{"->":"start"},{"->":"0.7"},null]}],"nop","\n",["done",{"#f":5,"#n":"g-0"}],null],"done",{"lower":[{"temp=":"x"},"ev",{"VAR?":"x"},1,"-","/ev",{"temp=":"x","re":true},{"#f":1}],"raise":[{"temp=":"x"},"ev",{"VAR?":"x"},1,"+","/ev",{"temp=":"x","re":true},{"#f":1}],"start":[[["^They are keeping me waiting.","\n",["ev",{"^->":"start.0.g-0.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^Hut 14",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"start.0.g-0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"^. The door was locked after I sat down. ","\n","^I don't even have a pen to do any work. There's a copy of the morning's intercept in my pocket, but staring at the jumbled letters will only drive me mad.","\n","^I am not a machine, whatever they say about me.","\n",{"->":".^.^.^.opts"},{"#f":5}],"#f":5,"#n":"g-0"}],{"opts":[["ev","visit",2,"MIN","/ev","ev","du",0,"==","/ev",{"->":".^.s0","c":true},"ev","du",1,"==","/ev",{"->":".^.s1","c":true},"ev","du",2,"==","/ev",{"->":".^.s2","c":true},"nop",{"s0":["pop",{"->":".^.^.23"},null],"s1":["pop","^I rattle my fingers on the field table.",{"->":".^.^.23"},null],"s2":["pop",{"->":".^.^.23"},null],"#f":5}],"\n","ev","str","^Think","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Plan","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Wait","/str","/ev",{"*":".^.c-3","flg":20},{"c-1":["^ ","\n","^They suspect me to be a traitor. They think I stole the component from the calculating machine. They will be searching my bunk and cases.","\n","^When they don't find it, ","ev",{"CNT?":".^.^.c-2"},"/ev",[{"->":".^.b","c":true},{"b":["^then",{"->":".^.^.^.9"},null]}],"nop","^ they'll come back and demand I talk.","\n",{"->":".^.^"},{"->":".^.^.^.g-1"},{"#f":5}],"c-2":["\n","ev",{"CNT?":".^.^.c-1"},"!","/ev",[{"->":".^.b","c":true},{"b":["^What I am is",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^I am",{"->":".^.^.^.7"},null]}],"nop","^ a problem—solver. Good with figures, quick with crosswords, excellent at chess.","\n","^But in this scenario — in this trap — what is the winning play?","\n",["ev","str","^Co—operate","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Dissemble","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Divert","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^I must co—operate. My credibility is my main asset. To contradict myself, or another source, would be fatal.","\n","^I must simply hope they do not ask the questions I do not want to answer.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":"start.0.g-1"},{"#f":5}],"c-1":["^ ","\n","^Misinformation, then. Just as the war in Europe is one of plans and interceptions, not planes and bombs.","\n","^My best hope is a story they prefer to the truth.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":"start.0.g-1"},{"#f":5}],"c-2":["^ ","\n","^Avoidance and delay. The military machine never fights on a single front. If I move slowly enough, things will resolve themselves some other way, my reputation intact.","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":"start.0.g-1"},{"#f":5}]}],{"#f":5}],"c-3":["^\t\t","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":[{"->":"start.waited"},{"#f":5}]}],{"waited":[[["^Half an hour goes by before Commander Harris returns. He closes the door behind him quickly, as though afraid a loose word might slip inside.","\n","^\"Well, then,\" he begins, awkwardly. This is an unseemly situation.","\n",["ev",{"^->":"start.waited.0.g-0.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^\"Commander.\"",{"->":"$r","var":true},null]}],["ev",{"^->":"start.waited.0.g-0.5.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str",{"CNT?":"start.0.opts.c-2.12.c-2"},"!","/ev",{"*":".^.^.c-1","flg":19},{"s":["^\"Tell me what this is about.\"",{"->":"$r","var":true},null]}],"ev","str","^Wait","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["ev",{"^->":"start.waited.0.g-0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"\n","^He nods. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-1":["ev",{"^->":"start.waited.0.g-0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.5.s"},[{"#n":"$r2"}],"\n","^He shakes his head.","\n","^\"Now, don't let's pretend.\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-2":["\n","^I say nothing.","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5,"#n":"g-0"}],{"g-1":["^He has brought two cups of tea in metal mugs: he sets them down on the tabletop between us.","\n","ev","str","^Deny","/str",{"CNT?":".^.^.g-0.c-1"},"/ev",{"*":".^.c-3","flg":21},"ev","str","^Take one","/str","/ev",{"*":".^.c-4","flg":20},["ev",{"^->":"start.waited.0.g-1.15.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str",{"CNT?":".^.^.^.g-0.c-1"},"!","/ev",{"*":".^.^.c-5","flg":19},{"s":["^\"What's going on?\"",{"->":"$r","var":true},null]}],"ev","str","^Wait","/str","/ev",{"*":".^.c-6","flg":20},{"c-3":["^ \"I'm not pretending anything.\"","\n","ev",{"CNT?":"start.0.opts.c-2.12.c-0"},"/ev",[{"->":".^.b","c":true},{"b":["^I'm lying already, despite my good intentions.",{"->":".^.^.^.6"},null]}],"nop","\n","^Harris looks disapproving. ",{"->":".^.^.c-6.3.pushes_cup"},"\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-4":["\n","ev",true,"/ev",{"VAR=":"teacup","re":true},"^I take a mug and warm my hands. It's ","<>","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-5":["ev",{"^->":"start.waited.0.g-1.c-5.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.15.s"},[{"#n":"$r2"}],"\n","^\"You know already.\"","\n",{"->":".^.^.c-6.3.pushes_cup"},{"->":".^.^.^.g-2"},{"#f":5}],"c-6":["\n","^I wait for him to speak.","\n",[["^He pushes one mug halfway towards me: ","<>","\n",{"->":".^.^.^.^.^.g-2"},{"#f":5,"#n":"pushes_cup"}],null],{"#f":5}],"#f":5}],"g-2":["^a small gesture of friendship.","\n","^Enough to give me hope?","\n","ev","str","^Take it","/str",{"VAR?":"teacup"},"!","/ev",{"*":".^.c-7","flg":21},"ev","str","^Don't take it","/str",{"VAR?":"teacup"},"!","/ev",{"*":".^.c-8","flg":21},"ev","str","^Drink","/str",{"VAR?":"teacup"},"/ev",{"*":".^.c-9","flg":21},"ev","str","^Wait","/str",{"VAR?":"teacup"},"/ev",{"*":".^.c-10","flg":21},{"c-7":["^ ","\n","^I ","ev",{"CNT?":".^.^.^.g-1.c-4"},"/ev",[{"->":".^.b","c":true},{"b":["^lift the mug",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["^take the mug,",{"->":".^.^.^.8"},null]}],"nop","^ and blow away the steam. It is too hot to drink.","\n","^Harris picks his own up and just holds it.","\n","ev",true,"/ev",{"VAR=":"teacup","re":true},"ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-8":["^ ","\n","^Just a cup of insipid canteen tea. I leave it where it is.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-9":["^ ","\n","^I raise the cup to my mouth but it's too hot to drink.","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-10":["^ \t\t","\n","^I say nothing as ",{"->":".^.^.c-7"},"\n",{"->":".^.^.^.g-3"},{"#f":5}],"#f":5}],"g-3":["^\"Quite a difficult situation,\" ","ev",{"CNT?":".^.^.g-2.c-7"},"/ev",[{"->":".^.b","c":true},{"b":["^he",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["^Harris",{"->":".^.^.^.6"},null]}],"nop","^ begins","ev",{"VAR?":"forceful"},0,"<=","/ev",[{"->":".^.b","c":true},{"b":["^, sternly",{"->":".^.^.^.14"},null]}],"nop","^. I've seen him adopt this stiff tone of voice before, but only when talking to the brass. \"I'm sure you agree.\"","\n","ev","str","^Agree","/str","/ev",{"*":".^.c-11","flg":20},"ev","str","^Disagree","/str","/ev",{"*":".^.c-12","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-13","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-14","flg":20},{"c-11":["^ ","\n","^\"Awkward,\" I reply","\n",{"->":".^.^.^.g-4"},{"#f":5}],"c-12":["^ ","\n","^\"I don't see why,\" I reply","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.^.g-4"},{"#f":5}],"c-13":["^ ",{"->":".^.^.c-12"},"\n",{"->":".^.^.^.g-4"},{"#f":5}],"c-14":["^ ","\n","^\"I'm sure you've handled worse,\" I reply casually","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.^.g-4"},{"#f":5}],"#f":5}],"g-4":["ev",{"VAR?":"teacup"},"/ev",[{"->":".^.b","c":true},{"b":["\n","ev",true,"/ev",{"VAR=":"drugged","re":true},"<>","^, sipping at my tea as though we were old friends","\n",{"->":".^.^.^.4"},null]}],"nop","\n","<>","^.","\n",["ev","str","^Watch him","/str","/ev",{"*":".^.c-15","flg":20},"ev","str","^Wait","/str","/ev",{"*":".^.c-16","flg":20},"ev","str","^Smile","/str",{"CNT?":".^.^.^.g-3.c-12"},"!","/ev",{"*":".^.c-17","flg":21},{"c-15":["\n","^His face is telling me nothing. I've seen Harris broad and full of laughter. Today he is tight, as much part of the military machine as the device in Hut 5.","\n",{"->":".^.^.^.^.g-6"},{"#f":5}],"c-16":["\n","^I wait to see how he'll respond.","\n",{"->":".^.^.^.^.g-6"},{"#f":5}],"c-17":["\n","^I try a weak smile. It is not returned.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":".^.^.^.^.g-6"},{"#f":5}],"#f":5,"#n":"g-5"}],{"#f":5}],"g-6":["^\"We need that component,\" he says.","\n",["ev",{"CNT?":"missing_reel"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n",{"->t->":"missing_reel"},{"->":"harris_demands_component"},{"->":".^.^.^.5"},null]}],"nop","\n",["ev","str","^Yes","/str","/ev",{"*":".^.c-18","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-19","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-20","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-21","flg":20},{"c-18":["\n","^\"Of course I do,\" I answer.","\n",{"->":".^.^.^.^.^.g-9"},{"#f":5}],"c-19":["\n","^\"No I don't. And I've got work to do...\"","\n","^\"Work that will be rather difficult for you to do, don't you think?\" Harris interrupts.","\n",{"->":".^.^.^.^.^.g-9"},{"#f":5}],"c-20":["\n",{"->":"here_at_bletchley_diversion"},{"->":".^.^.^.^.^.g-9"},{"#f":5}],"c-21":["^ ","\n",{"->":".^.^.c-19"},{"->":".^.^.^.^.^.g-9"},{"#f":5}],"#f":5,"#n":"g-8"}],{"#f":5,"#n":"g-7"}],{"#f":5}],"g-9":[{"->t->":"missing_reel"},{"->":"harris_demands_component"},{"#f":5}]}],{"#f":1}],"#f":1}],"missing_reel":[["ev","str","^The stolen component...","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Shrug","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["\n","^I shrug.","\n","ev","void","/ev","->->",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^The reel went missing from the Bombe this afternoon. The four of us were in the Hut, working on the latest German intercept. The results were garbage. It was Russell who found the gap in the plugboard.","\n",["^Any of us could have taken it; and no one else would have known its worth.","\n","ev","str","^Panic","/str",{"VAR?":"forceful"},0,"<=","/ev",{"*":".^.c-2","flg":21},"ev","str","^Calculate","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Deny","/str",{"VAR?":"evasive"},0,">=","/ev",{"*":".^.c-4","flg":21},{"c-2":["^ They will pin it on me. They need a scapegoat so that the work can continue. I'm a likely target. Weaker than the rest. ","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":".^.^.^.^.g-2"},{"#f":5}],"c-3":["^ My odds, then, are one in four. Not bad; although the stakes themselves are higher than I would like.","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.^.^.g-2"},{"#f":5}],"c-4":["^ But this is still a mere formality. The work will not stop. A replacement component will be made and we will all be put back to work. We are too valuable to shoot. ","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.^.^.g-2"},{"#f":5}],"#f":5,"#n":"g-1"}],{"#f":5}],"g-2":["ev","void","/ev","->->",{"#f":5}]}],{"#f":1}],"here_at_bletchley_diversion":[["^\"Here at Bletchley? Of course.\"","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","^\"Here, now,\" Harris corrects. \"We are not talking to everyone. I can imagine you might feel pretty sore about that. I can imagine you feeling picked on. ","ev",{"VAR?":"forceful"},0,"<","/ev",[{"->":".^.b","c":true},{"b":["^You're a sensitive soul.",{"->":".^.^.^.21"},null]}],"nop","^\"","\n",["ev",{"^->":"here_at_bletchley_diversion.0.24.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str","/ev",{"*":".^.^.c-0","flg":22},{"s":["^\"I'm fine",{"->":"$r","var":true},null]}],["ev",{"^->":"here_at_bletchley_diversion.0.25.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str",{"VAR?":"forceful"},0,"<","/ev",{"*":".^.^.c-1","flg":19},{"s":["^\"What do you mean by that?\"",{"->":"$r","var":true},null]}],["ev",{"^->":"here_at_bletchley_diversion.0.26.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str",{"VAR?":"forceful"},0,">=","/ev",{"*":".^.^.c-2","flg":23},{"s":["^\"Damn right",{"->":"$r","var":true},null]}],"ev","str","^Be honest","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-4","flg":20},{"c-0":["ev",{"^->":"here_at_bletchley_diversion.0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.24.s"},[{"#n":"$r2"}],"^,\" I reply. \"This is all some misunderstanding and the quicker we have it cleared up the better.\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","^\"I couldn't agree more.\" And then he comes right out with it, with an accusation.","\n",{"->":".^.^.done"},{"#f":5}],"c-1":["ev",{"^->":"here_at_bletchley_diversion.0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.25.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.done"},{"#f":5}],"c-2":["ev",{"^->":"here_at_bletchley_diversion.0.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.26.s"},[{"#n":"$r2"}],"^ I'm sore. Was it one of the others who put you up to this? Was it Hooper? He's always been jealous of me. He's...\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n","ev",true,"/ev",{"VAR=":"hooper_mentioned","re":true},"^The Commander moustache bristles as he purses his lips. \"Has he now? Of your achievements, do you think?\"","\n","^It's difficult not to shake the sense that he's ","ev",{"VAR?":"evasive"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^mocking",{"->":".^.^.^.28"},null]}],[{"->":".^.b"},{"b":["^simply humouring",{"->":".^.^.^.28"},null]}],"nop","^ me.","\n","^\"Or of your brain? Or something else?\"","\n",[["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-0","flg":22},{"s":["^\"Of my genius.",{"->":"$r","var":true},null]}],["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["^\"Of my standing.",{"->":"$r","var":true},null]}],"ev","str","^Evade","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"^ Hooper simply can't stand that I'm cleverer than he is. We work so closely together, cooped up in that Hut all day. It drives him to distraction. To worse.\"","\n","^\"You're suggesting Hooper would sabotage this country's future simply to spite you?\" Harris chooses his words like the military man he is, each lining up to create a ring around me.","\n",["ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ \t\t\t","\n","^\"","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^He's petty enough, certainly",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^I wouldn't put it past him",{"->":".^.^.^.10"},null]}],"nop","^. He's a creep.\" ","ev",{"VAR?":"teacup"},"/ev",[{"->":".^.b","c":true},{"b":["^ I set the teacup down.",{"->":".^.^.^.17"},null]}],[{"->":".^.b"},{"b":["^I wipe a hand across my forehead.",{"->":".^.^.^.17"},null]}],"nop","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n","ev",false,"/ev",{"VAR=":"teacup","re":true},{"->":".^.^.suggest_its_a_lie"},{"#f":5}],"c-1":["^ \t\t\t","\n","^\"No, ","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^of course not",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^I suppose not",{"->":".^.^.^.10"},null]}],"nop","^.\" ","ev",{"VAR?":"teacup"},"/ev",[{"->":".^.b","c":true},{"b":["^I put the teacup back down on the table",{"->":".^.^.^.17"},null]}],[{"->":".^.b"},{"b":["^I push the teacup around on its base",{"->":".^.^.^.17"},null]}],"nop","^.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","ev",false,"/ev",{"VAR=":"teacup","re":true},{"->":".^.^.suggest_its_a_lie"},{"#f":5}],"c-2":["^ \t\t","\n","^\"I don't know what I'm suggesting. I don't understand what's going on.\"","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n","^\"But of course you do.\" Harris narrows his eyes.","\n",{"->":".^.^.^.^.^.^.done"},{"->":".^.^.suggest_its_a_lie"},{"#f":5}],"suggest_its_a_lie":["^\"All I can say is, ever since I arrived here, he's been looking to ways to bring me down a peg. I wouldn't be surprised if he set this whole affair up just to have me court—martialled.\"","\n","^\"We don't court—martial civilians,\" Harris replies. \"Traitors are simply hung at her Majesty's pleasure.\"","\n",["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-0.10.suggest_its_a_lie.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str","/ev",{"*":".^.^.c-3","flg":22},{"s":["^\"Quite right",{"->":"$r","var":true},null]}],["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-0.10.suggest_its_a_lie.5.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str","/ev",{"*":".^.^.c-4","flg":22},{"s":["^\"I'm no traitor",{"->":"$r","var":true},null]}],"ev","str","^Lie","/str","/ev",{"*":".^.c-5","flg":20},{"c-3":["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-0.10.suggest_its_a_lie.c-3.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"^,\" I answer smartly.","\n",{"->":".^.^.^.g-0"},{"#f":5}],"c-4":["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-0.10.suggest_its_a_lie.c-4.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.5.s"},[{"#n":"$r2"}],"^,\" I answer","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^smartly",{"->":".^.^.^.14"},null]}],[{"->":".^.b"},{"b":["^, voice quivering. \"For God's sake!\"",{"->":".^.^.^.14"},null]}],"nop","\n",{"->":".^.^.^.g-0"},{"#f":5}],"c-5":["^ ",{"->":".^.^.c-4"},"\n",{"->":".^.^.^.g-0"},{"#f":5}],"#f":5}],"g-0":["^He stares back at me.","\n",{"->":".^.^.^.^.^.^.done"},{"#f":5}]}],{"#f":5}],"c-1":["ev",{"^->":"here_at_bletchley_diversion.0.c-2.33.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"^ My reputation.\" ","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^I'm aware of how arrogant I must sound but I plough on all the same.",{"->":".^.^.^.14"},null]}],[{"->":".^.b"},{"b":["^I don't like to talk of myself like this, but I carry on all the same.",{"->":".^.^.^.14"},null]}],"nop","^ \"Hooper simply can't bear knowing that, once all this is over, I'll be the one receiving the knighthood and he...\"","\n","^\"No—one will be getting a knighthood if the Germans make landfall,\" Harris answers sharply. He casts a quick eye to the door of the Hut to check the latch is still down, then continues in more of a murmur: \"Not you and not Hooper. Now answer me.\"","\n","^For the first time since the door closed, I wonder what the threat might be if I do not.","\n",{"->":".^.^.^.^.done"},{"#f":5}],"c-2":["^ \t\t\t\t","\n","ev",false,"/ev",{"VAR=":"teacup","re":true},"ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n","^\"How should I know?\" I reply, defensively. ","ev",{"VAR?":"teacup"},"/ev",[{"->":".^.b","c":true},{"b":["^I set the teacup back on the table.",{"->":".^.^.^.17"},null]}],"nop","^ ",{"->":".^.^.c-0.10.suggest_its_a_lie"},"\n",{"->":".^.^.^.^.done"},{"#f":5}]}],{"#f":5}],"c-3":["^ \t",{"->":".^.^.c-2"},"\n",{"->":".^.^.done"},{"#f":5}],"c-4":["^ \t\t",{"->":".^.^.c-0"},"\n",{"->":".^.^.done"},{"#f":5}],"done":[{"->":"harris_demands_component"},{"#f":5}]}],{"#f":1}],"harris_demands_component":[["^\"","ev",{"CNT?":"here_at_bletchley_diversion"},"/ev",[{"->":".^.b","c":true},{"b":["^Please",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["^So",{"->":".^.^.^.6"},null]}],"nop","^. Do you have it?\" Harris is ","ev",{"VAR?":"forceful"},3,">","/ev",[{"->":".^.b","c":true},{"b":["^sweating slightly",{"->":".^.^.^.15"},null]}],[{"->":".^.b"},{"b":["^wasting no time",{"->":".^.^.^.15"},null]}],"nop","^: Bletchley is his watch. \"Do you know where it is?\"","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["\n","^\"I do.\"","\n",{"->":"admitted_to_something"},{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ \"I have no idea.\" ","\n",{"->":".^.^.silence"},{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ \t\t",{"->":".^.^.c-1"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-3":["^ \t\t","\n","^\"The component?\"","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","^\"Don't play stupid,\" he replies. \"","ev",{"CNT?":"missing_reel"},"!","/ev",[{"->":".^.b","c":true},{"b":["^The component that went missing this afternoon. ",{"->":".^.^.^.22"},null]}],"nop","^Where is it?\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["ev",{"CNT?":"missing_reel"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n",{"->t->":"missing_reel"},{"->":".^.^.^.5"},null]}],"nop","\n","ev","str","^Co-operate","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^Delay","/str","/ev",{"*":".^.c-5","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-6","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-7","flg":20},{"c-4":["^ \"I know where it is.\"","\n",{"->":"admitted_to_something"},{"->":".^.^.^.silence"},{"#f":5}],"c-5":["^ \"I know nothing about it.\" My voice shakes","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^ with anger",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["^; I'm unaccustomed to facing off against men with holstered guns",{"->":".^.^.^.8"},null]}],"nop","^. ","\n",{"->":".^.^.^.silence"},{"#f":5}],"c-6":["^ ",{"->":".^.^.c-5"},"\n",{"->":".^.^.^.silence"},{"#f":5}],"c-7":["^ ","\n","^\"I don't know what gives you the right to pick on me. ","ev",{"VAR?":"forceful"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^I demand a lawyer.",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^I want a lawyer.",{"->":".^.^.^.10"},null]}],"nop","^\"","\n","^\"This is time of war,\" Harris answers. \"And by God, if I have to shoot you to recover the component, I will. Understand?\" He points at the mug, ",{"->":".^.^.^.silence.drinkit"},"\n",{"->":".^.^.^.silence"},{"#f":5}],"#f":5}],"silence":["^There's an icy silence. ","ev",{"VAR?":"forceful"},2,">","/ev",[{"->":".^.b","c":true},{"b":["^I've cracked him a little.",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["ev",{"VAR?":"evasive"},2,">","/ev",[{"->":".^.b","c":true},{"b":["^He's tiring of my evasiveness.",{"->":".^.^.^.6"},null]}],"nop",{"->":".^.^.^.8"},null]}],"nop","\n",["^\"Now drink your tea and talk.\"","\n","ev","str","^Drink","/str",{"VAR?":"teacup"},"/ev",{"*":".^.c-8","flg":21},"ev","str","^Put the cup down","/str",{"VAR?":"teacup"},"/ev",{"*":".^.c-9","flg":21},"ev","str","^Take the cup","/str",{"VAR?":"teacup"},"!","/ev",{"*":".^.c-10","flg":21},"ev","str","^Don't take it","/str",{"VAR?":"teacup"},"!","/ev",{"*":".^.c-11","flg":21},{"c-8":["^ \t\t\t",{"->":".^.^.c-10.2.drinkfromcup"},"\n",{"->":".^.^.^.^.g-1"},{"#f":5}],"c-9":["^ ","\n","^I set the cup carefully down on the table once more.","\n","ev",false,"/ev",{"VAR=":"teacup","re":true},"ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.c-11.10.whatsinit"},{"->":".^.^.^.^.g-1"},{"#f":5}],"c-10":["^ ","\n",[["^I lift the cup ","ev",{"VAR?":"teacup"},"/ev",[{"->":".^.b","c":true},{"b":["^to my lips ",{"->":".^.^.^.5"},null]}],"nop","^and sip. He waits for me to swallow before speaking again.","\n","ev",true,"/ev",{"VAR=":"drugged","re":true},"ev",true,"/ev",{"VAR=":"teacup","re":true},{"->":".^.^.^.^.^.^.g-1"},{"#f":5,"#n":"drinkfromcup"}],null],{"#f":5}],"c-11":["^ ","\n","^I leave the cup where it is.","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",[["^\"Why?\" I ask coldly. \"What's in it?\"","\n",{"->":".^.^.^.^.^.^.g-1"},{"#f":5,"#n":"whatsinit"}],null],{"#f":5}],"#f":5,"#n":"drinkit"}],{"#f":5}],"g-1":["^\"Lapsang Souchong,\" he ","ev",{"CNT?":".^.^.silence.drinkit.c-10.2.drinkfromcup"},"/ev",[{"->":".^.b","c":true},{"b":["^remarks",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["^replies",{"->":".^.^.^.6"},null]}],"nop","^, placing his own cup back on the table untouched. \"Such a curious flavour. It might almost not be tea at all. You might say it hides a multitude of sins. As do you. Isn't that right?\"","\n","ev","str","^Agree","/str","/ev",{"*":".^.c-12","flg":20},"ev","str","^Disagree","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-13","flg":21},"ev","str","^Disagree","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-14","flg":21},"ev","str","^Lie","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-15","flg":21},"ev","str","^Lie","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-16","flg":21},"ev","str","^Evade","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-17","flg":21},"ev","str","^Evade","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-18","flg":21},{"c-12":["^ ","\n","^\"I suppose so,\" I reply. \"I've done things I shouldn't have done.\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":"harris_presses_for_details"},{"#f":5}],"c-13":["\n","^\"I've done nothing that I'm ashamed of.\"","\n",{"->":"harris_asks_for_theory"},{"#f":5}],"c-14":["^ ","\n","^I open my mouth to disagree, but the words I want won't come. It is like Harris has taken a screwdriver to the sides of my jaw.","\n",{"->":"admitted_to_something.ive_done_things"},{"#f":5}],"c-15":["^ \t",{"->":".^.^.c-14"},"\n",{"#f":5}],"c-16":["^ \t",{"->":".^.^.c-13"},"\n",{"#f":5}],"c-17":["^ ",{"->":".^.^.c-14"},"\n",{"#f":5}],"c-18":["^ ","\n","^\"None of us are blameless, Harris. ","ev",{"VAR?":"forceful"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^But you're not my priest and I'm not yours",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^But I've done nothing to deserve this treatment",{"->":".^.^.^.10"},null]}],"nop","^. Now, please. Let me go. I'll help you find this damn component, of course I will.\"","\n","^He appears to consider the offer.","\n",{"->":"harris_asks_for_theory"},{"#f":5}],"#f":5}]}],{"#f":1}],"harris_presses_for_details":[["^\"You mean you've left yourself open,\" Harris answers. \"To pressure. Is that what you're saying?\"","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^No","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-2","flg":21},"ev","str","^Evade","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-3","flg":21},"ev","str","^Evade","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-4","flg":21},{"c-0":["^ ",{"->":".^.^.^.admit_open_to_pressure"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"I'm not saying anything of the sort,\" I snap back. \"What is this, Harris? You're accusing me of treachery but I don't see a shred of evidence for it! Why don't you put your cards on the table?\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^I shake my head violently, to say no, that's not it, but whatever is wrong with tongue is wrong with neck too. I look across at the table at Harris' face and realise with a start how sympathetic he is. Such a kind, generous man. How can I hold anything back from him?","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","^I take another mouthful of the bitter, strange—tasting tea before answering.","\n",{"->":".^.^.^.admit_open_to_pressure"},{"->":".^.^.g-0"},{"#f":5}],"c-3":["^ ","\n","^\"You're the one applying pressure here,\" I answer ","ev",{"VAR?":"forceful"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^smartly",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^somewhat miserably",{"->":".^.^.^.10"},null]}],"nop","^. \"I'm just waiting until you tell me what is really going on.\"","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.g-0"},{"#f":5}],"c-4":["^ \t\t\t\t ","\n","^\"We're all under pressure here.\"","\n","^He looks at me with pity. ",{"->":"harris_has_seen_it_before"},"\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"It's simple enough,\" Harris says. ",{"->":"harris_has_seen_it_before"},"\n",{"#f":5}]}],{"admit_open_to_pressure":["^\"That's it,\" I reply. \"There are some things... which a man shouldn't do.\"","\n","ev",true,"/ev",{"VAR=":"admitblackmail","re":true},"^Harris doesn't stiffen. Doesn't lean away, as though my condition might be infectious. I had thought they trained them in the army to shoot my kind on sight.","\n","^He offers no sympathy either. He nods, once. His understanding of me is a mere turning cog in his calculations, with no meaning to it.","\n",{"->":"harris_has_seen_it_before"},{"#f":1}],"#f":1}],"admitted_to_something":[["ev",{"VAR?":"drugged"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^Harris stares back at me. ","ev",{"VAR?":"evasive"},0,"==","/ev",[{"->":".^.b","c":true},{"b":["^He cannot have expected it to be so easy to break me.",{"->":".^.^.^.8"},null]}],"nop","\n",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["\n","^Harris smiles with satisfaction, as if your willingness to talk was somehow his doing.","\n",{"->":".^.^.^.6"},null]}],"nop","\n","^\"I see.\"","\n","^There's a long pause, like the delay between feeding a line of cypher into the Bombe and waiting for its valves to warm up enough to begin processing.","\n","^\"You want to explain that?\"","\n","ev","str","^Explain","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't explain","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^Lie","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-2","flg":21},"ev","str","^Evade","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-3","flg":21},"ev","str","^Say nothing","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-4","flg":21},{"c-0":["^ ","\n","^I pause a moment, trying to choose my words. To just come out and say it, after a lifetime of hiding... that is a circle I cannot square.","\n",["ev","str","^Explain","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Say nothing","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-1","flg":21},"ev","str","^Lie","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-2","flg":21},{"c-0":["^ \t",{"->":".^.^.^.^.^.ive_done_things"},"\n",{"#f":5}],"c-1":["^ \t",{"->":".^.^.^.^.c-4"},"\n",{"#f":5}],"c-2":["^ \t",{"->":"claim_hooper_took_component"},"\n",{"#f":5}]}],{"#f":5}],"c-1":["\n","^\"There's nothing to explain,\" I reply stiffly. ",{"->":".^.^.^.i_know_where"},"\n",{"#f":5}],"c-2":["^ ",{"->":"claim_hooper_took_component"},"\n",{"#f":5}],"c-3":["\n","^\"Explain what you should be doing, do you mean, rather than bullying me? Certainly.\" I fold my arms. ",{"->":".^.^.^.i_know_where"},"\n",{"#f":5}],"c-4":["\n","^I fold my arms, intended firmly to say nothing. But somehow, watching Harris' face, I cannot bring myself to do it. I want to confess. I want to tell him everything I can, to explain myself to him, to earn his forgiveness. The sensation is so strong my will is powerless in the face of it.","\n","^Something is wrong with me, I am sure of it. There is a strange, bitter flavour on my tongue. I taste it as words start to form.","\n",{"->":".^.^.^.ive_done_things"},{"#f":5}]}],{"i_know_where":["^\"I know where your component is because it's obvious where your component is. That doesn't mean I took it, just because I can figure out a simple problem, any more than it means I'm a German spy because I can crack their codes.\"","\n",{"->":"harris_asks_for_theory"},{"#f":1}],"ive_done_things":["^\"I've done things,\" I begin","ev",{"CNT?":"harris_demands_component.0.g-1.c-14"},"/ev",[{"->":".^.b","c":true},{"b":["^ helplessly",{"->":".^.^.^.5"},null]}],"nop","^. \"Things I didn't want to do. I tried not to. But in the end, it felt like cutting off my own arm to resist.\"","\n",{"->":"harris_presses_for_details"},{"#f":1}],"#f":1}],"harris_asks_for_theory":[["^\"Tell me, then,\" he asks. \"What's your theory? You're a smart fellow — as smart as they come around here, and that's saying something. What's your opinion on the missing component? Accident, perhaps? Or do you blame one of the other men? ","ev",{"VAR?":"hooper_mentioned"},"/ev",[{"->":".^.b","c":true},{"b":["^Hooper?",{"->":".^.^.^.5"},null]}],"nop","^\"","\n","ev","str","^Blame no—one","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Blame someone","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n",{"->":".^.^.^.an_accident"},{"#f":5}],"c-1":["^ ",{"->":"claim_hooper_took_component"},"\n",{"#f":5}]}],{"an_accident":[["^\"An accident, naturally.\" I risk a smile. \"That damned machine is made from spare parts and string. Even these Huts leak when it rains. It wouldn't take more than one fellow to trip over a cable to shake out a component. Have you tried looking under the thing?\"","\n","^\"Do you believe we haven't?\"","\n","^In a sudden moment I understand that his reply is a threat.","\n","^\"Now,\" he continues. \"Are you sure there isn't anything you want to tell me?\"","\n","ev","str","^Co-operate","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Evade","/str",{"VAR?":"evasive"},0,">","/ev",{"*":".^.c-1","flg":21},{"c-0":["\n","^\"All right.\" With a sigh, your defiance collapses. \"If you're searched my things then I suppose you've found ","ev",{"VAR?":"evasive"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^ what you need",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["^my letters. Haven't you? In fact, if you haven't, don't tell me",{"->":".^.^.^.9"},null]}],"nop","^.","\n","ev",true,"/ev",{"VAR=":"admitblackmail","re":true},"^Harris nods once.","\n","<>","^ ",{"->":"harris_has_seen_it_before"},"\n",{"#f":5}],"c-1":["^ \"Only that you're being unreasonable, and behaving like a swine.\"","\n","^\"You imbecile,\" Harris replies, with sudden force. He is half out of his chair. \"You know the situation as well as I do. Why the fencing? The Hun are poised like rats, ready to run all over this country. They'll destroy everything. You understand that, don't you? You're not so locked up inside your crossword puzzles that you don't see that, are you? This machine we have here — you men — you are the best and only hope this country has. God help her.\"","\n","ev",true,"/ev",{"VAR=":"losttemper","re":true},"^I sit back, startled by the force of his outburst. His carefully sculpted expression has curled to angry disgust. He really does hate me, I think. He'll have my blood for the taste of it.","\n",["ev","str","^Placate","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Mock","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Dismiss","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["\n","^\"Now steady on,\" I reply, gesturing for him to be calm.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"I can imagine how being surrounded by clever men is pretty threatening for you, Commander,\" I reply with a sneer. \"They don't train you to think in the Armed Forces.\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["\n","^\"Then I'll be going, on and getting on with my job of saving her, shall I?\" I even rise half to my feet, before he slams the tabletop.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"Talk,\" Harris demands. \"Talk now. Tell me where you've hidden it or who you passed it to. Or God help me, I'll take your wretched pansy body to pieces looking for it.\"","\n",{"->":"harris_demands_you_speak"},{"#f":5}]}],{"#f":5}]}],{"#f":1}],"#f":1}],"harris_has_seen_it_before":[["^\"I've seen it before. A young man like you — clever, removed. The kind that doesn't go to parties. Who takes himself too seriously. Who takes things too far.\"","\n","^He slides his thumb between two fingers.","\n","^\"Now they own you.\"","\n","ev","str","^Agree","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Disagree","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-2","flg":21},"ev","str","^Apologise","/str",{"VAR?":"drugged"},{"VAR?":"forceful"},0,"<","&&","/ev",{"*":".^.c-3","flg":21},{"c-0":["^ ","\n","^\"What could I do?\" I'm shaking now. The night is cold and the heat—lamp in the Hut has been removed. \"","ev",{"VAR?":"forceful"},2,">","/ev",[{"->":".^.b","c":true},{"b":["^I won't",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^I don't want to",{"->":".^.^.^.10"},null]}],"nop","^ go to prison.\"","\n","^\"Smart man,\" he replies. \"You wouldn't last.","\n",{"->":".^.^.tell_me_now"},{"#f":5}],"c-1":["^ ","\n","^\"I can still fix this.\"","\n","^Harris shakes his head. \"You'll do nothing. This is beyond you now. You may go to prison or may go to firing squad - or we can change your name and move you somewhere where your indiscretions can't hurt you. But right now, none of that matters. What happens to you doesn't matter. All that matters is where that component is.","\n",{"->":".^.^.tell_me_now"},{"#f":5}],"c-2":["^ ","\n","^\"I wanted to tell you,\" I tell him. \"I thought I could find out who they were. Lead you to them.\"","\n","^Harris looks at me with contempt. \"You wretch. You'll pay for what you've done to this country today. If a single man loses his life because of your pride and your perversions then God help your soul.","\n",{"->":".^.^.tell_me_now"},{"#f":5}],"c-3":["\n","^\"Harris, I...\"","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n","^\"Stop it,\" he interrupts. \"There's no jury here to sway. And there's no time.","\n",{"->":".^.^.tell_me_now"},{"#f":5}],"tell_me_now":["<>","^ So why don't you tell me, right now. Where is it?\"","\n",{"->":"harris_demands_you_speak"},{"#f":5}]}],{"#f":1}],"harris_demands_you_speak":[["^His eyes bear down like carbonised drill—bits.","\n","ev","str","^Confess","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Dissemble","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^Dissemble","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-2","flg":21},{"c-0":["^ ","\n","ev",{"VAR?":"forceful"},1,">","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"You want me to tell you what happened? You'll be disgusted.\"","\n",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["\n","^\"All right. I'll tell you what happened.\" And never mind my shame.","\n",{"->":".^.^.^.9"},null]}],"nop","\n","^\"I can imagine how it starts,\" he replies.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ",{"->":"claim_hooper_took_component"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["\n","^My plan now is to blame Hooper, but I cannot seem to tell the story. Whatever they put in my tea, it rules my tongue. ","ev",{"VAR?":"forceful"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^I fight it as hard as I can but it does no good.",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["^I am desperate to tell him everything. I am weeping with shame.",{"->":".^.^.^.9"},null]}],"nop","\n","ev",{"^var":"forceful","ci":-1},{"f()":"lower"},"pop","/ev","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":[{"->":"i_met_a_young_man"},{"#f":5}]}],{"#f":1}],"i_met_a_young_man":[["ev","str","^Talk","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n","^\"There was a young man. I met him in the town. A few months ago now. We got to talking. Not about work. And I used my cover story, but he seemed to know it wasn't true. That got me wondering if he might be one of us.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Harris is not letting me off any more.","\n","^\"You seriously entertained that possibility?\"","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-3","flg":20},{"c-1":["\n","^\"Yes, I considered it. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-2":["^ ","\n","^\"No. Not for more than a moment, of course. Everyone here is marked out by how little we would be willing to say about it.\"","\n","^\"Only you told this young man more than a little, didn't you?\"","\n","^I nod. \"","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-3":["^ ","\n","^\"I was quite certain, after a while. After we'd been talking. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^He seemed to know all about me. He... he was quite enchanted by my achievements.\"","\n","^The way Harris is staring I expect him to strike me, but he does not. He replies, \"I can see how that must have been attractive to you,\" with such plain—spokeness that I think I must have misheard.","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^No","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-5","flg":21},"ev","str","^No","/str",{"VAR?":"drugged"},"/ev",{"*":".^.c-6","flg":21},"ev","str","^Lie","/str",{"VAR?":"drugged"},"!","/ev",{"*":".^.c-7","flg":21},{"c-4":["^ \"It's a lonely life in this place,\" I reply. \"Lonely - and still one never gets a moment to oneself.\"","\n","^\"That's how it is in the Service,\" Harris answers.","\n",["ev","str","^Argue","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Agree","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ \"I'm not in the Service.\"","\n","^Harris shakes his head. \"Yes, you are.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ \"Perhaps. But I didn't choose this life.\" ","\n","^Harris shakes his head. \"No. And there's plenty of others who didn't who are suffering far worse.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Then he waves the thought aside.","\n",{"->":".^.^.^.^.^.g-2"},{"#f":5}]}],{"#f":5}],"c-5":["^ \"The boy was a pretty simpleton. Quite inferior. His good opinion meant nothing to be. Harris, do not misunderstand. I was simply after his body.\"","\n","ev",{"^var":"evasive","ci":-1},{"f()":"raise"},"pop","/ev","\n","^Harris, to his credit, doesn't flinch; but I can see he will have nightmares of this moment later tonight. I'm tempted to reach out and take his hand to worsen it for him.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-6":["^ ","\n","^\"It wasn't,\" I reply. \"But I doubt you'd understand.\"","\n","^He simply nods.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-7":["^ ",{"->":".^.^.c-5"},"\n",{"->":".^.^.^.g-2"},{"#f":5}],"#f":5}],"g-2":["^\"Go on with your confession.\"","\n",["ev",{"CNT?":".^.^.^.g-1.c-5"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^That gives me pause. I hadn't thought of it as such. But I suppose he's right. I am about to admit what I did.","\n",{"->":".^.^.^.5"},null]}],"nop","\n","^\"There's not much else to say. I took the part from Bombe computing device. You seem to know that already. I had to. He was going to expose me if I didn't.\"","\n","^\"This young man was blackmailing you over your affair?\"","\n","ev",{"VAR?":"drugged"},"/ev",{"temp=":"harris_thinks_youre_drugged"},"ev",{"VAR?":"drugged"},"/ev",[{"->":".^.b","c":true},{"b":["\n","ev",false,"/ev",{"VAR=":"drugged","re":true},"^As Harris speaks I find myself suddenly sharply aware, as if waking from a long sleep. The table, the corrugated walls of the hut, everything seems suddenly more tangible than a moment before.","\n","^Whatever it was they put in my drink is wearing off.","\n",{"->":".^.^.^.19"},null]}],"nop","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-8","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-9","flg":20},"ev","str","^Tell the truth","/str","/ev",{"*":".^.c-10","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-11","flg":20},{"c-8":["^ ","\n","^\"Yes. I suppose he was their agent. I should have realised but I didn't. Then he threatened to tell you. I thought you would have me locked up: I couldn't bear the thought of it. I love working here. I've never been so happy, so successful, anywhere before. I didn't want to lose it.\"","\n","^\"So what did you do with the component?\" Harris talks urgently. He grips his gloves tightly in one hand, perhaps prepared to lift them and strike if it is required. \"Have you passed it to this man already? Have you left it somewhere for him to find?\"","\n",["ev","str","^I have it","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^I don't have it","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Tell the truth","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["^ \t","\n","^\"I still have it. Not on me, of course. ",{"->":"reveal_location_of_component"},"\n",{"#f":5}],"c-1":["^ \t",{"->":".^.^.^.^.^.^.^.i_dont_have_it"},"\n",{"#f":5}],"c-2":["^ \t\t\t\t\t\t\t",{"->":".^.^.c-1"},"\n",{"#f":5}],"c-3":["^ \t\t\t\t",{"->":".^.^.c-0"},"\n",{"#f":5}]}],{"#f":5}],"c-9":["^ ","\n","^\"No, Harris. The young man wasn't blackmailing me.\" I take a deep breath. \"It was Hooper.\"","\n","ev",{"VAR?":"hooper_mentioned"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Hooper!\" Harris exclaims, in surprise. ","ev",{"VAR?":"harris_thinks_youre_drugged"},"/ev",[{"->":".^.b","c":true},{"b":["^He does not doubt me for a moment.",{"->":".^.^.^.6"},null]}],"nop","\n",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["\n","^\"Now look here,\" Harris interrupts. \"Don't start that again.\"","\n",{"->":".^.^.^.10"},null]}],"nop","\n","^\"It's the truth, Harris. If I'm going to jail, so be it, but I won't hang at Traitor's Gate. Hooper was the one who told the boy about our work. Hooper put the boy on to me. ","ev",{"VAR?":"forceful"},2,"<","/ev",[{"->":".^.b","c":true},{"b":["^I should have realised, of course. These things don't happen by chance. I was a fool to think they might.",{"->":".^.^.^.19"},null]}],"nop","^ And then, once he had me compromised, he demanded I steal the part from the machine.\"","\n","ev",true,"/ev",{"VAR=":"revealedhooperasculprit","re":true},"^\"Which you did.\" Harris leans forward. \"And then what? You still have it? You've stashed it somewhere?\"","\n",["ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["^ ","\n","^\"Yes. I only had a moment. ",{"->":"reveal_location_of_component"},"\n",{"#f":5}],"c-1":["^ ",{"->":".^.^.^.^.^.^.^.passed_onto_hooper"},"\n",{"#f":5}],"c-2":["^ \t\t\t",{"->":".^.^.c-1"},"\n",{"#f":5}],"c-3":["^ \t\t","\n","^\"I can't remember.\"","\n","^He draws his gun and lays it lightly on the field table.","\n","^\"I'm sorry to threaten you, friend. But His Majesty needs that brain of yours, and that brain alone. There are plenty of other parts to you that our country could do better without. Now I'll ask you again. Did you hide the component?\"","\n",["ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["^ ",{"->":".^.^.^.^.c-0"},"\n",{"#f":5}],"c-1":["^ ","\n","^\"Very well then.\" I swallow nervously, to make it look more genuine. ",{"->":"i_met_a_young_man.passed_onto_hooper"},"\n",{"#f":5}],"c-2":["^ ",{"->":".^.^.c-1"},"\n",{"#f":5}],"c-3":["^ ",{"->":"i_met_a_young_man.i_dont_have_it"},"\n",{"#f":5}]}],{"#f":5}]}],{"#f":5}],"c-10":["^ \t",{"->":".^.^.c-8"},"\n",{"#f":5}],"c-11":["^ \t\t\t\t",{"->":".^.^.c-9"},"\n",{"#f":5}],"#f":5,"#n":"paused"}],{"#f":5}]}],{"i_dont_have_it":[["^\"I don't have it any more. I passed it through the fence to my contact straight after taking it, before it was discovered to be missing. It would have been idiocy to do differently. It's long gone, I'm afraid.\"","\n","^\"You fool, Manning,\" Harris curses, getting quickly to his feet. \"You utter fool. Do you suppose you will be any better off living under Hitler? It's men like you who will get us all killed. Men too feeble, too weak in their hearts to stand up and take a man's responsibility for the world. You're happier to stay a child all your life and play with your little childish toys.\"","\n","ev","str","^Answer back","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Say nothing","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["\n","^\"Really, Commander,\" I reply. \"It rather sounds like you want to spank me.\"","\n","^\"For God's sake,\" he declares with thick disgust, then swoops away out of the room.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^I say nothing. It's true, isn't it? I can't deny that I know there is a world out there, a complicated world of pain and suffering. And I can't deny that I don't think about it a moment longer than I have to. What use is thinking on a problem that cannot be solved? It is precisely our ability to avoid such endless spirals that makes us human and not machine.","\n","^\"God have mercy on your soul,\" Harris says finally, as he gets to his feet and heads for the door. \"I fear no—one else will.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":[{"->":"left_alone"},{"#f":5}]}],{"#f":1}],"passed_onto_hooper":[["ev",true,"/ev",{"VAR=":"hooper_mentioned","re":true},"^\"No. I passed it on to Hooper.\"","\n","^\"I see. And what did he do with it?\"","\n","ev","str","^Evade","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Tell the truth","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^\"I don't know.\"","\n","^\"You can do better than that. Remember, there's a hangman's noose waiting for traitors.\"","\n",["ev","str","^Theorise","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Shrug","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"Well, then,\" I answer, nervously. \"What would he do? Either get rid of it straight away — or if that wasn't possible, which it probably wouldn't be, since he'd have to arrange things with his contacts — so most likely, he'd hide it somewhere and wait, until you had the rope around my neck and he could be sure he was safe.\"","\n",{"->":"claim_hooper_took_component.harris_being_convinced"},{"#f":5}],"c-1":["^ ",{"->":"claim_hooper_took_component.its_your_problem"},"\n",{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n","^\"I don't think Hooper could have planned this in advance. So he'd need to get word to whoever he's working with, and that would take time. So I think he would have hidden it somewhere, and be waiting to make sure I soundly take the fall. That way, if anything goes wrong, he can arrange for the part to be conveniently re—found.\"","\n",{"->":"claim_hooper_took_component.harris_being_convinced"},{"#f":5}],"c-2":["\n","^\"I'm sure I saw him this evening, talking to someone by the fence on the woodland side of the compound. He's probably passed it on already. You'll have to ask him.\"","\n",{"->":"claim_hooper_took_component.harrumphs"},{"#f":5}]}],{"#f":1}],"#f":1}],"claim_hooper_took_component":[["^\"I saw Hooper take it.\"","\n","ev",true,"/ev",{"VAR=":"hooper_mentioned","re":true},"ev",{"VAR?":"losttemper"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Did you?\"","\n","^The worst of his rage is passing; he is now moving into a kind of contemptuous despair. I can imagine him wrapping up our interview soon, leaving the hut, locking the door, and dropping the key down the well in the yard.","\n","^And why wouldn't he? With my name tarnished they will not let me back to work on the Bombe — if there is the slightest smell of treachery about my name I would be lucky not be locked up for the remainder of the war.","\n",{"->":".^.^.^.11"},null]}],[{"->":".^.b"},{"b":["\n","^\"I see.\" He is starting to lose his patience. I have seen Harris angry a few times, with lackeys and secretaries. But never with us. With the 'brains' he has always been cautious, treating us like children.","\n","^And now I see that, like a father, he wants to smack us when we disobey him.","\n",{"->":".^.^.^.11"},null]}],"nop","\n","^\"Just get to the truth, man. Every minute matters.\"","\n","ev","str","^Persist with this","/str",{"VAR?":"admitblackmail"},"/ev",{"*":".^.c-0","flg":21},"ev","str","^Tell the truth","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Persist with this","/str",{"VAR?":"admitblackmail"},"!","/ev",{"*":".^.c-2","flg":21},{"c-0":["\n","^\"I know what you're thinking. If I've transgressed once then I must be guilty of everything else... But I'm not. We were close to cracking the 13th's intercept. We were getting correlations in the data. Then Hooper disappeared for a moment, and next minute the machine was down.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"Very well. I see there's no point in covering up. You know everything anyway.\"","\n","^Harris nods, and waits for me to continue.","\n",{"->":"i_met_a_young_man"},{"->":".^.^.g-0"},{"#f":5}],"c-2":["\n","^\"This is the truth.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I have become, somehow, an accustomed liar — the words roll easily off my tongue. Perhaps I am a traitor, I think, now that I dissemble as easily as one.","\n","^\"Go on,\" Harris says, giving me no indication of whether he believes my tale.","\n","ev","str","^Assert","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Imply","/str","/ev",{"*":".^.c-4","flg":20},{"c-3":["^ \"I saw him take it,\" I continue. \"Collins was outside having a cigarette. Peterson was at the table. But I was at the front of the machine. I saw Hooper go around the side. He leant down and pulled something free. I even challenged him. I said, 'What's that? Someone put a nail somewhere they shouldn't have?' He didn't reply.\"","\n","^Harris watches me for a long moment.","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-4":["^ \"At the moment the machine halted, Peterson was at the bench and Collins was outside having a smoke. I was checking the dip—switches. Hooper was the only one at the back of the Bombe. No—one else could have done it.\"","\n","^\"That's not quite the same as seeing him do it,\" Harris remarks.","\n",["ev","str","^Logical","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Persuasive","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Confident","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["\n","^\"When you have eliminated the impossible...\" I begin, but Harris cuts me off.","\n",{"->":".^.^.^.^.^.g-1"},{"#f":5}],"c-1":["^ ","\n","^\"You have to believe me.\"","\n","^\"We don't have to believe anyone,\" Harris returns. \"I will only be happy with the truth, and your story doesn't tie up. We know you've been leaving yourself open to pressure. We've been watching your activities for some time. But we thought you were endangering the reputation of this site; not risking the country herself. Perhaps I put too much trust in your intellectual pride.\"","\n","^He pauses for a moment, considering something. Then he continues:","\n","^\"It might have been Hooper. It might have been you. ",{"->":".^.^.^.^.^.we_wont_guess"},"\n",{"->":".^.^.^.^.^.g-1"},{"#f":5}],"c-2":["^ ","\n","^\"Ask the others,\" I reply, leaning back. \"They'll tell you. If they haven't already, that's only because they're protecting Hooper. Hoping he'll come to his senses and stop being an idiot. I hope he does too. And if you lock him up in a freezing hut like you've done me, I'm sure he will.\"","\n","^\"We have,\" Harris replies simply.","\n","^It's all I can do not to gape.","\n",{"->":".^.^.^.^.^.g-1.hoopers_hut_3"},{"->":".^.^.^.^.^.g-1"},{"#f":5}]}],{"#f":5}],"#f":5}],"g-1":["^\"We are left with two possibilities. You, or Hooper.\" The Commander pauses to smooth down his moustache. ","<>","\n",["^\"Hooper's in Hut 3 with the Captain, having a similar conversation.\"","\n",["ev",{"^->":"claim_hooper_took_component.0.g-1.hoopers_hut_3.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-5","flg":22},{"s":["^\"And the other men?",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.g-1.hoopers_hut_3.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-6","flg":22},{"s":["^\"Then you know I'm right.",{"->":"$r","var":true},null]}],{"c-5":["ev",{"^->":"claim_hooper_took_component.0.g-1.hoopers_hut_3.c-5.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"^ Do we have a hut each? Are there enough senior officers to go round?\"","\n","^\"Collins was outside when it happened, and Peterson can't get round the machine in that chair of his,\" Harris replies. \"That leaves you and Hooper.","\n",{"->":".^.^.^.^.we_wont_guess"},{"#f":5}],"c-6":["ev",{"^->":"claim_hooper_took_component.0.g-1.hoopers_hut_3.c-6.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"^ You knew all along. Why did you threaten me?\"","\n","^\"All we know is that we have a traitor, holding the fate of the country in his hands.","\n",{"->":".^.^.^.^.we_wont_guess"},{"#f":5}],"#f":5,"#n":"hoopers_hut_3"}],{"#f":5}],"we_wont_guess":["<>","^ We're not in the business of guessing here at Bletchley. We are military intelligence. We get answers.\" Harris points a finger. \"And if that component has left these grounds, then every minute is critical.\"","\n","ev","str","^Co-operate","/str","/ev",{"*":".^.c-7","flg":20},"ev","str","^Block","/str","/ev",{"*":".^.c-8","flg":20},{"c-7":["^ ","\n","^\"I'd be happy to help,\" I answer, leaning forwards. \"I'm sure there's something I could do.\"","\n","^\"Like what, exactly?\"","\n",[["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^\"Put me in with Hooper.\"",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["^\"Tell Hooper I've confessed.",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.^.^.^.^.putmein"},{"#f":5}],"c-1":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"^ Better yet. Let him see you marching me off in handcuffs. Then let him go, and see what he does. Ten to one he'll go straight to wherever he's hidden that component and his game will be up.\"","\n","^Harris nods slowly, chewing over the idea. It isn't a bad plan even — except, of course, Hooper has not hidden the component, and won't lead them anywhere. But that's a problem I might be able to solve once I'm out of this place; and once they're too busy dogging Hooper's steps from hut to hut.","\n","^\"Interesting,\" the Commander muses. \"But I'm not so sure he'd be that stupid. And if he's already passed the part on, the whole thing will only be a waste of time.\"","\n",[["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-0","flg":22},{"s":["^\"Trust me. He hasn't.",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["^\"You're right. Let me talk to him",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-2","flg":18},{"s":["^\"You're right.\" ",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"^ If I know that man, and I do, he'll be wanting to keep his options open as long as possible. If the component's gone then he's in it up to his neck. He'll take a week at least to make sure he's escaped suspicion. Then he'll pass it on.\"","\n","^\"And if we keep applying pressure to him, you think the component will eventually just turn up?\"","\n",[["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-0","flg":22},{"s":["^\"Yes.",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^\"Or be thrown into the river.\" ",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"^ Probably under my bunk.\"","\n","^Harris smiles wryly. \"We'll know that for a fake, then. We've looked there already.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"\n","^\"Hmm.\" Harris chews his moustache thoughtfully. \"Well, that would put us in a spot, seeing as how we'd never know for certain. We'd have to be ready to change our whole approach just in case the part had got through to the Germans.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["<>","^ I don't mind telling you, this is a disaster, this whole thing. What I want is to find that little bit of mechanical trickery. I don't care where. In your luncheon box or under Hooper's pillow. Just somewhere, and within the grounds of this place.\"","\n",["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.g-0.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-2","flg":22},{"s":["^\"Then let him he think he's off the hook.",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.g-0.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.\"","/str","/ev",{"*":".^.^.c-3","flg":22},{"s":["^\"Then you'd better get searching",{"->":"$r","var":true},null]}],{"c-2":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.g-0.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"^ Make a show of me. And then you'll get your man.\"","\n","^Somehow, I think. But that's the part I need to work.","\n",{"->":"harris_takes_you_to_hooper"},{"#f":5}],"c-3":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-0.10.g-0.c-3.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"^,\" I reply, tiring of his complaining. A war is a war, you have to expect an enemy. ",{"->":".^.^.^.^.^.^.^.^.^.^.^.its_your_problem"},"\n",{"#f":5}],"#f":5}]}],{"#f":5}],"c-1":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"^, then. As a colleague. Maybe I can get something useful out of him.\"","\n",{"->":".^.^.^.^.^.^.^.^.putmein"},{"#f":5}],"c-2":["ev",{"^->":"claim_hooper_took_component.0.we_wont_guess.c-7.6.c-1.12.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],{"->":".^.^.^.^.^.^.^.^.shake_head"},"\n",{"#f":5}]}],{"#f":5}]}],{"#f":5}],"c-8":["^ ",{"->":".^.^.^.^.its_your_problem"},"\n",{"#f":5}],"#f":5}]}],{"harris_being_convinced":[["^\"Makes sense,\" Harris agrees, cautiously. ","ev",{"VAR?":"evasive"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^I can see he's still not entirely convinced by my tale, as well he might not be — I've hardly been entirely straight with him.",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["^I can see he's still not certain whether he can trust me.",{"->":".^.^.^.8"},null]}],"nop","^ \"Which means the question is, what can we do to rat him out?\"","\n","ev","str","^Offer to help","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't offer to help","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"Maybe I can help with that.\"","\n","^\"Oh, yes? And how, exactly?\"","\n",[["ev",{"^->":"claim_hooper_took_component.harris_being_convinced.0.c-0.6.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^\"I'll talk to him.\" ",{"->":"$r","var":true},null]}],["ev",{"^->":"claim_hooper_took_component.harris_being_convinced.0.c-0.6.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^\"","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["^\"We'll fool him.",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"claim_hooper_took_component.harris_being_convinced.0.c-0.6.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"\n","^\"What?\"","\n","^\"Put me in with Hooper with him. Maybe I can get something useful out of him.\"","\n",{"->":".^.^.^.^.^.^.putmein"},{"#f":5}],"c-1":["ev",{"^->":"claim_hooper_took_component.harris_being_convinced.0.c-0.6.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"^ He's waiting to be sure that I've been strung up for this, so let's give him what he wants. If he sees me taken away, clapped in irons — he'll go straight to that component and set about getting rid of it.\"","\n",{"->":"harris_takes_you_to_hooper"},{"#f":5}]}],{"#f":5}],"c-1":["\n","^I lean back. ",{"->":".^.^.^.^.its_your_problem"},"\n",{"#f":5}]}],{"#f":1}],"putmein":[["^Harris shakes his head.","\n","^\"He despises you. I don't see why he'd give himself up to you.\"","\n","ev","str","^Insist","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Give in","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ \"Try me. Just me and him.\" ","\n",{"->":".^.^.^.^.go_in_alone"},{"#f":5}],"c-1":["^ \"You're right.\" ","\n",{"->":".^.^.^.^.shake_head"},{"#f":5}]}],{"#f":1}],"shake_head":["<>","^ I shake my head. \"You're right. I don't see how I can help you. So there's only one conclusion.\"","\n","^\"Oh, yes? And what's that?\"","\n",{"->":".^.^.its_your_problem"},{"#f":1}],"its_your_problem":["^\"It's your problem. Your security breach. So much for your careful vetting process.\"","\n","^I lean back in my chair and fold my arms so the way they shake will not be visible.","\n","^\"You'd better get on with solving it, instead of wasting your time in here with me.\"","\n",{"->":".^.^.harrumphs"},{"#f":1}],"harrumphs":[["^Harris harrumphs. He's thinking it all over.","\n","ev","str","^Wait","/str",{"CNT?":".^.^.^.putmein"},"/ev",{"*":".^.c-0","flg":21},"ev","str","^Wait","/str",{"CNT?":".^.^.^.putmein"},"!","/ev",{"*":".^.c-1","flg":21},{"c-0":["^ ","\n","^\"All right,\" he declares, gruffly. \"We'll try it. But if this doesn't work, I might just put the both of you in front of a firing squad and be done with these games. Worse things happen in time of war, you know.\"","\n","^\"Alone,\" I add.","\n",{"->":".^.^.^.^.go_in_alone"},{"#f":5}],"c-1":["^ ","\n","^\"No,\" Harris declares, finally. \"I think you're lying about Hooper. I think you're a clever, scheming young man — that's why we hired you — and you're looking for the only reasonable out this situation has to offer. But I'm not taking it. We know you were in the room with the machine, we know you're of a perverted persuasion, we know you have compromised yourself. There's nothing more to say here. Either you tell me what you've done with that component, or we will hang you and search just as hard. It's your choice.\"","\n",{"->":"harris_threatens_lynching"},{"#f":5}]}],{"#f":1}],"go_in_alone":[["^\"Alone?\"","\n","^\"Alone.\"","\n","^Harris considers it. I watch his eyes, flicking backwards and forwards over mine, like a ribbon—reader loading its program.","\n","ev","str","^Patient","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Impatient","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ \"Well?\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ \"For God's sake, man, what do you have to lose?\" ","\n","ev",{"^var":"forceful","ci":-1},{"f()":"raise"},"pop","/ev","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"We'll be outside the door,\" Harris replies, seriously. \"The first sign of any funny business and we'll have you both on the floor in minutes. You understand? The country needs your brain, but it's not too worried about your legs. Remember that.\"","\n","^Then he gets to his feet, and opens the door, and marches me out across the yard. The evening is drawing in and there's a chill in the air. My mind is racing. I have one opportunity here — a moment in which to put the fear of God into Hooper and make him do something foolish that places him in harm's way. But how to achieve it?","\n","^\"You ready?\" Harris demands.","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-4","flg":20},{"c-2":["\n","^\"Absolutely.\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-3":["\n","^\"No.\"","\n","^\"Too bad.\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-4":["^ ",{"->":".^.^.c-2"},"\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":[{"->":"inside_hoopers_hut"},{"#f":5}]}],{"#f":1}],"#f":1}],"harris_takes_you_to_hooper":[["^Harris gets to his feet. \"All right,\" he says. \"I should no better than to trust a clever man, but we'll give it a go.\"","\n","^Then, he smiles, with all his teeth, like a wolf.","\n","ev",{"CNT?":"claim_hooper_took_component.0.g-1.hoopers_hut_3"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Especially since this is a plan that involves keeping you in handcuffs. I don't see what I have to lose.\"","\n",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["\n","^\"Hooper's in Hut 3 being debriefed by the Captain. Let's see if we can't get his attention somehow.\"","\n",{"->":".^.^.^.9"},null]}],"nop","\n","^He raps on the door for the guard and gives the man a quick instruction. He returns a moment later with a cool pair of iron cuffs.","\n","^\"Put 'em up,\" Harris instructs, and I do so. The metal closes around my wrists like a trap. I stand and follow Harris willingly out through the door.","\n","^But whatever I'm doing with my body, my mind is scheming. Somehow, I'm thinking, I have to get away from these men long enough to get that component behind Hut 2 and put it somewhere Hooper will go. Or, otherwise, somehow get Hooper to go there himself...","\n","^Harris marches me over to Hut 3, and gestures for the guard to stand aside. Pushing me forward, he opens the door nice and wide.","\n","^\"Captain. Manning talked. If you'd step out for a moment?\"","\n","ev","str","^Play the part, head down","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Look inside the hut","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Call to Hooper","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["\n","^From where he's sitting, I know Hooper can see me, so I keep my head down and look guilty as sin. The bastard is probably smiling.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["\n","^I look in through the door and catch Hooper's expression. I had half expected him to be smiling be he isn't. He looks shocked, almost hurt. \"Iain,\" he murmurs. \"You couldn't...\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^I have a single moment to shout something to Hooper before the door closes.","\n","^\"I'll get you Hooper, you'll see!\" I cry. Then:","\n",[["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^\"Queen to rook two, checkmate!\"",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"^ I call, then laugh viciously, as if I am damning him straight to hell.","\n","ev",2,"/ev",{"VAR=":"hooperClueType","re":true},{"->":".^.^.only_catch"},{"#f":5}],"only_catch":["^I only catch Hooper's reaction for a moment — his eyebrow lifts in surprise and alarm. Good. If he thinks it is a threat then he just might be careless enough to go looking for what it might mean.","\n",["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.only_catch.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^\"Ask not for whom the bell tolls!\"",{"->":"$r","var":true},null]}],["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.only_catch.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-2","flg":18},{"s":["^\"Two words: messy, without one missing!\"",{"->":"$r","var":true},null]}],{"c-1":["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.only_catch.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"\n","^He stares back at me, as if were a madman and perhaps for a split second I see him shudder.","\n",{"->":".^.^.^.^.^.g-0"},{"#f":5}],"c-2":["ev",{"^->":"harris_takes_you_to_hooper.0.c-2.6.only_catch.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"^ I cry, laughing. It isn't the best clue, hardly worthy of The Times, but it will have to do.","\n","ev",3,"/ev",{"VAR=":"hooperClueType","re":true},{"->":".^.^"},{"->":".^.^.^.^.^.g-0"},{"#f":5}],"#f":5}]}],{"#f":5}],"g-0":["^The Captain comes outside, pulling the door to. \"What's this?\" he asks. \"A confession? Just like that?\"","\n","^\"No,\" the Commander admits, in a low voice. \"I'm afraid not. Rather more a scheme. The idea is to let Hooper go and see what he does. If he believes we have Manning here in irons, he'll try to shift the component.\"","\n","^\"If he has it.\"","\n","^\"Indeed.\"","\n","^The Captain peers at me for a moment, like I was some kind of curious insect.","\n","^\"Sometimes, I think you people are magicians,\" he remarks. \"Other times you seem more like witches. Very well.\"","\n","^With that he opens the door to the Hut and goes back inside. The Commander uses the moment to hustle me roughly forward.","\n","ev",{"CNT?":".^.^.c-2"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^\"And what was all that shouting about?\" he hisses in my ear as we move towards the barracks. \"Are you trying to pull something? Or just make me look incompetent?\"","\n",{"->":".^.^.^.19"},null]}],[{"->":".^.b"},{"b":["\n","^\"This scheme of yours had better come off,\" he hisses in my ear. \"Otherwise the Captain is going to start having men tailing me to see where I go on Saturdays.\"","\n",{"->":".^.^.^.19"},null]}],"nop","\n","ev","str","^Reassure","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Dissuade","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-5","flg":20},"ev","str","^Say nothing","/str","/ev",{"*":".^.c-6","flg":20},{"c-3":["^ ","\n","ev",{"CNT?":".^.^.^.c-2"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"It will. Hooper's running scared,\" I reply, hoping I sound more confident than I feel.","\n",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["\n","^\"Just adding to the drama,\" I tell him, confidently. \"I'm sure you can understand that.\"","\n",{"->":".^.^.^.8"},null]}],"nop","\n","^\"I think we've had enough drama today already,\" Harris replies. \"Let's hope for a clean kill.\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-4":["^ ","\n","ev",{"CNT?":".^.^.^.c-2"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"The Captain thought it was a good scheme. You'll most likely get a promotion.\"","\n",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["\n","^\"I'm not trying to do anything except save my neck.\"","\n",{"->":".^.^.^.8"},null]}],"nop","\n","^\"Let's hope things work out,\" Harris agrees darkly.","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-5":["^ ","\n","^\"We're still in ear—shot if they let Hooper go. Best get us inside and then we can talk, if we must.\"","\n","^\"I've had enough of your voice for one day,\" Harris replies grimly. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-6":["\n","^I let him have his rant. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^He hustles me up the steps of the barracks, keeping me firmly gripped as if I had any chance of giving him, a trained military man, the slip. It's all I can do not to fall into the room.","\n",{"->":"slam_door_shut_and_gone"},{"#f":5}]}],{"#f":1}],"inside_hoopers_hut":[[["^Harris opens the door and pushes me inside. \"Captain,\" he calls. \"Could I have a moment?\"","\n","^The Captain, looking puzzled, steps out. The door is closed. Hooper stares at me, open—mouthed, about to say something. I probably have less than a minute before the Captain storms back in and declares this plan to be bunkum.","\n","ev","str","^Threaten","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Bargain","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Plead","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["\n","^\"Listen to me, Hooper. We were the only men in that hut today, so we know what happened. But I want you to know this. I put the component inside a breeze—block in the foundations of Hut 2, wrapped in one of your shirts. They're going to find it eventually, and that's going to be what tips the balance. And there's nothing you can do to stop any of that from happening.\"","\n","ev",1,"/ev",{"VAR=":"hooperClueType","re":true},"^His eyes bulge with terror. \"What did I do, to you? What did I ever do?\"","\n",["ev","str","^Tell the truth","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^\"You treated me like vermin. Like something abhorrent.\"","\n","^\"You are something abhorrent.\"","\n","^\"I wasn't. Not when I came here. And I won't be, once you're gone.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"Nothing,\" I reply. \"You're just the other man in the room. One of us has to get the blame.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^\"It doesn't matter. Just remember what I said. I've beaten you, Hooper. Remember that.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I get to my feet and open the door of the Hut. The Captain storms back inside and I'm quickly thrown out. ",{"->":".^.^.^.^.^.^.hustled_out"},"\n",{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n","^\"Hooper, I'll make a deal with you. We both know what happened in that hut this afternoon. I know because I did it, and you know because you know you didn't. But once this is done I'll be rich, and I'll split that with you. I'll let you have the results, too. Your name on the discovery of the Bombe. And it won't hurt the war effort — you know as well as me that the component on its own is worthless, it's the wiring of the Bombe, the usage, that's what's valuable. So how about it?\"","\n","^Hooper looks back at me, appalled. \"You're asking me to commit treason?\"","\n",["ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["\n","^\"Yes, perhaps. But also to ensure your name goes down in the annals of mathematics. ",{"->":".^.^.^.^.^.^.back_of_hut_2"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"No. It's not treason. It's a trade, plain and simple.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^\"I'm suggesting you save your own skin. I've wrapped that component in one of your shirts, Hooper. They'll be searching this place top to bottom. They'll find it eventually, and when they do, that's the thing that will swing it against you. So take my advice now. Hut 2.\"","\n","ev",1,"/ev",{"VAR=":"hooperClueType","re":true},{"->":".^.^.g-0"},{"#f":5}],"c-3":["^ ",{"->":".^.^.c-2"},"\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":[{"->":".^.^.^.^.^.^.no_chance"},{"#f":5}]}],{"#f":5}],"c-2":["^ ","\n","^\"Please, Hooper. You don't understand. They have information on me. I don't need to tell you what I've done, you know. Have a soul. And the component — it's nothing. It's not the secret of the Bombe. It's just a part. The German's think it's a weapon — a missile component. Let them have it. Please, man. Just help me.\"","\n","^\"Help you?\" Hooper stares. \"Help you? You're a traitor. A snake in the grass. And you're queer.\"","\n",["ev","str","^Deny","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Accept","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^\"I'm no traitor. You know I'm not. How much work have I done here against the Germans? I've given my all. And you know as well as I do, if the Reich were to invade, I would be a dead man. Please, Hooper. I'm not doing any of this lightly.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["\n","^\"I am what I am,\" I reply. \"I'm the way I was made. But they'll hang me unless you help, Hooper. Don't let them hang me.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^\"That's not important now. What matters is what you do, this evening.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"Assuming I wanted to help you,\" he replies, carefully. \"Which I don't. What would I do?\"","\n","^\"Nothing. Almost nothing.","\n",{"->":".^.^.^.^.^.^.back_of_hut_2"},{"#f":5}]}],{"#f":5}],"#f":5,"#n":"g-0"}],null],{"back_of_hut_2":["<>","^ All you have to do is go to the back of Hut 2. There's a breeze—block with a cavity. That's where I've put it. I'll be locked up overnight. But you can pick it up and pass it to my contact. He'll be at the south fence around two AM.\"","\n","ev",1,"/ev",{"VAR=":"hooperClueType","re":true},{"->":".^.^.no_chance"},{"#f":1}],"no_chance":["^\"If you think I'll do that then you're crazy,\" Hooper replies.","\n","^At that moment the door flies open and the Captain comes storming back inside.","\n",{"->":".^.^.hustled_out"},{"#f":1}],"hustled_out":["^Harris hustles me over to the barracks. \"I hope that's the end of it,\" he mutters.","\n","^\"Just be sure to let him out,\" I reply. \"And then see where he goes.\"","\n",{"->":"slam_door_shut_and_gone"},{"#f":1}],"#f":1}],"slam_door_shut_and_gone":[["^Then they slam the door shut, and it locks.","\n","ev",{"VAR?":"hooperClueType"},0,"==","/ev",[{"->":".^.b","c":true},{"b":["\n","<>","^ How am I supposed to manage anything from in here?","\n","ev","str","^Try the door","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Try the windows","/str","/ev",{"*":".^.c-1","flg":20},{"->":".^.^.^.9"},{"c-0":["^ ",{"->":".^.^.^.^.^.try_the_door"},"\n",{"#f":5}],"c-1":["^ ",{"->":".^.^.^.^.^.try_the_windows"},"\n",{"#f":5}]}]}],[{"->":".^.b"},{"b":["\n","^I can only hope that Hooper bites. If he thinks I'm bitter enough to have framed him, and arrogant enough to have taunted him with ","ev",{"VAR?":"hooperClueType"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^a clue to",{"->":".^.^.^.8"},null]}],"nop","^ where the damning evidence is hidden...","\n","^If he hates me enough, and is paranoid enough, then he might ","ev",{"VAR?":"hooperClueType"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^unravel my little riddle and",{"->":".^.^.^.18"},null]}],"nop","^ go searching around Hut 2.","\n",{"->":".^.^.^.9"},null]}],"nop","\n","ev","str","^Wait","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["^ \t",{"->":"night_falls"},"\n",{"#f":5}]}],{"try_the_door":["^I try the door. It's locked, of course.","\n",{"->":".^.^.from_outside_heard"},{"#f":1}],"from_outside_heard":[["^From outside, I hear a voice. Hooper's. He's haranguing someone.","\n",["ev","str","^Listen at the keyhole","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Try the window","/str",{"CNT?":".^.^.^.^.try_the_windows"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^Try the door","/str",{"CNT?":".^.^.^.^.try_the_door"},"!",{"CNT?":".^.c-0"},"&&","/ev",{"*":".^.c-2","flg":21},"ev","str","^Smash the window","/str",{"CNT?":".^.^.^.^.try_the_windows"},"/ev",{"*":".^.c-3","flg":21},"ev","str","^Wait","/str",{"CNT?":".^.^.^.^.try_the_door"},{"CNT?":".^.^.^.^.try_the_windows"},"&&","/ev",{"*":".^.c-4","flg":21},{"c-0":["^ ","\n","^I put my ear down to the keyhole, but there's nothing now. Probably still a guard outside, of course, but they're keeping mum.","\n",{"->":".^.^"},{"#f":5}],"c-1":["^ ",{"->":".^.^.^.^.^.try_the_windows"},"\n",{"#f":5}],"c-2":["^ ",{"->":".^.^.^.^.^.try_the_door"},"\n",{"#f":5}],"c-3":["^ ",{"->":".^.^.^.^.^.try_to_smash_the_window"},"\n",{"#f":5}],"c-4":["^ ","\n","^It's useless. There's nothing I can do but hope. I sit down on one corner of the bunk to wait.","\n",{"->":"night_falls"},{"#f":5}],"#f":5,"#n":"opts"}],null],{"#f":1}],"try_the_windows":["^I go over to the window and try to jimmy it open. Not much luck, but in my struggling I notice this window only backs on the thin little brook that runs down the back of the compound. Which means, if I smashed it, I might get away with no—one seeing.","\n",{"->":".^.^.from_outside_heard"},{"#f":1}],"try_to_smash_the_window":[["^The window is my only way out of here. I just need a way to smash it.","\n","ev","str","^Punch it","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Find something","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Use something you've got","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^I suppose my fist would do a good enough job. But I'd cut myself to ribbons, most likely. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","ev",2,"/ev",{"VAR=":"smashingWindowItem","re":true},"^I cast around the small room. There's a bucket in one corner for emergencies — I suppose I could use that. I pick it up but it's not very easy to heft. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^I pat down my pockets but all I'm carrying is the intercept, which is no good at all.","\n",["ev","str","^Something you're wearing?","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Look around","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^Ah, but of course! I slip off one shoe and heft it by the toe. The heel will make a decent enough hammer, if I give it enough wallop.","\n","ev",1,"/ev",{"VAR=":"smashingWindowItem","re":true},"^But I'll cut my hand to ribbons doing it. ","<>","\n",{"->":".^.^.^.^.g-0"},{"#f":5}],"c-1":["^ ",{"->":".^.^.^.^.c-1"},"\n",{"->":".^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"g-0":["^And the noise would be terrible. There must be a way of making this easier. I'm supposed to be a thief now. What would a burglar do?","\n","ev","str","^Work slowly","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Find something to help","/str","/ev",{"*":".^.c-4","flg":20},{"c-3":["^ ","\n","^Work carefully? It's difficult to work carefully when all one's has is ","ev",{"VAR?":"smashingWindowItem"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["^a bucket. It's rather like the sledgehammer for the proverbial nut",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["ev",{"VAR?":"smashingWindowItem"},1,"==","/ev",[{"->":".^.b","c":true},{"b":["^a shoe",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^nothing but brute force",{"->":".^.^.^.7"},null]}],"nop",{"->":".^.^.^.10"},null]}],"nop","^.","\n",["ev","str","^Just do it","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Look around for something","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ",{"->":".^.^.^.^.^.^.^.time_to_move_now"},"\n",{"->":".^.^.^.^.^.g-1"},{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.^.^.^.g-1"},{"#f":5}]}],{"#f":5}],"c-4":["^ ","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":[{"->":".^.^.^.^.find_something_to_smash_window"},{"#f":5}]}],{"#f":1}],"time_to_move_now":[["^Enough of this. There isn't any time to lose. Right now they'll be following Hooper as he goes to bed, and goes to sleep; and then that's it. The minute he closes his eyelids and drifts off that's the moment that this trap swings shut on me.","\n","^So I punch out the glass with my ","ev",{"VAR?":"smashingWindowItem"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["^bucket",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["ev",{"VAR?":"smashingWindowItem"},1,"==","/ev",[{"->":".^.b","c":true},{"b":["^shoe",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^fist",{"->":".^.^.^.7"},null]}],"nop",{"->":".^.^.^.10"},null]}],"nop","^ and it shatters with a terrific noise. Then I stop, and wait, to see if anyone will come in through the door.","\n","^Nothing.","\n","ev","str","^Wait a little longer","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Clear the frame of shards","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^I pause for a moment longer. It doesn't do to be too careless...","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["\n","^With my jacket wrapped round my arm, I sweep out the remaining shards of glass. It's not a big window, but I'm not a big man. If I was Harris, I'd be stuffed, but as it is...","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Then the door locks turns. The door opens. Then Jeremy — one of the guards, rather — sticks his head through the door. \"I thought I heard...\"","\n","^He stops. Looks for a moment. ","ev",{"VAR?":"smashingWindowItem"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["^Sees the bucket in my hand.",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^Sees the broken window.",{"->":".^.^.^.10"},null]}],"nop","^ Then without a moment's further thought he blows his shrill whistles and hustles into the hut, grabbing me roughly by my arms.","\n","ev",{"CNT?":".^.^.c-0"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^I'll never know if I hadn't have waited that extra moment — maybe I still could have got away. But, how far?","\n",{"->":".^.^.^.17"},null]}],"nop","\n","^I'm hustled into one of the huts. Nowhere to sleep, but they're not interested in my comfort any longer. Harris comes in with the Captain.","\n","^\"So,\" Harris remarks. \"Looks like your little trap worked. Only it worked to show you out for what you are.\"","\n","ev","str","^Tell the truth","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-4","flg":20},{"c-2":["^ ","\n","ev",{"CNT?":"i_met_a_young_man"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Please, Harris. You can't understand the pressure they put me under. You can't understand what it's like, to be in love but be able to do nothing about it...\"","\n",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["\n","^\"Harris. They were blackmailing me. They knew about... certain indiscretions. You can understand, can't you, Harris? I was in an impossible bind...\"","\n",{"->":".^.^.^.7"},null]}],"nop","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-3":["\n","^\"I had to get out, Harris. I had to provoke Hooper into doing something that would incriminate himself fully. He's too clever, you see...\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-4":["^ ","\n","^\"This proves nothing,\" I reply stubbornly. \"You still don't have the component and without it, I don't see what you can hope to prove.\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^\"Be quiet, man. We know all about your and your sordid affairs.\" The Captain curls his lip. \"Don't you know there's a war on? Do you know the kind of place they would have sent you if it haven't had been for that brain of yours? Don't you think you owe it to your country to use it a little more?\"","\n","^Do I, I wonder? Do I owe this country anything, this country that has spurned who and what am I since the day I became a man?","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-5","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-6","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-7","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-8","flg":20},{"c-5":["^ ","\n","^My anger deflates like a collapsing equation, all arguments cancelling each other out. The world, of course, owes me nothing; and I owe it everything.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-6":["^ ","\n","^Of course not. I am alone; that is what they wanted me to be, because of who and what I love. So I have no nation, no country.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-7":["^ \t",{"->":".^.^.c-6"},"\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-8":["^ \t","\n","^But what is a country, after all? A country is not a concept, not an ideal. Every country falls, its borders shift and move, its language disappears to be replaced by another. Neither the Reich nor the British Empire will survive forever, so what use is my loyalty to either? ","\n","^I may as well, therefore, look after myself. Something I have attempted, but failed miserably, to do.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"#f":5}],"g-2":["^\"I'm afraid we have only one option, Manning,\" Harris says. \"Please, man. Tell us where the component is.\"","\n","ev",true,"/ev",{"VAR=":"notraitor","re":true},"ev",false,"/ev",{"VAR=":"losttemper","re":true},"ev","str","^Tell them","/str","/ev",{"*":".^.c-9","flg":20},"ev","str","^Say nothing","/str","/ev",{"*":".^.c-10","flg":20},{"c-9":["\n","ev",false,"/ev",{"VAR=":"revealedhooperasculprit","re":true},"^\"All right.\" I am beaten, after all. \"","<>",{"->":"reveal_location_of_component"},"\n",{"#f":5}],"c-10":["^ ",{"->":"my_lips_are_sealed"},"\n",{"#f":5}],"#f":5}]}],{"#f":1}],"find_something_to_smash_window":[["^Let me see. There's the bunk, ","ev",{"VAR?":"smashingWindowItem"},"!",2,"==","/ev",[{"->":".^.b","c":true},{"b":["^a bucket,",{"->":".^.^.^.8"},null]}],"nop","^ nothing else. I have my jacket but nothing in the pockets — no handkerchief, for instance.","\n",["ev","str","^The bunk","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^The jacket","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^The bucket","/str",{"VAR?":"smashingWindowItem"},"!",2,"==","/ev",{"*":".^.c-2","flg":21},{"c-0":["^ \t","\n","^The bunk has a solid metal frame, a blanket, a pillow, nothing more.","\n",[["ev","str","^The frame","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^The blanket","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^The pillow","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Something else","/str",{"CNT?":".^"},1,">","/ev",{"*":".^.c-3","flg":21},{"c-0":["\n","^The frame is heavy and solid. I couldn't lift it or shift it without help from another man. And it wouldn't do me any good here anyway. I can reach the window perfectly well.","\n",{"->":".^.^"},{"#f":5}],"c-1":["^ ","\n","^The blanket. Perfect. I scoop it up off the bed and hold it in place over the window. ",{"->":"smash_the_window"},"\n",{"#f":5}],"c-2":["^ ","\n","^The pillow is fat and fluffy. I could put it over the window and it would muffle the sound of breaking glass, certainly; but I wouldn't be able to break any glass through it either.","\n",{"->":".^.^"},{"#f":5}],"c-3":["^ ",{"->":".^.^.^.^.^"},"\n",{"#f":5}],"#f":5,"#n":"bunk_opts"}],null],{"#f":5}],"c-1":["^ ","\n","^I slip off my jacket and hold it with one hand over the glass. ",{"->":"smash_the_window"},"\n",{"#f":5}],"c-2":["^ ","\n","^The bucket? Hardly. The bucket might do some good if I wanted to sweep up the glass afterwards, but it won't help me smash the glass quietly.","\n",{"->":".^.^"},{"#f":5}],"#f":5,"#n":"opts"}],null],{"#f":1}],"#f":1}],"smash_the_window":[["^Then I heft ","ev",{"VAR?":"smashingWindowItem"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["^up the bucket — this really is quite a fiddly thing to be doing in cuffs — ",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["ev",{"VAR?":"smashingWindowItem"},1,"==","/ev",[{"->":".^.b","c":true},{"b":["^ my shoe by its toe, ",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^back my arm, ",{"->":".^.^.^.7"},null]}],"nop",{"->":".^.^.^.8"},null]}],"nop","^ and take a strong swing, trying to imagine it's Harris' face on the other side.","\n","ev",true,"/ev",{"VAR=":"smashedglass","re":true},"ev",0,"/ev",{"VAR=":"smashingWindowItem","re":true},"ev","str","^Smash!","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^The sound of the impact is muffled. With my arm still covered, I sweep out the remaining glass in the frame.","\n",["^I'm ready to escape. The only trouble is — when they look in on me in the morning, there will be no question what has happened. It won't help me one jot with shifting suspicion off my back.","\n","ev","str","^Wait","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Slip out","/str","/ev",{"*":".^.c-2","flg":20},{"c-1":["\n","^So perhaps I should wait it out, after all. Who knows? I might have a better opportunity later.","\n",{"->":"night_passes"},{"->":".^.^.^.^.g-2"},{"#f":5}],"c-2":["^ ","\n","^Moving quickly and quietly, I hoist myself up onto the window—frame and worm my way outside into the freezing night air. Then I am away, slipping down the paths between the Huts, sticking to the shadows, on my way to Hut 2.","\n",{"->":".^.^.^.^.g-2"},{"#f":5}],"#f":5,"#n":"g-1"}],{"#f":5}],"g-2":["ev","str","^Go the shortest way","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Take a longer route","/str","/ev",{"*":".^.c-4","flg":20},{"c-3":["^ ","\n","^There's no time to lose. Throwing caution to the wind I make my way quickly to Hut 2, and around the back. I don't think I've been seen but if I have it is too late. My actions are suspicious enough for the noose. I have no choice but to follow through.","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-4":["\n","^In case I'm being followed, I divert around the perimeter of the compound. It's a much longer path, and it takes me across some terrain that's difficult to negotiate in the dark — muddy, and thick with thistles and nestles.","\n","ev",true,"/ev",{"VAR=":"muddyshoes","re":true},"^Still, I can be confident no—one is behind me. I crouch down behind the rear wall of Hut 2. ","<>","\n",{"->":".^.^.^.g-3"},{"#f":5}],"#f":5}],"g-3":["^The component is still there, wrapped in a tea—towel and shoved into a cavity in a breeze—block at the base of the Hut wall.","\n","ev","str","^Take it","/str","/ev",{"*":".^.c-5","flg":20},"ev","str","^Leave it","/str","/ev",{"*":".^.c-6","flg":20},{"c-5":["^ ","\n","^Quickly, I pull it free, and slip it into the pocket of my jacket.","\n","ev",true,"/ev",{"VAR=":"gotcomponent","re":true},{"->":".^.^.^.g-4"},{"#f":5}],"c-6":["^ ","\n","^Still there means no—one has found it, which means it is probably well—hidden. And short of skipping the compound now, I can afford to leave it hidden there a while longer. So I leave it in place.","\n",{"->":".^.^.^.g-4"},{"#f":5}],"#f":5}],"g-4":["^Where now?","\n","ev","str","^Back to the barracks","/str","/ev",{"*":".^.c-7","flg":20},"ev","str","^Go to Hooper's dorm","/str",{"VAR?":"gotcomponent"},"/ev",{"*":".^.c-8","flg":21},"ev","str","^Escape the compound","/str","/ev",{"*":".^.c-9","flg":20},{"c-7":["^ ",{"->":"return_to_room_after_excursion"},"\n",{"#f":5}],"c-8":["^ ",{"->":"go_to_hoopers_dorm"},"\n",{"#f":5}],"c-9":["^ ","\n","^Enough of this place. Time for me to get moving. I can get to the train station on foot, catch the postal train to Scotland and be somewhere else before anyone realises that I'm gone.","\n","^Of course, then they'll be looking for me in earnest. ","ev",{"VAR?":"framedhooper"},"!","/ev",[{"->":".^.b","c":true},{"b":["^As a confirmed traitor.",{"->":".^.^.^.11"},null]}],[{"->":".^.b"},{"b":["^Perhaps not as a traitor — they might take the idea that Hooper was involved with the theft — but certainly as a valuable mind, one containing valuable secrets and all too easily threatened. They will think I am running away because of my indiscretions. I suppose, in fairness, that I am.",{"->":".^.^.^.11"},null]}],"nop","\n",["ev","str","^Go","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't go","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ \t\t\t",{"->":"live_on_the_run"},"\n",{"#f":5}],"c-1":["^ ","\n","^It's no good. That's only half a solution. I couldn't be happy with that.","\n",["ev","str","^Back to the barracks","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^To Hooper's dorm","/str",{"VAR?":"gotcomponent"},{"CNT?":"go_to_hoopers_dorm"},"!","&&","/ev",{"*":".^.c-1","flg":21},{"c-0":["^ \t\t\t",{"->":"return_to_room_after_excursion"},"\n",{"#f":5}],"c-1":["^ ",{"->":"go_to_hoopers_dorm"},"\n",{"#f":5}]}],{"#f":5}]}],{"#f":5}],"#f":5}]}],{"#f":1}],"go_to_hoopers_dorm":[["^I creep around the outside of the huts towards Hooper's dorm. Time to wrap up this little game once and for all. A few guards patrol the area at night but not many — after all, very few know this place even exists.","\n","^Our quarters are arranged away from the main house; where we sleep is of less importance than where we work. We each have our own hut, through some are less permanent than others. Hooper's is a military issue tent: quite a large canopy, with two rooms inside and a short porch area where he insists people leave their shoes. It's all zipped up for the night and no light shines from inside.","\n","^I hang back for a moment. If Harris is keeping to the terms of our deal then someone will be watching this place. But I can see no—one.","\n","ev","str","^Open the outer zip","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Look for another opening","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Hide the component somewhere","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^I creep forward to the tent, intent on lifting the zip to the front porch area just a little — enough to slip the component inside, and without the risk of the noise waking Hooper from his snoring.","\n","^The work is careful, and more than little fiddly — Hooper has tied the zips down on the inside, the fastidious little bastard! — but after a little work I manage to make a hole large enough for my hand.","\n",["ev","str","^Slip in the component","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No, some other way","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ \t\t","\n","^I slide the component into the tent, work the zip closed, and move quickly away into the shadows. It takes a few minutes for my breath to slow, and my heart to stop hammering, but I see no other movement. If anyone is watching Hooper's tent, they are asleep at their posts.","\n","ev",true,"/ev",{"VAR=":"putcomponentintent","re":true},"ev",false,"/ev",{"VAR=":"gotcomponent","re":true},{"->":"return_to_room_after_excursion"},{"#f":5}],"c-1":["^ \t\t\t","\n","^Then pause. This is too transparent. Too blatant. If I leave it here, like this, Hooper will never be seen to go looking for it: he will stumble over it in plain sight, and the men watching will wonder why it was not there when he went to bed.","\n","^No, I must try something else — or nothing at all.","\n",["ev","str","^On top of the tent","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Throw the component into the long grass","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Give up","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ",{"->":".^.^.^.^.^.^.^.put_component_on_tent"},"\n",{"#f":5}],"c-1":["^ ","\n","^From inspiration — or desperation, I am not certain — a simple approach occurs to me. ",{"->":".^.^.^.^.^.^.^.toss_component_into_bushes"},"\n",{"#f":5}],"c-2":["^ ","\n","^There is nothing to be gained here. I have the component now; maybe it will be of some value tomorrow.","\n",["ev","str","^Return to my barrack","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Escape the compound","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ",{"->":"return_to_room_after_excursion"},"\n",{"#f":5}],"c-1":["^ ",{"->":"live_on_the_run"},"\n",{"#f":5}]}],{"#f":5}]}],{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n","^Making a wide circuit I creep around the tent. It has plenty of other flaps and openings, tied down with Gordian complexity. But nothing afford itself to slipping the component inside.","\n",["ev","str","^Try the porch zip","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Try on top of the tent","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Give up","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ \t\t\t",{"->":".^.^.^.^.c-0"},"\n",{"#f":5}],"c-1":["^ \t\t",{"->":".^.^.^.^.^.put_component_on_tent"},"\n",{"#f":5}],"c-2":["^ \t\t\t\t\t\t","\n","^It's no good. Nothing I can do will be any less than obvious — something appearing where something was not there before. The men watching Hooper will know it is a deception and Hooper's protestations will be taken at face value.","\n","^If I can't find a way for Hooper to pick the component up, as if from a hiding place of his own devising, and be caught doing it, then I have no plan at all.","\n",["ev","str","^Return to my barrack","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Escape the compound","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Toss the component into the bushes","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ",{"->":"return_to_room_after_excursion"},"\n",{"#f":5}],"c-1":["^ ",{"->":"live_on_the_run"},"\n",{"#f":5}],"c-2":["^ ",{"->":".^.^.^.^.^.^.^.toss_component_into_bushes"},"\n",{"#f":5}]}],{"#f":5}]}],{"#f":5}],"c-2":["^ ","\n","^If I leave the component here somewhere it should be somewhere I can rely on Hooper finding it, but no—one before Hooper. In particular.","\n",["ev","str","^Behind the tent","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Inside the porch section","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^On top of the canvas","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^\t\t\t \t",{"->":".^.^.^.^.c-1"},"\n",{"#f":5}],"c-1":["^ \t\t",{"->":".^.^.^.^.c-0"},"\n",{"#f":5}],"c-2":["^ \t\t\t",{"->":".^.^.^.^.^.put_component_on_tent"},"\n",{"#f":5}]}],{"#f":5}]}],{"put_component_on_tent":["^A neat idea strikes me. If I could place it on top of the canvas, somewhere in the middle where it would bow the cloth inwards, then it would be invisible to anyone passing by. But to Hooper, it would be above him: a shadow staring him in the face as he awoke. What could be more natural than getting up, coming out, and looking to see what had fallen on him during the night?","\n","^It's the work of a moment. I was once an excellent bowler for the second XI back at school. This time I throw underarm, of course, but I still land the vital missing component exactly where I want it to go.","\n","ev",true,"/ev",{"VAR=":"framedhooper","re":true},"ev",false,"/ev",{"VAR=":"gotcomponent","re":true},"^For a second I hold my breath, but nothing and no—one stirs. ",{"->":"return_to_room_after_excursion"},"\n",{"#f":1}],"toss_component_into_bushes":["^I toss the component away into the bushes behind Hooper's tent and return to my barrack, wishing myself a long sleep followed by a morning, free of this business.","\n","ev",false,"/ev",{"VAR=":"gotcomponent","re":true},"ev",true,"/ev",{"VAR=":"throwncomponentaway","re":true},{"->":"return_to_room_after_excursion"},{"#f":1}],"#f":1}],"live_on_the_run":["^Better to live on the run than die on the spit. Creeping around the edge of the compound","ev",{"VAR?":"gotcomponent"},"/ev",[{"->":".^.b","c":true},{"b":["^, the Bombe component heavy in my pocket",{"->":".^.^.^.5"},null]}],"nop","^, I make my way to the front gate. As always, it's manned by two guards, but I slip past their box by crawling on my belly.","\n","^And then I'm on the road. Walking, not running. Silent. Free.","\n","^For the moment, at least.","\n","end",{"#f":1}],"return_to_room_after_excursion":[["ev",{"VAR?":"gotcomponent"},"/ev",[{"->":".^.b","c":true},{"b":["^The weight of the Bombe component safely in my jacket",{"->":".^.^.^.5"},null]}],[{"->":".^.b"},{"b":["^Satisfied",{"->":".^.^.^.5"},null]}],"nop","^, I return the short way up the paths between the huts to the barrack block and the broken window.","\n","^It's a little harder getting back through — the window is higher off the ground than the floor inside — but after a decent bit of jumping and hauling I manage to get my elbows up, and then one leg, and finally I collapse inside, quite winded and out breath.","\n","ev","str","^Wait","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["^ \t",{"->":"night_passes"},"\n",{"#f":5}]}],{"#f":1}],"night_passes":[["^The rest of the night passes slowly. I sleep a little, dozing mostly. Then I'm woken by the rooster in the yard. The door opens, and Harris comes in. He takes one look at the broken window and frowns with puzzlement.","\n","ev",{"VAR?":"putcomponentintent"},"/ev",[{"->":".^.b","c":true},{"b":["^ ",{"->":".^.^.^.^.put_component_inside_tent"},{"->":".^.^.^.6"},null]}],"nop","\n","^\"What happened there?\"","\n","ev","str","^Confess","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Deny","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Show him the component","/str",{"VAR?":"gotcomponent"},"/ev",{"*":".^.c-2","flg":21},{"c-0":["^ ","\n","^\"I broke it,\" I reply. There doesn't seem any use in trying to lie. \"I thought I could escape. But I couldn't get myself through.\"","\n","^The Commander laughs. ",{"->":".^.^.^.glad_youre_here"},"\n",{"#f":5}],"c-1":["^ ","\n","^\"I'm not sure. I was asleep: I woke up when someone broke the window. I looked out to see who it was, but they were already gone.\"","\n","^Harris looks at me with puzzlement. \"Someone came by to break the window, and then ran off? That's absurd. That's utterly absurd. Admit it, Manning. You tried to escape and you couldn't get through.\"","\n",["ev","str","^Admit it","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Deny it","/str",{"VAR?":"framedhooper"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^Deny it","/str",{"VAR?":"framedhooper"},"/ev",{"*":".^.c-2","flg":21},{"c-0":["\n","^\"All right. ","ev",{"VAR?":"forceful"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^Damn you.",{"->":".^.^.^.8"},null]}],"nop","^ That's exactly it.\"","\n",{"->":".^.^.^.^.^.glad_youre_here"},{"#f":5}],"c-1":["\n","^\"If I wanted to escape, I would have made damn sure that I could,\" I tell him sternly.","\n",{"->":"harris_certain_is_you"},{"#f":5}],"c-2":["^ ","\n","^\"I tell you, someone broke it. Someone wanted to threaten me, I think.\"","\n","^Harris shakes his head. \"Well, we can look into that matter later. For now, you probably want to hear the more pressing news. ",{"->":".^.^.^.^.^.found_missing_component"},"\n",{"#f":5}]}],{"#f":5}],"c-2":["^ ",{"->":".^.^.^.someone_threw_component"},"\n",{"#f":5}]}],{"put_component_inside_tent":[["^He takes one look around, and sighs, a deep, wistful sigh.","\n","^\"Things just get worse and worse for you, Manning,\" he remarks. \"You are your own worst enemy.\"","\n","ev","str","^Agree","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Disagree","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^\"I've thought so before.\" ","ev",{"VAR?":"admitblackmail"},"/ev",[{"->":".^.b","c":true},{"b":["^Certainly in the matter of getting blackmailed.",{"->":".^.^.^.7"},null]}],"nop","\n","^\"Let me tell you what happened this morning. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["\n","^\"Right now, I think you take that role, Harris,\" I reply coolly.","\n",[["^\"Very droll,\" he replies. \"Let me tell you what happened this morning. It will take the smile off your face. ","<>","\n",{"->":".^.^.^.^.g-0"},{"#f":5,"#n":"droll"}],null],{"#f":5}],"c-2":["^ ","\n","^\"I'm looking forward to having a wash and a change of clothes; which should make me a little less evil to be around.\"","\n",{"->":".^.^.c-1.3.droll"},{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Our men watching Hooper's tent saw Hooper wake up, get dressed, clamber out of his tent and then step on something in at the entrance of his tent.\"","\n","ev",true,"/ev",{"VAR=":"piecereturned","re":true},"ev","str","^Be interested","/str","/ev",{"*":".^.c-3","flg":20},"ev","str","^Be dismissive","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^Say nothing","/str","/ev",{"*":".^.c-5","flg":20},{"c-3":["^ ","\n","^\"You mean he didn't even hide it? He put it in his shoe?\"","\n",[["^\"No,\" Harris replies. \"That isn't really what I mean. ","<>","\n",{"->":".^.^.^.^.^.g-1"},{"#f":5,"#n":"not_that"}],null],{"#f":5}],"c-4":["\n","^\"So he's an idiot, and he hid it in his shoe.\"","\n",{"->":".^.^.c-3.4.not_that"},{"->":".^.^.^.g-1"},{"#f":5}],"c-5":["^ ","\n","^I say quiet, listening, not sure how this will go.","\n","^\"In case I'm not making myself clear,\" Harris continues, \"","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^I mean, he managed to find it, by accident, somewhere where it wasn't the night before. And at the same time, you're sitting here with your window broken. So, I rather think you've played your last hand and lost. It's utterly implausible that Hooper stole that component and then left it lying around in the doorway of his tent. So I came to tell you that the game is up, for you.\"","\n","^He nods and gets to his feet. ",{"->":"left_alone"},"\n",{"#f":5}]}],{"#f":1}],"someone_threw_component":[["^\"Someone threw this in through the window over night,\" I reply, and open my jacket to reveal the component from the Bombe. \"I couldn't see who, it was too dark. But I know what it is.\"","\n","^He reaches out and takes it. \"Well, I'll be damned,\" he murmurs. \"That's it all right. And you didn't have it on you when we put you in here. But it can't have been Hooper — I had men watching him all night. And there's no—one else it could have been.\"","\n","^He turns the component over in his hands, bemused.","\n","ev",true,"/ev",{"VAR=":"piecereturned","re":true},"ev","str","^Suggest something","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Suggest nothing","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"Perhaps Hooper had an accomplice. Someone else who works on site.\"","\n","^Harris shakes his head, distractedly. \"That doesn't make sense,\" he says. \"Why go to all the trouble of stealing it only to give it back? And why like this?\"","\n",["ev","str","^Suggest something","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Suggest nothing","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"Perhaps the accomplice thought it was Hooper being kept in here. Maybe they saw the guard...\"","\n",{"->":"all_too_farfetched"},{"->":".^.^.^.^.g-0"},{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I shrug, eloquently.","\n",[{"->":"all_too_farfetched"},{"#f":5,"#n":"g-1"}],{"#f":5}]}],{"#f":1}],"glad_youre_here":[["^\"Shame,\" he remarks. \"I should have left that window open and put a guard on you. Might have been interesting to see where you went. Anyway, I'm glad you're still here, even if you do smell like a dog.\"","\n","ev","str","^Be optimistic","/str",{"VAR?":"framedhooper"},"!","/ev",{"*":".^.c-0","flg":21},"ev","str","^Be pessimistic","/str",{"VAR?":"framedhooper"},"!","/ev",{"*":".^.c-1","flg":21},"ev","str","^Be optimistic","/str",{"VAR?":"framedhooper"},"/ev",{"*":".^.c-2","flg":21},"ev","str","^Be pessimistic","/str",{"VAR?":"framedhooper"},"/ev",{"*":".^.c-3","flg":21},{"c-0":["^ ","\n",{"->":"night_falls.morning_not_saved.0.c-0"},{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n",{"->":"night_falls.morning_not_saved.0.c-1"},{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ","\n","^\"I'm looking forward to having a bath.\"","\n","^\"Well, you should enjoy it. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"c-3":["\n","^\"I imagine I'll smell worse after another couple of days of this.\"","\n","^\"That won't be necessary. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":[{"->":".^.^.^.^.found_missing_component"},{"#f":5}]}],{"#f":1}],"found_missing_component":[["^We found the missing component. Or rather, Hooper found it for us. He snuck out and retrieved it from on top. Of all the damnest places — you would never have known it was there. He claimed ignorance when we jumped him, of course. But it's good enough for me.\"","\n","ev","str","^Approve","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Disapprove","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["\n","^\"I can't tell you enough, I'm glad to hear it. I've had a devil of a night.\"","\n","^His gaze flicks to the broken window, but only for a moment. I think he genuinely cannot believe I could have done it.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"You should never have hired him. A below-average intelligence can't be expected to cope with the pressure of our work.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^Harris rolls his eyes, but he might almost be smiling. \"You'd better get along, ","ev",{"CNT?":".^.^.c-0"},"/ev",[{"->":".^.b","c":true},{"b":["^and work through your devils",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["^Mr Intelligent",{"->":".^.^.^.6"},null]}],"nop","^. There's a 24—hour—late message to be tackled and we're a genius short. So you'd better be ready to work twice as hard.\"","\n","ev","str","^Thank him","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Argue with him","/str","/ev",{"*":".^.c-3","flg":20},{"c-2":["^ \t","\n","^\"I'll enjoy it. Thank you for helping me clear this up.\"","\n","^\"Don't thank me yet. There's still a war to fight. Now get a move on.\"","\n","^I nod, and hurry out of the door. The air outside has never tasted fresher and more invigorating. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-3":["^ ","\n","^\"I'll work as hard as I work.\"","\n","^\"Get out,\" Harris growls. \"Before I decide to arrest you as an accessory.\"","\n","^I do as he says. Outside the barrack, the air has never smelt sweeter.","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":[{"->":"head_for_my_dorm_free"},{"#f":5}]}],{"#f":1}],"#f":1}],"night_falls":[["^Night falls. The clockwork of the heavens keeps turning, whatever state I might be in. No—one can steal the components that make the sun go down and the stars come out. I watch it performing its operations. I can't sleep.","\n","ev",{"VAR?":"hooperClueType"},0,">","/ev",[{"->":".^.b","c":true},{"b":["\n","^Has Hooper taken my bait?","\n",{"->":".^.^.^.8"},null]}],"nop","\n","ev","str","^Look of out the window","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Listen at the door","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Wait","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["^ ","\n","^I peer out of the window, but it looks out onto the little brook at the back of the compound, with no view of the other huts or the House. Who knows if there are men up, searching the base of Hut 2, following one another with flashlights...","\n","ev",{"CNT?":"inside_hoopers_hut.back_of_hut_2"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^Perhaps Hooper is there, in the dark, trying to help me after all?","\n",{"->":".^.^.^.8"},null]}],"nop","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ \t","\n","^I put my ear to the keyhole but can make out nothing. Are there still guards posted? ","ev",{"VAR?":"hooperClueType"},0,">","/ev",[{"->":".^.b","c":true},{"b":["^Perhaps, if Hooper has managed to incriminate himself, the guards have been removed?",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^Perhaps the component has been found and the crisis is over.",{"->":".^.^.^.10"},null]}],"nop","\n","^Perhaps the door is unlocked and they left me to sleep?","\n",["ev","str","^Try it","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Leave it","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ I try the handle. No such luck.","\n",{"->":".^.^.^.^.g-0"},{"#f":5}],"c-1":["^ I don't touch it. I don't want anyone outside thinking I'm trying to escape.","\n",{"->":".^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"c-2":["^ \t\t\t\t\t","\n","^There is nothing I can do to speed up time.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^The night moves at its own pace. I suppose by morning I will know my fate.","\n","ev","str","^Wait","/str",{"VAR?":"hooperClueType"},0,">","/ev",{"*":".^.c-3","flg":21},"ev","str","^Wait","/str",{"VAR?":"hooperClueType"},0,"==","/ev",{"*":".^.c-4","flg":21},{"c-3":["^ ","\n","^Morning comes. I'm woken by a rooster calling from the yard behind the House. I must have slept after all. I pull myself up from the bunk, shivering slightly. There is condensation on the inside of the window. I have probably given myself a chill.","\n","^Without knocking, Harris comes inside. \"You're up,\" he remarks, and then, \"You smell like an animal.\"","\n",["ev","str","^Be friendly","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Be cold","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"I suppose I do rather.\" I laugh, but Harris does not.","\n","^\"This damn business gets worse and worse,\" he says, talking as he goes over to unlock and throw open the window. ","<>","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"So would you,\" I reply tartly. Harris shrugs.","\n","^\"I've been through worse than this,\" he replies matter—of—factly. \"It's hardly my fault if you sleep in your clothes.\"","\n","^I glare back. He goes over to the window, unlocks it and throws it open, relishing the fresh air from outside.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"Hooper's confessed, you know.\"","\n","ev","str","^Be eager","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Be cautious","/str","/ev",{"*":".^.c-3","flg":20},{"c-2":["^ ","\n","^\"He has? I knew he would. The worm.\"","\n","^\"Steady now. Matters aren't over yet. ","<>","\n",{"->":".^.^.^.hooper_didnt_give_himself_up"},{"#f":5}],"c-3":["^ ","\n","^\"Oh, yes?\"","\n","^\"Yes. For what that's worth. ","<>","\n",{"->":".^.^.^.hooper_didnt_give_himself_up"},{"#f":5}],"#f":5}],"hooper_didnt_give_himself_up":["^There's still the issue of the component. It hasn't turned up. He didn't lead us to it. I guess he figured you must have had something on him. I don't know.\"","\n","^He looks quite put out by the whole affair. He is not the kind of man to deal well with probabilities.","\n","ev","str","^Be interested","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^Be disinterested","/str","/ev",{"*":".^.c-5","flg":20},{"c-4":["^ ","\n","^\"You mean he confessed of his own accord? You didn't catch him?\"","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-5":["^ ","\n","^\"Well, I'm glad his conscience finally caught up with him,\" I reply dismissively.","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^\"The Captain went back into that hut and he confessed immediately. We were so surprised we didn't let you go.\" He wrinkles his nose. \"I'm rather sorry about that now. I suggest you have a wash.\"","\n","^And with that he gestures to the doorway.","\n","ev","str","^Go","/str","/ev",{"*":".^.c-6","flg":20},"ev","str","^Wait","/str","/ev",{"*":".^.c-7","flg":20},{"c-6":["^ ","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-7":["^ ","\n","^I hang back a moment. Something does not seem quite right. After all, Hooper did not steal the component. He has no reason to confess to anything. Perhaps this is another trap?","\n","^\"Well?\" Harris asks. \"What are you waiting for? Please don't tell me you want to confess now as well, I don't think my head could stand it.\"","\n",["ev","str","^Confess","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't confess","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^After a chance like this? A chance — however real — to save my neck? To hand it over — what, to save Hooper's worthless skin?","\n",["ev","str","^Confess","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't confess","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^I see. Perhaps you think I bullied the man into giving himself up. Perhaps he understood my little clue far enough to know it was a threat against him, but not well enough to understand where he should look to find it. So he took the easy route out and folded. Gave me the hand.","\n","ev",true,"/ev",{"VAR=":"hooperConfessed","re":true},"^Hardly sporting, of course.","\n",["ev","str","^Confess","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't confess","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["\n","^Well, then. I suppose this must be what it feels like to have a conscience. I suppose I had always wondered.","\n","^\"Harris, sir. I don't know what Hooper's playing at, sir. But I can't let him do this.\"","\n","^\"Do what?\"","\n","^\"Take the rope for this. I took it, sir.","\n","ev",false,"/ev",{"VAR=":"revealedhooperasculprit","re":true},"ev",false,"/ev",{"VAR=":"losttemper","re":true},{"->":"reveal_location_of_component"},{"->":".^.^.^.^.^.^.g-0"},{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"c-1":["^ ","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^\"I certainly don't. But still, I'm surprised. I had Hooper down for a full—blown double agent, a traitor. He knows he'll face the rope, doesn't he?\"","\n","^\"Don't ask me to explain why he did what he did,\" Harris sighs. \"Just be grateful that he did, and you're now off the hook.\"","\n",{"->":".^.^.^.^.^.g-2"},{"#f":5}]}],{"#f":5}],"#f":5}],"g-2":["^Curiouser and curiouser. I nod once to Harris and slip outside into the cold morning air.","\n","ev",{"VAR?":"hooperClueType"},0,"==","/ev",[{"->":".^.b","c":true},{"b":["\n","^Hooper's confession only makes sense in one fashion","ev",{"VAR?":"hooperConfessed"},"/ev",[{"->":".^.b","c":true},{"b":["^, and that is his being dim—witted and slow",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^ — if I successfully implied to him that I had him framed, but he did not unpack my little clue well enough to go looking for the component. Well, I had figured him for a more intelligent opponent, but a resignation from the game will suffice",{"->":".^.^.^.7"},null]}],"nop","^. Or perhaps he knew he would be followed if he went to check, and decided he would be doomed either way.","\n",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["\n","^Hooper's confession only makes sense in one way — and that's that he believed me. He reasoned that he would be followed. To try and uncover the component would have got him arrested, and to confess was the same.","\n","^He simply caved, and threw in his hand.","\n",{"->":".^.^.^.9"},null]}],"nop","\n","^Of course, however, there is only one way to be certain that Harris is telling the truth, and that is to check the breeze—block at the back of Hut 2.","\n","ev","str","^Check","/str","/ev",{"*":".^.c-8","flg":20},"ev","str","^Don't check","/str","/ev",{"*":".^.c-9","flg":20},{"c-8":["^ ",{"->":"go_to_where_component_is_hidden"},"\n",{"#f":5}],"c-9":["\n","^But there will time for that later. If there is nothing there, then Hooper discovered the component after all and Harris' men will have swooped on him, and the story about his confession is just a ruse to test me out.","\n","^And if the component is still there — well. It will be just as valuable to my contact in a week's time, and his deadline of the 31st is not yet upon us.","\n",{"->":"head_for_my_dorm_free"},{"#f":5}],"#f":5}]}],{"#f":5}],"c-4":["^ ",{"->":".^.^.^.^.morning_not_saved"},"\n",{"#f":5}],"#f":5}]}],{"morning_not_saved":[["^Morning comes with the call of a rooster from the yard of the House. I must have slept after all. I pull myself up off the bunk, shivering slightly. There is condensation on the inside of the window. I have probably given myself a chill.","\n","^It's not long after that Harris enters the hut. He closes the door behind him, careful as ever, then takes a chair across from me.","\n","^\"You smell like a dog,\" he remarks.","\n","ev","str","^Be optimistic","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Be pessimistic","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"I'm looking forward to a long bath,\" I reply. \"And getting back to work.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^\"So would you after the night I've had.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":[{"->":"harris_certain_is_you"},{"#f":5}]}],{"#f":1}],"#f":1}],"harris_certain_is_you":["^\"Well, I'm afraid it is going to get worse for you,\" Harris replies soberly. \"We followed Hooper, and he took himself neatly to bed and slept like a boy scout. Which puts us back to square one, and you firmly in the frame. And I'm afraid I don't have time for any more games. I want you to tell me where that component is, or we will hang you as a traitor.\"","\n","ev",false,"/ev",{"VAR=":"revealedhooperasculprit","re":true},"ev",false,"/ev",{"VAR=":"losttemper","re":true},{"->":"harris_threatens_lynching"},{"#f":1}],"head_for_my_dorm_free":[["^I head for my dorm, intent on a bath, breakfast, a glance at the crossword before the other men get to it, and then on with work. They should have replaced the component in the Bombe by now. We will only be a day behind.","\n","ev",{"VAR?":"framedhooper"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^And then everything will proceed as before. The component will mean nothing to the Germans — this is the one fact I could never have explained to a man like Harris, even though the principle behind the Bombe is the same as the principle behind the army. The individual pieces — the men, the components — do not matter. They are identical. It is how they are arranged that counts.","\n",{"->":".^.^.^.7"},null]}],"nop","\n","^I bump into Russell in the dorm hut.","\n","^\"Did you hear?\" he whispers. \"Terrible news about Hooper. Absolutely terrible.\"","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["^ ","\n","^\"Quite terrible. I would never have guessed.\"","\n","^\"Well.\" Russell harrumphs.","\n",[["^\"Quince was saying this morning, apparently his grandfather was German. So perhaps it's to be expected. See you there?\"","\n",{"->":".^.^.^.^.g-0"},{"#f":5,"#n":"quince"}],null],{"#f":5}],"c-1":["\n","^\"Heard what?\"","\n",[["^\"Hooper's been taken away. They caught him, uncovering that missing Bombe component from a hiding place somewhere, apparently about to take it to his contact.\" Russell harrumphs. ",{"->":".^.^.^.^.c-0.6.quince"},"\n",{"->":".^.^.^.^.g-0"},{"#f":5,"#n":"hooper_taken"}],null],{"#f":5}],"c-2":["^ ","\n","^\"I don't know what you're talking about.\"","\n",{"->":".^.^.c-1.3.hooper_taken"},{"->":".^.^.g-0"},{"#f":5}],"c-3":["\n","^\"If you'll excuse me, Russell. I was about to take a bath.\"","\n","^\"Oh, of course. Worked all night, did you? Well, you'll hear soon enough. Can hardly hide the fact there'll only be three of us from now on.\"","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I wave to him and move away, my thoughts turning to the young man in the village. My lover. My contact. My blackmailer. Hooper may have taken the fall for the missing component, but ","ev",{"VAR?":"framedhooper"},"!","/ev",[{"->":".^.b","c":true},{"b":["^if he did recover it from Hut 2 then ",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^ its recovery does mean ",{"->":".^.^.^.7"},null]}],"nop","^I have nothing to sell to save my reputation","ev",{"CNT?":"i_met_a_young_man"},"/ev",[{"->":".^.b","c":true},{"b":["^, if I have any left",{"->":".^.^.^.13"},null]}],"nop","^.","\n","ev",{"VAR?":"framedhooper"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^If he didn't, of course, and Harris was telling the truth about his sudden confession, then I will be able to buy my freedom once and for all.","\n",{"->":".^.^.^.21"},null]}],"nop","\n","ev","str","^Get the component","/str",{"VAR?":"framedhooper"},"!","/ev",{"*":".^.c-4","flg":21},"ev","str","^Leave it","/str",{"VAR?":"framedhooper"},"!","/ev",{"*":".^.c-5","flg":21},"ev","str","^Act normal","/str","/ev",{"*":".^.c-6","flg":20},{"c-4":["^ ",{"->":"go_to_where_component_is_hidden"},"\n",{"#f":5}],"c-5":["^ ","\n","^I will have to leave that question for another day. To return there now, when they're probably watching my every step, would be suicide. After all, if Hooper ","ev",{"VAR?":"hooperClueType"},1,"==","/ev",[{"->":".^.b","c":true},{"b":["^followed",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^understood",{"->":".^.^.^.10"},null]}],"nop","^ my clue, he will have explained it to them to save his neck. They won't believe him — but they won't quite disbelieve him either. We're locked in a cycle now, him and me, of half—truth and probability. There's nothing either of us can do to put the other entirely into blame.","\n",{"->":"ending_return_to_normal"},{"#f":5}],"c-6":["^ ","\n","^But there is nothing to be done about it. ",{"->":"ending_return_to_normal"},"\n",{"#f":5}],"#f":5}]}],{"#f":1}],"ending_return_to_normal":[["^Nothing, that is, except to act as if there is no game being played. I'll have a bath, then start work as normal. I've got a week to find something to give my blackmailer","ev",{"CNT?":"i_met_a_young_man"},"/ev",[{"->":".^.b","c":true},{"b":["^ — or give him nothing: it seems my superiors know about my indiscretions now already",{"->":".^.^.^.5"},null]}],"nop","^.","\n","ev","str","^Co-operate","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Dissemble","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-3","flg":20},{"c-0":["^ ","\n","^Something will turn up. It always does. An opportunity will present itself, and more easily now that Hooper is out of the way.","\n","^But for now, there's yesterday's intercept to be resolved.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^Or perhaps I might hand my young blackmailer over my superiors instead for being the spy he is.","\n","^Perhaps that would be the moral thing to do, even, and not just the most smart.","\n","^But not today. Today, there's an intercept to resolve.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["\n","^In a week's time, this whole affair will be in the past and quite forgotten. I'm quite sure of that. ",{"->":".^.^.c-3"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-3":["^ I've more important problems to think about now. There's still yesterday's intercept to be resolved. ","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^The Bombe needs to be set up once more and set running.","\n","^It's time I tackled a problem I can solve.","\n","end",{"#f":5}]}],{"#f":1}],"go_to_where_component_is_hidden":[["^It won't take a moment to settle the matter. I can justify a walk past Hut 2 as part of my morning stroll. It will be obvious in a moment if the component is still there.","\n","^On my way across the paddocks, between the huts and the House, I catch sight of young Miss Lyon, arriving for work on her bicycle. She giggles as she sees me and waves.","\n","ev","str","^Wave back","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Ignore her","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^I wave cheerily back and she giggles, almost drops her bicycle, then dashes away inside the House. Judging by the clock on the front gable, she's running a little late this morning.","\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["^ ","\n","^I give no reaction. She sighs to herself, as if this kind of behaviour is normal, and trots away inside the House to begin her duties.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I turn the corner of Hut 3 and walk down the short gravel path to Hut 2. It was a good spot to choose — Hut 2 is where the electricians work, and they're generally focussed on what they're doing. They don't often come outside to smoke a cigarette so it's easy to slip past the doorway unnoticed.","\n","ev","str","^Check inside","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Go around the back","/str","/ev",{"*":".^.c-3","flg":20},{"c-2":["^ \t\t","\n","^I hop up the steps and put my head inside all the same. Nobody about. Still too early in the AM for sparks, I suppose. ","<>","\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-3":["^ ","\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["^I head on around the back of the hut. The breeze—block with the cavity is on the left side.","\n","ev","str","^Check","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^Look around","/str","/ev",{"*":".^.c-5","flg":20},{"c-4":["^ \t\t","\n","^No time to waste. I drop to my knees and check the breeze—block. Sure enough, there's nothing there. Hooper took the bait.","\n","^Suddenly, there's a movement behind me. I look up to see, first a snub pistol, and then, Harris.","\n",{"->":".^.^.^.g-2"},{"#f":5}],"c-5":["^ ","\n","^I pause to glance around, and catch a glimpse of movement. Someone ducking around the corner of the hut. Or a canvas sheet flapping in the light breeze. Impossible to be sure.","\n",["ev","str","^Check the breeze—block","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Check around the side of the hut","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ",{"->":".^.^.^.^.c-4"},"\n",{"->":".^.^.^.^.^.g-2"},{"#f":5}],"c-1":["^ ","\n","^But too important to guess. I move back around the side of the hut.","\n","^Harris is there, leaning in against the wall. He holds a stub pistol in his hand.","\n",{"->":".^.^.^.^.^.g-2"},{"#f":5}]}],{"#f":5}],"#f":5}],"g-2":["ev",{"VAR?":"hooperClueType"},1,">","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"","ev",{"VAR?":"hooperClueType"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["^Queen to rook two",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["^Messy without one missing whatever it was",{"->":".^.^.^.9"},null]}],"nop","^,\" he declares. \"I wouldn't have fathomed it but Hooper did. Explained it right after we sprung him doing what you're doing now. We weren't sure what to believe but now, you seem to have resolved that for us.\"","\n",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["\n","^\"Hooper said you'd told him where to look. I didn't believe him. Or, well. I wasn't sure what to believe. Now I rather think you've settled it.\"","\n",{"->":".^.^.^.7"},null]}],"nop","\n","ev","str","^Agree","/str","/ev",{"*":".^.c-6","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-7","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-8","flg":20},{"c-6":["^ ","\n","^\"I have, rather.\" I put my hands into my pockets. \"I seem to have done exactly that.\"","\n","^\"I'm afraid my little story about Hooper confessing wasn't true. I wanted to see if you'd go to retrieve the part.\" Harris gestures me to start walking. \"You were close, Manning, I'll give you that. I wanted to believe you. But I'm glad I didn't.\"","\n",{"->":".^.^.^.g-3.done"},{"->":".^.^.^.g-3"},{"#f":5}],"c-7":["^ ","\n","^\"I spoke to Russell. He said he saw Hooper doing something round here. I wanted to see what it was.\"","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-8":["^ ","\n","^\"Harris, you'd better watch out. He's planted a time—bomb here.\"","\n","^Harris stares at me for a moment, then laughs. \"Oh, goodness. That's rich.\"","\n","^I almost wish I had a way to make the hut explode, but of course I don't.","\n",{"->":".^.^.^.g-3"},{"#f":5}],"#f":5}],"g-3":["^\"Enough.\" Harris gestures for me to start walking. \"This story couldn't be simpler. You took it to cover your back. You hid it. You lied to get Hooper into trouble, and when you thought you'd won, you came to scoop your prize. A good hand but ultimately, ","ev",{"VAR?":"hooperClueType"},1,"<=","/ev",[{"->":".^.b","c":true},{"b":["^if it hadn't have been you who hid the component, then you wouldn't be here now",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["^you told Hooper where to look with your little riddle",{"->":".^.^.^.8"},null]}],"nop","^.\"","\n",["^He leads me across the yard. Back towards Hut 5 to be decoded, and taken to pieces, once again.","\n","end",{"#f":5,"#n":"done"}],{"#f":5}]}],{"#f":1}],"harris_threatens_lynching":[["ev",{"CNT?":"harris_certain_is_you"},"/ev",[{"->":".^.b","c":true},{"b":["^He passes a hand across his eyes with a long look of despair.",{"->":".^.^.^.5"},null]}],[{"->":".^.b"},{"b":["^He gets to his feet, and gathers his gloves from the table top.",{"->":".^.^.^.5"},null]}],"nop","\n","^\"I'm going to go outside and organise a rope. That'll take about twelve minutes. That's how long you have to decide.\"","\n","ev","str","^Protest","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Confess","/str",{"VAR?":"gotcomponent"},"!",{"VAR?":"throwncomponentaway"},"!","&&","/ev",{"*":".^.c-1","flg":21},"ev","str","^Stay silent","/str","/ev",{"*":".^.c-2","flg":20},"ev","str","^Show him the component","/str",{"VAR?":"gotcomponent"},"/ev",{"*":".^.c-3","flg":21},{"c-0":["^ ","\n","^\"You can't do this!\" I cry. \"It's murder! I demand a trial, a lawyer; for God's sake, man, you can't just throw me overboard, we're not barbarians...!\"","\n",[["^\"You leave me no choice,\" Harris snaps back, eyes cold as gun—metal. \"You and your damn cyphers. Your damn clever problems. If men like you didn't exist, if we could just all be straight with one another.\" He gets to his feet and heads for the door. \"I fear for the future of this world, with men like you in. Reich or no Reich, Mr Manning, people like you simply complicate matters.\"","\n",{"->":"left_alone"},{"->":".^.^.^.^.g-0"},{"#f":5,"#n":"too_clever"}],null],{"#f":5}],"c-1":["^ ","\n","^I nod. \"I don't need twelve minutes. ",{"->":"reveal_location_of_component"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-2":["^ ",{"->":"my_lips_are_sealed"},"\n",{"->":".^.^.g-0"},{"#f":5}],"c-3":["^ ","\n","^\"I don't need twelve minutes. Here it is.\"","\n","^I open my jacket and pull the Bombe component out of my pocket. Harris takes it from me, whistling, curious.","\n","^\"Well, I'll be. That's it all right.\"","\n","^\"That's it.\"","\n","^\"But you didn't have it on you yesterday.\"","\n",["ev","str","^Explain","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Don't explain","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","^\"I climbed out of the window overnight,\" I explain. \"I went and got this from where it was hidden, and brought it back here.\"","\n",{"->":".^.^.^.^.g-0"},{"#f":5}],"c-1":["\n","^\"No. I didn't.\"","\n",{"->":".^.^.^.^.g-0"},{"#f":5}]}],{"#f":5}],"g-0":[{"->":"all_too_farfetched"},"ev","str","^Confess","/str",{"VAR?":"throwncomponentaway"},"/ev",{"*":".^.c-4","flg":21},"ev","str","^Frame Hooper","/str",{"VAR?":"throwncomponentaway"},"/ev",{"*":".^.c-5","flg":21},{"c-4":["\n","^\"I don't need twelve minutes. The component is in the long grass behind Hooper's tent. I threw it there hoping to somehow frame him, but now I see that won't be possible. I was naive, I suppose.\"","\n","ev",true,"/ev",{"VAR=":"piecereturned","re":true},{"->":"reveal_location_of_component.harris_believes"},{"#f":5}],"c-5":["^ ","\n","^\"Look, I know where it is. The missing piece of the Bombe is in the long grasses behind Hooper's tent. I saw him throw it there right after we finished work. He knew you'd scour the camp but I suppose he thought you'd more obvious places first. I suppose he was right about that. Look there. That proves his guilt.\"","\n","ev",true,"/ev",{"VAR=":"longgrasshooperframe","re":true},"ev",true,"/ev",{"VAR=":"piecereturned","re":true},"^\"That doesn't prove anything,\" Harris returns sharply. \"But we'll check what you say, all the same.\" He gets to his feet and heads out of the door.","\n",{"->":"left_alone"},{"#f":5}],"#f":5}]}],{"#f":1}],"reveal_location_of_component":["<>","^ The missing component of the Bombe computer is hidden in a small cavity in a breeze—block supporting the left rear post of Hut 2. I put in there anticipating a search. I intended to ","ev",{"VAR?":"revealedhooperasculprit"},"/ev",[{"->":".^.b","c":true},{"b":["^pass it to Hooper",{"->":".^.^.^.7"},null]}],[{"->":".^.b"},{"b":["^dispose of it",{"->":".^.^.^.7"},null]}],"nop","^ once the fuss had died down. I suppose I was foolish to think that it might.\"","\n","ev",true,"/ev",{"VAR=":"piecereturned","re":true},{"->":".^.harris_believes"},{"harris_believes":["ev",{"CNT?":"night_falls.0.g-0.c-3.6.hooper_didnt_give_himself_up"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Indeed. And Mr Manning: God help you if you're lying to me.\"","\n",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["\n","^\"I thought as much. I hadn't expected you to give it out so easily, however. You understand, Hooper has said nothing, of course. In fact, he went to Hut 2 directly after we released him and uncovered the component. But he told us you had instructed him where to go. Hence my little double bluff. Frankly, I'll be glad when I'm shot of the lot of you mathematicians.\"","\n",{"->":".^.^.^.6"},null]}],"nop","\n","^Harris stands, and slips away smartly. ",{"->":"left_alone"},"\n",{"#f":1}],"#f":1}],"my_lips_are_sealed":["^I say nothing, my lips tightly, firmly sealed. It's true I am a traitor, to the very laws of nature. The world has taught me that since a very early age. But not to my country — should the Reich win this war, I would hardly be treated as an honoured hero. I was doomed from the very start.","\n","ev",true,"/ev",{"VAR=":"notraitor","re":true},"^I explain none of this. How could a man like Harris understand?","\n","^The Commander takes one look back from the doorway as he pulls it to.","\n","^\"It's been a pleasure working with you, Mr Manning,\" he declares. \"You've done a great service to this country. If we come through, I'm sure they'll remember you name. I'm sorry it had to end this way and I'll do my best to keep it quiet. No—one need know what you did.\"","\n",{"->":"left_alone"},{"#f":1}],"all_too_farfetched":["^\"This is all too far—fetched,\" Harris says. \"I'm glad to have this back, but I need to think.\"","\n","^Getting to his feet, he nods once. \"You'll have to wait a little longer, I'm afraid, Manning.\"","\n","^Then he steps out of the door, muttering to himself.","\n",{"->":"make_your_peace"},{"#f":1}],"left_alone":["ev",{"CNT?":"slam_door_shut_and_gone.time_to_move_now"},"/ev",[{"->":".^.b","c":true},{"b":["^The Commander holds the door for his superior, and follows him out.",{"->":".^.^.^.4"},null]}],"nop","^ Then the door closes. I am alone again, as I have been for most of my short life.","\n",{"->":"make_your_peace"},{"#f":1}],"make_your_peace":[["ev","str","^Make your peace","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^I am waiting again. I have no God to make my peace with. I find it difficult to believe in goodness of any kind, in a world such as this.","\n","ev",{"VAR?":"notraitor"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","ev",true,"/ev",{"VAR=":"notraitor","re":true},"^But I am no traitor. Not to my country. To my sex, perhaps. But how could I support the Reich? If the Nazis were to come to power, I would be worse off than ever.","\n",{"->":".^.^.^.7"},null]}],"nop","\n","ev",{"CNT?":"harris_threatens_lynching.0.c-0.4.too_clever"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^In truth, it is men like Harris who are complex, not men like me. I live to make things ordered, systematic. I like my pencils sharpened and lined up in a row. I do not deal in difficult borders, or uncertainties, or alliances. If I could, I would reduce the world to something easier to understand, something finite.","\n","^But I cannot, not even here, in our little haven from the horrors of the war.","\n",{"->":".^.^.^.13"},null]}],"nop","\n","^I have no place here. No way to fit. I am caught, in the middle, cryptic and understood only thinly, through my machines.","\n",["ev",{"^->":"make_your_peace.0.g-0.17.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^I must seem very calm. \t\t\t",{"->":"$r","var":true},null]}],["ev",{"^->":"make_your_peace.0.g-0.18.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-2","flg":18},{"s":["^Perhaps I should try to escape.",{"->":"$r","var":true},null]}],{"c-1":["ev",{"^->":"make_your_peace.0.g-0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.17.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.^.g-1"},{"#f":5}],"c-2":["ev",{"^->":"make_your_peace.0.g-0.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.18.s"},[{"#n":"$r2"}],"^ But escape to where? I am already a prisoner. Jail would be a blessing. ",{"->":".^.^.^.g-1.monastic"},"\n",{"->":".^.^.^.g-1"},{"#f":5}],"#f":5}],"g-1":["<>","^ I suppose I do not believe they will hang me. They will lock me up and continue to use my brain, if they can. I wonder what they will tell the world — perhaps that I have taken my own life. That would be simplest. The few who know me would believe it.","\n","^Well, then. Not a bad existence, in prison. Removed from temptation.","\n",["^A monastic life, with plenty of problems to keep me going.","\n","^I wonder what else I might yet unravel before I'm done?","\n",["ev",{"^->":"make_your_peace.0.g-1.monastic.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-3","flg":18},{"s":["^The door is opening.",{"->":"$r","var":true},null]}],{"c-3":["ev",{"^->":"make_your_peace.0.g-1.monastic.c-3.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"^ Harris is returning. Our little calculation here is complete. ","ev",{"VAR?":"piecereturned"},"!","/ev",[{"->":".^.b","c":true},{"b":["^ I can only hope one of the others will be able to explain to him that the part I stole will mean nothing to the Germans.",{"->":".^.^.^.13"},null]}],[{"->":".^.b"},{"b":["^We are just pieces in this machine; interchangeable and prone to wear.",{"->":".^.^.^.13"},null]}],"nop","\n",{"->":".^.^.^.^.g-2"},{"#f":5}],"#f":5,"#n":"monastic"}],{"#f":5}],"g-2":["^That is the true secret of the calculating engine, and the source of its power. It is not the components that matter, they are quite repetitive. What matters is how they are wired; the diversity of the patterns and structures they can form. Much like people — it is how they connect that determines our victories and tragedies, and not their genius.","\n","^Which makes me wonder. Should I give ","ev",{"CNT?":"i_met_a_young_man"},"/ev",[{"->":".^.b","c":true},{"b":["^up my beautiful young man",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["^the young man who put me in this spot",{"->":".^.^.^.8"},null]}],"nop","^ to them as well as myself?","\n","ev","str","^Yes","/str","/ev",{"*":".^.c-4","flg":20},"ev","str","^No","/str","/ev",{"*":".^.c-5","flg":20},"ev","str","^Lie","/str","/ev",{"*":".^.c-6","flg":20},"ev","str","^Evade","/str","/ev",{"*":".^.c-7","flg":20},{"c-4":["^ ","\n","^But of course I will. ","ev",{"VAR?":"forceful"},2,">","/ev",[{"->":".^.b","c":true},{"b":["^Perhaps I can persuade them to put him in my cell.",{"->":".^.^.^.10"},null]}],[{"->":".^.b"},{"b":["^A little vengeance, disguised as doing something good.",{"->":".^.^.^.10"},null]}],"nop","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-5":["^ ","\n","^No. What would be the use? He will be long gone, and the name he told me is no doubt hokum. No: I was alone before in guilt, and I am thus alone again.","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-6":["^ ","\n","^No. Why would I? He is no doubt an innocent himself, trapped by some dire circumstance. Forced to act the way he did. I have every sympathy for him.","\n","^Of course I do.","\n",{"->":".^.^.^.g-3"},{"#f":5}],"c-7":["^ ","\n","^It depends, perhaps, on what his name his worth. If it were to prove valuable, well; perhaps I can concoct a few more such lovers with which to ease my later days.","\n","ev",{"VAR?":"hooper_mentioned"},"/ev",[{"->":".^.b","c":true},{"b":["^ Hooper, perhaps. He wouldn't like that. ",{"->":".^.^.^.8"},null]}],"nop","\n",{"->":".^.^.^.g-3"},{"#f":5}],"#f":5}],"g-3":["ev",{"VAR?":"longgrasshooperframe"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^Harris put the cuffs around my wrists. \"I still have the intercept in my pocket,\" I remark. \"Wherever we're going, could I have a pencil?\"","\n",{"->":".^.^.^.6"},null]}],[{"->":".^.b"},{"b":["\n","^\"We recovered the part, just where you said it was,\" Harris reports, as he puts the cuffs around my wrists. \"Of course, a couple of the men swear blind they searched there yesterday, so I'm afraid, what with the broken window... we've formed a perfectly good theory which doesn't bode well for you.\"","\n",{"->":".^.^.^.6"},null]}],"nop","\n","ev",true,"/ev",{"VAR=":"piecereturned","re":true},"ev",{"VAR?":"longgrasshooperframe"},"/ev",[{"->":".^.b","c":true},{"b":["\n","^\"I see.\" It doesn't seem worth arguing any further. \"I still have the intercept in my pocket,\" I remark. \"Wherever we're going, could I have a pencil?\"","\n",{"->":".^.^.^.16"},null]}],"nop","\n","^He looks me in the eye.","\n","ev",{"VAR?":"losttemper"},"!","/ev",[{"->":".^.b","c":true},{"b":["\n","^\"Of course. And one of your computing things, if I get my way. And when we're old, and smoking pipes together in The Rag like heroes, I'll explain to you the way that decent men have affairs.","\n",{"->":".^.^.^.26"},null]}],[{"->":".^.b"},{"b":["\n","^\"I'll give you a stone to chisel notches in the wall. And that's all the calculations you'll be doing. And as you sit there, pissing into a bucket and growing a beard down to your toes, you have a think about how a smart man would conduct his illicit affairs. With a bit of due decorum you could have learnt off any squaddie.","\n",{"->":".^.^.^.26"},null]}],"nop","\n","<>","^ You scientists.\"","\n","^He drags me up to my feet.","\n","^\"You think you have to re—invent everything.\"","\n","^With that, he hustles me out of the door and I can't help thinking that, with a little more strategy, I could still have won the day. But too late now, of course.","\n","end",{"#f":5}]}],{"#f":1}],"global decl":["ev",0,{"VAR=":"forceful"},0,{"VAR=":"evasive"},false,{"VAR=":"teacup"},false,{"VAR=":"gotcomponent"},false,{"VAR=":"drugged"},false,{"VAR=":"hooper_mentioned"},false,{"VAR=":"losttemper"},false,{"VAR=":"admitblackmail"},0,{"VAR=":"hooperClueType"},false,{"VAR=":"hooperConfessed"},0,{"VAR=":"smashingWindowItem"},false,{"VAR=":"notraitor"},false,{"VAR=":"revealedhooperasculprit"},false,{"VAR=":"smashedglass"},false,{"VAR=":"muddyshoes"},false,{"VAR=":"framedhooper"},false,{"VAR=":"putcomponentintent"},false,{"VAR=":"throwncomponentaway"},false,{"VAR=":"piecereturned"},false,{"VAR=":"longgrasshooperframe"},false,{"VAR=":"DEBUG"},"/ev","end",null],"#f":1}],"listDefs":{}}; \ No newline at end of file diff --git a/prototype/book-3057904.png b/prototype/book-3057904.png new file mode 100644 index 0000000..d0895d0 Binary files /dev/null and b/prototype/book-3057904.png differ diff --git a/prototype/brown-wooden-flooring.jpg b/prototype/brown-wooden-flooring.jpg new file mode 100644 index 0000000..aa24506 Binary files /dev/null and b/prototype/brown-wooden-flooring.jpg differ diff --git a/prototype/code/Main.ink b/prototype/code/Main.ink new file mode 100644 index 0000000..c9ba3ab --- /dev/null +++ b/prototype/code/Main.ink @@ -0,0 +1,16 @@ +# title: Das Herrenhaus +# author: Georg Tomitsch + +VAR location = 0 + +INCLUDE Stats.ink + +-> Herrenhaus + +=== Herrenhaus === +~ location = Herrenhaus +Du stehst vor einem Herrenhaus. + * Aktion 1 # 1 + * Aktion 2 # 2 + * Aktion 3 # 3 + - -> END diff --git a/prototype/code/Stats.ink b/prototype/code/Stats.ink new file mode 100644 index 0000000..e268174 --- /dev/null +++ b/prototype/code/Stats.ink @@ -0,0 +1,79 @@ +// Quest tracking functions as described by Jon Ingold in his GDC 2017 talk. + +// Every state implies the states before. + +=== function state_reached(state) === + ~ return + +// The state is never rolled back. If a lower or the same state is moved to nothing happens. +=== function move_to_state(state) === + ~ return + +// Often the state is checked as a range (excluding first and last state) +=== function state_between(first_state, last_state) === + ~ return + +// Implementation of ChoiceScript's Fairmath system + +// Adjust the variable by adding amount percent of the current value +=== function set(ref variable, amount) === + ~ variable = MIN(100, variable + variable * amount / 100) + ~ return variable + +// Implementation of relative opposed pair stats +=== function opposed(positive, negative) === + ~ return positive / negative * 100 // TODO Check if this calculation is correct + + +// Inkle's default number writing function +=== function print_num(x) +{ + - x >= 1000: + {print_num(x / 1000)} thousand { x mod 1000 > 0:{print_num(x mod 1000)}} + - x >= 100: + {print_num(x / 100)} hundred { x mod 100 > 0:and {print_num(x mod 100)}} + - x == 0: + zero + - else: + { x >= 20: + { x / 10: + - 2: twenty + - 3: thirty + - 4: forty + - 5: fifty + - 6: sixty + - 7: seventy + - 8: eighty + - 9: ninety + } + { x mod 10 > 0: + <>-<> + } + } + { x < 10 || x > 20: + { x mod 10: + - 1: one + - 2: two + - 3: three + - 4: four + - 5: five + - 6: six + - 7: seven + - 8: eight + - 9: nine + } + - else: + { x: + - 10: ten + - 11: eleven + - 12: twelve + - 13: thirteen + - 14: fourteen + - 15: fifteen + - 16: sixteen + - 17: seventeen + - 18: eighteen + - 19: nineteen + } + } +} \ No newline at end of file diff --git a/prototype/game - Kopie.js b/prototype/game - Kopie.js new file mode 100644 index 0000000..32e20dd --- /dev/null +++ b/prototype/game - Kopie.js @@ -0,0 +1,566 @@ +(function(storyContent) { + // Create ink story from the content using inkjs + var story = new inkjs.Story(storyContent); + + var savePoint = ""; + + let fade_in = true; + + // Global tags - those at the top of the ink file + // We support: + // # theme: dark + // # author: Your Name + var globalTags = story.globalTags; + if( globalTags ) { + for(var i=0; i func(...args), + timeoutId: null + }; + + timeoutObject.timeoutId = setTimeout(() => { + timeoutObject.execute(); + timeoutQueue = timeoutQueue.filter(t => t !== timeoutObject); + }, delay); + + timeoutQueue.push(timeoutObject); + + return timeoutObject.timeoutId; + } + + function fastForward() { + // Sort the queue based on timeoutId (assuming that smaller ids are scheduled earlier) + timeoutQueue.sort((a, b) => a.timeoutId - b.timeoutId); + // Clear and execute all timeouts + timeoutQueue.forEach(timeoutObject => { + clearTimeout(timeoutObject.timeoutId); + timeoutObject.execute(); + }); + + timeoutQueue = []; + document.getElementById("page_right").scrollTo({top: document.getElementById("page_right").scrollHeight, behavior: 'smooth'}); + } + + // var numberOfPreviewLines = 0; + + function typesetParagraph(paragraph_data, indent_width, delay = 0) { + console.log("Typesetting Paragraph with: ", paragraph_data, indent_width); + var left = indent_width; + var p = document.createElement("p"); + p.style.position = 'relative'; + var line_height = parseFloat(window.getComputedStyle(document.querySelector("#ruler")).lineHeight); + // numberOfPreviewLines += paragraph_data.breaks.length - 1; + // console.log("Calculated line height:", line_height); + p.style.height = line_height * (paragraph_data.breaks.length - 1) + 'px'; + p.style.marginBlockEnd = 0; + for(let i = 1; i < paragraph_data.breaks.length; i++) { + if(i > 1) + left = 0; + for(let j = paragraph_data.breaks[i-1].position; j <= paragraph_data.breaks[i].position; j++) { + // console.log("i =",i,"j =",j,"from =",paragraph_data.breaks[i-1].position,"to =",paragraph_data.breaks[i].position,"node_width =", paragraph_data.nodes[j].width, "left =", left, "type =", paragraph_data.nodes[j].type, "value =", paragraph_data.nodes[j].value); + if(paragraph_data.nodes[j].type === 'box' && paragraph_data.nodes[j].value !== '' && j < paragraph_data.breaks[i].position) { + if(j > paragraph_data.breaks[i-1].position + 1 && paragraph_data.nodes[j-1].type === 'penalty' && p.lastChild) { + p.lastChild.textContent += paragraph_data.nodes[j].value; + left += paragraph_data.nodes[j].width; + } else { + let word = document.createElement("span"); + word.style.position = 'absolute'; + word.classList.add("fade-in"); + word.style.top = line_height * (i - 1) + 'px'; + word.style.left = left + 'px'; + word.innerHTML = paragraph_data.nodes[j].value; + insertAfter(delay, p, word); + delay += 100.0; + // p.appendChild(word); + if(j > 0) + left += paragraph_data.nodes[j].width; + else + left += paragraph_data.nodes[j].width - indent_width; + } + } else if(j > paragraph_data.breaks[i-1].position && paragraph_data.nodes[j].type === 'glue' && paragraph_data.nodes[j].width !== 0 && j <= paragraph_data.breaks[i].position) { + // Insert space character + if(paragraph_data.breaks[i].ratio > 0) { + left += paragraph_data.nodes[j].width + paragraph_data.breaks[i].ratio * paragraph_data.nodes[j].stretch; + } else { + left += paragraph_data.nodes[j].width + paragraph_data.breaks[i].ratio * paragraph_data.nodes[j].shrink; + } + } else if(paragraph_data.nodes[j].type === 'penalty' && paragraph_data.nodes[j].penalty === 100 && j === paragraph_data.breaks[i].position) { + let word = document.createElement("span"); + word.style.position = 'absolute'; + word.style.top = line_height * (i - 1) + 'px'; + word.style.left = left + 'px'; + word.innerHTML = "-"; + insertAfter(delay, p, word); + delay += 100; + // p.appendChild(word); + // left += paragraph_data.nodes[j].width; + } + } + }; + return [p, delay]; + } + + function measureText(str) { + if (str === ' ') { + str = '\u00A0'; + } + ruler.textContent = str; + return ruler.getClientRects()[0].width; + } + + function updateBookDimensions() { + const vw = window.innerWidth; + const vh = window.innerHeight; + const viewportAspectRatio = vw / vh; + const imageAspectRatio = 2727 / 1691; + + let bookWidth, bookHeight; + + if (viewportAspectRatio > imageAspectRatio) { + bookWidth = vh * imageAspectRatio; + bookHeight = vh; + } else { + bookWidth = vw; + bookHeight = vw / imageAspectRatio; + } + + document.documentElement.style.setProperty('--book-width', `${bookWidth}px`); + document.documentElement.style.setProperty('--book-height', `${bookHeight}px`); + + // Setting a CSS variable that will be either vw or vh depending on the viewport aspect ratio + document.documentElement.style.setProperty( + "--viewport-dimension", + viewportAspectRatio > imageAspectRatio ? 'vw' : 'vh' + ); + document.documentElement.style.setProperty('--viewport-aspect-ratio', viewportAspectRatio); + let story = document.getElementById("story"); + let paddingTop = window.getComputedStyle(story).paddingTop; + let paddingBottom = window.getComputedStyle(story).paddingBottom; + document.documentElement.style.setProperty('--story-line-height', (story.clientHeight - paddingTop - paddingBottom) / 28) + } + + // Update the aspect ratio when the page loads + updateBookDimensions(); + + // Update the aspect ratio whenever the window is resized + window.addEventListener('resize', updateBookDimensions); + + window.addEventListener('keydown', (event) => { + if (event.code === 'Space') { + fade_in = false; + fastForward(); + } + }); + + // page features setup + var hasSave = loadSavePoint(); + setupButtons(hasSave); + + // Set initial save point + savePoint = story.state.toJson(); + + // Kick off the start of the story! + continueStory(true); + + // Main story processing function. Each time this is called it generates + // all the next content up as far as the next set of choices. + function continueStory(firstTime) { + + var paragraphIndex = 0; + var delay = 0.0; + + // Don't over-scroll past new content + var previousBottomEdge = firstTime ? 0 : contentBottomEdgeY(); + + var fade_in = true + + // Generate story text - loop through available content + while(story.canContinue) { + // Get ink to generate the next paragraph + var paragraphText = story.Continue(); + var tags = story.currentTags; + + // Any special tags included with this line + var customClasses = []; + for(var i=0; i { + var measure = parseFloat(window.getComputedStyle(document.getElementById("story")).width); + var indentWidth = parseFloat(window.getComputedStyle(document.querySelector("#indent")).textIndent); + var previewWidth = measure; + var preview_data = kap(hyphenator_en(text, '.hyphenatePipe'), measureText, 'align-justify', measure, true, indentWidth); + return { preview_data, indentWidth, previewWidth}; + }); + hyphenator_promise.then(({ preview_data, indentWidth, previewWidth }) => { + // updateParagraphPreview(preview_data, indentWidth, previewWidth); + var p, d; + [p, d] = typesetParagraph(preview_data, indentWidth, delay); + delay = d; + // Add any custom classes derived from ink tags + for(var i=0; i { + // var wordElement = document.createElement('span'); + // Hyphenopoly.hyphenators["en-us"].then((hyphenator_en) => { + // wordElement.innerHTML = hyphenator_en(word); + // }); + // // showAfter(delay, wordElement); + // insertAfter(delay, paragraphElement, wordElement, fade_in); + // insertAfter(delay, paragraphElement, document.createTextNode(" "), false); + // delay +=100.0; + // // paragraphElement.appendChild(wordElement); + // // paragraphElement.appendChild(document.createTextNode(" ")); + // }); + // // paragraphElement.innerHTML = paragraphText; + // storyContainer.appendChild(paragraphElement); + + + // Fade in paragraph after a short delay + // showAfter(delay, paragraphElement); + // delay += 200.0; + } + + // Create HTML choices from ink choices + story.currentChoices.forEach(function(choice) { + + // Create paragraph with anchor element + var choiceParagraphElement = document.createElement('p'); + choiceParagraphElement.classList.add("choice"); + choiceParagraphElement.innerHTML = `${choice.text}` + // choiceContainer.appendChild(choiceParagraphElement); + insertAfter(delay, choiceContainer, choiceParagraphElement, fade_in); + // Fade choice in after a short delay + // showAfter(delay, choiceParagraphElement); + delay += 200.0; + + // Click on choice + var choiceAnchorEl = choiceParagraphElement.querySelectorAll("a")[0]; + choiceAnchorEl.addEventListener("click", function(event) { + + // Don't follow link + event.preventDefault(); + + // Remove all existing choices + removeAll(".choice", true); + + // Tell the story where to go next + story.ChooseChoiceIndex(choice.index); + + // This is where the save button will save from + savePoint = story.state.toJson(); + + // Aaand loop + continueStory(); + }); + }); + + // Extend height to fit + // We do this manually so that removing elements and creating new ones doesn't + // cause the height (and therefore scroll) to jump backwards temporarily. + // storyContainer.style.height = contentBottomEdgeY()+"px"; + + if( !firstTime ) + scrollDown(previousBottomEdge); + + } + + function restart() { + story.ResetState(); + + setVisible(".header", true); + removeAll(".choice", true); + + // set save point to here + savePoint = story.state.toJson(); + + continueStory(true); + + outerScrollContainer.scrollTo({ top: 0, left: 0, behavior: 'smooth'}); + } + + // ----------------------------------- + // Various Helper functions + // ----------------------------------- + + // Fades in an element after a specified delay + function showAfter(delay, el) { + el.classList.add("hide"); + setTimeout(function() { + setTimeout(function() { el.classList.remove("hide") }, delay); + }); + } + + function insertAfter(delay, target, el, fade_in = true) { + if(fade_in) { + el.classList.add("fade-in"); + scheduleTimeout(function() { + target.appendChild(el); + el.scrollIntoView({ behavior: 'smooth'}); + }, delay); + } else { + scheduleTimeout(function() { + target.appendChild(el); + }, delay); + } + } + + // Scrolls the page down, but no further than the bottom edge of what you could + // see previously, so it doesn't go too far. + function scrollDown(previousBottomEdge) { + return; // TODO: Fix or remove function + // Line up top of screen with the bottom of where the previous content ended + var target = previousBottomEdge; + + // Can't go further than the very bottom of the page + var limit = outerScrollContainer.scrollHeight - outerScrollContainer.clientHeight; + if( target > limit ) target = limit; + + var start = outerScrollContainer.scrollTop; + + var dist = target - start; + var duration = 300 + 300*dist/100; + var startTime = null; + function step(time) { + if( startTime == null ) startTime = time; + var t = (time-startTime) / duration; + var lerp = 3*t*t - 2*t*t*t; // ease in/out + outerScrollContainer.scrollTo({ left: 0, top: (1.0-lerp)*start + lerp*target, behavior: 'smooth'}); + if( t < 1 ) requestAnimationFrame(step); + } + requestAnimationFrame(step); + } + + // The Y coordinate of the bottom end of all the story content, used + // for growing the container, and deciding how far to scroll. + function contentBottomEdgeY() { + var bottomElement = storyContainer.lastElementChild; + return bottomElement ? bottomElement.offsetTop + bottomElement.offsetHeight : 0; + } + + // Remove all elements that match the given selector. Used for removing choices after + // you've picked one, as well as for the CLEAR and RESTART tags. + function removeAll(selector, choices = false) + { + if(choices) + var allElements = choiceContainer.querySelectorAll(selector); + else + var allElements = storyContainer.querySelectorAll(selector); + for(var i=0; i { + + var element = document.getElementById("lighting"); + window.running = false; + window.fastForwardingAll = false; + window.speech = false; + + function setRandomDuration(event) { + var randomDuration = Math.random() * (5 - 0.1) + 0.1; + var previousDirection = event.animationName; + // element.style.animation = null; + // console.log("Animation restarts from:", element.style.animationName, event); + if (previousDirection == 'gradient-animation-grow') + element.style.animation = `gradient-animation-shrink ${randomDuration}s 1`; + else + element.style.animation = `gradient-animation-grow ${randomDuration}s 1`; + } + + async function fetch_include(filename) { + const response = await fetch(filename); + code = await response.text(); + // console.log("Loaded include:", JSON.parse(code)); + return JSON.parse(code); + } + + var storyContent = {}; + // const storyContent = fetch_include('Herrenhaus.js'); + // const file_contents_1 = fetch_include("code/Main.ink"); + // const file_contents_2 = fetch_include("code/Stats.ink"); + + // const fileHandler = new inkjs.JsonFileHandler({ + // "Main.ink": file_contents_1, + // "Stats.ink": file_contents_2 + // }); + // const errorHandler = (message, errorType) => { + // console.log(message + "\n"); + // } + // const story = new inkjs.Compiler(file_contents_1, {fileHandler, errorHandler}).Compile(); + // // story is an inkjs.Story that can be played right away + + // storyContent = story.ToJson(); + // // the generated json can be further re-used + +const translations = { + 'en-us': { + by: "", + speed: "speed*", + title_speed: "Set speed of text animation", + restart: "restart", + title_restart: "Restart story from beginning", + save: "save", + title_save: "Save progress", + load: "load", + title_load: "Reload from save point", + prompt: "What do you want to do?", + remark: "*click on the right page or press the spacebar
to fast forward the text-animation
", + end: "The End", + action_examine: "objects to examine", + action_comment: "topics to comment on", + action_ask: "things to ask about", + action_interact: "things to interact with", + action_reflect: "things to reflect on", + action_inventory: "things you carry with you", + speech: "Speech", + title_speech: "Toggle text to speech" + }, + 'de': { + by: "", + speed: "Geschwindikeit*", + title_speed: "Geschwindigkeit der Textanimation einstellen", + restart: "Neustart", + title_restart: "Die Geschichte von vorne beginnen", + save: "Speichern", + title_save: "Den Fortschritt der Geschichte speichern", + load: "Laden", + title_load: "Zum gespeicherten Spielfortschritt zurückkehren", + prompt: "Was möchtest du tun?", + remark: "*Klicke auf die rechte Buchseite oder drücke die Leertaste
um die Textanimation zu überspringen
", + end: "Ende", + action_examine: "Untersuchen", + action_comment: "Kommentieren", + action_ask: "Fragen", + action_interact: "Interagieren", + action_reflect: "Reflektieren", + action_inventory: "Inventar", + speech: "Sprachausgabe", + title_speech: "Sprachausgabe ein und ausschalten" + } +}; + +// Function to change locale +function setLocale(locale) { + if (translations[locale]) { + Object.keys(translations[locale]).forEach(key => { + const prefix = key.substring(0, 5); + const postfix = key.substring(6, key.length); + // console.log("Detected translation:", key, prefix, postfix); + const elements = document.querySelectorAll(`.l10n-${(prefix === 'title' ? postfix : key)}`); + elements.forEach(element => { + // console.log("Translating:", element, locale, key); + if(prefix === "title") + element.title = translations[locale][key]; + else + element.innerHTML = translations[locale][key]; + }); + }); + } else { + console.error(`Locale ${locale} is not defined`); + } +} + +setLocale(locale); +// console.log("SmartyPants:", SmartyPants.smartypants('"Dies ist ein Test...", sagte Georg.', 1)); + +Hyphenopoly.config({ + require: { + "en-us": "FORCEHYPHENOPOLY", + "de": "FORCEHYPHENOPOLY" + }, + paths: { + maindir: "./", + patterndir: "./patterns/" + }, + setup: { + selectors: { + ".hyphenate": { + hyphen: "\u00AD" + }, + ".hyphenatePipe": { + hyphen: "|" + } + } + } +}); + +Hyphenopoly.hyphenators[locale].then((hyphenator_en) => { + (async function(storyContent) { + // const response = await fetch('TheIntercept.ink.json'); + const response = await fetch('Herrenhaus.ink.json'); + storyContent = await response.json(); + // console.log("Loading game:", response, storyContent); + + // Create ink story from the content using inkjs + var story = new inkjs.Story(storyContent); + var cev = () => {}; + var savePoint = ""; + var rstack = []; + var ruler = document.getElementById('ruler'); + var measure = []; + + rstack.push(ruler); + + var hasSave = false; + element.addEventListener("animationend", setRandomDuration); // Set new duration each time animation ends + window.addEventListener("turnCompleteEvent", event => { + // console.log("Turn ended:", event); + window.running = false; + window.fastForwardingAll = false; + window.indented_paragraphs = 0; + + if (hasSave) { + document.getElementById("reload").removeAttribute("disabled"); + } + document.getElementById("rewind").removeAttribute("disabled"); + }); + + const speedSlider = document.getElementById('speed'); + window.speed = Math.pow(100.0 - speedSlider.value, 3) / 10000 * 10 + 0.01; + window.delay = 0.0; + speedSlider.oninput = function() { + window.speed = Math.pow(100.0 - this.value, 3) / 10000 * 10 + 0.01; + // console.log(`Speed: ${speed}ms`); // Replace this with your animation speed setting function + }; + + let fade_in = true; + + // Global tags - those at the top of the ink file + // We support: + // # title: Your Title + // # author: Your Name + // # subtitle: Your Subtitle + var globalTags = story.globalTags; + if( globalTags ) { + for(var i=0; i func(...args), + timeoutId: null + }; + + timeoutObject.timeoutId = setTimeout(() => { + timeoutObject.execute(); + timeoutQueue = timeoutQueue.filter(t => t !== timeoutObject); + if(timeoutQueue.length <= 0){ + let event = new CustomEvent("allWordsSetEvent", { + detail: { messages: "All scheduled word fade in animations were played."}, + bubbles: true, + cancelable: false + }); + document.dispatchEvent(event); + } + }, delay); + + timeoutQueue.push(timeoutObject); + + return timeoutObject.timeoutId; + } + + function fastForward() { + window.delay = 0.0; + // Sort the queue based on timeoutId (assuming that smaller ids are scheduled earlier) + timeoutQueue.sort((a, b) => a.timeoutId - b.timeoutId); + // Clear and execute all timeouts + timeoutQueue.forEach(timeoutObject => { + clearTimeout(timeoutObject.timeoutId); + timeoutObject.execute(); + }); + timeoutQueue = []; + let event = new CustomEvent("allWordsSetEvent", { + detail: { messages: "All scheduled word fade in animations were played."}, + bubbles: true, + cancelable: false + }); + document.dispatchEvent(event); + document.getElementById("page_right").scrollTo({top: document.getElementById("page_right").scrollHeight, behavior: 'smooth'}); + } + + function fastForwardAll() { + window.fastForwardingAll = true; + fastForward(); + } + + + function smoothScroll(target, duration) { + var display = document.getElementById('page_right'); + var targetPosition = target.getBoundingClientRect().top; + var startPosition = display.scrollTop; + var distance = targetPosition; + var startTime = null; + // console.log("Scheduled scrolldown to:", target, duration); + if(duration < 5) { + display.scrollTo(0, targetPosition); + return; + } + + function animation(currentTime) { + if (startTime === null) startTime = currentTime; + var timeElapsed = currentTime - startTime; + var run = ease(timeElapsed, startPosition, distance, duration); + display.scrollTo(0, run); + if (timeElapsed < duration) requestAnimationFrame(animation); + } + + function ease(t, b, c, d) { + // console.log("Easing:", t, b, c, d); + t /= d / 2; + if (t < 1) return c / 2 * t * t + b; + t--; + return -c / 2 * (t * (t - 2) - 1) + b; + } + + requestAnimationFrame(animation); + } + + function typesetParagraph(paragraph_data, delay = 0, measure = []) { + var stack = []; + var left = 0; + var p = document.createElement("p"); + p.style.position = 'relative'; + p.classList.add("latest-paragraph"); + p.dataset.numberOfLines = paragraph_data.breaks.length - 1; + var line_height = parseFloat(window.getComputedStyle(document.querySelector('#ruler')).lineHeight); + var line_width = parseFloat(window.getComputedStyle(document.getElementById('story')).width); + var page_height = parseFloat(window.getComputedStyle(document.getElementById('page_right')).height); + p.style.height = line_height * (paragraph_data.breaks.length - 1) + 'px'; + var paragraph_height = parseFloat(p.style.height); + p.dataset.vpc = paragraph_height * 100 / page_height; + p.style.marginBlockEnd = 0; + stack.push(p); + for(let i = 1; i < paragraph_data.breaks.length; i++) { + left = measure[measure.length - 1] - measure[Math.min(i - 1, measure.length - 1)]; + var lastChild = null; + var syllable = ""; + for(let j = paragraph_data.breaks[i-1].position; j <= paragraph_data.breaks[i].position; j++) { + if(paragraph_data.nodes[j].type === 'box' && paragraph_data.nodes[j].value !== '' && j < paragraph_data.breaks[i].position) { + if(j > paragraph_data.breaks[i-1].position + 1 && paragraph_data.nodes[j-1].type === 'penalty' && lastChild) { + syllable += '\u200c' + paragraph_data.nodes[j].value; + lastChild.innerHTML = syllable; + left += paragraph_data.nodes[j].width; + } else { + let word = document.createElement("span"); + word.style.position = 'absolute'; + word.classList.add("fade-in"); + word.style.animationDuration = speed * 10 + 'ms'; + word.style.top = line_height * (i - 1) * 100 / paragraph_height + '%'; + // word.style.left = left + 'px'; + word.style.left = left * 100 / line_width + '%'; + syllable = paragraph_data.nodes[j].value; + word.innerHTML = syllable; + lastChild = word; + if(!window.fastForwardingAll) + insertAfter(delay, stack[stack.length-1], word); + delay += window.speed; + left += paragraph_data.nodes[j].width; + } + } else if(paragraph_data.nodes[j].type === 'tag') { + if(paragraph_data.nodes[j].value.substr(0,2) == ' paragraph_data.breaks[i-1].position && paragraph_data.nodes[j].type === 'glue' && paragraph_data.nodes[j].width !== 0 && j <= paragraph_data.breaks[i].position) { + // Insert space character + if(paragraph_data.breaks[i].ratio > 0) { + left += paragraph_data.nodes[j].width + paragraph_data.breaks[i].ratio * paragraph_data.nodes[j].stretch; + } else { + left += paragraph_data.nodes[j].width + paragraph_data.breaks[i].ratio * paragraph_data.nodes[j].shrink; + } + let word = document.createElement("span"); + word.style.position = 'absolute'; + word.classList.add("fade-in"); + word.style.top = line_height * (i - 1) * 100 / paragraph_height + '%'; + // word.style.left = left + 'px'; + word.style.left = left * 100 / line_width + '%'; + word.innerHTML = " "; + if(!window.fastForwardingAll) + insertAfter(delay, stack[stack.length-1], word); + } else if(paragraph_data.nodes[j].type === 'penalty' && paragraph_data.nodes[j].penalty === 100 && j === paragraph_data.breaks[i].position) { + let word = document.createElement("span"); + word.style.position = 'absolute'; + word.style.top = line_height * (i - 1) * 100 / paragraph_height + '%'; + // word.style.left = left + 'px'; + word.style.left = left * 100 / line_width + '%'; + word.innerHTML = "-"; + if(!window.fastForwardingAll) + insertAfter(delay, stack[stack.length-1], word); + delay += window.speed; + } + } + }; + return [p, delay]; + } + + function measureText(str) { + if(str.substr(0, 2) == ' imageAspectRatio) { + bookWidth = vh * imageAspectRatio; + bookHeight = vh; + } else { + bookWidth = vw; + bookHeight = vw / imageAspectRatio; + } + + document.documentElement.style.setProperty('--book-width', `${bookWidth}px`); + document.documentElement.style.setProperty('--book-height', `${bookHeight}px`); + + // Setting a CSS variable that will be either vw or vh depending on the viewport aspect ratio + document.documentElement.style.setProperty( + "--viewport-dimension", + viewportAspectRatio > imageAspectRatio ? 'vw' : 'vh' + ); + document.documentElement.style.setProperty('--viewport-aspect-ratio', viewportAspectRatio); + let story = document.getElementById("story"); + let paddingTop = window.getComputedStyle(story).paddingTop; + let paddingBottom = window.getComputedStyle(story).paddingBottom; + document.documentElement.style.setProperty('--story-line-height', (story.clientHeight - paddingTop - paddingBottom) / 28); + updateParagraphHeight(); + } + + function updateParagraphHeight() { + document.querySelectorAll("#story p").forEach((element) => { + let pHeight = parseFloat(window.getComputedStyle(document.getElementById('page_right')).height); + let newHeight = pHeight * element.dataset.vpc / 100 + 'px'; + element.style.height = newHeight; + }); + } + + // Update the aspect ratio when the page loads + updateBookDimensions(); + + // Update the aspect ratio whenever the window is resized + window.addEventListener('resize', updateBookDimensions); + + window.addEventListener('keydown', (event) => { + if (event.code === 'Space') { + fade_in = false; + fastForward(); + } + }); + + document.getElementById('page_right').addEventListener('click', (event) => { + fade_in = false; + fastForward(); + }); + + // page features setup + hasSave = loadSavePoint(); + setupButtons(hasSave); + + // Set initial save point + savePoint = story.state.toJson(); + + // Kick off the start of the story! + continueStory(); + + // Main story processing function. Each time this is called it generates + // all the next content up as far as the next set of choices. + async function continueStory(first_time = true) { + + createChoiceContainer = (categoryContainers, categoryNumbers, action, prompt, choice, tagDebug, registerKeys = false) => { + var choiceCategoryContainer = categoryContainers[action]; + if(!choiceCategoryContainer) { + console.log("Creating new category choice container for:", categoryContainers, categoryNumbers, action, prompt, choice, registerKeys, choiceContainer); + choiceCategoryContainer = document.createElement('ol'); + var p = document.createElement('p'); + p.innerHTML = (prompt); + choiceCategoryContainer.appendChild(p); + choiceCategoryContainer.classList.add("choice"); + choiceCategoryContainer.classList.add("fade-in"); + if(!registerKeys) + choiceCategoryContainer.classList.add("categorized"); + if(story.currentChoices.length && !window.fastForwardingAll) + choiceContainer.appendChild(choiceCategoryContainer); + } + categoryContainers[action] = choiceCategoryContainer; + var choiceNumber = categoryNumbers[action]; + if(choiceNumber === undefined) + choiceNumber = 0; + choiceNumber++; + var choiceParagraphElement = document.createElement('li'); + choiceParagraphElement.classList.add("choice"); + choiceParagraphElement.lang = locale; + choiceParagraphElement.title = tagDebug; + choiceParagraphElement.innerHTML = `
${SmartyPants.smartypantsu(choice.text, 1)}` + if(!window.fastForwardingAll) + insertAfter(window.delay, choiceCategoryContainer, choiceParagraphElement, fade_in); + window.delay += window.speed; + // Press choice key + if(registerKeys) { + choiceParagraphElement.value = choiceNumber; + registerKey('Digit' + choiceNumber, choice.index); + } else { + var categorizedNumber = categoryNumbers['categorized']; + categorizedNumber++; + var keyLetter = String.fromCharCode(64 + categorizedNumber); + console.log("Registering key:", keyLetter, categorizedNumber, choice.index); + choiceParagraphElement.value = categorizedNumber; + registerKey('Key' + keyLetter, choice.index); + categoryNumbers['categorized'] = categorizedNumber; + } + // Click on choice + var choiceAnchorEl = choiceParagraphElement.querySelectorAll("a")[0]; + choiceAnchorEl.addEventListener("click", (event) => { + // Don't follow link + event.preventDefault(); + choose(choice.index); + }); + categoryNumbers[action] = choiceNumber; + } + + var fade_in = true; + window.running = true; + window.fastForwardingAll = false; + chapter_begin = false; + this.keyRegistry = {}; + if(measure.length == 1) + measure.pop(); // Remove lingering measures if all that is left is the full line. + + document.querySelectorAll('#story p').forEach((p) => { p.classList.remove("latest-paragraph")}); + + // Generate story text - loop through available content + while(story.canContinue) { + if(window.fastForwardingAll) + return; + window.delay = 0.0; + // Get ink to generate the next paragraph + var paragraphText = story.Continue(); + var tags = story.currentTags; + + // Any special tags included with this line + var customClasses = []; + var tagDebug = ""; + for(var i=0; i 1) + first_word += ' ' + words[1]; + text = '' + first_word + ' ' + paragraphText.substr(first_word.length + 2 + opening_quote.length, paragraphText.length); + console.log("Created chapter begin:", words, first_word, first_letter); + drop_cap = document.createElement("span"); + drop_cap.classList.add("drop-cap"); + drop_cap.appendChild(document.createTextNode(first_letter)); + drop_cap.style.left = '0%'; + drop_cap.style.top = '0%'; + drop_cap.style.position = 'absolute'; + if(opening_quote) { + drop_quote = document.createElement("span"); + drop_quote.classList.add("drop-quote"); + drop_quote.appendChild(document.createTextNode(opening_quote)); + drop_quote.style.left = '-4.45%'; + drop_quote.style.top = '-16%'; + drop_quote.style.position = 'absolute'; + } + } else { + if(measure.length < 1) { + measure.push(parseFloat(window.getComputedStyle(document.getElementById("story")).width)); + measure.push(parseFloat(window.getComputedStyle(document.getElementById("story")).width) - indentWidth * 0.5); + } + } + var preview_data = kap(hyphenator_en(SmartyPants.smartypantsu(text, 1), '.hyphenatePipe'), measureText, measure.toReversed(), true); + var p, d; + [p, d] = typesetParagraph(preview_data, window.delay, measure.toReversed()); + for(let k = 0; k < parseInt(p.dataset.numberOfLines); k++) { + measure.pop(); + } + window.indented_paragraphs -= p.dataset.numberOfLines; + console.log("Reducing indented_paragraphes to:", window.indented_paragraphs, p, preview_data, measure); + if(drop_quote) + insertAfter(0, p, drop_quote, true); + if(drop_cap) + insertAfter(0, p, drop_cap, true); + // window.delay = d; + // Add any custom classes derived from ink tags + for(var i=0; i { + document.addEventListener('allWordsSetEvent', resolve, { once: true }); + }), new Promise(async resolve => { + if(!window.speech) { + resolve(); + return; + } + let filepath = await window.elevenlabs.getSpeech(text); + const audio = new Audio(`${filepath}`); + audio.onended = resolve; // Resolve the promise when the audio ends + audio.play(); + // Listen for a click event to fade out the audio + storyContainer.addEventListener('click', fadeOutAudio); + + // Listen for a keypress event to fade out the audio + window.addEventListener('keydown', fadeOutAudio); + + audio.play(); + + function fadeOutAudio(event) { + if((event instanceof KeyboardEvent && event.key === ' ') || (event instanceof MouseEvent && event.type === 'click')) { + // Stop listening for the click and keypress events + storyContainer.removeEventListener('click', fadeOutAudio); + window.removeEventListener('keydown', fadeOutAudio); + + // Fade out the audio by decrementing the volume + let volume = 1.0; + const fadeInterval = setInterval(() => { + if (volume > 0.1) { + volume -= 0.1; // Change this to make the fade out faster or slower + audio.volume = volume; + } else { + // Stop the fade out + clearInterval(fadeInterval); + + // Stop the audio + audio.pause(); + resolve(); + } + }, window.speed); // Change this to make the fade out faster or slower + + } + } + })]) + } + + window.delay = 0.0; + // Create HTML choices from ink choices + var categoryContainers = { default: null } + var categoryNumbers = { default: 0, categorized: 0 } + story.currentChoices.forEach(function(choice) { + if(window.fastForwardingAll) + return; + // Create paragraph with anchor element + var tagDebug = ""; + var action = "default"; + choice.tags.forEach(tag => { + tagDebug += tag + ";" + var splitTag = splitPropertyTag(tag); + // console.log("Split choice tag:", splitTag); + if(splitTag.property === "ACTION") + action = splitTag.val; + }); + + if(action != "default") { + createChoiceContainer(categoryContainers, categoryNumbers, action, translations[locale]['action_' + action], choice, tagDebug); + } else { + createChoiceContainer(categoryContainers, categoryNumbers, "default", translations[locale]['prompt'], choice, tagDebug, true); + } + }); + + cev = (event) => { + console.log("Key pressed:", event, this.keyRegistry); + for(const key in this.keyRegistry) { + if(event.code === key) { + window.removeEventListener('keypress', cev); + choose(this.keyRegistry[key]); + break; + } + } + }; + window.addEventListener('keypress', cev); + + function choose(index) { + // Remove all existing choices + removeAll(".choice", true); + clearKeyRegistry(); + + // Tell the story where to go next + story.ChooseChoiceIndex(index); + + // This is where the save button will save from + savePoint = story.state.toJson(); + + // Aaand loop + continueStory(false); + } + + function registerKey(key, choice) { + this.keyRegistry[key] = choice; + } + + function clearKeyRegistry() { + this.keyRegistry = {}; + } + var tce = new CustomEvent("turnCompleteEvent", { + detail: { messages: "All text and choices have been set up."}, + bubbles: true, + cancelable: false + }); + document.dispatchEvent(tce); + if(story.canContinue === false && story.currentChoices.length === 0) { + var end = document.createElement("p"); + end.style.textTransform = "uppercase"; + end.style.textAlign = "center"; + end.classList.add("fade-in"); + end.classList.add("choice"); + end.appendChild(document.createTextNode(translations[locale]['end'])); + choiceContainer.appendChild(end); + } + } + + function restartStory() { + window.delay = 0.0; + story.ResetState(); + fastForwardAll(); + setVisible(".header", true); + removeAll("p"); + removeAll("img"); + removeAll("h2"); + removeAll("double"); + removeAll(".choice", true); + window.removeEventListener('keypress', cev); + + // set save point to here + savePoint = story.state.toJson(); + } + + // ----------------------------------- + // Various Helper functions + // ----------------------------------- + + // Fades in an element after a specified delay + function showAfter(delay, el) { + el.classList.add("hide"); + setTimeout(function() { + setTimeout(function() { el.classList.remove("hide") }, delay); + }); + } + + function insertAfter(delay, target, el, fade_in = true) { + if(fade_in) { + el.classList.add("fade-in"); + scheduleTimeout(function() { + target.appendChild(el); + // el.scrollIntoView({ behavior: 'smooth'}); + }, delay); + } else { + scheduleTimeout(function() { + target.appendChild(el); + }, delay); + } + } + + // Remove all elements that match the given selector. Used for removing choices after + // you've picked one, as well as for the CLEAR and RESTART tags. + function removeAll(selector, choices = false) + { + if(choices) + var allElements = choiceContainer.querySelectorAll(selector); + else + var allElements = storyContainer.querySelectorAll(selector); + for(var i=0; i { + let d = document.createElement('div'); + d.innerHTML = p; + document.getElementById('story').appendChild(d.firstChild); + }); + story.state.LoadJson(savedState); + updateParagraphHeight(); + window.removeEventListener('keypress', cev); + return true; + } + } catch (e) { + console.debug("Couldn't load save state"); + } + return false; + } + + // Used to hook up the functionality for global functionality buttons + function setupButtons(hasSave) { + + let rewindEl = document.getElementById("rewind"); + let saveEl = document.getElementById("save"); + let reloadEl = document.getElementById("reload"); + let speedEl = document.getElementById("speed_reset"); + let speechEl = document.getElementById("speech"); + + if (rewindEl) rewindEl.addEventListener("click", function(event) { + if (rewindEl.getAttribute("disabled") == "disabled") + return; + rewindEl.setAttribute("disabled", "disabled"); + reloadEl.setAttribute("disabled", "disabled"); + restartStory(); + if(window.running) + window.addEventListener("turnCompleteEvent", continueStory()); + else { + // if (hasSave) { + // document.getElementById("reload").removeAttribute("disabled"); + // } + // document.getElementById("rewind").removeAttribute("disabled"); + continueStory(); + } + }); + + if (saveEl) saveEl.addEventListener("click", function(event) { + if (save.getAttribute("disabled") == "disabled") + return; + try { + let history = Array.from(document.querySelectorAll("#story p:not(.latest-paragraph)")).map(p => p.outerHTML); + // console.log("Saving history:", history); + window.localStorage.setItem('save-history', JSON.stringify(history)); + window.localStorage.setItem('save-state', savePoint); + hasSave = true; + reloadEl.removeAttribute("disabled"); + } catch (e) { + console.warn("Couldn't save state"); + } + + }); + + reloadEl.addEventListener("click", function(event) { + if (reloadEl.getAttribute("disabled") == "disabled") + return; + reloadEl.setAttribute("disabled", "disabled"); + rewindEl.setAttribute("disabled", "disabled"); + fastForwardAll(); + removeAll("p"); + removeAll("img"); + removeAll("h2"); + removeAll("double"); + removeAll(".choice", true); + loadSavePoint(); + if(window.running) + window.addEventListener("turnCompleteEvent", continueStory()); + else { + // if (hasSave) { + // document.getElementById("reload").removeAttribute("disabled"); + // } + // document.getElementById("rewind").removeAttribute("disabled"); + continueStory(); + } + }); + + speedEl.addEventListener('click', () => { + let range = document.getElementById('speed'); + range.value = 50; + range.dispatchEvent(new Event('input')); + + }); + + speechEl.addEventListener('click', () => { + window.speech = !window.speech; + if(speechEl.getAttribute('disabled') === 'disabled') + speechEl.removeAttribute('disabled'); + else + speechEl.setAttribute('disabled', 'disabled'); + }) + } + + })(storyContent); +}); +}; \ No newline at end of file diff --git a/prototype/index.html b/prototype/index.html new file mode 100644 index 0000000..1ff8097 --- /dev/null +++ b/prototype/index.html @@ -0,0 +1,57 @@ + + + + + + + + Ink.js Book Runtime + + + +

We are using Node.js , + Chromium , + and Electron .

+
+
+
+ +

+

+
+
+
+
+
+
*click on page or press spacebar to fast forward text animation
+
+ +
+
+
What do you want to do next?
+
+ + + + + + + + + + + + + + diff --git a/prototype/ink-full.js b/prototype/ink-full.js new file mode 100644 index 0000000..4ba6b45 --- /dev/null +++ b/prototype/ink-full.js @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).inkjs={})}(this,(function(t){"use strict";class e{constructor(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;this.sourceFilename=t,this.pluginNames=e,this.countAllVisits=n,this.errorHandler=i,this.fileHandler=r}}class n{constructor(t,e,n){this.length=t,this.debugMetadata=e,this.text=n}}var i;!function(t){t[t.Author=0]="Author",t[t.Warning=1]="Warning",t[t.Error=2]="Error"}(i||(i={}));class r{constructor(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;this.identifier=t,this.isByReference=e,this.isDivertTarget=n}get typeName(){return"Argument"}}function s(t,e){return t instanceof e?u(t):null}function a(t,e){if(t instanceof e)return u(t);throw new Error(`${t} is not of type ${e}`)}function o(t){return t.hasValidName&&t.name?t:null}function l(t){return void 0===t?null:t}function h(t){return"object"==typeof t&&"function"==typeof t.Equals}function u(t,e){return t}function c(t){return null!=t}class d{constructor(){var t=this;this._alreadyHadError=!1,this._alreadyHadWarning=!1,this._debugMetadata=null,this._runtimeObject=null,this.content=[],this.parent=null,this.GetType=()=>this.typeName,this.AddContent=t=>{null===this.content&&(this.content=[]);const e=Array.isArray(t)?t:[t];for(const t of e)t.hasOwnProperty("parent")&&(t.parent=this),this.content.push(t);return Array.isArray(t)?void 0:t},this.InsertContent=(t,e)=>(null===this.content&&(this.content=[]),e.parent=this,this.content.splice(t,0,e),e),this.Find=e=>function(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,i=s(t,e);if(null!==i&&(null===n||!0===n(i)))return i;if(null===t.content)return null;for(const i of t.content){let t=i.Find&&i.Find(e)(n);if(t)return t}return null},this.FindAll=t=>(e,n)=>{const i=Array.isArray(n)?n:[],r=s(this,t);if(null===r||e&&!0!==e(r)||i.push(r),null===this.content)return[];for(const n of this.content)n.FindAll&&n.FindAll(t)(e,i);return i},this.Warning=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;t.Error(e,n,!0)}}get debugMetadata(){return null===this._debugMetadata&&this.parent?this.parent.debugMetadata:this._debugMetadata}set debugMetadata(t){this._debugMetadata=t}get hasOwnDebugMetadata(){return Boolean(this.debugMetadata)}get typeName(){return"ParsedObject"}get story(){let t=this;for(;t.parent;)t=t.parent;return t}get runtimeObject(){return this._runtimeObject||(this._runtimeObject=this.GenerateRuntimeObject(),this._runtimeObject&&(this._runtimeObject.debugMetadata=this.debugMetadata)),this._runtimeObject}set runtimeObject(t){this._runtimeObject=t}get runtimePath(){if(!this.runtimeObject.path)throw new Error;return this.runtimeObject.path}get containerForCounting(){return this.runtimeObject}get ancestry(){let t=[],e=this.parent;for(;e;)t.push(e),e=e.parent;return t=t.reverse(),t}ResolveReferences(t){if(null!==this.content)for(const e of this.content)e.ResolveReferences(t)}Error(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(null===e&&(e=this),!(e._alreadyHadError&&!n||e._alreadyHadWarning&&n)){if(!this.parent)throw new Error(`No parent object to send error to: ${t}`);this.parent.Error(t,e,n),n?e._alreadyHadWarning=!0:e._alreadyHadError=!0}}}class p extends d{constructor(t){super(),this.warningMessage=t,this.GenerateRuntimeObject=()=>(this.Warning(this.warningMessage),null)}get typeName(){return"AuthorWarning"}}let m=class t{constructor(){if(this._components=[],this._componentsString=null,this._isRelative=!1,"string"==typeof arguments[0]){let t=arguments[0];this.componentsString=t}else if(arguments[0]instanceof t.Component&&arguments[1]instanceof t){let t=arguments[0],e=arguments[1];this._components.push(t),this._components=this._components.concat(e._components)}else if(arguments[0]instanceof Array){let t=arguments[0],e=!!arguments[1];this._components=this._components.concat(t),this._isRelative=e}}get isRelative(){return this._isRelative}get componentCount(){return this._components.length}get head(){return this._components.length>0?this._components[0]:null}get tail(){if(this._components.length>=2){let e=this._components.slice(1,this._components.length);return new t(e)}return t.self}get length(){return this._components.length}get lastComponent(){let t=this._components.length-1;return t>=0?this._components[t]:null}get containsNamedComponent(){for(let t=0,e=this._components.length;t=0}get isParent(){return this.name==t.parentId}static ToParent(){return new e(t.parentId)}toString(){return this.isIndex?this.index.toString():this.name}Equals(t){return null!=t&&t.isIndex==this.isIndex&&(this.isIndex?this.index==t.index:this.name==t.name)}}t.Component=e}(m||(m={})),function(t){function e(t,e){if(!t)throw void 0!==e&&console.warn(e),console.trace&&console.trace(),new Error("")}t.AssertType=function(t,n,i){e(t instanceof n,i)},t.Assert=e}(f||(f={}));class C extends Error{}function S(t){throw new C(`${t} is null or undefined`)}class y{constructor(){this.parent=null,this._debugMetadata=null,this._path=null}get debugMetadata(){return null===this._debugMetadata&&this.parent?this.parent.debugMetadata:this._debugMetadata}set debugMetadata(t){this._debugMetadata=t}get ownDebugMetadata(){return this._debugMetadata}DebugLineNumberOfPath(t){if(null===t)return null;let e=this.rootContentContainer;if(e){let n=e.ContentAtPath(t).obj;if(n){let t=n.debugMetadata;if(null!==t)return t.startLineNumber}}return null}get path(){if(null==this._path)if(null==this.parent)this._path=new m;else{let t=[],e=this,n=s(e.parent,L);for(;null!==n;){let i=o(e);if(null!=i&&i.hasValidName){if(null===i.name)return S("namedChild.name");t.unshift(new m.Component(i.name))}else t.unshift(new m.Component(n.content.indexOf(e)));e=n,n=s(n.parent,L)}this._path=new m(t)}return this._path}ResolvePath(t){if(null===t)return S("path");if(t.isRelative){let e=s(this,L);return null===e&&(f.Assert(null!==this.parent,"Can't resolve relative path because we don't have a parent"),e=s(this.parent,L),f.Assert(null!==e,"Expected parent to be a container"),f.Assert(t.GetComponent(0).isParent),t=t.tail),null===e?S("nearestContainer"):e.ContentAtPath(t)}{let e=this.rootContentContainer;return null===e?S("contentContainer"):e.ContentAtPath(t)}}ConvertPathToRelative(t){let e=this.path,n=Math.min(t.length,e.length),i=-1;for(let r=0;r1?e-1:0),i=1;ivoid 0!==n[e]?n[e]:t))}toString(){return this.string}Clear(){this.string=""}}class w{constructor(){if(this.originName=null,this.itemName=null,void 0!==arguments[1]){let t=arguments[0],e=arguments[1];this.originName=t,this.itemName=e}else if(arguments[0]){let t=arguments[0].toString().split(".");this.originName=t[0],this.itemName=t[1]}}static get Null(){return new w(null,null)}get isNull(){return null==this.originName&&null==this.itemName}get fullName(){return(null!==this.originName?this.originName:"?")+"."+this.itemName}toString(){return this.fullName}Equals(t){if(t instanceof w){let e=t;return e.itemName==this.itemName&&e.originName==this.originName}return!1}copy(){return new w(this.originName,this.itemName)}serialized(){return JSON.stringify({originName:this.originName,itemName:this.itemName})}static fromSerializedKey(t){let e=JSON.parse(t);if(!w.isLikeInkListItem(e))return w.Null;let n=e;return new w(n.originName,n.itemName)}static isLikeInkListItem(t){return"object"==typeof t&&(!(!t.hasOwnProperty("originName")||!t.hasOwnProperty("itemName"))&&(("string"==typeof t.originName||null===typeof t.originName)&&("string"==typeof t.itemName||null===typeof t.itemName)))}}class E extends Map{constructor(){if(super(arguments[0]instanceof E?arguments[0]:[]),this.origins=null,this._originNames=[],arguments[0]instanceof E){let t=arguments[0],e=t.originNames;null!==e&&(this._originNames=e.slice()),null!==t.origins&&(this.origins=t.origins.slice())}else if("string"==typeof arguments[0]){let t=arguments[0],e=arguments[1];if(this.SetInitialOriginName(t),null===e.listDefinitions)return S("originStory.listDefinitions");let n=e.listDefinitions.TryListGetDefinition(t,null);if(!n.exists)throw new Error("InkList origin could not be found in story when constructing new list: "+t);if(null===n.result)return S("def.result");this.origins=[n.result]}else if("object"==typeof arguments[0]&&arguments[0].hasOwnProperty("Key")&&arguments[0].hasOwnProperty("Value")){let t=arguments[0];this.Add(t.Key,t.Value)}}static FromString(t,e){var n;let i=null===(n=e.listDefinitions)||void 0===n?void 0:n.FindSingleItemListWithName(t);if(i)return null===i.value?S("listValue.value"):new E(i.value);throw new Error("Could not find the InkListItem from the string '"+t+"' to create an InkList because it doesn't exist in the original list definition in ink.")}AddItem(t){if(t instanceof w){let e=t;if(null==e.originName)return void this.AddItem(e.itemName);if(null===this.origins)return S("this.origins");for(let t of this.origins)if(t.name==e.originName){let n=t.TryGetValueForItem(e,0);if(n.exists)return void this.Add(e,n.result);throw new Error("Could not add the item "+e+" to this list because it doesn't exist in the original list definition in ink.")}throw new Error("Failed to add item to list because the item was from a new list definition that wasn't previously known to this list. Only items from previously known lists can be used, so that the int value can be found.")}{let e=t,n=null;if(null===this.origins)return S("this.origins");for(let t of this.origins){if(null===e)return S("itemName");if(t.ContainsItemWithName(e)){if(null!=n)throw new Error("Could not add the item "+e+" to this list because it could come from either "+t.name+" or "+n.name);n=t}}if(null==n)throw new Error("Could not add the item "+e+" to this list because it isn't known to any list definitions previously associated with this list.");let i=new w(n.name,e),r=n.ValueForItem(i);this.Add(i,r)}}ContainsItemNamed(t){for(let[e]of this){if(w.fromSerializedKey(e).itemName==t)return!0}return!1}ContainsKey(t){return this.has(t.serialized())}Add(t,e){let n=t.serialized();if(this.has(n))throw new Error(`The Map already contains an entry for ${t}`);this.set(n,e)}Remove(t){return this.delete(t.serialized())}get Count(){return this.size}get originOfMaxItem(){if(null==this.origins)return null;let t=this.maxItem.Key.originName,e=null;return this.origins.every((n=>n.name!=t||(e=n,!1))),e}get originNames(){if(this.Count>0){null==this._originNames&&this.Count>0?this._originNames=[]:(this._originNames||(this._originNames=[]),this._originNames.length=0);for(let[t]of this){let e=w.fromSerializedKey(t);if(null===e.originName)return S("item.originName");this._originNames.push(e.originName)}}return this._originNames}SetInitialOriginName(t){this._originNames=[t]}SetInitialOriginNames(t){this._originNames=null==t?null:t.slice()}get maxItem(){let t={Key:w.Null,Value:0};for(let[e,n]of this){let i=w.fromSerializedKey(e);(t.Key.isNull||n>t.Value)&&(t={Key:i,Value:n})}return t}get minItem(){let t={Key:w.Null,Value:0};for(let[e,n]of this){let i=w.fromSerializedKey(e);(t.Key.isNull||nt.maxItem.Value)}GreaterThanOrEquals(t){return 0!=this.Count&&(0==t.Count||this.minItem.Value>=t.minItem.Value&&this.maxItem.Value>=t.maxItem.Value)}LessThan(t){return 0!=t.Count&&(0==this.Count||this.maxItem.Value0?new E(this.maxItem):new E}MinAsList(){return this.Count>0?new E(this.minItem):new E}ListWithSubRange(t,e){if(0==this.Count)return new E;let n=this.orderedItems,i=0,r=Number.MAX_SAFE_INTEGER;Number.isInteger(t)?i=t:t instanceof E&&t.Count>0&&(i=t.minItem.Value),Number.isInteger(e)?r=e:e instanceof E&&e.Count>0&&(r=e.maxItem.Value);let s=new E;s.SetInitialOriginNames(this.originNames);for(let t of n)t.Value>=i&&t.Value<=r&&s.Add(t.Key,t.Value);return s}Equals(t){if(t instanceof E==!1)return!1;if(t.Count!=this.Count)return!1;for(let[e]of this)if(!t.has(e))return!1;return!0}get orderedItems(){let t=new Array;for(let[e,n]of this){let i=w.fromSerializedKey(e);t.push({Key:i,Value:n})}return t.sort(((t,e)=>null===t.Key.originName?S("x.Key.originName"):null===e.Key.originName?S("y.Key.originName"):t.Value==e.Value?t.Key.originName.localeCompare(e.Key.originName):t.Valuee.Value?1:0)),t}toString(){let t=this.orderedItems,e=new b;for(let n=0;n0&&e.Append(", ");let i=t[n].Key;if(null===i.itemName)return S("item.itemName");e.Append(i.itemName)}return e.toString()}valueOf(){return NaN}}class _ extends Error{constructor(t){super(t),this.useEndLineNumber=!1,this.message=t,this.name="StoryException"}}function T(t,e,n){if(null===t)return{result:n,exists:!1};let i=t.get(e);return void 0===i?{result:n,exists:!1}:{result:i,exists:!0}}class x extends y{static Create(t,e){if(e){if(e===g.Int&&Number.isInteger(Number(t)))return new N(Number(t));if(e===g.Float&&!isNaN(t))return new O(Number(t))}return"boolean"==typeof t?new P(Boolean(t)):"string"==typeof t?new I(String(t)):Number.isInteger(Number(t))?new N(Number(t)):isNaN(t)?t instanceof m?new F(a(t,m)):t instanceof E?new R(a(t,E)):null:new O(Number(t))}Copy(){return a(x.Create(this.valueObject),y)}BadCastException(t){return new _("Can't cast "+this.valueObject+" from "+this.valueType+" to "+t)}}class A extends x{constructor(t){super(),this.value=t}get valueObject(){return this.value}toString(){return null===this.value?S("Value.value"):this.value.toString()}}class P extends A{constructor(t){super(t||!1)}get isTruthy(){return Boolean(this.value)}get valueType(){return g.Bool}Cast(t){if(null===this.value)return S("Value.value");if(t==this.valueType)return this;if(t==g.Int)return new N(this.value?1:0);if(t==g.Float)return new O(this.value?1:0);if(t==g.String)return new I(this.value?"true":"false");throw this.BadCastException(t)}toString(){return this.value?"true":"false"}}class N extends A{constructor(t){super(t||0)}get isTruthy(){return 0!=this.value}get valueType(){return g.Int}Cast(t){if(null===this.value)return S("Value.value");if(t==this.valueType)return this;if(t==g.Bool)return new P(0!==this.value);if(t==g.Float)return new O(this.value);if(t==g.String)return new I(""+this.value);throw this.BadCastException(t)}}class O extends A{constructor(t){super(t||0)}get isTruthy(){return 0!=this.value}get valueType(){return g.Float}Cast(t){if(null===this.value)return S("Value.value");if(t==this.valueType)return this;if(t==g.Bool)return new P(0!==this.value);if(t==g.Int)return new N(this.value);if(t==g.String)return new I(""+this.value);throw this.BadCastException(t)}}class I extends A{constructor(t){if(super(t||""),this._isNewline="\n"==this.value,this._isInlineWhitespace=!0,null===this.value)return S("Value.value");this.value.length>0&&this.value.split("").every((t=>" "==t||"\t"==t||(this._isInlineWhitespace=!1,!1)))}get valueType(){return g.String}get isTruthy(){return null===this.value?S("Value.value"):this.value.length>0}get isNewline(){return this._isNewline}get isInlineWhitespace(){return this._isInlineWhitespace}get isNonWhitespace(){return!this.isNewline&&!this.isInlineWhitespace}Cast(t){if(t==this.valueType)return this;if(t==g.Int){let e=function(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=parseInt(t);return Number.isNaN(n)?{result:e,exists:!1}:{result:n,exists:!0}}(this.value);if(e.exists)return new N(e.result);throw this.BadCastException(t)}if(t==g.Float){let e=function(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=parseFloat(t);return Number.isNaN(n)?{result:e,exists:!1}:{result:n,exists:!0}}(this.value);if(e.exists)return new O(e.result);throw this.BadCastException(t)}throw this.BadCastException(t)}}class F extends A{constructor(){super(arguments.length>0&&void 0!==arguments[0]?arguments[0]:null)}get valueType(){return g.DivertTarget}get targetPath(){return null===this.value?S("Value.value"):this.value}set targetPath(t){this.value=t}get isTruthy(){throw new Error("Shouldn't be checking the truthiness of a divert target")}Cast(t){if(t==this.valueType)return this;throw this.BadCastException(t)}toString(){return"DivertTargetValue("+this.targetPath+")"}}class W extends A{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;super(t),this._contextIndex=e}get contextIndex(){return this._contextIndex}set contextIndex(t){this._contextIndex=t}get variableName(){return null===this.value?S("Value.value"):this.value}set variableName(t){this.value=t}get valueType(){return g.VariablePointer}get isTruthy(){throw new Error("Shouldn't be checking the truthiness of a variable pointer")}Cast(t){if(t==this.valueType)return this;throw this.BadCastException(t)}toString(){return"VariablePointerValue("+this.variableName+")"}Copy(){return new W(this.variableName,this.contextIndex)}}class R extends A{get isTruthy(){return null===this.value?S("this.value"):this.value.Count>0}get valueType(){return g.List}Cast(t){if(null===this.value)return S("Value.value");if(t==g.Int){let t=this.value.maxItem;return t.Key.isNull?new N(0):new N(t.Value)}if(t==g.Float){let t=this.value.maxItem;return t.Key.isNull?new O(0):new O(t.Value)}if(t==g.String){let t=this.value.maxItem;return t.Key.isNull?new I(""):new I(t.Key.toString())}if(t==this.valueType)return this;throw this.BadCastException(t)}constructor(t,e){super(null),t||e?t instanceof E?this.value=new E(t):t instanceof w&&"number"==typeof e&&(this.value=new E({Key:t,Value:e})):this.value=new E}static RetainListOriginsForAssignment(t,e){let n=s(t,R),i=s(e,R);return i&&null===i.value?S("newList.value"):n&&null===n.value?S("oldList.value"):void(n&&i&&0==i.value.Count&&i.value.SetInitialOriginNames(n.value.originNames))}}!function(t){t[t.Bool=-1]="Bool",t[t.Int=0]="Int",t[t.Float=1]="Float",t[t.List=2]="List",t[t.String=3]="String",t[t.DivertTarget=4]="DivertTarget",t[t.VariablePointer=5]="VariablePointer"}(g||(g={}));class k{constructor(){this.obj=null,this.approximate=!1}get correctObj(){return this.approximate?null:this.obj}get container(){return this.obj instanceof L?this.obj:null}copy(){let t=new k;return t.obj=this.obj,t.approximate=this.approximate,t}}class L extends y{constructor(){super(...arguments),this.name=null,this._content=[],this.namedContent=new Map,this.visitsShouldBeCounted=!1,this.turnIndexShouldBeCounted=!1,this.countingAtStartOnly=!1,this._pathToFirstLeafContent=null}get hasValidName(){return null!=this.name&&this.name.length>0}get content(){return this._content}set content(t){this.AddContent(t)}get namedOnlyContent(){let t=new Map;for(let[e,n]of this.namedContent){let i=a(n,y);t.set(e,i)}for(let e of this.content){let n=o(e);null!=n&&n.hasValidName&&t.delete(n.name)}return 0==t.size&&(t=null),t}set namedOnlyContent(t){let e=this.namedOnlyContent;if(null!=e)for(let[t]of e)this.namedContent.delete(t);if(null!=t)for(let[,e]of t){let t=o(e);null!=t&&this.AddToNamedContentOnly(t)}}get countFlags(){let t=0;return this.visitsShouldBeCounted&&(t|=L.CountFlags.Visits),this.turnIndexShouldBeCounted&&(t|=L.CountFlags.Turns),this.countingAtStartOnly&&(t|=L.CountFlags.CountStartOnly),t==L.CountFlags.CountStartOnly&&(t=0),t}set countFlags(t){let e=t;(e&L.CountFlags.Visits)>0&&(this.visitsShouldBeCounted=!0),(e&L.CountFlags.Turns)>0&&(this.turnIndexShouldBeCounted=!0),(e&L.CountFlags.CountStartOnly)>0&&(this.countingAtStartOnly=!0)}get pathToFirstLeafContent(){return null==this._pathToFirstLeafContent&&(this._pathToFirstLeafContent=this.path.PathByAppendingPath(this.internalPathToFirstLeafContent)),this._pathToFirstLeafContent}get internalPathToFirstLeafContent(){let t=[],e=this;for(;e instanceof L;)e.content.length>0&&(t.push(new m.Component(0)),e=e.content[0]);return new m(t)}AddContent(t){if(t instanceof Array){let e=t;for(let t of e)this.AddContent(t)}else{let e=t;if(this._content.push(e),e.parent)throw new Error("content is already in "+e.parent);e.parent=this,this.TryAddNamedContent(e)}}TryAddNamedContent(t){let e=o(t);null!=e&&e.hasValidName&&this.AddToNamedContentOnly(e)}AddToNamedContentOnly(t){if(f.AssertType(t,y,"Can only add Runtime.Objects to a Runtime.Container"),a(t,y).parent=this,null===t.name)return S("namedContentObj.name");this.namedContent.set(t.name,t)}ContentAtPath(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-1;-1==n&&(n=t.length);let i=new k;i.approximate=!1;let r=this,a=this;for(let o=e;o=0&&t.index=0||r.set(t,e);if(r.size>0){i(),t.AppendLine("-- named: --");for(let[,i]of r){f.AssertType(i,L,"Can only print out named Containers"),i.BuildStringOfHierarchy(t,e,n),t.AppendLine()}}e--,i(),t.Append("]")}}!function(t){var e;(e=t.CountFlags||(t.CountFlags={}))[e.Start=0]="Start",e[e.Visits=1]="Visits",e[e.Turns=2]="Turns",e[e.CountStartOnly=4]="CountStartOnly"}(L||(L={}));class D extends y{get commandType(){return this._commandType}constructor(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:D.CommandType.NotSet;super(),this._commandType=t}Copy(){return new D(this.commandType)}static EvalStart(){return new D(D.CommandType.EvalStart)}static EvalOutput(){return new D(D.CommandType.EvalOutput)}static EvalEnd(){return new D(D.CommandType.EvalEnd)}static Duplicate(){return new D(D.CommandType.Duplicate)}static PopEvaluatedValue(){return new D(D.CommandType.PopEvaluatedValue)}static PopFunction(){return new D(D.CommandType.PopFunction)}static PopTunnel(){return new D(D.CommandType.PopTunnel)}static BeginString(){return new D(D.CommandType.BeginString)}static EndString(){return new D(D.CommandType.EndString)}static NoOp(){return new D(D.CommandType.NoOp)}static ChoiceCount(){return new D(D.CommandType.ChoiceCount)}static Turns(){return new D(D.CommandType.Turns)}static TurnsSince(){return new D(D.CommandType.TurnsSince)}static ReadCount(){return new D(D.CommandType.ReadCount)}static Random(){return new D(D.CommandType.Random)}static SeedRandom(){return new D(D.CommandType.SeedRandom)}static VisitIndex(){return new D(D.CommandType.VisitIndex)}static SequenceShuffleIndex(){return new D(D.CommandType.SequenceShuffleIndex)}static StartThread(){return new D(D.CommandType.StartThread)}static Done(){return new D(D.CommandType.Done)}static End(){return new D(D.CommandType.End)}static ListFromInt(){return new D(D.CommandType.ListFromInt)}static ListRange(){return new D(D.CommandType.ListRange)}static ListRandom(){return new D(D.CommandType.ListRandom)}static BeginTag(){return new D(D.CommandType.BeginTag)}static EndTag(){return new D(D.CommandType.EndTag)}toString(){return"ControlCommand "+this.commandType.toString()}}!function(t){var e;(e=t.CommandType||(t.CommandType={}))[e.NotSet=-1]="NotSet",e[e.EvalStart=0]="EvalStart",e[e.EvalOutput=1]="EvalOutput",e[e.EvalEnd=2]="EvalEnd",e[e.Duplicate=3]="Duplicate",e[e.PopEvaluatedValue=4]="PopEvaluatedValue",e[e.PopFunction=5]="PopFunction",e[e.PopTunnel=6]="PopTunnel",e[e.BeginString=7]="BeginString",e[e.EndString=8]="EndString",e[e.NoOp=9]="NoOp",e[e.ChoiceCount=10]="ChoiceCount",e[e.Turns=11]="Turns",e[e.TurnsSince=12]="TurnsSince",e[e.ReadCount=13]="ReadCount",e[e.Random=14]="Random",e[e.SeedRandom=15]="SeedRandom",e[e.VisitIndex=16]="VisitIndex",e[e.SequenceShuffleIndex=17]="SequenceShuffleIndex",e[e.StartThread=18]="StartThread",e[e.Done=19]="Done",e[e.End=20]="End",e[e.ListFromInt=21]="ListFromInt",e[e.ListRange=22]="ListRange",e[e.ListRandom=23]="ListRandom",e[e.BeginTag=24]="BeginTag",e[e.EndTag=25]="EndTag",e[e.TOTAL_VALUES=26]="TOTAL_VALUES"}(D||(D={}));class V extends d{constructor(){super(...arguments),this._prototypeRuntimeConstantExpression=null,this.outputWhenComplete=!1,this.GenerateRuntimeObject=()=>{const t=new L;return t.AddContent(D.EvalStart()),this.GenerateIntoContainer(t),this.outputWhenComplete&&t.AddContent(D.EvalOutput()),t.AddContent(D.EvalEnd()),t},this.GenerateConstantIntoContainer=t=>{null===this._prototypeRuntimeConstantExpression&&(this._prototypeRuntimeConstantExpression=new L,this.GenerateIntoContainer(this._prototypeRuntimeConstantExpression));for(const e of this._prototypeRuntimeConstantExpression.content){const n=e.Copy();n&&t.AddContent(n)}},this.toString=()=>"No string value in JavaScript."}get typeName(){return"Expression"}Equals(t){return!1}}class j extends y{toString(){return"Void"}}class B extends y{static CallWithName(t){return new B(t)}static CallExistsWithName(t){return this.GenerateNativeFunctionsIfNecessary(),this._nativeFunctions.get(t)}get name(){return null===this._name?S("NativeFunctionCall._name"):this._name}set name(t){this._name=t,this._isPrototype||(null===B._nativeFunctions?S("NativeFunctionCall._nativeFunctions"):this._prototype=B._nativeFunctions.get(this._name)||null)}get numberOfParameters(){return this._prototype?this._prototype.numberOfParameters:this._numberOfParameters}set numberOfParameters(t){this._numberOfParameters=t}Call(t){if(this._prototype)return this._prototype.Call(t);if(this.numberOfParameters!=t.length)throw new Error("Unexpected number of parameters");let e=!1;for(let n of t){if(n instanceof j)throw new _('Attempting to perform operation on a void value. Did you forget to "return" a value from a function you called here?');n instanceof R&&(e=!0)}if(2==t.length&&e)return this.CallBinaryListOperation(t);let n=this.CoerceValuesToSingleType(t),i=n[0].valueType;return i==g.Int||i==g.Float||i==g.String||i==g.DivertTarget||i==g.List?this.CallType(n):null}CallType(t){let e=a(t[0],A),n=e.valueType,i=e,r=t.length;if(2==r||1==r){if(null===this._operationFuncs)return S("NativeFunctionCall._operationFuncs");let s=this._operationFuncs.get(n);if(!s){const t=g[n];throw new _("Cannot perform operation "+this.name+" on "+t)}if(2==r){let e=a(t[1],A),n=s;if(null===i.value||null===e.value)return S("NativeFunctionCall.Call BinaryOp values");let r=n(i.value,e.value);return A.Create(r)}{let t=s;if(null===i.value)return S("NativeFunctionCall.Call UnaryOp value");let n=t(i.value);return this.name===B.Int?A.Create(n,g.Int):this.name===B.Float?A.Create(n,g.Float):A.Create(n,e.valueType)}}throw new Error("Unexpected number of parameters to NativeFunctionCall: "+t.length)}CallBinaryListOperation(t){if(("+"==this.name||"-"==this.name)&&t[0]instanceof R&&t[1]instanceof N)return this.CallListIncrementOperation(t);let e=a(t[0],A),n=a(t[1],A);if(!("&&"!=this.name&&"||"!=this.name||e.valueType==g.List&&n.valueType==g.List)){if(null===this._operationFuncs)return S("NativeFunctionCall._operationFuncs");let t=this._operationFuncs.get(g.Int);if(null===t)return S("NativeFunctionCall.CallBinaryListOperation op");let i=function(t){if("boolean"==typeof t)return t;throw new Error(`${t} is not a boolean`)}(t(e.isTruthy?1:0,n.isTruthy?1:0));return new P(i)}if(e.valueType==g.List&&n.valueType==g.List)return this.CallType([e,n]);throw new _("Can not call use "+this.name+" operation on "+g[e.valueType]+" and "+g[n.valueType])}CallListIncrementOperation(t){let e=a(t[0],R),n=a(t[1],N),i=new E;if(null===e.value)return S("NativeFunctionCall.CallListIncrementOperation listVal.value");for(let[t,r]of e.value){let s=w.fromSerializedKey(t);if(null===this._operationFuncs)return S("NativeFunctionCall._operationFuncs");let a=this._operationFuncs.get(g.Int);if(null===n.value)return S("NativeFunctionCall.CallListIncrementOperation intVal.value");let o=a(r,n.value),l=null;if(null===e.value.origins)return S("NativeFunctionCall.CallListIncrementOperation listVal.value.origins");for(let t of e.value.origins)if(t.name==s.originName){l=t;break}if(null!=l){let t=l.TryGetItemWithValue(o,w.Null);t.exists&&i.Add(t.result,o)}}return new R(i)}CoerceValuesToSingleType(t){let e=g.Int,n=null;for(let i of t){let t=a(i,A);t.valueType>e&&(e=t.valueType),t.valueType==g.List&&(n=s(t,R))}let i=[];if(g[e]==g[g.List])for(let e of t){let t=a(e,A);if(t.valueType==g.List)i.push(t);else{if(t.valueType!=g.Int){const e=g[t.valueType];throw new _("Cannot mix Lists and "+e+" values in this operation")}{let e=parseInt(t.valueObject);if(n=a(n,R),null===n.value)return S("NativeFunctionCall.CoerceValuesToSingleType specialCaseList.value");let r=n.value.originOfMaxItem;if(null===r)return S("NativeFunctionCall.CoerceValuesToSingleType list");let s=r.TryGetItemWithValue(e,w.Null);if(!s.exists)throw new _("Could not find List item with the value "+e+" in "+r.name);{let t=new R(s.result,e);i.push(t)}}}}else for(let n of t){let t=a(n,A).Cast(e);i.push(t)}return i}constructor(){if(super(),this._name=null,this._numberOfParameters=0,this._prototype=null,this._isPrototype=!1,this._operationFuncs=null,0===arguments.length)B.GenerateNativeFunctionsIfNecessary();else if(1===arguments.length){let t=arguments[0];B.GenerateNativeFunctionsIfNecessary(),this.name=t}else if(2===arguments.length){let t=arguments[0],e=arguments[1];this._isPrototype=!0,this.name=t,this.numberOfParameters=e}}static Identity(t){return t}static GenerateNativeFunctionsIfNecessary(){if(null==this._nativeFunctions){this._nativeFunctions=new Map,this.AddIntBinaryOp(this.Add,((t,e)=>t+e)),this.AddIntBinaryOp(this.Subtract,((t,e)=>t-e)),this.AddIntBinaryOp(this.Multiply,((t,e)=>t*e)),this.AddIntBinaryOp(this.Divide,((t,e)=>Math.floor(t/e))),this.AddIntBinaryOp(this.Mod,((t,e)=>t%e)),this.AddIntUnaryOp(this.Negate,(t=>-t)),this.AddIntBinaryOp(this.Equal,((t,e)=>t==e)),this.AddIntBinaryOp(this.Greater,((t,e)=>t>e)),this.AddIntBinaryOp(this.Less,((t,e)=>tt>=e)),this.AddIntBinaryOp(this.LessThanOrEquals,((t,e)=>t<=e)),this.AddIntBinaryOp(this.NotEquals,((t,e)=>t!=e)),this.AddIntUnaryOp(this.Not,(t=>0==t)),this.AddIntBinaryOp(this.And,((t,e)=>0!=t&&0!=e)),this.AddIntBinaryOp(this.Or,((t,e)=>0!=t||0!=e)),this.AddIntBinaryOp(this.Max,((t,e)=>Math.max(t,e))),this.AddIntBinaryOp(this.Min,((t,e)=>Math.min(t,e))),this.AddIntBinaryOp(this.Pow,((t,e)=>Math.pow(t,e))),this.AddIntUnaryOp(this.Floor,B.Identity),this.AddIntUnaryOp(this.Ceiling,B.Identity),this.AddIntUnaryOp(this.Int,B.Identity),this.AddIntUnaryOp(this.Float,(t=>t)),this.AddFloatBinaryOp(this.Add,((t,e)=>t+e)),this.AddFloatBinaryOp(this.Subtract,((t,e)=>t-e)),this.AddFloatBinaryOp(this.Multiply,((t,e)=>t*e)),this.AddFloatBinaryOp(this.Divide,((t,e)=>t/e)),this.AddFloatBinaryOp(this.Mod,((t,e)=>t%e)),this.AddFloatUnaryOp(this.Negate,(t=>-t)),this.AddFloatBinaryOp(this.Equal,((t,e)=>t==e)),this.AddFloatBinaryOp(this.Greater,((t,e)=>t>e)),this.AddFloatBinaryOp(this.Less,((t,e)=>tt>=e)),this.AddFloatBinaryOp(this.LessThanOrEquals,((t,e)=>t<=e)),this.AddFloatBinaryOp(this.NotEquals,((t,e)=>t!=e)),this.AddFloatUnaryOp(this.Not,(t=>0==t)),this.AddFloatBinaryOp(this.And,((t,e)=>0!=t&&0!=e)),this.AddFloatBinaryOp(this.Or,((t,e)=>0!=t||0!=e)),this.AddFloatBinaryOp(this.Max,((t,e)=>Math.max(t,e))),this.AddFloatBinaryOp(this.Min,((t,e)=>Math.min(t,e))),this.AddFloatBinaryOp(this.Pow,((t,e)=>Math.pow(t,e))),this.AddFloatUnaryOp(this.Floor,(t=>Math.floor(t))),this.AddFloatUnaryOp(this.Ceiling,(t=>Math.ceil(t))),this.AddFloatUnaryOp(this.Int,(t=>Math.floor(t))),this.AddFloatUnaryOp(this.Float,B.Identity),this.AddStringBinaryOp(this.Add,((t,e)=>t+e)),this.AddStringBinaryOp(this.Equal,((t,e)=>t===e)),this.AddStringBinaryOp(this.NotEquals,((t,e)=>!(t===e))),this.AddStringBinaryOp(this.Has,((t,e)=>t.includes(e))),this.AddStringBinaryOp(this.Hasnt,((t,e)=>!t.includes(e))),this.AddListBinaryOp(this.Add,((t,e)=>t.Union(e))),this.AddListBinaryOp(this.Subtract,((t,e)=>t.Without(e))),this.AddListBinaryOp(this.Has,((t,e)=>t.Contains(e))),this.AddListBinaryOp(this.Hasnt,((t,e)=>!t.Contains(e))),this.AddListBinaryOp(this.Intersect,((t,e)=>t.Intersect(e))),this.AddListBinaryOp(this.Equal,((t,e)=>t.Equals(e))),this.AddListBinaryOp(this.Greater,((t,e)=>t.GreaterThan(e))),this.AddListBinaryOp(this.Less,((t,e)=>t.LessThan(e))),this.AddListBinaryOp(this.GreaterThanOrEquals,((t,e)=>t.GreaterThanOrEquals(e))),this.AddListBinaryOp(this.LessThanOrEquals,((t,e)=>t.LessThanOrEquals(e))),this.AddListBinaryOp(this.NotEquals,((t,e)=>!t.Equals(e))),this.AddListBinaryOp(this.And,((t,e)=>t.Count>0&&e.Count>0)),this.AddListBinaryOp(this.Or,((t,e)=>t.Count>0||e.Count>0)),this.AddListUnaryOp(this.Not,(t=>0==t.Count?1:0)),this.AddListUnaryOp(this.Invert,(t=>t.inverse)),this.AddListUnaryOp(this.All,(t=>t.all)),this.AddListUnaryOp(this.ListMin,(t=>t.MinAsList())),this.AddListUnaryOp(this.ListMax,(t=>t.MaxAsList())),this.AddListUnaryOp(this.Count,(t=>t.Count)),this.AddListUnaryOp(this.ValueOfList,(t=>t.maxItem.Value));let t=(t,e)=>t.Equals(e),e=(t,e)=>!t.Equals(e);this.AddOpToNativeFunc(this.Equal,2,g.DivertTarget,t),this.AddOpToNativeFunc(this.NotEquals,2,g.DivertTarget,e)}}AddOpFuncForType(t,e){null==this._operationFuncs&&(this._operationFuncs=new Map),this._operationFuncs.set(t,e)}static AddOpToNativeFunc(t,e,n,i){if(null===this._nativeFunctions)return S("NativeFunctionCall._nativeFunctions");let r=this._nativeFunctions.get(t);r||(r=new B(t,e),this._nativeFunctions.set(t,r)),r.AddOpFuncForType(n,i)}static AddIntBinaryOp(t,e){this.AddOpToNativeFunc(t,2,g.Int,e)}static AddIntUnaryOp(t,e){this.AddOpToNativeFunc(t,1,g.Int,e)}static AddFloatBinaryOp(t,e){this.AddOpToNativeFunc(t,2,g.Float,e)}static AddFloatUnaryOp(t,e){this.AddOpToNativeFunc(t,1,g.Float,e)}static AddStringBinaryOp(t,e){this.AddOpToNativeFunc(t,2,g.String,e)}static AddListBinaryOp(t,e){this.AddOpToNativeFunc(t,2,g.List,e)}static AddListUnaryOp(t,e){this.AddOpToNativeFunc(t,1,g.List,e)}toString(){return'Native "'+this.name+'"'}}B.Add="+",B.Subtract="-",B.Divide="/",B.Multiply="*",B.Mod="%",B.Negate="_",B.Equal="==",B.Greater=">",B.Less="<",B.GreaterThanOrEquals=">=",B.LessThanOrEquals="<=",B.NotEquals="!=",B.Not="!",B.And="&&",B.Or="||",B.Min="MIN",B.Max="MAX",B.Pow="POW",B.Floor="FLOOR",B.Ceiling="CEILING",B.Int="INT",B.Float="FLOAT",B.Has="?",B.Hasnt="!?",B.Intersect="^",B.ListMin="LIST_MIN",B.ListMax="LIST_MAX",B.All="LIST_ALL",B.Count="LIST_COUNT",B.ValueOfList="LIST_VALUE",B.Invert="LIST_INVERT",B._nativeFunctions=null;class M extends V{constructor(t,e){if(super(),this.isInt=()=>"int"==this.subtype,this.isFloat=()=>"float"==this.subtype,this.isBool=()=>"bool"==this.subtype,this.GenerateIntoContainer=t=>{this.isInt()?t.AddContent(new N(this.value)):this.isFloat()?t.AddContent(new O(this.value)):this.isBool()&&t.AddContent(new P(this.value))},this.toString=()=>String(this.value),("number"!=typeof t||Number.isNaN(t))&&"boolean"!=typeof t)throw new Error("Unexpected object type in NumberExpression.");this.value=t,this.subtype=e}get typeName(){return"Number"}Equals(t){const e=s(t,M);return!!e&&(e.subtype==this.subtype&&e.value==this.value)}}class G extends V{get nativeNameForOp(){return"-"===this.op?"_":"not"===this.op?"!":this.op}constructor(t,e){super(),this.op=e,this.GenerateIntoContainer=t=>{this.innerExpression.GenerateIntoContainer(t),t.AddContent(B.CallWithName(this.nativeNameForOp))},this.toString=()=>this.nativeNameForOp+this.innerExpression,this.innerExpression=this.AddContent(t)}get typeName(){return"UnaryExpression"}}G.WithInner=(t,e)=>{const n=s(t,M);if(n){if("-"===e){if(n.isInt())return new M(-n.value,"int");if(n.isFloat())return new M(-n.value,"float")}else if("!"==e||"not"==e){if(n.isInt())return new M(0==n.value,"bool");if(n.isFloat())return new M(0==n.value,"bool");if(n.isBool())return new M(!n.value,"bool")}throw new Error("Unexpected operation or number type")}return new G(t,e)};class $ extends V{constructor(t,e,n){super(),this.opName=n,this.GenerateIntoContainer=t=>{this.leftExpression.GenerateIntoContainer(t),this.rightExpression.GenerateIntoContainer(t),this.opName=this.NativeNameForOp(this.opName),t.AddContent(B.CallWithName(this.opName))},this.NativeNameForOp=t=>"and"===t?"&&":"or"===t?"||":"mod"===t?"%":"has"===t?"?":"hasnt"===t?"!?":t,this.toString=()=>`(${this.leftExpression} ${this.opName} ${this.rightExpression})`,this.leftExpression=this.AddContent(t),this.rightExpression=this.AddContent(e),this.opName=n}get typeName(){return"BinaryExpression"}ResolveReferences(t){if(super.ResolveReferences(t),"?"===this.NativeNameForOp(this.opName)){const t=s(this.leftExpression,G);null===t||"not"!==t.op&&"!"!==t.op||this.Error(`Using 'not' or '!' here negates '${t.innerExpression}' rather than the result of the '?' or 'has' operator. You need to add parentheses around the (A ? B) expression.`)}}}class q{constructor(t){this.set=new Set,this.Add=t=>this.set.add(t),this.AddRange=(t,e)=>{for(let n=t.charCodeAt(0);n<=e.charCodeAt(0);++n)this.Add(String.fromCharCode(n));return this},this.AddCharacters=t=>{if("string"==typeof t||Array.isArray(t))for(const e of t)this.Add(e);else for(const e of t.set)this.Add(e);return this},t&&this.AddCharacters(t)}}q.FromRange=(t,e)=>(new q).AddRange(t,e);class U{constructor(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];if(this._start=t,this._end=e,this._correspondingCharSet=new q,this._excludes=new Set,this.ToCharacterSet=()=>{if(0===this._correspondingCharSet.set.size)for(let t,e=this.start.charCodeAt(0);e<=this.end.charCodeAt(0);e+=1)t=String.fromCharCode(e),this._excludes.has(t)||this._correspondingCharSet.AddCharacters(t);return this._correspondingCharSet},n instanceof q)this._excludes=n.set;else for(const t of n)this._excludes.add(t)}get start(){return this._start}get end(){return this._end}}U.Define=function(t,e){return new U(t,e,arguments.length>2&&void 0!==arguments[2]?arguments[2]:[])};class K extends y{constructor(){let t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];super(),this._pathOnChoice=null,this.hasCondition=!1,this.hasStartContent=!1,this.hasChoiceOnlyContent=!1,this.isInvisibleDefault=!1,this.onceOnly=!0,this.onceOnly=t}get pathOnChoice(){if(null!=this._pathOnChoice&&this._pathOnChoice.isRelative){let t=this.choiceTarget;t&&(this._pathOnChoice=t.path)}return this._pathOnChoice}set pathOnChoice(t){this._pathOnChoice=t}get choiceTarget(){return null===this._pathOnChoice?S("ChoicePoint._pathOnChoice"):this.ResolvePath(this._pathOnChoice).container}get pathStringOnChoice(){return null===this.pathOnChoice?S("ChoicePoint.pathOnChoice"):this.CompactPathString(this.pathOnChoice)}set pathStringOnChoice(t){this.pathOnChoice=new m(t)}get flags(){let t=0;return this.hasCondition&&(t|=1),this.hasStartContent&&(t|=2),this.hasChoiceOnlyContent&&(t|=4),this.isInvisibleDefault&&(t|=8),this.onceOnly&&(t|=16),t}set flags(t){this.hasCondition=(1&t)>0,this.hasStartContent=(2&t)>0,this.hasChoiceOnlyContent=(4&t)>0,this.isInvisibleDefault=(8&t)>0,this.onceOnly=(16&t)>0}toString(){if(null===this.pathOnChoice)return S("ChoicePoint.pathOnChoice");return"Choice: -> "+this.pathOnChoice.toString()}}!function(t){t[t.Tunnel=0]="Tunnel",t[t.Function=1]="Function",t[t.FunctionEvaluationFromGame=2]="FunctionEvaluationFromGame"}(v||(v={}));class H{constructor(){this.container=null,this.index=-1,2===arguments.length&&(this.container=arguments[0],this.index=arguments[1])}Resolve(){return this.index<0?this.container:null==this.container?null:0==this.container.content.length?this.container:this.index>=this.container.content.length?null:this.container.content[this.index]}get isNull(){return null==this.container}get path(){return this.isNull?null:this.index>=0?this.container.path.PathByAppendingComponent(new m.Component(this.index)):this.container.path}toString(){return this.container?"Ink Pointer -> "+this.container.path.toString()+" -- index "+this.index:"Ink Pointer (null)"}copy(){return new H(this.container,this.index)}static StartOf(t){return new H(t,0)}static get Null(){return new H(null,-1)}}let J=class t extends y{get targetPath(){if(null!=this._targetPath&&this._targetPath.isRelative){let t=this.targetPointer.Resolve();t&&(this._targetPath=t.path)}return this._targetPath}set targetPath(t){this._targetPath=t,this._targetPointer=H.Null}get targetPointer(){if(this._targetPointer.isNull){let t=this.ResolvePath(this._targetPath).obj;if(null===this._targetPath)return S("this._targetPath");if(null===this._targetPath.lastComponent)return S("this._targetPath.lastComponent");if(this._targetPath.lastComponent.isIndex){if(null===t)return S("targetObj");this._targetPointer.container=t.parent instanceof L?t.parent:null,this._targetPointer.index=this._targetPath.lastComponent.index}else this._targetPointer=H.StartOf(t instanceof L?t:null)}return this._targetPointer.copy()}get targetPathString(){return null==this.targetPath?null:this.CompactPathString(this.targetPath)}set targetPathString(t){this.targetPath=null==t?null:new m(t)}get hasVariableTarget(){return null!=this.variableDivertName}constructor(t){super(),this._targetPath=null,this._targetPointer=H.Null,this.variableDivertName=null,this.pushesToStack=!1,this.stackPushType=0,this.isExternal=!1,this.externalArgs=0,this.isConditional=!1,this.pushesToStack=!1,void 0!==t&&(this.pushesToStack=!0,this.stackPushType=t)}Equals(e){let n=e;return n instanceof t&&this.hasVariableTarget==n.hasVariableTarget&&(this.hasVariableTarget?this.variableDivertName==n.variableDivertName:null===this.targetPath?S("this.targetPath"):this.targetPath.Equals(n.targetPath))}toString(){if(this.hasVariableTarget)return"Divert(variable: "+this.variableDivertName+")";if(null==this.targetPath)return"Divert(null)";{let t=new b,e=this.targetPath.toString();return t.Append("Divert"),this.isConditional&&t.Append("?"),this.pushesToStack&&(this.stackPushType==v.Function?t.Append(" function"):t.Append(" tunnel")),t.Append(" -> "),t.Append(this.targetPathString),t.Append(" ("),t.Append(e),t.Append(")"),t.toString()}}};var z;!function(t){t[t.Knot=0]="Knot",t[t.List=1]="List",t[t.ListItem=2]="ListItem",t[t.Var=3]="Var",t[t.SubFlowAndWeave=4]="SubFlowAndWeave",t[t.Arg=5]="Arg",t[t.Temp=6]="Temp"}(z||(z={}));let X=class extends y{constructor(t,e){super(),this.variableName=t||null,this.isNewDeclaration=!!e,this.isGlobal=!1}toString(){return"VarAssign to "+this.variableName}},Y=class extends d{get runtimeChoice(){if(!this._runtimeChoice)throw new Error;return this._runtimeChoice}get name(){var t;return(null===(t=this.identifier)||void 0===t?void 0:t.name)||null}get condition(){return this._condition}set condition(t){this._condition=t,t&&this.AddContent(t)}get runtimeContainer(){return this._innerContentContainer}get innerContentContainer(){return this._innerContentContainer}get containerForCounting(){return this._innerContentContainer}get runtimePath(){if(!this.innerContentContainer||!this.innerContentContainer.path)throw new Error;return this.innerContentContainer.path}constructor(t,e,n){super(),this._condition=null,this._innerContentContainer=null,this._outerContainer=null,this._runtimeChoice=null,this._returnToR1=null,this._returnToR2=null,this._r1Label=null,this._r2Label=null,this._divertToStartContentOuter=null,this._divertToStartContentInner=null,this._startContentRuntimeContainer=null,this.isInvisibleDefault=!1,this.hasWeaveStyleInlineBrackets=!1,this.GenerateRuntimeObject=()=>{if(this._outerContainer=new L,this._runtimeChoice=new K(this.onceOnly),this._runtimeChoice.isInvisibleDefault=this.isInvisibleDefault,(this.startContent||this.choiceOnlyContent||this.condition)&&this._outerContainer.AddContent(D.EvalStart()),this.startContent){this._returnToR1=new F,this._outerContainer.AddContent(this._returnToR1);const t=new X("$r",!0);this._outerContainer.AddContent(t),this._outerContainer.AddContent(D.BeginString()),this._divertToStartContentOuter=new J,this._outerContainer.AddContent(this._divertToStartContentOuter),this._startContentRuntimeContainer=this.startContent.GenerateRuntimeObject(),this._startContentRuntimeContainer.name="s";const e=new J;e.variableDivertName="$r",this._startContentRuntimeContainer.AddContent(e),this._outerContainer.AddToNamedContentOnly(this._startContentRuntimeContainer),this._r1Label=new L,this._r1Label.name="$r1",this._outerContainer.AddContent(this._r1Label),this._outerContainer.AddContent(D.EndString()),this._runtimeChoice.hasStartContent=!0}if(this.choiceOnlyContent){this._outerContainer.AddContent(D.BeginString());const t=this.choiceOnlyContent.GenerateRuntimeObject();this._outerContainer.AddContentsOfContainer(t),this._outerContainer.AddContent(D.EndString()),this._runtimeChoice.hasChoiceOnlyContent=!0}if(this.condition&&(this.condition.GenerateIntoContainer(this._outerContainer),this._runtimeChoice.hasCondition=!0),(this.startContent||this.choiceOnlyContent||this.condition)&&this._outerContainer.AddContent(D.EvalEnd()),this._outerContainer.AddContent(this._runtimeChoice),this._innerContentContainer=new L,this.startContent){this._returnToR2=new F,this._innerContentContainer.AddContent(D.EvalStart()),this._innerContentContainer.AddContent(this._returnToR2),this._innerContentContainer.AddContent(D.EvalEnd());const t=new X("$r",!0);this._innerContentContainer.AddContent(t),this._divertToStartContentInner=new J,this._innerContentContainer.AddContent(this._divertToStartContentInner),this._r2Label=new L,this._r2Label.name="$r2",this._innerContentContainer.AddContent(this._r2Label)}if(this.innerContent){const t=this.innerContent.GenerateRuntimeObject();this._innerContentContainer.AddContentsOfContainer(t)}return this.story.countAllVisits&&(this._innerContentContainer.visitsShouldBeCounted=!0),this._innerContentContainer.countingAtStartOnly=!0,this._outerContainer},this.toString=()=>null!==this.choiceOnlyContent?`* ${this.startContent}[${this.choiceOnlyContent}]...`:`* ${this.startContent}...`,this.startContent=t,this.choiceOnlyContent=e,this.innerContent=n,this.indentationDepth=1,t&&this.AddContent(this.startContent),e&&this.AddContent(this.choiceOnlyContent),n&&this.AddContent(this.innerContent),this.onceOnly=!0}get typeName(){return"Choice"}ResolveReferences(t){var e;if(this._innerContentContainer&&(this.runtimeChoice.pathOnChoice=this._innerContentContainer.path,this.onceOnly&&(this._innerContentContainer.visitsShouldBeCounted=!0)),this._returnToR1){if(!this._r1Label)throw new Error;this._returnToR1.targetPath=this._r1Label.path}if(this._returnToR2){if(!this._r2Label)throw new Error;this._returnToR2.targetPath=this._r2Label.path}if(this._divertToStartContentOuter){if(!this._startContentRuntimeContainer)throw new Error;this._divertToStartContentOuter.targetPath=this._startContentRuntimeContainer.path}if(this._divertToStartContentInner){if(!this._startContentRuntimeContainer)throw new Error;this._divertToStartContentInner.targetPath=this._startContentRuntimeContainer.path}super.ResolveReferences(t),this.identifier&&((null===(e=this.identifier)||void 0===e?void 0:e.name)||"").length>0&&t.CheckForNamingCollisions(this,this.identifier,z.SubFlowAndWeave)}};class Z{constructor(){this.characterIndex=0,this.characterInLineIndex=0,this.lineIndex=0,this.reportedErrorInScope=!1,this.uniqueId=0,this.customFlags=0,this.CopyFrom=t=>{Z._uniqueIdCounter++,this.uniqueId=Z._uniqueIdCounter,this.characterIndex=t.characterIndex,this.characterInLineIndex=t.characterInLineIndex,this.lineIndex=t.lineIndex,this.customFlags=t.customFlags,this.reportedErrorInScope=!1},this.SquashFrom=t=>{this.characterIndex=t.characterIndex,this.characterInLineIndex=t.characterInLineIndex,this.lineIndex=t.lineIndex,this.reportedErrorInScope=t.reportedErrorInScope,this.customFlags=t.customFlags}}}Z._uniqueIdCounter=1e3;class Q{get currentElement(){return this._stack[this._numElements-1]}get lineIndex(){return this.currentElement.lineIndex}set lineIndex(t){this.currentElement.lineIndex=t}get characterIndex(){return this.currentElement.characterIndex}set characterIndex(t){this.currentElement.characterIndex=t}get characterInLineIndex(){return this.currentElement.characterInLineIndex}set characterInLineIndex(t){this.currentElement.characterInLineIndex=t}get customFlags(){return this.currentElement.customFlags}set customFlags(t){this.currentElement.customFlags=t}get errorReportedAlreadyInScope(){return this.currentElement.reportedErrorInScope}get stackHeight(){return this._numElements}constructor(){this._stack=[],this._numElements=0,this.StringParserState=()=>{this._stack=new Array(200);for(let t=0;t<200;++t)this._stack[t]=new Z;this._numElements=1},this.Push=()=>{if(this._numElements>=this._stack.length&&this._numElements>0)throw new Error("Stack overflow in parser state.");const t=this._stack[this._numElements-1],e=this._stack[this._numElements];return this._numElements++,e.CopyFrom(t),e.uniqueId},this.Pop=t=>{if(1==this._numElements)throw new Error("Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?");if(this.currentElement.uniqueId!=t)throw new Error("Mismatched rule IDs while Poping - do you have mismatched Begin/Succeed/Fail?");this._numElements-=1},this.Peek=t=>{if(this.currentElement.uniqueId!=t)throw new Error("Mismatched rule IDs while Peeking - do you have mismatched Begin/Succeed/Fail?");return this._stack[this._numElements-1]},this.PeekPenultimate=()=>this._numElements>=2?this._stack[this._numElements-2]:null,this.Squash=()=>{if(this._numElements<2)throw new Error("Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?");const t=this._stack[this._numElements-2],e=this._stack[this._numElements-1];t.SquashFrom(e),this._numElements-=1},this.NoteErrorReported=()=>{for(const t of this._stack)t.reportedErrorInScope=!0};for(let t=0;t<200;t++)this._stack[t]=new Z;this._numElements=1}}const tt=Symbol("ParseSuccessStruct");class et{constructor(t){var e=this;this.ParseRule=null,this.errorHandler=null,this.hadError=!1,this.BeginRule=()=>this.state.Push(),this.FailRule=t=>(this.state.Pop(t),null),this.CancelRule=t=>{this.state.Pop(t)},this.SucceedRule=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;const i=e.state.Peek(t),r=e.state.PeekPenultimate();e.RuleDidSucceed&&e.RuleDidSucceed(n,r,i),e.state.Squash();let s=n;return null===s&&(s=et.ParseSuccess),s},this.Expect=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=e.ParseObject(t);if(null===r){let s;null===n&&(n=t.name);const a=e.LineRemainder();s=null===a||0===a.length?"end of line":`'${a}'`,e.Error(`Expected ${n} but saw ${s}`),null!==i&&(r=i())}return r},this.Error=function(t){let n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];e.ErrorOnLine(t,e.lineIndex+1,n)},this.ErrorWithParsedObject=function(t,n){let i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];e.ErrorOnLine(t,n.debugMetadata?n.debugMetadata.startLineNumber:-1,i)},this.ErrorOnLine=(t,e,n)=>{if(!this.state.errorReportedAlreadyInScope){const i=n?"Warning":"Error";if(!this.errorHandler)throw new Error(`${i} on line ${e}: ${t}`);this.errorHandler(t,this.index,e-1,n),this.state.NoteErrorReported()}n||(this.hadError=!0)},this.Warning=t=>this.Error(t,!0),this.LineRemainder=()=>this.Peek((()=>this.ParseUntilCharactersFromString("\n\r"))),this.SetFlag=(t,e)=>{e?this.state.customFlags|=t:this.state.customFlags&=~t},this.GetFlag=t=>Boolean(this.state.customFlags&t),this.ParseObject=t=>{const e=this.BeginRule(),n=this.state.stackHeight,i=t();if(n!==this.state.stackHeight)throw new Error("Mismatched Begin/Fail/Succeed rules");return null===i?this.FailRule(e):(this.SucceedRule(e,i),i)},this.Parse=t=>{const e=this.BeginRule(),n=t();return null===n?(this.FailRule(e),null):(this.SucceedRule(e,n),n)},this.OneOf=t=>{for(const e of t){const t=this.ParseObject(e);if(null!==t)return t}return null},this.OneOrMore=t=>{const e=[];let n=null;do{n=this.ParseObject(t),null!==n&&e.push(n)}while(null!==n);return e.length>0?e:null},this.Optional=t=>()=>{const e=this.ParseObject(t);return null===e?et.ParseSuccess:e},this.Exclude=t=>()=>this.ParseObject(t)&&et.ParseSuccess,this.OptionalExclude=t=>()=>(this.ParseObject(t),et.ParseSuccess),this.String=t=>()=>this.ParseString(t),this.TryAddResultToList=function(t,e){let n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(t!==et.ParseSuccess){if(n&&Array.isArray(t)){const n=t;if(null!==n){for(const t of n)e.push(t);return}}e.push(t)}},this.Interleave=function(t,n){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];const s=e.BeginRule(),a=[],o=e.ParseObject(t);if(null===o)return e.FailRule(s);e.TryAddResultToList(o,a,r);let l=null,h=null;do{if(null!==i&&null!==e.Peek(i))break;if(l=e.ParseObject(n),null===l)break;if(e.TryAddResultToList(l,a,r),h=null,null!==l){if(h=e.ParseObject(t),null===h)break;e.TryAddResultToList(h,a,r)}}while((null!==l||null!==h)&&(l!==et.ParseSuccess||h!=et.ParseSuccess)&&e.remainingLength>0);return 0===a.length?e.FailRule(s):e.SucceedRule(s,a)},this.ParseString=t=>{if(t.length>this.remainingLength)return null;const e=this.BeginRule();let n=this.index,i=this.characterInLineIndex,r=this.lineIndex,s=!0;for(let e=0;e{if(this.remainingLength>0){const t=this._chars[this.index];return"\n"===t&&(this.lineIndex+=1,this.characterInLineIndex=-1),this.index+=1,this.characterInLineIndex+=1,t}return"0"},this.ParseUntilCharactersFromString=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;return e.ParseCharactersFromString(t,!1,n)},this.ParseUntilCharactersFromCharSet=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;return e.ParseCharactersFromCharSet(t,!1,n)},this.ParseCharactersFromString=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-1;const r=new q(t);return"number"==typeof n?e.ParseCharactersFromCharSet(r,!0,n):e.ParseCharactersFromCharSet(r,n,i)},this.ParseCharactersFromCharSet=function(t){let n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-1;-1===i&&(i=Number.MAX_SAFE_INTEGER);const r=e.index;let s=e.index,a=e.characterInLineIndex,o=e.lineIndex,l=0;for(;sr?e._chars.slice(r,e.index).join(""):null},this.Peek=t=>{const e=this.BeginRule(),n=t();return this.CancelRule(e),n},this.ParseInt=()=>{const t=this.index,e=this.characterInLineIndex,n=null!==this.ParseString("-");this.ParseCharactersFromString(" \t");const i=this.ParseCharactersFromCharSet(et.numbersCharacterSet);if(null===i)return this.index=t,this.characterInLineIndex=e,null;let r;return Number.isNaN(Number(i))?(this.Error("Failed to read integer value: "+i+". Perhaps it's out of the range of acceptable numbers ink supports? ("+Number.MIN_SAFE_INTEGER+" to "+Number.MAX_SAFE_INTEGER+")"),null):(r=Number(i),n?-r:r)},this.ParseFloat=()=>{const t=this.index,e=this.characterInLineIndex,n=this.ParseInt();if(null!==n&&null!==this.ParseString(".")){const t=this.ParseCharactersFromCharSet(et.numbersCharacterSet);return Number(`${n}.${t}`)}return this.index=t,this.characterInLineIndex=e,null},this.ParseNewline=()=>{const t=this.BeginRule();return this.ParseString("\r"),null===this.ParseString("\n")?this.FailRule(t):this.SucceedRule(t,"\n")};const n=this.PreProcessInputString(t);this.state=new Q,this._chars=t?n.split(""):[],this.inputString=n}get currentCharacter(){return this.index>=0&&this.remainingLength>0?this._chars[this.index]:"0"}PreProcessInputString(t){return t}get endOfInput(){return this.index>=this._chars.length}get remainingString(){return this._chars.slice(this.index,this.index+this.remainingLength).join("")}get remainingLength(){return this._chars.length-this.index}get lineIndex(){return this.state.lineIndex}set lineIndex(t){this.state.lineIndex=t}set characterInLineIndex(t){this.state.characterInLineIndex=t}get characterInLineIndex(){return this.state.characterInLineIndex}get index(){return this.state.characterIndex}set index(t){this.state.characterIndex=t}ParseUntil(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;const i=this.BeginRule(),r=new q;null!==e&&(r.set=new Set([...r.set.values(),...e.set.values()])),null!==n&&(r.set=new Set([...r.set.values(),...n.set.values()]));let s="",a=null;for(;;){const n=this.ParseUntilCharactersFromCharSet(r);if(n&&(s+=n),a=this.Peek(t),null!==a)break;{if(this.endOfInput)break;const t=this.currentCharacter;if(null!==e&&e.set.has(t)){s+=t,"\n"===t&&(this.lineIndex+=1,this.characterInLineIndex=-1),this.index+=1,this.characterInLineIndex+=1;continue}break}}return s.length>0?this.SucceedRule(i,String(s)):this.FailRule(i)}}et.ParseSuccess=tt,et.numbersCharacterSet=new q("0123456789");class nt extends et{constructor(){super(...arguments),this._commentOrNewlineStartCharacter=new q("/\r\n"),this._commentBlockEndCharacter=new q("*"),this._newlineCharacters=new q("\n\r"),this.Process=()=>{const t=this.Interleave(this.Optional(this.CommentsAndNewlines),this.Optional(this.MainInk));return null!==t?t.join(""):""},this.MainInk=()=>this.ParseUntil(this.CommentsAndNewlines,this._commentOrNewlineStartCharacter,null),this.CommentsAndNewlines=()=>{let t=this.Interleave(this.Optional(this.ParseNewline),this.Optional(this.ParseSingleComment));return null!==t?t.join(""):null},this.ParseSingleComment=()=>this.OneOf([this.EndOfLineComment,this.BlockComment]),this.EndOfLineComment=()=>null===this.ParseString("//")?null:(this.ParseUntilCharactersFromCharSet(this._newlineCharacters),""),this.BlockComment=()=>{if(null===this.ParseString("/*"))return null;const t=this.lineIndex,e=this.ParseUntil(this.String("*/"),this._commentBlockEndCharacter,null);return this.endOfInput||this.ParseString("*/"),null!=e?"\n".repeat(this.lineIndex-t):null}}PreProcessInputString(t){return t}}class it extends d{constructor(t,e){super(),this.initialCondition=t,this.branches=e,this._reJoinTarget=null,this.GenerateRuntimeObject=()=>{const t=new L;this.initialCondition&&t.AddContent(this.initialCondition.runtimeObject);for(const e of this.branches){const n=e.runtimeObject;t.AddContent(n)}return null===this.initialCondition||null===this.branches[0].ownExpression||this.branches[this.branches.length-1].isElse||t.AddContent(D.PopEvaluatedValue()),this._reJoinTarget=D.NoOp(),t.AddContent(this._reJoinTarget),t},this.initialCondition&&this.AddContent(this.initialCondition),null!==this.branches&&this.AddContent(this.branches)}get typeName(){return"Conditional"}ResolveReferences(t){const e=this._reJoinTarget.path;for(const t of this.branches){if(!t.returnDivert)throw new Error;t.returnDivert.targetPath=e}super.ResolveReferences(t)}}class rt extends d{constructor(t){super(),this.text=t,this.GenerateRuntimeObject=()=>new I(this.text),this.toString=()=>this.text}get typeName(){return"Text"}}class st extends d{get constantName(){var t;return null===(t=this.constantIdentifier)||void 0===t?void 0:t.name}get expression(){if(!this._expression)throw new Error;return this._expression}constructor(t,e){super(),this._expression=null,this.GenerateRuntimeObject=()=>null,this.constantIdentifier=t,e&&(this._expression=this.AddContent(e))}get typeName(){return"CONST"}ResolveReferences(t){super.ResolveReferences(t),t.CheckForNamingCollisions(this,this.constantIdentifier,z.Var)}}var at;!function(t){t[t.Story=0]="Story",t[t.Knot=1]="Knot",t[t.Stitch=2]="Stitch",t[t.WeavePoint=3]="WeavePoint"}(at||(at={}));class ot extends d{get name(){var t;return(null===(t=this.identifier)||void 0===t?void 0:t.name)||null}get runtimeContainer(){return this.runtimeObject}constructor(t,e){super(),this.indentationDepth=e,this.GenerateRuntimeObject=()=>{const t=new L;if(t.name=this.name,this.story.countAllVisits&&(t.visitsShouldBeCounted=!0),t.countingAtStartOnly=!0,this.content)for(const e of this.content)t.AddContent(e.runtimeObject);return t},this.toString=()=>{var t,e;return"- "+((null===(t=this.identifier)||void 0===t?void 0:t.name)?"("+(null===(e=this.identifier)||void 0===e?void 0:e.name)+")":"gather")},t&&(this.identifier=t)}get typeName(){return"Gather"}ResolveReferences(t){super.ResolveReferences(t),this.identifier&&(this.identifier.name||"").length>0&&t.CheckForNamingCollisions(this,this.identifier,z.SubFlowAndWeave)}}class lt{get baseTargetLevel(){return this.baseLevelIsAmbiguous?at.Story:this._baseTargetLevel}get baseLevelIsAmbiguous(){return!this._baseTargetLevel}get firstComponent(){return null!=this.components&&this.components.length?this.components[0].name:null}get numberOfComponents(){return this.components?this.components.length:0}get dotSeparatedComponents(){return null==this._dotSeparatedComponents&&(this._dotSeparatedComponents=(this.components?this.components:[]).map((t=>t.name)).filter(c).join(".")),this._dotSeparatedComponents}constructor(t,e){this._dotSeparatedComponents=null,this.toString=()=>null===this.components||0===this.components.length?this.baseTargetLevel===at.WeavePoint?"-> ":"":`-> ${this.dotSeparatedComponents}`,this.ResolveFromContext=t=>{if(null==this.components||0==this.components.length)return null;let e=this.ResolveBaseTarget(t);return null===e?null:this.components.length>1?this.ResolveTailComponents(e):e},this.ResolveBaseTarget=t=>{const e=this.firstComponent;let n=t;for(;n;){const i=n===t,r=this.GetChildFromContext(n,e,null,i);if(r)return r;n=n.parent}return null},this.ResolveTailComponents=t=>{let e=t;if(!this.components)return null;for(let t=1;t3&&void 0!==arguments[3]&&arguments[3];const r=null===n,a=s(t,Pt);if(e&&null!==a&&(r||n===at.WeavePoint))return a.WeavePointNamed(e);let o=s(t,dt);if(e&&null!==o){const t=i||o.flowLevel===at.Knot;return o.ContentWithNameAtLevel(e,n,t)}return null},Object.values(at).includes(t)?(this._baseTargetLevel=t,this.components=e||[]):Array.isArray(t)?(this._baseTargetLevel=null,this.components=t||[]):(this._baseTargetLevel=null,this.components=[t])}get typeName(){return"Path"}}class ht extends d{constructor(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;super(),this.returnedExpression=null,this.GenerateRuntimeObject=()=>{const t=new L;return this.returnedExpression?t.AddContent(this.returnedExpression.runtimeObject):(t.AddContent(D.EvalStart()),t.AddContent(new j),t.AddContent(D.EvalEnd())),t.AddContent(D.PopFunction()),t},t&&(this.returnedExpression=this.AddContent(t))}get typeName(){return"ReturnType"}}function ut(t){let e=t.parent;for(;e;){if(e.hasOwnProperty("iamFlowbase")&&e.iamFlowbase())return e;e=e.parent}return null}class ct{constructor(t){this.debugMetadata=null,this.toString=()=>this.name||"undefined identifer",this.name=t}get typeName(){return"Identifier"}static Done(){return new ct("DONE")}}class dt extends d{get hasParameters(){return null!==this.args&&this.args.length>0}get subFlowsByName(){return this._subFlowsByName}get typeName(){return this.isFunction?"Function":String(this.flowLevel)}get name(){var t;return(null===(t=this.identifier)||void 0===t?void 0:t.name)||null}constructor(t){var e;let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],a=arguments.length>4&&void 0!==arguments[4]&&arguments[4];super(),e=this,this.isFunction=r,this._rootWeave=null,this._subFlowsByName=new Map,this._startingSubFlowDivert=null,this._startingSubFlowRuntime=null,this._firstChildFlow=null,this.variableDeclarations=new Map,this.identifier=null,this.args=null,this.iamFlowbase=()=>!0,this.SplitWeaveAndSubFlowContent=(t,e)=>{var n,i;const r=[],a=[];this._subFlowsByName=new Map;for(const e of t){const t=s(e,dt);t?(null===this._firstChildFlow&&(this._firstChildFlow=t),a.push(e),(null===(n=t.identifier)||void 0===n?void 0:n.name)&&this._subFlowsByName.set(null===(i=t.identifier)||void 0===i?void 0:i.name,t)):r.push(e)}e&&r.push(new ot(null,1),new St(new lt(ct.Done())));const o=[];return r.length>0&&(this._rootWeave=new Pt(r,0),o.push(this._rootWeave)),a.length>0&&o.push(...a),o},this.ResolveVariableWithName=(t,e)=>{var n;const i={},r=null===e?this:ut(e);if(r){if(null!==r.args)for(const e of r.args)if((null===(n=e.identifier)||void 0===n?void 0:n.name)===t)return i.found=!0,i.isArgument=!0,i.ownerFlow=r,i;if(r!==this.story&&r.variableDeclarations.has(t))return i.found=!0,i.ownerFlow=r,i.isTemporary=!0,i}return this.story.variableDeclarations.has(t)?(i.found=!0,i.ownerFlow=this.story,i.isGlobal=!0,i):(i.found=!1,i)},this.AddNewVariableDeclaration=t=>{const e=t.variableName;if(this.variableDeclarations.has(e)){const n=this.variableDeclarations.get(e);let i="";return n.debugMetadata&&(i=` (${n.debugMetadata})`),void this.Error(`found declaration variable '${e}' that was already declared${i}`,t,!1)}this.variableDeclarations.set(t.variableName,t)},this.ResolveWeavePointNaming=()=>{this._rootWeave&&this._rootWeave.ResolveWeavePointNaming();for(const[,t]of this._subFlowsByName)t.hasOwnProperty("ResolveWeavePointNaming")&&t.ResolveWeavePointNaming()},this.GenerateRuntimeObject=()=>{var t;let e=null;this.isFunction?this.CheckForDisallowedFunctionFlowControl():this.flowLevel!==at.Knot&&this.flowLevel!==at.Stitch||(e=this.Find(ht)(),null!==e&&this.Error(`Return statements can only be used in knots that are declared as functions: == function ${this.identifier} ==`,e));const n=new L;n.name=null===(t=this.identifier)||void 0===t?void 0:t.name,this.story.countAllVisits&&(n.visitsShouldBeCounted=!0),this.GenerateArgumentVariableAssignments(n);let i=0;for(;null!==this.content&&i{var e;if(null!==this.args&&0!==this.args.length)for(let n=this.args.length-1;n>=0;--n){const i=(null===(e=this.args[n].identifier)||void 0===e?void 0:e.name)||null,r=new X(i,!0);t.AddContent(r)}},this.ContentWithNameAtLevel=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];var r;if((n===e.flowLevel||null===n)&&t===(null===(r=e.identifier)||void 0===r?void 0:r.name))return e;if(n===at.WeavePoint||null===n){let r=null;if(e._rootWeave&&(r=e._rootWeave.WeavePointNamed(t),r))return r;if(n===at.WeavePoint)return i?e.DeepSearchForAnyLevelContent(t):null}if(null!==n&&n{const e=this.ContentWithNameAtLevel(t,at.WeavePoint,!1);if(e)return e;for(const[,e]of this._subFlowsByName){const n=e.ContentWithNameAtLevel(t,null,!0);if(n)return n}return null},this.CheckForDisallowedFunctionFlowControl=()=>{this.flowLevel!==at.Knot&&this.Error("Functions cannot be stitches - i.e. they should be defined as '== function myFunc ==' rather than internal to another knot.");for(const[t,e]of this._subFlowsByName)this.Error(`Functions may not contain stitches, but saw '${t}' within the function '${this.identifier}'`,e);if(!this._rootWeave)throw new Error;const t=this._rootWeave.FindAll(St)();for(const e of t)e.isFunctionCall||e.parent instanceof Ct||this.Error(`Functions may not contain diverts, but saw '${e}'`,e);const e=this._rootWeave.FindAll(Y)();for(const t of e)this.Error(`Functions may not contain choices, but saw '${t}'`,t)},this.WarningInTermination=t=>{let e="Apparent loose end exists where the flow runs out. Do you need a '-> DONE' statement, choice or divert?";t.parent===this._rootWeave&&this._firstChildFlow&&(e=`${e} Note that if you intend to enter '${this._firstChildFlow.identifier}' next, you need to divert to it explicitly.`);const n=s(t,St);n&&n.isTunnel&&(e+=` When final tunnel to '${n.target} ->' returns it won't have anywhere to go.`),this.Warning(e,t)},this.toString=()=>`${this.typeName} '${this.identifier}'`,this.identifier=t,this.args=i,null===n&&(n=[]),this.PreProcessTopLevelObjects(n),n=this.SplitWeaveAndSubFlowContent(n,"Story"==this.GetType()&&!a),this.AddContent(n)}PreProcessTopLevelObjects(t){}ResolveReferences(t){var e,n;if(this._startingSubFlowDivert){if(!this._startingSubFlowRuntime)throw new Error;this._startingSubFlowDivert.targetPath=this._startingSubFlowRuntime.path}if(super.ResolveReferences(t),null!==this.args){for(const e of this.args)t.CheckForNamingCollisions(this,e.identifier,z.Arg,"argument");for(let t=0;t{for(let t=this.content.length-1;t>=0;--t){const e=s(this.content[t],rt);if(null===e)break;if(e.text=e.text.replace(new RegExp(/[ \t]/g),""),0!==e.text.length)break;this.content.splice(t,1)}},this.GenerateRuntimeObject=()=>{const t=new L;if(null!==this.content)for(const e of this.content){const n=e.runtimeObject;n&&t.AddContent(n)}return this.dontFlatten&&this.story.DontFlattenContainer(t),t},this.toString=()=>`ContentList(${this.content.join(", ")})`,t&&this.AddContent(t);for(var e=arguments.length,n=new Array(e>1?e-1:0),i=1;i0&&void 0!==arguments[0]?arguments[0]:null;super(),this.pathForCount=null,this.name=t}toString(){if(null!=this.name)return"var("+this.name+")";return"read_count("+this.pathStringForCount+")"}};class ft extends V{get name(){return this.path.join(".")}get path(){return this.pathIdentifiers.map((t=>t.name)).filter(c)}get identifier(){if(!this.pathIdentifiers||0==this.pathIdentifiers.length)return null;const t=this.path.join(".");return new ct(t)}get runtimeVarRef(){return this._runtimeVarRef}constructor(t){super(),this.pathIdentifiers=t,this._runtimeVarRef=null,this.isConstantReference=!1,this.isListItemReference=!1,this.GenerateIntoContainer=t=>{let e=this.story.constants.get(this.name);if(e)return e.GenerateConstantIntoContainer(t),void(this.isConstantReference=!0);if(this._runtimeVarRef=new mt(this.name),1===this.path.length||2===this.path.length){let t="",e="";1===this.path.length?t=this.path[0]:(e=this.path[0],t=this.path[1]);this.story.ResolveListItem(e,t,this)&&(this.isListItemReference=!0)}t.AddContent(this._runtimeVarRef)},this.toString=()=>`{${this.path.join(".")}}`}get typeName(){return"ref"}ResolveReferences(t){if(super.ResolveReferences(t),this.isConstantReference||this.isListItemReference)return;const e=new lt(this.pathIdentifiers),n=e.ResolveFromContext(this);if(n){if(!n.containerForCounting)throw new Error;if(n.containerForCounting.visitsShouldBeCounted=!0,null===this._runtimeVarRef)return;this._runtimeVarRef.pathForCount=n.runtimePath,this._runtimeVarRef.name=null;let t=s(n,dt);t&&t.isFunction&&(this.parent instanceof Pt||this.parent instanceof pt||this.parent instanceof dt)&&this.Warning(`'${t.identifier}' being used as read count rather than being called as function. Perhaps you intended to write ${t.identifier}()`)}else{if(this.path.length>1){let t=`Could not find target for read count: ${e}`;return this.path.length<=2&&(t+=`, or couldn't find list item with the name ${this.path.join(",")}`),void this.Error(t)}t.ResolveVariableWithName(this.name,this).found||this.Error(`Unresolved variable: ${this.name}`,this)}}}class gt extends V{get proxyDivert(){return this._proxyDivert}get name(){return this._proxyDivert.target.firstComponent||""}get args(){return this._proxyDivert.args}get runtimeDivert(){return this._proxyDivert.runtimeDivert}get isChoiceCount(){return"CHOICE_COUNT"===this.name}get isTurns(){return"TURNS"===this.name}get isTurnsSince(){return"TURNS_SINCE"===this.name}get isRandom(){return"RANDOM"===this.name}get isSeedRandom(){return"SEED_RANDOM"===this.name}get isListRange(){return"LIST_RANGE"===this.name}get isListRandom(){return"LIST_RANDOM"===this.name}get isReadCount(){return"READ_COUNT"===this.name}constructor(t,e){super(),this._divertTargetToCount=null,this._variableReferenceToCount=null,this.shouldPopReturnedValue=!1,this.GenerateIntoContainer=t=>{const e=this.story.ResolveList(this.name);let n=!1;if(this.isChoiceCount)this.args.length>0&&this.Error("The CHOICE_COUNT() function shouldn't take any arguments"),t.AddContent(D.ChoiceCount());else if(this.isTurns)this.args.length>0&&this.Error("The TURNS() function shouldn't take any arguments"),t.AddContent(D.Turns());else if(this.isTurnsSince||this.isReadCount){const e=s(this.args[0],Ct),n=s(this.args[0],ft);if(1!==this.args.length||null===e&&null===n)return void this.Error(`The ${this.name}() function should take one argument: a divert target to the target knot, stitch, gather or choice you want to check. e.g. TURNS_SINCE(-> myKnot)`);e?(this._divertTargetToCount=e,this.AddContent(this._divertTargetToCount),this._divertTargetToCount.GenerateIntoContainer(t)):n&&(this._variableReferenceToCount=n,this.AddContent(this._variableReferenceToCount),this._variableReferenceToCount.GenerateIntoContainer(t)),this.isTurnsSince?t.AddContent(D.TurnsSince()):t.AddContent(D.ReadCount())}else if(this.isRandom){2!==this.args.length&&this.Error("RANDOM should take 2 parameters: a minimum and a maximum integer");for(let e=0;e1&&(t+="s"),this.Error(t)}for(let e=0;e1&&this.Error("Can currently only construct a list from one integer (or an empty list from a given list definition)"),1===this.args.length)t.AddContent(new I(this.name)),this.args[0].GenerateIntoContainer(t),t.AddContent(D.ListFromInt());else{const e=new E;e.SetInitialOriginName(this.name),t.AddContent(new R(e))}else t.AddContent(this._proxyDivert.runtimeObject),n=!0;n||this.content.splice(this.content.indexOf(this._proxyDivert),1),this.shouldPopReturnedValue&&t.AddContent(D.PopEvaluatedValue())},this.toString=()=>{const t=this.args.join(", ");return`${this.name}(${t})`},this._proxyDivert=new St(new lt(t),e),this._proxyDivert.isFunctionCall=!0,this.AddContent(this._proxyDivert)}get typeName(){return"FunctionCall"}ResolveReferences(t){if(super.ResolveReferences(t),!this.content.includes(this._proxyDivert)&&null!==this.args)for(const e of this.args)e.ResolveReferences(t);if(this._divertTargetToCount){const t=this._divertTargetToCount.divert,e=null!=t.runtimeDivert.variableDivertName;if(e)return void this.Error(`When getting the TURNS_SINCE() of a variable target, remove the '->' - i.e. it should just be TURNS_SINCE(${t.runtimeDivert.variableDivertName})`);const n=t.targetContent;if(null===n)e||this.Error(`Failed to find target for TURNS_SINCE: '${t.target}'`);else{if(!n.containerForCounting)throw new Error;n.containerForCounting.turnIndexShouldBeCounted=!0}}else if(this._variableReferenceToCount){const t=this._variableReferenceToCount.runtimeVarRef;if(!t)throw new Error;null!==t.pathForCount&&this.Error(`Should be '${gt.name}'(-> '${this._variableReferenceToCount.name}). Usage without the '->' only makes sense for variable targets.`)}}}gt.IsBuiltIn=t=>!!B.CallExistsWithName(t)||("CHOICE_COUNT"===t||"TURNS_SINCE"===t||"TURNS"===t||"RANDOM"===t||"SEED_RANDOM"===t||"LIST_VALUE"===t||"LIST_RANDOM"===t||"READ_COUNT"===t);class vt extends V{get subExpressions(){return this.content}constructor(t){super(),this.GenerateIntoContainer=t=>{let e=!0;for(const n of this.subExpressions)n.GenerateIntoContainer(t),e||t.AddContent(B.CallWithName("&&")),e=!1},this.AddContent(t)}get typeName(){return"MultipleConditionExpression"}}class Ct extends V{get runtimeDivert(){if(!this._runtimeDivert)throw new Error;return this._runtimeDivert}get runtimeDivertTargetValue(){if(!this._runtimeDivertTargetValue)throw new Error;return this._runtimeDivertTargetValue}constructor(t){super(),this._runtimeDivert=null,this._runtimeDivertTargetValue=null,this.GenerateIntoContainer=t=>{this.divert.GenerateRuntimeObject(),this._runtimeDivert=this.divert.runtimeDivert,this._runtimeDivertTargetValue=new F,t.AddContent(this.runtimeDivertTargetValue)},this.Equals=t=>{const e=s(t,Ct);if(!e||!this.divert.target||!e.divert.target)return!1;return this.divert.target.dotSeparatedComponents===e.divert.target.dotSeparatedComponents},this.divert=this.AddContent(t)}get typeName(){return"DivertTarget"}ResolveReferences(t){if(super.ResolveReferences(t),this.divert.isDone||this.divert.isEnd)return void this.Error("Can't use -> DONE or -> END as variable divert targets",this);let e=this;for(;e&&e instanceof V;){let t=!1,n=!1;const i=e.parent;if(i instanceof $){const e=i;"=="!==e.opName&&"!="!==e.opName?t=!0:(e.leftExpression instanceof Ct||e.leftExpression instanceof ft)&&(e.rightExpression instanceof Ct||e.rightExpression instanceof ft)||(t=!0),n=!0}else if(i instanceof gt){const e=i;e.isTurnsSince||e.isReadCount||(t=!0),n=!0}else(i instanceof V||i instanceof vt||i instanceof Y&&i.condition===e||i instanceof it||i instanceof Nt)&&(t=!0,n=!0);if(t&&this.Error(`Can't use a divert target like that. Did you intend to call '${this.divert.target}' as a function: likeThis(), or check the read count: likeThis, with no arrows?`,this),n)break;e=i}if(this.runtimeDivert.hasVariableTarget){if(!this.divert.target)throw new Error;this.Error(`Since '${this.divert.target.dotSeparatedComponents}' is a variable, it shouldn't be preceded by '->' here.`)}this.runtimeDivert.targetPath&&(this.runtimeDivertTargetValue.targetPath=this.runtimeDivert.targetPath);let n=this.divert.targetContent;if(null!==n){let t=n.containerForCounting;if(null!==t){const e=s(this.parent,gt);e&&e.isTurnsSince||(t.visitsShouldBeCounted=!0),t.turnIndexShouldBeCounted=!0}let e=s(n,dt);if(null!=e&&null!==e.args)for(const t of e.args)t.isByReference&&this.Error(`Can't store a divert target to a knot or function that has by-reference arguments ('${e.identifier}' has 'ref ${t.identifier}').`)}}}class St extends d{get runtimeDivert(){if(!this._runtimeDivert)throw new Error;return this._runtimeDivert}set runtimeDivert(t){this._runtimeDivert=t}get isEnd(){return Boolean(this.target&&"END"===this.target.dotSeparatedComponents)}get isDone(){return Boolean(this.target&&"DONE"===this.target.dotSeparatedComponents)}constructor(t,e){super(),this.args=[],this.target=null,this.targetContent=null,this._runtimeDivert=null,this.isFunctionCall=!1,this.isEmpty=!1,this.isTunnel=!1,this.isThread=!1,this.GenerateRuntimeObject=()=>{if(this.isEnd)return D.End();if(this.isDone)return D.Done();this.runtimeDivert=new J,this.ResolveTargetContent(),this.CheckArgumentValidity();const t=null!==this.args&&this.args.length>0;if(t||this.isFunctionCall||this.isTunnel||this.isThread){const e=new L;if(t){this.isFunctionCall||e.AddContent(D.EvalStart());let t=null;this.targetContent&&(t=this.targetContent.args);for(let n=0;nthis.target?this.target.firstComponent:null,this.ResolveTargetContent=()=>{if(!this.isEmpty&&!this.isEnd&&null===this.targetContent){let t=this.PathAsVariableName();if(null!==t){const e=s(ut(this),dt);if(e){const n=e.ResolveVariableWithName(t,this);if(n.found){if(n.isArgument&&n.ownerFlow&&n.ownerFlow.args){let e=n.ownerFlow.args.find((e=>{var n;return(null===(n=e.identifier)||void 0===n?void 0:n.name)==t}));e&&!e.isDivertTarget&&this.Error(`Since '${e.identifier}' is used as a variable divert target (on ${this.debugMetadata}), it should be marked as: -> ${e.identifier}`,n.ownerFlow)}return void(this.runtimeDivert.variableDivertName=t)}}}if(!this.target)throw new Error;this.targetContent=this.target.ResolveFromContext(this)}},this.CheckArgumentValidity=()=>{if(this.isEmpty)return;let t=0;if(null!==this.args&&this.args.length>0&&(t=this.args.length),null===this.targetContent)return;const e=s(this.targetContent,dt);if(!(0!==t||null!==e&&e.hasParameters))return;if(null===e&&t>0)return void this.Error("target needs to be a knot or stitch in order to pass arguments");if(null!==e&&(null===e.args||!e.args&&t>0))return void this.Error(`target (${e.name}) doesn't take parameters`);if(this.parent instanceof Ct)return void(t>0&&this.Error("can't store arguments in a divert target variable"));const n=e.args.length;if(n!==t){let i;return i=0===t?"but there weren't any passed to it":t ${n.identifier} but saw ${i}`,i)}}null!==e||this.Error("Can't call as a function or with arguments unless it's a knot or stitch")},this.CheckExternalArgumentValidity=t=>{const e=this.target?this.target.firstComponent:null,n=t.externals.get(e);if(!n)throw new Error("external not found");const i=n.argumentNames.length;let r=0;this.args&&(r=this.args.length),r!==i&&this.Error(`incorrect number of arguments sent to external function '${e}'. Expected ${i} but got ${r}`)},this.toString=()=>{let t="";return null===this.target?"-> ":(t+=this.target.toString(),this.isTunnel&&(t+=" ->"),this.isFunctionCall&&(t+=" ()"),t)},t&&(this.target=t),e&&(this.args=e,this.AddContent(e))}get typeName(){return"Divert"}ResolveReferences(t){if(this.isEmpty||this.isEnd||this.isDone)return;if(!this.runtimeDivert)throw new Error;this.targetContent&&(this.runtimeDivert.targetPath=this.targetContent.runtimePath),super.ResolveReferences(t);let e=s(this.targetContent,dt);e&&(!e.isFunction&&this.isFunctionCall?super.Error(`${e.identifier} hasn't been marked as a function, but it's being called as one. Do you need to declare the knot as '== function ${e.identifier} =='?`):!e.isFunction||this.isFunctionCall||this.parent instanceof Ct||super.Error(e.identifier+" can't be diverted to. It can only be called as a function since it's been marked as such: '"+e.identifier+"(...)'"));const n=null!==this.targetContent;let i=!1,r=!1;if(!this.target)throw new Error;if(1===this.target.numberOfComponents){if(!this.target.firstComponent)throw new Error;if(i=gt.IsBuiltIn(this.target.firstComponent),r=t.IsExternal(this.target.firstComponent),i||r)return this.isFunctionCall||super.Error(`${this.target.firstComponent} must be called as a function: ~ ${this.target.firstComponent}()`),void(r&&(this.runtimeDivert.isExternal=!0,null!==this.args&&(this.runtimeDivert.externalArgs=this.args.length),this.runtimeDivert.pushesToStack=!1,this.runtimeDivert.targetPath=new m(this.target.firstComponent),this.CheckExternalArgumentValidity(t)))}null==this.runtimeDivert.variableDivertName&&(n||i||r||this.Error(`target not found: '${this.target}'`))}Error(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];e!==this&&e?super.Error(t,e):this.isFunctionCall?super.Error(`Function call ${t}`,e,n):super.Error(`Divert ${t}`,e,n)}}class yt{constructor(t,e){this.divert=t,this.targetRuntimeObj=e}}class bt{constructor(t,e){this.divert=t,this.targetContent=e}}var wt;!function(t){t[t.Stopping=1]="Stopping",t[t.Cycle=2]="Cycle",t[t.Shuffle=4]="Shuffle",t[t.Once=8]="Once"}(wt||(wt={}));class Et extends d{constructor(t,e){super(),this.sequenceType=e,this._sequenceDivertsToResolve=[],this.GenerateRuntimeObject=()=>{const t=new L;t.visitsShouldBeCounted=!0,t.countingAtStartOnly=!0,this._sequenceDivertsToResolve=[],t.AddContent(D.EvalStart()),t.AddContent(D.VisitIndex());const e=(this.sequenceType&wt.Once)>0,n=(this.sequenceType&wt.Cycle)>0,i=(this.sequenceType&wt.Stopping)>0,r=(this.sequenceType&wt.Shuffle)>0;let s=this.sequenceElements.length;if(e&&(s+=1),i||e?(t.AddContent(new N(s-1)),t.AddContent(B.CallWithName("MIN"))):n&&(t.AddContent(new N(this.sequenceElements.length)),t.AddContent(B.CallWithName("%"))),r){const n=D.NoOp();if(e||i){const e=i?this.sequenceElements.length-1:this.sequenceElements.length;t.AddContent(D.Duplicate()),t.AddContent(new N(e)),t.AddContent(B.CallWithName("=="));const r=new J;r.isConditional=!0,t.AddContent(r),this.AddDivertToResolve(r,n)}let r=this.sequenceElements.length;i&&(r-=1),t.AddContent(new N(r)),t.AddContent(D.SequenceShuffleIndex()),(e||i)&&t.AddContent(n)}t.AddContent(D.EvalEnd());const a=D.NoOp();for(let e=0;e{this._sequenceDivertsToResolve.push(new bt(t,e))},this.sequenceType=e,this.sequenceElements=[];for(const e of t){const t=e.content;let n=null;n=null===t||0===t.length?e:new Pt(t),this.sequenceElements.push(n),this.AddContent(n)}}get typeName(){return"Sequence"}ResolveReferences(t){super.ResolveReferences(t);for(const t of this._sequenceDivertsToResolve)t.divert.targetPath=t.targetContent.path}}class _t extends d{constructor(){super(...arguments),this._overrideDivertTarget=null,this._divertAfter=null,this.GenerateRuntimeObject=()=>{const t=new L;if(t.AddContent(D.EvalStart()),this.divertAfter){const e=this.divertAfter.GenerateRuntimeObject(),n=e;if(n){const e=this.divertAfter.args;if(null!==e&&e.length>0){let e=-1,i=-1;for(let t=0;t` -> ${this._divertAfter}`}get divertAfter(){return this._divertAfter}set divertAfter(t){this._divertAfter=t,this._divertAfter&&this.AddContent(this._divertAfter)}get typeName(){return"TunnelOnwards"}ResolveReferences(t){super.ResolveReferences(t),this.divertAfter&&this.divertAfter.targetContent&&(this._overrideDivertTarget.targetPath=this.divertAfter.targetContent.runtimePath)}}let Tt=class{constructor(t,e){this._name=t||"",this._items=null,this._itemNameToValues=e||new Map}get name(){return this._name}get items(){if(null==this._items){this._items=new Map;for(let[t,e]of this._itemNameToValues){let n=new w(this.name,t);this._items.set(n.serialized(),e)}}return this._items}ValueForItem(t){if(!t.itemName)return 0;let e=this._itemNameToValues.get(t.itemName);return void 0!==e?e:0}ContainsItem(t){return!!t.itemName&&(t.originName==this.name&&this._itemNameToValues.has(t.itemName))}ContainsItemWithName(t){return this._itemNameToValues.has(t)}TryGetItemWithValue(t,e){for(let[e,n]of this._itemNameToValues)if(n==t)return{result:new w(this.name,e),exists:!0};return{result:w.Null,exists:!1}}TryGetValueForItem(t,e){if(!t.itemName)return{result:0,exists:!1};let n=this._itemNameToValues.get(t.itemName);return n?{result:n,exists:!0}:{result:0,exists:!1}}};class xt extends d{get typeName(){return"ListDefinition"}get runtimeListDefinition(){var t;const e=new Map;for(const t of this.itemDefinitions)e.has(t.name)?this.Error(`List '${this.identifier}' contains duplicate items called '${t.name}'`):e.set(t.name,t.seriesValue);return new Tt((null===(t=this.identifier)||void 0===t?void 0:t.name)||"",e)}constructor(t){super(),this.itemDefinitions=t,this.identifier=null,this.variableAssignment=null,this._elementsByName=null,this.ItemNamed=t=>{if(null===this._elementsByName){this._elementsByName=new Map;for(const t of this.itemDefinitions)this._elementsByName.set(t.name,t)}return this._elementsByName.get(t)||null},this.GenerateRuntimeObject=()=>{var t,e;const n=new E;for(const e of this.itemDefinitions)if(e.inInitialList){const i=new w((null===(t=this.identifier)||void 0===t?void 0:t.name)||null,e.name||null);n.Add(i,e.seriesValue)}return n.SetInitialOriginName((null===(e=this.identifier)||void 0===e?void 0:e.name)||""),new R(n)};let e=1;for(const t of this.itemDefinitions)null!==t.explicitValue&&(e=t.explicitValue),t.seriesValue=e,e+=1;this.AddContent(t)}ResolveReferences(t){super.ResolveReferences(t),t.CheckForNamingCollisions(this,this.identifier,z.List)}}class At extends d{get variableName(){return this.variableIdentifier.name}get typeName(){return this.isNewTemporaryDeclaration?"temp":this.isGlobalDeclaration?null!==this.listDefinition?"LIST":"VAR":"variable assignment"}get isDeclaration(){return this.isGlobalDeclaration||this.isNewTemporaryDeclaration}constructor(t){let{assignedExpression:e,isGlobalDeclaration:n,isTemporaryNewDeclaration:i,listDef:r,variableIdentifier:s}=t;super(),this._runtimeAssignment=null,this.expression=null,this.listDefinition=null,this.GenerateRuntimeObject=()=>{let t=null;if(this.isGlobalDeclaration?t=this.story:this.isNewTemporaryDeclaration&&(t=ut(this)),t&&t.AddNewVariableDeclaration(this),this.isGlobalDeclaration)return null;const e=new L;return this.expression?e.AddContent(this.expression.runtimeObject):this.listDefinition&&e.AddContent(this.listDefinition.runtimeObject),this._runtimeAssignment=new X(this.variableName,this.isNewTemporaryDeclaration),e.AddContent(this._runtimeAssignment),e},this.toString=()=>`${this.isGlobalDeclaration?"VAR":this.isNewTemporaryDeclaration?"~ temp":""} ${this.variableName}`,this.variableIdentifier=s,this.isGlobalDeclaration=Boolean(n),this.isNewTemporaryDeclaration=Boolean(i),r instanceof xt?(this.listDefinition=this.AddContent(r),this.listDefinition.variableAssignment=this,this.isGlobalDeclaration=!0):e&&(this.expression=this.AddContent(e))}ResolveReferences(t){if(super.ResolveReferences(t),this.isDeclaration&&null===this.listDefinition&&t.CheckForNamingCollisions(this,this.variableIdentifier,this.isGlobalDeclaration?z.Var:z.Temp),this.isGlobalDeclaration){const t=s(this.expression,ft);!t||t.isConstantReference||t.isListItemReference||this.Error("global variable assignments cannot refer to other variables, only literal values, constants and list items")}if(!this.isNewTemporaryDeclaration){const e=t.ResolveVariableWithName(this.variableName,this);e.found||(this.variableName in this.story.constants?this.Error(`Can't re-assign to a constant (do you need to use VAR when declaring '${this.variableName}'?)`,this):this.Error(`Variable could not be found to assign to: '${this.variableName}'`,this)),this._runtimeAssignment&&(this._runtimeAssignment.isGlobal=e.isGlobal)}}}class Pt extends d{get rootContainer(){return this._rootContainer||(this._rootContainer=this.GenerateRuntimeObject()),this._rootContainer}get namedWeavePoints(){return this._namedWeavePoints}get lastParsedSignificantObject(){if(0===this.content.length)return null;let t=null;for(let e=this.content.length-1;e>=0;--e){t=this.content[e];let n=s(t,rt);if((!n||"\n"!==n.text)&&!this.IsGlobalDeclaration(t))break}const e=s(t,Pt);return e&&(t=e.lastParsedSignificantObject),t}constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;super(),this.previousWeavePoint=null,this.addContentToPreviousWeavePoint=!1,this.hasSeenChoiceInSection=!1,this.currentContainer=null,this._unnamedGatherCount=0,this._choiceCount=0,this._rootContainer=null,this._namedWeavePoints=new Map,this.looseEnds=[],this.gatherPointsToResolve=[],this.ResolveWeavePointNaming=()=>{var t,e,n;const i=[...this.FindAll(ot)((t=>!(null===t.name||void 0===t.name))),...this.FindAll(Y)((t=>!(null===t.name||void 0===t.name)))];this._namedWeavePoints=new Map;for(const r of i){const i=this.namedWeavePoints.get((null===(t=r.identifier)||void 0===t?void 0:t.name)||"");if(i){const t=i instanceof ot?"gather":"choice",e=i;this.Error(`A ${t} with the same label name '${r.name}' already exists in this context on line ${e.debugMetadata?e.debugMetadata.startLineNumber:"NO DEBUG METADATA AVAILABLE"}`,r)}(null===(e=r.identifier)||void 0===e?void 0:e.name)&&this.namedWeavePoints.set(null===(n=r.identifier)||void 0===n?void 0:n.name,r)}},this.ConstructWeaveHierarchyFromIndentation=()=>{let t=0;for(;tthis.baseIndentIndex){let e=t;for(;t{for(const e of t)if(e instanceof Y||e instanceof ot)return e.indentationDepth-1;return 0},this.GenerateRuntimeObject=()=>{this._rootContainer=new L,this.currentContainer=this._rootContainer,this.looseEnds=[],this.gatherPointsToResolve=[];for(const t of this.content)if(t instanceof Y||t instanceof ot)this.AddRuntimeForWeavePoint(t);else if(t instanceof Pt){const e=t;this.AddRuntimeForNestedWeave(e),this.gatherPointsToResolve.splice(0,0,...e.gatherPointsToResolve)}else this.AddGeneralRuntimeContent(t.runtimeObject);return this.PassLooseEndsToAncestors(),this._rootContainer},this.AddRuntimeForGather=t=>{const e=!this.hasSeenChoiceInSection;this.hasSeenChoiceInSection=!1;const n=t.runtimeContainer;if(t.name||(n.name=`g-${this._unnamedGatherCount}`,this._unnamedGatherCount+=1),e){if(!this.currentContainer)throw new Error;this.currentContainer.AddContent(n)}else this.rootContainer.AddToNamedContentOnly(n);for(const e of this.looseEnds){const i=e;if(i instanceof ot){if(i.indentationDepth==t.indentationDepth)continue}let r=null;if(i instanceof St)r=i.runtimeObject;else{r=new J;const t=i;if(!t.runtimeContainer)throw new Error;t.runtimeContainer.AddContent(r)}this.gatherPointsToResolve.push(new yt(r,n))}this.looseEnds=[],this.currentContainer=n},this.AddRuntimeForWeavePoint=t=>{if(t instanceof ot)this.AddRuntimeForGather(t);else if(t instanceof Y){if(!this.currentContainer)throw new Error;this.previousWeavePoint instanceof ot&&this.looseEnds.splice(this.looseEnds.indexOf(this.previousWeavePoint),1);const e=t;if(this.currentContainer.AddContent(e.runtimeObject),!e.innerContentContainer)throw new Error;e.innerContentContainer.name=`c-${this._choiceCount}`,this.currentContainer.AddToNamedContentOnly(e.innerContentContainer),this._choiceCount+=1,this.hasSeenChoiceInSection=!0}if(this.addContentToPreviousWeavePoint=!1,this.WeavePointHasLooseEnd(t)){this.looseEnds.push(t);s(t,Y)&&(this.addContentToPreviousWeavePoint=!0)}this.previousWeavePoint=t},this.AddRuntimeForNestedWeave=t=>{this.AddGeneralRuntimeContent(t.rootContainer),null!==this.previousWeavePoint&&(this.looseEnds.splice(this.looseEnds.indexOf(this.previousWeavePoint),1),this.addContentToPreviousWeavePoint=!1)},this.AddGeneralRuntimeContent=t=>{if(null!==t)if(this.addContentToPreviousWeavePoint){if(!this.previousWeavePoint||!this.previousWeavePoint.runtimeContainer)throw new Error;this.previousWeavePoint.runtimeContainer.AddContent(t)}else{if(!this.currentContainer)throw new Error;this.currentContainer.AddContent(t)}},this.PassLooseEndsToAncestors=()=>{if(0===this.looseEnds.length)return;let t=null,e=null,n=!1;for(let i=this.parent;null!==i;i=i.parent){const r=s(i,Pt);r&&(n||null!==t||(t=r),n&&null===e&&(e=r)),(i instanceof Et||i instanceof it)&&(n=!0)}if(null!==t||null!==e)for(let i=this.looseEnds.length-1;i>=0;i-=1){const r=this.looseEnds[i];let s=!1;if(n){if(r instanceof Y&&null!==t)t.ReceiveLooseEnd(r),s=!0;else if(!(r instanceof Y)){const n=t||e;null!==n&&(n.ReceiveLooseEnd(r),s=!0)}}else(null==t?void 0:t.hasOwnProperty("ReceiveLooseEnd"))&&t.ReceiveLooseEnd(r),s=!0;s&&this.looseEnds.splice(i,1)}},this.ReceiveLooseEnd=t=>{this.looseEnds.push(t)},this.WeavePointNamed=t=>{if(!this.namedWeavePoints)return null;let e=this.namedWeavePoints.get(t);return e||null},this.IsGlobalDeclaration=t=>{const e=s(t,At);if(e&&e.isGlobalDeclaration&&e.isDeclaration)return!0;return!!s(t,st)},this.ContentThatFollowsWeavePoint=t=>{const e=[],n=t;if(null!==n.content)for(const t of n.content)this.IsGlobalDeclaration(t)||e.push(t);const i=s(n.parent,Pt);if(null===i)throw new Error("Expected weave point parent to be weave?");for(let t=i.content.indexOf(n)+1;t{if(this.lastParsedSignificantObject instanceof p)return;if(null!==this.looseEnds&&this.looseEnds.length>0)for(const e of this.looseEnds){const n=this.ContentThatFollowsWeavePoint(e);this.ValidateFlowOfObjectsTerminates(n,e,t)}else{for(const t of this.content)if(t instanceof Y||t instanceof St)return;this.ValidateFlowOfObjectsTerminates(this.content,this,t)}},this.BadNestedTerminationHandler=t=>{let e=null;for(let n=t.parent;null!==n;n=n.parent)if(n instanceof Et||n instanceof it){e=s(n,it);break}let n="Choices nested in conditionals or sequences need to explicitly divert afterwards.";if(null!==e){1===e.FindAll(Y)().length&&(n=`Choices with conditions should be written: '* {condition} choice'. Otherwise, ${n.toLowerCase()}`)}this.Error(n,t)},this.ValidateFlowOfObjectsTerminates=(t,e,n)=>{let i=!1,r=e;for(const e of t){if(null!==e.Find(St)((t=>!(t.isThread||t.isTunnel||t.isFunctionCall||t.parent instanceof Ct)))&&(i=!0),null!=e.Find(_t)()){i=!0;break}r=e}if(!i){if(r instanceof p)return;n(r)}},this.WeavePointHasLooseEnd=t=>{if(null===t.content)return!0;for(let e=t.content.length-1;e>=0;--e){let n=s(t.content[e],St);if(n){if(!(n.isThread||n.isTunnel||n.isFunctionCall))return!1}}return!0},this.CheckForWeavePointNamingCollisions=()=>{if(!this.namedWeavePoints)return;const t=[];for(const e of this.ancestry){const n=s(e,dt);if(!n)break;t.push(n)}for(const[e,n]of this.namedWeavePoints)for(const i of t){const t=i.ContentWithNameAtLevel(e);if(t&&t!==n){const i=`${n.GetType()} '${e}' has the same label name as a ${t.GetType()} (on ${t.debugMetadata})`;this.Error(i,n)}}},this.baseIndentIndex=-1==e?this.DetermineBaseIndentationFromContent(t):e,this.AddContent(t),this.ConstructWeaveHierarchyFromIndentation()}get typeName(){return"Weave"}ResolveReferences(t){if(super.ResolveReferences(t),null!==this.looseEnds&&this.looseEnds.length>0){let t=!1;for(let e=this.parent;null!==e;e=e.parent)if(e instanceof Et||e instanceof it){t=!0;break}t&&this.ValidateTermination(this.BadNestedTerminationHandler)}for(const t of this.gatherPointsToResolve)t.divert.targetPath=t.targetRuntimeObj.path;this.CheckForWeavePointNamingCollisions()}}class Nt extends d{get ownExpression(){return this._ownExpression}set ownExpression(t){this._ownExpression=t,this._ownExpression&&this.AddContent(this._ownExpression)}constructor(t){super(),this._contentContainer=null,this._conditionalDivert=null,this._ownExpression=null,this._innerWeave=null,this.isTrueBranch=!1,this.matchingEquality=!1,this.isElse=!1,this.isInline=!1,this.returnDivert=null,this.GenerateRuntimeObject=()=>{if(this._innerWeave)for(const t of this._innerWeave.content){const e=s(t,rt);e&&e.text.startsWith("else:")&&this.Warning("Saw the text 'else:' which is being treated as content. Did you mean '- else:'?",e)}const t=new L,e=this.matchingEquality&&!this.isElse;if(e&&t.AddContent(D.Duplicate()),this._conditionalDivert=new J,this._conditionalDivert.isConditional=!this.isElse,!this.isTrueBranch&&!this.isElse){const e=null!==this.ownExpression;e&&t.AddContent(D.EvalStart()),this.ownExpression&&this.ownExpression.GenerateIntoContainer(t),this.matchingEquality&&t.AddContent(B.CallWithName("==")),e&&t.AddContent(D.EvalEnd())}return t.AddContent(this._conditionalDivert),this._contentContainer=this.GenerateRuntimeForContent(),this._contentContainer.name="b",this.isInline||this._contentContainer.InsertContent(new I("\n"),0),(e||this.isElse&&this.matchingEquality)&&this._contentContainer.InsertContent(D.PopEvaluatedValue(),0),t.AddToNamedContentOnly(this._contentContainer),this.returnDivert=new J,this._contentContainer.AddContent(this.returnDivert),t},this.GenerateRuntimeForContent=()=>null===this._innerWeave?new L:this._innerWeave.rootContainer,t&&(this._innerWeave=new Pt(t),this.AddContent(this._innerWeave))}get typeName(){return"ConditionalSingleBranch"}ResolveReferences(t){if(!this._conditionalDivert||!this._contentContainer)throw new Error;this._conditionalDivert.targetPath=this._contentContainer.path,super.ResolveReferences(t)}}var Ot;!function(t){t[t.ParsingString=1]="ParsingString",t[t.TagActive=2]="TagActive"}(Ot||(Ot={}));class It{constructor(){this.startLineNumber=0,this.endLineNumber=0,this.startCharacterNumber=0,this.endCharacterNumber=0,this.fileName=null,this.sourceName=null}Merge(t){let e=new It;return e.fileName=this.fileName,e.sourceName=this.sourceName,this.startLineNumbert.startLineNumber?(e.startLineNumber=t.startLineNumber,e.startCharacterNumber=t.startCharacterNumber):(e.startLineNumber=this.startLineNumber,e.startCharacterNumber=Math.min(this.startCharacterNumber,t.startCharacterNumber)),this.endLineNumber>t.endLineNumber?(e.endLineNumber=this.endLineNumber,e.endCharacterNumber=this.endCharacterNumber):this.endLineNumber(this.story.AddExternal(this),null)}get typeName(){return"EXTERNAL"}toString(){var t;return`EXTERNAL ${null===(t=this.identifier)||void 0===t?void 0:t.name}`}}class Wt{constructor(t,e,n){this.name=t,this.args=e,this.isFunction=n}}class Rt extends d{constructor(t){super(),this._objToWrap=t,this.GenerateRuntimeObject=()=>this._objToWrap}}let kt=class extends Rt{constructor(t){super(t)}get typeName(){return"Glue"}};class Lt extends y{toString(){return"Glue"}}class Dt extends V{constructor(t,e,n){super(),this.varIdentifier=t,this._runtimeAssignment=null,this.expression=null,this.GenerateIntoContainer=t=>{var e,n;t.AddContent(new mt((null===(e=this.varIdentifier)||void 0===e?void 0:e.name)||null)),this.expression?this.expression.GenerateIntoContainer(t):t.AddContent(new N(1)),t.AddContent(B.CallWithName(this.isInc?"+":"-")),this._runtimeAssignment=new X((null===(n=this.varIdentifier)||void 0===n?void 0:n.name)||null,!1),t.AddContent(this._runtimeAssignment)},this.toString=()=>{var t,e;return this.expression?`${null===(t=this.varIdentifier)||void 0===t?void 0:t.name}${this.isInc?" += ":" -= "}${this.expression}`:`${null===(e=this.varIdentifier)||void 0===e?void 0:e.name}`+(this.isInc?"++":"--")},e instanceof V?(this.expression=e,this.AddContent(this.expression),this.isInc=Boolean(n)):this.isInc=e}get typeName(){return"IncDecExpression"}ResolveReferences(t){var e;super.ResolveReferences(t);const n=t.ResolveVariableWithName((null===(e=this.varIdentifier)||void 0===e?void 0:e.name)||"",this);if(n.found||this.Error(`variable for ${this.incrementDecrementWord} could not be found: '${this.varIdentifier}' after searching: {this.descriptionOfScope}`),!this._runtimeAssignment)throw new Error;this._runtimeAssignment.isGlobal=n.isGlobal,this.parent instanceof Pt||this.parent instanceof dt||this.parent instanceof pt||this.Error(`Can't use ${this.incrementDecrementWord} as sub-expression`)}get incrementDecrementWord(){return this.isInc?"increment":"decrement"}}class Vt extends d{constructor(t){super(),this.includedStory=t,this.GenerateRuntimeObject=()=>null}get typeName(){return"IncludedFile"}}class jt{constructor(t,e,n){this.type=t,this.precedence=e,this.requireWhitespace=n,this.toString=()=>this.type}}class Bt extends dt{get flowLevel(){return at.Knot}constructor(t,e,n,i){super(t,e,n,i)}get typeName(){return this.isFunction?"Function":"Knot"}ResolveReferences(t){super.ResolveReferences(t);let e=this.story;for(const t in this.subFlowsByName){const n=e.ContentWithNameAtLevel(t,at.Knot,!1);if(n){const e=this.subFlowsByName.get(t),i=`Stitch '${e?e.name:"NO STITCH FOUND"}' has the same name as a knot (on ${n.debugMetadata})`;this.Error(i,e)}}}}class Mt extends V{constructor(t){super(),this.itemIdentifierList=t,this.GenerateIntoContainer=t=>{var e,n;const i=new E;if(null!=this.itemIdentifierList)for(const t of this.itemIdentifierList){const r=(null===(e=null==t?void 0:t.name)||void 0===e?void 0:e.split("."))||[];let s=null,a="";r.length>1?(s=r[0],a=r[1]):a=r[0];const o=this.story.ResolveListItem(s,a,this);if(null===o)null===s?this.Error(`Could not find list definition that contains item '${t}'`):this.Error(`Could not find list item ${t}`);else{if(null==o.parent)return void this.Error(`Could not find list definition for item ${t}`);s||(s=(null===(n=o.parent.identifier)||void 0===n?void 0:n.name)||null);const e=new w(s,o.name||null);i.has(e.serialized())?this.Warning(`Duplicate of item '${t}' in list.`):i.Add(e,o.seriesValue)}}t.AddContent(new R(i))}}get typeName(){return"List"}}class Gt extends d{get fullName(){var t;const e=this.parent;if(null===e)throw new Error("Can't get full name without a parent list.");return`${null===(t=e.identifier)||void 0===t?void 0:t.name}.${this.name}`}get typeName(){return"ListElement"}get name(){var t;return(null===(t=this.indentifier)||void 0===t?void 0:t.name)||null}constructor(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;super(),this.indentifier=t,this.inInitialList=e,this.explicitValue=n,this.seriesValue=0,this.parent=null,this.GenerateRuntimeObject=()=>{throw new Error("Not implemented.")},this.toString=()=>this.fullName,this.parent=this.parent}ResolveReferences(t){super.ResolveReferences(t),t.CheckForNamingCollisions(this,this.indentifier,z.ListItem)}}var $t;t.StatementLevel=void 0,($t=t.StatementLevel||(t.StatementLevel={}))[$t.InnerBlock=0]="InnerBlock",$t[$t.Stitch=1]="Stitch",$t[$t.Knot=2]="Knot",$t[$t.Top=3]="Top";class qt extends dt{get flowLevel(){return at.Stitch}constructor(t,e,n,i){super(t,e,n,i),this.baseToString=this.toString,this.toString=()=>`${null!==this.parent?this.parent+" > ":""}${this.baseToString()}`}get typeName(){return"Stitch"}}let Ut=class extends y{constructor(t){super(),this.text=t.toString()||""}toString(){return"# "+this.text}};class Kt extends y{constructor(){super(...arguments),this.text="",this.index=0,this.threadAtGeneration=null,this.sourcePath="",this.targetPath=null,this.isInvisibleDefault=!1,this.tags=null,this.originalThreadIndex=0}get pathStringOnChoice(){return null===this.targetPath?S("Choice.targetPath"):this.targetPath.toString()}set pathStringOnChoice(t){this.targetPath=new m(t)}}class Ht{constructor(t){this._lists=new Map,this._allUnambiguousListValueCache=new Map;for(let e of t){this._lists.set(e.name,e);for(let[t,n]of e.items){let e=w.fromSerializedKey(t),i=new R(e,n);if(!e.itemName)throw new Error("item.itemName is null or undefined.");this._allUnambiguousListValueCache.set(e.itemName,i),this._allUnambiguousListValueCache.set(e.fullName,i)}}}get lists(){let t=[];for(let[,e]of this._lists)t.push(e);return t}TryListGetDefinition(t,e){if(null===t)return{result:e,exists:!1};let n=this._lists.get(t);return n?{result:n,exists:!0}:{result:e,exists:!1}}FindSingleItemListWithName(t){if(null===t)return S("name");let e=this._allUnambiguousListValueCache.get(t);return void 0!==e?e:null}}class Jt{static JArrayToRuntimeObjList(t){let e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.length;e&&n--;let i=[];for(let e=0;et->")),e=i.hasVariableTarget?i.variableDivertName:i.targetPathString,t.WriteObjectStart(),t.WriteProperty(n,e),i.hasVariableTarget&&t.WriteProperty("var",!0),i.isConditional&&t.WriteProperty("c",!0),i.externalArgs>0&&t.WriteIntProperty("exArgs",i.externalArgs),void t.WriteObjectEnd()}let r=s(e,K);if(r)return t.WriteObjectStart(),t.WriteProperty("*",r.pathStringOnChoice),t.WriteIntProperty("flg",r.flags),void t.WriteObjectEnd();let a=s(e,P);if(a)return void t.WriteBool(a.value);let o=s(e,N);if(o)return void t.WriteInt(o.value);let l=s(e,O);if(l)return void t.WriteFloat(l.value);let h=s(e,I);if(h)return void(h.isNewline?t.Write("\n",!1):(t.WriteStringStart(),t.WriteStringInner("^"),t.WriteStringInner(h.value),t.WriteStringEnd()));let u=s(e,R);if(u)return void this.WriteInkList(t,u);let c=s(e,F);if(c)return t.WriteObjectStart(),null===c.value?S("divTargetVal.value"):(t.WriteProperty("^->",c.value.componentsString),void t.WriteObjectEnd());let d=s(e,W);if(d)return t.WriteObjectStart(),t.WriteProperty("^var",d.value),t.WriteIntProperty("ci",d.contextIndex),void t.WriteObjectEnd();if(s(e,Lt))return void t.Write("<>");let p=s(e,D);if(p)return void t.Write(Jt._controlCommandNames[p.commandType]);let m=s(e,B);if(m){let e=m.name;return"^"==e&&(e="L^"),void t.Write(e)}let f=s(e,mt);if(f){t.WriteObjectStart();let e=f.pathStringForCount;return null!=e?t.WriteProperty("CNT?",e):t.WriteProperty("VAR?",f.name),void t.WriteObjectEnd()}let g=s(e,X);if(g){t.WriteObjectStart();let e=g.isGlobal?"VAR=":"temp=";return t.WriteProperty(e,g.variableName),g.isNewDeclaration||t.WriteProperty("re",!0),void t.WriteObjectEnd()}if(s(e,j))return void t.Write("void");let C=s(e,Ut);if(C)return t.WriteObjectStart(),t.WriteProperty("#",C.text),void t.WriteObjectEnd();let y=s(e,Kt);if(!y)throw new Error("Failed to convert runtime object to Json token: "+e);this.WriteChoice(t,y)}static JObjectToDictionaryRuntimeObjs(t){let e=new Map;for(let n in t)if(t.hasOwnProperty(n)){let i=this.JTokenToRuntimeObject(t[n]);if(null===i)return S("inkObject");e.set(n,i)}return e}static JObjectToIntDictionary(t){let e=new Map;for(let n in t)t.hasOwnProperty(n)&&e.set(n,parseInt(t[n]));return e}static JTokenToRuntimeObject(t){if("number"==typeof t&&!isNaN(t)||"boolean"==typeof t)return A.Create(t);if("string"==typeof t){let e=t.toString(),n=e[0];if("^"==n)return new I(e.substring(1));if("\n"==n&&1==e.length)return new I("\n");if("<>"==e)return new Lt;for(let t=0;t->"==e)return D.PopTunnel();if("~ret"==e)return D.PopFunction();if("void"==e)return new j}if("object"==typeof t&&!Array.isArray(t)){let e,n=t;if(n["^->"])return e=n["^->"],new F(new m(e.toString()));if(n["^var"]){e=n["^var"];let t=new W(e.toString());return"ci"in n&&(e=n.ci,t.contextIndex=parseInt(e)),t}let i=!1,r=!1,s=v.Function,a=!1;if((e=n["->"])?i=!0:(e=n["f()"])?(i=!0,r=!0,s=v.Function):(e=n["->t->"])?(i=!0,r=!0,s=v.Tunnel):(e=n["x()"])&&(i=!0,a=!0,r=!1,s=v.Function),i){let t=new J;t.pushesToStack=r,t.stackPushType=s,t.isExternal=a;let i=e.toString();return(e=n.var)?t.variableDivertName=i:t.targetPathString=i,t.isConditional=!!n.c,a&&(e=n.exArgs)&&(t.externalArgs=parseInt(e)),t}if(e=n["*"]){let t=new K;return t.pathStringOnChoice=e.toString(),(e=n.flg)&&(t.flags=parseInt(e)),t}if(e=n["VAR?"])return new mt(e.toString());if(e=n["CNT?"]){let t=new mt;return t.pathStringForCount=e.toString(),t}let o=!1,l=!1;if((e=n["VAR="])?(o=!0,l=!0):(e=n["temp="])&&(o=!0,l=!1),o){let t=e.toString(),i=!n.re,r=new X(t,i);return r.isGlobal=l,r}if(void 0!==n["#"])return e=n["#"],new Ut(e.toString());if(e=n.list){let t=e,i=new E;if(e=n.origins){let t=e;i.SetInitialOriginNames(t)}for(let e in t)if(t.hasOwnProperty(e)){let n=t[e],r=new w(e),s=parseInt(n);i.Add(r,s)}return new R(i)}if(null!=n.originalChoicePath)return this.JObjectToChoice(n)}if(Array.isArray(t))return this.JArrayToContainer(t);if(null==t)return null;throw new Error("Failed to convert token to runtime object: "+this.toJson(t,["parent"]))}static toJson(t,e,n){return JSON.stringify(t,((t,n)=>(null==e?void 0:e.some((e=>e===t)))?void 0:n),n)}static WriteRuntimeContainer(t,e){let n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(t.WriteArrayStart(),null===e)return S("container");for(let n of e.content)this.WriteRuntimeObject(t,n);let i=e.namedOnlyContent,r=e.countFlags,a=null!=e.name&&!n,o=null!=i||r>0||a;if(o&&t.WriteObjectStart(),null!=i)for(let[e,n]of i){let i=e,r=s(n,L);t.WritePropertyStart(i),this.WriteRuntimeContainer(t,r,!0),t.WritePropertyEnd()}r>0&&t.WriteIntProperty("#f",r),a&&t.WriteProperty("#n",e.name),o?t.WriteObjectEnd():t.WriteNull(),t.WriteArrayEnd()}static JArrayToContainer(t){let e=new L;e.content=this.JArrayToRuntimeObjList(t,!0);let n=t[t.length-1];if(null!=n){let t=new Map;for(let i in n)if("#f"==i)e.countFlags=parseInt(n[i]);else if("#n"==i)e.name=n[i].toString();else{let e=this.JTokenToRuntimeObject(n[i]),r=s(e,L);r&&(r.name=i),t.set(i,e)}e.namedOnlyContent=t}return e}static JObjectToChoice(t){let e=new Kt;return e.text=t.text.toString(),e.index=parseInt(t.index),e.sourcePath=t.originalChoicePath.toString(),e.originalThreadIndex=parseInt(t.originalThreadIndex),e.pathStringOnChoice=t.targetPath.toString(),t.tags&&(e.tags=t.tags),e}static WriteChoice(t,e){t.WriteObjectStart(),t.WriteProperty("text",e.text),t.WriteIntProperty("index",e.index),t.WriteProperty("originalChoicePath",e.sourcePath),t.WriteIntProperty("originalThreadIndex",e.originalThreadIndex),t.WriteProperty("targetPath",e.pathStringOnChoice),e.tags&&t.WriteProperty("tags",(t=>{t.WriteArrayStart();for(const n of e.tags)t.WriteStringStart(),t.WriteStringInner(n),t.WriteStringEnd();t.WriteArrayEnd()})),t.WriteObjectEnd()}static WriteInkList(t,e){let n=e.value;if(null===n)return S("rawList");t.WriteObjectStart(),t.WritePropertyStart("list"),t.WriteObjectStart();for(let[e,i]of n){let n=w.fromSerializedKey(e),r=i;if(null===n.itemName)return S("item.itemName");t.WritePropertyNameStart(),t.WritePropertyNameInner(n.originName?n.originName:"?"),t.WritePropertyNameInner("."),t.WritePropertyNameInner(n.itemName),t.WritePropertyNameEnd(),t.Write(r),t.WritePropertyEnd()}if(t.WriteObjectEnd(),t.WritePropertyEnd(),0==n.Count&&null!=n.originNames&&n.originNames.length>0){t.WritePropertyStart("origins"),t.WriteArrayStart();for(let e of n.originNames)t.Write(e);t.WriteArrayEnd(),t.WritePropertyEnd()}t.WriteObjectEnd()}static ListDefinitionsToJToken(t){let e={};for(let n of t.lists){let t={};for(let[e,i]of n.items){let n=w.fromSerializedKey(e);if(null===n.itemName)return S("item.itemName");t[n.itemName]=i}e[n.name]=t}return e}static JTokenToListDefinitions(t){let e=t,n=[];for(let t in e)if(e.hasOwnProperty(t)){let i=t.toString(),r=e[t],s=new Map;for(let n in r)if(e.hasOwnProperty(t)){let t=r[n];s.set(n,parseInt(t))}let a=new Tt(i,s);n.push(a)}return new Ht(n)}}Jt._controlCommandNames=(()=>{let t=[];t[D.CommandType.EvalStart]="ev",t[D.CommandType.EvalOutput]="out",t[D.CommandType.EvalEnd]="/ev",t[D.CommandType.Duplicate]="du",t[D.CommandType.PopEvaluatedValue]="pop",t[D.CommandType.PopFunction]="~ret",t[D.CommandType.PopTunnel]="->->",t[D.CommandType.BeginString]="str",t[D.CommandType.EndString]="/str",t[D.CommandType.NoOp]="nop",t[D.CommandType.ChoiceCount]="choiceCnt",t[D.CommandType.Turns]="turn",t[D.CommandType.TurnsSince]="turns",t[D.CommandType.ReadCount]="readc",t[D.CommandType.Random]="rnd",t[D.CommandType.SeedRandom]="srnd",t[D.CommandType.VisitIndex]="visit",t[D.CommandType.SequenceShuffleIndex]="seq",t[D.CommandType.StartThread]="thread",t[D.CommandType.Done]="done",t[D.CommandType.End]="end",t[D.CommandType.ListFromInt]="listInt",t[D.CommandType.ListRange]="range",t[D.CommandType.ListRandom]="lrnd",t[D.CommandType.BeginTag]="#",t[D.CommandType.EndTag]="/#";for(let e=0;e1}constructor(){if(this._threadCounter=0,this._startOfRoot=H.Null,arguments[0]instanceof re){let t=arguments[0];this._startOfRoot=H.StartOf(t.rootContentContainer),this.Reset()}else{let t=arguments[0];this._threads=[];for(let e of t._threads)this._threads.push(e.Copy());this._threadCounter=t._threadCounter,this._startOfRoot=t._startOfRoot.copy()}}Reset(){this._threads=[],this._threads.push(new zt.Thread),this._threads[0].callstack.push(new zt.Element(v.Tunnel,this._startOfRoot))}SetJsonToken(t,e){this._threads.length=0;let n=t.threads;for(let t of n){let n=t,i=new zt.Thread(n,e);this._threads.push(i)}this._threadCounter=parseInt(t.threadCounter),this._startOfRoot=H.StartOf(e.rootContentContainer)}WriteJson(t){t.WriteObject((t=>{t.WritePropertyStart("threads"),t.WriteArrayStart();for(let e of this._threads)e.WriteJson(t);t.WriteArrayEnd(),t.WritePropertyEnd(),t.WritePropertyStart("threadCounter"),t.WriteInt(this._threadCounter),t.WritePropertyEnd()}))}PushThread(){let t=this.currentThread.Copy();this._threadCounter++,t.threadIndex=this._threadCounter,this._threads.push(t)}ForkThread(){let t=this.currentThread.Copy();return this._threadCounter++,t.threadIndex=this._threadCounter,t}PopThread(){if(!this.canPopThread)throw new Error("Can't pop thread");this._threads.splice(this._threads.indexOf(this.currentThread),1)}get canPopThread(){return this._threads.length>1&&!this.elementIsEvaluateFromGame}get elementIsEvaluateFromGame(){return this.currentElement.type==v.FunctionEvaluationFromGame}Push(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,i=new zt.Element(t,this.currentElement.currentPointer,!1);i.evaluationStackHeightWhenPushed=e,i.functionStartInOutputStream=n,this.callStack.push(i)}CanPop(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;return!!this.canPop&&(null==t||this.currentElement.type==t)}Pop(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;if(!this.CanPop(t))throw new Error("Mismatched push/pop in Callstack");this.callStack.pop()}GetTemporaryVariableWithName(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;-1==e&&(e=this.currentElementIndex+1);let n=T(this.callStack[e-1].temporaryVariables,t,null);return n.exists?n.result:null}SetTemporaryVariable(t,e,n){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:-1;-1==i&&(i=this.currentElementIndex+1);let r=this.callStack[i-1];if(!n&&!r.temporaryVariables.get(t))throw new Error("Could not find temporary variable to set: "+t);let s=T(r.temporaryVariables,t,null);s.exists&&R.RetainListOriginsForAssignment(s.result,e),r.temporaryVariables.set(t,e)}ContextForVariableNamed(t){return this.currentElement.temporaryVariables.get(t)?this.currentElementIndex+1:0}ThreadWithIndex(t){let e=this._threads.filter((e=>{if(e.threadIndex==t)return e}));return e.length>0?e[0]:null}get callStack(){return this.currentThread.callstack}get callStackTrace(){let t=new b;for(let e=0;e")}}}return t.toString()}}!function(t){class e{constructor(t,e){let n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];this.evaluationStackHeightWhenPushed=0,this.functionStartInOutputStream=0,this.currentPointer=e.copy(),this.inExpressionEvaluation=n,this.temporaryVariables=new Map,this.type=t}Copy(){let t=new e(this.type,this.currentPointer,this.inExpressionEvaluation);return t.temporaryVariables=new Map(this.temporaryVariables),t.evaluationStackHeightWhenPushed=this.evaluationStackHeightWhenPushed,t.functionStartInOutputStream=this.functionStartInOutputStream,t}}t.Element=e;class n{constructor(){if(this.threadIndex=0,this.previousPointer=H.Null,this.callstack=[],arguments[0]&&arguments[1]){let t=arguments[0],n=arguments[1];this.threadIndex=parseInt(t.threadIndex);let i=t.callstack;for(let t of i){let i,r=t,s=parseInt(r.type),a=H.Null,o=r.cPath;if(void 0!==o){i=o.toString();let t=n.ContentAtPath(new m(i));if(a.container=t.container,a.index=parseInt(r.idx),null==t.obj)throw new Error("When loading state, internal story location couldn't be found: "+i+". Has the story changed since this save data was created?");if(t.approximate){if(null===a.container)return S("pointer.container");n.Warning("When loading state, exact internal story location couldn't be found: '"+i+"', so it was approximated to '"+a.container.path.toString()+"' to recover. Has the story changed since this save data was created?")}}let l=!!r.exp,h=new e(s,a,l),u=r.temp;void 0!==u?h.temporaryVariables=Jt.JObjectToDictionaryRuntimeObjs(u):h.temporaryVariables.clear(),this.callstack.push(h)}let r=t.previousContentObject;if(void 0!==r){let t=new m(r.toString());this.previousPointer=n.PointerAtPath(t)}}}Copy(){let t=new n;t.threadIndex=this.threadIndex;for(let e of this.callstack)t.callstack.push(e.Copy());return t.previousPointer=this.previousPointer.copy(),t}WriteJson(t){t.WriteObjectStart(),t.WritePropertyStart("callstack"),t.WriteArrayStart();for(let e of this.callstack){if(t.WriteObjectStart(),!e.currentPointer.isNull){if(null===e.currentPointer.container)return S("el.currentPointer.container");t.WriteProperty("cPath",e.currentPointer.container.path.componentsString),t.WriteIntProperty("idx",e.currentPointer.index)}t.WriteProperty("exp",e.inExpressionEvaluation),t.WriteIntProperty("type",e.type),e.temporaryVariables.size>0&&(t.WritePropertyStart("temp"),Jt.WriteDictionaryRuntimeObjs(t,e.temporaryVariables),t.WritePropertyEnd()),t.WriteObjectEnd()}if(t.WriteArrayEnd(),t.WritePropertyEnd(),t.WriteIntProperty("threadIndex",this.threadIndex),!this.previousPointer.isNull){let e=this.previousPointer.Resolve();if(null===e)return S("this.previousPointer.Resolve()");t.WriteProperty("previousContentObject",e.path.toString())}t.WriteObjectEnd()}}t.Thread=n}(zt||(zt={}));class Xt extends class{}{variableChangedEvent(t,e){for(let n of this.variableChangedEventCallbacks)n(t,e)}get batchObservingVariableChanges(){return this._batchObservingVariableChanges}set batchObservingVariableChanges(t){if(this._batchObservingVariableChanges=t,t)this._changedVariablesForBatchObs=new Set;else if(null!=this._changedVariablesForBatchObs){for(let t of this._changedVariablesForBatchObs){let e=this._globalVariables.get(t);e?this.variableChangedEvent(t,e):S("currentValue")}this._changedVariablesForBatchObs=null}}get callStack(){return this._callStack}set callStack(t){this._callStack=t}$(t,e){if(void 0===e){let e=null;return null!==this.patch&&(e=this.patch.TryGetGlobal(t,null),e.exists)?e.result.valueObject:(e=this._globalVariables.get(t),void 0===e&&(e=this._defaultGlobalVariables.get(t)),void 0!==e?e.valueObject:null)}{if(void 0===this._defaultGlobalVariables.get(t))throw new _("Cannot assign to a variable ("+t+") that hasn't been declared in the story");let n=A.Create(e);if(null==n)throw null==e?new Error("Cannot pass null to VariableState"):new Error("Invalid value passed to VariableState: "+e.toString());this.SetGlobal(t,n)}}constructor(t,e){super(),this.variableChangedEventCallbacks=[],this.patch=null,this._batchObservingVariableChanges=!1,this._defaultGlobalVariables=new Map,this._changedVariablesForBatchObs=new Set,this._globalVariables=new Map,this._callStack=t,this._listDefsOrigin=e;try{return new Proxy(this,{get:(t,e)=>e in t?t[e]:t.$(e),set:(t,e,n)=>(e in t?t[e]=n:t.$(e,n),!0)})}catch(t){}}ApplyPatch(){if(null===this.patch)return S("this.patch");for(let[t,e]of this.patch.globals)this._globalVariables.set(t,e);if(null!==this._changedVariablesForBatchObs)for(let t of this.patch.changedVariables)this._changedVariablesForBatchObs.add(t);this.patch=null}SetJsonToken(t){this._globalVariables.clear();for(let[e,n]of this._defaultGlobalVariables){let i=t[e];if(void 0!==i){let t=Jt.JTokenToRuntimeObject(i);if(null===t)return S("tokenInkObject");this._globalVariables.set(e,t)}else this._globalVariables.set(e,n)}}WriteJson(t){t.WriteObjectStart();for(let[e,n]of this._globalVariables){let i=e,r=n;if(Xt.dontSaveDefaultValues&&this._defaultGlobalVariables.has(i)){let t=this._defaultGlobalVariables.get(i);if(this.RuntimeObjectsEqual(r,t))continue}t.WritePropertyStart(i),Jt.WriteRuntimeObject(t,r),t.WritePropertyEnd()}t.WriteObjectEnd()}RuntimeObjectsEqual(t,e){if(null===t)return S("obj1");if(null===e)return S("obj2");if(t.constructor!==e.constructor)return!1;let n=s(t,P);if(null!==n)return n.value===a(e,P).value;let i=s(t,N);if(null!==i)return i.value===a(e,N).value;let r=s(t,O);if(null!==r)return r.value===a(e,O).value;let o=s(t,A),l=s(e,A);if(null!==o&&null!==l)return h(o.valueObject)&&h(l.valueObject)?o.valueObject.Equals(l.valueObject):o.valueObject===l.valueObject;throw new Error("FastRoughDefinitelyEquals: Unsupported runtime object type: "+t.constructor.name)}GetVariableWithName(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1,n=this.GetRawVariableWithName(t,e),i=s(n,W);return null!==i&&(n=this.ValueAtVariablePointer(i)),n}TryGetDefaultVariableValue(t){let e=T(this._defaultGlobalVariables,t,null);return e.exists?e.result:null}GlobalVariableExistsWithName(t){return this._globalVariables.has(t)||null!==this._defaultGlobalVariables&&this._defaultGlobalVariables.has(t)}GetRawVariableWithName(t,e){let n=null;if(0==e||-1==e){let e=null;if(null!==this.patch&&(e=this.patch.TryGetGlobal(t,null),e.exists))return e.result;if(e=T(this._globalVariables,t,null),e.exists)return e.result;if(null!==this._defaultGlobalVariables&&(e=T(this._defaultGlobalVariables,t,null),e.exists))return e.result;if(null===this._listDefsOrigin)return S("VariablesState._listDefsOrigin");let n=this._listDefsOrigin.FindSingleItemListWithName(t);if(n)return n}return n=this._callStack.GetTemporaryVariableWithName(t,e),n}ValueAtVariablePointer(t){return this.GetVariableWithName(t.variableName,t.contextIndex)}Assign(t,e){let n=t.variableName;if(null===n)return S("name");let i=-1,r=!1;if(r=t.isNewDeclaration?t.isGlobal:this.GlobalVariableExistsWithName(n),t.isNewDeclaration){let t=s(e,W);if(null!==t){e=this.ResolveVariablePointer(t)}}else{let t=null;do{t=s(this.GetRawVariableWithName(n,i),W),null!=t&&(n=t.variableName,i=t.contextIndex,r=0==i)}while(null!=t)}r?this.SetGlobal(n,e):this._callStack.SetTemporaryVariable(n,e,t.isNewDeclaration,i)}SnapshotDefaultGlobals(){this._defaultGlobalVariables=new Map(this._globalVariables)}RetainListOriginsForAssignment(t,e){let n=a(t,R),i=a(e,R);n.value&&i.value&&0==i.value.Count&&i.value.SetInitialOriginNames(n.value.originNames)}SetGlobal(t,e){let n=null;if(null===this.patch&&(n=T(this._globalVariables,t,null)),null!==this.patch&&(n=this.patch.TryGetGlobal(t,null),n.exists||(n=T(this._globalVariables,t,null))),R.RetainListOriginsForAssignment(n.result,e),null===t)return S("variableName");if(null!==this.patch?this.patch.SetGlobal(t,e):this._globalVariables.set(t,e),null!==this.variableChangedEvent&&null!==n&&e!==n.result)if(this.batchObservingVariableChanges){if(null===this._changedVariablesForBatchObs)return S("this._changedVariablesForBatchObs");null!==this.patch?this.patch.AddChangedVariable(t):null!==this._changedVariablesForBatchObs&&this._changedVariablesForBatchObs.add(t)}else this.variableChangedEvent(t,e)}ResolveVariablePointer(t){let e=t.contextIndex;-1==e&&(e=this.GetContextIndexOfVariableNamed(t.variableName));let n=s(this.GetRawVariableWithName(t.variableName,e),W);return null!=n?n:new W(t.variableName,e)}GetContextIndexOfVariableNamed(t){return this.GlobalVariableExistsWithName(t)?0:this._callStack.currentElementIndex}ObserveVariableChange(t){this.variableChangedEventCallbacks.push(t)}}Xt.dontSaveDefaultValues=!0;class Yt{constructor(t){this.seed=t%2147483647,this.seed<=0&&(this.seed+=2147483646)}next(){return this.seed=48271*this.seed%2147483647}nextFloat(){return(this.next()-1)/2147483646}}class Zt{get globals(){return this._globals}get changedVariables(){return this._changedVariables}get visitCounts(){return this._visitCounts}get turnIndices(){return this._turnIndices}constructor(){if(this._changedVariables=new Set,this._visitCounts=new Map,this._turnIndices=new Map,1===arguments.length&&null!==arguments[0]){let t=arguments[0];this._globals=new Map(t._globals),this._changedVariables=new Set(t._changedVariables),this._visitCounts=new Map(t._visitCounts),this._turnIndices=new Map(t._turnIndices)}else this._globals=new Map,this._changedVariables=new Set,this._visitCounts=new Map,this._turnIndices=new Map}TryGetGlobal(t,e){return null!==t&&this._globals.has(t)?{result:this._globals.get(t),exists:!0}:{result:e,exists:!1}}SetGlobal(t,e){this._globals.set(t,e)}AddChangedVariable(t){return this._changedVariables.add(t)}TryGetVisitCount(t,e){return this._visitCounts.has(t)?{result:this._visitCounts.get(t),exists:!0}:{result:e,exists:!1}}SetVisitCount(t,e){this._visitCounts.set(t,e)}SetTurnIndex(t,e){this._turnIndices.set(t,e)}TryGetTurnIndex(t,e){return this._turnIndices.has(t)?{result:this._turnIndices.get(t),exists:!0}:{result:e,exists:!1}}}class Qt{static TextToDictionary(t){return new Qt.Reader(t).ToDictionary()}static TextToArray(t){return new Qt.Reader(t).ToArray()}}!function(t){t.Reader=class{constructor(t){this._rootObject=JSON.parse(t)}ToDictionary(){return this._rootObject}ToArray(){return this._rootObject}};class e{constructor(){this._currentPropertyName=null,this._currentString=null,this._stateStack=[],this._collectionStack=[],this._propertyNameStack=[],this._jsonObject=null}WriteObject(t){this.WriteObjectStart(),t(this),this.WriteObjectEnd()}WriteObjectStart(){this.StartNewObject(!0);let e={};if(this.state===t.Writer.State.Property){this.Assert(null!==this.currentCollection),this.Assert(null!==this.currentPropertyName);let t=this._propertyNameStack.pop();this.currentCollection[t]=e,this._collectionStack.push(e)}else this.state===t.Writer.State.Array?(this.Assert(null!==this.currentCollection),this.currentCollection.push(e),this._collectionStack.push(e)):(this.Assert(this.state===t.Writer.State.None),this._jsonObject=e,this._collectionStack.push(e));this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Object))}WriteObjectEnd(){this.Assert(this.state===t.Writer.State.Object),this._collectionStack.pop(),this._stateStack.pop()}WriteProperty(t,e){if(this.WritePropertyStart(t),arguments[1]instanceof Function){(0,arguments[1])(this)}else{let t=arguments[1];this.Write(t)}this.WritePropertyEnd()}WriteIntProperty(t,e){this.WritePropertyStart(t),this.WriteInt(e),this.WritePropertyEnd()}WriteFloatProperty(t,e){this.WritePropertyStart(t),this.WriteFloat(e),this.WritePropertyEnd()}WritePropertyStart(e){this.Assert(this.state===t.Writer.State.Object),this._propertyNameStack.push(e),this.IncrementChildCount(),this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Property))}WritePropertyEnd(){this.Assert(this.state===t.Writer.State.Property),this.Assert(1===this.childCount),this._stateStack.pop()}WritePropertyNameStart(){this.Assert(this.state===t.Writer.State.Object),this.IncrementChildCount(),this._currentPropertyName="",this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Property)),this._stateStack.push(new t.Writer.StateElement(t.Writer.State.PropertyName))}WritePropertyNameEnd(){this.Assert(this.state===t.Writer.State.PropertyName),this.Assert(null!==this._currentPropertyName),this._propertyNameStack.push(this._currentPropertyName),this._currentPropertyName=null,this._stateStack.pop()}WritePropertyNameInner(e){this.Assert(this.state===t.Writer.State.PropertyName),this.Assert(null!==this._currentPropertyName),this._currentPropertyName+=e}WriteArrayStart(){this.StartNewObject(!0);let e=[];if(this.state===t.Writer.State.Property){this.Assert(null!==this.currentCollection),this.Assert(null!==this.currentPropertyName);let t=this._propertyNameStack.pop();this.currentCollection[t]=e,this._collectionStack.push(e)}else this.state===t.Writer.State.Array?(this.Assert(null!==this.currentCollection),this.currentCollection.push(e),this._collectionStack.push(e)):(this.Assert(this.state===t.Writer.State.None),this._jsonObject=e,this._collectionStack.push(e));this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Array))}WriteArrayEnd(){this.Assert(this.state===t.Writer.State.Array),this._collectionStack.pop(),this._stateStack.pop()}Write(t){null!==t?(this.StartNewObject(!1),this._addToCurrentObject(t)):console.error("Warning: trying to write a null value")}WriteBool(t){null!==t&&(this.StartNewObject(!1),this._addToCurrentObject(t))}WriteInt(t){null!==t&&(this.StartNewObject(!1),this._addToCurrentObject(Math.floor(t)))}WriteFloat(t){null!==t&&(this.StartNewObject(!1),t==Number.POSITIVE_INFINITY?this._addToCurrentObject(34e37):t==Number.NEGATIVE_INFINITY?this._addToCurrentObject(-34e37):isNaN(t)?this._addToCurrentObject(0):this._addToCurrentObject(t))}WriteNull(){this.StartNewObject(!1),this._addToCurrentObject(null)}WriteStringStart(){this.StartNewObject(!1),this._currentString="",this._stateStack.push(new t.Writer.StateElement(t.Writer.State.String))}WriteStringEnd(){this.Assert(this.state==t.Writer.State.String),this._stateStack.pop(),this._addToCurrentObject(this._currentString),this._currentString=null}WriteStringInner(e){this.Assert(this.state===t.Writer.State.String),null!==e?this._currentString+=e:console.error("Warning: trying to write a null string")}toString(){return null===this._jsonObject?"":JSON.stringify(this._jsonObject)}StartNewObject(e){e?this.Assert(this.state===t.Writer.State.None||this.state===t.Writer.State.Property||this.state===t.Writer.State.Array):this.Assert(this.state===t.Writer.State.Property||this.state===t.Writer.State.Array),this.state===t.Writer.State.Property&&this.Assert(0===this.childCount),this.state!==t.Writer.State.Array&&this.state!==t.Writer.State.Property||this.IncrementChildCount()}get state(){return this._stateStack.length>0?this._stateStack[this._stateStack.length-1].type:t.Writer.State.None}get childCount(){return this._stateStack.length>0?this._stateStack[this._stateStack.length-1].childCount:0}get currentCollection(){return this._collectionStack.length>0?this._collectionStack[this._collectionStack.length-1]:null}get currentPropertyName(){return this._propertyNameStack.length>0?this._propertyNameStack[this._propertyNameStack.length-1]:null}IncrementChildCount(){this.Assert(this._stateStack.length>0);let t=this._stateStack.pop();t.childCount++,this._stateStack.push(t)}Assert(t){if(!t)throw Error("Assert failed while writing JSON")}_addToCurrentObject(e){this.Assert(null!==this.currentCollection),this.state===t.Writer.State.Array?(this.Assert(Array.isArray(this.currentCollection)),this.currentCollection.push(e)):this.state===t.Writer.State.Property&&(this.Assert(!Array.isArray(this.currentCollection)),this.Assert(null!==this.currentPropertyName),this.currentCollection[this.currentPropertyName]=e,this._propertyNameStack.pop())}}t.Writer=e,function(e){var n;(n=e.State||(e.State={}))[n.None=0]="None",n[n.Object=1]="Object",n[n.Array=2]="Array",n[n.Property=3]="Property",n[n.PropertyName=4]="PropertyName",n[n.String=5]="String";e.StateElement=class{constructor(e){this.type=t.Writer.State.None,this.childCount=0,this.type=e}}}(e=t.Writer||(t.Writer={}))}(Qt||(Qt={}));class te{constructor(){let t=arguments[0],e=arguments[1];if(this.name=t,this.callStack=new zt(e),arguments[2]){let t=arguments[2];this.callStack.SetJsonToken(t.callstack,e),this.outputStream=Jt.JArrayToRuntimeObjList(t.outputStream),this.currentChoices=Jt.JArrayToRuntimeObjList(t.currentChoices);let n=t.choiceThreads;void 0!==n&&this.LoadFlowChoiceThreads(n,e)}else this.outputStream=[],this.currentChoices=[]}WriteJson(t){t.WriteObjectStart(),t.WriteProperty("callstack",(t=>this.callStack.WriteJson(t))),t.WriteProperty("outputStream",(t=>Jt.WriteListRuntimeObjs(t,this.outputStream)));let e=!1;for(let n of this.currentChoices){if(null===n.threadAtGeneration)return S("c.threadAtGeneration");n.originalThreadIndex=n.threadAtGeneration.threadIndex,null===this.callStack.ThreadWithIndex(n.originalThreadIndex)&&(e||(e=!0,t.WritePropertyStart("choiceThreads"),t.WriteObjectStart()),t.WritePropertyStart(n.originalThreadIndex),n.threadAtGeneration.WriteJson(t),t.WritePropertyEnd())}e&&(t.WriteObjectEnd(),t.WritePropertyEnd()),t.WriteProperty("currentChoices",(t=>{t.WriteArrayStart();for(let e of this.currentChoices)Jt.WriteChoice(t,e);t.WriteArrayEnd()})),t.WriteObjectEnd()}LoadFlowChoiceThreads(t,e){for(let n of this.currentChoices){let i=this.callStack.ThreadWithIndex(n.originalThreadIndex);if(null!==i)n.threadAtGeneration=i.Copy();else{let i=t[`${n.originalThreadIndex}`];n.threadAtGeneration=new zt.Thread(i,e)}}}}class ee{ToJson(){let t=new Qt.Writer;return this.WriteJson(t),t.toString()}toJson(){let t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return this.ToJson(t)}LoadJson(t){let e=Qt.TextToDictionary(t);this.LoadJsonObj(e),null!==this.onDidLoadState&&this.onDidLoadState()}VisitCountAtPathString(t){let e;if(null!==this._patch){let n=this.story.ContentAtPath(new m(t)).container;if(null===n)throw new Error("Content at path not found: "+t);if(e=this._patch.TryGetVisitCount(n,0),e.exists)return e.result}return e=T(this._visitCounts,t,null),e.exists?e.result:0}VisitCountForContainer(t){if(null===t)return S("container");if(!t.visitsShouldBeCounted)return this.story.Error("Read count for target ("+t.name+" - on "+t.debugMetadata+") unknown. The story may need to be compiled with countAllVisits flag (-c)."),0;if(null!==this._patch){let e=this._patch.TryGetVisitCount(t,0);if(e.exists)return e.result}let e=t.path.toString(),n=T(this._visitCounts,e,null);return n.exists?n.result:0}IncrementVisitCountForContainer(t){if(null!==this._patch){let e=this.VisitCountForContainer(t);return e++,void this._patch.SetVisitCount(t,e)}let e=t.path.toString(),n=T(this._visitCounts,e,null);n.exists?this._visitCounts.set(e,n.result+1):this._visitCounts.set(e,1)}RecordTurnIndexVisitToContainer(t){if(null!==this._patch)return void this._patch.SetTurnIndex(t,this.currentTurnIndex);let e=t.path.toString();this._turnIndices.set(e,this.currentTurnIndex)}TurnsSinceForContainer(t){if(t.turnIndexShouldBeCounted||this.story.Error("TURNS_SINCE() for target ("+t.name+" - on "+t.debugMetadata+") unknown. The story may need to be compiled with countAllVisits flag (-c)."),null!==this._patch){let e=this._patch.TryGetTurnIndex(t,0);if(e.exists)return this.currentTurnIndex-e.result}let e=t.path.toString(),n=T(this._turnIndices,e,0);return n.exists?this.currentTurnIndex-n.result:-1}get callstackDepth(){return this.callStack.depth}get outputStream(){return this._currentFlow.outputStream}get currentChoices(){return this.canContinue?[]:this._currentFlow.currentChoices}get generatedChoices(){return this._currentFlow.currentChoices}get currentErrors(){return this._currentErrors}get currentWarnings(){return this._currentWarnings}get variablesState(){return this._variablesState}set variablesState(t){this._variablesState=t}get callStack(){return this._currentFlow.callStack}get evaluationStack(){return this._evaluationStack}get currentTurnIndex(){return this._currentTurnIndex}set currentTurnIndex(t){this._currentTurnIndex=t}get currentPathString(){let t=this.currentPointer;return t.isNull?null:null===t.path?S("pointer.path"):t.path.toString()}get currentPointer(){return this.callStack.currentElement.currentPointer.copy()}set currentPointer(t){this.callStack.currentElement.currentPointer=t.copy()}get previousPointer(){return this.callStack.currentThread.previousPointer.copy()}set previousPointer(t){this.callStack.currentThread.previousPointer=t.copy()}get canContinue(){return!this.currentPointer.isNull&&!this.hasError}get hasError(){return null!=this.currentErrors&&this.currentErrors.length>0}get hasWarning(){return null!=this.currentWarnings&&this.currentWarnings.length>0}get currentText(){if(this._outputStreamTextDirty){let t=new b,e=!1;for(let n of this.outputStream){let i=s(n,I);if(e||null===i){let t=s(n,D);null!==t&&(t.commandType==D.CommandType.BeginTag?e=!0:t.commandType==D.CommandType.EndTag&&(e=!1))}else t.Append(i.value)}this._currentText=this.CleanOutputWhitespace(t.toString()),this._outputStreamTextDirty=!1}return this._currentText}CleanOutputWhitespace(t){let e=new b,n=-1,i=0;for(let r=0;r0&&n!=i&&e.Append(" "),n=-1),"\n"==s&&(i=r+1),a||e.Append(s)}return e.toString()}get currentTags(){if(this._outputStreamTagsDirty){this._currentTags=[];let t=!1,e=new b;for(let n of this.outputStream){let i=s(n,D);if(null!=i){if(i.commandType==D.CommandType.BeginTag){if(t&&e.Length>0){let t=this.CleanOutputWhitespace(e.toString());this._currentTags.push(t),e.Clear()}t=!0}else if(i.commandType==D.CommandType.EndTag){if(e.Length>0){let t=this.CleanOutputWhitespace(e.toString());this._currentTags.push(t),e.Clear()}t=!1}}else if(t){let t=s(n,I);null!==t&&e.Append(t.value)}else{let t=s(n,Ut);null!=t&&null!=t.text&&t.text.length>0&&this._currentTags.push(t.text)}}if(e.Length>0){let t=this.CleanOutputWhitespace(e.toString());this._currentTags.push(t),e.Clear()}this._outputStreamTagsDirty=!1}return this._currentTags}get currentFlowName(){return this._currentFlow.name}get currentFlowIsDefaultFlow(){return this._currentFlow.name==this.kDefaultFlowName}get aliveFlowNames(){if(this._aliveFlowNamesDirty){if(this._aliveFlowNames=[],null!=this._namedFlows)for(let t of this._namedFlows.keys())t!=this.kDefaultFlowName&&this._aliveFlowNames.push(t);this._aliveFlowNamesDirty=!1}return this._aliveFlowNames}get inExpressionEvaluation(){return this.callStack.currentElement.inExpressionEvaluation}set inExpressionEvaluation(t){this.callStack.currentElement.inExpressionEvaluation=t}constructor(t){this.kInkSaveStateVersion=10,this.kMinCompatibleLoadVersion=8,this.onDidLoadState=null,this._currentErrors=null,this._currentWarnings=null,this.divertedPointer=H.Null,this._currentTurnIndex=0,this.storySeed=0,this.previousRandom=0,this.didSafeExit=!1,this._currentText=null,this._currentTags=null,this._outputStreamTextDirty=!0,this._outputStreamTagsDirty=!0,this._patch=null,this._aliveFlowNames=null,this._namedFlows=null,this.kDefaultFlowName="DEFAULT_FLOW",this._aliveFlowNamesDirty=!0,this.story=t,this._currentFlow=new te(this.kDefaultFlowName,t),this.OutputStreamDirty(),this._aliveFlowNamesDirty=!0,this._evaluationStack=[],this._variablesState=new Xt(this.callStack,t.listDefinitions),this._visitCounts=new Map,this._turnIndices=new Map,this.currentTurnIndex=-1;let e=(new Date).getTime();this.storySeed=new Yt(e).next()%100,this.previousRandom=0,this.GoToStart()}GoToStart(){this.callStack.currentElement.currentPointer=H.StartOf(this.story.mainContentContainer)}SwitchFlow_Internal(t){if(null===t)throw new Error("Must pass a non-null string to Story.SwitchFlow");if(null===this._namedFlows&&(this._namedFlows=new Map,this._namedFlows.set(this.kDefaultFlowName,this._currentFlow)),t===this._currentFlow.name)return;let e,n=T(this._namedFlows,t,null);n.exists?e=n.result:(e=new te(t,this.story),this._namedFlows.set(t,e),this._aliveFlowNamesDirty=!0),this._currentFlow=e,this.variablesState.callStack=this._currentFlow.callStack,this.OutputStreamDirty()}SwitchToDefaultFlow_Internal(){null!==this._namedFlows&&this.SwitchFlow_Internal(this.kDefaultFlowName)}RemoveFlow_Internal(t){if(null===t)throw new Error("Must pass a non-null string to Story.DestroyFlow");if(t===this.kDefaultFlowName)throw new Error("Cannot destroy default flow");if(this._currentFlow.name===t&&this.SwitchToDefaultFlow_Internal(),null===this._namedFlows)return S("this._namedFlows");this._namedFlows.delete(t),this._aliveFlowNamesDirty=!0}CopyAndStartPatching(){let t=new ee(this.story);if(t._patch=new Zt(this._patch),t._currentFlow.name=this._currentFlow.name,t._currentFlow.callStack=new zt(this._currentFlow.callStack),t._currentFlow.currentChoices.push(...this._currentFlow.currentChoices),t._currentFlow.outputStream.push(...this._currentFlow.outputStream),t.OutputStreamDirty(),null!==this._namedFlows){t._namedFlows=new Map;for(let[e,n]of this._namedFlows)t._namedFlows.set(e,n),t._aliveFlowNamesDirty=!0;t._namedFlows.set(this._currentFlow.name,t._currentFlow)}return this.hasError&&(t._currentErrors=[],t._currentErrors.push(...this.currentErrors||[])),this.hasWarning&&(t._currentWarnings=[],t._currentWarnings.push(...this.currentWarnings||[])),t.variablesState=this.variablesState,t.variablesState.callStack=t.callStack,t.variablesState.patch=t._patch,t.evaluationStack.push(...this.evaluationStack),this.divertedPointer.isNull||(t.divertedPointer=this.divertedPointer.copy()),t.previousPointer=this.previousPointer.copy(),t._visitCounts=this._visitCounts,t._turnIndices=this._turnIndices,t.currentTurnIndex=this.currentTurnIndex,t.storySeed=this.storySeed,t.previousRandom=this.previousRandom,t.didSafeExit=this.didSafeExit,t}RestoreAfterPatch(){this.variablesState.callStack=this.callStack,this.variablesState.patch=this._patch}ApplyAnyPatch(){if(null!==this._patch){this.variablesState.ApplyPatch();for(let[t,e]of this._patch.visitCounts)this.ApplyCountChanges(t,e,!0);for(let[t,e]of this._patch.turnIndices)this.ApplyCountChanges(t,e,!1);this._patch=null}}ApplyCountChanges(t,e,n){(n?this._visitCounts:this._turnIndices).set(t.path.toString(),e)}WriteJson(t){if(t.WriteObjectStart(),t.WritePropertyStart("flows"),t.WriteObjectStart(),null!==this._namedFlows)for(let[e,n]of this._namedFlows)t.WriteProperty(e,(t=>n.WriteJson(t)));else t.WriteProperty(this._currentFlow.name,(t=>this._currentFlow.WriteJson(t)));if(t.WriteObjectEnd(),t.WritePropertyEnd(),t.WriteProperty("currentFlowName",this._currentFlow.name),t.WriteProperty("variablesState",(t=>this.variablesState.WriteJson(t))),t.WriteProperty("evalStack",(t=>Jt.WriteListRuntimeObjs(t,this.evaluationStack))),!this.divertedPointer.isNull){if(null===this.divertedPointer.path)return S("divertedPointer");t.WriteProperty("currentDivertTarget",this.divertedPointer.path.componentsString)}t.WriteProperty("visitCounts",(t=>Jt.WriteIntDictionary(t,this._visitCounts))),t.WriteProperty("turnIndices",(t=>Jt.WriteIntDictionary(t,this._turnIndices))),t.WriteIntProperty("turnIdx",this.currentTurnIndex),t.WriteIntProperty("storySeed",this.storySeed),t.WriteIntProperty("previousRandom",this.previousRandom),t.WriteIntProperty("inkSaveVersion",this.kInkSaveStateVersion),t.WriteIntProperty("inkFormatVersion",re.inkVersionCurrent),t.WriteObjectEnd()}LoadJsonObj(t){let e=t,n=e.inkSaveVersion;if(null==n)throw new Error("ink save format incorrect, can't load.");if(parseInt(n)1){let t=e.currentFlowName;this._currentFlow=this._namedFlows.get(t)}}else{this._namedFlows=null,this._currentFlow.name=this.kDefaultFlowName,this._currentFlow.callStack.SetJsonToken(e.callstackThreads,this.story),this._currentFlow.outputStream=Jt.JArrayToRuntimeObjList(e.outputStream),this._currentFlow.currentChoices=Jt.JArrayToRuntimeObjList(e.currentChoices);let t=e.choiceThreads;this._currentFlow.LoadFlowChoiceThreads(t,this.story)}this.OutputStreamDirty(),this._aliveFlowNamesDirty=!0,this.variablesState.SetJsonToken(e.variablesState),this.variablesState.callStack=this._currentFlow.callStack,this._evaluationStack=Jt.JArrayToRuntimeObjList(e.evalStack);let r=e.currentDivertTarget;if(null!=r){let t=new m(r.toString());this.divertedPointer=this.story.PointerAtPath(t)}this._visitCounts=Jt.JObjectToIntDictionary(e.visitCounts),this._turnIndices=Jt.JObjectToIntDictionary(e.turnIndices),this.currentTurnIndex=parseInt(e.turnIdx),this.storySeed=parseInt(e.storySeed),this.previousRandom=parseInt(e.previousRandom)}ResetErrors(){this._currentErrors=null,this._currentWarnings=null}ResetOutput(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;this.outputStream.length=0,null!==t&&this.outputStream.push(...t),this.OutputStreamDirty()}PushToOutputStream(t){let e=s(t,I);if(null!==e){let t=this.TrySplittingHeadTailWhitespace(e);if(null!==t){for(let e of t)this.PushToOutputStreamIndividual(e);return void this.OutputStreamDirty()}}this.PushToOutputStreamIndividual(t),this.OutputStreamDirty()}PopFromOutputStream(t){this.outputStream.splice(this.outputStream.length-t,t),this.OutputStreamDirty()}TrySplittingHeadTailWhitespace(t){let e=t.value;if(null===e)return S("single.value");let n=-1,i=-1;for(let t=0;t=0;t--){let n=e[t];if("\n"!=n){if(" "==n||"\t"==n)continue;break}-1==r&&(r=t),s=t}if(-1==n&&-1==r)return null;let a=[],o=0,l=e.length;if(-1!=n){if(n>0){let t=new I(e.substring(0,n));a.push(t)}a.push(new I("\n")),o=i+1}if(-1!=r&&(l=s),l>o){let t=e.substring(o,l);a.push(new I(t))}if(-1!=r&&s>i&&(a.push(new I("\n")),r=0;e--){let n=this.outputStream[e],i=n instanceof D?n:null;if(null!=(n instanceof Lt?n:null)){r=e;break}if(null!=i&&i.commandType==D.CommandType.BeginString){e>=t&&(t=-1);break}}let s=-1;if(s=-1!=r&&-1!=t?Math.min(t,r):-1!=r?r:t,-1!=s){if(n.isNewline)i=!1;else if(n.isNonWhitespace&&(r>-1&&this.RemoveExistingGlue(),t>-1)){let t=this.callStack.elements;for(let e=t.length-1;e>=0;e--){let n=t[e];if(n.type!=v.Function)break;n.functionStartInOutputStream=-1}}}else n.isNewline&&(!this.outputStreamEndsInNewline&&this.outputStreamContainsContent||(i=!1))}if(i){if(null===t)return S("obj");this.outputStream.push(t),this.OutputStreamDirty()}}TrimNewlinesFromOutputStream(){let t=-1,e=this.outputStream.length-1;for(;e>=0;){let n=this.outputStream[e],i=s(n,D),r=s(n,I);if(null!=i||null!=r&&r.isNonWhitespace)break;null!=r&&r.isNewline&&(t=e),e--}if(t>=0)for(e=t;e=0;t--){let e=this.outputStream[t];if(e instanceof Lt)this.outputStream.splice(t,1);else if(e instanceof D)break}this.OutputStreamDirty()}get outputStreamEndsInNewline(){if(this.outputStream.length>0)for(let t=this.outputStream.length-1;t>=0;t--){if(this.outputStream[t]instanceof D)break;let e=this.outputStream[t];if(e instanceof I){if(e.isNewline)return!0;if(e.isNonWhitespace)break}}return!1}get outputStreamContainsContent(){for(let t of this.outputStream)if(t instanceof I)return!0;return!1}get inStringEvaluation(){for(let t=this.outputStream.length-1;t>=0;t--){let e=s(this.outputStream[t],D);if(e instanceof D&&e.commandType==D.CommandType.BeginString)return!0}return!1}PushEvaluationStack(t){let e=s(t,R);if(e){let t=e.value;if(null===t)return S("rawList");if(null!=t.originNames){t.origins||(t.origins=[]),t.origins.length=0;for(let e of t.originNames){if(null===this.story.listDefinitions)return S("StoryState.story.listDefinitions");let n=this.story.listDefinitions.TryListGetDefinition(e,null);if(null===n.result)return S("StoryState def.result");t.origins.indexOf(n.result)<0&&t.origins.push(n.result)}}}if(null===t)return S("obj");this.evaluationStack.push(t)}PopEvaluationStack(t){if(void 0===t){return l(this.evaluationStack.pop())}if(t>this.evaluationStack.length)throw new Error("trying to pop too many objects");return l(this.evaluationStack.splice(this.evaluationStack.length-t,t))}PeekEvaluationStack(){return this.evaluationStack[this.evaluationStack.length-1]}ForceEnd(){this.callStack.Reset(),this._currentFlow.currentChoices.length=0,this.currentPointer=H.Null,this.previousPointer=H.Null,this.didSafeExit=!0}TrimWhitespaceFromFunctionEnd(){f.Assert(this.callStack.currentElement.type==v.Function);let t=this.callStack.currentElement.functionStartInOutputStream;-1==t&&(t=0);for(let e=this.outputStream.length-1;e>=t;e--){let t=this.outputStream[e],n=s(t,I),i=s(t,D);if(null!=n){if(i)break;if(!n.isNewline&&!n.isInlineWhitespace)break;this.outputStream.splice(e,1),this.OutputStreamDirty()}}}PopCallStack(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;this.callStack.currentElement.type==v.Function&&this.TrimWhitespaceFromFunctionEnd(),this.callStack.Pop(t)}SetChosenPath(t,e){this._currentFlow.currentChoices.length=0;let n=this.story.PointerAtPath(t);n.isNull||-1!=n.index||(n.index=0),this.currentPointer=n,e&&this.currentTurnIndex++}StartFunctionEvaluationFromGame(t,e){this.callStack.Push(v.FunctionEvaluationFromGame,this.evaluationStack.length),this.callStack.currentElement.currentPointer=H.StartOf(t),this.PassArgumentsToEvaluationStack(e)}PassArgumentsToEvaluationStack(t){if(null!==t)for(let e=0;et;){let t=this.PopEvaluationStack();null===e&&(e=t)}if(this.PopCallStack(v.FunctionEvaluationFromGame),e){if(e instanceof j)return null;let t=a(e,A);return t.valueType==g.DivertTarget?t.valueObject.toString():t.valueObject}return null}AddError(t,e){e?(null==this._currentWarnings&&(this._currentWarnings=[]),this._currentWarnings.push(t)):(null==this._currentErrors&&(this._currentErrors=[]),this._currentErrors.push(t))}OutputStreamDirty(){this._outputStreamTextDirty=!0,this._outputStreamTagsDirty=!0}}class ne{constructor(){this.startTime=void 0}get ElapsedMilliseconds(){return void 0===this.startTime?0:(new Date).getTime()-this.startTime}Start(){this.startTime=(new Date).getTime()}Stop(){this.startTime=void 0}}var ie;!function(t){t[t.Author=0]="Author",t[t.Warning=1]="Warning",t[t.Error=2]="Error"}(ie||(ie={})),Number.isInteger||(Number.isInteger=function(t){return"number"==typeof t&&isFinite(t)&&t>-9007199254740992&&t<9007199254740992&&Math.floor(t)===t});let re=class t extends y{get currentChoices(){let t=[];if(null===this._state)return S("this._state");for(let e of this._state.currentChoices)e.isInvisibleDefault||(e.index=t.length,t.push(e));return t}get currentText(){return this.IfAsyncWeCant("call currentText since it's a work in progress"),this.state.currentText}get currentTags(){return this.IfAsyncWeCant("call currentTags since it's a work in progress"),this.state.currentTags}get currentErrors(){return this.state.currentErrors}get currentWarnings(){return this.state.currentWarnings}get currentFlowName(){return this.state.currentFlowName}get currentFlowIsDefaultFlow(){return this.state.currentFlowIsDefaultFlow}get aliveFlowNames(){return this.state.aliveFlowNames}get hasError(){return this.state.hasError}get hasWarning(){return this.state.hasWarning}get variablesState(){return this.state.variablesState}get listDefinitions(){return this._listDefinitions}get state(){return this._state}StartProfiling(){}EndProfiling(){}constructor(){let e;super(),this.inkVersionMinimumCompatible=18,this.onError=null,this.onDidContinue=null,this.onMakeChoice=null,this.onEvaluateFunction=null,this.onCompleteEvaluateFunction=null,this.onChoosePathString=null,this._prevContainers=[],this.allowExternalFunctionFallbacks=!1,this._listDefinitions=null,this._variableObservers=null,this._hasValidatedExternals=!1,this._temporaryEvaluationContainer=null,this._asyncContinueActive=!1,this._stateSnapshotAtLastNewline=null,this._sawLookaheadUnsafeFunctionAfterNewline=!1,this._recursiveContinueCount=0,this._asyncSaving=!1,this._profiler=null;let n=null,i=null;if(arguments[0]instanceof L)e=arguments[0],void 0!==arguments[1]&&(n=arguments[1]),this._mainContentContainer=e;else if("string"==typeof arguments[0]){let t=arguments[0];i=Qt.TextToDictionary(t)}else i=arguments[0];if(null!=n&&(this._listDefinitions=new Ht(n)),this._externals=new Map,null!==i){let e=i,n=e.inkVersion;if(null==n)throw new Error("ink version number not found. Are you sure it's a valid .ink.json file?");let r=parseInt(n);if(r>t.inkVersionCurrent)throw new Error("Version of ink used to build story was newer than the current version of the engine");if(rJt.WriteRuntimeContainer(t,this._mainContentContainer))),null!=this._listDefinitions){e.WritePropertyStart("listDefs"),e.WriteObjectStart();for(let t of this._listDefinitions.lists){e.WritePropertyStart(t.name),e.WriteObjectStart();for(let[n,i]of t.items){let t=w.fromSerializedKey(n),r=i;e.WriteIntProperty(t.itemName,r)}e.WriteObjectEnd(),e.WritePropertyEnd()}e.WriteObjectEnd(),e.WritePropertyEnd()}if(e.WriteObjectEnd(),n)return e.toString()}ResetState(){this.IfAsyncWeCant("ResetState"),this._state=new ee(this),this._state.variablesState.ObserveVariableChange(this.VariableStateDidChangeEvent.bind(this)),this.ResetGlobals()}ResetErrors(){if(null===this._state)return S("this._state");this._state.ResetErrors()}ResetCallstack(){if(this.IfAsyncWeCant("ResetCallstack"),null===this._state)return S("this._state");this._state.ForceEnd()}ResetGlobals(){if(this._mainContentContainer.namedContent.get("global decl")){let t=this.state.currentPointer.copy();this.ChoosePath(new m("global decl"),!1),this.ContinueInternal(),this.state.currentPointer=t}this.state.variablesState.SnapshotDefaultGlobals()}SwitchFlow(t){if(this.IfAsyncWeCant("switch flow"),this._asyncSaving)throw new Error("Story is already in background saving mode, can't switch flow to "+t);this.state.SwitchFlow_Internal(t)}RemoveFlow(t){this.state.RemoveFlow_Internal(t)}SwitchToDefaultFlow(){this.state.SwitchToDefaultFlow_Internal()}Continue(){return this.ContinueAsync(0),this.currentText}get canContinue(){return this.state.canContinue}get asyncContinueComplete(){return!this._asyncContinueActive}ContinueAsync(t){this._hasValidatedExternals||this.ValidateExternalBindings(),this.ContinueInternal(t)}ContinueInternal(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;null!=this._profiler&&this._profiler.PreContinue();let e=t>0;if(this._recursiveContinueCount++,!this._asyncContinueActive){if(this._asyncContinueActive=e,!this.canContinue)throw new Error("Can't continue - should check canContinue before calling Continue");this._state.didSafeExit=!1,this._state.ResetOutput(),1==this._recursiveContinueCount&&(this._state.variablesState.batchObservingVariableChanges=!0)}let n=new ne;n.Start();let i=!1;this._sawLookaheadUnsafeFunctionAfterNewline=!1;do{try{i=this.ContinueSingleStep()}catch(t){if(!(t instanceof _))throw t;this.AddError(t.message,void 0,t.useEndLineNumber);break}if(i)break;if(this._asyncContinueActive&&n.ElapsedMilliseconds>t)break}while(this.canContinue);if(n.Stop(),!i&&this.canContinue||(null!==this._stateSnapshotAtLastNewline&&this.RestoreStateSnapshot(),this.canContinue||(this.state.callStack.canPopThread&&this.AddError("Thread available to pop, threads should always be flat by the end of evaluation?"),0!=this.state.generatedChoices.length||this.state.didSafeExit||null!=this._temporaryEvaluationContainer||(this.state.callStack.CanPop(v.Tunnel)?this.AddError("unexpectedly reached end of content. Do you need a '->->' to return from a tunnel?"):this.state.callStack.CanPop(v.Function)?this.AddError("unexpectedly reached end of content. Do you need a '~ return'?"):this.state.callStack.canPop?this.AddError("unexpectedly reached end of content for unknown reason. Please debug compiler!"):this.AddError("ran out of content. Do you need a '-> DONE' or '-> END'?"))),this.state.didSafeExit=!1,this._sawLookaheadUnsafeFunctionAfterNewline=!1,1==this._recursiveContinueCount&&(this._state.variablesState.batchObservingVariableChanges=!1),this._asyncContinueActive=!1,null!==this.onDidContinue&&this.onDidContinue()),this._recursiveContinueCount--,null!=this._profiler&&this._profiler.PostContinue(),this.state.hasError||this.state.hasWarning){if(null===this.onError){let t=new b;throw t.Append("Ink had "),this.state.hasError&&(t.Append(`${this.state.currentErrors.length}`),t.Append(1==this.state.currentErrors.length?" error":"errors"),this.state.hasWarning&&t.Append(" and ")),this.state.hasWarning&&(t.Append(`${this.state.currentWarnings.length}`),t.Append(1==this.state.currentWarnings.length?" warning":"warnings"),this.state.hasWarning&&t.Append(" and ")),t.Append(". It is strongly suggested that you assign an error handler to story.onError. The first issue was: "),t.Append(this.state.hasError?this.state.currentErrors[0]:this.state.currentWarnings[0]),new _(t.toString())}if(this.state.hasError)for(let t of this.state.currentErrors)this.onError(t,ie.Error);if(this.state.hasWarning)for(let t of this.state.currentWarnings)this.onError(t,ie.Warning);this.ResetErrors()}}ContinueSingleStep(){if(null!=this._profiler&&this._profiler.PreStep(),this.Step(),null!=this._profiler&&this._profiler.PostStep(),this.canContinue||this.state.callStack.elementIsEvaluateFromGame||this.TryFollowDefaultInvisibleChoice(),null!=this._profiler&&this._profiler.PreSnapshot(),!this.state.inStringEvaluation){if(null!==this._stateSnapshotAtLastNewline){if(null===this._stateSnapshotAtLastNewline.currentTags)return S("this._stateAtLastNewline.currentTags");if(null===this.state.currentTags)return S("this.state.currentTags");let e=this.CalculateNewlineOutputStateChange(this._stateSnapshotAtLastNewline.currentText,this.state.currentText,this._stateSnapshotAtLastNewline.currentTags.length,this.state.currentTags.length);if(e==t.OutputStateChange.ExtendedBeyondNewline||this._sawLookaheadUnsafeFunctionAfterNewline)return this.RestoreStateSnapshot(),!0;e==t.OutputStateChange.NewlineRemoved&&this.DiscardSnapshot()}this.state.outputStreamEndsInNewline&&(this.canContinue?null==this._stateSnapshotAtLastNewline&&this.StateSnapshot():this.DiscardSnapshot())}return null!=this._profiler&&this._profiler.PostSnapshot(),!1}CalculateNewlineOutputStateChange(e,n,i,r){if(null===e)return S("prevText");if(null===n)return S("currText");let s=n.length>=e.length&&e.length>0&&"\n"==n.charAt(e.length-1);if(i==r&&e.length==n.length&&s)return t.OutputStateChange.NoChange;if(!s)return t.OutputStateChange.NewlineRemoved;if(r>i)return t.OutputStateChange.ExtendedBeyondNewline;for(let i=e.length;i0?this.Error("Failed to find content at path '"+t+"', and no approximation of it was possible."):i.approximate&&this.Warning("Failed to find content at path '"+t+"', so it was approximated to: '"+i.obj.path+"'."),e)}StateSnapshot(){this._stateSnapshotAtLastNewline=this._state,this._state=this._state.CopyAndStartPatching()}RestoreStateSnapshot(){null===this._stateSnapshotAtLastNewline&&S("_stateSnapshotAtLastNewline"),this._stateSnapshotAtLastNewline.RestoreAfterPatch(),this._state=this._stateSnapshotAtLastNewline,this._stateSnapshotAtLastNewline=null,this._asyncSaving||this._state.ApplyAnyPatch()}DiscardSnapshot(){this._asyncSaving||this._state.ApplyAnyPatch(),this._stateSnapshotAtLastNewline=null}CopyStateForBackgroundThreadSave(){if(this.IfAsyncWeCant("start saving on a background thread"),this._asyncSaving)throw new Error("Story is already in background saving mode, can't call CopyStateForBackgroundThreadSave again!");let t=this._state;return this._state=this._state.CopyAndStartPatching(),this._asyncSaving=!0,t}BackgroundSaveComplete(){null===this._stateSnapshotAtLastNewline&&this._state.ApplyAnyPatch(),this._asyncSaving=!1}Step(){let t=!0,e=this.state.currentPointer.copy();if(e.isNull)return;let n=s(e.Resolve(),L);for(;n&&(this.VisitContainer(n,!0),0!=n.content.length);)e=H.StartOf(n),n=s(e.Resolve(),L);this.state.currentPointer=e.copy(),null!=this._profiler&&this._profiler.Step(this.state.callStack);let i=e.Resolve(),r=this.PerformLogicAndFlowControl(i);if(this.state.currentPointer.isNull)return;r&&(t=!1);let a=s(i,K);if(a){let e=this.ProcessChoice(a);e&&this.state.generatedChoices.push(e),i=null,t=!1}if(i instanceof L&&(t=!1),t){let t=s(i,W);if(t&&-1==t.contextIndex){let e=this.state.callStack.ContextForVariableNamed(t.variableName);i=new W(t.variableName,e)}this.state.inExpressionEvaluation?this.state.PushEvaluationStack(i):this.state.PushToOutputStream(i)}this.NextContent();let o=s(i,D);o&&o.commandType==D.CommandType.StartThread&&this.state.callStack.PushThread()}VisitContainer(t,e){t.countingAtStartOnly&&!e||(t.visitsShouldBeCounted&&this.state.IncrementVisitCountForContainer(t),t.turnIndexShouldBeCounted&&this.state.RecordTurnIndexVisitToContainer(t))}VisitChangedContainersDueToDivert(){let t=this.state.previousPointer.copy(),e=this.state.currentPointer.copy();if(e.isNull||-1==e.index)return;if(this._prevContainers.length=0,!t.isNull){let e=s(t.Resolve(),L)||s(t.container,L);for(;e;)this._prevContainers.push(e),e=s(e.parent,L)}let n=e.Resolve();if(null==n)return;let i=s(n.parent,L),r=!0;for(;i&&(this._prevContainers.indexOf(i)<0||i.countingAtStartOnly);){let t=i.content.length>0&&n==i.content[0]&&r;t||(r=!1),this.VisitContainer(i,t),n=i,i=s(i.parent,L)}}PopChoiceStringAndTags(t){let e=a(this.state.PopEvaluationStack(),I);for(;this.state.evaluationStack.length>0&&null!=s(this.state.PeekEvaluationStack(),Ut);){let e=s(this.state.PopEvaluationStack(),Ut);e&&t.push(e.text)}return e.value}ProcessChoice(t){let e=!0;if(t.hasCondition){let t=this.state.PopEvaluationStack();this.IsTruthy(t)||(e=!1)}let n="",i="",r=[];if(t.hasChoiceOnlyContent&&(i=this.PopChoiceStringAndTags(r)||""),t.hasStartContent&&(n=this.PopChoiceStringAndTags(r)||""),t.onceOnly){this.state.VisitCountForContainer(t.choiceTarget)>0&&(e=!1)}if(!e)return null;let s=new Kt;return s.targetPath=t.pathOnChoice,s.sourcePath=t.path.toString(),s.isInvisibleDefault=t.isInvisibleDefault,s.threadAtGeneration=this.state.callStack.ForkThread(),s.tags=r.reverse(),s.text=(n+i).replace(/^[ \t]+|[ \t]+$/g,""),s}IsTruthy(t){if(t instanceof A){let e=t;if(e instanceof F){let t=e;return this.Error("Shouldn't use a divert target (to "+t.targetPath+") as a conditional value. Did you intend a function call 'likeThis()' or a read count check 'likeThis'? (no arrows)"),!1}return e.isTruthy}return!1}PerformLogicAndFlowControl(t){if(null==t)return!1;if(t instanceof J){let e=t;if(e.isConditional){let t=this.state.PopEvaluationStack();if(!this.IsTruthy(t))return!0}if(e.hasVariableTarget){let t=e.variableDivertName,n=this.state.variablesState.GetVariableWithName(t);if(null==n)this.Error("Tried to divert using a target from a variable that could not be found ("+t+")");else if(!(n instanceof F)){let e=s(n,N),i="Tried to divert to a target from a variable, but the variable ("+t+") didn't contain a divert target, it ";e instanceof N&&0==e.value?i+="was empty/null (the value 0).":i+="contained '"+n+"'.",this.Error(i)}let i=a(n,F);this.state.divertedPointer=this.PointerAtPath(i.targetPath)}else{if(e.isExternal)return this.CallExternalFunction(e.targetPathString,e.externalArgs),!0;this.state.divertedPointer=e.targetPointer.copy()}return e.pushesToStack&&this.state.callStack.Push(e.stackPushType,void 0,this.state.outputStream.length),this.state.divertedPointer.isNull&&!e.isExternal&&(e&&e.debugMetadata&&null!=e.debugMetadata.sourceName?this.Error("Divert target doesn't exist: "+e.debugMetadata.sourceName):this.Error("Divert resolution failed: "+e)),!0}if(t instanceof D){let e=t;switch(e.commandType){case D.CommandType.EvalStart:this.Assert(!1===this.state.inExpressionEvaluation,"Already in expression evaluation?"),this.state.inExpressionEvaluation=!0;break;case D.CommandType.EvalEnd:this.Assert(!0===this.state.inExpressionEvaluation,"Not in expression evaluation mode"),this.state.inExpressionEvaluation=!1;break;case D.CommandType.EvalOutput:if(this.state.evaluationStack.length>0){let t=this.state.PopEvaluationStack();if(!(t instanceof j)){let e=new I(t.toString());this.state.PushToOutputStream(e)}}break;case D.CommandType.NoOp:break;case D.CommandType.Duplicate:this.state.PushEvaluationStack(this.state.PeekEvaluationStack());break;case D.CommandType.PopEvaluatedValue:this.state.PopEvaluationStack();break;case D.CommandType.PopFunction:case D.CommandType.PopTunnel:let t=e.commandType==D.CommandType.PopFunction?v.Function:v.Tunnel,n=null;if(t==v.Tunnel){let t=this.state.PopEvaluationStack();n=s(t,F),null===n&&this.Assert(t instanceof j,"Expected void if ->-> doesn't override target")}if(this.state.TryExitFunctionEvaluationFromGame())break;if(this.state.callStack.currentElement.type==t&&this.state.callStack.canPop)this.state.PopCallStack(),n&&(this.state.divertedPointer=this.PointerAtPath(n.targetPath));else{let e=new Map;e.set(v.Function,"function return statement (~ return)"),e.set(v.Tunnel,"tunnel onwards statement (->->)");let n=e.get(this.state.callStack.currentElement.type);this.state.callStack.canPop||(n="end of flow (-> END or choice)");let i="Found "+e.get(t)+", when expected "+n;this.Error(i)}break;case D.CommandType.BeginString:this.state.PushToOutputStream(e),this.Assert(!0===this.state.inExpressionEvaluation,"Expected to be in an expression when evaluating a string"),this.state.inExpressionEvaluation=!1;break;case D.CommandType.BeginTag:this.state.PushToOutputStream(e);break;case D.CommandType.EndTag:if(this.state.inStringEvaluation){let t=[],e=0;for(let n=this.state.outputStream.length-1;n>=0;--n){let i=this.state.outputStream[n];e++;let r=s(i,D);if(null!=r){if(r.commandType==D.CommandType.BeginTag)break;this.Error("Unexpected ControlCommand while extracting tag from choice");break}i instanceof I&&t.push(i)}this.state.PopFromOutputStream(e);let n=new b;for(let e of t.reverse())n.Append(e.toString());let i=new Ut(this.state.CleanOutputWhitespace(n.toString()));this.state.PushEvaluationStack(i)}else this.state.PushToOutputStream(e);break;case D.CommandType.EndString:{let t=[],e=[],n=0;for(let i=this.state.outputStream.length-1;i>=0;--i){let r=this.state.outputStream[i];n++;let a=s(r,D);if(a&&a.commandType==D.CommandType.BeginString)break;r instanceof Ut&&e.push(r),r instanceof I&&t.push(r)}this.state.PopFromOutputStream(n);for(let t of e)this.state.PushToOutputStream(t);t=t.reverse();let i=new b;for(let e of t)i.Append(e.toString());this.state.inExpressionEvaluation=!0,this.state.PushEvaluationStack(new I(i.toString()));break}case D.CommandType.ChoiceCount:let i=this.state.generatedChoices.length;this.state.PushEvaluationStack(new N(i));break;case D.CommandType.Turns:this.state.PushEvaluationStack(new N(this.state.currentTurnIndex+1));break;case D.CommandType.TurnsSince:case D.CommandType.ReadCount:let r=this.state.PopEvaluationStack();if(!(r instanceof F)){let t="";r instanceof N&&(t=". Did you accidentally pass a read count ('knot_name') instead of a target ('-> knot_name')?"),this.Error("TURNS_SINCE / READ_COUNT expected a divert target (knot, stitch, label name), but saw "+r+t);break}let o,l=a(r,F),h=s(this.ContentAtPath(l.targetPath).correctObj,L);null!=h?o=e.commandType==D.CommandType.TurnsSince?this.state.TurnsSinceForContainer(h):this.state.VisitCountForContainer(h):(o=e.commandType==D.CommandType.TurnsSince?-1:0,this.Warning("Failed to find container for "+e.toString()+" lookup at "+l.targetPath.toString())),this.state.PushEvaluationStack(new N(o));break;case D.CommandType.Random:{let t=s(this.state.PopEvaluationStack(),N),e=s(this.state.PopEvaluationStack(),N);if(null==e||e instanceof N==!1)return this.Error("Invalid value for minimum parameter of RANDOM(min, max)");if(null==t||t instanceof N==!1)return this.Error("Invalid value for maximum parameter of RANDOM(min, max)");if(null===t.value)return S("maxInt.value");if(null===e.value)return S("minInt.value");let n=t.value-e.value+1;(!isFinite(n)||n>Number.MAX_SAFE_INTEGER)&&(n=Number.MAX_SAFE_INTEGER,this.Error("RANDOM was called with a range that exceeds the size that ink numbers can use.")),n<=0&&this.Error("RANDOM was called with minimum as "+e.value+" and maximum as "+t.value+". The maximum must be larger");let i=this.state.storySeed+this.state.previousRandom,r=new Yt(i).next(),a=r%n+e.value;this.state.PushEvaluationStack(new N(a)),this.state.previousRandom=r;break}case D.CommandType.SeedRandom:let u=s(this.state.PopEvaluationStack(),N);if(null==u||u instanceof N==!1)return this.Error("Invalid value passed to SEED_RANDOM");if(null===u.value)return S("minInt.value");this.state.storySeed=u.value,this.state.previousRandom=0,this.state.PushEvaluationStack(new j);break;case D.CommandType.VisitIndex:let c=this.state.VisitCountForContainer(this.state.currentPointer.container)-1;this.state.PushEvaluationStack(new N(c));break;case D.CommandType.SequenceShuffleIndex:let d=this.NextSequenceShuffleIndex();this.state.PushEvaluationStack(new N(d));break;case D.CommandType.StartThread:break;case D.CommandType.Done:this.state.callStack.canPopThread?this.state.callStack.PopThread():(this.state.didSafeExit=!0,this.state.currentPointer=H.Null);break;case D.CommandType.End:this.state.ForceEnd();break;case D.CommandType.ListFromInt:let p=s(this.state.PopEvaluationStack(),N),m=a(this.state.PopEvaluationStack(),I);if(null===p)throw new _("Passed non-integer when creating a list element from a numerical value.");let f=null;if(null===this.listDefinitions)return S("this.listDefinitions");let g=this.listDefinitions.TryListGetDefinition(m.value,null);if(!g.exists)throw new _("Failed to find LIST called "+m.value);{if(null===p.value)return S("minInt.value");let t=g.result.TryGetItemWithValue(p.value,w.Null);t.exists&&(f=new R(t.result,p.value))}null==f&&(f=new R),this.state.PushEvaluationStack(f);break;case D.CommandType.ListRange:let C=s(this.state.PopEvaluationStack(),A),y=s(this.state.PopEvaluationStack(),A),T=s(this.state.PopEvaluationStack(),R);if(null===T||null===y||null===C)throw new _("Expected list, minimum and maximum for LIST_RANGE");if(null===T.value)return S("targetList.value");let x=T.value.ListWithSubRange(y.valueObject,C.valueObject);this.state.PushEvaluationStack(new R(x));break;case D.CommandType.ListRandom:{let t=this.state.PopEvaluationStack();if(null===t)throw new _("Expected list for LIST_RANDOM");let e=t.value,n=null;if(null===e)throw S("list");if(0==e.Count)n=new E;else{let t=this.state.storySeed+this.state.previousRandom,i=new Yt(t).next(),r=i%e.Count,s=e.entries();for(let t=0;t<=r-1;t++)s.next();let a=s.next().value,o={Key:w.fromSerializedKey(a[0]),Value:a[1]};if(null===o.Key.originName)return S("randomItem.Key.originName");n=new E(o.Key.originName,this),n.Add(o.Key,o.Value),this.state.previousRandom=i}this.state.PushEvaluationStack(new R(n));break}default:this.Error("unhandled ControlCommand: "+e)}return!0}if(t instanceof X){let e=t,n=this.state.PopEvaluationStack();return this.state.variablesState.Assign(e,n),!0}if(t instanceof mt){let e=t,n=null;if(null!=e.pathForCount){let t=e.containerForCount,i=this.state.VisitCountForContainer(t);n=new N(i)}else n=this.state.variablesState.GetVariableWithName(e.name),null==n&&(this.Warning("Variable not found: '"+e.name+"'. Using default value of 0 (false). This can happen with temporary variables if the declaration hasn't yet been hit. Globals are always given a default value on load if a value doesn't exist in the save state."),n=new N(0));return this.state.PushEvaluationStack(n),!0}if(t instanceof B){let e=t,n=this.state.PopEvaluationStack(e.numberOfParameters),i=e.Call(n);return this.state.PushEvaluationStack(i),!0}return!1}ChoosePathString(t){let e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];if(this.IfAsyncWeCant("call ChoosePathString right now"),null!==this.onChoosePathString&&this.onChoosePathString(t,n),e)this.ResetCallstack();else if(this.state.callStack.currentElement.type==v.Function){let e="",n=this.state.callStack.currentElement.currentPointer.container;throw null!=n&&(e="("+n.path.toString()+") "),new Error("Story was running a function "+e+"when you called ChoosePathString("+t+") - this is almost certainly not not what you want! Full stack trace: \n"+this.state.callStack.callStackTrace)}this.state.PassArgumentsToEvaluationStack(n),this.ChoosePath(new m(t))}IfAsyncWeCant(t){if(this._asyncContinueActive)throw new Error("Can't "+t+". Story is in the middle of a ContinueAsync(). Make more ContinueAsync() calls or a single Continue() call beforehand.")}ChoosePath(t){let e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.state.SetChosenPath(t,e),this.VisitChangedContainersDueToDivert()}ChooseChoiceIndex(t){let e=this.currentChoices;this.Assert(t>=0&&t1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(null!==this.onEvaluateFunction&&this.onEvaluateFunction(t,e),this.IfAsyncWeCant("evaluate a function"),null==t)throw new Error("Function is null");if(""==t||""==t.trim())throw new Error("Function is empty or white space.");let i=this.KnotContainerWithName(t);if(null==i)throw new Error("Function doesn't exist: '"+t+"'");let r=[];r.push(...this.state.outputStream),this._state.ResetOutput(),this.state.StartFunctionEvaluationFromGame(i,e);let s=new b;for(;this.canContinue;)s.Append(this.Continue());let a=s.toString();this._state.ResetOutput(r);let o=this.state.CompleteFunctionEvaluationFromGame();return null!=this.onCompleteEvaluateFunction&&this.onCompleteEvaluateFunction(t,e,a,o),n?{returned:o,output:a}:o}EvaluateExpression(t){let e=this.state.callStack.elements.length;this.state.callStack.Push(v.Tunnel),this._temporaryEvaluationContainer=t,this.state.GoToStart();let n=this.state.evaluationStack.length;return this.Continue(),this._temporaryEvaluationContainer=null,this.state.callStack.elements.length>e&&this.state.PopCallStack(),this.state.evaluationStack.length>n?this.state.PopEvaluationStack():null}CallExternalFunction(t,e){if(null===t)return S("funcName");let n=this._externals.get(t),i=null,r=void 0!==n;if(r&&!n.lookAheadSafe&&null!==this._stateSnapshotAtLastNewline)return void(this._sawLookaheadUnsafeFunctionAfterNewline=!0);if(!r){if(this.allowExternalFunctionFallbacks)return i=this.KnotContainerWithName(t),this.Assert(null!==i,"Trying to call EXTERNAL function '"+t+"' which has not been bound, and fallback ink function could not be found."),this.state.callStack.Push(v.Function,void 0,this.state.outputStream.length),void(this.state.divertedPointer=H.StartOf(i));this.Assert(!1,"Trying to call EXTERNAL function '"+t+"' which has not been bound (and ink fallbacks disabled).")}let s=[];for(let t=0;t2&&void 0!==arguments[2])||arguments[2];this.IfAsyncWeCant("bind an external function"),this.Assert(!this._externals.has(t),"Function '"+t+"' has already been bound."),this._externals.set(t,{function:e,lookAheadSafe:n})}TryCoerce(t){return t}BindExternalFunction(t,e){let n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];this.Assert(null!=e,"Can't bind a null function"),this.BindExternalFunctionGeneral(t,(t=>{this.Assert(t.length>=e.length,"External function expected "+e.length+" arguments");let n=[];for(let e=0,i=t.length;e1?"s":"",t+=": '",t+=Array.from(n).join("', '"),t+="' ",t+=this.allowExternalFunctionFallbacks?", and no fallback ink function found.":" (ink fallbacks disabled)",this.Error(t)}else if(null!=t){for(let e of t.content){null!=e&&e.hasValidName||this.ValidateExternalBindings(e,n)}for(let[,e]of t.namedContent)this.ValidateExternalBindings(s(e,y),n)}else if(null!=e){let t=s(e,J);if(t&&t.isExternal){let e=t.targetPathString;if(null===e)return S("name");if(!this._externals.has(e))if(this.allowExternalFunctionFallbacks){this.mainContentContainer.namedContent.has(e)||n.add(e)}else n.add(e)}}}ObserveVariable(t,e){if(this.IfAsyncWeCant("observe a new variable"),null===this._variableObservers&&(this._variableObservers=new Map),!this.state.variablesState.GlobalVariableExistsWithName(t))throw new Error("Cannot observe variable '"+t+"' because it wasn't declared in the ink story.");this._variableObservers.has(t)?this._variableObservers.get(t).push(e):this._variableObservers.set(t,[e])}ObserveVariables(t,e){for(let n=0,i=t.length;n=e.container.content.length;){t=!1;let n=s(e.container.parent,L);if(n instanceof L==!1)break;let i=n.content.indexOf(e.container);if(-1==i)break;if(e=new H(n,i),e.index++,t=!0,null===e.container)return S("pointer.container")}return t||(e=H.Null),this.state.callStack.currentElement.currentPointer=e.copy(),t}TryFollowDefaultInvisibleChoice(){let t=this._state.currentChoices,e=t.filter((t=>t.isInvisibleDefault));if(0==e.length||t.length>e.length)return!1;let n=e[0];return null===n.targetPath?S("choice.targetPath"):null===n.threadAtGeneration?S("choice.threadAtGeneration"):(this.state.callStack.currentThread=n.threadAtGeneration,null!==this._stateSnapshotAtLastNewline&&(this.state.callStack.currentThread=this.state.callStack.ForkThread()),this.ChoosePath(n.targetPath,!1),!0)}NextSequenceShuffleIndex(){let t=s(this.state.PopEvaluationStack(),N);if(!(t instanceof N))return this.Error("expected number of elements in sequence for shuffle index"),0;let e=this.state.currentPointer.container;if(null===e)return S("seqContainer");if(null===t.value)return S("numElementsIntVal.value");let n=t.value,i=a(this.state.PopEvaluationStack(),N).value;if(null===i)return S("seqCount");let r=i/n,o=i%n,l=e.path.toString(),h=0;for(let t=0,e=l.length;t1&&void 0!==arguments[1]&&arguments[1],n=new _(t);throw n.useEndLineNumber=e,n}Warning(t){this.AddError(t,!0)}AddError(t){let e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=this.currentDebugMetadata,r=e?"WARNING":"ERROR";if(null!=i){let e=n?i.endLineNumber:i.startLineNumber;t="RUNTIME "+r+": '"+i.fileName+"' line "+e+": "+t}else t=this.state.currentPointer.isNull?"RUNTIME "+r+": "+t:"RUNTIME "+r+": ("+this.state.currentPointer+"): "+t;this.state.AddError(t,e),e||this.state.ForceEnd()}Assert(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(0==t)throw null==e&&(e="Story assert"),new Error(e+" "+this.currentDebugMetadata)}get currentDebugMetadata(){let t,e=this.state.currentPointer;if(!e.isNull&&null!==e.Resolve()&&(t=e.Resolve().debugMetadata,null!==t))return t;for(let n=this.state.callStack.elements.length-1;n>=0;--n)if(e=this.state.callStack.elements[n].currentPointer,!e.isNull&&null!==e.Resolve()&&(t=e.Resolve().debugMetadata,null!==t))return t;for(let e=this.state.outputStream.length-1;e>=0;--e){if(t=this.state.outputStream[e].debugMetadata,null!==t)return t}return null}get mainContentContainer(){return this._temporaryEvaluationContainer?this._temporaryEvaluationContainer:this._mainContentContainer}};re.inkVersionCurrent=21,function(t){var e;(e=t.OutputStateChange||(t.OutputStateChange={}))[e.NoChange=0]="NoChange",e[e.ExtendedBeyondNewline=1]="ExtendedBeyondNewline",e[e.NewlineRemoved=2]="NewlineRemoved"}(re||(re={}));class se extends dt{get flowLevel(){return at.Story}get hadError(){return this._hadError}get hadWarning(){return this._hadWarning}constructor(t){var e;super(null,t,null,!1,arguments.length>1&&void 0!==arguments[1]&&arguments[1]),e=this,this._errorHandler=null,this._hadError=!1,this._hadWarning=!1,this._dontFlattenContainers=new Set,this._listDefs=new Map,this.constants=new Map,this.externals=new Map,this.countAllVisits=!1,this.ExportRuntime=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;var n,i;e._errorHandler=t,e.constants=new Map;for(const t of e.FindAll(st)()){const n=e.constants.get(t.constantName);if(n&&!n.Equals(t.expression)){const i=`CONST '${t.constantName}' has been redefined with a different value. Multiple definitions of the same CONST are valid so long as they contain the same value. Initial definition was on ${n.debugMetadata}.`;e.Error(i,t,!1)}e.constants.set(t.constantName,t.expression)}e._listDefs=new Map;for(const t of e.FindAll(xt)())(null===(n=t.identifier)||void 0===n?void 0:n.name)&&e._listDefs.set(null===(i=t.identifier)||void 0===i?void 0:i.name,t);e.externals=new Map,e.ResolveWeavePointNaming();const r=e.runtimeObject,s=new L;s.AddContent(D.EvalStart());const a=[];for(const[t,n]of e.variableDeclarations)if(n.isGlobalDeclaration){if(n.listDefinition)e._listDefs.set(t,n.listDefinition),s.AddContent(n.listDefinition.runtimeObject),a.push(n.listDefinition.runtimeListDefinition);else{if(!n.expression)throw new Error;n.expression.GenerateIntoContainer(s)}const i=new X(t,!0);i.isGlobal=!0,s.AddContent(i)}s.AddContent(D.EvalEnd()),s.AddContent(D.End()),e.variableDeclarations.size>0&&(s.name="global decl",r.AddToNamedContentOnly(s)),r.AddContent(D.Done());const o=new re(r,a);return e.runtimeObject=o,e.hadError?null:(e.FlattenContainersIn(r),e.ResolveReferences(e),e.hadError?null:(o.ResetState(),o))},this.ResolveList=t=>{let e=this._listDefs.get(t);return e||null},this.ResolveListItem=function(t,n){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=null;if(t)return(r=e._listDefs.get(t))?r.ItemNamed(n):null;{let t=null,r=null;for(const[,s]of e._listDefs.entries()){const a=s.ItemNamed(n);a&&(t?e.Error(`Ambiguous item name '${n}' found in multiple sets, including ${r.identifier} and ${s.identifier}`,i,!1):(t=a,r=s))}return t}},this.FlattenContainersIn=t=>{const e=new Set;if(t.content)for(const n of t.content){const t=s(n,L);t&&e.add(t)}if(t.namedContent)for(const[,n]of t.namedContent){const t=s(n,L);t&&e.add(t)}for(const t of e)this.TryFlattenContainer(t),this.FlattenContainersIn(t)},this.TryFlattenContainer=t=>{if(t.namedContent&&t.namedContent.size>0||t.hasValidName||this._dontFlattenContainers.has(t))return;const e=s(t.parent,L);if(e){let n=e.content.indexOf(t);e.content.splice(n,1);const i=t.ownDebugMetadata;if(t.content)for(const r of t.content)r.parent=null,null!==i&&null===r.ownDebugMetadata&&(r.debugMetadata=i),e.InsertContent(r,n),n+=1}},this.Error=(t,e,n)=>{let r=n?i.Warning:i.Error,s="";if(e instanceof p?(s+="TODO: ",r=i.Author):s+=n?"WARNING: ":"ERROR: ",e&&null!==e.debugMetadata&&e.debugMetadata.startLineNumber>=1&&(null!=e.debugMetadata.fileName&&(s+=`'${e.debugMetadata.fileName}' `),s+=`line ${e.debugMetadata.startLineNumber}: `),s+=t,t=s,null===this._errorHandler)throw new Error(t);this._errorHandler(t,r),this._hadError=r===i.Error,this._hadWarning=r===i.Warning},this.ResetError=()=>{this._hadError=!1,this._hadWarning=!1},this.IsExternal=t=>this.externals.has(t),this.AddExternal=t=>{this.externals.has(t.name)?this.Error(`Duplicate EXTERNAL definition of '${t.name}'`,t,!1):t.name&&this.externals.set(t.name,t)},this.DontFlattenContainer=t=>{this._dontFlattenContainers.add(t)},this.NameConflictError=(t,e,n,i)=>{t.Error(`${i} '${e}': name has already been used for a ${n.typeName.toLowerCase()} on ${n.debugMetadata}`)},this.CheckForNamingCollisions=function(t,n,i){var r;const a=(arguments.length>3&&void 0!==arguments[3]?arguments[3]:"")||t.typeName;if(se.IsReservedKeyword(null==n?void 0:n.name))return void t.Error(`'${n}' cannot be used for the name of a ${a.toLowerCase()} because it's a reserved keyword`);if(gt.IsBuiltIn((null==n?void 0:n.name)||""))return void t.Error(`'${n}' cannot be used for the name of a ${a.toLowerCase()} because it's a built in function`);const o=s(e.ContentWithNameAtLevel((null==n?void 0:n.name)||"",at.Knot),dt);if(o&&(o!==t||i===z.Arg))return void e.NameConflictError(t,(null==n?void 0:n.name)||"",o,a);if(i{switch(t){case"true":case"false":case"not":case"return":case"else":case"VAR":case"CONST":case"temp":case"LIST":case"function":return!0}return!1};class ae extends V{get isSingleString(){if(1!==this.content.length)return!1;return this.content[0]instanceof rt}constructor(t){super(),this.GenerateIntoContainer=t=>{t.AddContent(D.BeginString());for(const e of this.content)t.AddContent(e.runtimeObject);t.AddContent(D.EndString())},this.toString=()=>{let t="";for(const e of this.content)t+=e;return t},this.AddContent(t)}get typeName(){return"String"}Equals(t){const e=s(t,ae);if(null===e)return!1;if(!this.isSingleString||!e.isSingleString)return!1;return this.toString()===e.toString()}}class oe extends d{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];super(),this.GenerateRuntimeObject=()=>this.isStart?D.BeginTag():D.EndTag(),this.toString=()=>this.isStart?"#StartTag":"#EndTag",this.isStart=t,this.inChoice=e}get typeName(){return"Tag"}}class le{constructor(t){this.rootPath=t,this.ResolveInkFilename=()=>{throw Error("Can't resolve filename because no FileHandler was provided when instantiating the parser / compiler.")},this.LoadInkFileContents=()=>{throw Error("Can't load ink content because no FileHandler was provided when instantiating the parser / compiler.")}}}class he extends et{get fileHandler(){if(!this._fileHandler)throw new Error("No FileHandler defined");return this._fileHandler}set fileHandler(t){this._fileHandler=t}constructor(e){var n;let a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,h=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;if(super(e),n=this,this.ParseStory=()=>{const e=this.StatementsAtLevel(t.StatementLevel.Top);return new se(e,this._rootParser!==this)},this.SeparatedList=(t,e)=>{const n=this.Parse(t);if(null===n)return null;const i=[];for(i.push(n);;){const n=this.BeginRule();if(null===e()){this.FailRule(n);break}const r=this.Parse(t);if(null===r){this.FailRule(n);break}this.SucceedRule(n),i.push(r)}return i},this.CreateDebugMetadata=(t,e)=>{const n=new It;return n.startLineNumber=((null==t?void 0:t.lineIndex)||0)+1,n.endLineNumber=e.lineIndex+1,n.startCharacterNumber=((null==t?void 0:t.characterInLineIndex)||0)+1,n.endCharacterNumber=e.characterInLineIndex+1,n.fileName=this._filename,n},this.RuleDidSucceed=(t,e,n)=>{const i=s(t,d);i&&(i.debugMetadata=this.CreateDebugMetadata(e,n));const r=Array.isArray(t)?t:null;if(null!==r)for(const t of r){s(t,d)&&(t.hasOwnDebugMetadata||(t.debugMetadata=this.CreateDebugMetadata(e,n)))}const a=s(t,ct);null!=a&&(a.debugMetadata=this.CreateDebugMetadata(e,n))},this.OnStringParserError=function(t,e){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,s=arguments.length>3&&void 0!==arguments[3]&&arguments[3];let a=s?"WARNING:":"ERROR:";if(null!==n._filename&&(a+=` '${n._filename}'`),a+=` line ${r+1}: ${t}`,null===n._externalErrorHandler)throw new Error(a);n._externalErrorHandler(a,s?i.Warning:i.Error)},this.AuthorWarning=()=>{this.Whitespace();const t=this.Parse(this.IdentifierWithMetadata);if(null===t||"TODO"!==t.name)return null;this.Whitespace(),this.ParseString(":"),this.Whitespace();const e=this.ParseUntilCharactersFromString("\n\r");return e?new p(e):null},this.ExtendIdentifierCharacterRanges=t=>{const e=he.ListAllCharacterRanges();for(const n of e)t.AddCharacters(n.ToCharacterSet())},this._parsingChoice=!1,this.Choice=()=>{let t=!0,e=this.Interleave(this.OptionalExclude(this.Whitespace),this.String("*"));if(!e){if(e=this.Interleave(this.OptionalExclude(this.Whitespace),this.String("+")),null===e)return null;t=!1}const n=this.Parse(this.BracketedName);this.Whitespace();const i=this.Parse(this.ChoiceCondition);if(this.Whitespace(),this._parsingChoice)throw new Error("Already parsing a choice - shouldn't have nested choices");this._parsingChoice=!0;let r=null;const a=this.Parse(this.MixedTextAndLogic);a&&(r=new pt(a));let o=null,l=null;const h=null!==this.ParseString("[");if(h){this.EndTagIfNecessary(r);const t=this.Parse(this.MixedTextAndLogic);null!==t&&(o=new pt(t)),this.Expect(this.String("]"),"closing ']' for weave-style option"),this.EndTagIfNecessary(o);let e=this.Parse(this.MixedTextAndLogic);null!==e&&(l=new pt(e))}this.Whitespace(),this.EndTagIfNecessary(null!=l?l:r);const u=this.Parse(this.MultiDivert);this._parsingChoice=!1,this.Whitespace();const c=!r&&!l&&!o;if(c&&null===u&&this.Warning("Choice is completely empty. Interpretting as a default fallback choice. Add a divert arrow to remove this warning: * ->"),r||!h||o||this.Warning("Blank choice - if you intended a default fallback choice, use the `* ->` syntax"),l||(l=new pt),this.EndTagIfNecessary(l),null!==u)for(const t of u){const e=s(t,St);e&&e.isEmpty||l.AddContent(t)}l.AddContent(new rt("\n"));const d=new Y(r,o,l);return n&&(d.identifier=n),d.indentationDepth=e.length,d.hasWeaveStyleInlineBrackets=h,d.condition=i,d.onceOnly=t,d.isInvisibleDefault=c,d},this.ChoiceCondition=()=>{const t=this.Interleave(this.ChoiceSingleCondition,this.ChoiceConditionsSpace);return null===t?null:1===t.length?t[0]:new vt(t)},this.ChoiceConditionsSpace=()=>(this.Newline(),this.Whitespace(),tt),this.ChoiceSingleCondition=()=>{if(null===this.ParseString("{"))return null;const t=this.Expect(this.Expression,"choice condition inside { }");return this.DisallowIncrement(t),this.Expect(this.String("}"),"closing '}' for choice condition"),t},this.Gather=()=>{const t=this.Parse(this.GatherDashes);if(null===t)return null;const e=Number(t),n=this.Parse(this.BracketedName),i=new ot(n,e);return this.Newline(),i},this.GatherDashes=()=>{this.Whitespace();let t=0;for(;null!==this.ParseDashNotArrow();)t+=1,this.Whitespace();return 0===t?null:t},this.ParseDashNotArrow=()=>{const t=this.BeginRule();return null===this.ParseString("->")&&"-"===this.ParseSingleCharacter()?this.SucceedRule(t):this.FailRule(t)},this.BracketedName=()=>{if(null===this.ParseString("("))return null;this.Whitespace();const t=this.Parse(this.IdentifierWithMetadata);return null===t?null:(this.Whitespace(),this.Expect(this.String(")"),"closing ')' for bracketed name"),t)},this.InnerConditionalContent=e=>{if(void 0===e){const t=this.Parse(this.ConditionExpression),e=this.Parse((()=>this.InnerConditionalContent(t)));return null===e?null:e}let n;const i=null!==e,r=null===this.Parse(this.Newline);if(r&&!i)return null;if(r)n=this.InlineConditionalBranches();else{if(n=this.MultilineConditionalBranches(),null===n){if(e){let e=this.StatementsAtLevel(t.StatementLevel.InnerBlock);if(null!==e){n=[new Nt(e)];const t=this.Parse(this.SingleMultilineCondition);t&&(t.isElse||(this.ErrorWithParsedObject("Expected an '- else:' clause here rather than an extra condition",t),t.isElse=!0),n.push(t))}}if(null===n)return null}else if(1===n.length&&n[0].isElse&&e){const t=new Nt(null);t.isTrueBranch=!0,n.unshift(t)}if(e){let t=!1;for(let e=0;e2?this.ErrorWithParsedObject("Only final branch can be an 'else'. Did you miss a ':'?",i):0===e?i.isTrueBranch=!0:i.isElse=!0}}else{for(let t=0;t{const t=this.Interleave(this.MixedTextAndLogic,this.Exclude(this.String("|")),null,!1);if(null===t||0===t.length)return null;const e=[];if(t.length>2)this.Error("Expected one or two alternatives separated by '|' in inline conditional");else{const n=new Nt(t[0]);if(n.isTrueBranch=!0,e.push(n),t.length>1){const n=new Nt(t[1]);n.isElse=!0,e.push(n)}}return e},this.MultilineConditionalBranches=()=>{this.MultilineWhitespace();const t=this.OneOrMore(this.SingleMultilineCondition);return null===t?null:(this.MultilineWhitespace(),t)},this.SingleMultilineCondition=()=>{if(this.Whitespace(),null!==this.ParseString("->")||null===this.ParseString("-"))return null;this.Whitespace();let e=null;const n=null!==this.Parse(this.ElseExpression);n||(e=this.Parse(this.ConditionExpression));let i=this.StatementsAtLevel(t.StatementLevel.InnerBlock);null===e&&null===i&&(this.Error("expected content for the conditional branch following '-'"),i=[new rt("")]),this.MultilineWhitespace();const r=new Nt(i);return r.ownExpression=e,r.isElse=n,r},this.ConditionExpression=()=>{const t=this.Parse(this.Expression);return null===t?null:(this.DisallowIncrement(t),this.Whitespace(),null===this.ParseString(":")?null:t)},this.ElseExpression=()=>null===this.ParseString("else")?null:(this.Whitespace(),null===this.ParseString(":")?null:tt),this._nonTextPauseCharacters=null,this._nonTextEndCharacters=null,this._notTextEndCharactersChoice=null,this._notTextEndCharactersString=null,this.TrimEndWhitespace=(t,e)=>{if(t.length>0){const n=t.length-1,i=t[n];if(i instanceof rt){const r=i;r.text=r.text.replace(new RegExp(/[ \t]+$/g),""),e?r.text+=" ":0===r.text.length&&(t.splice(n,1),this.TrimEndWhitespace(t,!1))}}},this.LineOfMixedTextAndLogic=()=>{this.Parse(this.Whitespace);let t=this.Parse(this.MixedTextAndLogic);if(!t||!t.length)return null;const e=t[0];if(e&&e.text&&e.text.startsWith("return")&&this.Warning("Do you need a '~' before 'return'? If not, perhaps use a glue: <> (since it's lowercase) or rewrite somehow?"),0===t.length)return null;return t[t.length-1]instanceof St||this.TrimEndWhitespace(t,!1),this.EndTagIfNecessary(t),t.length>0&&t[0]instanceof oe&&t[0].isStart||t.push(new rt("\n")),this.Expect(this.EndOfLine,"end of line",this.SkipToNextLine),t},this.MixedTextAndLogic=()=>{null!==this.ParseObject(this.Spaced(this.String("~")))&&this.Error("You shouldn't use a '~' here - tildas are for logic that's on its own line. To do inline logic, use { curly braces } instead");let t=this.Interleave(this.Optional(this.ContentText),this.Optional(this.InlineLogicOrGlueOrStartTag));if(!this._parsingChoice){const e=this.Parse(this.MultiDivert);null!==e&&(null===t&&(t=[]),this.EndTagIfNecessary(t),this.TrimEndWhitespace(t,!0),t.push(...e))}return t||null},this.ContentText=()=>this.ContentTextAllowingEscapeChar(),this.ContentTextAllowingEscapeChar=()=>{let t=null;for(;;){let e=this.Parse(this.ContentTextNoEscape);const n=null!==this.ParseString("\\");if(!n&&null===e)break;if(null===t&&(t=""),null!==e&&(t+=String(e)),n){t+=this.ParseSingleCharacter()}}return null!==t?new rt(t):null},this.ContentTextNoEscape=()=>{null===this._nonTextPauseCharacters&&(this._nonTextPauseCharacters=new q("-<")),null===this._nonTextEndCharacters&&(this._nonTextEndCharacters=new q("{}|\n\r\\#"),this._notTextEndCharactersChoice=new q(this._nonTextEndCharacters),this._notTextEndCharactersChoice.AddCharacters("[]"),this._notTextEndCharactersString=new q(this._nonTextEndCharacters),this._notTextEndCharactersString.AddCharacters('"'));let t=null;t=this.parsingStringExpression?this._notTextEndCharactersString:this._parsingChoice?this._notTextEndCharactersChoice:this._nonTextEndCharacters;const e=this.ParseUntil((()=>this.OneOf([this.ParseDivertArrow,this.ParseThreadArrow,this.EndOfLine,this.Glue])),this._nonTextPauseCharacters,t);return null!==e?e:null},this.MultiDivert=()=>{this.Whitespace();let t=[];const e=this.Parse(this.StartThread);if(e)return t=[e],t;const n=this.Interleave(this.ParseDivertArrowOrTunnelOnwards,this.DivertIdentifierWithArguments);if(!n)return null;t=[],this.EndTagIfNecessary(t);for(let e=0;e->"===n[e]){0===e||e===n.length-1||e===n.length-2||this.Error("Tunnel onwards '->->' must only come at the begining or the start of a divert");const i=new _t;if(e) are only valid on choices")}return t},this.StartThread=()=>{if(this.Whitespace(),null===this.ParseThreadArrow())return null;this.Whitespace();const t=this.Expect(this.DivertIdentifierWithArguments,"target for new thread",(()=>new St(null)));return t.isThread=!0,t},this.DivertIdentifierWithArguments=()=>{this.Whitespace();const t=this.Parse(this.DotSeparatedDivertPathComponents);if(!t)return null;this.Whitespace();const e=this.Parse(this.ExpressionFunctionCallArguments);this.Whitespace();const n=new lt(t);return new St(n,e)},this.SingleDivert=()=>{const t=this.Parse(this.MultiDivert);if(!t)return null;if(1!==t.length)return null;if(t[0]instanceof _t)return null;const e=t[0];return e.isTunnel?null:e},this.DotSeparatedDivertPathComponents=()=>this.Interleave(this.Spaced(this.IdentifierWithMetadata),this.Exclude(this.String("."))),this.ParseDivertArrowOrTunnelOnwards=()=>{let t=0;for(;null!==this.ParseString("->");)t+=1;return 0===t?null:1===t?"->":(2===t||this.Error("Unexpected number of arrows in divert. Should only have '->' or '->->'"),"->->")},this.ParseDivertArrow=()=>this.ParseString("->"),this.ParseThreadArrow=()=>this.ParseString("<-"),this._binaryOperators=[],this._maxBinaryOpLength=0,this.TempDeclarationOrAssignment=()=>{this.Whitespace();const t=this.ParseTempKeyword();this.Whitespace();let e=null;if(e=t?this.Expect(this.IdentifierWithMetadata,"variable name"):this.Parse(this.IdentifierWithMetadata),null===e)return null;this.Whitespace();const n=null!==this.ParseString("+"),i=null!==this.ParseString("-");if(n&&i&&this.Error("Unexpected sequence '+-'"),null===this.ParseString("="))return t&&this.Error("Expected '='"),null;const r=this.Expect(this.Expression,"value expression to be assigned");if(n||i){return new Dt(e,r,n)}return new At({variableIdentifier:e,assignedExpression:r,isTemporaryNewDeclaration:t})},this.DisallowIncrement=t=>{t instanceof Dt&&this.Error("Can't use increment/decrement here. It can only be used on a ~ line")},this.ParseTempKeyword=()=>{const t=this.BeginRule();return"temp"===this.Parse(this.Identifier)?(this.SucceedRule(t),!0):(this.FailRule(t),!1)},this.ReturnStatement=()=>{this.Whitespace();if("return"!==this.Parse(this.Identifier))return null;this.Whitespace();const t=this.Parse(this.Expression);return new ht(t)},this.Expression=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;n.Whitespace();let e=n.ExpressionUnary();if(null===e)return null;for(n.Whitespace();;){const i=n.BeginRule(),r=n.ParseInfixOperator();if(!(null!==r&&r.precedence>t)){n.FailRule(i);break}{const t=`right side of '${r.type}' expression`,s=n.Expect((()=>n.ExpressionInfixRight(e,r)),t);if(null===s)return n.FailRule(i),null;e=n.SucceedRule(i,s)}}return n.Whitespace(),e},this.ExpressionUnary=()=>{const t=this.Parse(this.ExpressionDivertTarget);if(null!==t)return t;let e=this.OneOf([this.String("-"),this.String("!")]);null===e&&(e=this.Parse(this.ExpressionNot)),this.Whitespace();let n=this.OneOf([this.ExpressionList,this.ExpressionParen,this.ExpressionFunctionCall,this.ExpressionVariableName,this.ExpressionLiteral]);if(null===n&&null!==e&&(n=this.ExpressionUnary()),null===n)return null;null!==e&&(n=G.WithInner(n,e)),this.Whitespace();const i=this.OneOf([this.String("++"),this.String("--")]);if(null!==i){const t="++"===i;if(n instanceof ft){n=new Dt(n.identifier,t)}else this.Error(`can only increment and decrement variables, but saw '${n}'.`)}return n},this.ExpressionNot=()=>{const t=this.Identifier();return"not"===t?t:null},this.ExpressionLiteral=()=>this.OneOf([this.ExpressionFloat,this.ExpressionInt,this.ExpressionBool,this.ExpressionString]),this.ExpressionDivertTarget=()=>{this.Whitespace();const t=this.Parse(this.SingleDivert);return!t||t&&t.isThread?null:(this.Whitespace(),new Ct(t))},this.ExpressionInt=()=>{const t=this.ParseInt();return null===t?null:new M(t,"int")},this.ExpressionFloat=()=>{const t=this.ParseFloat();return null===t?null:new M(t,"float")},this.ExpressionString=()=>{if(null===this.ParseString('"'))return null;this.parsingStringExpression=!0;let t=this.Parse(this.MixedTextAndLogic);return this.Expect(this.String('"'),"close quote for string expression"),this.parsingStringExpression=!1,null===t?t=[new rt("")]:t.find((t=>t instanceof St))&&this.Error("String expressions cannot contain diverts (->)"),new ae(t)},this.ExpressionBool=()=>{const t=this.Parse(this.Identifier);return"true"===t?new M(!0,"bool"):"false"===t?new M(!1,"bool"):null},this.ExpressionFunctionCall=()=>{const t=this.Parse(this.IdentifierWithMetadata);if(null===t)return null;this.Whitespace();const e=this.Parse(this.ExpressionFunctionCallArguments);return null===e?null:new gt(t,e)},this.ExpressionFunctionCallArguments=()=>{if(null===this.ParseString("("))return null;const t=this.Exclude(this.String(","));let e=this.Interleave(this.Expression,t);return null===e&&(e=[]),this.Whitespace(),this.Expect(this.String(")"),"closing ')' for function call"),e},this.ExpressionVariableName=()=>{const t=this.Interleave(this.IdentifierWithMetadata,this.Exclude(this.Spaced(this.String("."))));return null===t||se.IsReservedKeyword(t[0].name)?null:new ft(t)},this.ExpressionParen=()=>{if(null===this.ParseString("("))return null;const t=this.Parse(this.Expression);return null===t?null:(this.Whitespace(),this.Expect(this.String(")"),"closing parenthesis ')' for expression"),t)},this.ExpressionInfixRight=(t,e)=>{if(!t)return null;this.Whitespace();const n=this.Parse((()=>this.Expression(e.precedence)));if(n){return new $(t,n,e.type)}return null},this.ParseInfixOperator=()=>{for(const t of this._binaryOperators){const e=this.BeginRule();if(null!==this.ParseString(t.type)){if(t.requireWhitespace&&null===this.Whitespace()){this.FailRule(e);continue}return this.SucceedRule(e,t)}this.FailRule(e)}return null},this.ExpressionList=()=>{if(this.Whitespace(),null===this.ParseString("("))return null;this.Whitespace();const t=this.SeparatedList(this.ListMember,this.Spaced(this.String(",")));return this.Whitespace(),null===this.ParseString(")")?null:new Mt(t)},this.ListMember=()=>{this.Whitespace();let t=this.Parse(this.IdentifierWithMetadata);if(null===t)return null;if(null!==this.ParseString(".")){const e=this.Expect(this.IdentifierWithMetadata,`element name within the set ${t}`);t.name+=`.${null==e?void 0:e.name}`}return this.Whitespace(),t},this.RegisterExpressionOperators=()=>{this.RegisterBinaryOperator("&&",1),this.RegisterBinaryOperator("||",1),this.RegisterBinaryOperator("and",1,!0),this.RegisterBinaryOperator("or",1,!0),this.RegisterBinaryOperator("==",2),this.RegisterBinaryOperator(">=",2),this.RegisterBinaryOperator("<=",2),this.RegisterBinaryOperator("<",2),this.RegisterBinaryOperator(">",2),this.RegisterBinaryOperator("!=",2),this.RegisterBinaryOperator("?",3),this.RegisterBinaryOperator("has",3,!0),this.RegisterBinaryOperator("!?",3),this.RegisterBinaryOperator("hasnt",3,!0),this.RegisterBinaryOperator("^",3),this.RegisterBinaryOperator("+",4),this.RegisterBinaryOperator("-",5),this.RegisterBinaryOperator("*",6),this.RegisterBinaryOperator("/",7),this.RegisterBinaryOperator("%",8),this.RegisterBinaryOperator("mod",8,!0)},this.RegisterBinaryOperator=function(t,e){const i=new jt(t,e,arguments.length>2&&void 0!==arguments[2]&&arguments[2]);n._binaryOperators.push(i),n._maxBinaryOpLength=Math.max(n._maxBinaryOpLength,t.length)},this._openFilenames=[],this.IncludeStatement=()=>{if(this.Whitespace(),null===this.ParseString("INCLUDE"))return null;this.Whitespace();let t=this.Expect((()=>this.ParseUntilCharactersFromString("\n\r")),"filename for include statement");t=t.replace(new RegExp(/[ \t]+$/g),"");const e=this.fileHandler.ResolveInkFilename(t);if(this.FilenameIsAlreadyOpen(e))return this.Error(`Recursive INCLUDE detected: '${e}' is already open.`),this.ParseUntilCharactersFromString("\r\n"),new Vt(null);this.AddOpenFilename(e);let n=null,i="";try{i=this._rootParser.fileHandler.LoadInkFileContents(e)}catch(e){this.Error(`Failed to load: '${t}'.\nError:${e}`)}if(null!=i){n=new he(i,t,this._externalErrorHandler,this._rootParser,this.fileHandler).ParseStory()}return this.RemoveOpenFilename(e),new Vt(n)},this.FilenameIsAlreadyOpen=t=>this._rootParser._openFilenames.includes(t),this.AddOpenFilename=t=>{this._rootParser._openFilenames.push(t)},this.RemoveOpenFilename=t=>{this._rootParser._openFilenames.splice(this._rootParser._openFilenames.indexOf(t),1)},this.KnotDefinition=()=>{const e=this.Parse(this.KnotDeclaration);if(null===e)return null;this.Expect(this.EndOfLine,"end of line after knot name definition",this.SkipToNextLine);const n=this.Expect((()=>this.StatementsAtLevel(t.StatementLevel.Knot)),"at least one line within the knot",this.KnotStitchNoContentRecoveryRule);return new Bt(e.name,n,e.args,e.isFunction)},this.KnotDeclaration=()=>{if(this.Whitespace(),null===this.KnotTitleEquals())return null;this.Whitespace();const t=this.Parse(this.IdentifierWithMetadata);let e;const n="function"===(null==t?void 0:t.name);n?(this.Expect(this.Whitespace,"whitespace after the 'function' keyword"),e=this.Parse(this.IdentifierWithMetadata)):e=t,null===e&&(this.Error("Expected the name of the "+(n?"function":"knot")),e=new ct("")),this.Whitespace();const i=this.Parse(this.BracketedKnotDeclArguments);return this.Whitespace(),this.Parse(this.KnotTitleEquals),new Wt(e,i,n)},this.KnotTitleEquals=()=>{const t=this.ParseCharactersFromString("=");return null===t||t.length<=1?null:t},this.StitchDefinition=()=>{const e=this.Parse(this.StitchDeclaration);if(null===e)return null;this.Expect(this.EndOfLine,"end of line after stitch name",this.SkipToNextLine);const n=this.Expect((()=>this.StatementsAtLevel(t.StatementLevel.Stitch)),"at least one line within the stitch",this.KnotStitchNoContentRecoveryRule);return new qt(e.name,n,e.args,e.isFunction)},this.StitchDeclaration=()=>{if(this.Whitespace(),null===this.ParseString("="))return null;if(null!==this.ParseString("="))return null;this.Whitespace();const t=null!==this.ParseString("function");t&&this.Whitespace();const e=this.Parse(this.IdentifierWithMetadata);if(null===e)return null;this.Whitespace();const n=this.Parse(this.BracketedKnotDeclArguments);return this.Whitespace(),new Wt(e,n,t)},this.KnotStitchNoContentRecoveryRule=()=>{this.ParseUntil(this.KnotDeclaration,new q("="),null);return[new rt("")]},this.BracketedKnotDeclArguments=()=>{if(null===this.ParseString("("))return null;let t=this.Interleave(this.Spaced(this.FlowDeclArgument),this.Exclude(this.String(",")));return this.Expect(this.String(")"),"closing ')' for parameter list"),null===t&&(t=[]),t},this.FlowDeclArgument=()=>{const t=this.Parse(this.IdentifierWithMetadata);this.Whitespace();const e=this.ParseDivertArrow();this.Whitespace();const n=this.Parse(this.IdentifierWithMetadata);if(null==t&&null===n)return null;const i=new r;return null!==e&&(i.isDivertTarget=!0),null!==t&&"ref"===t.name?(null===n&&this.Error("Expected an parameter name after 'ref'"),i.identifier=n,i.isByReference=!0):(i.isDivertTarget?i.identifier=n:i.identifier=t,null===i.identifier&&this.Error("Expected an parameter name"),i.isByReference=!1),i},this.ExternalDeclaration=()=>{this.Whitespace();const t=this.Parse(this.IdentifierWithMetadata);if(null===t||"EXTERNAL"!=t.name)return null;this.Whitespace();const e=this.Expect(this.IdentifierWithMetadata,"name of external function")||new ct("");this.Whitespace();let n=this.Expect(this.BracketedKnotDeclArguments,`declaration of arguments for EXTERNAL, even if empty, i.e. 'EXTERNAL ${e}()'`);null===n&&(n=[]);const i=n.map((t=>{var e;return null===(e=t.identifier)||void 0===e?void 0:e.name})).filter(c);return new Ft(e,i)},this._identifierCharSet=null,this.LogicLine=()=>{if(this.Whitespace(),null===this.ParseString("~"))return null;this.Whitespace();let t=this.Expect((()=>this.OneOf([this.ReturnStatement,this.TempDeclarationOrAssignment,this.Expression])),"expression after '~'",this.SkipToNextLine);if(null===t)return new pt;t instanceof V&&!(t instanceof gt||t instanceof Dt)&&this.Error("Logic following a '~' can't be that type of expression. It can only be something like:\n\t~ return\n\t~ var x = blah\n\t~ x++\n\t~ myFunction()");const e=s(t,gt);return e&&(e.shouldPopReturnedValue=!0),null!==t.Find(gt)()&&(t=new pt(t,new rt("\n"))),this.Expect(this.EndOfLine,"end of line",this.SkipToNextLine),t},this.VariableDeclaration=()=>{this.Whitespace();if("VAR"!==this.Parse(this.Identifier))return null;this.Whitespace();const t=this.Expect(this.IdentifierWithMetadata,"variable name");this.Whitespace(),this.Expect(this.String("="),"the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)"),this.Whitespace();const e=this.Expect(this.Expression,"initial value for ");if(e){if(e instanceof M||e instanceof ae||e instanceof Ct||e instanceof ft||e instanceof Mt||this.Error("initial value for a variable must be a number, constant, list or divert target"),null!==this.Parse(this.ListElementDefinitionSeparator))this.Error("Unexpected ','. If you're trying to declare a new list, use the LIST keyword, not VAR");else if(e instanceof ae){e.isSingleString||this.Error("Constant strings cannot contain any logic.")}return new At({assignedExpression:e,isGlobalDeclaration:!0,variableIdentifier:t})}return null},this.ListDeclaration=()=>{this.Whitespace();if("LIST"!=this.Parse(this.Identifier))return null;this.Whitespace();const t=this.Expect(this.IdentifierWithMetadata,"list name");this.Whitespace(),this.Expect(this.String("="),"the '=' for an assignment of the list definition"),this.Whitespace();const e=this.Expect(this.ListDefinition,"list item names");return e?(e.identifier=new ct(t.name),new At({variableIdentifier:t,listDef:e})):null},this.ListDefinition=()=>{this.AnyWhitespace();const t=this.SeparatedList(this.ListElementDefinition,this.ListElementDefinitionSeparator);return null===t?null:new xt(t)},this.ListElementDefinitionSeparator=()=>(this.AnyWhitespace(),null===this.ParseString(",")?null:(this.AnyWhitespace(),",")),this.ListElementDefinition=()=>{const t=null!==this.ParseString("(");let e=t;this.Whitespace();const n=this.Parse(this.IdentifierWithMetadata);if(null===n)return null;this.Whitespace(),t&&null!=this.ParseString(")")&&(e=!1,this.Whitespace());let i=null;if(null!==this.ParseString("=")){this.Whitespace();const t=this.Expect(this.ExpressionInt,"value to be assigned to list item");null!==t&&(i=t.value),e&&(this.Whitespace(),null!==this.ParseString(")")&&(e=!1))}return e&&this.Error("Expected closing ')'"),new Gt(n,t,i)},this.ConstDeclaration=()=>{this.Whitespace();if("CONST"!==this.Parse(this.Identifier))return null;this.Whitespace();const t=this.Expect(this.IdentifierWithMetadata,"constant name");this.Whitespace(),this.Expect(this.String("="),"the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)"),this.Whitespace();const e=this.Expect(this.Expression,"initial value for ");if(e instanceof M||e instanceof Ct||e instanceof ae){if(e instanceof ae){e.isSingleString||this.Error("Constant strings cannot contain any logic.")}}else this.Error("initial value for a constant must be a number or divert target");return new st(t,e)},this.InlineLogicOrGlueOrStartTag=()=>this.OneOf([this.InlineLogic,this.Glue,this.StartTag]),this.Glue=()=>null!==this.ParseString("<>")?new kt(new Lt):null,this.InlineLogic=()=>{if(null===this.ParseString("{"))return null;let t=this.parsingStringExpression,e=this.tagActive;this.Whitespace();const n=this.Expect(this.InnerLogic,"some kind of logic, conditional or sequence within braces: { ... }");if(null===n)return this.parsingStringExpression=t,null;this.DisallowIncrement(n);let i=s(n,pt);return i||(i=new pt(n)),this.Whitespace(),this.Expect(this.String("}"),"closing brace '}' for inline logic"),this.parsingStringExpression=t,e||this.EndTagIfNecessary(i),i},this.InnerLogic=()=>{this.Whitespace();const t=this.ParseObject(this.SequenceTypeAnnotation);if(null!==t){const e=this.Expect(this.InnerSequenceObjects,"sequence elements (for cycle/stoping etc)");return null===e?null:new Et(e,t)}const e=this.Parse(this.ConditionExpression);if(e){return this.Expect((()=>this.InnerConditionalContent(e)),"conditional content following query")}const n=[this.InnerConditionalContent,this.InnerSequence,this.InnerExpression];for(const t of n){const e=this.BeginRule(),n=this.ParseObject(t);if(n){if(null!==this.Peek(this.Spaced(this.String("}"))))return this.SucceedRule(e,n);this.FailRule(e)}else this.FailRule(e)}return null},this.InnerExpression=()=>{const t=this.Parse(this.Expression);return t&&(t.outputWhenComplete=!0),t},this.IdentifierWithMetadata=()=>{const t=this.Identifier();return null===t?null:new ct(t)},this.Identifier=()=>{const t=this.ParseCharactersFromCharSet(this.identifierCharSet);if(null===t)return null;let e=!0;for(let n of t)if(!(n>="0"&&n<="9")){e=!1;break}return e?null:t},this._sequenceTypeSymbols=new q("!&~$"),this.InnerSequence=()=>{this.Whitespace();let t=wt.Stopping;const e=this.Parse(this.SequenceTypeAnnotation);null!==e&&(t=e);const n=this.Parse(this.InnerSequenceObjects);return null===n||n.length<=1?null:new Et(n,t)},this.SequenceTypeAnnotation=()=>{let t=this.Parse(this.SequenceTypeSymbolAnnotation);if(null===t&&(t=this.Parse(this.SequenceTypeWordAnnotation)),null===t)return null;switch(t){case wt.Once:case wt.Cycle:case wt.Stopping:case wt.Shuffle:case wt.Shuffle|wt.Stopping:case wt.Shuffle|wt.Once:break;default:return this.Error(`Sequence type combination not supported: ${t}`),wt.Stopping}return t},this.SequenceTypeSymbolAnnotation=()=>{null===this._sequenceTypeSymbols&&(this._sequenceTypeSymbols=new q("!&~$ "));let t=0;const e=this.ParseCharactersFromCharSet(this._sequenceTypeSymbols);if(null===e)return null;for(const n of e)switch(n){case"!":t|=wt.Once;break;case"&":t|=wt.Cycle;break;case"~":t|=wt.Shuffle;break;case"$":t|=wt.Stopping}return 0===t?null:t},this.SequenceTypeWordAnnotation=()=>{const t=this.Interleave(this.SequenceTypeSingleWord,this.Exclude(this.Whitespace));if(null===t||0===t.length)return null;if(null===this.ParseString(":"))return null;let e=0;for(const n of t)e|=n;return e},this.SequenceTypeSingleWord=()=>{let t=null;const e=this.Parse(this.IdentifierWithMetadata);if(null!==e)switch(e.name){case"once":t=wt.Once;break;case"cycle":t=wt.Cycle;break;case"shuffle":t=wt.Shuffle;break;case"stopping":t=wt.Stopping}return null===t?null:t},this.InnerSequenceObjects=()=>{let t=null;return t=null!==this.Parse(this.Newline)?this.Parse(this.InnerMultilineSequenceObjects):this.Parse(this.InnerInlineSequenceObjects),t},this.InnerInlineSequenceObjects=()=>{const t=this.Interleave(this.Optional(this.MixedTextAndLogic),this.String("|"),null,!1);if(null===t)return null;const e=[];let n=!1;for(const i of t)if("|"===i)n||e.push(new pt),n=!1;else{const t=i;null===t?this.Error(`Expected content, but got ${i} (this is an ink compiler bug!)`):e.push(new pt(t)),n=!0}return n||e.push(new pt),e},this.InnerMultilineSequenceObjects=()=>{this.MultilineWhitespace();const t=this.OneOrMore(this.SingleMultilineSequenceElement);return null===t?null:t},this.SingleMultilineSequenceElement=()=>{if(this.Whitespace(),null!==this.ParseString("->"))return null;if(null===this.ParseString("-"))return null;this.Whitespace();const e=this.StatementsAtLevel(t.StatementLevel.InnerBlock);return null===e?this.MultilineWhitespace():e.unshift(new rt("\n")),new pt(e)},this._statementRulesAtLevel=[],this._statementBreakRulesAtLevel=[],this.StatementsAtLevel=e=>{if(e===t.StatementLevel.InnerBlock){null!==this.Parse(this.GatherDashes)&&this.Error("You can't use a gather (the dashes) within the { curly braces } context. For multi-line sequences and conditions, you should only use one dash.")}return this.Interleave(this.Optional(this.MultilineWhitespace),(()=>this.StatementAtLevel(e)),(()=>this.StatementsBreakForLevel(e)))},this.StatementAtLevel=e=>{const n=this._statementRulesAtLevel[e],i=this.OneOf(n);return e===t.StatementLevel.Top&&i instanceof ht&&this.Error("should not have return statement outside of a knot"),i},this.StatementsBreakForLevel=t=>{this.Whitespace();const e=this._statementBreakRulesAtLevel[t],n=this.OneOf(e);return null===n?null:n},this.GenerateStatementLevelRules=()=>{const e=Object.values(t.StatementLevel);this._statementRulesAtLevel="f".repeat(e.length).split("f").map((()=>[])),this._statementBreakRulesAtLevel="f".repeat(e.length).split("f").map((()=>[]));for(const n of e){const e=[],i=[];e.push(this.Line(this.MultiDivert)),n>=t.StatementLevel.Top&&e.push(this.KnotDefinition),e.push(this.Line(this.Choice)),e.push(this.Line(this.AuthorWarning)),n>t.StatementLevel.InnerBlock&&e.push(this.Gather),n>=t.StatementLevel.Knot&&e.push(this.StitchDefinition),e.push(this.Line(this.ListDeclaration)),e.push(this.Line(this.VariableDeclaration)),e.push(this.Line(this.ConstDeclaration)),e.push(this.Line(this.ExternalDeclaration)),e.push(this.Line(this.IncludeStatement)),e.push(this.LogicLine),e.push(this.LineOfMixedTextAndLogic),n<=t.StatementLevel.Knot&&i.push(this.KnotDeclaration),n<=t.StatementLevel.Stitch&&i.push(this.StitchDeclaration),n<=t.StatementLevel.InnerBlock&&(i.push(this.ParseDashNotArrow),i.push(this.String("}"))),this._statementRulesAtLevel[n]=e,this._statementBreakRulesAtLevel[n]=i}},this.SkipToNextLine=()=>(this.ParseUntilCharactersFromString("\n\r"),this.ParseNewline(),tt),this.Line=t=>()=>{const e=this.ParseObject(t);return null===e?null:(this.Expect(this.EndOfLine,"end of line",this.SkipToNextLine),e)},this.StartTag=()=>{if(this.Whitespace(),null===this.ParseString("#"))return null;this.parsingStringExpression&&this.Error("Tags aren't allowed inside of strings. Please use \\# if you want a hash symbol.");let t=null;if(this.tagActive){let e=new pt;e.AddContent(new oe(!1)),e.AddContent(new oe(!0)),t=e}else t=new oe(!0);return this.tagActive=!0,this.Whitespace(),t},this._inlineWhitespaceChars=new q(" \t"),this.EndOfLine=()=>this.OneOf([this.Newline,this.EndOfFile]),this.Newline=()=>{this.Whitespace();return null!==this.ParseNewline()?tt:null},this.EndOfFile=()=>(this.Whitespace(),this.endOfInput?tt:null),this.MultilineWhitespace=()=>{let t=this.OneOrMore(this.Newline);if(null===t)return null;return t.length>=1?tt:null},this.Whitespace=()=>null!==this.ParseCharactersFromCharSet(this._inlineWhitespaceChars)?tt:null,this.Spaced=t=>()=>{this.Whitespace();const e=this.ParseObject(t);return null===e?null:(this.Whitespace(),e)},this.AnyWhitespace=()=>{let t=!1;for(;null!==this.OneOf([this.Whitespace,this.MultilineWhitespace]);)t=!0;return t?tt:null},this.MultiSpaced=t=>()=>{this.AnyWhitespace();const e=this.ParseObject(t);return null===e?null:(this.AnyWhitespace(),e)},this._filename=null,this._externalErrorHandler=null,this._fileHandler=null,this._filename=a,this.RegisterExpressionOperators(),this.GenerateStatementLevelRules(),this.errorHandler=this.OnStringParserError,this._externalErrorHandler=o,this._fileHandler=null===h?new le:h,null===l){if(this._rootParser=this,this._openFilenames=[],null!==this._filename){const t=this.fileHandler.ResolveInkFilename(this._filename);this._openFilenames.push(t)}}else this._rootParser=l}PreProcessInputString(t){return new nt(t).Process()}get parsingStringExpression(){return this.GetFlag(Number(Ot.ParsingString))}set parsingStringExpression(t){this.SetFlag(Number(Ot.ParsingString),t)}get tagActive(){return this.GetFlag(Number(Ot.TagActive))}set tagActive(t){this.SetFlag(Number(Ot.TagActive),t)}get identifierCharSet(){return null===this._identifierCharSet&&((this._identifierCharSet=new q).AddRange("A","Z").AddRange("a","z").AddRange("0","9").Add("_"),this.ExtendIdentifierCharacterRanges(this._identifierCharSet)),this._identifierCharSet}EndTagIfNecessary(t){this.tagActive&&(null!=t&&(t instanceof pt?t.AddContent(new oe(!1)):t.push(new oe(!1))),this.tagActive=!1)}}he.LatinBasic=U.Define("A","z",(new q).AddRange("[","`")),he.LatinExtendedA=U.Define("Ā","ſ"),he.LatinExtendedB=U.Define("ƀ","ɏ"),he.Greek=U.Define("Ͱ","Ͽ",(new q).AddRange("͸","΅").AddCharacters("ʹ͵͸·΋΍΢")),he.Cyrillic=U.Define("Ѐ","ӿ",(new q).AddRange("҂","҉")),he.Armenian=U.Define("԰","֏",(new q).AddCharacters("԰").AddRange("՗","ՠ").AddRange("ֈ","֎")),he.Hebrew=U.Define("֐","׿",new q),he.Arabic=U.Define("؀","ۿ",new q),he.Korean=U.Define("가","힯",new q),he.ListAllCharacterRanges=()=>[he.LatinBasic,he.LatinExtendedA,he.LatinExtendedB,he.Arabic,he.Armenian,he.Cyrillic,he.Greek,he.Hebrew,he.Korean];t.Compiler=class{get errors(){return this._errors}get warnings(){return this._warnings}get authorMessages(){return this._authorMessages}get inputString(){return this._inputString}get options(){return this._options}get parsedStory(){if(!this._parsedStory)throw new Error;return this._parsedStory}get runtimeStory(){if(!this._runtimeStory)throw new Error("Compilation failed.");return this._runtimeStory}get parser(){if(!this._parser)throw new Error;return this._parser}get debugSourceRanges(){return this._debugSourceRanges}constructor(t){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;this._errors=[],this._warnings=[],this._authorMessages=[],this._parsedStory=null,this._runtimeStory=null,this._parser=null,this._debugSourceRanges=[],this.Compile=()=>(this._parser=new he(this.inputString,this.options.sourceFilename||null,this.OnError,null,this.options.fileHandler),this._parsedStory=this.parser.ParseStory(),0===this.errors.length?(this.parsedStory.countAllVisits=this.options.countAllVisits,this._runtimeStory=this.parsedStory.ExportRuntime(this.OnError)):this._runtimeStory=null,this.runtimeStory),this.RetrieveDebugSourceForLatestContent=()=>{var t;for(const e of this.runtimeStory.state.outputStream){const i=s(e,I);if(null!==i){const e=new n((null===(t=i.value)||void 0===t?void 0:t.length)||0,i.debugMetadata,i.value||"unknown");this.debugSourceRanges.push(e)}}},this.DebugMetadataForContentAtOffset=t=>{let e=0,n=null;for(const i of this.debugSourceRanges){if(null!==i.debugMetadata&&(n=i.debugMetadata),t>=e&&t{switch(e){case i.Author:this._authorMessages.push(t);break;case i.Warning:this._warnings.push(t);break;case i.Error:this._errors.push(t)}null!==this.options.errorHandler&&this.options.errorHandler(t,e)},this._inputString=t,this._options=r||new e}},t.CompilerOptions=e,t.InkList=E,t.InkParser=he,t.JsonFileHandler=class{constructor(t){this.fileHierarchy=t,this.ResolveInkFilename=t=>{if(Object.keys(this.fileHierarchy).includes(t))return t;throw new Error(`Cannot locate ${t}. Are you trying a relative import ? This is not yet implemented.`)},this.LoadInkFileContents=t=>{if(Object.keys(this.fileHierarchy).includes(t))return this.fileHierarchy[t];throw new Error(`Cannot open ${t}.`)}}},t.Story=re})); +//# sourceMappingURL=ink-full.js.map diff --git a/prototype/ink-full.js.map b/prototype/ink-full.js.map new file mode 100644 index 0000000..3599f3a --- /dev/null +++ b/prototype/ink-full.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ink-full.js","sources":["../src/compiler/CompilerOptions.ts","../src/compiler/DebugSourceRange.ts","../src/compiler/Parser/ErrorType.ts","../src/compiler/Parser/ParsedHierarchy/Argument.ts","../src/engine/TypeAssertion.ts","../src/compiler/Parser/ParsedHierarchy/Object.ts","../src/compiler/Parser/ParsedHierarchy/AuthorWarning.ts","../src/engine/Path.ts","../src/engine/Debug.ts","../src/engine/Value.ts","../src/engine/PushPop.ts","../src/engine/NullException.ts","../src/engine/Object.ts","../src/engine/StringBuilder.ts","../src/engine/InkList.ts","../src/engine/StoryException.ts","../src/engine/TryGetResult.ts","../src/engine/SearchResult.ts","../src/engine/Container.ts","../src/engine/ControlCommand.ts","../src/compiler/Parser/ParsedHierarchy/Expression/Expression.ts","../src/engine/Void.ts","../src/engine/NativeFunctionCall.ts","../src/compiler/Parser/ParsedHierarchy/Expression/NumberExpression.ts","../src/compiler/Parser/ParsedHierarchy/Expression/UnaryExpression.ts","../src/compiler/Parser/ParsedHierarchy/Expression/BinaryExpression.ts","../src/compiler/Parser/CharacterSet.ts","../src/compiler/Parser/CharacterRange.ts","../src/engine/ChoicePoint.ts","../src/engine/Pointer.ts","../src/engine/Divert.ts","../src/compiler/Parser/ParsedHierarchy/SymbolType.ts","../src/engine/VariableAssignment.ts","../src/compiler/Parser/ParsedHierarchy/Choice.ts","../src/compiler/Parser/StringParser/StringParserElement.ts","../src/compiler/Parser/StringParser/StringParserState.ts","../src/compiler/Parser/StringParser/StringParser.ts","../src/compiler/Parser/CommentEliminator.ts","../src/compiler/Parser/ParsedHierarchy/Conditional/Conditional.ts","../src/compiler/Parser/ParsedHierarchy/Text.ts","../src/compiler/Parser/ParsedHierarchy/Declaration/ConstantDeclaration.ts","../src/compiler/Parser/ParsedHierarchy/Flow/FlowLevel.ts","../src/compiler/Parser/ParsedHierarchy/Gather/Gather.ts","../src/compiler/Parser/ParsedHierarchy/Path.ts","../src/compiler/Parser/ParsedHierarchy/ReturnType.ts","../src/compiler/Parser/ParsedHierarchy/Flow/ClosestFlowBase.ts","../src/compiler/Parser/ParsedHierarchy/Identifier.ts","../src/compiler/Parser/ParsedHierarchy/Flow/FlowBase.ts","../src/compiler/Parser/ParsedHierarchy/ContentList.ts","../src/engine/VariableReference.ts","../src/compiler/Parser/ParsedHierarchy/Variable/VariableReference.ts","../src/compiler/Parser/ParsedHierarchy/FunctionCall.ts","../src/compiler/Parser/ParsedHierarchy/Expression/MultipleConditionExpression.ts","../src/compiler/Parser/ParsedHierarchy/Divert/DivertTarget.ts","../src/compiler/Parser/ParsedHierarchy/Divert/Divert.ts","../src/compiler/Parser/ParsedHierarchy/Gather/GatherPointToResolve.ts","../src/compiler/Parser/ParsedHierarchy/Sequence/SequenceDivertToResolve.ts","../src/compiler/Parser/ParsedHierarchy/Sequence/SequenceType.ts","../src/compiler/Parser/ParsedHierarchy/Sequence/Sequence.ts","../src/compiler/Parser/ParsedHierarchy/TunnelOnwards.ts","../src/engine/ListDefinition.ts","../src/compiler/Parser/ParsedHierarchy/List/ListDefinition.ts","../src/compiler/Parser/ParsedHierarchy/Variable/VariableAssignment.ts","../src/compiler/Parser/ParsedHierarchy/Weave.ts","../src/compiler/Parser/ParsedHierarchy/Conditional/ConditionalSingleBranch.ts","../src/compiler/Parser/CustomFlags.ts","../src/engine/DebugMetadata.ts","../src/compiler/Parser/ParsedHierarchy/Declaration/ExternalDeclaration.ts","../src/compiler/Parser/FlowDecl.ts","../src/compiler/Parser/ParsedHierarchy/Wrap.ts","../src/compiler/Parser/ParsedHierarchy/Glue.ts","../src/engine/Glue.ts","../src/compiler/Parser/ParsedHierarchy/Expression/IncDecExpression.ts","../src/compiler/Parser/ParsedHierarchy/IncludedFile.ts","../src/compiler/Parser/InfixOperator.ts","../src/compiler/Parser/ParsedHierarchy/Knot.ts","../src/compiler/Parser/ParsedHierarchy/List/List.ts","../src/compiler/Parser/ParsedHierarchy/List/ListElementDefinition.ts","../src/compiler/Parser/StatementLevel.ts","../src/compiler/Parser/ParsedHierarchy/Stitch.ts","../src/engine/Tag.ts","../src/engine/Choice.ts","../src/engine/ListDefinitionsOrigin.ts","../src/engine/JsonSerialisation.ts","../src/engine/CallStack.ts","../src/engine/VariablesState.ts","../src/engine/PRNG.ts","../src/engine/StatePatch.ts","../src/engine/SimpleJson.ts","../src/engine/Flow.ts","../src/engine/StoryState.ts","../src/engine/StopWatch.ts","../src/engine/Error.ts","../src/engine/Story.ts","../src/compiler/Parser/ParsedHierarchy/Story.ts","../src/compiler/Parser/ParsedHierarchy/Expression/StringExpression.ts","../src/compiler/Parser/ParsedHierarchy/Tag.ts","../src/compiler/FileHandler/DefaultFileHandler.ts","../src/compiler/Parser/InkParser.ts","../src/compiler/Compiler.ts","../src/compiler/FileHandler/JsonFileHandler.ts"],"sourcesContent":["import { ErrorHandler } from \"../engine/Error\";\nimport { IFileHandler } from \"./IFileHandler\";\n\nexport class CompilerOptions {\n constructor(\n public readonly sourceFilename: string | null = null,\n public readonly pluginNames: string[] = [],\n public readonly countAllVisits: boolean = false,\n public readonly errorHandler: ErrorHandler | null = null,\n public readonly fileHandler: IFileHandler | null = null\n ) {}\n}\n","import { DebugMetadata } from \"../engine/DebugMetadata\";\n\nexport class DebugSourceRange {\n constructor(\n public readonly length: number,\n public readonly debugMetadata: DebugMetadata | null,\n public text: string\n ) {}\n}\n","// TODO: Unifify with Engine.\n\nexport enum ErrorType {\n Author,\n Warning,\n Error,\n}\n","import { Identifier } from \"./Identifier\";\n\nexport class Argument {\n constructor(\n public identifier: Identifier | null = null,\n public isByReference: boolean | null = null,\n public isDivertTarget: boolean | null = null\n ) {}\n\n get typeName(): string {\n return \"Argument\";\n }\n}\n","import { INamedContent } from \"./INamedContent\";\n\nexport function asOrNull(\n obj: any,\n type: (new (...arg: any[]) => T) | (Function & { prototype: T })\n): T | null {\n if (obj instanceof type) {\n return unsafeTypeAssertion(obj, type);\n } else {\n return null;\n }\n}\n\nexport function asOrThrows(\n obj: any,\n type: (new (...arg: any[]) => T) | (Function & { prototype: T })\n): T | never {\n if (obj instanceof type) {\n return unsafeTypeAssertion(obj, type);\n } else {\n throw new Error(`${obj} is not of type ${type}`);\n }\n}\n\nexport function asNumberOrThrows(obj: any) {\n if (typeof obj === \"number\") {\n return obj as number;\n } else {\n throw new Error(`${obj} is not a number`);\n }\n}\n\nexport function asBooleanOrThrows(obj: any) {\n if (typeof obj === \"boolean\") {\n return obj as boolean;\n } else {\n throw new Error(`${obj} is not a boolean`);\n }\n}\n\n// So here, in the reference implementation, contentObj is casted to an INamedContent\n// but here we use js-style duck typing: if it implements the same props as the interface,\n// we treat it as valid.\nexport function asINamedContentOrNull(obj: any): INamedContent | null {\n if (obj.hasValidName && obj.name) {\n return obj as INamedContent;\n }\n\n return null;\n}\n\nexport function nullIfUndefined(obj: T | undefined): T | null {\n if (typeof obj === \"undefined\") {\n return null;\n }\n\n return obj;\n}\n\nexport function isEquatable(type: any) {\n return typeof type === \"object\" && typeof type.Equals === \"function\";\n}\n\nfunction unsafeTypeAssertion(\n obj: any,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n type: (new () => T) | (Function & { prototype: T })\n) {\n return obj as T;\n}\n\nexport function filterUndef(element: T | undefined): element is T {\n return element != undefined;\n}\n","import { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { DebugMetadata } from \"../../../engine/DebugMetadata\";\nimport { FindQueryFunc } from \"./FindQueryFunc\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Path as RuntimePath } from \"../../../engine/Path\";\nimport { Story } from \"./Story\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\n\nexport abstract class ParsedObject {\n public abstract readonly GenerateRuntimeObject: () => RuntimeObject | null;\n\n private _alreadyHadError: boolean = false;\n private _alreadyHadWarning: boolean = false;\n private _debugMetadata: DebugMetadata | null = null;\n private _runtimeObject: RuntimeObject | null = null;\n\n public content: ParsedObject[] = [];\n public parent: ParsedObject | null = null;\n\n get debugMetadata() {\n if (this._debugMetadata === null && this.parent) {\n return this.parent.debugMetadata;\n }\n\n return this._debugMetadata;\n }\n\n set debugMetadata(value: DebugMetadata | null) {\n this._debugMetadata = value;\n }\n\n get hasOwnDebugMetadata(): boolean {\n return Boolean(this.debugMetadata);\n }\n\n get typeName(): string {\n return \"ParsedObject\";\n }\n\n public readonly GetType = (): string => this.typeName;\n\n get story(): Story {\n let ancestor: ParsedObject = this;\n while (ancestor.parent) {\n ancestor = ancestor.parent;\n }\n\n return ancestor as Story;\n }\n\n get runtimeObject(): RuntimeObject {\n if (!this._runtimeObject) {\n this._runtimeObject = this.GenerateRuntimeObject();\n if (this._runtimeObject) {\n this._runtimeObject.debugMetadata = this.debugMetadata;\n }\n }\n\n return this._runtimeObject as RuntimeObject;\n }\n\n set runtimeObject(value: RuntimeObject) {\n this._runtimeObject = value;\n }\n\n get runtimePath(): RuntimePath {\n if (!this.runtimeObject.path) {\n throw new Error();\n }\n\n return this.runtimeObject.path;\n }\n\n // When counting visits and turns since, different object\n // types may have different containers that needs to be counted.\n // For most it'll just be the object's main runtime object,\n // but for e.g. choices, it'll be the target container.\n get containerForCounting(): RuntimeContainer | null {\n return this.runtimeObject as RuntimeContainer;\n }\n\n get ancestry(): ParsedObject[] {\n let result = [];\n\n let ancestor = this.parent;\n while (ancestor) {\n result.push(ancestor);\n ancestor = ancestor.parent;\n }\n\n result = result.reverse();\n\n return result;\n }\n\n /*\n get descriptionOfScope(): string {\n const locationNames: string[] = [];\n\n let ancestor: ParsedObject | null = this;\n while (ancestor) {\n var ancestorFlow = ancestor as FlowBase;\n if (ancestorFlow && ancestorFlow.name != null) {\n locationNames.push(`'${ancestorFlow.name}'`);\n }\n ancestor = ancestor.parent;\n }\n\n let scopeSB = '';\n if (locationNames.length > 0) {\n const locationsListStr = locationNames.join(', ');\n scopeSB += `${locationsListStr} and`;\n }\n\n scopeSB += 'at top scope';\n\n return scopeSB;\n }\n*/\n\n // Return the object so that method can be chained easily\n public readonly AddContent = (\n subContent: V\n ) => {\n if (this.content === null) {\n this.content = [];\n }\n\n const sub = Array.isArray(subContent) ? subContent : [subContent];\n\n // Make resilient to content not existing, which can happen\n // in the case of parse errors where we've already reported\n // an error but still want a valid structure so we can\n // carry on parsing.\n for (const ss of sub) {\n if (ss.hasOwnProperty(\"parent\")) {\n ss.parent = this;\n }\n this.content.push(ss);\n }\n\n if (Array.isArray(subContent)) {\n return;\n } else {\n return subContent;\n }\n };\n\n public readonly InsertContent = (\n index: number,\n subContent: T\n ): T => {\n if (this.content === null) {\n this.content = [];\n }\n\n subContent.parent = this;\n this.content.splice(index, 0, subContent);\n\n return subContent;\n };\n\n public readonly Find =\n (\n type: (new (...arg: any[]) => T) | (Function & { prototype: T })\n ) =>\n (queryFunc: FindQueryFunc | null = null): T | null => {\n let tObj = asOrNull(this, type) as any as T;\n if (tObj !== null && (queryFunc === null || queryFunc(tObj) === true)) {\n return tObj;\n }\n\n if (this.content === null) {\n return null;\n }\n\n for (const obj of this.content) {\n let nestedResult = obj.Find && obj.Find(type)(queryFunc);\n if (nestedResult) {\n return nestedResult as T;\n }\n }\n\n return null;\n };\n\n public readonly FindAll =\n (\n type: (new (...arg: any[]) => T) | (Function & { prototype: T })\n ) =>\n (queryFunc?: FindQueryFunc, foundSoFar?: T[]): T[] => {\n const found = Array.isArray(foundSoFar) ? foundSoFar : [];\n\n const tObj = asOrNull(this, type);\n if (tObj !== null && (!queryFunc || queryFunc(tObj) === true)) {\n found.push(tObj);\n }\n\n if (this.content === null) {\n return [];\n }\n\n for (const obj of this.content) {\n obj.FindAll && obj.FindAll(type)(queryFunc, found);\n }\n\n return found;\n };\n\n public ResolveReferences(context: Story) {\n if (this.content !== null) {\n for (const obj of this.content) {\n obj.ResolveReferences(context);\n }\n }\n }\n\n public Error(\n message: string,\n source: ParsedObject | null = null,\n isWarning: boolean = false\n ): void {\n if (source === null) {\n source = this;\n }\n\n // Only allow a single parsed object to have a single error *directly* associated with it\n if (\n (source._alreadyHadError && !isWarning) ||\n (source._alreadyHadWarning && isWarning)\n ) {\n return;\n }\n\n if (this.parent) {\n this.parent.Error(message, source, isWarning);\n } else {\n throw new Error(`No parent object to send error to: ${message}`);\n }\n\n if (isWarning) {\n source._alreadyHadWarning = true;\n } else {\n source._alreadyHadError = true;\n }\n }\n\n public readonly Warning = (\n message: string,\n source: ParsedObject | null = null\n ): void => {\n this.Error(message, source, true);\n };\n}\n","import { ParsedObject } from \"./Object\";\n\nexport class AuthorWarning extends ParsedObject {\n constructor(public readonly warningMessage: string) {\n super();\n }\n\n get typeName(): string {\n return \"AuthorWarning\";\n }\n\n public readonly GenerateRuntimeObject = (): null => {\n this.Warning(this.warningMessage);\n return null;\n };\n}\n","export class Path {\n public static parentId = \"^\";\n\n public _isRelative: boolean;\n public _components: Path.Component[];\n public _componentsString: string | null;\n\n constructor();\n constructor(componentsString: string);\n constructor(head: Path.Component, tail: Path);\n constructor(head: Path.Component[], relative?: boolean);\n constructor() {\n this._components = [];\n this._componentsString = null;\n this._isRelative = false;\n\n if (typeof arguments[0] == \"string\") {\n let componentsString = arguments[0] as string;\n this.componentsString = componentsString;\n } else if (\n arguments[0] instanceof Path.Component &&\n arguments[1] instanceof Path\n ) {\n let head = arguments[0] as Path.Component;\n let tail = arguments[1] as Path;\n this._components.push(head);\n this._components = this._components.concat(tail._components);\n } else if (arguments[0] instanceof Array) {\n let head = arguments[0] as Path.Component[];\n let relative = !!arguments[1] as boolean;\n this._components = this._components.concat(head);\n this._isRelative = relative;\n }\n }\n get isRelative() {\n return this._isRelative;\n }\n get componentCount(): number {\n return this._components.length;\n }\n get head(): Path.Component | null {\n if (this._components.length > 0) {\n return this._components[0];\n } else {\n return null;\n }\n }\n get tail(): Path {\n if (this._components.length >= 2) {\n // careful, the original code uses length-1 here. This is because the second argument of\n // List.GetRange is a number of elements to extract, wherease Array.slice uses an index\n let tailComps = this._components.slice(1, this._components.length);\n return new Path(tailComps);\n } else {\n return Path.self;\n }\n }\n get length(): number {\n return this._components.length;\n }\n get lastComponent(): Path.Component | null {\n let lastComponentIdx = this._components.length - 1;\n if (lastComponentIdx >= 0) {\n return this._components[lastComponentIdx];\n } else {\n return null;\n }\n }\n get containsNamedComponent(): boolean {\n for (let i = 0, l = this._components.length; i < l; i++) {\n if (!this._components[i].isIndex) {\n return true;\n }\n }\n return false;\n }\n static get self(): Path {\n let path = new Path();\n path._isRelative = true;\n return path;\n }\n\n public GetComponent(index: number): Path.Component {\n return this._components[index];\n }\n public PathByAppendingPath(pathToAppend: Path): Path {\n let p = new Path();\n\n let upwardMoves = 0;\n for (let i = 0; i < pathToAppend._components.length; ++i) {\n if (pathToAppend._components[i].isParent) {\n upwardMoves++;\n } else {\n break;\n }\n }\n\n for (let i = 0; i < this._components.length - upwardMoves; ++i) {\n p._components.push(this._components[i]);\n }\n\n for (let i = upwardMoves; i < pathToAppend._components.length; ++i) {\n p._components.push(pathToAppend._components[i]);\n }\n\n return p;\n }\n get componentsString(): string {\n if (this._componentsString == null) {\n this._componentsString = this._components.join(\".\");\n if (this.isRelative)\n this._componentsString = \".\" + this._componentsString;\n }\n\n return this._componentsString;\n }\n set componentsString(value: string) {\n this._components.length = 0;\n\n this._componentsString = value;\n\n if (this._componentsString == null || this._componentsString == \"\") return;\n\n if (this._componentsString[0] == \".\") {\n this._isRelative = true;\n this._componentsString = this._componentsString.substring(1);\n }\n\n let componentStrings = this._componentsString.split(\".\");\n for (let str of componentStrings) {\n // we need to distinguish between named components that start with a number, eg \"42somewhere\", and indexed components\n // the normal parseInt won't do for the detection because it's too relaxed.\n // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt\n if (/^(\\-|\\+)?([0-9]+|Infinity)$/.test(str)) {\n this._components.push(new Path.Component(parseInt(str)));\n } else {\n this._components.push(new Path.Component(str));\n }\n }\n }\n public toString(): string {\n return this.componentsString;\n }\n public Equals(otherPath: Path | null): boolean {\n if (otherPath == null) return false;\n\n if (otherPath._components.length != this._components.length) return false;\n\n if (otherPath.isRelative != this.isRelative) return false;\n\n // the original code uses SequenceEqual here, so we need to iterate over the components manually.\n for (let i = 0, l = otherPath._components.length; i < l; i++) {\n // it's not quite clear whether this test should use Equals or a simple == operator,\n // see https://github.com/y-lohse/inkjs/issues/22\n if (!otherPath._components[i].Equals(this._components[i])) return false;\n }\n\n return true;\n }\n public PathByAppendingComponent(c: Path.Component): Path {\n let p = new Path();\n p._components.push(...this._components);\n p._components.push(c);\n return p;\n }\n}\n\nexport namespace Path {\n export class Component {\n public readonly index: number;\n public readonly name: string | null;\n\n constructor(indexOrName: string | number) {\n this.index = -1;\n this.name = null;\n if (typeof indexOrName == \"string\") {\n this.name = indexOrName;\n } else {\n this.index = indexOrName;\n }\n }\n get isIndex(): boolean {\n return this.index >= 0;\n }\n get isParent(): boolean {\n return this.name == Path.parentId;\n }\n\n public static ToParent(): Component {\n return new Component(Path.parentId);\n }\n public toString(): string | null {\n if (this.isIndex) {\n return this.index.toString();\n } else {\n return this.name;\n }\n }\n public Equals(otherComp: Component): boolean {\n if (otherComp != null && otherComp.isIndex == this.isIndex) {\n if (this.isIndex) {\n return this.index == otherComp.index;\n } else {\n return this.name == otherComp.name;\n }\n }\n\n return false;\n }\n }\n}\n","export namespace Debug {\n export function AssertType(\n variable: any,\n type: new () => T,\n message: string\n ): void | never {\n Assert(variable instanceof type, message);\n }\n\n export function Assert(condition: boolean, message?: string): void | never {\n if (!condition) {\n if (typeof message !== \"undefined\") {\n console.warn(message);\n }\n\n if (console.trace) {\n console.trace();\n }\n\n throw new Error(\"\");\n }\n }\n}\n","import { InkObject } from \"./Object\";\nimport { Path } from \"./Path\";\nimport { InkList, InkListItem } from \"./InkList\";\nimport { StoryException } from \"./StoryException\";\nimport { asOrNull, asOrThrows } from \"./TypeAssertion\";\nimport { tryParseInt, tryParseFloat } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\n\nexport abstract class AbstractValue extends InkObject {\n public abstract get valueType(): ValueType;\n public abstract get isTruthy(): boolean;\n public abstract get valueObject(): any;\n\n public abstract Cast(newType: ValueType): Value;\n\n public static Create(\n val: any,\n preferredNumberType?: ValueType\n ): Value | null {\n // This code doesn't exist in upstream and is simply here to enforce\n // the creation of the proper number value.\n // If `preferredNumberType` is not provided or if value doesn't match\n // `preferredNumberType`, this conditional does nothing.\n if (preferredNumberType) {\n if (\n preferredNumberType === (ValueType.Int as ValueType) &&\n Number.isInteger(Number(val))\n ) {\n return new IntValue(Number(val));\n } else if (\n preferredNumberType === (ValueType.Float as ValueType) &&\n !isNaN(val)\n ) {\n return new FloatValue(Number(val));\n }\n }\n\n if (typeof val === \"boolean\") {\n return new BoolValue(Boolean(val));\n }\n\n // https://github.com/y-lohse/inkjs/issues/425\n // Changed condition sequence, because Number('') is\n // parsed to 0, which made setting string to empty\n // impossible\n if (typeof val === \"string\") {\n return new StringValue(String(val));\n } else if (Number.isInteger(Number(val))) {\n return new IntValue(Number(val));\n } else if (!isNaN(val)) {\n return new FloatValue(Number(val));\n } else if (val instanceof Path) {\n return new DivertTargetValue(asOrThrows(val, Path));\n } else if (val instanceof InkList) {\n return new ListValue(asOrThrows(val, InkList));\n }\n\n return null;\n }\n public Copy() {\n return asOrThrows(AbstractValue.Create(this.valueObject), InkObject);\n }\n public BadCastException(targetType: ValueType) {\n return new StoryException(\n \"Can't cast \" +\n this.valueObject +\n \" from \" +\n this.valueType +\n \" to \" +\n targetType\n );\n }\n}\n\nexport abstract class Value<\n T extends { toString: () => string },\n> extends AbstractValue {\n public value: T | null;\n\n constructor(val: T | null) {\n super();\n this.value = val;\n }\n public get valueObject() {\n return this.value;\n }\n public toString() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value.toString();\n }\n}\n\nexport class BoolValue extends Value {\n constructor(val: boolean) {\n super(val || false);\n }\n public get isTruthy() {\n return Boolean(this.value);\n }\n public get valueType() {\n return ValueType.Bool;\n }\n\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Int) {\n return new IntValue(this.value ? 1 : 0);\n }\n\n if (newType == ValueType.Float) {\n return new FloatValue(this.value ? 1.0 : 0.0);\n }\n\n if (newType == ValueType.String) {\n return new StringValue(this.value ? \"true\" : \"false\");\n }\n\n throw this.BadCastException(newType);\n }\n\n public toString() {\n return this.value ? \"true\" : \"false\";\n }\n}\n\nexport class IntValue extends Value {\n constructor(val: number) {\n super(val || 0);\n }\n public get isTruthy() {\n return this.value != 0;\n }\n public get valueType() {\n return ValueType.Int;\n }\n\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Bool) {\n return new BoolValue(this.value === 0 ? false : true);\n }\n\n if (newType == ValueType.Float) {\n return new FloatValue(this.value);\n }\n\n if (newType == ValueType.String) {\n return new StringValue(\"\" + this.value);\n }\n\n throw this.BadCastException(newType);\n }\n}\n\nexport class FloatValue extends Value {\n constructor(val: number) {\n super(val || 0.0);\n }\n public get isTruthy() {\n return this.value != 0.0;\n }\n public get valueType() {\n return ValueType.Float;\n }\n\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Bool) {\n return new BoolValue(this.value === 0.0 ? false : true);\n }\n\n if (newType == ValueType.Int) {\n return new IntValue(this.value);\n }\n\n if (newType == ValueType.String) {\n return new StringValue(\"\" + this.value);\n }\n\n throw this.BadCastException(newType);\n }\n}\n\nexport class StringValue extends Value {\n public _isNewline: boolean;\n public _isInlineWhitespace: boolean;\n\n constructor(val: string) {\n super(val || \"\");\n\n this._isNewline = this.value == \"\\n\";\n this._isInlineWhitespace = true;\n\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (this.value.length > 0) {\n this.value.split(\"\").every((c) => {\n if (c != \" \" && c != \"\\t\") {\n this._isInlineWhitespace = false;\n return false;\n }\n\n return true;\n });\n }\n }\n public get valueType() {\n return ValueType.String;\n }\n public get isTruthy() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value.length > 0;\n }\n public get isNewline() {\n return this._isNewline;\n }\n public get isInlineWhitespace() {\n return this._isInlineWhitespace;\n }\n public get isNonWhitespace() {\n return !this.isNewline && !this.isInlineWhitespace;\n }\n\n public Cast(newType: ValueType): Value {\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Int) {\n let parsedInt = tryParseInt(this.value);\n if (parsedInt.exists) {\n return new IntValue(parsedInt.result);\n } else {\n throw this.BadCastException(newType);\n }\n }\n\n if (newType == ValueType.Float) {\n let parsedFloat = tryParseFloat(this.value);\n if (parsedFloat.exists) {\n return new FloatValue(parsedFloat.result);\n } else {\n throw this.BadCastException(newType);\n }\n }\n\n throw this.BadCastException(newType);\n }\n}\n\nexport class DivertTargetValue extends Value {\n constructor(targetPath: Path | null = null) {\n super(targetPath);\n }\n public get valueType() {\n return ValueType.DivertTarget;\n }\n public get targetPath() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value;\n }\n public set targetPath(value: Path) {\n this.value = value;\n }\n public get isTruthy(): never {\n throw new Error(\"Shouldn't be checking the truthiness of a divert target\");\n }\n\n public Cast(newType: ValueType): Value {\n if (newType == this.valueType) return this;\n\n throw this.BadCastException(newType);\n }\n public toString() {\n return \"DivertTargetValue(\" + this.targetPath + \")\";\n }\n}\n\nexport class VariablePointerValue extends Value {\n public _contextIndex: number;\n\n constructor(variableName: string, contextIndex: number = -1) {\n super(variableName);\n\n this._contextIndex = contextIndex;\n }\n\n public get contextIndex() {\n return this._contextIndex;\n }\n public set contextIndex(value: number) {\n this._contextIndex = value;\n }\n public get variableName() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value;\n }\n public set variableName(value: string) {\n this.value = value;\n }\n public get valueType() {\n return ValueType.VariablePointer;\n }\n\n public get isTruthy(): never {\n throw new Error(\n \"Shouldn't be checking the truthiness of a variable pointer\"\n );\n }\n\n public Cast(newType: ValueType): Value {\n if (newType == this.valueType) return this;\n\n throw this.BadCastException(newType);\n }\n public toString() {\n return \"VariablePointerValue(\" + this.variableName + \")\";\n }\n public Copy() {\n return new VariablePointerValue(this.variableName, this.contextIndex);\n }\n}\n\nexport class ListValue extends Value {\n public get isTruthy() {\n if (this.value === null) {\n return throwNullException(\"this.value\");\n }\n return this.value.Count > 0;\n }\n public get valueType() {\n return ValueType.List;\n }\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == ValueType.Int) {\n let max = this.value.maxItem;\n if (max.Key.isNull) return new IntValue(0);\n else return new IntValue(max.Value);\n } else if (newType == ValueType.Float) {\n let max = this.value.maxItem;\n if (max.Key.isNull) return new FloatValue(0.0);\n else return new FloatValue(max.Value);\n } else if (newType == ValueType.String) {\n let max = this.value.maxItem;\n if (max.Key.isNull) return new StringValue(\"\");\n else {\n return new StringValue(max.Key.toString());\n }\n }\n\n if (newType == this.valueType) return this;\n\n throw this.BadCastException(newType);\n }\n constructor();\n constructor(list: InkList);\n constructor(listOrSingleItem: InkListItem, singleValue: number);\n constructor(listOrSingleItem?: InkListItem | InkList, singleValue?: number) {\n super(null);\n\n if (!listOrSingleItem && !singleValue) {\n this.value = new InkList();\n } else if (listOrSingleItem instanceof InkList) {\n this.value = new InkList(listOrSingleItem);\n } else if (\n listOrSingleItem instanceof InkListItem &&\n typeof singleValue === \"number\"\n ) {\n this.value = new InkList({\n Key: listOrSingleItem,\n Value: singleValue,\n });\n }\n }\n public static RetainListOriginsForAssignment(\n oldValue: InkObject | null,\n newValue: InkObject\n ) {\n let oldList = asOrNull(oldValue, ListValue);\n let newList = asOrNull(newValue, ListValue);\n\n if (newList && newList.value === null)\n return throwNullException(\"newList.value\");\n if (oldList && oldList.value === null)\n return throwNullException(\"oldList.value\");\n\n // When assigning the empty list, try to retain any initial origin names\n if (oldList && newList && newList.value!.Count == 0)\n newList.value!.SetInitialOriginNames(oldList.value!.originNames);\n }\n}\n\nexport enum ValueType {\n Bool = -1,\n Int = 0,\n Float = 1,\n List = 2,\n String = 3,\n DivertTarget = 4,\n VariablePointer = 5,\n}\n","export enum PushPopType {\n Tunnel = 0,\n Function = 1,\n FunctionEvaluationFromGame = 2,\n}\n","/**\n * In the original C# code, a SystemException would be thrown when passing\n * null to methods expected a valid instance. Javascript has no such\n * concept, but TypeScript will not allow `null` to be passed to methods\n * explicitely requiring a valid type.\n *\n * Whenever TypeScript complain about the possibility of a `null` value,\n * check the offending value and it it's null, throw this exception using\n * `throwNullException(name: string)`.\n */\nexport class NullException extends Error {}\n\n/**\n * Throw a NullException.\n *\n * @param name a short description of the offending value (often its name within the code).\n */\nexport function throwNullException(name: string): never {\n throw new NullException(`${name} is null or undefined`);\n}\n","import { Path } from \"./Path\";\nimport { Container } from \"./Container\";\nimport { Debug } from \"./Debug\";\nimport { asOrNull, asINamedContentOrNull } from \"./TypeAssertion\";\nimport { throwNullException } from \"./NullException\";\nimport { SearchResult } from \"./SearchResult\";\nimport { DebugMetadata } from \"./DebugMetadata\";\n\nexport class InkObject {\n public parent: InkObject | null = null;\n\n get debugMetadata(): DebugMetadata | null {\n if (this._debugMetadata === null) {\n if (this.parent) {\n return this.parent.debugMetadata;\n }\n }\n\n return this._debugMetadata;\n }\n\n set debugMetadata(value) {\n this._debugMetadata = value;\n }\n\n get ownDebugMetadata() {\n return this._debugMetadata;\n }\n\n private _debugMetadata: DebugMetadata | null = null;\n\n public DebugLineNumberOfPath(path: Path) {\n if (path === null) return null;\n\n // Try to get a line number from debug metadata\n let root = this.rootContentContainer;\n if (root) {\n let targetContent = root.ContentAtPath(path).obj;\n if (targetContent) {\n let dm = targetContent.debugMetadata;\n if (dm !== null) {\n return dm.startLineNumber;\n }\n }\n }\n\n return null;\n }\n\n get path() {\n if (this._path == null) {\n if (this.parent == null) {\n this._path = new Path();\n } else {\n let comps: Path.Component[] = [];\n\n let child: InkObject = this;\n let container = asOrNull(child.parent, Container);\n\n while (container !== null) {\n let namedChild = asINamedContentOrNull(child);\n if (namedChild != null && namedChild.hasValidName) {\n if (namedChild.name === null)\n return throwNullException(\"namedChild.name\");\n comps.unshift(new Path.Component(namedChild.name!));\n } else {\n comps.unshift(new Path.Component(container.content.indexOf(child)));\n }\n\n child = container;\n container = asOrNull(container.parent, Container);\n }\n\n this._path = new Path(comps);\n }\n }\n\n return this._path;\n }\n private _path: Path | null = null;\n\n public ResolvePath(path: Path | null): SearchResult {\n if (path === null) return throwNullException(\"path\");\n if (path.isRelative) {\n let nearestContainer = asOrNull(this, Container);\n\n if (nearestContainer === null) {\n Debug.Assert(\n this.parent !== null,\n \"Can't resolve relative path because we don't have a parent\"\n );\n nearestContainer = asOrNull(this.parent, Container);\n Debug.Assert(\n nearestContainer !== null,\n \"Expected parent to be a container\"\n );\n Debug.Assert(path.GetComponent(0).isParent);\n path = path.tail;\n }\n\n if (nearestContainer === null) {\n return throwNullException(\"nearestContainer\");\n }\n return nearestContainer.ContentAtPath(path);\n } else {\n let contentContainer = this.rootContentContainer;\n if (contentContainer === null) {\n return throwNullException(\"contentContainer\");\n }\n return contentContainer.ContentAtPath(path);\n }\n }\n\n public ConvertPathToRelative(globalPath: Path) {\n let ownPath = this.path;\n\n let minPathLength = Math.min(globalPath.length, ownPath.length);\n let lastSharedPathCompIndex = -1;\n\n for (let i = 0; i < minPathLength; ++i) {\n let ownComp = ownPath.GetComponent(i);\n let otherComp = globalPath.GetComponent(i);\n\n if (ownComp.Equals(otherComp)) {\n lastSharedPathCompIndex = i;\n } else {\n break;\n }\n }\n\n // No shared path components, so just use global path\n if (lastSharedPathCompIndex == -1) return globalPath;\n\n let numUpwardsMoves = ownPath.componentCount - 1 - lastSharedPathCompIndex;\n\n let newPathComps: Path.Component[] = [];\n\n for (let up = 0; up < numUpwardsMoves; ++up)\n newPathComps.push(Path.Component.ToParent());\n\n for (\n let down = lastSharedPathCompIndex + 1;\n down < globalPath.componentCount;\n ++down\n )\n newPathComps.push(globalPath.GetComponent(down));\n\n let relativePath = new Path(newPathComps, true);\n return relativePath;\n }\n\n public CompactPathString(otherPath: Path) {\n let globalPathStr = null;\n let relativePathStr = null;\n\n if (otherPath.isRelative) {\n relativePathStr = otherPath.componentsString;\n globalPathStr = this.path.PathByAppendingPath(otherPath).componentsString;\n } else {\n let relativePath = this.ConvertPathToRelative(otherPath);\n relativePathStr = relativePath.componentsString;\n globalPathStr = otherPath.componentsString;\n }\n\n if (relativePathStr.length < globalPathStr.length) return relativePathStr;\n else return globalPathStr;\n }\n\n get rootContentContainer() {\n let ancestor: InkObject = this;\n while (ancestor.parent) {\n ancestor = ancestor.parent;\n }\n return asOrNull(ancestor, Container);\n }\n\n public Copy(): InkObject {\n throw Error(\"Not Implemented: Doesn't support copying\");\n }\n // SetChild works slightly diferently in the js implementation.\n // Since we can't pass an objets property by reference, we instead pass\n // the object and the property string.\n // TODO: This method can probably be rewritten with type-safety in mind.\n public SetChild(obj: any, prop: any, value: any) {\n if (obj[prop]) obj[prop] = null;\n\n obj[prop] = value;\n\n if (obj[prop]) obj[prop].parent = this;\n }\n\n public Equals(obj: any) {\n return obj === this;\n }\n}\n","export class StringBuilder {\n private string: string;\n\n constructor(str?: string) {\n str = typeof str !== \"undefined\" ? str.toString() : \"\";\n this.string = str;\n }\n get Length(): number {\n return this.string.length;\n }\n public Append(str: string | null) {\n if (str !== null) {\n this.string += str;\n }\n }\n public AppendLine(str?: string) {\n if (typeof str !== \"undefined\") this.Append(str);\n this.string += \"\\n\";\n }\n public AppendFormat(format: string, ...args: any[]) {\n // taken from http://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format\n this.string += format.replace(/{(\\d+)}/g, (match: string, num: number) =>\n typeof args[num] != \"undefined\" ? args[num] : match\n );\n }\n public toString(): string {\n return this.string;\n }\n\n public Clear() {\n this.string = \"\";\n }\n}\n","import { throwNullException } from \"./NullException\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { Story } from \"./Story\";\n\nexport class InkListItem implements IInkListItem {\n // InkListItem is a struct\n\n public readonly originName: string | null = null;\n public readonly itemName: string | null = null;\n\n constructor(originName: string | null, itemName: string | null);\n constructor(fullName: string | null);\n constructor() {\n if (typeof arguments[1] !== \"undefined\") {\n let originName = arguments[0] as string | null;\n let itemName = arguments[1] as string | null;\n\n this.originName = originName;\n this.itemName = itemName;\n } else if (arguments[0]) {\n let fullName = arguments[0] as string;\n\n let nameParts = fullName.toString().split(\".\");\n this.originName = nameParts[0];\n this.itemName = nameParts[1];\n }\n }\n public static get Null() {\n return new InkListItem(null, null);\n }\n public get isNull() {\n return this.originName == null && this.itemName == null;\n }\n get fullName() {\n return (\n (this.originName !== null ? this.originName : \"?\") + \".\" + this.itemName\n );\n }\n public toString(): string {\n return this.fullName;\n }\n public Equals(obj: InkListItem) {\n if (obj instanceof InkListItem) {\n let otherItem = obj;\n return (\n otherItem.itemName == this.itemName &&\n otherItem.originName == this.originName\n );\n }\n\n return false;\n }\n\n // These methods did not exist in the original C# code. Their purpose is to\n // make `InkListItem` mimics the value-type semantics of the original\n // struct. Please refer to the end of this file, for a more in-depth\n // explanation.\n\n /**\n * Returns a shallow clone of the current instance.\n */\n public copy() {\n return new InkListItem(this.originName, this.itemName);\n }\n /**\n * Returns a `SerializedInkListItem` representing the current\n * instance. The result is intended to be used as a key inside a Map.\n */\n public serialized(): SerializedInkListItem {\n // We are simply using a JSON representation as a value-typed key.\n return JSON.stringify({\n originName: this.originName,\n itemName: this.itemName,\n });\n }\n\n /**\n * Reconstructs a `InkListItem` from the given SerializedInkListItem.\n */\n public static fromSerializedKey(key: SerializedInkListItem): InkListItem {\n let obj = JSON.parse(key);\n if (!InkListItem.isLikeInkListItem(obj)) return InkListItem.Null;\n\n let inkListItem = obj as IInkListItem;\n\n return new InkListItem(inkListItem.originName, inkListItem.itemName);\n }\n\n /**\n * Determines whether the given item is sufficiently `InkListItem`-like\n * to be used as a template when reconstructing the InkListItem.\n */\n private static isLikeInkListItem(item: any) {\n if (typeof item !== \"object\") return false;\n if (!item.hasOwnProperty(\"originName\") || !item.hasOwnProperty(\"itemName\"))\n return false;\n if (typeof item.originName !== \"string\" && typeof item.originName !== null)\n return false;\n if (typeof item.itemName !== \"string\" && typeof item.itemName !== null)\n return false;\n\n return true;\n }\n}\n\nexport class InkList extends Map {\n public origins: ListDefinition[] | null = null;\n public _originNames: string[] | null = [];\n\n constructor();\n constructor(otherList: InkList);\n constructor(singleOriginListName: string, originStory: Story);\n constructor(singleElement: KeyValuePair);\n constructor() {\n // Trying to be smart here, this emulates the constructor inheritance found\n // in the original code, but only if otherList is an InkList. IIFE FTW.\n super(\n (() => {\n if (arguments[0] instanceof InkList) {\n return arguments[0];\n } else {\n return [];\n }\n })()\n );\n\n if (arguments[0] instanceof InkList) {\n let otherList = arguments[0] as InkList;\n\n let otherOriginNames = otherList.originNames as string[];\n if (otherOriginNames !== null)\n this._originNames = otherOriginNames.slice();\n if (otherList.origins !== null) {\n this.origins = otherList.origins.slice();\n }\n } else if (typeof arguments[0] === \"string\") {\n let singleOriginListName = arguments[0] as string;\n let originStory = arguments[1] as Story;\n this.SetInitialOriginName(singleOriginListName);\n\n if (originStory.listDefinitions === null) {\n return throwNullException(\"originStory.listDefinitions\");\n }\n let def = originStory.listDefinitions.TryListGetDefinition(\n singleOriginListName,\n null\n );\n if (def.exists) {\n // Throwing now, because if the value is `null` it will\n // eventually throw down the line.\n if (def.result === null) {\n return throwNullException(\"def.result\");\n }\n this.origins = [def.result];\n } else {\n throw new Error(\n \"InkList origin could not be found in story when constructing new list: \" +\n singleOriginListName\n );\n }\n } else if (\n typeof arguments[0] === \"object\" &&\n arguments[0].hasOwnProperty(\"Key\") &&\n arguments[0].hasOwnProperty(\"Value\")\n ) {\n let singleElement = arguments[0] as KeyValuePair;\n this.Add(singleElement.Key, singleElement.Value);\n }\n }\n\n public static FromString(myListItem: string, originStory: Story) {\n let listValue =\n originStory.listDefinitions?.FindSingleItemListWithName(myListItem);\n if (listValue) {\n if (listValue.value === null) {\n return throwNullException(\"listValue.value\");\n }\n return new InkList(listValue.value);\n } else {\n throw new Error(\n \"Could not find the InkListItem from the string '\" +\n myListItem +\n \"' to create an InkList because it doesn't exist in the original list definition in ink.\"\n );\n }\n }\n\n public AddItem(itemOrItemName: InkListItem | string | null) {\n if (itemOrItemName instanceof InkListItem) {\n let item = itemOrItemName;\n\n if (item.originName == null) {\n this.AddItem(item.itemName);\n return;\n }\n\n if (this.origins === null) return throwNullException(\"this.origins\");\n\n for (let origin of this.origins) {\n if (origin.name == item.originName) {\n let intVal = origin.TryGetValueForItem(item, 0);\n if (intVal.exists) {\n this.Add(item, intVal.result);\n return;\n } else {\n throw new Error(\n \"Could not add the item \" +\n item +\n \" to this list because it doesn't exist in the original list definition in ink.\"\n );\n }\n }\n }\n\n throw new Error(\n \"Failed to add item to list because the item was from a new list definition that wasn't previously known to this list. Only items from previously known lists can be used, so that the int value can be found.\"\n );\n } else {\n let itemName = itemOrItemName as string | null;\n\n let foundListDef: ListDefinition | null = null;\n\n if (this.origins === null) return throwNullException(\"this.origins\");\n\n for (let origin of this.origins) {\n if (itemName === null) return throwNullException(\"itemName\");\n\n if (origin.ContainsItemWithName(itemName)) {\n if (foundListDef != null) {\n throw new Error(\n \"Could not add the item \" +\n itemName +\n \" to this list because it could come from either \" +\n origin.name +\n \" or \" +\n foundListDef.name\n );\n } else {\n foundListDef = origin;\n }\n }\n }\n\n if (foundListDef == null)\n throw new Error(\n \"Could not add the item \" +\n itemName +\n \" to this list because it isn't known to any list definitions previously associated with this list.\"\n );\n\n let item = new InkListItem(foundListDef.name, itemName);\n let itemVal = foundListDef.ValueForItem(item);\n this.Add(item, itemVal);\n }\n }\n public ContainsItemNamed(itemName: string | null) {\n for (let [key] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (item.itemName == itemName) return true;\n }\n\n return false;\n }\n public ContainsKey(key: InkListItem) {\n return this.has(key.serialized());\n }\n public Add(key: InkListItem, value: number) {\n let serializedKey = key.serialized();\n if (this.has(serializedKey)) {\n // Throw an exception to match the C# behavior.\n throw new Error(`The Map already contains an entry for ${key}`);\n }\n this.set(serializedKey, value);\n }\n public Remove(key: InkListItem) {\n return this.delete(key.serialized());\n }\n get Count() {\n return this.size;\n }\n get originOfMaxItem(): ListDefinition | null {\n if (this.origins == null) return null;\n\n let maxOriginName = this.maxItem.Key.originName;\n let result = null;\n this.origins.every((origin) => {\n if (origin.name == maxOriginName) {\n result = origin;\n return false;\n } else return true;\n });\n\n return result;\n }\n get originNames(): string[] {\n if (this.Count > 0) {\n if (this._originNames == null && this.Count > 0) this._originNames = [];\n else {\n if (!this._originNames) this._originNames = [];\n this._originNames.length = 0;\n }\n\n for (let [key] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (item.originName === null)\n return throwNullException(\"item.originName\");\n this._originNames.push(item.originName);\n }\n }\n\n return this._originNames as string[];\n }\n public SetInitialOriginName(initialOriginName: string) {\n this._originNames = [initialOriginName];\n }\n public SetInitialOriginNames(initialOriginNames: string[]) {\n if (initialOriginNames == null) this._originNames = null;\n else this._originNames = initialOriginNames.slice(); // store a copy\n }\n get maxItem() {\n let max: KeyValuePair = {\n Key: InkListItem.Null,\n Value: 0,\n };\n for (let [key, value] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (max.Key.isNull || value > max.Value)\n max = { Key: item, Value: value };\n }\n\n return max;\n }\n get minItem() {\n let min: KeyValuePair = {\n Key: InkListItem.Null,\n Value: 0,\n };\n for (let [key, value] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (min.Key.isNull || value < min.Value) {\n min = { Key: item, Value: value };\n }\n }\n return min;\n }\n get inverse() {\n let list = new InkList();\n if (this.origins != null) {\n for (let origin of this.origins) {\n for (let [key, value] of origin.items) {\n let item = InkListItem.fromSerializedKey(key);\n if (!this.ContainsKey(item)) list.Add(item, value);\n }\n }\n }\n return list;\n }\n get all() {\n let list = new InkList();\n if (this.origins != null) {\n for (let origin of this.origins) {\n for (let [key, value] of origin.items) {\n let item = InkListItem.fromSerializedKey(key);\n list.set(item.serialized(), value);\n }\n }\n }\n return list;\n }\n public Union(otherList: InkList) {\n let union = new InkList(this);\n for (let [key, value] of otherList) {\n union.set(key, value);\n }\n return union;\n }\n public Intersect(otherList: InkList) {\n let intersection = new InkList();\n for (let [key, value] of this) {\n if (otherList.has(key)) intersection.set(key, value);\n }\n\n return intersection;\n }\n public HasIntersection(otherList: InkList): boolean {\n for (let [key] of this) {\n if (otherList.has(key)) return true;\n }\n return false;\n }\n public Without(listToRemove: InkList) {\n let result = new InkList(this);\n for (let [key] of listToRemove) {\n result.delete(key);\n }\n\n return result;\n }\n\n public Contains(key: string): boolean;\n public Contains(otherList: InkList): boolean;\n public Contains(what: string | InkList): boolean {\n if (typeof what == \"string\") return this.ContainsItemNamed(what);\n const otherList = what;\n if (otherList.size == 0 || this.size == 0) return false;\n for (let [key] of otherList) {\n if (!this.has(key)) return false;\n }\n\n return true;\n }\n public GreaterThan(otherList: InkList) {\n if (this.Count == 0) return false;\n if (otherList.Count == 0) return true;\n\n return this.minItem.Value > otherList.maxItem.Value;\n }\n public GreaterThanOrEquals(otherList: InkList) {\n if (this.Count == 0) return false;\n if (otherList.Count == 0) return true;\n\n return (\n this.minItem.Value >= otherList.minItem.Value &&\n this.maxItem.Value >= otherList.maxItem.Value\n );\n }\n public LessThan(otherList: InkList) {\n if (otherList.Count == 0) return false;\n if (this.Count == 0) return true;\n\n return this.maxItem.Value < otherList.minItem.Value;\n }\n public LessThanOrEquals(otherList: InkList) {\n if (otherList.Count == 0) return false;\n if (this.Count == 0) return true;\n\n return (\n this.maxItem.Value <= otherList.maxItem.Value &&\n this.minItem.Value <= otherList.minItem.Value\n );\n }\n public MaxAsList() {\n if (this.Count > 0) return new InkList(this.maxItem);\n else return new InkList();\n }\n public MinAsList() {\n if (this.Count > 0) return new InkList(this.minItem);\n else return new InkList();\n }\n public ListWithSubRange(minBound: any, maxBound: any) {\n if (this.Count == 0) return new InkList();\n\n let ordered = this.orderedItems;\n\n let minValue = 0;\n let maxValue = Number.MAX_SAFE_INTEGER;\n\n if (Number.isInteger(minBound)) {\n minValue = minBound;\n } else {\n if (minBound instanceof InkList && minBound.Count > 0)\n minValue = minBound.minItem.Value;\n }\n\n if (Number.isInteger(maxBound)) {\n maxValue = maxBound;\n } else {\n if (maxBound instanceof InkList && maxBound.Count > 0)\n maxValue = maxBound.maxItem.Value;\n }\n\n let subList = new InkList();\n subList.SetInitialOriginNames(this.originNames);\n for (let item of ordered) {\n if (item.Value >= minValue && item.Value <= maxValue) {\n subList.Add(item.Key, item.Value);\n }\n }\n\n return subList;\n }\n public Equals(otherInkList: InkList) {\n if (otherInkList instanceof InkList === false) return false;\n if (otherInkList.Count != this.Count) return false;\n\n for (let [key] of this) {\n if (!otherInkList.has(key)) return false;\n }\n\n return true;\n }\n // GetHashCode not implemented\n get orderedItems() {\n // List>\n let ordered = new Array>();\n\n for (let [key, value] of this) {\n let item = InkListItem.fromSerializedKey(key);\n ordered.push({ Key: item, Value: value });\n }\n\n ordered.sort((x, y) => {\n if (x.Key.originName === null) {\n return throwNullException(\"x.Key.originName\");\n }\n if (y.Key.originName === null) {\n return throwNullException(\"y.Key.originName\");\n }\n\n if (x.Value == y.Value) {\n return x.Key.originName.localeCompare(y.Key.originName);\n } else {\n // TODO: refactor this bit into a numberCompareTo method?\n if (x.Value < y.Value) return -1;\n return x.Value > y.Value ? 1 : 0;\n }\n });\n\n return ordered;\n }\n public toString() {\n let ordered = this.orderedItems;\n\n let sb = new StringBuilder();\n for (let i = 0; i < ordered.length; i++) {\n if (i > 0) sb.Append(\", \");\n\n let item = ordered[i].Key;\n if (item.itemName === null) return throwNullException(\"item.itemName\");\n sb.Append(item.itemName);\n }\n\n return sb.toString();\n }\n // casting a InkList to a Number, for somereason, actually gives a number.\n // This messes up the type detection when creating a Value from a InkList.\n // Returning NaN here prevents that.\n public valueOf() {\n return NaN;\n }\n}\n\n/**\n * In the original C# code, `InkListItem` was defined as value type, meaning\n * that two `InkListItem` would be considered equal as long as they held the\n * same values. This doesn't hold true in Javascript, as `InkListItem` is a\n * reference type (Javascript doesn't allow the creation of custom value types).\n *\n * The key equality of Map objects is based on the \"SameValueZero\" algorithm;\n * since `InkListItem` is a value type, two keys will only be considered\n * equal if they are, in fact, the same object. As we are trying to emulate\n * the original behavior as close as possible, this will lead to unforeseen\n * side effects.\n *\n * In order to have a key equality based on value semantics, we'll convert\n * `InkListItem` to a valid string representation and use this representation\n * as a key (strings are value types in Javascript). Rather than using the\n * type `string` directly, we'll alias it to `SerializedInkListItem` and use\n * this type as the key for our Map-based `InkList`.\n *\n * Reducing `InkListItem` to a JSON representation would not be bulletproof\n * in the general case, but for our needs it works well. The major downside of\n * this method is that we will have to to reconstruct the original `InkListItem`\n * every time we'll need to access its properties.\n */\nexport type SerializedInkListItem = string;\n\n/**\n * An interface inherited by `InkListItem`, defining exposed\n * properties. It's mainly used when deserializing a `InkListItem` from its\n * key (`SerializedInkListItem`)\n */\ninterface IInkListItem {\n readonly originName: string | null;\n readonly itemName: string | null;\n}\nexport interface KeyValuePair {\n Key: K;\n Value: V;\n}\n","export class StoryException extends Error {\n public useEndLineNumber: boolean;\n public message: string;\n public name: string;\n\n constructor(message: string) {\n super(message);\n this.useEndLineNumber = false;\n this.message = message;\n this.name = \"StoryException\";\n }\n}\n","/**\n * This interface normalize the `TryGet` behavior found in the original\n * C# project. Any `TryGet` method will return a object conforming to this\n * interface.\n *\n * The original function returns a boolean and has a second parameter called\n * item that is an `out`. Both are needed and we can't just return the item\n * because it'll always be truthy. Instead, we return an object containing\n * whether the result exists (`exists`) and the result itself (`result`).\n *\n * For instance a `TryGet` prototype would look like this:\n```\nTryGetItemWithValue(val: number, item: InkListItem): TryGetResult{\n```\n *\n * On the other hand, dealing with the result can be done in the following way:\n```\nvar item = item.TryGetItemWithValue(intVal, InkListItem.Null);\nif (item.exists) {\n\tconsole.log(item.result)\n}\n```\n *\n */\nexport interface TryGetResult {\n result: T;\n exists: boolean;\n}\n\nexport function tryGetValueFromMap(\n map: Map | null,\n key: K,\n /* out */ value: V\n): TryGetResult {\n if (map === null) {\n return { result: value, exists: false };\n }\n\n let val = map.get(key);\n\n if (typeof val === \"undefined\") {\n return { result: value, exists: false };\n } else {\n return { result: val, exists: true };\n }\n}\n\nexport function tryParseInt(\n value: any,\n /* out */ defaultValue: number = 0\n): TryGetResult {\n let val = parseInt(value);\n\n if (!Number.isNaN(val)) {\n return { result: val, exists: true };\n } else {\n return { result: defaultValue, exists: false };\n }\n}\n\nexport function tryParseFloat(\n value: any,\n /* out */ defaultValue: number = 0\n): TryGetResult {\n let val = parseFloat(value);\n\n if (!Number.isNaN(val)) {\n return { result: val, exists: true };\n } else {\n return { result: defaultValue, exists: false };\n }\n}\n","import { InkObject } from \"./Object\";\nimport { Container } from \"./Container\";\n\nexport class SearchResult {\n public obj: InkObject | null = null;\n public approximate: boolean = false;\n\n get correctObj() {\n return this.approximate ? null : this.obj;\n }\n\n get container() {\n return this.obj instanceof Container ? this.obj : null;\n }\n\n public copy() {\n let searchResult = new SearchResult();\n searchResult.obj = this.obj;\n searchResult.approximate = this.approximate;\n\n return searchResult;\n }\n}\n","import { StringValue } from \"./Value\";\nimport { throwNullException } from \"./NullException\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { INamedContent } from \"./INamedContent\";\nimport { InkObject } from \"./Object\";\nimport { SearchResult } from \"./SearchResult\";\nimport { Path } from \"./Path\";\nimport { Debug } from \"./Debug\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { asINamedContentOrNull, asOrNull, asOrThrows } from \"./TypeAssertion\";\n\nexport class Container extends InkObject implements INamedContent {\n public name: string | null = null;\n\n public _content: InkObject[] = [];\n public namedContent: Map = new Map();\n\n public visitsShouldBeCounted: boolean = false;\n public turnIndexShouldBeCounted: boolean = false;\n public countingAtStartOnly: boolean = false;\n\n public _pathToFirstLeafContent: Path | null = null;\n\n get hasValidName() {\n return this.name != null && this.name.length > 0;\n }\n get content() {\n return this._content;\n }\n set content(value: InkObject[]) {\n this.AddContent(value);\n }\n get namedOnlyContent() {\n let namedOnlyContentDict: Map | null = new Map();\n\n for (let [key, value] of this.namedContent) {\n let inkObject = asOrThrows(value, InkObject);\n namedOnlyContentDict.set(key, inkObject);\n }\n\n for (let c of this.content) {\n let named = asINamedContentOrNull(c);\n if (named != null && named.hasValidName) {\n namedOnlyContentDict.delete(named.name!);\n }\n }\n\n if (namedOnlyContentDict.size == 0) namedOnlyContentDict = null;\n\n return namedOnlyContentDict;\n }\n set namedOnlyContent(value: Map | null) {\n let existingNamedOnly = this.namedOnlyContent;\n if (existingNamedOnly != null) {\n for (let [key] of existingNamedOnly) {\n this.namedContent.delete(key);\n }\n }\n\n if (value == null) return;\n\n for (let [, val] of value) {\n let named = asINamedContentOrNull(val);\n if (named != null) this.AddToNamedContentOnly(named);\n }\n }\n get countFlags(): number {\n let flags: Container.CountFlags = 0;\n if (this.visitsShouldBeCounted) flags |= Container.CountFlags.Visits;\n if (this.turnIndexShouldBeCounted) flags |= Container.CountFlags.Turns;\n if (this.countingAtStartOnly) flags |= Container.CountFlags.CountStartOnly;\n\n if (flags == Container.CountFlags.CountStartOnly) {\n flags = 0;\n }\n\n return flags;\n }\n set countFlags(value: number) {\n let flag: Container.CountFlags = value;\n if ((flag & Container.CountFlags.Visits) > 0)\n this.visitsShouldBeCounted = true;\n if ((flag & Container.CountFlags.Turns) > 0)\n this.turnIndexShouldBeCounted = true;\n if ((flag & Container.CountFlags.CountStartOnly) > 0)\n this.countingAtStartOnly = true;\n }\n get pathToFirstLeafContent() {\n if (this._pathToFirstLeafContent == null)\n this._pathToFirstLeafContent = this.path.PathByAppendingPath(\n this.internalPathToFirstLeafContent\n );\n\n return this._pathToFirstLeafContent;\n }\n get internalPathToFirstLeafContent() {\n let components: Path.Component[] = [];\n let container: Container = this;\n while (container instanceof Container) {\n if (container.content.length > 0) {\n components.push(new Path.Component(0));\n container = container.content[0] as Container;\n }\n }\n return new Path(components);\n }\n\n public AddContent(contentObjOrList: InkObject | InkObject[]) {\n if (contentObjOrList instanceof Array) {\n let contentList = contentObjOrList as InkObject[];\n\n for (let c of contentList) {\n this.AddContent(c);\n }\n } else {\n let contentObj = contentObjOrList as InkObject;\n\n this._content.push(contentObj);\n\n if (contentObj.parent) {\n throw new Error(\"content is already in \" + contentObj.parent);\n }\n\n contentObj.parent = this;\n\n this.TryAddNamedContent(contentObj);\n }\n }\n public TryAddNamedContent(contentObj: InkObject) {\n let namedContentObj = asINamedContentOrNull(contentObj);\n if (namedContentObj != null && namedContentObj.hasValidName) {\n this.AddToNamedContentOnly(namedContentObj);\n }\n }\n public AddToNamedContentOnly(namedContentObj: INamedContent) {\n Debug.AssertType(\n namedContentObj,\n InkObject,\n \"Can only add Runtime.Objects to a Runtime.Container\"\n );\n let runtimeObj = asOrThrows(namedContentObj, InkObject);\n runtimeObj.parent = this;\n\n if (namedContentObj.name === null)\n return throwNullException(\"namedContentObj.name\");\n this.namedContent.set(namedContentObj.name!, namedContentObj);\n }\n public ContentAtPath(\n path: Path,\n partialPathStart: number = 0,\n partialPathLength: number = -1\n ) {\n if (partialPathLength == -1) partialPathLength = path.length;\n\n let result = new SearchResult();\n result.approximate = false;\n\n let currentContainer: Container | null = this;\n let currentObj: InkObject = this;\n\n for (let i = partialPathStart; i < partialPathLength; ++i) {\n let comp = path.GetComponent(i);\n if (currentContainer == null) {\n result.approximate = true;\n break;\n }\n\n let foundObj: InkObject | null =\n currentContainer.ContentWithPathComponent(comp);\n\n if (foundObj == null) {\n result.approximate = true;\n break;\n }\n\n currentObj = foundObj;\n currentContainer = asOrNull(foundObj, Container);\n }\n\n result.obj = currentObj;\n\n return result;\n }\n public InsertContent(contentObj: InkObject, index: number) {\n this.content.splice(index, 0, contentObj);\n\n if (contentObj.parent) {\n throw new Error(\"content is already in \" + contentObj.parent);\n }\n\n contentObj.parent = this;\n\n this.TryAddNamedContent(contentObj);\n }\n public AddContentsOfContainer(otherContainer: Container) {\n this.content.push(...otherContainer.content);\n\n for (let obj of otherContainer.content) {\n obj.parent = this;\n this.TryAddNamedContent(obj);\n }\n }\n public ContentWithPathComponent(component: Path.Component): InkObject | null {\n if (component.isIndex) {\n if (component.index >= 0 && component.index < this.content.length) {\n return this.content[component.index];\n } else {\n return null;\n }\n } else if (component.isParent) {\n return this.parent;\n } else {\n if (component.name === null) {\n return throwNullException(\"component.name\");\n }\n let foundContent = tryGetValueFromMap(\n this.namedContent,\n component.name,\n null\n );\n if (foundContent.exists) {\n return asOrThrows(foundContent.result, InkObject);\n } else {\n return null;\n }\n }\n }\n public BuildStringOfHierarchy(): string;\n public BuildStringOfHierarchy(\n sb: StringBuilder,\n indentation: number,\n pointedObj: InkObject | null\n ): string;\n public BuildStringOfHierarchy() {\n let sb: StringBuilder;\n if (arguments.length == 0) {\n sb = new StringBuilder();\n this.BuildStringOfHierarchy(sb, 0, null);\n return sb.toString();\n }\n\n sb = arguments[0] as StringBuilder;\n let indentation = arguments[1] as number;\n let pointedObj = arguments[2] as InkObject | null;\n\n function appendIndentation() {\n const spacesPerIndent = 4; // Truly const in the original code\n for (let i = 0; i < spacesPerIndent * indentation; ++i) {\n sb.Append(\" \");\n }\n }\n\n appendIndentation();\n sb.Append(\"[\");\n\n if (this.hasValidName) {\n sb.AppendFormat(\" ({0})\", this.name);\n }\n\n if (this == pointedObj) {\n sb.Append(\" <---\");\n }\n\n sb.AppendLine();\n\n indentation++;\n\n for (let i = 0; i < this.content.length; ++i) {\n let obj = this.content[i];\n\n if (obj instanceof Container) {\n let container = obj as Container;\n\n container.BuildStringOfHierarchy(sb, indentation, pointedObj);\n } else {\n appendIndentation();\n if (obj instanceof StringValue) {\n sb.Append('\"');\n sb.Append(obj.toString().replace(\"\\n\", \"\\\\n\"));\n sb.Append('\"');\n } else {\n sb.Append(obj.toString());\n }\n }\n\n if (i != this.content.length - 1) {\n sb.Append(\",\");\n }\n\n if (!(obj instanceof Container) && obj == pointedObj) {\n sb.Append(\" <---\");\n }\n\n sb.AppendLine();\n }\n\n let onlyNamed: Map = new Map();\n\n for (let [key, value] of this.namedContent) {\n if (this.content.indexOf(asOrThrows(value, InkObject)) >= 0) {\n continue;\n } else {\n onlyNamed.set(key, value);\n }\n }\n\n if (onlyNamed.size > 0) {\n appendIndentation();\n sb.AppendLine(\"-- named: --\");\n\n for (let [, value] of onlyNamed) {\n Debug.AssertType(\n value,\n Container,\n \"Can only print out named Containers\"\n );\n let container = value as Container;\n container.BuildStringOfHierarchy(sb, indentation, pointedObj);\n sb.AppendLine();\n }\n }\n\n indentation--;\n\n appendIndentation();\n sb.Append(\"]\");\n }\n}\n\nexport namespace Container {\n export enum CountFlags {\n Start = 0,\n Visits = 1,\n Turns = 2,\n CountStartOnly = 4,\n }\n}\n","import { InkObject } from \"./Object\";\n\nexport class ControlCommand extends InkObject {\n private _commandType: ControlCommand.CommandType;\n\n get commandType(): ControlCommand.CommandType {\n return this._commandType;\n }\n\n constructor(\n commandType: ControlCommand.CommandType = ControlCommand.CommandType.NotSet\n ) {\n super();\n this._commandType = commandType;\n }\n\n public Copy() {\n return new ControlCommand(this.commandType);\n }\n public static EvalStart() {\n return new ControlCommand(ControlCommand.CommandType.EvalStart);\n }\n public static EvalOutput() {\n return new ControlCommand(ControlCommand.CommandType.EvalOutput);\n }\n public static EvalEnd() {\n return new ControlCommand(ControlCommand.CommandType.EvalEnd);\n }\n public static Duplicate() {\n return new ControlCommand(ControlCommand.CommandType.Duplicate);\n }\n public static PopEvaluatedValue() {\n return new ControlCommand(ControlCommand.CommandType.PopEvaluatedValue);\n }\n public static PopFunction() {\n return new ControlCommand(ControlCommand.CommandType.PopFunction);\n }\n public static PopTunnel() {\n return new ControlCommand(ControlCommand.CommandType.PopTunnel);\n }\n public static BeginString() {\n return new ControlCommand(ControlCommand.CommandType.BeginString);\n }\n public static EndString() {\n return new ControlCommand(ControlCommand.CommandType.EndString);\n }\n public static NoOp() {\n return new ControlCommand(ControlCommand.CommandType.NoOp);\n }\n public static ChoiceCount() {\n return new ControlCommand(ControlCommand.CommandType.ChoiceCount);\n }\n public static Turns() {\n return new ControlCommand(ControlCommand.CommandType.Turns);\n }\n public static TurnsSince() {\n return new ControlCommand(ControlCommand.CommandType.TurnsSince);\n }\n public static ReadCount() {\n return new ControlCommand(ControlCommand.CommandType.ReadCount);\n }\n public static Random() {\n return new ControlCommand(ControlCommand.CommandType.Random);\n }\n public static SeedRandom() {\n return new ControlCommand(ControlCommand.CommandType.SeedRandom);\n }\n public static VisitIndex() {\n return new ControlCommand(ControlCommand.CommandType.VisitIndex);\n }\n public static SequenceShuffleIndex() {\n return new ControlCommand(ControlCommand.CommandType.SequenceShuffleIndex);\n }\n public static StartThread() {\n return new ControlCommand(ControlCommand.CommandType.StartThread);\n }\n public static Done() {\n return new ControlCommand(ControlCommand.CommandType.Done);\n }\n public static End() {\n return new ControlCommand(ControlCommand.CommandType.End);\n }\n public static ListFromInt() {\n return new ControlCommand(ControlCommand.CommandType.ListFromInt);\n }\n public static ListRange() {\n return new ControlCommand(ControlCommand.CommandType.ListRange);\n }\n public static ListRandom() {\n return new ControlCommand(ControlCommand.CommandType.ListRandom);\n }\n public static BeginTag() {\n return new ControlCommand(ControlCommand.CommandType.BeginTag);\n }\n public static EndTag() {\n return new ControlCommand(ControlCommand.CommandType.EndTag);\n }\n public toString() {\n return \"ControlCommand \" + this.commandType.toString();\n }\n}\n\nexport namespace ControlCommand {\n export enum CommandType {\n NotSet = -1,\n EvalStart, // 0\n EvalOutput, // 1\n EvalEnd, // 2\n Duplicate, // 3\n PopEvaluatedValue, // 4\n PopFunction, // 5\n PopTunnel, // 6\n BeginString, // 7\n EndString, // 8\n NoOp, // 9\n ChoiceCount, // 10\n Turns, // 11\n TurnsSince, // 12\n ReadCount, // 13\n Random, // 14\n SeedRandom, // 15\n VisitIndex, // 16\n SequenceShuffleIndex, // 17\n StartThread, // 18\n Done, // 19\n End, // 20\n ListFromInt, // 21\n ListRange, // 22\n ListRandom, // 23\n BeginTag, // 24\n EndTag, // 25\n\n TOTAL_VALUES,\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\n\nexport abstract class Expression extends ParsedObject {\n public abstract GenerateIntoContainer: (container: RuntimeContainer) => void;\n\n private _prototypeRuntimeConstantExpression: RuntimeContainer | null = null;\n public outputWhenComplete: boolean = false;\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n\n // Tell Runtime to start evaluating the following content as an expression\n container.AddContent(RuntimeControlCommand.EvalStart());\n\n this.GenerateIntoContainer(container);\n\n // Tell Runtime to output the result of the expression evaluation to the output stream\n if (this.outputWhenComplete) {\n container.AddContent(RuntimeControlCommand.EvalOutput());\n }\n\n // Tell Runtime to stop evaluating the content as an expression\n container.AddContent(RuntimeControlCommand.EvalEnd());\n\n return container;\n };\n\n // When generating the value of a constant expression,\n // we can't just keep generating the same constant expression into\n // different places where the constant value is referenced, since then\n // the same runtime objects would be used in multiple places, which\n // is impossible since each runtime object should have one parent.\n // Instead, we generate a prototype of the runtime object(s), then\n // copy them each time they're used.\n public readonly GenerateConstantIntoContainer = (\n container: RuntimeContainer\n ): void => {\n if (this._prototypeRuntimeConstantExpression === null) {\n this._prototypeRuntimeConstantExpression = new RuntimeContainer();\n this.GenerateIntoContainer(this._prototypeRuntimeConstantExpression);\n }\n\n for (const runtimeObj of this._prototypeRuntimeConstantExpression.content) {\n const copy = runtimeObj.Copy();\n if (copy) {\n container.AddContent(copy);\n }\n }\n };\n\n get typeName(): string {\n return \"Expression\";\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public Equals(obj: ParsedObject): boolean {\n return false;\n }\n\n public readonly toString = () => \"No string value in JavaScript.\";\n}\n","import { InkObject } from \"./Object\";\n\nexport class Void extends InkObject {\n public toString() {\n return \"Void\";\n }\n}\n","import { Value, ValueType, IntValue, ListValue, BoolValue } from \"./Value\";\nimport { StoryException } from \"./StoryException\";\nimport { Void } from \"./Void\";\nimport { Path } from \"./Path\";\nimport { InkList, InkListItem } from \"./InkList\";\nimport { InkObject } from \"./Object\";\nimport { asOrNull, asOrThrows, asBooleanOrThrows } from \"./TypeAssertion\";\nimport { throwNullException } from \"./NullException\";\n\ntype BinaryOp = (left: T, right: T) => any;\ntype UnaryOp = (val: T) => any;\n\nexport class NativeFunctionCall extends InkObject {\n public static readonly Add: string = \"+\";\n public static readonly Subtract: string = \"-\";\n public static readonly Divide: string = \"/\";\n public static readonly Multiply: string = \"*\";\n public static readonly Mod: string = \"%\";\n public static readonly Negate: string = \"_\";\n public static readonly Equal: string = \"==\";\n public static readonly Greater: string = \">\";\n public static readonly Less: string = \"<\";\n public static readonly GreaterThanOrEquals: string = \">=\";\n public static readonly LessThanOrEquals: string = \"<=\";\n public static readonly NotEquals: string = \"!=\";\n public static readonly Not: string = \"!\";\n public static readonly And: string = \"&&\";\n public static readonly Or: string = \"||\";\n public static readonly Min: string = \"MIN\";\n public static readonly Max: string = \"MAX\";\n public static readonly Pow: string = \"POW\";\n public static readonly Floor: string = \"FLOOR\";\n public static readonly Ceiling: string = \"CEILING\";\n public static readonly Int: string = \"INT\";\n public static readonly Float: string = \"FLOAT\";\n public static readonly Has: string = \"?\";\n public static readonly Hasnt: string = \"!?\";\n public static readonly Intersect: string = \"^\";\n public static readonly ListMin: string = \"LIST_MIN\";\n public static readonly ListMax: string = \"LIST_MAX\";\n public static readonly All: string = \"LIST_ALL\";\n public static readonly Count: string = \"LIST_COUNT\";\n public static readonly ValueOfList: string = \"LIST_VALUE\";\n public static readonly Invert: string = \"LIST_INVERT\";\n\n public static CallWithName(functionName: string) {\n return new NativeFunctionCall(functionName);\n }\n\n public static CallExistsWithName(functionName: string) {\n this.GenerateNativeFunctionsIfNecessary();\n return this._nativeFunctions!.get(functionName);\n }\n\n get name() {\n if (this._name === null)\n return throwNullException(\"NativeFunctionCall._name\");\n return this._name;\n }\n set name(value: string) {\n this._name = value;\n if (!this._isPrototype) {\n if (NativeFunctionCall._nativeFunctions === null)\n throwNullException(\"NativeFunctionCall._nativeFunctions\");\n else\n this._prototype =\n NativeFunctionCall._nativeFunctions.get(this._name) || null;\n }\n }\n public _name: string | null = null;\n\n get numberOfParameters() {\n if (this._prototype) {\n return this._prototype.numberOfParameters;\n } else {\n return this._numberOfParameters;\n }\n }\n set numberOfParameters(value: number) {\n this._numberOfParameters = value;\n }\n public _numberOfParameters: number = 0;\n\n public Call(parameters: InkObject[]): InkObject | null {\n if (this._prototype) {\n return this._prototype.Call(parameters);\n }\n\n if (this.numberOfParameters != parameters.length) {\n throw new Error(\"Unexpected number of parameters\");\n }\n\n let hasList = false;\n for (let p of parameters) {\n if (p instanceof Void)\n throw new StoryException(\n 'Attempting to perform operation on a void value. Did you forget to \"return\" a value from a function you called here?'\n );\n if (p instanceof ListValue) hasList = true;\n }\n\n if (parameters.length == 2 && hasList) {\n return this.CallBinaryListOperation(parameters);\n }\n\n let coercedParams = this.CoerceValuesToSingleType(parameters);\n let coercedType = coercedParams[0].valueType;\n\n if (coercedType == ValueType.Int) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.Float) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.String) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.DivertTarget) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.List) {\n return this.CallType(coercedParams);\n }\n\n return null;\n }\n\n public CallType string }>(\n parametersOfSingleType: Array>\n ) {\n let param1 = asOrThrows(parametersOfSingleType[0], Value);\n let valType = param1.valueType;\n\n let val1 = param1 as Value;\n\n let paramCount = parametersOfSingleType.length;\n\n if (paramCount == 2 || paramCount == 1) {\n if (this._operationFuncs === null)\n return throwNullException(\"NativeFunctionCall._operationFuncs\");\n let opForTypeObj = this._operationFuncs.get(valType);\n if (!opForTypeObj) {\n const key = ValueType[valType];\n throw new StoryException(\n \"Cannot perform operation \" + this.name + \" on \" + key\n );\n }\n\n if (paramCount == 2) {\n let param2 = asOrThrows(parametersOfSingleType[1], Value);\n\n let val2 = param2 as Value;\n\n let opForType = opForTypeObj as BinaryOp;\n\n if (val1.value === null || val2.value === null)\n return throwNullException(\"NativeFunctionCall.Call BinaryOp values\");\n let resultVal = opForType(val1.value, val2.value);\n\n return Value.Create(resultVal);\n } else {\n let opForType = opForTypeObj as UnaryOp;\n\n if (val1.value === null)\n return throwNullException(\"NativeFunctionCall.Call UnaryOp value\");\n let resultVal = opForType(val1.value);\n\n // This code is different from upstream. Since JavaScript treats\n // integers and floats as the same numbers, it's impossible\n // to force an number to be either an integer or a float.\n //\n // It can be useful to force a specific number type\n // (especially for divisions), so the result of INT() & FLOAT()\n // is coerced to the the proper value type.\n //\n // Note that we also force all other unary operation to\n // return the same value type, although this is only\n // meaningful for numbers. See `Value.Create`.\n if (this.name === NativeFunctionCall.Int) {\n return Value.Create(resultVal, ValueType.Int);\n } else if (this.name === NativeFunctionCall.Float) {\n return Value.Create(resultVal, ValueType.Float);\n } else {\n return Value.Create(resultVal, param1.valueType);\n }\n }\n } else {\n throw new Error(\n \"Unexpected number of parameters to NativeFunctionCall: \" +\n parametersOfSingleType.length\n );\n }\n }\n\n public CallBinaryListOperation(parameters: InkObject[]) {\n if (\n (this.name == \"+\" || this.name == \"-\") &&\n parameters[0] instanceof ListValue &&\n parameters[1] instanceof IntValue\n )\n return this.CallListIncrementOperation(parameters);\n\n let v1 = asOrThrows(parameters[0], Value);\n let v2 = asOrThrows(parameters[1], Value);\n\n if (\n (this.name == \"&&\" || this.name == \"||\") &&\n (v1.valueType != ValueType.List || v2.valueType != ValueType.List)\n ) {\n if (this._operationFuncs === null)\n return throwNullException(\"NativeFunctionCall._operationFuncs\");\n let op = this._operationFuncs.get(ValueType.Int) as BinaryOp;\n if (op === null)\n return throwNullException(\n \"NativeFunctionCall.CallBinaryListOperation op\"\n );\n let result = asBooleanOrThrows(\n op(v1.isTruthy ? 1 : 0, v2.isTruthy ? 1 : 0)\n );\n return new BoolValue(result);\n }\n\n if (v1.valueType == ValueType.List && v2.valueType == ValueType.List)\n return this.CallType([v1, v2]);\n\n throw new StoryException(\n \"Can not call use \" +\n this.name +\n \" operation on \" +\n ValueType[v1.valueType] +\n \" and \" +\n ValueType[v2.valueType]\n );\n }\n\n public CallListIncrementOperation(listIntParams: InkObject[]) {\n let listVal = asOrThrows(listIntParams[0], ListValue);\n let intVal = asOrThrows(listIntParams[1], IntValue);\n\n let resultInkList = new InkList();\n\n if (listVal.value === null)\n return throwNullException(\n \"NativeFunctionCall.CallListIncrementOperation listVal.value\"\n );\n for (let [listItemKey, listItemValue] of listVal.value) {\n let listItem = InkListItem.fromSerializedKey(listItemKey);\n\n if (this._operationFuncs === null)\n return throwNullException(\"NativeFunctionCall._operationFuncs\");\n let intOp = this._operationFuncs.get(ValueType.Int) as BinaryOp;\n\n if (intVal.value === null)\n return throwNullException(\n \"NativeFunctionCall.CallListIncrementOperation intVal.value\"\n );\n let targetInt = intOp(listItemValue, intVal.value);\n\n let itemOrigin = null;\n if (listVal.value.origins === null)\n return throwNullException(\n \"NativeFunctionCall.CallListIncrementOperation listVal.value.origins\"\n );\n for (let origin of listVal.value.origins) {\n if (origin.name == listItem.originName) {\n itemOrigin = origin;\n break;\n }\n }\n if (itemOrigin != null) {\n let incrementedItem = itemOrigin.TryGetItemWithValue(\n targetInt,\n InkListItem.Null\n );\n if (incrementedItem.exists)\n resultInkList.Add(incrementedItem.result, targetInt);\n }\n }\n\n return new ListValue(resultInkList);\n }\n\n public CoerceValuesToSingleType(parametersIn: InkObject[]) {\n let valType = ValueType.Int;\n\n let specialCaseList: null | ListValue = null;\n\n for (let obj of parametersIn) {\n let val = asOrThrows(obj, Value);\n if (val.valueType > valType) {\n valType = val.valueType;\n }\n\n if (val.valueType == ValueType.List) {\n specialCaseList = asOrNull(val, ListValue);\n }\n }\n\n let parametersOut = [];\n\n if (ValueType[valType] == ValueType[ValueType.List]) {\n for (let inkObjectVal of parametersIn) {\n let val = asOrThrows(inkObjectVal, Value);\n if (val.valueType == ValueType.List) {\n parametersOut.push(val);\n } else if (val.valueType == ValueType.Int) {\n let intVal = parseInt(val.valueObject);\n\n specialCaseList = asOrThrows(specialCaseList, ListValue);\n if (specialCaseList.value === null)\n return throwNullException(\n \"NativeFunctionCall.CoerceValuesToSingleType specialCaseList.value\"\n );\n let list = specialCaseList.value.originOfMaxItem;\n\n if (list === null)\n return throwNullException(\n \"NativeFunctionCall.CoerceValuesToSingleType list\"\n );\n let item = list.TryGetItemWithValue(intVal, InkListItem.Null);\n if (item.exists) {\n let castedValue = new ListValue(item.result, intVal);\n parametersOut.push(castedValue);\n } else\n throw new StoryException(\n \"Could not find List item with the value \" +\n intVal +\n \" in \" +\n list.name\n );\n } else {\n const key = ValueType[val.valueType];\n throw new StoryException(\n \"Cannot mix Lists and \" + key + \" values in this operation\"\n );\n }\n }\n } else {\n for (let inkObjectVal of parametersIn) {\n let val = asOrThrows(inkObjectVal, Value);\n let castedValue = val.Cast(valType);\n parametersOut.push(castedValue);\n }\n }\n\n return parametersOut;\n }\n\n constructor(name: string);\n constructor(name: string, numberOfParameters: number);\n constructor();\n constructor() {\n super();\n\n if (arguments.length === 0) {\n NativeFunctionCall.GenerateNativeFunctionsIfNecessary();\n } else if (arguments.length === 1) {\n let name = arguments[0];\n NativeFunctionCall.GenerateNativeFunctionsIfNecessary();\n this.name = name;\n } else if (arguments.length === 2) {\n let name = arguments[0];\n let numberOfParameters = arguments[1];\n\n this._isPrototype = true;\n this.name = name;\n this.numberOfParameters = numberOfParameters;\n }\n }\n\n public static Identity(t: T): any {\n return t;\n }\n\n public static GenerateNativeFunctionsIfNecessary() {\n if (this._nativeFunctions == null) {\n this._nativeFunctions = new Map();\n\n // Int operations\n this.AddIntBinaryOp(this.Add, (x, y) => x + y);\n this.AddIntBinaryOp(this.Subtract, (x, y) => x - y);\n this.AddIntBinaryOp(this.Multiply, (x, y) => x * y);\n this.AddIntBinaryOp(this.Divide, (x, y) => Math.floor(x / y));\n this.AddIntBinaryOp(this.Mod, (x, y) => x % y);\n this.AddIntUnaryOp(this.Negate, (x) => -x);\n\n this.AddIntBinaryOp(this.Equal, (x, y) => x == y);\n this.AddIntBinaryOp(this.Greater, (x, y) => x > y);\n this.AddIntBinaryOp(this.Less, (x, y) => x < y);\n this.AddIntBinaryOp(this.GreaterThanOrEquals, (x, y) => x >= y);\n this.AddIntBinaryOp(this.LessThanOrEquals, (x, y) => x <= y);\n this.AddIntBinaryOp(this.NotEquals, (x, y) => x != y);\n this.AddIntUnaryOp(this.Not, (x) => x == 0);\n\n this.AddIntBinaryOp(this.And, (x, y) => x != 0 && y != 0);\n this.AddIntBinaryOp(this.Or, (x, y) => x != 0 || y != 0);\n\n this.AddIntBinaryOp(this.Max, (x, y) => Math.max(x, y));\n this.AddIntBinaryOp(this.Min, (x, y) => Math.min(x, y));\n\n this.AddIntBinaryOp(this.Pow, (x, y) => Math.pow(x, y));\n this.AddIntUnaryOp(this.Floor, NativeFunctionCall.Identity);\n this.AddIntUnaryOp(this.Ceiling, NativeFunctionCall.Identity);\n this.AddIntUnaryOp(this.Int, NativeFunctionCall.Identity);\n this.AddIntUnaryOp(this.Float, (x) => x);\n\n // Float operations\n this.AddFloatBinaryOp(this.Add, (x, y) => x + y);\n this.AddFloatBinaryOp(this.Subtract, (x, y) => x - y);\n this.AddFloatBinaryOp(this.Multiply, (x, y) => x * y);\n this.AddFloatBinaryOp(this.Divide, (x, y) => x / y);\n this.AddFloatBinaryOp(this.Mod, (x, y) => x % y);\n this.AddFloatUnaryOp(this.Negate, (x) => -x);\n\n this.AddFloatBinaryOp(this.Equal, (x, y) => x == y);\n this.AddFloatBinaryOp(this.Greater, (x, y) => x > y);\n this.AddFloatBinaryOp(this.Less, (x, y) => x < y);\n this.AddFloatBinaryOp(this.GreaterThanOrEquals, (x, y) => x >= y);\n this.AddFloatBinaryOp(this.LessThanOrEquals, (x, y) => x <= y);\n this.AddFloatBinaryOp(this.NotEquals, (x, y) => x != y);\n this.AddFloatUnaryOp(this.Not, (x) => x == 0.0);\n\n this.AddFloatBinaryOp(this.And, (x, y) => x != 0.0 && y != 0.0);\n this.AddFloatBinaryOp(this.Or, (x, y) => x != 0.0 || y != 0.0);\n\n this.AddFloatBinaryOp(this.Max, (x, y) => Math.max(x, y));\n this.AddFloatBinaryOp(this.Min, (x, y) => Math.min(x, y));\n\n this.AddFloatBinaryOp(this.Pow, (x, y) => Math.pow(x, y));\n this.AddFloatUnaryOp(this.Floor, (x) => Math.floor(x));\n this.AddFloatUnaryOp(this.Ceiling, (x) => Math.ceil(x));\n this.AddFloatUnaryOp(this.Int, (x) => Math.floor(x));\n this.AddFloatUnaryOp(this.Float, NativeFunctionCall.Identity);\n\n // String operations\n this.AddStringBinaryOp(this.Add, (x, y) => x + y); // concat\n this.AddStringBinaryOp(this.Equal, (x, y) => x === y);\n this.AddStringBinaryOp(this.NotEquals, (x, y) => !(x === y));\n this.AddStringBinaryOp(this.Has, (x, y) => x.includes(y));\n this.AddStringBinaryOp(this.Hasnt, (x, y) => !x.includes(y));\n\n this.AddListBinaryOp(this.Add, (x, y) => x.Union(y));\n this.AddListBinaryOp(this.Subtract, (x, y) => x.Without(y));\n this.AddListBinaryOp(this.Has, (x, y) => x.Contains(y));\n this.AddListBinaryOp(this.Hasnt, (x, y) => !x.Contains(y));\n this.AddListBinaryOp(this.Intersect, (x, y) => x.Intersect(y));\n\n this.AddListBinaryOp(this.Equal, (x, y) => x.Equals(y));\n this.AddListBinaryOp(this.Greater, (x, y) => x.GreaterThan(y));\n this.AddListBinaryOp(this.Less, (x, y) => x.LessThan(y));\n this.AddListBinaryOp(this.GreaterThanOrEquals, (x, y) =>\n x.GreaterThanOrEquals(y)\n );\n this.AddListBinaryOp(this.LessThanOrEquals, (x, y) =>\n x.LessThanOrEquals(y)\n );\n this.AddListBinaryOp(this.NotEquals, (x, y) => !x.Equals(y));\n\n this.AddListBinaryOp(this.And, (x, y) => x.Count > 0 && y.Count > 0);\n this.AddListBinaryOp(this.Or, (x, y) => x.Count > 0 || y.Count > 0);\n\n this.AddListUnaryOp(this.Not, (x) => (x.Count == 0 ? 1 : 0));\n\n this.AddListUnaryOp(this.Invert, (x) => x.inverse);\n this.AddListUnaryOp(this.All, (x) => x.all);\n this.AddListUnaryOp(this.ListMin, (x) => x.MinAsList());\n this.AddListUnaryOp(this.ListMax, (x) => x.MaxAsList());\n this.AddListUnaryOp(this.Count, (x) => x.Count);\n this.AddListUnaryOp(this.ValueOfList, (x) => x.maxItem.Value);\n\n let divertTargetsEqual = (d1: Path, d2: Path) => d1.Equals(d2);\n let divertTargetsNotEqual = (d1: Path, d2: Path) => !d1.Equals(d2);\n this.AddOpToNativeFunc(\n this.Equal,\n 2,\n ValueType.DivertTarget,\n divertTargetsEqual\n );\n this.AddOpToNativeFunc(\n this.NotEquals,\n 2,\n ValueType.DivertTarget,\n divertTargetsNotEqual\n );\n }\n }\n\n public AddOpFuncForType(\n valType: ValueType,\n op: UnaryOp | BinaryOp\n ): void {\n if (this._operationFuncs == null) {\n this._operationFuncs = new Map();\n }\n\n this._operationFuncs.set(valType, op);\n }\n\n public static AddOpToNativeFunc(\n name: string,\n args: number,\n valType: ValueType,\n op: UnaryOp | BinaryOp\n ): void {\n if (this._nativeFunctions === null)\n return throwNullException(\"NativeFunctionCall._nativeFunctions\");\n let nativeFunc = this._nativeFunctions.get(name);\n if (!nativeFunc) {\n nativeFunc = new NativeFunctionCall(name, args);\n this._nativeFunctions.set(name, nativeFunc);\n }\n\n nativeFunc.AddOpFuncForType(valType, op);\n }\n\n public static AddIntBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.Int, op);\n }\n public static AddIntUnaryOp(name: string, op: UnaryOp) {\n this.AddOpToNativeFunc(name, 1, ValueType.Int, op);\n }\n\n public static AddFloatBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.Float, op);\n }\n public static AddFloatUnaryOp(name: string, op: UnaryOp) {\n this.AddOpToNativeFunc(name, 1, ValueType.Float, op);\n }\n\n public static AddStringBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.String, op);\n }\n\n public static AddListBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.List, op);\n }\n public static AddListUnaryOp(name: string, op: UnaryOp) {\n this.AddOpToNativeFunc(name, 1, ValueType.List, op);\n }\n\n public toString() {\n return 'Native \"' + this.name + '\"';\n }\n\n public _prototype: NativeFunctionCall | null = null;\n public _isPrototype: boolean = false;\n public _operationFuncs: Map | UnaryOp> | null =\n null;\n public static _nativeFunctions: Map | null = null;\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"./Expression\";\nimport { BoolValue, FloatValue, IntValue } from \"../../../../engine/Value\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\nimport { ParsedObject } from \"../Object\";\n\n// This class is named Number in the C# codebase\n// but this conflict with the built-in Number class\nexport class NumberExpression extends Expression {\n public value: number | boolean;\n public subtype: \"int\" | \"float\" | \"bool\";\n\n constructor(value: number | boolean, subtype: \"int\" | \"float\" | \"bool\") {\n super();\n\n if (\n (typeof value === \"number\" && !Number.isNaN(value)) ||\n typeof value == \"boolean\"\n ) {\n this.value = value;\n this.subtype = subtype;\n } else {\n throw new Error(\"Unexpected object type in NumberExpression.\");\n }\n }\n\n get typeName(): string {\n return \"Number\";\n }\n\n public isInt = (): boolean => this.subtype == \"int\";\n\n public isFloat = (): boolean => this.subtype == \"float\";\n\n public isBool = (): boolean => this.subtype == \"bool\";\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n if (this.isInt()) {\n container.AddContent(new IntValue(this.value as number));\n } else if (this.isFloat()) {\n container.AddContent(new FloatValue(this.value as number));\n } else if (this.isBool()) {\n container.AddContent(new BoolValue(this.value as boolean));\n }\n };\n\n public readonly toString = (): string => String(this.value);\n\n public Equals(obj: ParsedObject): boolean {\n const numberExpression = asOrNull(obj, NumberExpression);\n if (!numberExpression) return false;\n\n return (\n numberExpression.subtype == this.subtype &&\n numberExpression.value == this.value\n );\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"./Expression\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\nimport { NumberExpression } from \"./NumberExpression\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class UnaryExpression extends Expression {\n get nativeNameForOp(): string {\n // Replace \"-\" with \"_\" to make it unique (compared to subtraction)\n if (this.op === \"-\") {\n return \"_\";\n } else if (this.op === \"not\") {\n return \"!\";\n }\n\n return this.op;\n }\n\n public innerExpression: Expression;\n\n // Attempt to flatten inner expression immediately\n // e.g. convert (-(5)) into (-5)\n public static readonly WithInner = (\n inner: Expression,\n op: string\n ): Expression => {\n const innerNumber = asOrNull(inner, NumberExpression);\n\n if (innerNumber) {\n if (op === \"-\") {\n if (innerNumber.isInt()) {\n return new NumberExpression(-innerNumber.value, \"int\");\n } else if (innerNumber.isFloat()) {\n return new NumberExpression(-innerNumber.value, \"float\");\n }\n } else if (op == \"!\" || op == \"not\") {\n if (innerNumber.isInt()) {\n return new NumberExpression(innerNumber.value == 0, \"bool\");\n } else if (innerNumber.isFloat()) {\n return new NumberExpression(innerNumber.value == 0.0, \"bool\");\n } else if (innerNumber.isBool()) {\n return new NumberExpression(!innerNumber.value, \"bool\");\n }\n }\n\n throw new Error(\"Unexpected operation or number type\");\n }\n\n // Normal fallback\n const unary = new UnaryExpression(inner, op);\n\n return unary;\n };\n\n constructor(\n inner: Expression,\n public readonly op: string\n ) {\n super();\n\n this.innerExpression = this.AddContent(inner) as Expression;\n }\n\n get typeName(): string {\n return \"UnaryExpression\";\n }\n\n public readonly GenerateIntoContainer = (container: RuntimeContainer) => {\n this.innerExpression.GenerateIntoContainer(container);\n container.AddContent(NativeFunctionCall.CallWithName(this.nativeNameForOp));\n };\n\n public readonly toString = (): string =>\n this.nativeNameForOp + this.innerExpression;\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"./Expression\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\nimport { Story } from \"../Story\";\nimport { UnaryExpression } from \"./UnaryExpression\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class BinaryExpression extends Expression {\n public readonly leftExpression: Expression;\n public readonly rightExpression: Expression;\n\n constructor(\n left: Expression,\n right: Expression,\n public opName: string\n ) {\n super();\n\n this.leftExpression = this.AddContent(left) as Expression;\n this.rightExpression = this.AddContent(right) as Expression;\n\n this.opName = opName;\n }\n\n get typeName(): string {\n return \"BinaryExpression\";\n }\n\n public readonly GenerateIntoContainer = (container: RuntimeContainer) => {\n this.leftExpression.GenerateIntoContainer(container);\n this.rightExpression.GenerateIntoContainer(container);\n this.opName = this.NativeNameForOp(this.opName);\n container.AddContent(NativeFunctionCall.CallWithName(this.opName));\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n // Check for the following case:\n //\n // (not A) ? B\n //\n // Since this easy to accidentally do:\n //\n // not A ? B\n //\n // when you intend:\n //\n // not (A ? B)\n if (this.NativeNameForOp(this.opName) === \"?\") {\n const leftUnary = asOrNull(this.leftExpression, UnaryExpression);\n if (\n leftUnary !== null &&\n (leftUnary.op === \"not\" || leftUnary.op === \"!\")\n ) {\n this.Error(\n `Using 'not' or '!' here negates '${leftUnary.innerExpression}' rather than the result of the '?' or 'has' operator. You need to add parentheses around the (A ? B) expression.`\n );\n }\n }\n }\n\n public readonly NativeNameForOp = (opName: string): string => {\n if (opName === \"and\") {\n return \"&&\";\n } else if (opName === \"or\") {\n return \"||\";\n } else if (opName === \"mod\") {\n return \"%\";\n } else if (opName === \"has\") {\n return \"?\";\n } else if (opName === \"hasnt\") {\n return \"!?\";\n }\n\n return opName;\n };\n\n public readonly toString = (): string =>\n `(${this.leftExpression} ${this.opName} ${this.rightExpression})`;\n}\n","export class CharacterSet {\n public static readonly FromRange = (\n start: string,\n end: string\n ): CharacterSet => new CharacterSet().AddRange(start, end);\n\n public set: Set = new Set();\n\n constructor(arg?: string | string[] | CharacterSet) {\n if (arg) {\n this.AddCharacters(arg);\n }\n }\n\n public readonly Add = (arg: string) => this.set.add(arg);\n\n public readonly AddRange = (start: string, end: string): CharacterSet => {\n for (let c = start.charCodeAt(0); c <= end.charCodeAt(0); ++c) {\n this.Add(String.fromCharCode(c));\n }\n\n return this;\n };\n\n public readonly AddCharacters = (\n chars: string | string[] | CharacterSet\n ): CharacterSet => {\n if (typeof chars === \"string\" || Array.isArray(chars)) {\n for (const c of chars) {\n this.Add(c);\n }\n } else {\n for (const c of chars.set) {\n this.Add(c);\n }\n }\n\n return this;\n };\n}\n","import { CharacterSet } from \"./CharacterSet\";\n\n/// \n/// A class representing a character range. Allows for lazy-loading a corresponding character set.\n/// \nexport class CharacterRange {\n public static Define = (\n start: string,\n end: string,\n excludes: string[] | CharacterSet = []\n ): CharacterRange => new CharacterRange(start, end, excludes);\n\n private _correspondingCharSet: CharacterSet = new CharacterSet();\n private _excludes = new Set();\n\n constructor(\n private _start: string,\n private _end: string,\n excludes: string[] | CharacterSet = []\n ) {\n if (excludes instanceof CharacterSet) {\n this._excludes = excludes.set;\n } else {\n for (const item of excludes) {\n this._excludes.add(item);\n }\n }\n }\n\n get start(): string {\n return this._start;\n }\n\n get end(): string {\n return this._end;\n }\n\n /// \n /// Returns a character set instance corresponding to the character range\n /// represented by the current instance.\n /// \n /// \n /// The internal character set is created once and cached in memory.\n /// \n /// The char set.\n public readonly ToCharacterSet = (): CharacterSet => {\n if (this._correspondingCharSet.set.size === 0) {\n for (\n let ii = this.start.charCodeAt(0), c;\n ii <= this.end.charCodeAt(0);\n ii += 1\n ) {\n c = String.fromCharCode(ii);\n if (!this._excludes.has(c)) {\n this._correspondingCharSet.AddCharacters(c);\n }\n }\n }\n\n return this._correspondingCharSet;\n };\n}\n","import { InkObject } from \"./Object\";\nimport { Path } from \"./Path\";\nimport { Container } from \"./Container\";\nimport { throwNullException } from \"./NullException\";\n\nexport class ChoicePoint extends InkObject {\n public _pathOnChoice: Path | null = null;\n public hasCondition: boolean = false;\n public hasStartContent: boolean = false;\n public hasChoiceOnlyContent: boolean = false;\n public isInvisibleDefault: boolean = false;\n public onceOnly: boolean = true;\n\n constructor(onceOnly: boolean = true) {\n super();\n this.onceOnly = onceOnly;\n }\n get pathOnChoice(): Path | null {\n if (this._pathOnChoice != null && this._pathOnChoice.isRelative) {\n let choiceTargetObj = this.choiceTarget;\n if (choiceTargetObj) {\n this._pathOnChoice = choiceTargetObj.path;\n }\n }\n return this._pathOnChoice;\n }\n set pathOnChoice(value: Path | null) {\n this._pathOnChoice = value;\n }\n get choiceTarget(): Container | null {\n if (this._pathOnChoice === null)\n return throwNullException(\"ChoicePoint._pathOnChoice\");\n return this.ResolvePath(this._pathOnChoice).container;\n }\n get pathStringOnChoice(): string {\n if (this.pathOnChoice === null)\n return throwNullException(\"ChoicePoint.pathOnChoice\");\n return this.CompactPathString(this.pathOnChoice);\n }\n set pathStringOnChoice(value: string) {\n this.pathOnChoice = new Path(value);\n }\n get flags(): number {\n let flags = 0;\n if (this.hasCondition) flags |= 1;\n if (this.hasStartContent) flags |= 2;\n if (this.hasChoiceOnlyContent) flags |= 4;\n if (this.isInvisibleDefault) flags |= 8;\n if (this.onceOnly) flags |= 16;\n return flags;\n }\n set flags(value: number) {\n this.hasCondition = (value & 1) > 0;\n this.hasStartContent = (value & 2) > 0;\n this.hasChoiceOnlyContent = (value & 4) > 0;\n this.isInvisibleDefault = (value & 8) > 0;\n this.onceOnly = (value & 16) > 0;\n }\n public toString(): string {\n if (this.pathOnChoice === null)\n return throwNullException(\"ChoicePoint.pathOnChoice\");\n // int? targetLineNum = DebugLineNumberOfPath (pathOnChoice);\n let targetLineNum = null;\n let targetString = this.pathOnChoice.toString();\n\n if (targetLineNum != null) {\n targetString = \" line \" + targetLineNum + \"(\" + targetString + \")\";\n }\n\n return \"Choice: -> \" + targetString;\n }\n}\n","import { Path } from \"./Path\";\nimport { Container } from \"./Container\";\nimport { InkObject } from \"./Object\";\n\nexport class Pointer {\n public container: Container | null = null;\n public index: number = -1;\n\n constructor();\n constructor(container: Container | null, index: number);\n constructor() {\n if (arguments.length === 2) {\n this.container = arguments[0];\n this.index = arguments[1];\n }\n }\n\n public Resolve(): InkObject | null {\n if (this.index < 0) return this.container;\n if (this.container == null) return null;\n if (this.container.content.length == 0) return this.container;\n if (this.index >= this.container.content.length) return null;\n\n return this.container.content[this.index];\n }\n\n get isNull(): boolean {\n return this.container == null;\n }\n\n get path(): Path | null {\n if (this.isNull) return null;\n\n if (this.index >= 0)\n return this.container!.path.PathByAppendingComponent(\n new Path.Component(this.index)\n );\n else return this.container!.path;\n }\n\n public toString(): string {\n if (!this.container) return \"Ink Pointer (null)\";\n\n return (\n \"Ink Pointer -> \" +\n this.container.path.toString() +\n \" -- index \" +\n this.index\n );\n }\n\n // This method does not exist in the original C# code, but is here to maintain the\n // value semantics of Pointer.\n public copy(): Pointer {\n return new Pointer(this.container, this.index);\n }\n\n public static StartOf(container: Container | null): Pointer {\n return new Pointer(container, 0);\n }\n\n public static get Null(): Pointer {\n return new Pointer(null, -1);\n }\n}\n","import { Path } from \"./Path\";\nimport { PushPopType } from \"./PushPop\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { InkObject } from \"./Object\";\nimport { Pointer } from \"./Pointer\";\nimport { Container } from \"./Container\";\nimport { throwNullException } from \"./NullException\";\n\nexport class Divert extends InkObject {\n get targetPath() {\n if (this._targetPath != null && this._targetPath.isRelative) {\n let targetObj = this.targetPointer.Resolve();\n if (targetObj) {\n this._targetPath = targetObj.path;\n }\n }\n\n return this._targetPath;\n }\n set targetPath(value: Path | null) {\n this._targetPath = value;\n this._targetPointer = Pointer.Null;\n }\n\n public _targetPath: Path | null = null;\n\n get targetPointer() {\n if (this._targetPointer.isNull) {\n let targetObj = this.ResolvePath(this._targetPath).obj;\n\n if (this._targetPath === null)\n return throwNullException(\"this._targetPath\");\n if (this._targetPath.lastComponent === null)\n return throwNullException(\"this._targetPath.lastComponent\");\n\n if (this._targetPath.lastComponent.isIndex) {\n if (targetObj === null) return throwNullException(\"targetObj\");\n this._targetPointer.container =\n targetObj.parent instanceof Container ? targetObj.parent : null;\n this._targetPointer.index = this._targetPath.lastComponent.index;\n } else {\n this._targetPointer = Pointer.StartOf(\n targetObj instanceof Container ? targetObj : null\n );\n }\n }\n\n return this._targetPointer.copy();\n }\n\n public _targetPointer: Pointer = Pointer.Null;\n\n get targetPathString() {\n if (this.targetPath == null) return null;\n\n return this.CompactPathString(this.targetPath);\n }\n set targetPathString(value: string | null) {\n if (value == null) {\n this.targetPath = null;\n } else {\n this.targetPath = new Path(value);\n }\n }\n\n public variableDivertName: string | null = null;\n get hasVariableTarget() {\n return this.variableDivertName != null;\n }\n\n public pushesToStack: boolean = false;\n public stackPushType: PushPopType = 0;\n\n public isExternal: boolean = false;\n public externalArgs: number = 0;\n\n public isConditional: boolean = false;\n\n constructor(stackPushType?: PushPopType) {\n super();\n this.pushesToStack = false;\n\n if (typeof stackPushType !== \"undefined\") {\n this.pushesToStack = true;\n this.stackPushType = stackPushType;\n }\n }\n\n public Equals(obj: Divert | null) {\n let otherDivert = obj;\n if (otherDivert instanceof Divert) {\n if (this.hasVariableTarget == otherDivert.hasVariableTarget) {\n if (this.hasVariableTarget) {\n return this.variableDivertName == otherDivert.variableDivertName;\n } else {\n if (this.targetPath === null)\n return throwNullException(\"this.targetPath\");\n return this.targetPath.Equals(otherDivert.targetPath);\n }\n }\n }\n return false;\n }\n\n public toString() {\n if (this.hasVariableTarget) {\n return \"Divert(variable: \" + this.variableDivertName + \")\";\n } else if (this.targetPath == null) {\n return \"Divert(null)\";\n } else {\n let sb = new StringBuilder();\n\n let targetStr = this.targetPath.toString();\n // int? targetLineNum = DebugLineNumberOfPath (targetPath);\n let targetLineNum = null;\n if (targetLineNum != null) {\n targetStr = \"line \" + targetLineNum;\n }\n\n sb.Append(\"Divert\");\n\n if (this.isConditional) sb.Append(\"?\");\n\n if (this.pushesToStack) {\n if (this.stackPushType == PushPopType.Function) {\n sb.Append(\" function\");\n } else {\n sb.Append(\" tunnel\");\n }\n }\n\n sb.Append(\" -> \");\n sb.Append(this.targetPathString);\n\n sb.Append(\" (\");\n sb.Append(targetStr);\n sb.Append(\")\");\n\n return sb.toString();\n }\n }\n}\n","export enum SymbolType {\n Knot = 0,\n List = 1,\n ListItem = 2,\n Var = 3,\n SubFlowAndWeave = 4,\n Arg = 5,\n Temp = 6,\n}\n","import { InkObject } from \"./Object\";\n\nexport class VariableAssignment extends InkObject {\n public readonly variableName: string | null;\n public readonly isNewDeclaration: boolean;\n public isGlobal: boolean;\n\n constructor(variableName: string | null, isNewDeclaration: boolean) {\n super();\n this.variableName = variableName || null;\n this.isNewDeclaration = !!isNewDeclaration;\n this.isGlobal = false;\n }\n\n public toString(): string {\n return \"VarAssign to \" + this.variableName;\n }\n}\n","import { ChoicePoint } from \"../../../engine/ChoicePoint\";\nimport { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ContentList } from \"./ContentList\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../engine/ControlCommand\";\nimport { Divert as RuntimeDivert } from \"../../../engine/Divert\";\nimport { DivertTargetValue } from \"../../../engine/Value\";\nimport { INamedContent } from \"../../../engine/INamedContent\";\nimport { IWeavePoint } from \"./IWeavePoint\";\nimport { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Path as RuntimePath } from \"../../../engine/Path\";\nimport { Story } from \"./Story\";\nimport { SymbolType } from \"./SymbolType\";\nimport { VariableAssignment as RuntimeVariableAssignment } from \"../../../engine/VariableAssignment\";\nimport { Expression } from \"./Expression/Expression\";\nimport { Identifier } from \"./Identifier\";\n\nexport class Choice extends ParsedObject implements IWeavePoint, INamedContent {\n private _condition: Expression | null = null;\n private _innerContentContainer: RuntimeContainer | null = null;\n private _outerContainer: RuntimeContainer | null = null;\n private _runtimeChoice: ChoicePoint | null = null;\n get runtimeChoice(): ChoicePoint {\n if (!this._runtimeChoice) {\n throw new Error();\n }\n\n return this._runtimeChoice;\n }\n\n private _returnToR1: DivertTargetValue | null = null;\n private _returnToR2: DivertTargetValue | null = null;\n private _r1Label: RuntimeContainer | null = null;\n private _r2Label: RuntimeContainer | null = null;\n private _divertToStartContentOuter: RuntimeDivert | null = null;\n private _divertToStartContentInner: RuntimeDivert | null = null;\n private _startContentRuntimeContainer: RuntimeContainer | null = null;\n\n public startContent: ContentList;\n public choiceOnlyContent: ContentList;\n public innerContent: ContentList;\n public identifier?: Identifier;\n get name() {\n return this.identifier?.name || null;\n }\n public onceOnly: boolean;\n public isInvisibleDefault: boolean = false;\n public indentationDepth: number;\n public hasWeaveStyleInlineBrackets: boolean = false;\n\n get condition() {\n return this._condition;\n }\n\n set condition(value) {\n this._condition = value;\n if (value) {\n this.AddContent(value as ParsedObject);\n }\n }\n\n // Required for IWeavePoint interface\n // Choice's target container. Used by weave to append any extra\n // nested weave content into.\n get runtimeContainer() {\n return this._innerContentContainer;\n }\n\n get innerContentContainer() {\n return this._innerContentContainer;\n }\n\n get containerForCounting() {\n return this._innerContentContainer;\n }\n\n // Override runtimePath to point to the Choice's target content (after it's chosen),\n // as opposed to the default implementation which would point to the choice itself\n // (or it's outer container), which is what runtimeObject is.\n get runtimePath(): RuntimePath {\n if (!this.innerContentContainer || !this.innerContentContainer.path) {\n throw new Error();\n }\n\n return this.innerContentContainer.path;\n }\n\n constructor(\n startContent: ContentList,\n choiceOnlyContent: ContentList,\n innerContent: ContentList\n ) {\n super();\n\n this.startContent = startContent;\n this.choiceOnlyContent = choiceOnlyContent;\n this.innerContent = innerContent;\n this.indentationDepth = 1;\n\n if (startContent) {\n this.AddContent(this.startContent);\n }\n\n if (choiceOnlyContent) {\n this.AddContent(this.choiceOnlyContent);\n }\n\n if (innerContent) {\n this.AddContent(this.innerContent);\n }\n\n this.onceOnly = true; // default\n }\n\n get typeName(): string {\n return \"Choice\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n this._outerContainer = new RuntimeContainer();\n\n // Content names for different types of choice:\n // * start content [choice only content] inner content\n // * start content -> divert\n // * start content\n // * [choice only content]\n\n // Hmm, this structure has become slightly insane!\n //\n // [\n // EvalStart\n // assign $r = $r1 -- return target = return label 1\n // BeginString\n // -> s\n // [(r1)] -- return label 1 (after start content)\n // EndString\n // BeginString\n // ... choice only content\n // EndEval\n // Condition expression\n // choice: -> \"c-0\"\n // (s) = [\n // start content\n // -> r -- goto return label 1 or 2\n // ]\n // ]\n //\n // in parent's container: (the inner content for the choice)\n //\n // (c-0) = [\n // EvalStart\n // assign $r = $r2 -- return target = return label 2\n // EndEval\n // -> s\n // [(r2)] -- return label 1 (after start content)\n // inner content\n // ]\n //\n\n this._runtimeChoice = new ChoicePoint(this.onceOnly);\n this._runtimeChoice.isInvisibleDefault = this.isInvisibleDefault;\n\n if (this.startContent || this.choiceOnlyContent || this.condition) {\n this._outerContainer.AddContent(RuntimeControlCommand.EvalStart());\n }\n\n // Start content is put into a named container that's referenced both\n // when displaying the choice initially, and when generating the text\n // when the choice is chosen.\n if (this.startContent) {\n // Generate start content and return\n // - We can't use a function since it uses a call stack element, which would\n // put temporary values out of scope. Instead we manually divert around.\n // - $r is a variable divert target contains the return point\n this._returnToR1 = new DivertTargetValue();\n this._outerContainer.AddContent(this._returnToR1);\n\n const varAssign = new RuntimeVariableAssignment(\"$r\", true);\n this._outerContainer.AddContent(varAssign);\n\n // Mark the start of the choice text generation, so that the runtime\n // knows where to rewind to to extract the content from the output stream.\n this._outerContainer.AddContent(RuntimeControlCommand.BeginString());\n\n this._divertToStartContentOuter = new RuntimeDivert();\n this._outerContainer.AddContent(this._divertToStartContentOuter);\n\n // Start content itself in a named container\n this._startContentRuntimeContainer =\n this.startContent.GenerateRuntimeObject() as RuntimeContainer;\n this._startContentRuntimeContainer.name = \"s\";\n\n // Effectively, the \"return\" statement - return to the point specified by $r\n const varDivert = new RuntimeDivert();\n varDivert.variableDivertName = \"$r\";\n this._startContentRuntimeContainer.AddContent(varDivert);\n\n // Add the container\n this._outerContainer.AddToNamedContentOnly(\n this._startContentRuntimeContainer\n );\n\n // This is the label to return to\n this._r1Label = new RuntimeContainer();\n this._r1Label.name = \"$r1\";\n this._outerContainer.AddContent(this._r1Label);\n\n this._outerContainer.AddContent(RuntimeControlCommand.EndString());\n\n this._runtimeChoice.hasStartContent = true;\n }\n\n // Choice only content - mark the start, then generate it directly into the outer container\n if (this.choiceOnlyContent) {\n this._outerContainer.AddContent(RuntimeControlCommand.BeginString());\n\n const choiceOnlyRuntimeContent =\n this.choiceOnlyContent.GenerateRuntimeObject() as RuntimeContainer;\n this._outerContainer.AddContentsOfContainer(choiceOnlyRuntimeContent);\n\n this._outerContainer.AddContent(RuntimeControlCommand.EndString());\n\n this._runtimeChoice.hasChoiceOnlyContent = true;\n }\n\n // Generate any condition for this choice\n if (this.condition) {\n this.condition.GenerateIntoContainer(this._outerContainer);\n this._runtimeChoice.hasCondition = true;\n }\n\n if (this.startContent || this.choiceOnlyContent || this.condition) {\n this._outerContainer.AddContent(RuntimeControlCommand.EvalEnd());\n }\n\n // Add choice itself\n this._outerContainer.AddContent(this._runtimeChoice);\n\n // Container that choice points to for when it's chosen\n this._innerContentContainer = new RuntimeContainer();\n\n // Repeat start content by diverting to its container\n if (this.startContent) {\n // Set the return point when jumping back into the start content\n // - In this case, it's the $r2 point, within the choice content \"c\".\n this._returnToR2 = new DivertTargetValue();\n this._innerContentContainer.AddContent(RuntimeControlCommand.EvalStart());\n this._innerContentContainer.AddContent(this._returnToR2);\n this._innerContentContainer.AddContent(RuntimeControlCommand.EvalEnd());\n const varAssign = new RuntimeVariableAssignment(\"$r\", true);\n this._innerContentContainer.AddContent(varAssign);\n\n // Main divert into start content\n this._divertToStartContentInner = new RuntimeDivert();\n this._innerContentContainer.AddContent(this._divertToStartContentInner);\n\n // Define label to return to\n this._r2Label = new RuntimeContainer();\n this._r2Label.name = \"$r2\";\n this._innerContentContainer.AddContent(this._r2Label);\n }\n\n // Choice's own inner content\n if (this.innerContent) {\n const innerChoiceOnlyContent =\n this.innerContent.GenerateRuntimeObject() as RuntimeContainer;\n this._innerContentContainer.AddContentsOfContainer(\n innerChoiceOnlyContent\n );\n }\n\n if (this.story.countAllVisits) {\n this._innerContentContainer.visitsShouldBeCounted = true;\n }\n\n this._innerContentContainer.countingAtStartOnly = true;\n\n return this._outerContainer;\n };\n\n public ResolveReferences(context: Story): void {\n // Weave style choice - target own content container\n if (this._innerContentContainer) {\n this.runtimeChoice.pathOnChoice = this._innerContentContainer.path;\n\n if (this.onceOnly) {\n this._innerContentContainer.visitsShouldBeCounted = true;\n }\n }\n\n if (this._returnToR1) {\n if (!this._r1Label) {\n throw new Error();\n }\n\n this._returnToR1.targetPath = this._r1Label.path;\n }\n\n if (this._returnToR2) {\n if (!this._r2Label) {\n throw new Error();\n }\n\n this._returnToR2.targetPath = this._r2Label.path;\n }\n\n if (this._divertToStartContentOuter) {\n if (!this._startContentRuntimeContainer) {\n throw new Error();\n }\n\n this._divertToStartContentOuter.targetPath =\n this._startContentRuntimeContainer.path;\n }\n\n if (this._divertToStartContentInner) {\n if (!this._startContentRuntimeContainer) {\n throw new Error();\n }\n\n this._divertToStartContentInner.targetPath =\n this._startContentRuntimeContainer.path;\n }\n\n super.ResolveReferences(context);\n\n if (this.identifier && (this.identifier?.name || \"\").length > 0) {\n context.CheckForNamingCollisions(\n this as ParsedObject,\n this.identifier,\n SymbolType.SubFlowAndWeave\n );\n }\n }\n\n public readonly toString = () => {\n if (this.choiceOnlyContent !== null) {\n return `* ${this.startContent}[${this.choiceOnlyContent}]...`;\n }\n\n return `* ${this.startContent}...`;\n };\n}\n","export class StringParserElement {\n public static _uniqueIdCounter: number = 1000;\n\n public characterIndex: number = 0;\n public characterInLineIndex: number = 0;\n public lineIndex: number = 0;\n public reportedErrorInScope: boolean = false;\n public uniqueId: number = 0;\n public customFlags: number = 0;\n\n public readonly CopyFrom = (fromElement: StringParserElement): void => {\n StringParserElement._uniqueIdCounter++;\n this.uniqueId = StringParserElement._uniqueIdCounter;\n this.characterIndex = fromElement.characterIndex;\n this.characterInLineIndex = fromElement.characterInLineIndex;\n this.lineIndex = fromElement.lineIndex;\n this.customFlags = fromElement.customFlags;\n this.reportedErrorInScope = false;\n };\n\n // Squash is used when succeeding from a rule,\n // so only the state information we wanted to carry forward is\n // retained. e.g. characterIndex and lineIndex are global,\n // however uniqueId is specific to the individual rule,\n // and likewise, custom flags are designed for the temporary\n // state of the individual rule too.\n public readonly SquashFrom = (fromElement: StringParserElement): void => {\n this.characterIndex = fromElement.characterIndex;\n this.characterInLineIndex = fromElement.characterInLineIndex;\n this.lineIndex = fromElement.lineIndex;\n this.reportedErrorInScope = fromElement.reportedErrorInScope;\n this.customFlags = fromElement.customFlags;\n };\n}\n","import { StringParserElement } from \"./StringParserElement\";\n\nexport class StringParserState {\n private _stack: StringParserElement[] = [];\n private _numElements: number = 0;\n\n get currentElement(): StringParserElement {\n return this._stack[this._numElements - 1];\n }\n\n get lineIndex(): number {\n return this.currentElement.lineIndex;\n }\n\n set lineIndex(value: number) {\n this.currentElement.lineIndex = value;\n }\n\n get characterIndex(): number {\n return this.currentElement.characterIndex;\n }\n\n set characterIndex(value: number) {\n this.currentElement.characterIndex = value;\n }\n\n get characterInLineIndex(): number {\n return this.currentElement.characterInLineIndex;\n }\n\n set characterInLineIndex(value: number) {\n this.currentElement.characterInLineIndex = value;\n }\n\n get customFlags(): number {\n return this.currentElement.customFlags;\n }\n\n set customFlags(value: number) {\n this.currentElement.customFlags = value;\n }\n\n get errorReportedAlreadyInScope(): boolean {\n return this.currentElement.reportedErrorInScope;\n }\n\n get stackHeight(): number {\n return this._numElements;\n }\n\n constructor() {\n const kExpectedMaxStackDepth = 200;\n for (let i = 0; i < kExpectedMaxStackDepth; i++) {\n this._stack[i] = new StringParserElement();\n }\n this._numElements = 1;\n }\n\n public readonly StringParserState = (): void => {\n const kExpectedMaxStackDepth: number = 200;\n this._stack = new Array(kExpectedMaxStackDepth);\n\n for (let ii = 0; ii < kExpectedMaxStackDepth; ++ii) {\n this._stack[ii] = new StringParserElement();\n }\n\n this._numElements = 1;\n };\n\n public readonly Push = (): number => {\n if (this._numElements >= this._stack.length && this._numElements > 0) {\n throw new Error(\"Stack overflow in parser state.\");\n }\n\n const prevElement = this._stack[this._numElements - 1];\n const newElement = this._stack[this._numElements];\n this._numElements++;\n\n newElement.CopyFrom(prevElement);\n\n return newElement.uniqueId;\n };\n\n public readonly Pop = (expectedRuleId: number): void => {\n if (this._numElements == 1) {\n throw new Error(\n \"Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?\"\n );\n }\n\n if (this.currentElement.uniqueId != expectedRuleId) {\n throw new Error(\n \"Mismatched rule IDs while Poping - do you have mismatched Begin/Succeed/Fail?\"\n );\n }\n\n // Restore state\n this._numElements -= 1;\n };\n\n public Peek = (expectedRuleId: number) => {\n if (this.currentElement.uniqueId != expectedRuleId) {\n throw new Error(\n \"Mismatched rule IDs while Peeking - do you have mismatched Begin/Succeed/Fail?\"\n );\n }\n\n return this._stack[this._numElements - 1];\n };\n\n public readonly PeekPenultimate = (): StringParserElement | null => {\n if (this._numElements >= 2) {\n return this._stack[this._numElements - 2];\n }\n\n return null;\n };\n\n // Reduce stack height while maintaining currentElement\n // Remove second last element: i.e. \"squash last two elements together\"\n // Used when succeeding from a rule (and ONLY when succeeding, since\n // the state of the top element is retained).\n public readonly Squash = (): void => {\n if (this._numElements < 2) {\n throw new Error(\n \"Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?\"\n );\n }\n\n const penultimateEl = this._stack[this._numElements - 2];\n const lastEl = this._stack[this._numElements - 1];\n\n penultimateEl.SquashFrom(lastEl);\n\n this._numElements -= 1;\n };\n\n public readonly NoteErrorReported = (): void => {\n for (const el of this._stack) {\n el.reportedErrorInScope = true;\n }\n };\n}\n","import { CharacterSet } from \"../CharacterSet\";\nimport { ParsedObject } from \"../ParsedHierarchy/Object\";\nimport { StringParserState } from \"./StringParserState\";\nimport { StringParserElement } from \"./StringParserElement\";\n\nexport const ParseSuccess = Symbol(\"ParseSuccessStruct\");\n\nexport type ParseRule = () => ParseRuleReturn;\n\nexport type ParseRuleReturn =\n | object\n | string\n | null\n | number\n | (typeof StringParser)[\"ParseSuccess\"];\n\nexport type SpecificParseRule = T;\n\nexport class StringParser {\n public ParseRule: ParseRule | null = null;\n\n public static readonly ParseSuccess: typeof ParseSuccess = ParseSuccess;\n public static readonly numbersCharacterSet = new CharacterSet(\"0123456789\");\n\n private _chars: string[];\n\n public errorHandler:\n | null\n | ((\n message: string,\n index: number,\n lineIndex?: number,\n isWarning?: boolean\n ) => void) = null;\n public state: StringParserState;\n public hadError: boolean = false;\n\n constructor(str: string) {\n const strPreProc = this.PreProcessInputString(str);\n this.state = new StringParserState();\n\n if (str) {\n this._chars = strPreProc.split(\"\");\n } else {\n this._chars = [];\n }\n\n this.inputString = strPreProc;\n }\n\n get currentCharacter(): string {\n if (this.index >= 0 && this.remainingLength > 0) {\n return this._chars[this.index];\n }\n\n return \"0\";\n }\n\n // Don't do anything by default, but provide ability for subclasses\n // to manipulate the string before it's used as input (converted to a char array)\n public PreProcessInputString(str: string): string {\n return str;\n }\n\n //--------------------------------\n // Parse state\n //--------------------------------\n\n public readonly BeginRule = (): number => this.state.Push();\n\n public readonly FailRule = (expectedRuleId: number): ParseRuleReturn => {\n this.state.Pop(expectedRuleId);\n return null;\n };\n\n public readonly CancelRule = (expectedRuleId: number): void => {\n this.state.Pop(expectedRuleId);\n };\n\n public readonly SucceedRule = (\n expectedRuleId: number,\n result: ParseRuleReturn = null\n ): ParseRuleReturn => {\n // Get state at point where this rule stared evaluating\n const stateAtSucceedRule = this.state.Peek(expectedRuleId);\n const stateAtBeginRule = this.state.PeekPenultimate();\n\n // Allow subclass to receive callback\n if (this.RuleDidSucceed) {\n this.RuleDidSucceed(result, stateAtBeginRule, stateAtSucceedRule);\n }\n\n // Flatten state stack so that we maintain the same values,\n // but remove one level in the stack.\n this.state.Squash();\n\n let finalResult: ParseRuleReturn = result;\n if (finalResult === null) {\n finalResult = StringParser.ParseSuccess;\n }\n\n return finalResult;\n };\n\n public RuleDidSucceed?: (\n result: ParseRuleReturn,\n startState: StringParserElement | null,\n endState: StringParserElement\n ) => void;\n\n public readonly Expect = (\n rule: ParseRule,\n message: string | null = null,\n recoveryRule: ParseRule | null = null\n ): ParseRuleReturn => {\n let result: ParseRuleReturn = this.ParseObject(rule);\n if (result === null) {\n if (message === null) {\n message = rule.name;\n }\n\n let butSaw: string;\n const lineRemainder: string = this.LineRemainder();\n if (lineRemainder === null || lineRemainder.length === 0) {\n butSaw = \"end of line\";\n } else {\n butSaw = `'${lineRemainder}'`;\n }\n\n this.Error(`Expected ${message} but saw ${butSaw}`);\n\n if (recoveryRule !== null) {\n result = recoveryRule();\n }\n }\n\n return result;\n };\n\n public Error = (message: string, isWarning: boolean = false): void => {\n this.ErrorOnLine(message, this.lineIndex + 1, isWarning);\n };\n\n public readonly ErrorWithParsedObject = (\n message: string,\n result: ParsedObject,\n isWarning: boolean = false\n ): void => {\n this.ErrorOnLine(\n message,\n result.debugMetadata ? result.debugMetadata.startLineNumber : -1,\n isWarning\n );\n };\n\n public readonly ErrorOnLine = (\n message: string,\n lineNumber: number,\n isWarning: boolean\n ): void => {\n if (!this.state.errorReportedAlreadyInScope) {\n const errorType = isWarning ? \"Warning\" : \"Error\";\n\n if (!this.errorHandler) {\n throw new Error(`${errorType} on line ${lineNumber}: ${message}`);\n } else {\n this.errorHandler(message, this.index, lineNumber - 1, isWarning);\n }\n\n this.state.NoteErrorReported();\n }\n\n if (!isWarning) {\n this.hadError = true;\n }\n };\n\n public readonly Warning = (message: string): void =>\n this.Error(message, true);\n\n get endOfInput(): boolean {\n return this.index >= this._chars.length;\n }\n\n get remainingString(): string {\n return this._chars\n .slice(this.index, this.index + this.remainingLength)\n .join(\"\");\n }\n\n public readonly LineRemainder = (): string =>\n this.Peek(() => this.ParseUntilCharactersFromString(\"\\n\\r\")) as string;\n\n get remainingLength() {\n return this._chars.length - this.index;\n }\n\n public inputString: string;\n\n get lineIndex() {\n return this.state.lineIndex;\n }\n\n set lineIndex(value: number) {\n this.state.lineIndex = value;\n }\n\n set characterInLineIndex(value: number) {\n this.state.characterInLineIndex = value;\n }\n\n get characterInLineIndex() {\n return this.state.characterInLineIndex;\n }\n\n get index(): number {\n // If we want subclass parsers to be able to set the index directly,\n // then we would need to know what the lineIndex of the new\n // index would be - would we have to step through manually\n // counting the newlines to do so?\n return this.state.characterIndex;\n }\n\n set index(value: number) {\n this.state.characterIndex = value;\n }\n\n public readonly SetFlag = (flag: number, trueOrFalse: boolean): void => {\n if (trueOrFalse) {\n this.state.customFlags |= flag;\n } else {\n this.state.customFlags &= ~flag;\n }\n };\n\n public readonly GetFlag = (flag: number): boolean =>\n Boolean(this.state.customFlags & flag);\n\n //--------------------------------\n // Structuring\n //--------------------------------\n\n public ParseObject = (rule: ParseRule): ParseRuleReturn => {\n const ruleId: number = this.BeginRule();\n const stackHeightBefore = this.state.stackHeight;\n const result = rule();\n\n if (stackHeightBefore !== this.state.stackHeight) {\n throw new Error(\"Mismatched Begin/Fail/Succeed rules\");\n }\n\n if (result === null) {\n return this.FailRule(ruleId);\n }\n\n this.SucceedRule(ruleId, result);\n\n return result;\n };\n\n public readonly Parse = (\n rule: SpecificParseRule\n ): ParseRuleReturn => {\n const ruleId: number = this.BeginRule();\n\n const result: ParseRuleReturn = rule();\n if (result === null) {\n this.FailRule(ruleId);\n return null;\n }\n\n this.SucceedRule(ruleId, result);\n\n return result;\n };\n\n public readonly OneOf = (array: ParseRule[]): ParseRuleReturn => {\n for (const rule of array) {\n const result = this.ParseObject(rule);\n if (result !== null) {\n return result;\n }\n }\n\n return null;\n };\n\n public readonly OneOrMore = (rule: ParseRule): ParseRuleReturn[] | null => {\n const results: ParseRuleReturn[] = [];\n let result: ParseRuleReturn = null;\n\n do {\n result = this.ParseObject(rule);\n if (result !== null) {\n results.push(result);\n }\n } while (result !== null);\n\n if (results.length > 0) {\n return results;\n }\n\n return null;\n };\n\n public readonly Optional =\n (rule: ParseRule): ParseRule =>\n () => {\n const result = this.ParseObject(rule);\n if (result === null) return StringParser.ParseSuccess;\n return result;\n };\n\n // Return ParseSuccess instead the real result so that it gets excluded\n // from result arrays (e.g. Interleave)\n public readonly Exclude =\n (rule: ParseRule): ParseRule =>\n () =>\n this.ParseObject(rule) && StringParser.ParseSuccess;\n\n // Combination of both of the above\n public readonly OptionalExclude =\n (rule: ParseRule): ParseRule =>\n () => {\n this.ParseObject(rule);\n return StringParser.ParseSuccess;\n };\n\n // Convenience method for creating more readable ParseString rules that can be combined\n // in other structuring rules (like OneOf etc)\n // e.g. OneOf(String(\"one\"), String(\"two\"))\n public readonly String =\n (str: string): ParseRule =>\n () =>\n this.ParseString(str);\n\n private readonly TryAddResultToList = (\n result: ParseRuleReturn,\n list: T[],\n flatten: boolean = true\n ): void => {\n if (result === StringParser.ParseSuccess) {\n return;\n }\n\n if (flatten && Array.isArray(result)) {\n const resultCollection = result as ParseRuleReturn[];\n if (resultCollection !== null) {\n for (const obj of resultCollection) {\n list.push(obj as any);\n }\n\n return;\n }\n }\n\n list.push(result as any);\n };\n\n public readonly Interleave = (\n ruleA: ParseRule,\n ruleB: ParseRule,\n untilTerminator: ParseRule | null = null,\n flatten: boolean = true\n ): T[] => {\n const ruleId: number = this.BeginRule();\n const results: T[] = [];\n\n // First outer padding\n const firstA = this.ParseObject(ruleA);\n if (firstA === null) {\n return this.FailRule(ruleId) as any;\n } else {\n this.TryAddResultToList(firstA, results, flatten);\n }\n\n let lastMainResult: ParseRuleReturn | null = null;\n let outerResult: ParseRuleReturn | null = null;\n do {\n // \"until\" condition hit?\n if (untilTerminator !== null && this.Peek(untilTerminator) !== null) {\n break;\n }\n\n // Main inner\n lastMainResult = this.ParseObject(ruleB);\n if (lastMainResult === null) {\n break;\n } else {\n this.TryAddResultToList(lastMainResult, results, flatten);\n }\n\n // Outer result (i.e. last A in ABA)\n outerResult = null;\n if (lastMainResult !== null) {\n outerResult = this.ParseObject(ruleA);\n\n if (outerResult === null) {\n break;\n } else {\n this.TryAddResultToList(outerResult, results, flatten);\n }\n }\n\n // Stop if there are no results, or if both are the placeholder \"ParseSuccess\" (i.e. Optional success rather than a true value)\n } while (\n (lastMainResult !== null || outerResult !== null) &&\n !(\n (lastMainResult as any) === StringParser.ParseSuccess &&\n outerResult == StringParser.ParseSuccess\n ) &&\n this.remainingLength > 0\n );\n\n if (results.length === 0) {\n return this.FailRule(ruleId) as T[];\n }\n\n return this.SucceedRule(ruleId, results) as T[];\n };\n\n //--------------------------------\n // Basic string parsing\n //--------------------------------\n\n public readonly ParseString = (str: string): string | null => {\n if (str.length > this.remainingLength) {\n return null;\n }\n\n const ruleId: number = this.BeginRule();\n\n // Optimisation from profiling:\n // Store in temporary local variables\n // since they're properties that would have to access\n // the rule stack every time otherwise.\n let i: number = this.index;\n let cli: number = this.characterInLineIndex;\n let li: number = this.lineIndex;\n\n let success: boolean = true;\n for (let tempIdx = 0; tempIdx < str.length; tempIdx += 1) {\n const c = str[tempIdx];\n\n if (this._chars[i] !== c) {\n success = false;\n break;\n }\n if (c === \"\\n\") {\n li++;\n cli = -1;\n }\n\n i++;\n cli++;\n }\n\n this.index = i;\n this.characterInLineIndex = cli;\n this.lineIndex = li;\n\n if (success) {\n return this.SucceedRule(ruleId, str) as any;\n }\n\n return this.FailRule(ruleId) as any;\n };\n\n public readonly ParseSingleCharacter = (): string => {\n if (this.remainingLength > 0) {\n const c = this._chars[this.index];\n if (c === \"\\n\") {\n this.lineIndex += 1;\n this.characterInLineIndex = -1;\n }\n\n this.index += 1;\n this.characterInLineIndex += 1;\n\n return c;\n }\n\n return \"0\";\n };\n\n public readonly ParseUntilCharactersFromString = (\n str: string,\n maxCount: number = -1\n ): string | null => this.ParseCharactersFromString(str, false, maxCount);\n\n public readonly ParseUntilCharactersFromCharSet = (\n charSet: CharacterSet,\n maxCount: number = -1\n ): string | null => this.ParseCharactersFromCharSet(charSet, false, maxCount);\n\n public readonly ParseCharactersFromString = (\n str: string,\n maxCountOrShouldIncludeStrChars: boolean | number = -1,\n maxCount: number = -1\n ): string | null => {\n const charSet = new CharacterSet(str);\n if (typeof maxCountOrShouldIncludeStrChars === \"number\") {\n return this.ParseCharactersFromCharSet(\n charSet,\n true,\n maxCountOrShouldIncludeStrChars\n );\n }\n\n return this.ParseCharactersFromCharSet(\n charSet,\n maxCountOrShouldIncludeStrChars,\n maxCount\n );\n };\n\n public readonly ParseCharactersFromCharSet = (\n charSet: CharacterSet,\n shouldIncludeChars: boolean = true,\n maxCount: number = -1\n ): string | null => {\n if (maxCount === -1) {\n maxCount = Number.MAX_SAFE_INTEGER;\n }\n\n const startIndex: number = this.index;\n\n // Optimisation from profiling:\n // Store in temporary local variables\n // since they're properties that would have to access\n // the rule stack every time otherwise.\n let ii: number = this.index;\n let cli: number = this.characterInLineIndex;\n let li: number = this.lineIndex;\n let count: number = 0;\n while (\n ii < this._chars.length &&\n charSet.set.has(this._chars[ii]) === shouldIncludeChars &&\n count < maxCount\n ) {\n if (this._chars[ii] === \"\\n\") {\n li += 1;\n cli = -1;\n }\n\n ii += 1;\n cli += 1;\n count += 1;\n }\n\n this.index = ii;\n this.characterInLineIndex = cli;\n this.lineIndex = li;\n\n const lastCharIndex: number = this.index;\n if (lastCharIndex > startIndex) {\n return this._chars.slice(startIndex, this.index).join(\"\");\n }\n\n return null;\n };\n\n public readonly Peek = (rule: ParseRule): ParseRuleReturn => {\n const ruleId: number = this.BeginRule();\n const result: ParseRuleReturn = rule();\n this.CancelRule(ruleId);\n\n return result;\n };\n\n public ParseUntil(\n stopRule: ParseRule,\n pauseCharacters: CharacterSet | null = null,\n endCharacters: CharacterSet | null = null\n ): string {\n const ruleId: number = this.BeginRule();\n const pauseAndEnd: CharacterSet = new CharacterSet();\n if (pauseCharacters !== null) {\n pauseAndEnd.set = new Set([\n ...pauseAndEnd.set.values(),\n ...pauseCharacters.set.values(),\n ]);\n }\n\n if (endCharacters !== null) {\n pauseAndEnd.set = new Set([\n ...pauseAndEnd.set.values(),\n ...endCharacters.set.values(),\n ]);\n }\n\n let parsedString = \"\";\n let ruleResultAtPause: ParseRuleReturn | null = null;\n\n // Keep attempting to parse strings up to the pause (and end) points.\n // - At each of the pause points, attempt to parse according to the rule\n // - When the end point is reached (or EOF), we're done\n do {\n // TODO: Perhaps if no pause or end characters are passed, we should check *every* character for stopRule?\n const partialParsedString: string | null =\n this.ParseUntilCharactersFromCharSet(pauseAndEnd);\n\n if (partialParsedString) {\n parsedString += partialParsedString;\n }\n\n // Attempt to run the parse rule at this pause point\n ruleResultAtPause = this.Peek(stopRule);\n\n // Rule completed - we're done\n if (ruleResultAtPause !== null) {\n break;\n } else {\n if (this.endOfInput) {\n break;\n }\n\n // Reached a pause point, but rule failed. Step past and continue parsing string\n const pauseCharacter: string = this.currentCharacter;\n if (\n pauseCharacters !== null &&\n pauseCharacters.set.has(pauseCharacter)\n ) {\n parsedString += pauseCharacter;\n if (pauseCharacter === \"\\n\") {\n this.lineIndex += 1;\n this.characterInLineIndex = -1;\n }\n\n this.index += 1;\n this.characterInLineIndex += 1;\n\n continue;\n } else {\n break;\n }\n }\n } while (true);\n\n if (parsedString.length > 0) {\n return this.SucceedRule(ruleId, String(parsedString)) as string;\n }\n\n return this.FailRule(ruleId) as string;\n }\n\n // No need to Begin/End rule since we never parse a newline, so keeping oldIndex is good enough\n public readonly ParseInt = (): number | null => {\n const oldIndex: number = this.index;\n const oldCharacterInLineIndex: number = this.characterInLineIndex;\n const negative: boolean = this.ParseString(\"-\") !== null;\n\n // Optional whitespace\n this.ParseCharactersFromString(\" \\t\");\n\n const parsedString = this.ParseCharactersFromCharSet(\n StringParser.numbersCharacterSet\n );\n if (parsedString === null) {\n // Roll back and fail\n this.index = oldIndex;\n this.characterInLineIndex = oldCharacterInLineIndex;\n\n return null;\n }\n\n let parsedInt: number;\n if (!Number.isNaN(Number(parsedString))) {\n parsedInt = Number(parsedString);\n return negative ? -parsedInt : parsedInt;\n }\n\n this.Error(\n \"Failed to read integer value: \" +\n parsedString +\n \". Perhaps it's out of the range of acceptable numbers ink supports? (\" +\n Number.MIN_SAFE_INTEGER +\n \" to \" +\n Number.MAX_SAFE_INTEGER +\n \")\"\n );\n\n return null;\n };\n\n // No need to Begin/End rule since we never parse a newline, so keeping oldIndex is good enough\n public readonly ParseFloat = (): number | null => {\n const oldIndex: number = this.index;\n const oldCharacterInLineIndex: number = this.characterInLineIndex;\n\n const leadingInt: number | null = this.ParseInt();\n if (leadingInt !== null) {\n if (this.ParseString(\".\") !== null) {\n const afterDecimalPointStr = this.ParseCharactersFromCharSet(\n StringParser.numbersCharacterSet\n );\n\n return Number(`${leadingInt}.${afterDecimalPointStr}`);\n }\n }\n\n // Roll back and fail\n this.index = oldIndex;\n this.characterInLineIndex = oldCharacterInLineIndex;\n\n return null;\n };\n\n public readonly ParseNewline = (): string => {\n const ruleId: number = this.BeginRule();\n\n // Optional \\r, definite \\n to support Windows (\\r\\n) and Mac/Unix (\\n)\n // 2nd May 2016: Always collapse \\r\\n to just \\n\n this.ParseString(\"\\r\");\n\n if (this.ParseString(\"\\n\") === null) {\n return this.FailRule(ruleId) as string;\n }\n\n return this.SucceedRule(ruleId, \"\\n\") as string;\n };\n}\n","import { CharacterSet } from \"./CharacterSet\";\nimport { StringParser } from \"./StringParser/StringParser\";\n\n/// \n/// Pre-pass before main ink parser runs. It actually performs two main tasks:\n/// - comment elimination to simplify the parse rules in the main parser\n/// - Conversion of Windows line endings (\\r\\n) to the simpler Unix style (\\n), so\n/// we don't have to worry about them later.\n/// \nexport class CommentEliminator extends StringParser {\n public _commentOrNewlineStartCharacter = new CharacterSet(\"/\\r\\n\");\n public _commentBlockEndCharacter = new CharacterSet(\"*\");\n public _newlineCharacters = new CharacterSet(\"\\n\\r\");\n\n public readonly Process = (): string => {\n // Make both comments and non-comments optional to handle trivial empty file case (or *only* comments)\n const stringList: string[] = this.Interleave(\n this.Optional(this.CommentsAndNewlines),\n this.Optional(this.MainInk)\n );\n\n if (stringList !== null) {\n return stringList.join(\"\");\n } else {\n return \"\";\n }\n };\n\n public readonly MainInk = () =>\n this.ParseUntil(\n this.CommentsAndNewlines,\n this._commentOrNewlineStartCharacter,\n null\n );\n\n public readonly CommentsAndNewlines = () => {\n let newLines: string[] = this.Interleave(\n this.Optional(this.ParseNewline),\n this.Optional(this.ParseSingleComment)\n );\n\n if (newLines !== null) {\n return newLines.join(\"\");\n }\n\n return null;\n };\n\n // Valid comments always return either an empty string or pure newlines,\n // which we want to keep so that line numbers stay the same\n public readonly ParseSingleComment = () =>\n this.OneOf([this.EndOfLineComment, this.BlockComment]);\n\n public readonly EndOfLineComment = () => {\n if (this.ParseString(\"//\") === null) {\n return null;\n }\n\n this.ParseUntilCharactersFromCharSet(this._newlineCharacters);\n\n return \"\";\n };\n\n public readonly BlockComment = () => {\n if (this.ParseString(\"/*\") === null) {\n return null;\n }\n\n const startLineIndex: number = this.lineIndex;\n const commentResult = this.ParseUntil(\n this.String(\"*/\"),\n this._commentBlockEndCharacter,\n null\n );\n\n if (!this.endOfInput) {\n this.ParseString(\"*/\");\n }\n\n // Count the number of lines that were inside the block, and replicate them as newlines\n // so that the line indexing still works from the original source\n if (commentResult != null) {\n return \"\\n\".repeat(this.lineIndex - startLineIndex);\n }\n\n // No comment at all\n return null;\n };\n\n public PreProcessInputString(str: string): string {\n return str;\n }\n}\n","import { ConditionalSingleBranch } from \"./ConditionalSingleBranch\";\nimport { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { Expression } from \"../Expression/Expression\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Story } from \"../Story\";\n\nexport class Conditional extends ParsedObject {\n private _reJoinTarget: RuntimeControlCommand | null = null;\n\n constructor(\n public initialCondition: Expression,\n public branches: ConditionalSingleBranch[]\n ) {\n super();\n\n if (this.initialCondition) {\n this.AddContent(this.initialCondition);\n }\n\n if (this.branches !== null) {\n this.AddContent(this.branches);\n }\n }\n\n get typeName(): string {\n return \"Conditional\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n\n // Initial condition\n if (this.initialCondition) {\n container.AddContent(this.initialCondition.runtimeObject);\n }\n\n // Individual branches\n for (const branch of this.branches) {\n const branchContainer = branch.runtimeObject;\n container.AddContent(branchContainer);\n }\n\n // If it's a switch-like conditional, each branch\n // will have a \"duplicate\" operation for the original\n // switched value. If there's no final else clause\n // and we fall all the way through, we need to clean up.\n // (An else clause doesn't dup but it *does* pop)\n if (\n this.initialCondition !== null &&\n this.branches[0].ownExpression !== null &&\n !this.branches[this.branches.length - 1].isElse\n ) {\n container.AddContent(RuntimeControlCommand.PopEvaluatedValue());\n }\n\n // Target for branches to rejoin to\n this._reJoinTarget = RuntimeControlCommand.NoOp();\n container.AddContent(this._reJoinTarget);\n\n return container;\n };\n\n public ResolveReferences(context: Story): void {\n const pathToReJoin = this._reJoinTarget!.path;\n\n for (const branch of this.branches) {\n if (!branch.returnDivert) {\n throw new Error();\n }\n\n branch.returnDivert.targetPath = pathToReJoin;\n }\n\n super.ResolveReferences(context);\n }\n}\n","import { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { StringValue } from \"../../../engine/Value\";\n\nexport class Text extends ParsedObject {\n constructor(public text: string) {\n super();\n }\n get typeName(): string {\n return \"Text\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject =>\n new StringValue(this.text);\n\n public readonly toString = (): string => this.text;\n}\n","import { Expression } from \"../Expression/Expression\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Story } from \"../Story\";\nimport { SymbolType } from \"../SymbolType\";\nimport { Identifier } from \"../Identifier\";\n\nexport class ConstantDeclaration extends ParsedObject {\n get constantName(): string | undefined {\n return this.constantIdentifier?.name;\n }\n public constantIdentifier: Identifier;\n\n private _expression: Expression | null = null;\n\n get expression(): Expression {\n if (!this._expression) {\n throw new Error();\n }\n\n return this._expression;\n }\n\n constructor(name: Identifier, assignedExpression: Expression) {\n super();\n\n this.constantIdentifier = name;\n\n // Defensive programming in case parsing of assignedExpression failed\n if (assignedExpression) {\n this._expression = this.AddContent(assignedExpression) as Expression;\n }\n }\n\n get typeName(): string {\n return \"CONST\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject | null => {\n // Global declarations don't generate actual procedural\n // runtime objects, but instead add a global variable to the story itself.\n // The story then initialises them all in one go at the start of the game.\n return null;\n };\n\n public ResolveReferences(context: Story) {\n super.ResolveReferences(context);\n context.CheckForNamingCollisions(\n this,\n this.constantIdentifier,\n SymbolType.Var\n );\n }\n}\n","export enum FlowLevel {\n Story, // 0\n Knot, // 1\n Stitch, // 2\n // not actually a FlowBase, but used for diverts\n WeavePoint, // 3\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { INamedContent } from \"../../../../engine/INamedContent\";\nimport { IWeavePoint } from \"../IWeavePoint\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Story } from \"../Story\";\nimport { SymbolType } from \"../SymbolType\";\nimport { Identifier } from \"../Identifier\";\n\nexport class Gather extends ParsedObject implements INamedContent, IWeavePoint {\n get name(): string | null {\n return this.identifier?.name || null;\n }\n public identifier?: Identifier;\n\n get runtimeContainer(): RuntimeContainer {\n return this.runtimeObject as RuntimeContainer;\n }\n\n constructor(\n identifier: Identifier | null,\n public readonly indentationDepth: number\n ) {\n super();\n\n if (identifier) this.identifier = identifier;\n }\n\n get typeName(): string {\n return \"Gather\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n container.name = this.name;\n\n if (this.story.countAllVisits) {\n container.visitsShouldBeCounted = true;\n }\n\n container.countingAtStartOnly = true;\n\n // A gather can have null content, e.g. it's just purely a line with \"-\"\n if (this.content) {\n for (const c of this.content) {\n container.AddContent(c.runtimeObject);\n }\n }\n\n return container;\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n if (this.identifier && (this.identifier.name || \"\").length > 0) {\n context.CheckForNamingCollisions(\n this,\n this.identifier,\n SymbolType.SubFlowAndWeave\n );\n }\n }\n\n public readonly toString = (): string =>\n `- ${this.identifier?.name ? \"(\" + this.identifier?.name + \")\" : \"gather\"}`;\n}\n","import { asOrNull, filterUndef } from \"../../../engine/TypeAssertion\";\nimport { FlowBase } from \"./Flow/FlowBase\";\nimport { FlowLevel } from \"./Flow/FlowLevel\";\nimport { Identifier } from \"./Identifier\";\nimport { ParsedObject } from \"./Object\";\nimport { Weave } from \"./Weave\";\n\nexport class Path {\n private _baseTargetLevel: FlowLevel | null;\n private components: Identifier[] | null;\n\n get baseTargetLevel() {\n if (this.baseLevelIsAmbiguous) {\n return FlowLevel.Story;\n }\n\n return this._baseTargetLevel;\n }\n\n get baseLevelIsAmbiguous(): boolean {\n return !this._baseTargetLevel;\n }\n\n get firstComponent(): string | null {\n if (this.components == null || !this.components.length) {\n return null;\n }\n\n return this.components[0].name;\n }\n\n get numberOfComponents(): number {\n return this.components ? this.components.length : 0;\n }\n\n private _dotSeparatedComponents: string | null = null;\n\n get dotSeparatedComponents(): string {\n if (this._dotSeparatedComponents == null) {\n this._dotSeparatedComponents = (this.components ? this.components : [])\n .map((c) => c.name)\n .filter(filterUndef)\n .join(\".\");\n }\n return this._dotSeparatedComponents;\n }\n\n constructor(\n argOne: FlowLevel | Identifier[] | Identifier,\n argTwo?: Identifier[]\n ) {\n if (Object.values(FlowLevel).includes(argOne as FlowLevel)) {\n this._baseTargetLevel = argOne as FlowLevel;\n this.components = argTwo || [];\n } else if (Array.isArray(argOne)) {\n this._baseTargetLevel = null;\n this.components = argOne || [];\n } else {\n this._baseTargetLevel = null;\n this.components = [argOne as Identifier];\n }\n }\n\n get typeName(): string {\n return \"Path\";\n }\n\n public readonly toString = (): string => {\n if (this.components === null || this.components.length === 0) {\n if (this.baseTargetLevel === FlowLevel.WeavePoint) {\n return \"-> \";\n }\n\n return \"\";\n }\n\n return `-> ${this.dotSeparatedComponents}`;\n };\n\n public readonly ResolveFromContext = (\n context: ParsedObject\n ): ParsedObject | null => {\n if (this.components == null || this.components.length == 0) {\n return null;\n }\n\n // Find base target of path from current context. e.g.\n // ==> BASE.sub.sub\n let baseTargetObject = this.ResolveBaseTarget(context);\n if (baseTargetObject === null) {\n return null;\n }\n\n // Given base of path, resolve final target by working deeper into hierarchy\n // e.g. ==> base.mid.FINAL\n if (this.components.length > 1) {\n return this.ResolveTailComponents(baseTargetObject);\n }\n\n return baseTargetObject;\n };\n\n // Find the root object from the base, i.e. root from:\n // root.sub1.sub2\n public readonly ResolveBaseTarget = (\n originalContext: ParsedObject\n ): ParsedObject | null => {\n const firstComp = this.firstComponent;\n\n // Work up the ancestry to find the node that has the named object\n let ancestorContext: ParsedObject | null = originalContext;\n while (ancestorContext) {\n // Only allow deep search when searching deeper from original context.\n // Don't allow search upward *then* downward, since that's searching *everywhere*!\n // Allowed examples:\n // - From an inner gather of a stitch, you should search up to find a knot called 'x'\n // at the root of a story, but not a stitch called 'x' in that knot.\n // - However, from within a knot, you should be able to find a gather/choice\n // anywhere called 'x'\n // (that latter example is quite loose, but we allow it)\n const deepSearch: boolean = ancestorContext === originalContext;\n\n const foundBase = this.GetChildFromContext(\n ancestorContext,\n firstComp,\n null,\n deepSearch\n );\n\n if (foundBase) {\n return foundBase;\n }\n\n ancestorContext = ancestorContext.parent;\n }\n\n return null;\n };\n\n // Find the final child from path given root, i.e.:\n // root.sub.finalChild\n public readonly ResolveTailComponents = (\n rootTarget: ParsedObject\n ): ParsedObject | null => {\n let foundComponent: ParsedObject | null = rootTarget;\n\n if (!this.components) return null;\n\n for (let ii = 1; ii < this.components.length; ++ii) {\n const compName = this.components[ii].name;\n\n let minimumExpectedLevel: FlowLevel;\n let foundFlow = asOrNull(foundComponent, FlowBase);\n if (foundFlow !== null) {\n minimumExpectedLevel = (foundFlow.flowLevel + 1) as FlowLevel;\n } else {\n minimumExpectedLevel = FlowLevel.WeavePoint;\n }\n\n foundComponent = this.GetChildFromContext(\n foundComponent,\n compName,\n minimumExpectedLevel\n );\n\n if (foundComponent === null) {\n break;\n }\n }\n\n return foundComponent;\n };\n\n // See whether \"context\" contains a child with a given name at a given flow level\n // Can either be a named knot/stitch (a FlowBase) or a weave point within a Weave (Choice or Gather)\n // This function also ignores any other object types that are neither FlowBase nor Weave.\n // Called from both ResolveBase (force deep) and ResolveTail for the individual components.\n public readonly GetChildFromContext = (\n context: ParsedObject,\n childName: string | null,\n minimumLevel: FlowLevel | null,\n forceDeepSearch: boolean = false\n ): ParsedObject | null => {\n // null childLevel means that we don't know where to find it\n const ambiguousChildLevel: boolean = minimumLevel === null;\n\n // Search for WeavePoint within Weave\n const weaveContext = asOrNull(context, Weave);\n if (\n childName &&\n weaveContext !== null &&\n (ambiguousChildLevel || minimumLevel === FlowLevel.WeavePoint)\n ) {\n return weaveContext.WeavePointNamed(childName) as ParsedObject;\n }\n\n // Search for content within Flow (either a sub-Flow or a WeavePoint)\n let flowContext = asOrNull(context, FlowBase);\n if (childName && flowContext !== null) {\n // When searching within a Knot, allow a deep searches so that\n // named weave points (choices and gathers) can be found within any stitch\n // Otherwise, we just search within the immediate object.\n const shouldDeepSearch =\n forceDeepSearch || flowContext.flowLevel === FlowLevel.Knot;\n\n return flowContext.ContentWithNameAtLevel(\n childName,\n minimumLevel,\n shouldDeepSearch\n );\n }\n\n return null;\n };\n}\n","import { Expression } from \"./Expression/Expression\";\nimport { ParsedObject } from \"./Object\";\nimport { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../engine/ControlCommand\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Void } from \"../../../engine/Void\";\n\nexport class ReturnType extends ParsedObject {\n public returnedExpression: Expression | null = null;\n\n constructor(returnedExpression: Expression | null = null) {\n super();\n\n if (returnedExpression) {\n this.returnedExpression = this.AddContent(\n returnedExpression\n ) as Expression;\n }\n }\n\n get typeName(): string {\n return \"ReturnType\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n\n if (this.returnedExpression) {\n // Evaluate expression\n container.AddContent(this.returnedExpression.runtimeObject);\n } else {\n // Return Runtime.Void when there's no expression to evaluate\n // (This evaluation will just add the Void object to the evaluation stack)\n container.AddContent(RuntimeControlCommand.EvalStart());\n container.AddContent(new Void());\n container.AddContent(RuntimeControlCommand.EvalEnd());\n }\n\n // Then pop the call stack\n // (the evaluated expression will leave the return value on the evaluation stack)\n container.AddContent(RuntimeControlCommand.PopFunction());\n\n return container;\n };\n}\n","// import { FlowBase } from './FlowBase';\n\nexport function ClosestFlowBase(obj: any): any | null {\n let ancestor = obj.parent;\n while (ancestor) {\n if (ancestor.hasOwnProperty(\"iamFlowbase\") && ancestor.iamFlowbase()) {\n return ancestor as any;\n }\n\n ancestor = ancestor.parent;\n }\n\n return null;\n}\n","import { DebugMetadata } from \"../../../engine/DebugMetadata\";\n\nexport class Identifier {\n public name: string;\n public debugMetadata: DebugMetadata | null = null;\n\n constructor(name: string) {\n this.name = name;\n }\n\n get typeName(): string {\n return \"Identifier\";\n }\n\n public static Done(): Identifier {\n return new Identifier(\"DONE\");\n }\n\n public readonly toString = (): string => this.name || \"undefined identifer\";\n}\n","import { Argument } from \"../Argument\";\nimport { Choice } from \"../Choice\";\nimport { Divert } from \"../Divert/Divert\";\nimport { DivertTarget } from \"../Divert/DivertTarget\";\nimport { FlowLevel } from \"./FlowLevel\";\nimport { Gather } from \"../Gather/Gather\";\nimport { INamedContent } from \"../../../../engine/INamedContent\";\n// import { Knot } from '../Knot';\nimport { ParsedObject } from \"../Object\";\nimport { Path } from \"../Path\";\nimport { ReturnType } from \"../ReturnType\";\nimport { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { VariableAssignment as RuntimeVariableAssignment } from \"../../../../engine/VariableAssignment\";\n//import { Story } from '../Story';\nimport { SymbolType } from \"../SymbolType\";\nimport { VariableAssignment } from \"../Variable/VariableAssignment\";\nimport { Weave } from \"../Weave\";\nimport { ClosestFlowBase } from \"./ClosestFlowBase\";\nimport { Identifier } from \"../Identifier\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\ntype VariableResolveResult = {\n found: boolean;\n isGlobal: boolean;\n isArgument: boolean;\n isTemporary: boolean;\n ownerFlow: FlowBase;\n};\n\n// Base class for Knots and Stitches\nexport abstract class FlowBase extends ParsedObject implements INamedContent {\n public abstract readonly flowLevel: FlowLevel;\n\n public _rootWeave: Weave | null = null;\n public _subFlowsByName: Map = new Map();\n public _startingSubFlowDivert: RuntimeDivert | null = null;\n public _startingSubFlowRuntime: RuntimeObject | null = null;\n public _firstChildFlow: FlowBase | null = null;\n public variableDeclarations: Map = new Map();\n\n get hasParameters() {\n return this.args !== null && this.args.length > 0;\n }\n\n get subFlowsByName() {\n return this._subFlowsByName;\n }\n\n get typeName(): string {\n if (this.isFunction) {\n return \"Function\";\n }\n\n return String(this.flowLevel);\n }\n\n get name(): string | null {\n return this.identifier?.name || null;\n }\n\n public identifier: Identifier | null = null;\n public args: Argument[] | null = null;\n\n constructor(\n identifier: Identifier | null,\n topLevelObjects: ParsedObject[] | null = null,\n args: Argument[] | null = null,\n public readonly isFunction: boolean = false,\n isIncludedStory: boolean = false\n ) {\n super();\n\n this.identifier = identifier;\n this.args = args;\n\n if (topLevelObjects === null) {\n topLevelObjects = [];\n }\n\n // Used by story to add includes\n this.PreProcessTopLevelObjects(topLevelObjects);\n\n topLevelObjects = this.SplitWeaveAndSubFlowContent(\n topLevelObjects,\n this.GetType() == \"Story\" && !isIncludedStory\n );\n\n this.AddContent(topLevelObjects);\n }\n\n public iamFlowbase = () => true;\n\n public readonly SplitWeaveAndSubFlowContent = (\n contentObjs: ParsedObject[],\n isRootStory: boolean\n ): ParsedObject[] => {\n const weaveObjs: ParsedObject[] = [];\n const subFlowObjs: ParsedObject[] = [];\n\n this._subFlowsByName = new Map();\n\n for (const obj of contentObjs) {\n const subFlow = asOrNull(obj, FlowBase);\n if (subFlow) {\n if (this._firstChildFlow === null) {\n this._firstChildFlow = subFlow;\n }\n\n subFlowObjs.push(obj);\n if (subFlow.identifier?.name) {\n this._subFlowsByName.set(subFlow.identifier?.name, subFlow);\n }\n } else {\n weaveObjs.push(obj);\n }\n }\n\n // Implicit final gather in top level story for ending without warning that you run out of content\n if (isRootStory) {\n weaveObjs.push(\n new Gather(null, 1),\n new Divert(new Path(Identifier.Done()))\n );\n }\n\n const finalContent: ParsedObject[] = [];\n\n if (weaveObjs.length > 0) {\n this._rootWeave = new Weave(weaveObjs, 0);\n finalContent.push(this._rootWeave);\n }\n\n if (subFlowObjs.length > 0) {\n finalContent.push(...subFlowObjs);\n }\n return finalContent;\n };\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public PreProcessTopLevelObjects(_: ParsedObject[]): void {\n // empty by default, used by Story to process included file references\n }\n\n public VariableResolveResult?: VariableResolveResult | null | undefined;\n\n public ResolveVariableWithName = (\n varName: string,\n fromNode: ParsedObject\n ): VariableResolveResult => {\n const result: VariableResolveResult = {} as any;\n\n // Search in the stitch / knot that owns the node first\n const ownerFlow = fromNode === null ? this : ClosestFlowBase(fromNode);\n\n if (ownerFlow) {\n // Argument\n if (ownerFlow.args !== null) {\n for (const arg of ownerFlow.args) {\n if (arg.identifier?.name === varName) {\n result.found = true;\n result.isArgument = true;\n result.ownerFlow = ownerFlow;\n return result;\n }\n }\n }\n\n // Temp\n if (\n ownerFlow !== this.story &&\n ownerFlow.variableDeclarations.has(varName)\n ) {\n result.found = true;\n result.ownerFlow = ownerFlow;\n result.isTemporary = true;\n\n return result;\n }\n }\n\n // Global\n if (this.story.variableDeclarations.has(varName)) {\n result.found = true;\n result.ownerFlow = this.story;\n result.isGlobal = true;\n\n return result;\n }\n\n result.found = false;\n\n return result;\n };\n\n public AddNewVariableDeclaration = (varDecl: VariableAssignment): void => {\n const varName = varDecl.variableName;\n if (this.variableDeclarations.has(varName)) {\n const varab = this.variableDeclarations.get(varName)!;\n let prevDeclError = \"\";\n const debugMetadata = varab.debugMetadata;\n if (debugMetadata) {\n prevDeclError = ` (${varab.debugMetadata})`;\n }\n\n this.Error(\n `found declaration variable '${varName}' that was already declared${prevDeclError}`,\n varDecl,\n false\n );\n\n return;\n }\n\n this.variableDeclarations.set(varDecl.variableName, varDecl);\n };\n\n public ResolveWeavePointNaming = (): void => {\n // Find all weave points and organise them by name ready for\n // diverting. Also detect naming collisions.\n if (this._rootWeave) {\n this._rootWeave.ResolveWeavePointNaming();\n }\n\n for (const [, value] of this._subFlowsByName) {\n if (value.hasOwnProperty(\"ResolveWeavePointNaming\")) {\n value.ResolveWeavePointNaming();\n }\n }\n };\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n let foundReturn: ReturnType | null = null;\n if (this.isFunction) {\n this.CheckForDisallowedFunctionFlowControl();\n } else if (\n this.flowLevel === FlowLevel.Knot ||\n this.flowLevel === FlowLevel.Stitch\n ) {\n // Non-functon: Make sure knots and stitches don't attempt to use Return statement\n foundReturn = this.Find(ReturnType)();\n\n if (foundReturn !== null) {\n this.Error(\n `Return statements can only be used in knots that are declared as functions: == function ${this.identifier} ==`,\n foundReturn\n );\n }\n }\n\n const container = new RuntimeContainer();\n container.name = this.identifier?.name as string;\n\n if (this.story.countAllVisits) {\n container.visitsShouldBeCounted = true;\n }\n\n this.GenerateArgumentVariableAssignments(container);\n\n // Run through content defined for this knot/stitch:\n // - First of all, any initial content before a sub-stitch\n // or any weave content is added to the main content container\n // - The first inner knot/stitch is automatically entered, while\n // the others are only accessible by an explicit divert\n // - The exception to this rule is if the knot/stitch takes\n // parameters, in which case it can't be auto-entered.\n // - Any Choices and Gathers (i.e. IWeavePoint) found are\n // processsed by GenerateFlowContent.\n let contentIdx: number = 0;\n while (this.content !== null && contentIdx < this.content.length) {\n const obj: ParsedObject = this.content[contentIdx];\n\n // Inner knots and stitches\n if (obj instanceof FlowBase) {\n const childFlow: FlowBase = obj;\n const childFlowRuntime = childFlow.runtimeObject;\n\n // First inner stitch - automatically step into it\n // 20/09/2016 - let's not auto step into knots\n if (\n contentIdx === 0 &&\n !childFlow.hasParameters &&\n this.flowLevel === FlowLevel.Knot\n ) {\n this._startingSubFlowDivert = new RuntimeDivert();\n container.AddContent(this._startingSubFlowDivert);\n this._startingSubFlowRuntime = childFlowRuntime;\n }\n\n // Check for duplicate knots/stitches with same name\n const namedChild = childFlowRuntime as RuntimeObject & INamedContent;\n const existingChild: INamedContent | null =\n container.namedContent.get(namedChild.name!) || null;\n\n if (existingChild) {\n const errorMsg = `${this.GetType()} already contains flow named '${\n namedChild.name\n }' (at ${(existingChild as any as RuntimeObject).debugMetadata})`;\n this.Error(errorMsg, childFlow);\n }\n\n container.AddToNamedContentOnly(namedChild);\n } else if (obj) {\n // Other content (including entire Weaves that were grouped in the constructor)\n // At the time of writing, all FlowBases have a maximum of one piece of \"other content\"\n // and it's always the root Weave\n container.AddContent(obj.runtimeObject);\n }\n\n contentIdx += 1;\n }\n\n // CHECK FOR FINAL LOOSE ENDS!\n // Notes:\n // - Functions don't need to terminate - they just implicitly return\n // - If return statement was found, don't continue finding warnings for missing control flow,\n // since it's likely that a return statement has been used instead of a ->-> or something,\n // or the writer failed to mark the knot as a function.\n // - _rootWeave may be null if it's a knot that only has stitches\n if (\n this.flowLevel !== FlowLevel.Story &&\n !this.isFunction &&\n this._rootWeave !== null &&\n foundReturn === null\n ) {\n this._rootWeave.ValidateTermination(this.WarningInTermination);\n }\n\n return container;\n };\n\n public readonly GenerateArgumentVariableAssignments = (\n container: RuntimeContainer\n ): void => {\n if (this.args === null || this.args.length === 0) {\n return;\n }\n\n // Assign parameters in reverse since they'll be popped off the evaluation stack\n // No need to generate EvalStart and EvalEnd since there's nothing being pushed\n // back onto the evaluation stack.\n for (let ii = this.args.length - 1; ii >= 0; --ii) {\n const paramName = this.args[ii].identifier?.name || null;\n const assign = new RuntimeVariableAssignment(paramName, true);\n container.AddContent(assign);\n }\n };\n\n public readonly ContentWithNameAtLevel = (\n name: string,\n level: FlowLevel | null = null,\n deepSearch: boolean = false\n ): ParsedObject | null => {\n // Referencing self?\n if (level === this.flowLevel || level === null) {\n if (name === this.identifier?.name) {\n return this;\n }\n }\n\n if (level === FlowLevel.WeavePoint || level === null) {\n let weavePointResult: ParsedObject | null = null;\n\n if (this._rootWeave) {\n weavePointResult = this._rootWeave.WeavePointNamed(\n name\n ) as ParsedObject;\n if (weavePointResult) {\n return weavePointResult;\n }\n }\n\n // Stop now if we only wanted a result if it's a weave point?\n if (level === FlowLevel.WeavePoint) {\n return deepSearch ? this.DeepSearchForAnyLevelContent(name) : null;\n }\n }\n\n // If this flow would be incapable of containing the requested level, early out\n // (e.g. asking for a Knot from a Stitch)\n if (level !== null && level < this.flowLevel) {\n return null;\n }\n\n let subFlow: FlowBase | null = this._subFlowsByName.get(name) || null;\n\n if (subFlow && (level === null || level === subFlow.flowLevel)) {\n return subFlow;\n }\n\n return deepSearch ? this.DeepSearchForAnyLevelContent(name) : null;\n };\n\n public readonly DeepSearchForAnyLevelContent = (name: string) => {\n const weaveResultSelf = this.ContentWithNameAtLevel(\n name,\n FlowLevel.WeavePoint,\n false\n );\n\n if (weaveResultSelf) {\n return weaveResultSelf;\n }\n\n for (const [, value] of this._subFlowsByName) {\n const deepResult = value.ContentWithNameAtLevel(name, null, true);\n\n if (deepResult) {\n return deepResult;\n }\n }\n\n return null;\n };\n\n public ResolveReferences(context: any): void {\n if (this._startingSubFlowDivert) {\n if (!this._startingSubFlowRuntime) {\n throw new Error();\n }\n\n this._startingSubFlowDivert.targetPath =\n this._startingSubFlowRuntime.path;\n }\n\n super.ResolveReferences(context);\n\n // Check validity of parameter names\n if (this.args !== null) {\n for (const arg of this.args) {\n context.CheckForNamingCollisions(\n this,\n arg.identifier,\n SymbolType.Arg,\n \"argument\"\n );\n }\n\n // Separately, check for duplicate arugment names, since they aren't Parsed.Objects,\n // so have to be checked independently.\n for (let ii = 0; ii < this.args.length; ii += 1) {\n for (let jj = ii + 1; jj < this.args.length; jj += 1) {\n if (\n this.args[ii].identifier?.name == this.args[jj].identifier?.name\n ) {\n this.Error(\n `Multiple arguments with the same name: '${this.args[ii].identifier}'`\n );\n }\n }\n }\n }\n\n // Check naming collisions for knots and stitches\n if (this.flowLevel !== FlowLevel.Story) {\n // Weave points aren't FlowBases, so this will only be knot or stitch\n const symbolType =\n this.flowLevel === FlowLevel.Knot\n ? SymbolType.Knot\n : SymbolType.SubFlowAndWeave;\n\n context.CheckForNamingCollisions(this, this.identifier, symbolType);\n }\n }\n\n public readonly CheckForDisallowedFunctionFlowControl = (): void => {\n // if (!(this instanceof Knot)) { // cannont use Knot here because of circular dependancy\n if (this.flowLevel !== FlowLevel.Knot) {\n this.Error(\n \"Functions cannot be stitches - i.e. they should be defined as '== function myFunc ==' rather than internal to another knot.\"\n );\n }\n\n // Not allowed sub-flows\n for (const [key, value] of this._subFlowsByName) {\n this.Error(\n `Functions may not contain stitches, but saw '${key}' within the function '${this.identifier}'`,\n value\n );\n }\n\n if (!this._rootWeave) {\n throw new Error();\n }\n\n const allDiverts = this._rootWeave.FindAll(Divert)();\n for (const divert of allDiverts) {\n if (!divert.isFunctionCall && !(divert.parent instanceof DivertTarget)) {\n this.Error(\n `Functions may not contain diverts, but saw '${divert}'`,\n divert\n );\n }\n }\n\n const allChoices = this._rootWeave.FindAll(Choice)();\n for (const choice of allChoices) {\n this.Error(\n `Functions may not contain choices, but saw '${choice}'`,\n choice\n );\n }\n };\n\n public readonly WarningInTermination = (terminatingObject: ParsedObject) => {\n let message: string =\n \"Apparent loose end exists where the flow runs out. Do you need a '-> DONE' statement, choice or divert?\";\n if (terminatingObject.parent === this._rootWeave && this._firstChildFlow) {\n message = `${message} Note that if you intend to enter '${this._firstChildFlow.identifier}' next, you need to divert to it explicitly.`;\n }\n\n const terminatingDivert = asOrNull(terminatingObject, Divert);\n if (terminatingDivert && terminatingDivert.isTunnel) {\n message += ` When final tunnel to '${terminatingDivert.target} ->' returns it won't have anywhere to go.`;\n }\n\n this.Warning(message, terminatingObject);\n };\n\n public readonly toString = (): string =>\n `${this.typeName} '${this.identifier}'`;\n}\n","import { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Text } from \"./Text\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\n\nexport class ContentList extends ParsedObject {\n public dontFlatten: boolean = false;\n\n get runtimeContainer(): RuntimeContainer {\n return this.runtimeObject as RuntimeContainer;\n }\n\n constructor(objects?: ParsedObject[], ...moreObjects: ParsedObject[]) {\n super();\n\n if (objects) {\n this.AddContent(objects);\n }\n\n if (moreObjects) {\n this.AddContent(moreObjects);\n }\n }\n\n get typeName(): string {\n return \"ContentList\";\n }\n\n public readonly TrimTrailingWhitespace = (): void => {\n for (let ii = this.content.length - 1; ii >= 0; --ii) {\n const text = asOrNull(this.content[ii], Text);\n if (text === null) {\n break;\n }\n\n text.text = text.text.replace(new RegExp(/[ \\t]/g), \"\");\n if (text.text.length === 0) {\n this.content.splice(ii, 1);\n } else {\n break;\n }\n }\n };\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n if (this.content !== null) {\n for (const obj of this.content) {\n const contentObjRuntime = obj.runtimeObject;\n\n // Some objects (e.g. author warnings) don't generate runtime objects\n if (contentObjRuntime) {\n container.AddContent(contentObjRuntime);\n }\n }\n }\n\n if (this.dontFlatten) {\n this.story.DontFlattenContainer(container);\n }\n\n return container;\n };\n\n public toString = (): string => `ContentList(${this.content.join(\", \")})`;\n}\n","import { InkObject } from \"./Object\";\nimport { Path } from \"./Path\";\n\nexport class VariableReference extends InkObject {\n public name: string | null;\n public pathForCount: Path | null = null;\n\n get containerForCount() {\n if (this.pathForCount === null) return null;\n return this.ResolvePath(this.pathForCount).container;\n }\n get pathStringForCount() {\n if (this.pathForCount === null) return null;\n\n return this.CompactPathString(this.pathForCount);\n }\n set pathStringForCount(value: string | null) {\n if (value === null) this.pathForCount = null;\n else this.pathForCount = new Path(value);\n }\n\n constructor(name: string | null = null) {\n super();\n this.name = name;\n }\n\n public toString() {\n if (this.name != null) {\n return \"var(\" + this.name + \")\";\n } else {\n let pathStr = this.pathStringForCount;\n return \"read_count(\" + pathStr + \")\";\n }\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ContentList } from \"../ContentList\";\nimport { Expression } from \"../Expression/Expression\";\nimport { FlowBase } from \"../Flow/FlowBase\";\nimport { ParsedObject } from \"../Object\";\nimport { Path } from \"../Path\";\nimport { Story } from \"../Story\";\nimport { VariableReference as RuntimeVariableReference } from \"../../../../engine/VariableReference\";\nimport { Weave } from \"../Weave\";\nimport { Identifier } from \"../Identifier\";\nimport { asOrNull, filterUndef } from \"../../../../engine/TypeAssertion\";\n\nexport class VariableReference extends Expression {\n private _runtimeVarRef: RuntimeVariableReference | null = null;\n\n // - Normal variables have a single item in their \"path\"\n // - Knot/stitch names for read counts are actual dot-separated paths\n // (though this isn't actually used at time of writing)\n // - List names are dot separated: listName.itemName (or just itemName)\n get name() {\n return this.path.join(\".\");\n }\n\n get path(): string[] {\n return this.pathIdentifiers.map((id) => id.name!).filter(filterUndef);\n }\n\n get identifier(): Identifier | null {\n if (!this.pathIdentifiers || this.pathIdentifiers.length == 0) {\n return null;\n }\n const name = this.path.join(\".\");\n const id = new Identifier(name);\n\n return id;\n }\n\n // Only known after GenerateIntoContainer has run\n public isConstantReference: boolean = false;\n public isListItemReference: boolean = false;\n\n get runtimeVarRef() {\n return this._runtimeVarRef;\n }\n\n constructor(public readonly pathIdentifiers: Identifier[]) {\n super();\n }\n\n get typeName(): string {\n return \"ref\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n let constantValue: Expression | null | undefined = this.story.constants.get(\n this.name\n );\n\n // If it's a constant reference, just generate the literal expression value\n // It's okay to access the constants at code generation time, since the\n // first thing the ExportRuntime function does it search for all the constants\n // in the story hierarchy, so they're all available.\n if (constantValue) {\n constantValue.GenerateConstantIntoContainer(container);\n this.isConstantReference = true;\n\n return;\n }\n\n this._runtimeVarRef = new RuntimeVariableReference(this.name);\n\n // List item reference?\n // Path might be to a list (listName.listItemName or just listItemName)\n if (this.path.length === 1 || this.path.length === 2) {\n let listItemName: string = \"\";\n let listName: string = \"\";\n\n if (this.path.length === 1) {\n listItemName = this.path[0];\n } else {\n listName = this.path[0];\n listItemName = this.path[1];\n }\n\n const listItem = this.story.ResolveListItem(listName, listItemName, this);\n\n if (listItem) {\n this.isListItemReference = true;\n }\n }\n\n container.AddContent(this._runtimeVarRef);\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n // Work is already done if it's a constant or list item reference\n if (this.isConstantReference || this.isListItemReference) {\n return;\n }\n\n // Is it a read count?\n const parsedPath = new Path(this.pathIdentifiers);\n const targetForCount: ParsedObject | null =\n parsedPath.ResolveFromContext(this);\n if (targetForCount) {\n if (!targetForCount.containerForCounting) {\n throw new Error();\n }\n\n targetForCount.containerForCounting.visitsShouldBeCounted = true;\n\n // If this is an argument to a function that wants a variable to be\n // passed by reference, then the Parsed.Divert will have generated a\n // Runtime.VariablePointerValue instead of allowing this object\n // to generate its RuntimeVariableReference. This only happens under\n // error condition since we shouldn't be passing a read count by\n // reference, but we don't want it to crash!\n if (this._runtimeVarRef === null) {\n return;\n }\n\n this._runtimeVarRef.pathForCount = targetForCount.runtimePath;\n this._runtimeVarRef.name = null;\n\n // Check for very specific writer error: getting read count and\n // printing it as content rather than as a piece of logic\n // e.g. Writing {myFunc} instead of {myFunc()}\n let targetFlow = asOrNull(targetForCount, FlowBase);\n if (targetFlow && targetFlow.isFunction) {\n // Is parent context content rather than logic?\n if (\n this.parent instanceof Weave ||\n this.parent instanceof ContentList ||\n this.parent instanceof FlowBase\n ) {\n this.Warning(\n `'${targetFlow.identifier}' being used as read count rather than being called as function. Perhaps you intended to write ${targetFlow.identifier}()`\n );\n }\n }\n\n return;\n }\n\n // Couldn't find this multi-part path at all, whether as a divert\n // target or as a list item reference.\n if (this.path.length > 1) {\n let errorMsg = `Could not find target for read count: ${parsedPath}`;\n if (this.path.length <= 2) {\n errorMsg += `, or couldn't find list item with the name ${this.path.join(\n \",\"\n )}`;\n }\n\n this.Error(errorMsg);\n\n return;\n }\n\n if (!context.ResolveVariableWithName(this.name, this).found) {\n this.Error(`Unresolved variable: ${this.name}`, this);\n }\n }\n\n public readonly toString = (): string => `{${this.path.join(\".\")}}`;\n}\n","import { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../engine/ControlCommand\";\nimport { Divert } from \"./Divert/Divert\";\nimport { Divert as RuntimeDivert } from \"../../../engine/Divert\";\nimport { DivertTarget } from \"./Divert/DivertTarget\";\nimport { Expression } from \"./Expression/Expression\";\nimport { InkList as RuntimeInkList } from \"../../../engine/InkList\";\nimport { ListValue } from \"../../../engine/Value\";\nimport { NativeFunctionCall } from \"../../../engine/NativeFunctionCall\";\nimport { NumberExpression } from \"./Expression/NumberExpression\";\nimport { Path } from \"./Path\";\nimport { Story } from \"./Story\";\nimport { StringValue } from \"../../../engine/Value\";\nimport { VariableReference } from \"./Variable/VariableReference\";\nimport { Identifier } from \"./Identifier\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\n\nexport class FunctionCall extends Expression {\n public static readonly IsBuiltIn = (name: string): boolean => {\n if (NativeFunctionCall.CallExistsWithName(name)) {\n return true;\n }\n\n return (\n name === \"CHOICE_COUNT\" ||\n name === \"TURNS_SINCE\" ||\n name === \"TURNS\" ||\n name === \"RANDOM\" ||\n name === \"SEED_RANDOM\" ||\n name === \"LIST_VALUE\" ||\n name === \"LIST_RANDOM\" ||\n name === \"READ_COUNT\"\n );\n };\n\n private _proxyDivert: Divert;\n get proxyDivert(): Divert {\n return this._proxyDivert;\n }\n private _divertTargetToCount: DivertTarget | null = null;\n private _variableReferenceToCount: VariableReference | null = null;\n\n get name(): string {\n return (this._proxyDivert.target as Path).firstComponent || \"\";\n }\n\n get args(): Expression[] {\n return this._proxyDivert.args;\n }\n\n get runtimeDivert(): RuntimeDivert {\n return this._proxyDivert.runtimeDivert;\n }\n\n get isChoiceCount(): boolean {\n return this.name === \"CHOICE_COUNT\";\n }\n\n get isTurns(): boolean {\n return this.name === \"TURNS\";\n }\n\n get isTurnsSince(): boolean {\n return this.name === \"TURNS_SINCE\";\n }\n\n get isRandom(): boolean {\n return this.name === \"RANDOM\";\n }\n\n get isSeedRandom(): boolean {\n return this.name === \"SEED_RANDOM\";\n }\n\n get isListRange(): boolean {\n return this.name === \"LIST_RANGE\";\n }\n\n get isListRandom(): boolean {\n return this.name === \"LIST_RANDOM\";\n }\n\n get isReadCount(): boolean {\n return this.name === \"READ_COUNT\";\n }\n\n public shouldPopReturnedValue: boolean = false;\n\n constructor(functionName: Identifier, args: Expression[]) {\n super();\n\n this._proxyDivert = new Divert(new Path(functionName), args);\n this._proxyDivert.isFunctionCall = true;\n this.AddContent(this._proxyDivert);\n }\n\n get typeName(): string {\n return \"FunctionCall\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n const foundList = this.story.ResolveList(this.name);\n\n let usingProxyDivert: boolean = false;\n\n if (this.isChoiceCount) {\n if (this.args.length > 0) {\n this.Error(\"The CHOICE_COUNT() function shouldn't take any arguments\");\n }\n\n container.AddContent(RuntimeControlCommand.ChoiceCount());\n } else if (this.isTurns) {\n if (this.args.length > 0) {\n this.Error(\"The TURNS() function shouldn't take any arguments\");\n }\n\n container.AddContent(RuntimeControlCommand.Turns());\n } else if (this.isTurnsSince || this.isReadCount) {\n const divertTarget = asOrNull(this.args[0], DivertTarget);\n const variableDivertTarget = asOrNull(this.args[0], VariableReference);\n\n if (\n this.args.length !== 1 ||\n (divertTarget === null && variableDivertTarget === null)\n ) {\n this.Error(\n `The ${this.name}() function should take one argument: a divert target to the target knot, stitch, gather or choice you want to check. e.g. TURNS_SINCE(-> myKnot)`\n );\n return;\n }\n\n if (divertTarget) {\n this._divertTargetToCount = divertTarget;\n this.AddContent(this._divertTargetToCount);\n\n this._divertTargetToCount.GenerateIntoContainer(container);\n } else if (variableDivertTarget) {\n this._variableReferenceToCount = variableDivertTarget;\n this.AddContent(this._variableReferenceToCount);\n\n this._variableReferenceToCount.GenerateIntoContainer(container);\n }\n\n if (this.isTurnsSince) {\n container.AddContent(RuntimeControlCommand.TurnsSince());\n } else {\n container.AddContent(RuntimeControlCommand.ReadCount());\n }\n } else if (this.isRandom) {\n if (this.args.length !== 2) {\n this.Error(\n \"RANDOM should take 2 parameters: a minimum and a maximum integer\"\n );\n }\n\n // We can type check single values, but not complex expressions\n for (let ii = 0; ii < this.args.length; ii += 1) {\n const num = asOrNull(this.args[ii], NumberExpression);\n if (num && !num.isInt()) {\n const paramName: string = ii === 0 ? \"minimum\" : \"maximum\";\n this.Error(`RANDOM's ${paramName} parameter should be an integer`);\n }\n\n this.args[ii].GenerateIntoContainer(container);\n }\n\n container.AddContent(RuntimeControlCommand.Random());\n } else if (this.isSeedRandom) {\n if (this.args.length !== 1) {\n this.Error(\"SEED_RANDOM should take 1 parameter - an integer seed\");\n }\n\n const num = asOrNull(this.args[0], NumberExpression);\n if (num && !num.isInt()) {\n this.Error(\"SEED_RANDOM's parameter should be an integer seed\");\n }\n\n this.args[0].GenerateIntoContainer(container);\n\n container.AddContent(RuntimeControlCommand.SeedRandom());\n } else if (this.isListRange) {\n if (this.args.length !== 3) {\n this.Error(\n \"LIST_RANGE should take 3 parameters - a list, a min and a max\"\n );\n }\n\n for (let ii = 0; ii < this.args.length; ii += 1) {\n this.args[ii].GenerateIntoContainer(container);\n }\n\n container.AddContent(RuntimeControlCommand.ListRange());\n } else if (this.isListRandom) {\n if (this.args.length !== 1) {\n this.Error(\"LIST_RANDOM should take 1 parameter - a list\");\n }\n\n this.args[0].GenerateIntoContainer(container);\n\n container.AddContent(RuntimeControlCommand.ListRandom());\n } else if (NativeFunctionCall.CallExistsWithName(this.name)) {\n const nativeCall = NativeFunctionCall.CallWithName(this.name);\n if (nativeCall.numberOfParameters !== this.args.length) {\n let msg = `${FunctionCall.name} should take ${nativeCall.numberOfParameters} parameter`;\n if (nativeCall.numberOfParameters > 1) {\n msg += \"s\";\n }\n\n this.Error(msg);\n }\n\n for (let ii = 0; ii < this.args.length; ii += 1) {\n this.args[ii].GenerateIntoContainer(container);\n }\n\n container.AddContent(NativeFunctionCall.CallWithName(this.name));\n } else if (foundList !== null) {\n if (this.args.length > 1) {\n this.Error(\n \"Can currently only construct a list from one integer (or an empty list from a given list definition)\"\n );\n }\n\n // List item from given int\n if (this.args.length === 1) {\n container.AddContent(new StringValue(this.name));\n this.args[0].GenerateIntoContainer(container);\n container.AddContent(RuntimeControlCommand.ListFromInt());\n } else {\n // Empty list with given origin.\n const list = new RuntimeInkList();\n list.SetInitialOriginName(this.name);\n container.AddContent(new ListValue(list));\n }\n } else {\n // Normal function call\n container.AddContent(this._proxyDivert.runtimeObject);\n usingProxyDivert = true;\n }\n\n // Don't attempt to resolve as a divert if we're not doing a normal function call\n if (!usingProxyDivert) {\n this.content.splice(this.content.indexOf(this._proxyDivert), 1);\n }\n\n // Function calls that are used alone on a tilda-based line:\n // ~ func()\n // Should tidy up any returned value from the evaluation stack,\n // since it's unused.\n if (this.shouldPopReturnedValue) {\n container.AddContent(RuntimeControlCommand.PopEvaluatedValue());\n }\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n // If we aren't using the proxy divert after all (e.g. if\n // it's a native function call), but we still have arguments,\n // we need to make sure they get resolved since the proxy divert\n // is no longer in the content array.\n if (!this.content.includes(this._proxyDivert) && this.args !== null) {\n for (const arg of this.args) {\n arg.ResolveReferences(context);\n }\n }\n\n if (this._divertTargetToCount) {\n const divert = this._divertTargetToCount.divert;\n const attemptingTurnCountOfVariableTarget =\n divert.runtimeDivert.variableDivertName != null;\n\n if (attemptingTurnCountOfVariableTarget) {\n this.Error(\n `When getting the TURNS_SINCE() of a variable target, remove the '->' - i.e. it should just be TURNS_SINCE(${divert.runtimeDivert.variableDivertName})`\n );\n\n return;\n }\n\n const targetObject = divert.targetContent;\n if (targetObject === null) {\n if (!attemptingTurnCountOfVariableTarget) {\n this.Error(\n `Failed to find target for TURNS_SINCE: '${divert.target}'`\n );\n }\n } else {\n if (!targetObject.containerForCounting) {\n throw new Error();\n }\n\n targetObject.containerForCounting.turnIndexShouldBeCounted = true;\n }\n } else if (this._variableReferenceToCount) {\n const runtimeVarRef = this._variableReferenceToCount.runtimeVarRef;\n if (!runtimeVarRef) {\n throw new Error();\n }\n\n if (runtimeVarRef.pathForCount !== null) {\n this.Error(\n `Should be '${FunctionCall.name}'(-> '${this._variableReferenceToCount.name}). Usage without the '->' only makes sense for variable targets.`\n );\n }\n }\n }\n\n public readonly toString = (): string => {\n const strArgs = this.args.join(\", \");\n return `${this.name}(${strArgs})`;\n };\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"./Expression\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\n\nexport class MultipleConditionExpression extends Expression {\n get subExpressions(): Expression[] {\n return this.content as Expression[];\n }\n\n constructor(conditionExpressions: Expression[]) {\n super();\n\n this.AddContent(conditionExpressions);\n }\n\n get typeName(): string {\n return \"MultipleConditionExpression\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n // A && B && C && D\n // => (((A B &&) C &&) D &&) etc\n let isFirst: boolean = true;\n for (const conditionExpr of this.subExpressions) {\n conditionExpr.GenerateIntoContainer(container);\n\n if (!isFirst) {\n container.AddContent(NativeFunctionCall.CallWithName(\"&&\"));\n }\n\n isFirst = false;\n }\n };\n}\n","import { BinaryExpression } from \"../Expression/BinaryExpression\";\nimport { Choice } from \"../Choice\";\nimport { Conditional } from \"../Conditional/Conditional\";\nimport { ConditionalSingleBranch } from \"../Conditional/ConditionalSingleBranch\";\nimport { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ParsedObject } from \"../Object\";\nimport { Divert } from \"./Divert\";\nimport { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { DivertTargetValue } from \"../../../../engine/Value\";\nimport { Expression } from \"../Expression/Expression\";\nimport { FlowBase } from \"../Flow/FlowBase\";\nimport { FunctionCall } from \"../FunctionCall\";\nimport { MultipleConditionExpression } from \"../Expression/MultipleConditionExpression\";\nimport { Story } from \"../Story\";\nimport { VariableReference } from \"../Variable/VariableReference\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class DivertTarget extends Expression {\n private _runtimeDivert: RuntimeDivert | null = null;\n get runtimeDivert(): RuntimeDivert {\n if (!this._runtimeDivert) {\n throw new Error();\n }\n\n return this._runtimeDivert;\n }\n\n private _runtimeDivertTargetValue: DivertTargetValue | null = null;\n get runtimeDivertTargetValue(): DivertTargetValue {\n if (!this._runtimeDivertTargetValue) {\n throw new Error();\n }\n\n return this._runtimeDivertTargetValue;\n }\n\n public divert: Divert;\n\n constructor(divert: Divert) {\n super();\n\n this.divert = this.AddContent(divert) as Divert;\n }\n\n get typeName(): string {\n return \"DivertTarget\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n this.divert.GenerateRuntimeObject();\n\n this._runtimeDivert = this.divert.runtimeDivert as RuntimeDivert;\n this._runtimeDivertTargetValue = new DivertTargetValue();\n\n container.AddContent(this.runtimeDivertTargetValue);\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n if (this.divert.isDone || this.divert.isEnd) {\n this.Error(\n `Can't use -> DONE or -> END as variable divert targets`,\n this\n );\n\n return;\n }\n\n let usageContext: ParsedObject | null = this;\n while (usageContext && usageContext instanceof Expression) {\n let badUsage: boolean = false;\n let foundUsage: boolean = false;\n\n const usageParent: any = (usageContext as Expression).parent;\n if (usageParent instanceof BinaryExpression) {\n // Only allowed to compare for equality\n\n const binaryExprParent = usageParent;\n if (\n binaryExprParent.opName !== \"==\" &&\n binaryExprParent.opName !== \"!=\"\n ) {\n badUsage = true;\n } else {\n if (\n !(\n binaryExprParent.leftExpression instanceof DivertTarget ||\n binaryExprParent.leftExpression instanceof VariableReference\n )\n ) {\n badUsage = true;\n } else if (\n !(\n binaryExprParent.rightExpression instanceof DivertTarget ||\n binaryExprParent.rightExpression instanceof VariableReference\n )\n ) {\n badUsage = true;\n }\n }\n\n foundUsage = true;\n } else if (usageParent instanceof FunctionCall) {\n const funcCall = usageParent;\n if (!funcCall.isTurnsSince && !funcCall.isReadCount) {\n badUsage = true;\n }\n\n foundUsage = true;\n } else if (usageParent instanceof Expression) {\n badUsage = true;\n foundUsage = true;\n } else if (usageParent instanceof MultipleConditionExpression) {\n badUsage = true;\n foundUsage = true;\n } else if (\n usageParent instanceof Choice &&\n (usageParent as Choice).condition === usageContext\n ) {\n badUsage = true;\n foundUsage = true;\n } else if (\n usageParent instanceof Conditional ||\n usageParent instanceof ConditionalSingleBranch\n ) {\n badUsage = true;\n foundUsage = true;\n }\n\n if (badUsage) {\n this.Error(\n `Can't use a divert target like that. Did you intend to call '${this.divert.target}' as a function: likeThis(), or check the read count: likeThis, with no arrows?`,\n this\n );\n }\n\n if (foundUsage) {\n break;\n }\n\n usageContext = usageParent;\n }\n\n // Example ink for this case:\n //\n // VAR x = -> blah\n //\n // ...which means that \"blah\" is expected to be a literal stitch target rather\n // than a variable name. We can't really intelligently recover from this (e.g. if blah happens to\n // contain a divert target itself) since really we should be generating a variable reference\n // rather than a concrete DivertTarget, so we list it as an error.\n if (this.runtimeDivert.hasVariableTarget) {\n if (!this.divert.target) {\n throw new Error();\n }\n\n this.Error(\n `Since '${this.divert.target.dotSeparatedComponents}' is a variable, it shouldn't be preceded by '->' here.`\n );\n }\n\n // Main resolve\n this.runtimeDivert.targetPath &&\n (this.runtimeDivertTargetValue.targetPath =\n this.runtimeDivert.targetPath);\n\n // Tell hard coded (yet variable) divert targets that they also need to be counted\n // TODO: Only detect DivertTargets that are values rather than being used directly for\n // read or turn counts. Should be able to detect this by looking for other uses of containerForCounting\n let targetContent = this.divert.targetContent;\n if (targetContent !== null) {\n let target = targetContent.containerForCounting;\n if (target !== null) {\n // Purpose is known: used directly in TURNS_SINCE(-> divTarg)\n const parentFunc = asOrNull(this.parent, FunctionCall);\n if (parentFunc && parentFunc.isTurnsSince) {\n target.turnIndexShouldBeCounted = true;\n } else {\n // Unknown purpose, count everything\n target.visitsShouldBeCounted = true;\n target.turnIndexShouldBeCounted = true;\n }\n }\n\n // Unfortunately not possible:\n // https://github.com/inkle/ink/issues/538\n //\n // VAR func = -> double\n //\n // === function double(ref x)\n // ~ x = x * 2\n //\n // Because when generating the parameters for a function\n // to be called, it needs to know ahead of time when\n // compiling whether to pass a variable reference or value.\n //\n let targetFlow = asOrNull(targetContent, FlowBase);\n if (targetFlow != null && targetFlow.args !== null) {\n for (const arg of targetFlow.args) {\n if (arg.isByReference) {\n this.Error(\n `Can't store a divert target to a knot or function that has by-reference arguments ('${targetFlow.identifier}' has 'ref ${arg.identifier}').`\n );\n }\n }\n }\n }\n }\n\n // Equals override necessary in order to check for CONST multiple definition equality\n public readonly Equals = (obj: ParsedObject): boolean => {\n const otherDivTarget = asOrNull(obj, DivertTarget);\n if (\n !otherDivTarget ||\n !this.divert.target ||\n !otherDivTarget.divert.target\n ) {\n return false;\n }\n\n const targetStr = this.divert.target.dotSeparatedComponents;\n const otherTargetStr = otherDivTarget.divert.target.dotSeparatedComponents;\n\n return targetStr === otherTargetStr;\n };\n}\n","import { Argument } from \"../Argument\";\nimport { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { DivertTarget } from \"./DivertTarget\";\nimport { Expression } from \"../Expression/Expression\";\nimport { FlowBase } from \"../Flow/FlowBase\";\nimport { FunctionCall } from \"../FunctionCall\";\nimport { ParsedObject } from \"../Object\";\nimport { Path } from \"../Path\";\nimport { Path as RuntimePath } from \"../../../../engine/Path\";\nimport { PushPopType } from \"../../../../engine/PushPop\";\nimport { Story } from \"../Story\";\nimport { VariablePointerValue } from \"../../../../engine/Value\";\nimport { VariableReference } from \"../Variable/VariableReference\";\nimport { ClosestFlowBase } from \"../Flow/ClosestFlowBase\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class Divert extends ParsedObject {\n public readonly args: Expression[] = [];\n\n public readonly target: Path | null = null;\n public targetContent: ParsedObject | null = null;\n private _runtimeDivert: RuntimeDivert | null = null;\n get runtimeDivert(): RuntimeDivert {\n if (!this._runtimeDivert) {\n throw new Error();\n }\n\n return this._runtimeDivert;\n }\n\n set runtimeDivert(value: RuntimeDivert) {\n this._runtimeDivert = value;\n }\n\n public isFunctionCall: boolean = false;\n public isEmpty: boolean = false;\n public isTunnel: boolean = false;\n public isThread: boolean = false;\n\n get isEnd(): boolean {\n return Boolean(this.target && this.target.dotSeparatedComponents === \"END\");\n }\n\n get isDone(): boolean {\n return Boolean(\n this.target && this.target.dotSeparatedComponents === \"DONE\"\n );\n }\n\n constructor(target?: Path | null | undefined, args?: Expression[]) {\n super();\n\n if (target) {\n this.target = target;\n }\n\n if (args) {\n this.args = args;\n this.AddContent(args);\n }\n }\n\n get typeName(): string {\n return \"Divert\";\n }\n\n public readonly GenerateRuntimeObject = () => {\n // End = end flow immediately\n // Done = return from thread or instruct the flow that it's safe to exit\n if (this.isEnd) {\n return RuntimeControlCommand.End();\n } else if (this.isDone) {\n return RuntimeControlCommand.Done();\n }\n\n this.runtimeDivert = new RuntimeDivert();\n\n // Normally we resolve the target content during the\n // Resolve phase, since we expect all runtime objects to\n // be available in order to find the final runtime path for\n // the destination. However, we need to resolve the target\n // (albeit without the runtime target) early so that\n // we can get information about the arguments - whether\n // they're by reference - since it affects the code we\n // generate here.\n this.ResolveTargetContent();\n\n this.CheckArgumentValidity();\n\n // Passing arguments to the knot\n const requiresArgCodeGen = this.args !== null && this.args.length > 0;\n if (\n requiresArgCodeGen ||\n this.isFunctionCall ||\n this.isTunnel ||\n this.isThread\n ) {\n const container = new RuntimeContainer();\n\n // Generate code for argument evaluation\n // This argument generation is coded defensively - it should\n // attempt to generate the code for all the parameters, even if\n // they don't match the expected arguments. This is so that the\n // parameter objects themselves are generated correctly and don't\n // get into a state of attempting to resolve references etc\n // without being generated.\n if (requiresArgCodeGen) {\n // Function calls already in an evaluation context\n if (!this.isFunctionCall) {\n container.AddContent(RuntimeControlCommand.EvalStart());\n }\n\n let targetArguments: Argument[] | null = null;\n if (this.targetContent) {\n targetArguments = (this.targetContent as FlowBase).args;\n }\n\n for (let ii = 0; ii < this.args.length; ++ii) {\n const argToPass: Expression = this.args[ii];\n let argExpected: Argument | null = null;\n if (targetArguments && ii < targetArguments.length) {\n argExpected = targetArguments[ii];\n }\n\n // Pass by reference: argument needs to be a variable reference\n if (argExpected && argExpected.isByReference) {\n const varRef = asOrNull(argToPass, VariableReference);\n if (!varRef) {\n this.Error(\n `Expected variable name to pass by reference to 'ref ${argExpected.identifier}' but saw ${argToPass}`\n );\n\n break;\n }\n\n // Check that we're not attempting to pass a read count by reference\n const targetPath = new Path(varRef.pathIdentifiers);\n const targetForCount: ParsedObject | null =\n targetPath.ResolveFromContext(this);\n if (targetForCount) {\n this.Error(\n `can't pass a read count by reference. '${\n targetPath.dotSeparatedComponents\n }' is a knot/stitch/label, but '${\n this.target!.dotSeparatedComponents\n }' requires the name of a VAR to be passed.`\n );\n\n break;\n }\n\n const varPointer = new VariablePointerValue(varRef.name);\n container.AddContent(varPointer);\n } else {\n // Normal value being passed: evaluate it as normal\n argToPass.GenerateIntoContainer(container);\n }\n }\n\n // Function calls were already in an evaluation context\n if (!this.isFunctionCall) {\n container.AddContent(RuntimeControlCommand.EvalEnd());\n }\n }\n\n // Starting a thread? A bit like a push to the call stack below... but not.\n // It sort of puts the call stack on a thread stack (argh!) - forks the full flow.\n if (this.isThread) {\n container.AddContent(RuntimeControlCommand.StartThread());\n } else if (this.isFunctionCall || this.isTunnel) {\n // If this divert is a function call, tunnel, we push to the call stack\n // so we can return again\n this.runtimeDivert.pushesToStack = true;\n this.runtimeDivert.stackPushType = this.isFunctionCall\n ? PushPopType.Function\n : PushPopType.Tunnel;\n }\n\n // Jump into the \"function\" (knot/stitch)\n container.AddContent(this.runtimeDivert);\n\n return container;\n }\n\n // Simple divert\n return this.runtimeDivert;\n };\n\n // When the divert is to a target that's actually a variable name\n // rather than an explicit knot/stitch name, try interpretting it\n // as such by getting the variable name.\n public readonly PathAsVariableName = () =>\n this.target ? this.target.firstComponent : null;\n\n public readonly ResolveTargetContent = (): void => {\n if (this.isEmpty || this.isEnd) {\n return;\n }\n\n if (this.targetContent === null) {\n // Is target of this divert a variable name that will be de-referenced\n // at runtime? If so, there won't be any further reference resolution\n // we can do at this point.\n let variableTargetName = this.PathAsVariableName();\n if (variableTargetName !== null) {\n const flowBaseScope = asOrNull(ClosestFlowBase(this), FlowBase);\n if (flowBaseScope) {\n const resolveResult = flowBaseScope.ResolveVariableWithName(\n variableTargetName,\n this\n );\n\n if (resolveResult.found) {\n // Make sure that the flow was typed correctly, given that we know that this\n // is meant to be a divert target\n if (\n resolveResult.isArgument &&\n resolveResult.ownerFlow &&\n resolveResult.ownerFlow.args\n ) {\n let argument = resolveResult.ownerFlow.args.find(\n (a) => a.identifier?.name == variableTargetName\n );\n\n if (argument && !argument.isDivertTarget) {\n this.Error(\n `Since '${argument.identifier}' is used as a variable divert target (on ${this.debugMetadata}), it should be marked as: -> ${argument.identifier}`,\n resolveResult.ownerFlow\n );\n }\n }\n\n this.runtimeDivert.variableDivertName = variableTargetName;\n return;\n }\n }\n }\n\n if (!this.target) {\n throw new Error();\n }\n\n this.targetContent = this.target.ResolveFromContext(this);\n }\n };\n\n public ResolveReferences(context: Story): void {\n if (this.isEmpty || this.isEnd || this.isDone) {\n return;\n } else if (!this.runtimeDivert) {\n throw new Error();\n }\n\n if (this.targetContent) {\n this.runtimeDivert.targetPath = this.targetContent.runtimePath;\n }\n\n // Resolve children (the arguments)\n super.ResolveReferences(context);\n\n // May be null if it's a built in function (e.g. TURNS_SINCE)\n // or if it's a variable target.\n let targetFlow = asOrNull(this.targetContent, FlowBase);\n if (targetFlow) {\n if (!targetFlow.isFunction && this.isFunctionCall) {\n super.Error(\n `${targetFlow.identifier} hasn't been marked as a function, but it's being called as one. Do you need to declare the knot as '== function ${targetFlow.identifier} =='?`\n );\n } else if (\n targetFlow.isFunction &&\n !this.isFunctionCall &&\n !(this.parent instanceof DivertTarget)\n ) {\n super.Error(\n targetFlow.identifier +\n \" can't be diverted to. It can only be called as a function since it's been marked as such: '\" +\n targetFlow.identifier +\n \"(...)'\"\n );\n }\n }\n\n // Check validity of target content\n const targetWasFound = this.targetContent !== null;\n let isBuiltIn: boolean = false;\n let isExternal: boolean = false;\n\n if (!this.target) {\n throw new Error();\n } else if (this.target.numberOfComponents === 1) {\n if (!this.target.firstComponent) {\n throw new Error();\n }\n\n // BuiltIn means TURNS_SINCE, CHOICE_COUNT, RANDOM or SEED_RANDOM\n isBuiltIn = FunctionCall.IsBuiltIn(this.target.firstComponent);\n\n // Client-bound function?\n isExternal = context.IsExternal(this.target.firstComponent);\n\n if (isBuiltIn || isExternal) {\n if (!this.isFunctionCall) {\n super.Error(\n `${this.target.firstComponent} must be called as a function: ~ ${this.target.firstComponent}()`\n );\n }\n\n if (isExternal) {\n this.runtimeDivert.isExternal = true;\n if (this.args !== null) {\n this.runtimeDivert.externalArgs = this.args.length;\n }\n\n this.runtimeDivert.pushesToStack = false;\n this.runtimeDivert.targetPath = new RuntimePath(\n this.target.firstComponent\n );\n\n this.CheckExternalArgumentValidity(context);\n }\n\n return;\n }\n }\n\n // Variable target?\n if (this.runtimeDivert.variableDivertName != null) {\n return;\n }\n\n if (!targetWasFound && !isBuiltIn && !isExternal) {\n this.Error(`target not found: '${this.target}'`);\n }\n }\n\n // Returns false if there's an error\n public readonly CheckArgumentValidity = (): void => {\n if (this.isEmpty) {\n return;\n }\n\n // Argument passing: Check for errors in number of arguments\n let numArgs = 0;\n if (this.args !== null && this.args.length > 0) {\n numArgs = this.args.length;\n }\n\n // Missing content?\n // Can't check arguments properly. It'll be due to some\n // other error though, so although there's a problem and\n // we report false, we don't need to report a specific error.\n // It may also be because it's a valid call to an external\n // function, that we check at the resolve stage.\n if (this.targetContent === null) {\n return;\n }\n\n const targetFlow = asOrNull(this.targetContent, FlowBase);\n\n // No error, crikey!\n if (numArgs === 0 && (targetFlow === null || !targetFlow.hasParameters)) {\n return;\n } else if (targetFlow === null && numArgs > 0) {\n this.Error(\n \"target needs to be a knot or stitch in order to pass arguments\"\n );\n return;\n } else if (\n targetFlow !== null &&\n (targetFlow.args === null || (!targetFlow.args && numArgs > 0))\n ) {\n this.Error(`target (${targetFlow.name}) doesn't take parameters`);\n return;\n } else if (this.parent instanceof DivertTarget) {\n if (numArgs > 0) {\n this.Error(`can't store arguments in a divert target variable`);\n }\n\n return;\n }\n\n const paramCount = targetFlow!.args!.length;\n if (paramCount !== numArgs) {\n let butClause: string;\n if (numArgs === 0) {\n butClause = \"but there weren't any passed to it\";\n } else if (numArgs < paramCount) {\n butClause = `but only got ${numArgs}`;\n } else {\n butClause = `but got ${numArgs}`;\n }\n\n this.Error(\n `to '${\n targetFlow!.identifier\n }' requires ${paramCount} arguments, ${butClause}`\n );\n\n return;\n }\n\n // Light type-checking for divert target arguments\n for (let ii = 0; ii < paramCount; ++ii) {\n const flowArg: Argument = targetFlow!.args![ii];\n const divArgExpr: Expression = this.args[ii];\n\n // Expecting a divert target as an argument, let's do some basic type checking\n if (flowArg.isDivertTarget) {\n // Not passing a divert target or any kind of variable reference?\n let varRef = asOrNull(divArgExpr, VariableReference);\n if (!(divArgExpr instanceof DivertTarget) && varRef === null) {\n this.Error(\n `Target '${\n targetFlow!.identifier\n }' expects a divert target for the parameter named -> ${\n flowArg.identifier\n } but saw ${divArgExpr}`,\n divArgExpr\n );\n } else if (varRef) {\n // Passing 'a' instead of '-> a'?\n // i.e. read count instead of divert target\n // Unfortunately have to manually resolve here since we're still in code gen\n const knotCountPath = new Path(varRef.pathIdentifiers);\n const targetForCount: ParsedObject | null =\n knotCountPath.ResolveFromContext(varRef);\n if (targetForCount) {\n this.Error(\n `Passing read count of '${knotCountPath.dotSeparatedComponents}' instead of a divert target. You probably meant '${knotCountPath}'`\n );\n }\n }\n }\n }\n\n if (targetFlow === null) {\n this.Error(\n \"Can't call as a function or with arguments unless it's a knot or stitch\"\n );\n return;\n }\n\n return;\n };\n\n public readonly CheckExternalArgumentValidity = (context: Story): void => {\n const externalName: string | null = this.target\n ? this.target.firstComponent\n : null;\n const external = context.externals.get(externalName as string);\n if (!external) {\n throw new Error(\"external not found\");\n }\n\n const externalArgCount: number = external.argumentNames.length;\n let ownArgCount = 0;\n if (this.args) {\n ownArgCount = this.args.length;\n }\n\n if (ownArgCount !== externalArgCount) {\n this.Error(\n `incorrect number of arguments sent to external function '${externalName}'. Expected ${externalArgCount} but got ${ownArgCount}`\n );\n }\n };\n\n public Error(\n message: string,\n source: ParsedObject | null = null,\n isWarning: boolean = false\n ): void {\n // Could be getting an error from a nested Divert\n if (source !== this && source) {\n super.Error(message, source);\n return;\n }\n\n if (this.isFunctionCall) {\n super.Error(`Function call ${message}`, source, isWarning);\n } else {\n super.Error(`Divert ${message}`, source, isWarning);\n }\n }\n\n public toString = (): string => {\n let returnString = \"\";\n if (this.target !== null) {\n returnString += this.target.toString();\n } else {\n return \"-> \";\n }\n\n if (this.isTunnel) {\n returnString += \" ->\";\n }\n if (this.isFunctionCall) {\n returnString += \" ()\";\n }\n\n return returnString;\n };\n}\n","import { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\n\nexport class GatherPointToResolve {\n constructor(\n public divert: RuntimeDivert,\n public targetRuntimeObj: RuntimeObject\n ) {}\n}\n","import { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\n\nexport class SequenceDivertToResolve {\n constructor(\n public divert: RuntimeDivert,\n public targetContent: RuntimeObject\n ) {}\n}\n","export enum SequenceType {\n Stopping = 1, // default\n Cycle = 2,\n Shuffle = 4,\n Once = 8,\n}\n","import { ContentList } from \"../ContentList\";\nimport { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { IntValue } from \"../../../../engine/Value\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { SequenceDivertToResolve } from \"./SequenceDivertToResolve\";\nimport { SequenceType } from \"./SequenceType\";\nimport { Story } from \"../Story\";\nimport { Weave } from \"../Weave\";\n\nexport class Sequence extends ParsedObject {\n private _sequenceDivertsToResolve: SequenceDivertToResolve[] = [];\n\n public sequenceElements: ParsedObject[];\n\n constructor(\n elementContentLists: ContentList[],\n public readonly sequenceType: SequenceType\n ) {\n super();\n\n this.sequenceType = sequenceType;\n this.sequenceElements = [];\n\n for (const elementContentList of elementContentLists) {\n const contentObjs = elementContentList.content;\n let seqElObject: ParsedObject | null = null;\n\n // Don't attempt to create a weave for the sequence element\n // if the content list is empty. Weaves don't like it!\n if (contentObjs === null || contentObjs.length === 0) {\n seqElObject = elementContentList;\n } else {\n seqElObject = new Weave(contentObjs);\n }\n\n this.sequenceElements.push(seqElObject);\n this.AddContent(seqElObject);\n }\n }\n\n get typeName(): string {\n return \"Sequence\";\n }\n\n // Generate runtime code that looks like:\n //\n // chosenIndex = MIN(sequence counter, num elements) e.g. for \"Stopping\"\n // if chosenIndex == 0, divert to s0\n // if chosenIndex == 1, divert to s1 [etc]\n //\n // - s0:\n // \n // divert to no-op\n // - s1:\n // \n // divert to no-op\n // - s2:\n // empty branch if using \"once\"\n // divert to no-op\n //\n // no-op\n //\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n container.visitsShouldBeCounted = true;\n container.countingAtStartOnly = true;\n\n this._sequenceDivertsToResolve = [];\n\n // Get sequence read count\n container.AddContent(RuntimeControlCommand.EvalStart());\n container.AddContent(RuntimeControlCommand.VisitIndex());\n\n const once: boolean = (this.sequenceType & SequenceType.Once) > 0;\n const cycle: boolean = (this.sequenceType & SequenceType.Cycle) > 0;\n const stopping: boolean = (this.sequenceType & SequenceType.Stopping) > 0;\n const shuffle: boolean = (this.sequenceType & SequenceType.Shuffle) > 0;\n\n let seqBranchCount = this.sequenceElements.length;\n if (once) {\n seqBranchCount += 1;\n }\n\n // Chosen sequence index:\n // - Stopping: take the MIN(read count, num elements - 1)\n // - Once: take the MIN(read count, num elements)\n // (the last one being empty)\n if (stopping || once) {\n //var limit = stopping ? seqBranchCount-1 : seqBranchCount;\n container.AddContent(new IntValue(seqBranchCount - 1));\n container.AddContent(NativeFunctionCall.CallWithName(\"MIN\"));\n } else if (cycle) {\n // - Cycle: take (read count % num elements)\n container.AddContent(new IntValue(this.sequenceElements.length));\n container.AddContent(NativeFunctionCall.CallWithName(\"%\"));\n }\n\n // Shuffle\n if (shuffle) {\n // Create point to return to when sequence is complete\n const postShuffleNoOp = RuntimeControlCommand.NoOp();\n\n // When visitIndex == lastIdx, we skip the shuffle\n if (once || stopping) {\n // if( visitIndex == lastIdx ) -> skipShuffle\n const lastIdx = stopping\n ? this.sequenceElements.length - 1\n : this.sequenceElements.length;\n\n container.AddContent(RuntimeControlCommand.Duplicate());\n container.AddContent(new IntValue(lastIdx));\n container.AddContent(NativeFunctionCall.CallWithName(\"==\"));\n\n const skipShuffleDivert = new RuntimeDivert();\n skipShuffleDivert.isConditional = true;\n container.AddContent(skipShuffleDivert);\n\n this.AddDivertToResolve(skipShuffleDivert, postShuffleNoOp);\n }\n\n // This one's a bit more complex! Choose the index at runtime.\n let elementCountToShuffle = this.sequenceElements.length;\n if (stopping) {\n elementCountToShuffle -= 1;\n }\n\n container.AddContent(new IntValue(elementCountToShuffle));\n container.AddContent(RuntimeControlCommand.SequenceShuffleIndex());\n if (once || stopping) {\n container.AddContent(postShuffleNoOp);\n }\n }\n\n container.AddContent(RuntimeControlCommand.EvalEnd());\n\n // Create point to return to when sequence is complete\n const postSequenceNoOp = RuntimeControlCommand.NoOp();\n\n // Each of the main sequence branches, and one extra empty branch if\n // we have a \"once\" sequence.\n for (let elIndex = 0; elIndex < seqBranchCount; elIndex += 1) {\n // This sequence element:\n // if( chosenIndex == this index ) divert to this sequence element\n // duplicate chosen sequence index, since it'll be consumed by \"==\"\n container.AddContent(RuntimeControlCommand.EvalStart());\n container.AddContent(RuntimeControlCommand.Duplicate());\n container.AddContent(new IntValue(elIndex));\n container.AddContent(NativeFunctionCall.CallWithName(\"==\"));\n container.AddContent(RuntimeControlCommand.EvalEnd());\n\n // Divert branch for this sequence element\n const sequenceDivert = new RuntimeDivert();\n sequenceDivert.isConditional = true;\n container.AddContent(sequenceDivert);\n\n let contentContainerForSequenceBranch: RuntimeContainer;\n\n // Generate content for this sequence element\n if (elIndex < this.sequenceElements.length) {\n const el = this.sequenceElements[elIndex];\n contentContainerForSequenceBranch =\n el.runtimeObject as RuntimeContainer;\n } else {\n // Final empty branch for \"once\" sequences\n contentContainerForSequenceBranch = new RuntimeContainer();\n }\n\n contentContainerForSequenceBranch.name = `s${elIndex}`;\n contentContainerForSequenceBranch.InsertContent(\n RuntimeControlCommand.PopEvaluatedValue(),\n 0\n );\n\n // When sequence element is complete, divert back to end of sequence\n const seqBranchCompleteDivert = new RuntimeDivert();\n contentContainerForSequenceBranch.AddContent(seqBranchCompleteDivert);\n container.AddToNamedContentOnly(contentContainerForSequenceBranch);\n\n // Save the diverts for reference resolution later (in ResolveReferences)\n this.AddDivertToResolve(\n sequenceDivert,\n contentContainerForSequenceBranch\n );\n this.AddDivertToResolve(seqBranchCompleteDivert, postSequenceNoOp);\n }\n\n container.AddContent(postSequenceNoOp);\n\n return container;\n };\n\n public readonly AddDivertToResolve = (\n divert: RuntimeDivert,\n targetContent: RuntimeObject\n ) => {\n this._sequenceDivertsToResolve.push(\n new SequenceDivertToResolve(divert, targetContent)\n );\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n for (const toResolve of this._sequenceDivertsToResolve) {\n toResolve.divert.targetPath = toResolve.targetContent.path;\n }\n }\n}\n","import { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../engine/ControlCommand\";\nimport { Divert } from \"./Divert/Divert\";\nimport { Divert as RuntimeDivert } from \"../../../engine/Divert\";\nimport { DivertTargetValue } from \"../../../engine/Value\";\nimport { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Story } from \"./Story\";\nimport { Void } from \"../../../engine/Void\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\nimport { VariableReference } from \"../../../engine/VariableReference\";\n\nexport class TunnelOnwards extends ParsedObject {\n private _overrideDivertTarget: DivertTargetValue | null = null;\n\n private _divertAfter: Divert | null = null;\n get divertAfter() {\n return this._divertAfter;\n }\n\n set divertAfter(value) {\n this._divertAfter = value;\n if (this._divertAfter) {\n this.AddContent(this._divertAfter);\n }\n }\n\n get typeName(): string {\n return \"TunnelOnwards\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n\n // Set override path for tunnel onwards (or nothing)\n container.AddContent(RuntimeControlCommand.EvalStart());\n\n if (this.divertAfter) {\n // Generate runtime object's generated code and steal the arguments runtime code\n const returnRuntimeObj = this.divertAfter.GenerateRuntimeObject();\n const returnRuntimeContainer = returnRuntimeObj as RuntimeContainer;\n if (returnRuntimeContainer) {\n // Steal all code for generating arguments from the divert\n const args = this.divertAfter.args;\n if (args !== null && args.length > 0) {\n // Steal everything betwen eval start and eval end\n let evalStart = -1;\n let evalEnd = -1;\n for (\n let ii = 0;\n ii < returnRuntimeContainer.content.length;\n ii += 1\n ) {\n const cmd = returnRuntimeContainer.content[\n ii\n ] as RuntimeControlCommand;\n if (cmd) {\n if (\n evalStart == -1 &&\n cmd.commandType === RuntimeControlCommand.CommandType.EvalStart\n ) {\n evalStart = ii;\n } else if (\n cmd.commandType === RuntimeControlCommand.CommandType.EvalEnd\n ) {\n evalEnd = ii;\n }\n }\n }\n\n for (let ii = evalStart + 1; ii < evalEnd; ii += 1) {\n const obj = returnRuntimeContainer.content[ii];\n obj.parent = null; // prevent error of being moved between owners\n container.AddContent(returnRuntimeContainer.content[ii]);\n }\n }\n }\n // Supply the divert target for the tunnel onwards target, either variable or more commonly, the explicit name\n // var returnDivertObj = returnRuntimeObj as Runtime.Divert;\n let returnDivertObj = asOrNull(returnRuntimeObj, RuntimeDivert);\n if (returnDivertObj != null && returnDivertObj.hasVariableTarget) {\n let runtimeVarRef = new VariableReference(\n returnDivertObj.variableDivertName\n );\n container.AddContent(runtimeVarRef);\n } else {\n this._overrideDivertTarget = new DivertTargetValue();\n container.AddContent(this._overrideDivertTarget);\n }\n } else {\n // No divert after tunnel onwards\n container.AddContent(new Void());\n }\n\n container.AddContent(RuntimeControlCommand.EvalEnd());\n container.AddContent(RuntimeControlCommand.PopTunnel());\n\n return container;\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n if (this.divertAfter && this.divertAfter.targetContent) {\n this._overrideDivertTarget!.targetPath =\n this.divertAfter.targetContent.runtimePath;\n }\n }\n\n public toString = (): string => {\n return ` -> ${this._divertAfter}`;\n };\n}\n","import { InkListItem, SerializedInkListItem } from \"./InkList\";\nimport { TryGetResult } from \"./TryGetResult\";\n\nexport class ListDefinition {\n public _name: string;\n public _items: Map | null;\n public _itemNameToValues: Map;\n\n constructor(name: string, items: Map | null) {\n this._name = name || \"\";\n this._items = null;\n this._itemNameToValues = items || new Map();\n }\n get name() {\n return this._name;\n }\n get items() {\n if (this._items == null) {\n this._items = new Map();\n for (let [key, value] of this._itemNameToValues) {\n let item = new InkListItem(this.name, key);\n this._items.set(item.serialized(), value);\n }\n }\n\n return this._items;\n }\n\n public ValueForItem(item: InkListItem) {\n if (!item.itemName) return 0;\n\n let intVal = this._itemNameToValues.get(item.itemName);\n if (typeof intVal !== \"undefined\") return intVal;\n else return 0;\n }\n public ContainsItem(item: InkListItem) {\n if (!item.itemName) return false;\n if (item.originName != this.name) return false;\n\n return this._itemNameToValues.has(item.itemName);\n }\n public ContainsItemWithName(itemName: string) {\n return this._itemNameToValues.has(itemName);\n }\n public TryGetItemWithValue(\n val: number,\n /* out */ item: InkListItem\n ): TryGetResult {\n for (let [key, value] of this._itemNameToValues) {\n if (value == val) {\n item = new InkListItem(this.name, key);\n return { result: item, exists: true };\n }\n }\n\n item = InkListItem.Null;\n return { result: item, exists: false };\n }\n\n public TryGetValueForItem(\n item: InkListItem,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n /* out */ intVal: number\n ): TryGetResult {\n if (!item.itemName) return { result: 0, exists: false };\n let value = this._itemNameToValues.get(item.itemName);\n\n if (!value) return { result: 0, exists: false };\n return { result: value, exists: true };\n }\n}\n","import { InkList as RuntimeInkList } from \"../../../../engine/InkList\";\nimport { InkListItem as RuntimeInkListItem } from \"../../../../engine/InkList\";\nimport { ListDefinition as RuntimeListDefinition } from \"../../../../engine/ListDefinition\";\nimport { ListElementDefinition } from \"./ListElementDefinition\";\nimport { ListValue } from \"../../../../engine/Value\";\nimport { ParsedObject } from \"../Object\";\nimport { Story } from \"../Story\";\nimport { SymbolType } from \"../SymbolType\";\nimport { VariableAssignment } from \"../Variable/VariableAssignment\";\nimport { Identifier } from \"../Identifier\";\n\nexport class ListDefinition extends ParsedObject {\n public identifier: Identifier | null = null;\n public variableAssignment: VariableAssignment | null = null;\n\n get typeName() {\n return \"ListDefinition\";\n }\n\n private _elementsByName: Map | null = null;\n\n get runtimeListDefinition(): RuntimeListDefinition {\n const allItems: Map = new Map();\n for (const e of this.itemDefinitions) {\n if (!allItems.has(e.name!)) {\n allItems.set(e.name!, e.seriesValue);\n } else {\n this.Error(\n `List '${this.identifier}' contains duplicate items called '${e.name}'`\n );\n }\n }\n\n return new RuntimeListDefinition(this.identifier?.name || \"\", allItems);\n }\n\n public readonly ItemNamed = (\n itemName: string\n ): ListElementDefinition | null => {\n if (this._elementsByName === null) {\n this._elementsByName = new Map();\n\n for (const el of this.itemDefinitions) {\n this._elementsByName.set(el.name!, el);\n }\n }\n\n const foundElement = this._elementsByName.get(itemName) || null;\n\n return foundElement;\n };\n\n constructor(public itemDefinitions: ListElementDefinition[]) {\n super();\n\n let currentValue = 1;\n for (const e of this.itemDefinitions) {\n if (e.explicitValue !== null) {\n currentValue = e.explicitValue;\n }\n\n e.seriesValue = currentValue;\n\n currentValue += 1;\n }\n\n this.AddContent(itemDefinitions as any);\n }\n\n public readonly GenerateRuntimeObject = (): ListValue => {\n const initialValues = new RuntimeInkList();\n for (const itemDef of this.itemDefinitions) {\n if (itemDef.inInitialList) {\n const item = new RuntimeInkListItem(\n this.identifier?.name || null,\n itemDef.name || null\n );\n initialValues.Add(item, itemDef.seriesValue);\n }\n }\n\n // Set origin name, so\n initialValues.SetInitialOriginName(this.identifier?.name || \"\");\n\n return new ListValue(initialValues);\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n context.CheckForNamingCollisions(this, this.identifier!, SymbolType.List);\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"../Expression/Expression\";\nimport { FlowBase } from \"../Flow/FlowBase\";\nimport { ClosestFlowBase } from \"../Flow/ClosestFlowBase\";\nimport { ListDefinition } from \"../List/ListDefinition\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Story } from \"../Story\";\nimport { SymbolType } from \"../SymbolType\";\nimport { VariableAssignment as RuntimeVariableAssignment } from \"../../../../engine/VariableAssignment\";\nimport { VariableReference } from \"./VariableReference\";\nimport { Identifier } from \"../Identifier\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class VariableAssignment extends ParsedObject {\n private _runtimeAssignment: RuntimeVariableAssignment | null = null;\n\n get variableName(): string {\n return this.variableIdentifier.name!;\n }\n public readonly variableIdentifier: Identifier;\n public readonly expression: Expression | null = null;\n public readonly listDefinition: ListDefinition | null = null;\n public readonly isGlobalDeclaration: boolean;\n public readonly isNewTemporaryDeclaration: boolean;\n\n get typeName() {\n if (this.isNewTemporaryDeclaration) {\n return \"temp\";\n } else if (this.isGlobalDeclaration) {\n if (this.listDefinition !== null) {\n return \"LIST\";\n }\n return \"VAR\";\n }\n\n return \"variable assignment\";\n }\n\n get isDeclaration(): boolean {\n return this.isGlobalDeclaration || this.isNewTemporaryDeclaration;\n }\n\n constructor({\n assignedExpression,\n isGlobalDeclaration,\n isTemporaryNewDeclaration,\n listDef,\n variableIdentifier,\n }: {\n readonly assignedExpression?: Expression;\n readonly isGlobalDeclaration?: boolean;\n readonly isTemporaryNewDeclaration?: boolean;\n readonly listDef?: ListDefinition;\n readonly variableIdentifier: Identifier;\n }) {\n super();\n\n this.variableIdentifier = variableIdentifier;\n this.isGlobalDeclaration = Boolean(isGlobalDeclaration);\n this.isNewTemporaryDeclaration = Boolean(isTemporaryNewDeclaration);\n\n // Defensive programming in case parsing of assignedExpression failed\n if (listDef instanceof ListDefinition) {\n this.listDefinition = this.AddContent(listDef) as ListDefinition;\n this.listDefinition.variableAssignment = this;\n\n // List definitions are always global\n this.isGlobalDeclaration = true;\n } else if (assignedExpression) {\n this.expression = this.AddContent(assignedExpression) as Expression;\n }\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject | null => {\n let newDeclScope: FlowBase | null | undefined = null;\n if (this.isGlobalDeclaration) {\n newDeclScope = this.story;\n } else if (this.isNewTemporaryDeclaration) {\n newDeclScope = ClosestFlowBase(this);\n }\n\n if (newDeclScope) {\n newDeclScope.AddNewVariableDeclaration(this);\n }\n\n // Global declarations don't generate actual procedural\n // runtime objects, but instead add a global variable to the story itself.\n // The story then initialises them all in one go at the start of the game.\n if (this.isGlobalDeclaration) {\n return null;\n }\n\n const container = new RuntimeContainer();\n\n // The expression's runtimeObject is actually another nested container\n if (this.expression) {\n container.AddContent(this.expression.runtimeObject);\n } else if (this.listDefinition) {\n container.AddContent(this.listDefinition.runtimeObject);\n }\n\n this._runtimeAssignment = new RuntimeVariableAssignment(\n this.variableName,\n this.isNewTemporaryDeclaration\n );\n\n container.AddContent(this._runtimeAssignment);\n\n return container;\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n // List definitions are checked for conflicts separately\n if (this.isDeclaration && this.listDefinition === null) {\n context.CheckForNamingCollisions(\n this,\n this.variableIdentifier,\n this.isGlobalDeclaration ? SymbolType.Var : SymbolType.Temp\n );\n }\n\n // Initial VAR x = [intialValue] declaration, not re-assignment\n if (this.isGlobalDeclaration) {\n const variableReference = asOrNull(this.expression, VariableReference);\n if (\n variableReference &&\n !variableReference.isConstantReference &&\n !variableReference.isListItemReference\n ) {\n this.Error(\n \"global variable assignments cannot refer to other variables, only literal values, constants and list items\"\n );\n }\n }\n\n if (!this.isNewTemporaryDeclaration) {\n const resolvedVarAssignment = context.ResolveVariableWithName(\n this.variableName,\n this\n );\n\n if (!resolvedVarAssignment.found) {\n if (this.variableName in this.story.constants) {\n this.Error(\n `Can't re-assign to a constant (do you need to use VAR when declaring '${this.variableName}'?)`,\n this\n );\n } else {\n this.Error(\n `Variable could not be found to assign to: '${this.variableName}'`,\n this\n );\n }\n }\n\n // A runtime assignment may not have been generated if it's the initial global declaration,\n // since these are hoisted out and handled specially in Story.ExportRuntime.\n if (this._runtimeAssignment) {\n this._runtimeAssignment.isGlobal = resolvedVarAssignment.isGlobal;\n }\n }\n }\n\n public readonly toString = (): string =>\n `${\n this.isGlobalDeclaration\n ? \"VAR\"\n : this.isNewTemporaryDeclaration\n ? \"~ temp\"\n : \"\"\n } ${this.variableName}`;\n}\n","import { AuthorWarning } from \"./AuthorWarning\";\nimport { Choice } from \"./Choice\";\nimport { Conditional } from \"./Conditional/Conditional\";\nimport { ConstantDeclaration } from \"./Declaration/ConstantDeclaration\";\nimport { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { Divert } from \"./Divert/Divert\";\nimport { Divert as RuntimeDivert } from \"../../../engine/Divert\";\nimport { DivertTarget } from \"./Divert/DivertTarget\";\nimport { FlowBase } from \"./Flow/FlowBase\";\nimport { Gather } from \"./Gather/Gather\";\nimport { GatherPointToResolve } from \"./Gather/GatherPointToResolve\";\nimport { IWeavePoint } from \"./IWeavePoint\";\nimport { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Sequence } from \"./Sequence/Sequence\";\nimport { Story } from \"./Story\";\nimport { Text } from \"./Text\";\nimport { TunnelOnwards } from \"./TunnelOnwards\";\nimport { VariableAssignment } from \"./Variable/VariableAssignment\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\n\ntype BadTerminationHandler = (terminatingObj: ParsedObject) => void;\n\n// Used by the FlowBase when constructing the weave flow from\n// a flat list of content objects.\nexport class Weave extends ParsedObject {\n // Containers can be chained as multiple gather points\n // get created as the same indentation level.\n // rootContainer is always the first in the chain, while\n // currentContainer is the latest.\n get rootContainer(): RuntimeContainer {\n if (!this._rootContainer) {\n this._rootContainer = this.GenerateRuntimeObject();\n }\n\n return this._rootContainer;\n }\n\n // Keep track of previous weave point (Choice or Gather)\n // at the current indentation level:\n // - to add ordinary content to be nested under it\n // - to add nested content under it when it's indented\n // - to remove it from the list of loose ends when\n // - it has indented content since it's no longer a loose end\n // - it's a gather and it has a choice added to it\n public previousWeavePoint: IWeavePoint | null = null;\n public addContentToPreviousWeavePoint: boolean = false;\n\n // Used for determining whether the next Gather should auto-enter\n public hasSeenChoiceInSection: boolean = false;\n\n public currentContainer: RuntimeContainer | null = null;\n public baseIndentIndex: number;\n\n private _unnamedGatherCount: number = 0;\n private _choiceCount: number = 0;\n private _rootContainer: RuntimeContainer | null = null;\n private _namedWeavePoints: Map = new Map();\n get namedWeavePoints() {\n return this._namedWeavePoints;\n }\n\n // Loose ends are:\n // - Choices or Gathers that need to be joined up\n // - Explicit Divert to gather points (i.e. \"->\" without a target)\n public looseEnds: IWeavePoint[] = [];\n\n public gatherPointsToResolve: GatherPointToResolve[] = [];\n\n get lastParsedSignificantObject(): ParsedObject | null {\n if (this.content.length === 0) {\n return null;\n }\n\n // Don't count extraneous newlines or VAR/CONST declarations,\n // since they're \"empty\" statements outside of the main flow.\n let lastObject: ParsedObject | null = null;\n for (let ii = this.content.length - 1; ii >= 0; --ii) {\n lastObject = this.content[ii];\n\n let lastText = asOrNull(lastObject, Text);\n if (lastText && lastText.text === \"\\n\") {\n continue;\n }\n\n if (this.IsGlobalDeclaration(lastObject)) {\n continue;\n }\n\n break;\n }\n\n const lastWeave = asOrNull(lastObject, Weave);\n if (lastWeave) {\n lastObject = lastWeave.lastParsedSignificantObject;\n }\n\n return lastObject;\n }\n\n constructor(cont: ParsedObject[], indentIndex: number = -1) {\n super();\n\n if (indentIndex == -1) {\n this.baseIndentIndex = this.DetermineBaseIndentationFromContent(cont);\n } else {\n this.baseIndentIndex = indentIndex;\n }\n\n this.AddContent(cont);\n\n this.ConstructWeaveHierarchyFromIndentation();\n }\n\n get typeName(): string {\n return \"Weave\";\n }\n\n public readonly ResolveWeavePointNaming = (): void => {\n const namedWeavePoints = [\n ...this.FindAll(Gather)(\n (w) => !(w.name === null || w.name === undefined)\n ),\n ...this.FindAll(Choice)(\n (w) => !(w.name === null || w.name === undefined)\n ),\n ];\n this._namedWeavePoints = new Map();\n\n for (const weavePoint of namedWeavePoints) {\n // Check for weave point naming collisions\n const existingWeavePoint: IWeavePoint | null | undefined =\n this.namedWeavePoints.get(weavePoint.identifier?.name || \"\");\n\n if (existingWeavePoint) {\n const typeName =\n existingWeavePoint instanceof Gather ? \"gather\" : \"choice\";\n const existingObj: ParsedObject = existingWeavePoint;\n\n this.Error(\n `A ${typeName} with the same label name '${\n weavePoint.name\n }' already exists in this context on line ${\n existingObj.debugMetadata\n ? existingObj.debugMetadata.startLineNumber\n : \"NO DEBUG METADATA AVAILABLE\"\n }`,\n weavePoint as ParsedObject\n );\n }\n if (weavePoint.identifier?.name) {\n this.namedWeavePoints.set(weavePoint.identifier?.name, weavePoint);\n }\n }\n };\n\n public readonly ConstructWeaveHierarchyFromIndentation = (): void => {\n // Find nested indentation and convert to a proper object hierarchy\n // (i.e. indented content is replaced with a Weave object that contains\n // that nested content)\n let contentIdx = 0;\n while (contentIdx < this.content.length) {\n const obj: ParsedObject = this.content[contentIdx];\n\n // Choice or Gather\n if (obj instanceof Choice || obj instanceof Gather) {\n const weavePoint: IWeavePoint = obj;\n const weaveIndentIdx = weavePoint.indentationDepth - 1;\n\n // Inner level indentation - recurse\n if (weaveIndentIdx > this.baseIndentIndex) {\n // Step through content until indent jumps out again\n let innerWeaveStartIdx = contentIdx;\n while (contentIdx < this.content.length) {\n const innerWeaveObj =\n asOrNull(this.content[contentIdx], Choice) ||\n asOrNull(this.content[contentIdx], Gather);\n if (innerWeaveObj !== null) {\n const innerIndentIdx = innerWeaveObj.indentationDepth - 1;\n if (innerIndentIdx <= this.baseIndentIndex) {\n break;\n }\n }\n\n contentIdx += 1;\n }\n\n const weaveContentCount = contentIdx - innerWeaveStartIdx;\n const weaveContent = this.content.slice(\n innerWeaveStartIdx,\n innerWeaveStartIdx + weaveContentCount\n );\n\n this.content.splice(innerWeaveStartIdx, weaveContentCount);\n\n const weave = new Weave(weaveContent, weaveIndentIdx);\n this.InsertContent(innerWeaveStartIdx, weave);\n\n // Continue iteration from this point\n contentIdx = innerWeaveStartIdx;\n }\n }\n\n contentIdx += 1;\n }\n };\n\n // When the indentation wasn't told to us at construction time using\n // a choice point with a known indentation level, we may be told to\n // determine the indentation level by incrementing from our closest ancestor.\n public readonly DetermineBaseIndentationFromContent = (\n contentList: ParsedObject[]\n ): number => {\n for (const obj of contentList) {\n if (obj instanceof Choice || obj instanceof Gather) {\n return obj.indentationDepth - 1;\n }\n }\n\n // No weave points, so it doesn't matter\n return 0;\n };\n\n public readonly GenerateRuntimeObject = (): RuntimeContainer => {\n this._rootContainer = new RuntimeContainer();\n this.currentContainer = this._rootContainer;\n this.looseEnds = [];\n this.gatherPointsToResolve = [];\n\n // Iterate through content for the block at this level of indentation\n // - Normal content is nested under Choices and Gathers\n // - Blocks that are further indented cause recursion\n // - Keep track of loose ends so that they can be diverted to Gathers\n for (const obj of this.content) {\n // Choice or Gather\n if (obj instanceof Choice || obj instanceof Gather) {\n this.AddRuntimeForWeavePoint(obj as IWeavePoint);\n } else {\n // Non-weave point\n if (obj instanceof Weave) {\n // Nested weave\n const weave = obj;\n this.AddRuntimeForNestedWeave(weave);\n this.gatherPointsToResolve.splice(\n 0,\n 0,\n ...weave.gatherPointsToResolve\n );\n } else {\n // Other object\n // May be complex object that contains statements - e.g. a multi-line conditional\n this.AddGeneralRuntimeContent(obj.runtimeObject);\n }\n }\n }\n\n // Pass any loose ends up the hierarhcy\n this.PassLooseEndsToAncestors();\n\n return this._rootContainer;\n };\n\n // Found gather point:\n // - gather any loose ends\n // - set the gather as the main container to dump new content in\n public readonly AddRuntimeForGather = (gather: Gather): void => {\n // Determine whether this Gather should be auto-entered:\n // - It is auto-entered if there were no choices in the last section\n // - A section is \"since the previous gather\" - so reset now\n const autoEnter = !this.hasSeenChoiceInSection;\n this.hasSeenChoiceInSection = false;\n\n const gatherContainer = gather.runtimeContainer;\n\n if (!gather.name) {\n // Use disallowed character so it's impossible to have a name collision\n gatherContainer.name = `g-${this._unnamedGatherCount}`;\n this._unnamedGatherCount += 1;\n }\n\n if (autoEnter) {\n if (!this.currentContainer) {\n throw new Error();\n }\n\n // Auto-enter: include in main content\n this.currentContainer.AddContent(gatherContainer);\n } else {\n // Don't auto-enter:\n // Add this gather to the main content, but only accessible\n // by name so that it isn't stepped into automatically, but only via\n // a divert from a loose end.\n this.rootContainer.AddToNamedContentOnly(gatherContainer);\n }\n\n // Consume loose ends: divert them to this gather\n for (const looseEndWeavePoint of this.looseEnds) {\n const looseEnd = looseEndWeavePoint as ParsedObject;\n\n // Skip gather loose ends that are at the same level\n // since they'll be handled by the auto-enter code below\n // that only jumps into the gather if (current runtime choices == 0)\n if (looseEnd instanceof Gather) {\n const prevGather = looseEnd;\n if (prevGather.indentationDepth == gather.indentationDepth) {\n continue;\n }\n }\n\n let divert: RuntimeDivert | null = null;\n if (looseEnd instanceof Divert) {\n divert = looseEnd.runtimeObject as RuntimeDivert;\n } else {\n divert = new RuntimeDivert();\n const looseWeavePoint = looseEnd as IWeavePoint;\n if (!looseWeavePoint.runtimeContainer) {\n throw new Error();\n }\n\n looseWeavePoint.runtimeContainer.AddContent(divert);\n }\n\n // Pass back knowledge of this loose end being diverted\n // to the FlowBase so that it can maintain a list of them,\n // and resolve the divert references later\n this.gatherPointsToResolve.push(\n new GatherPointToResolve(divert, gatherContainer)\n );\n }\n\n this.looseEnds = [];\n\n // Replace the current container itself\n this.currentContainer = gatherContainer;\n };\n\n public readonly AddRuntimeForWeavePoint = (weavePoint: IWeavePoint): void => {\n // Current level Gather\n if (weavePoint instanceof Gather) {\n this.AddRuntimeForGather(weavePoint);\n }\n\n // Current level choice\n else if (weavePoint instanceof Choice) {\n if (!this.currentContainer) {\n throw new Error();\n }\n\n // Gathers that contain choices are no longer loose ends\n // (same as when weave points get nested content)\n if (this.previousWeavePoint instanceof Gather) {\n this.looseEnds.splice(\n this.looseEnds.indexOf(this.previousWeavePoint),\n 1\n );\n }\n\n // Add choice point content\n const choice = weavePoint; //, Choice);\n\n this.currentContainer.AddContent(choice.runtimeObject);\n if (!choice.innerContentContainer) {\n throw new Error();\n } //guaranteed not to happen\n\n // Add choice's inner content to self\n choice.innerContentContainer.name = `c-${this._choiceCount}`;\n this.currentContainer.AddToNamedContentOnly(choice.innerContentContainer);\n this._choiceCount += 1;\n\n this.hasSeenChoiceInSection = true;\n }\n\n // Keep track of loose ends\n this.addContentToPreviousWeavePoint = false; // default\n if (this.WeavePointHasLooseEnd(weavePoint)) {\n this.looseEnds.push(weavePoint);\n\n const looseChoice = asOrNull(weavePoint, Choice);\n if (looseChoice) {\n this.addContentToPreviousWeavePoint = true;\n }\n }\n\n this.previousWeavePoint = weavePoint;\n };\n\n // Add nested block at a greater indentation level\n public readonly AddRuntimeForNestedWeave = (nestedResult: Weave): void => {\n // Add this inner block to current container\n // (i.e. within the main container, or within the last defined Choice/Gather)\n this.AddGeneralRuntimeContent(nestedResult.rootContainer);\n\n // Now there's a deeper indentation level, the previous weave point doesn't\n // count as a loose end (since it will have content to go to)\n if (this.previousWeavePoint !== null) {\n this.looseEnds.splice(this.looseEnds.indexOf(this.previousWeavePoint), 1);\n\n this.addContentToPreviousWeavePoint = false;\n }\n };\n\n // Normal content gets added into the latest Choice or Gather by default,\n // unless there hasn't been one yet.\n public readonly AddGeneralRuntimeContent = (content: RuntimeObject): void => {\n // Content is allowed to evaluate runtimeObject to null\n // (e.g. AuthorWarning, which doesn't make it into the runtime)\n if (content === null) {\n return;\n }\n\n if (this.addContentToPreviousWeavePoint) {\n if (\n !this.previousWeavePoint ||\n !this.previousWeavePoint.runtimeContainer\n ) {\n throw new Error();\n }\n\n this.previousWeavePoint.runtimeContainer.AddContent(content);\n } else {\n if (!this.currentContainer) {\n throw new Error();\n }\n\n this.currentContainer.AddContent(content);\n }\n };\n\n public readonly PassLooseEndsToAncestors = () => {\n if (this.looseEnds.length === 0) {\n return;\n }\n\n // Search for Weave ancestor to pass loose ends to for gathering.\n // There are two types depending on whether the current weave\n // is separated by a conditional or sequence.\n // - An \"inner\" weave is one that is directly connected to the current\n // weave - i.e. you don't have to pass through a conditional or\n // sequence to get to it. We're allowed to pass all loose ends to\n // one of these.\n // - An \"outer\" weave is one that is outside of a conditional/sequence\n // that the current weave is nested within. We're only allowed to\n // pass gathers (i.e. 'normal flow') loose ends up there, not normal\n // choices. The rule is that choices have to be diverted explicitly\n // by the author since it's ambiguous where flow should go otherwise.\n //\n // e.g.:\n //\n // - top <- e.g. outer weave\n // {true:\n // * choice <- e.g. inner weave\n // * * choice 2\n // more content <- e.g. current weave\n // * choice 2\n // }\n // - more of outer weave\n //\n let closestInnerWeaveAncestor: Weave | null = null;\n let closestOuterWeaveAncestor: Weave | null = null;\n\n // Find inner and outer ancestor weaves as defined above.\n let nested = false;\n for (\n let ancestor = this.parent;\n ancestor !== null;\n ancestor = ancestor.parent\n ) {\n // Found ancestor?\n const weaveAncestor = asOrNull(ancestor, Weave);\n if (weaveAncestor) {\n if (!nested && closestInnerWeaveAncestor === null) {\n closestInnerWeaveAncestor = weaveAncestor;\n }\n\n if (nested && closestOuterWeaveAncestor === null) {\n closestOuterWeaveAncestor = weaveAncestor;\n }\n }\n\n // Weaves nested within Sequences or Conditionals are\n // \"sealed\" - any loose ends require explicit diverts.\n if (ancestor instanceof Sequence || ancestor instanceof Conditional) {\n nested = true;\n }\n }\n\n // No weave to pass loose ends to at all?\n if (\n closestInnerWeaveAncestor === null &&\n closestOuterWeaveAncestor === null\n ) {\n return;\n }\n\n // Follow loose end passing logic as defined above\n for (let ii = this.looseEnds.length - 1; ii >= 0; ii -= 1) {\n const looseEnd = this.looseEnds[ii];\n let received = false;\n\n if (nested) {\n // This weave is nested within a conditional or sequence:\n // - choices can only be passed up to direct ancestor (\"inner\") weaves\n // - gathers can be passed up to either, but favour the closer (inner) weave\n // if there is one\n if (looseEnd instanceof Choice && closestInnerWeaveAncestor !== null) {\n closestInnerWeaveAncestor.ReceiveLooseEnd(looseEnd);\n received = true;\n } else if (!(looseEnd instanceof Choice)) {\n const receivingWeave =\n closestInnerWeaveAncestor || closestOuterWeaveAncestor;\n if (receivingWeave !== null) {\n receivingWeave.ReceiveLooseEnd(looseEnd);\n received = true;\n }\n }\n } else {\n // No nesting, all loose ends can be safely passed up\n if (closestInnerWeaveAncestor?.hasOwnProperty(\"ReceiveLooseEnd\")) {\n closestInnerWeaveAncestor!.ReceiveLooseEnd(looseEnd);\n }\n received = true;\n }\n\n if (received) {\n this.looseEnds.splice(ii, 1);\n }\n }\n };\n\n public readonly ReceiveLooseEnd = (childWeaveLooseEnd: IWeavePoint): void => {\n this.looseEnds.push(childWeaveLooseEnd);\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n // Check that choices nested within conditionals and sequences are terminated\n if (this.looseEnds !== null && this.looseEnds.length > 0) {\n let isNestedWeave = false;\n for (\n let ancestor = this.parent;\n ancestor !== null;\n ancestor = ancestor.parent\n ) {\n if (ancestor instanceof Sequence || ancestor instanceof Conditional) {\n isNestedWeave = true;\n break;\n }\n }\n\n if (isNestedWeave) {\n this.ValidateTermination(this.BadNestedTerminationHandler);\n }\n }\n\n for (const gatherPoint of this.gatherPointsToResolve) {\n gatherPoint.divert.targetPath = gatherPoint.targetRuntimeObj.path;\n }\n\n this.CheckForWeavePointNamingCollisions();\n }\n\n public readonly WeavePointNamed = (name: string): IWeavePoint | null => {\n if (!this.namedWeavePoints) {\n return null;\n }\n\n let weavePointResult: IWeavePoint | null | undefined =\n this.namedWeavePoints.get(name);\n if (weavePointResult) {\n return weavePointResult;\n }\n\n return null;\n };\n\n // Global VARs and CONSTs are treated as \"outside of the flow\"\n // when iterating over content that follows loose ends\n public readonly IsGlobalDeclaration = (obj: ParsedObject) => {\n const varAss = asOrNull(obj, VariableAssignment);\n if (varAss && varAss.isGlobalDeclaration && varAss.isDeclaration) {\n return true;\n }\n\n const constDecl = asOrNull(obj, ConstantDeclaration);\n if (constDecl) {\n return true;\n }\n\n return false;\n };\n\n // While analysing final loose ends, we look to see whether there\n // are any diverts etc which choices etc divert from\n public readonly ContentThatFollowsWeavePoint = (\n weavePoint: IWeavePoint\n ): ParsedObject[] => {\n const returned = [];\n const obj = weavePoint as ParsedObject;\n\n // Inner content first (e.g. for a choice)\n if (obj.content !== null) {\n for (const contentObj of obj.content) {\n // Global VARs and CONSTs are treated as \"outside of the flow\"\n if (this.IsGlobalDeclaration(contentObj)) {\n continue;\n }\n\n returned.push(contentObj);\n }\n }\n\n const parentWeave = asOrNull(obj.parent, Weave);\n if (parentWeave === null) {\n throw new Error(\"Expected weave point parent to be weave?\");\n }\n\n const weavePointIdx = parentWeave.content.indexOf(obj);\n for (let ii = weavePointIdx + 1; ii < parentWeave.content.length; ii += 1) {\n const laterObj = parentWeave.content[ii];\n\n // Global VARs and CONSTs are treated as \"outside of the flow\"\n if (this.IsGlobalDeclaration(laterObj)) {\n continue;\n }\n\n // End of the current flow\n // if (laterObj instanceof IWeavePoint) // cannot test on interface in ts\n if (laterObj instanceof Choice || laterObj instanceof Gather) {\n break;\n }\n\n // Other weaves will be have their own loose ends\n if (laterObj instanceof Weave) {\n break;\n }\n\n returned.push(laterObj);\n }\n\n return returned;\n };\n\n public readonly ValidateTermination = (\n badTerminationHandler: BadTerminationHandler\n ): void => {\n // Don't worry if the last object in the flow is a \"TODO\",\n // even if there are other loose ends in other places\n if (this.lastParsedSignificantObject instanceof AuthorWarning) {\n return;\n }\n\n // By now, any sub-weaves will have passed loose ends up to the root weave (this).\n // So there are 2 possible situations:\n // - There are loose ends from somewhere in the flow.\n // These aren't necessarily \"real\" loose ends - they're weave points\n // that don't connect to any lower weave points, so we just\n // have to check that they terminate properly.\n // - This weave is just a list of content with no actual weave points,\n // so we just need to check that the list of content terminates.\n\n const hasLooseEnds: boolean =\n this.looseEnds !== null && this.looseEnds.length > 0;\n\n if (hasLooseEnds) {\n for (const looseEnd of this.looseEnds) {\n const looseEndFlow = this.ContentThatFollowsWeavePoint(looseEnd);\n this.ValidateFlowOfObjectsTerminates(\n looseEndFlow,\n looseEnd as ParsedObject,\n badTerminationHandler\n );\n }\n } else {\n // No loose ends... is there any inner weaving at all?\n // If not, make sure the single content stream is terminated correctly\n //\n // If there's any actual weaving, assume that content is\n // terminated correctly since we would've had a loose end otherwise\n for (const obj of this.content) {\n if (obj instanceof Choice || obj instanceof Divert) {\n return;\n }\n }\n\n // Straight linear flow? Check it terminates\n this.ValidateFlowOfObjectsTerminates(\n this.content,\n this,\n badTerminationHandler\n );\n }\n };\n\n readonly BadNestedTerminationHandler: BadTerminationHandler = (\n terminatingObj\n ) => {\n let conditional: Conditional | null = null;\n for (\n let ancestor = terminatingObj.parent;\n ancestor !== null;\n ancestor = ancestor.parent\n ) {\n if (ancestor instanceof Sequence || ancestor instanceof Conditional) {\n conditional = asOrNull(ancestor, Conditional);\n break;\n }\n }\n\n let errorMsg =\n \"Choices nested in conditionals or sequences need to explicitly divert afterwards.\";\n\n // Tutorialise proper choice syntax if this looks like a single choice within a condition, e.g.\n // { condition:\n // * choice\n // }\n if (conditional !== null) {\n let numChoices = conditional.FindAll(Choice)().length;\n if (numChoices === 1) {\n errorMsg = `Choices with conditions should be written: '* {condition} choice'. Otherwise, ${errorMsg.toLowerCase()}`;\n }\n }\n\n this.Error(errorMsg, terminatingObj);\n };\n\n public readonly ValidateFlowOfObjectsTerminates = (\n objFlow: ParsedObject[],\n defaultObj: ParsedObject,\n badTerminationHandler: BadTerminationHandler\n ) => {\n let terminated = false;\n let terminatingObj: ParsedObject = defaultObj;\n for (const flowObj of objFlow) {\n const divert = flowObj.Find(Divert)(\n (d) =>\n !d.isThread &&\n !d.isTunnel &&\n !d.isFunctionCall &&\n !(d.parent instanceof DivertTarget)\n );\n\n if (divert !== null) {\n terminated = true;\n }\n\n if (flowObj.Find(TunnelOnwards)() != null) {\n terminated = true;\n break;\n }\n\n terminatingObj = flowObj;\n }\n\n if (!terminated) {\n // Author has left a note to self here - clearly we don't need\n // to leave them with another warning since they know what they're doing.\n if (terminatingObj instanceof AuthorWarning) {\n return;\n }\n\n badTerminationHandler(terminatingObj);\n }\n };\n\n public readonly WeavePointHasLooseEnd = (\n weavePoint: IWeavePoint\n ): boolean => {\n // No content, must be a loose end.\n if (weavePoint.content === null) {\n return true;\n }\n\n // If a weave point is diverted from, it doesn't have a loose end.\n // Detect a divert object within a weavePoint's main content\n // Work backwards since we're really interested in the end,\n // although it doesn't actually make a difference!\n // (content after a divert will simply be inaccessible)\n for (let ii = weavePoint.content.length - 1; ii >= 0; --ii) {\n let innerDivert = asOrNull(weavePoint.content[ii], Divert);\n if (innerDivert) {\n const willReturn =\n innerDivert.isThread ||\n innerDivert.isTunnel ||\n innerDivert.isFunctionCall;\n if (!willReturn) {\n return false;\n }\n }\n }\n\n return true;\n };\n\n // Enforce rule that weave points must not have the same\n // name as any stitches or knots upwards in the hierarchy\n public readonly CheckForWeavePointNamingCollisions = (): void => {\n if (!this.namedWeavePoints) {\n return;\n }\n\n const ancestorFlows = [];\n for (const obj of this.ancestry) {\n const flow = asOrNull(obj, FlowBase);\n if (flow) {\n ancestorFlows.push(flow);\n } else {\n break;\n }\n }\n\n for (const [weavePointName, weavePoint] of this.namedWeavePoints) {\n for (const flow of ancestorFlows) {\n // Shallow search\n const otherContentWithName =\n flow.ContentWithNameAtLevel(weavePointName);\n if (otherContentWithName && otherContentWithName !== weavePoint) {\n const errorMsg = `${weavePoint.GetType()} '${weavePointName}' has the same label name as a ${otherContentWithName.GetType()} (on ${\n otherContentWithName.debugMetadata\n })`;\n this.Error(errorMsg, weavePoint);\n }\n }\n }\n };\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { Expression } from \"../Expression/Expression\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\nimport { StringValue } from \"../../../../engine/Value\";\nimport { Story } from \"../Story\";\nimport { Text } from \"../Text\";\nimport { Weave } from \"../Weave\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class ConditionalSingleBranch extends ParsedObject {\n public _contentContainer: RuntimeContainer | null = null;\n public _conditionalDivert: RuntimeDivert | null = null;\n public _ownExpression: Expression | null = null;\n public _innerWeave: Weave | null = null;\n // bool condition, e.g.:\n // { 5 == 4:\n // - the true branch\n // - the false branch\n // }\n public isTrueBranch: boolean = false;\n\n // When each branch has its own expression like a switch statement,\n // this is non-null. e.g.\n // { x:\n // - 4: the value of x is four (ownExpression is the value 4)\n // - 3: the value of x is three\n // }\n get ownExpression() {\n return this._ownExpression;\n }\n\n set ownExpression(value) {\n this._ownExpression = value;\n if (this._ownExpression) {\n this.AddContent(this._ownExpression);\n }\n }\n\n // In the above example, match equality of x with 4 for the first branch.\n // This is as opposed to simply evaluating boolean equality for each branch,\n // example when shouldMatchEquality is FALSE:\n // {\n // 3 > 2: This will happen\n // 2 > 3: This won't happen\n // }\n public matchingEquality: boolean = false;\n\n public isElse: boolean = false;\n public isInline: boolean = false;\n\n public returnDivert: RuntimeDivert | null = null;\n\n constructor(content?: ParsedObject[] | null | undefined) {\n super();\n\n // Branches are allowed to be empty\n if (content) {\n this._innerWeave = new Weave(content);\n this.AddContent(this._innerWeave);\n }\n }\n\n get typeName(): string {\n return \"ConditionalSingleBranch\";\n }\n\n // Runtime content can be summarised as follows:\n // - Evaluate an expression if necessary to branch on\n // - Branch to a named container if true\n // - Divert back to main flow\n // (owner Conditional is in control of this target point)\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n // Check for common mistake, of putting \"else:\" instead of \"- else:\"\n if (this._innerWeave) {\n for (const c of this._innerWeave.content) {\n const text = asOrNull(c, Text);\n if (text) {\n // Don't need to trim at the start since the parser handles that already\n if (text.text.startsWith(\"else:\")) {\n this.Warning(\n \"Saw the text 'else:' which is being treated as content. Did you mean '- else:'?\",\n text\n );\n }\n }\n }\n }\n\n const container = new RuntimeContainer();\n\n // Are we testing against a condition that's used for more than just this\n // branch? If so, the first thing we need to do is replicate the value that's\n // on the evaluation stack so that we don't fully consume it, in case other\n // branches need to use it.\n const duplicatesStackValue: boolean = this.matchingEquality && !this.isElse;\n\n if (duplicatesStackValue) {\n container.AddContent(RuntimeControlCommand.Duplicate());\n }\n\n this._conditionalDivert = new RuntimeDivert();\n\n // else clause is unconditional catch-all, otherwise the divert is conditional\n this._conditionalDivert.isConditional = !this.isElse;\n\n // Need extra evaluation?\n if (!this.isTrueBranch && !this.isElse) {\n const needsEval: boolean = this.ownExpression !== null;\n if (needsEval) {\n container.AddContent(RuntimeControlCommand.EvalStart());\n }\n\n if (this.ownExpression) {\n this.ownExpression.GenerateIntoContainer(container);\n }\n\n // Uses existing duplicated value\n if (this.matchingEquality) {\n container.AddContent(NativeFunctionCall.CallWithName(\"==\"));\n }\n\n if (needsEval) {\n container.AddContent(RuntimeControlCommand.EvalEnd());\n }\n }\n\n // Will pop from stack if conditional\n container.AddContent(this._conditionalDivert);\n\n this._contentContainer = this.GenerateRuntimeForContent();\n this._contentContainer.name = \"b\";\n\n // Multi-line conditionals get a newline at the start of each branch\n // (as opposed to the start of the multi-line conditional since the condition\n // may evaluate to false.)\n if (!this.isInline) {\n this._contentContainer.InsertContent(new StringValue(\"\\n\"), 0);\n }\n\n if (duplicatesStackValue || (this.isElse && this.matchingEquality)) {\n this._contentContainer.InsertContent(\n RuntimeControlCommand.PopEvaluatedValue(),\n 0\n );\n }\n\n container.AddToNamedContentOnly(this._contentContainer);\n\n this.returnDivert = new RuntimeDivert();\n this._contentContainer.AddContent(this.returnDivert);\n\n return container;\n };\n\n public readonly GenerateRuntimeForContent = (): RuntimeContainer => {\n // Empty branch - create empty container\n if (this._innerWeave === null) {\n return new RuntimeContainer();\n }\n\n return this._innerWeave.rootContainer;\n };\n\n public ResolveReferences(context: Story): void {\n if (!this._conditionalDivert || !this._contentContainer) {\n throw new Error();\n }\n\n this._conditionalDivert.targetPath = this._contentContainer.path;\n super.ResolveReferences(context);\n }\n}\n","export enum CustomFlags {\n ParsingString = 0x1,\n TagActive = 0x2,\n}\n","export class DebugMetadata {\n public startLineNumber: number = 0;\n public endLineNumber: number = 0;\n public startCharacterNumber: number = 0;\n public endCharacterNumber: number = 0;\n public fileName: string | null = null;\n public sourceName: string | null = null;\n\n public Merge(dm: DebugMetadata) {\n let newDebugMetadata = new DebugMetadata();\n\n newDebugMetadata.fileName = this.fileName;\n newDebugMetadata.sourceName = this.sourceName;\n\n if (this.startLineNumber < dm.startLineNumber) {\n newDebugMetadata.startLineNumber = this.startLineNumber;\n newDebugMetadata.startCharacterNumber = this.startCharacterNumber;\n } else if (this.startLineNumber > dm.startLineNumber) {\n newDebugMetadata.startLineNumber = dm.startLineNumber;\n newDebugMetadata.startCharacterNumber = dm.startCharacterNumber;\n } else {\n newDebugMetadata.startLineNumber = this.startLineNumber;\n newDebugMetadata.startCharacterNumber = Math.min(\n this.startCharacterNumber,\n dm.startCharacterNumber\n );\n }\n\n if (this.endLineNumber > dm.endLineNumber) {\n newDebugMetadata.endLineNumber = this.endLineNumber;\n newDebugMetadata.endCharacterNumber = this.endCharacterNumber;\n } else if (this.endLineNumber < dm.endLineNumber) {\n newDebugMetadata.endLineNumber = dm.endLineNumber;\n newDebugMetadata.endCharacterNumber = dm.endCharacterNumber;\n } else {\n newDebugMetadata.endLineNumber = this.endLineNumber;\n newDebugMetadata.endCharacterNumber = Math.max(\n this.endCharacterNumber,\n dm.endCharacterNumber\n );\n }\n\n return newDebugMetadata;\n }\n\n public toString() {\n if (this.fileName !== null) {\n return `line ${this.startLineNumber} of ${this.fileName}\"`;\n } else {\n return \"line \" + this.startLineNumber;\n }\n }\n}\n","import { INamedContent } from \"../../../../engine/INamedContent\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Identifier } from \"../Identifier\";\n\nexport class ExternalDeclaration extends ParsedObject implements INamedContent {\n public get name(): string | null {\n return this.identifier?.name || null;\n }\n\n constructor(\n public readonly identifier: Identifier,\n public readonly argumentNames: string[]\n ) {\n super();\n }\n\n get typeName(): string {\n return \"EXTERNAL\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject | null => {\n this.story.AddExternal(this);\n\n // No runtime code exists for an external, only metadata\n return null;\n };\n\n public toString(): string {\n return `EXTERNAL ${this.identifier?.name}`;\n }\n}\n","import { Argument } from \"./ParsedHierarchy/Argument\";\nimport { Identifier } from \"./ParsedHierarchy/Identifier\";\n\nexport class FlowDecl {\n constructor(\n public readonly name: Identifier,\n public readonly args: Argument[],\n public readonly isFunction: boolean\n ) {}\n}\n","import { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\n\nexport class Wrap extends ParsedObject {\n constructor(private _objToWrap: T) {\n super();\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => this._objToWrap;\n}\n","import { Glue as RuntimeGlue } from \"../../../engine/Glue\";\nimport { Wrap } from \"./Wrap\";\n\nexport class Glue extends Wrap {\n constructor(glue: RuntimeGlue) {\n super(glue);\n }\n\n get typeName(): string {\n return \"Glue\";\n }\n}\n","import { InkObject } from \"./Object\";\n\nexport class Glue extends InkObject {\n public toString() {\n return \"Glue\";\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ContentList } from \"../ContentList\";\nimport { Expression } from \"./Expression\";\nimport { FlowBase } from \"../Flow/FlowBase\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\nimport { IntValue } from \"../../../../engine/Value\";\nimport { Story } from \"../Story\";\nimport { VariableAssignment as RuntimeVariableAssignment } from \"../../../../engine/VariableAssignment\";\nimport { VariableReference as RuntimeVariableReference } from \"../../../../engine/VariableReference\";\nimport { Weave } from \"../Weave\";\nimport { Identifier } from \"../Identifier\";\n\nexport class IncDecExpression extends Expression {\n private _runtimeAssignment: RuntimeVariableAssignment | null = null;\n\n public isInc: boolean;\n public expression: Expression | null = null;\n\n constructor(\n public readonly varIdentifier: Identifier | null,\n isIncOrExpression: boolean | Expression,\n isInc?: boolean\n ) {\n super();\n\n if (isIncOrExpression instanceof Expression) {\n this.expression = isIncOrExpression;\n this.AddContent(this.expression);\n this.isInc = Boolean(isInc);\n } else {\n this.isInc = isIncOrExpression as boolean;\n }\n }\n\n get typeName(): string {\n return \"IncDecExpression\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n // x = x + y\n // ^^^ ^ ^ ^\n // 4 1 3 2\n // Reverse polish notation: (x 1 +) (assign to x)\n\n // 1.\n container.AddContent(\n new RuntimeVariableReference(this.varIdentifier?.name || null)\n );\n\n // 2.\n // - Expression used in the form ~ x += y\n // - Simple version: ~ x++\n if (this.expression) {\n this.expression.GenerateIntoContainer(container);\n } else {\n container.AddContent(new IntValue(1));\n }\n\n // 3.\n container.AddContent(\n NativeFunctionCall.CallWithName(this.isInc ? \"+\" : \"-\")\n );\n\n // 4.\n this._runtimeAssignment = new RuntimeVariableAssignment(\n this.varIdentifier?.name || null,\n false\n );\n container.AddContent(this._runtimeAssignment);\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n const varResolveResult = context.ResolveVariableWithName(\n this.varIdentifier?.name || \"\",\n this\n );\n\n if (!varResolveResult.found) {\n this.Error(\n `variable for ${this.incrementDecrementWord} could not be found: '${this.varIdentifier}' after searching: {this.descriptionOfScope}`\n );\n }\n\n if (!this._runtimeAssignment) {\n throw new Error();\n }\n\n this._runtimeAssignment.isGlobal = varResolveResult.isGlobal;\n\n if (\n !(this.parent instanceof Weave) &&\n !(this.parent instanceof FlowBase) &&\n !(this.parent instanceof ContentList)\n ) {\n this.Error(`Can't use ${this.incrementDecrementWord} as sub-expression`);\n }\n }\n\n get incrementDecrementWord(): \"increment\" | \"decrement\" {\n if (this.isInc) {\n return \"increment\";\n }\n\n return \"decrement\";\n }\n\n public readonly toString = (): string => {\n if (this.expression) {\n return `${this.varIdentifier?.name}${this.isInc ? \" += \" : \" -= \"}${\n this.expression\n }`;\n }\n\n return `${this.varIdentifier?.name}` + (this.isInc ? \"++\" : \"--\");\n };\n}\n","import { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Story } from \"./Story\";\n\nexport class IncludedFile extends ParsedObject {\n constructor(public readonly includedStory: Story | null) {\n super();\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject | null => {\n // Left to the main story to process\n return null;\n };\n\n get typeName(): string {\n return \"IncludedFile\";\n }\n}\n","export class InfixOperator {\n constructor(\n public readonly type: string,\n public readonly precedence: number,\n public readonly requireWhitespace: boolean\n ) {}\n\n public readonly toString = (): string => this.type;\n}\n","import { Argument } from \"./Argument\";\nimport { FlowBase } from \"./Flow/FlowBase\";\nimport { FlowLevel } from \"./Flow/FlowLevel\";\nimport { Identifier } from \"./Identifier\";\nimport { ParsedObject } from \"./Object\";\nimport { Story } from \"./Story\";\n\nexport class Knot extends FlowBase {\n get flowLevel(): FlowLevel {\n return FlowLevel.Knot;\n }\n\n constructor(\n name: Identifier,\n topLevelObjects: ParsedObject[],\n args: Argument[],\n isFunction: boolean\n ) {\n super(name, topLevelObjects, args, isFunction);\n }\n\n get typeName(): string {\n return this.isFunction ? \"Function\" : \"Knot\";\n }\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n let parentStory = this.story;\n\n // Enforce rule that stitches must not have the same\n // name as any knots that exist in the story\n for (const stitchName in this.subFlowsByName) {\n const knotWithStitchName = parentStory.ContentWithNameAtLevel(\n stitchName,\n FlowLevel.Knot,\n false\n );\n\n if (knotWithStitchName) {\n const stitch = this.subFlowsByName.get(stitchName);\n const errorMsg = `Stitch '${\n stitch ? stitch.name : \"NO STITCH FOUND\"\n }' has the same name as a knot (on ${\n knotWithStitchName.debugMetadata\n })`;\n this.Error(errorMsg, stitch);\n }\n }\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"../Expression/Expression\";\nimport { InkList as RuntimeInkList } from \"../../../../engine/InkList\";\nimport { InkListItem as RuntimeInkListItem } from \"../../../../engine/InkList\";\nimport { ListElementDefinition } from \"./ListElementDefinition\";\nimport { ListValue } from \"../../../../engine/Value\";\nimport { Identifier } from \"../Identifier\";\n\nexport class List extends Expression {\n constructor(public readonly itemIdentifierList: Identifier[]) {\n super();\n }\n\n get typeName(): string {\n return \"List\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n const runtimeRawList = new RuntimeInkList();\n\n if (this.itemIdentifierList != null) {\n for (const itemIdentifier of this.itemIdentifierList) {\n const nameParts = itemIdentifier?.name?.split(\".\") || [];\n\n let listName: string | null = null;\n let listItemName: string = \"\";\n if (nameParts.length > 1) {\n listName = nameParts[0];\n listItemName = nameParts[1];\n } else {\n listItemName = nameParts[0];\n }\n\n const listItem = this.story.ResolveListItem(\n listName,\n listItemName,\n this\n ) as ListElementDefinition;\n\n if (listItem === null) {\n if (listName === null) {\n this.Error(\n `Could not find list definition that contains item '${itemIdentifier}'`\n );\n } else {\n this.Error(`Could not find list item ${itemIdentifier}`);\n }\n } else {\n if (listItem.parent == null) {\n this.Error(\n `Could not find list definition for item ${itemIdentifier}`\n );\n return;\n }\n if (!listName) {\n listName = listItem.parent.identifier?.name || null;\n }\n\n const item = new RuntimeInkListItem(listName, listItem.name || null);\n\n if (runtimeRawList.has(item.serialized())) {\n this.Warning(`Duplicate of item '${itemIdentifier}' in list.`);\n } else {\n runtimeRawList.Add(item, listItem.seriesValue);\n }\n }\n }\n }\n\n container.AddContent(new ListValue(runtimeRawList));\n };\n}\n","import { ListDefinition } from \"./ListDefinition\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Story } from \"../Story\";\nimport { SymbolType } from \"../SymbolType\";\nimport { Identifier } from \"../Identifier\";\n\nexport class ListElementDefinition extends ParsedObject {\n public seriesValue: number = 0;\n\n public parent: ListDefinition | null = null;\n\n get fullName(): string {\n const parentList = this.parent;\n if (parentList === null) {\n throw new Error(\"Can't get full name without a parent list.\");\n }\n\n return `${parentList.identifier?.name}.${this.name}`;\n }\n\n get typeName(): string {\n return \"ListElement\";\n }\n\n get name(): string | null {\n return this.indentifier?.name || null;\n }\n\n constructor(\n public readonly indentifier: Identifier,\n public readonly inInitialList: boolean,\n public readonly explicitValue: number | null = null\n ) {\n super();\n this.parent = this.parent as ListDefinition;\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n throw new Error(\"Not implemented.\");\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n context.CheckForNamingCollisions(\n this,\n this.indentifier,\n SymbolType.ListItem\n );\n }\n\n public readonly toString = (): string => this.fullName;\n}\n","export enum StatementLevel {\n InnerBlock,\n Stitch,\n Knot,\n Top,\n}\n","import { Argument } from \"./Argument\";\nimport { FlowBase } from \"./Flow/FlowBase\";\nimport { FlowLevel } from \"./Flow/FlowLevel\";\nimport { Identifier } from \"./Identifier\";\nimport { ParsedObject } from \"./Object\";\n\nexport class Stitch extends FlowBase {\n get flowLevel(): FlowLevel {\n return FlowLevel.Stitch;\n }\n\n constructor(\n name: Identifier,\n topLevelObjects: ParsedObject[],\n args: Argument[],\n isFunction: boolean\n ) {\n super(name, topLevelObjects, args, isFunction);\n }\n\n get typeName(): string {\n return \"Stitch\";\n }\n\n // Fixes TS issue with not being able to access the prototype via `super` in functions\n // attached to the class as properties.\n private baseToString = this.toString;\n\n public toString = (): string => {\n return `${\n this.parent !== null ? this.parent + \" > \" : \"\"\n }${this.baseToString()}`;\n };\n}\n","import { InkObject } from \"./Object\";\n\n// New version of tags is dynamic - it constructs the tags\n// at runtime based on BeginTag and EndTag control commands.\n// Plain text that's in the output stream is turned into tags\n// when you do story.currentTags.\n// The only place this is used is when flattening tags down\n// to string in advance, during dynamic string generation if\n// there's a tag embedded in it. See how ControlCommand.EndString\n// is implemented in Story.cs for more details + comment\nexport class Tag extends InkObject {\n public readonly text: string;\n\n constructor(tagText: string) {\n super();\n this.text = tagText.toString() || \"\";\n }\n\n public toString(): string {\n return \"# \" + this.text;\n }\n}\n","import { Path } from \"./Path\";\nimport { CallStack } from \"./CallStack\";\nimport { throwNullException } from \"./NullException\";\nimport { InkObject } from \"./Object\";\n\nexport class Choice extends InkObject {\n public text: string = \"\";\n public index: number = 0;\n public threadAtGeneration: CallStack.Thread | null = null;\n public sourcePath: string = \"\";\n public targetPath: Path | null = null;\n public isInvisibleDefault: boolean = false;\n public tags: string[] | null = null;\n public originalThreadIndex: number = 0;\n\n get pathStringOnChoice(): string {\n if (this.targetPath === null)\n return throwNullException(\"Choice.targetPath\");\n return this.targetPath.toString();\n }\n set pathStringOnChoice(value: string) {\n this.targetPath = new Path(value);\n }\n}\n","import { InkListItem } from \"./InkList\";\nimport { ListValue } from \"./Value\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { TryGetResult } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\n\nexport class ListDefinitionsOrigin {\n protected _lists: Map;\n protected _allUnambiguousListValueCache: Map;\n\n constructor(lists: ListDefinition[]) {\n this._lists = new Map();\n this._allUnambiguousListValueCache = new Map();\n\n for (let list of lists) {\n this._lists.set(list.name, list);\n\n for (let [key, val] of list.items) {\n let item = InkListItem.fromSerializedKey(key);\n let listValue = new ListValue(item, val);\n\n if (!item.itemName) {\n throw new Error(\"item.itemName is null or undefined.\");\n }\n\n this._allUnambiguousListValueCache.set(item.itemName, listValue);\n this._allUnambiguousListValueCache.set(item.fullName, listValue);\n }\n }\n }\n get lists(): ListDefinition[] {\n let listOfLists: ListDefinition[] = [];\n\n for (let [, value] of this._lists) {\n listOfLists.push(value);\n }\n\n return listOfLists;\n }\n public TryListGetDefinition(\n name: string | null,\n /* out */ def: ListDefinition | null\n ): TryGetResult {\n if (name === null) {\n return { result: def, exists: false };\n }\n // initially, this function returns a boolean and the second parameter is an out.\n let definition = this._lists.get(name);\n if (!definition) return { result: def, exists: false };\n\n return { result: definition, exists: true };\n }\n public FindSingleItemListWithName(name: string | null) {\n if (name === null) {\n return throwNullException(\"name\");\n }\n let val = this._allUnambiguousListValueCache.get(name);\n\n if (typeof val !== \"undefined\") {\n return val;\n }\n\n return null;\n }\n}\n","import { Container } from \"./Container\";\nimport {\n Value,\n IntValue,\n FloatValue,\n StringValue,\n DivertTargetValue,\n VariablePointerValue,\n ListValue,\n BoolValue,\n} from \"./Value\";\nimport { Glue } from \"./Glue\";\nimport { ControlCommand } from \"./ControlCommand\";\nimport { PushPopType } from \"./PushPop\";\nimport { Divert } from \"./Divert\";\nimport { ChoicePoint } from \"./ChoicePoint\";\nimport { VariableReference } from \"./VariableReference\";\nimport { VariableAssignment } from \"./VariableAssignment\";\nimport { NativeFunctionCall } from \"./NativeFunctionCall\";\nimport { Void } from \"./Void\";\nimport { Tag } from \"./Tag\";\nimport { Path } from \"./Path\";\nimport { Choice } from \"./Choice\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { ListDefinitionsOrigin } from \"./ListDefinitionsOrigin\";\nimport { InkListItem, InkList } from \"./InkList\";\nimport { InkObject } from \"./Object\";\nimport { asOrNull } from \"./TypeAssertion\";\nimport { throwNullException } from \"./NullException\";\nimport { SimpleJson } from \"./SimpleJson\";\n\nexport class JsonSerialisation {\n public static JArrayToRuntimeObjList(\n jArray: any[],\n skipLast: boolean = false\n ) {\n let count = jArray.length;\n if (skipLast) count--;\n\n let list: InkObject[] = [];\n\n for (let i = 0; i < count; i++) {\n let jTok = jArray[i];\n let runtimeObj = this.JTokenToRuntimeObject(jTok);\n if (runtimeObj === null) {\n return throwNullException(\"runtimeObj\");\n }\n list.push(runtimeObj);\n }\n\n return list;\n }\n\n public static WriteDictionaryRuntimeObjs(\n writer: SimpleJson.Writer,\n dictionary: Map\n ) {\n writer.WriteObjectStart();\n for (let [key, value] of dictionary) {\n writer.WritePropertyStart(key);\n this.WriteRuntimeObject(writer, value);\n writer.WritePropertyEnd();\n }\n writer.WriteObjectEnd();\n }\n\n public static WriteListRuntimeObjs(\n writer: SimpleJson.Writer,\n list: InkObject[]\n ) {\n writer.WriteArrayStart();\n for (let value of list) {\n this.WriteRuntimeObject(writer, value);\n }\n writer.WriteArrayEnd();\n }\n\n public static WriteIntDictionary(\n writer: SimpleJson.Writer,\n dict: Map\n ) {\n writer.WriteObjectStart();\n for (let [key, value] of dict) {\n writer.WriteIntProperty(key, value);\n }\n writer.WriteObjectEnd();\n }\n\n public static WriteRuntimeObject(\n writer: SimpleJson.Writer,\n obj: InkObject\n ): void {\n let container = asOrNull(obj, Container);\n if (container) {\n this.WriteRuntimeContainer(writer, container);\n return;\n }\n\n let divert = asOrNull(obj, Divert);\n if (divert) {\n let divTypeKey = \"->\";\n if (divert.isExternal) {\n divTypeKey = \"x()\";\n } else if (divert.pushesToStack) {\n if (divert.stackPushType == PushPopType.Function) {\n divTypeKey = \"f()\";\n } else if (divert.stackPushType == PushPopType.Tunnel) {\n divTypeKey = \"->t->\";\n }\n }\n\n let targetStr;\n if (divert.hasVariableTarget) {\n targetStr = divert.variableDivertName;\n } else {\n targetStr = divert.targetPathString;\n }\n\n writer.WriteObjectStart();\n writer.WriteProperty(divTypeKey, targetStr);\n\n if (divert.hasVariableTarget) {\n writer.WriteProperty(\"var\", true);\n }\n\n if (divert.isConditional) {\n writer.WriteProperty(\"c\", true);\n }\n\n if (divert.externalArgs > 0) {\n writer.WriteIntProperty(\"exArgs\", divert.externalArgs);\n }\n\n writer.WriteObjectEnd();\n return;\n }\n\n let choicePoint = asOrNull(obj, ChoicePoint);\n if (choicePoint) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"*\", choicePoint.pathStringOnChoice);\n writer.WriteIntProperty(\"flg\", choicePoint.flags);\n writer.WriteObjectEnd();\n return;\n }\n\n let boolVal = asOrNull(obj, BoolValue);\n if (boolVal) {\n writer.WriteBool(boolVal.value);\n return;\n }\n\n let intVal = asOrNull(obj, IntValue);\n if (intVal) {\n writer.WriteInt(intVal.value);\n return;\n }\n\n let floatVal = asOrNull(obj, FloatValue);\n if (floatVal) {\n writer.WriteFloat(floatVal.value);\n return;\n }\n\n let strVal = asOrNull(obj, StringValue);\n if (strVal) {\n if (strVal.isNewline) {\n writer.Write(\"\\n\", false);\n } else {\n writer.WriteStringStart();\n writer.WriteStringInner(\"^\");\n writer.WriteStringInner(strVal.value);\n writer.WriteStringEnd();\n }\n return;\n }\n\n let listVal = asOrNull(obj, ListValue);\n if (listVal) {\n this.WriteInkList(writer, listVal);\n return;\n }\n\n let divTargetVal = asOrNull(obj, DivertTargetValue);\n if (divTargetVal) {\n writer.WriteObjectStart();\n if (divTargetVal.value === null) {\n return throwNullException(\"divTargetVal.value\");\n }\n writer.WriteProperty(\"^->\", divTargetVal.value.componentsString);\n writer.WriteObjectEnd();\n\n return;\n }\n\n let varPtrVal = asOrNull(obj, VariablePointerValue);\n if (varPtrVal) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"^var\", varPtrVal.value);\n writer.WriteIntProperty(\"ci\", varPtrVal.contextIndex);\n writer.WriteObjectEnd();\n return;\n }\n\n let glue = asOrNull(obj, Glue);\n if (glue) {\n writer.Write(\"<>\");\n return;\n }\n\n let controlCmd = asOrNull(obj, ControlCommand);\n if (controlCmd) {\n writer.Write(\n JsonSerialisation._controlCommandNames[controlCmd.commandType]\n );\n return;\n }\n\n let nativeFunc = asOrNull(obj, NativeFunctionCall);\n if (nativeFunc) {\n let name = nativeFunc.name;\n\n if (name == \"^\") name = \"L^\";\n\n writer.Write(name);\n return;\n }\n\n let varRef = asOrNull(obj, VariableReference);\n if (varRef) {\n writer.WriteObjectStart();\n let readCountPath = varRef.pathStringForCount;\n if (readCountPath != null) {\n writer.WriteProperty(\"CNT?\", readCountPath);\n } else {\n writer.WriteProperty(\"VAR?\", varRef.name);\n }\n\n writer.WriteObjectEnd();\n return;\n }\n\n let varAss = asOrNull(obj, VariableAssignment);\n if (varAss) {\n writer.WriteObjectStart();\n\n let key = varAss.isGlobal ? \"VAR=\" : \"temp=\";\n writer.WriteProperty(key, varAss.variableName);\n\n // Reassignment?\n if (!varAss.isNewDeclaration) writer.WriteProperty(\"re\", true);\n\n writer.WriteObjectEnd();\n\n return;\n }\n\n let voidObj = asOrNull(obj, Void);\n if (voidObj) {\n writer.Write(\"void\");\n return;\n }\n\n let tag = asOrNull(obj, Tag);\n if (tag) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"#\", tag.text);\n writer.WriteObjectEnd();\n return;\n }\n\n let choice = asOrNull(obj, Choice);\n if (choice) {\n this.WriteChoice(writer, choice);\n return;\n }\n\n throw new Error(\"Failed to convert runtime object to Json token: \" + obj);\n }\n\n public static JObjectToDictionaryRuntimeObjs(jObject: Record) {\n let dict: Map = new Map();\n\n for (let key in jObject) {\n if (jObject.hasOwnProperty(key)) {\n let inkObject = this.JTokenToRuntimeObject(jObject[key]);\n if (inkObject === null) {\n return throwNullException(\"inkObject\");\n }\n dict.set(key, inkObject);\n }\n }\n\n return dict;\n }\n\n public static JObjectToIntDictionary(jObject: Record) {\n let dict: Map = new Map();\n for (let key in jObject) {\n if (jObject.hasOwnProperty(key)) {\n dict.set(key, parseInt(jObject[key]));\n }\n }\n return dict;\n }\n\n public static JTokenToRuntimeObject(token: any): InkObject | null {\n if (\n (typeof token === \"number\" && !isNaN(token)) ||\n typeof token === \"boolean\"\n ) {\n return Value.Create(token);\n }\n\n if (typeof token === \"string\") {\n let str = token.toString();\n\n // String value\n let firstChar = str[0];\n if (firstChar == \"^\") return new StringValue(str.substring(1));\n else if (firstChar == \"\\n\" && str.length == 1)\n return new StringValue(\"\\n\");\n\n // Glue\n if (str == \"<>\") return new Glue();\n\n // Control commands (would looking up in a hash set be faster?)\n for (let i = 0; i < JsonSerialisation._controlCommandNames.length; ++i) {\n let cmdName = JsonSerialisation._controlCommandNames[i];\n if (str == cmdName) {\n return new ControlCommand(i);\n }\n }\n\n // Native functions\n if (str == \"L^\") str = \"^\";\n if (NativeFunctionCall.CallExistsWithName(str))\n return NativeFunctionCall.CallWithName(str);\n\n // Pop\n if (str == \"->->\") return ControlCommand.PopTunnel();\n else if (str == \"~ret\") return ControlCommand.PopFunction();\n\n // Void\n if (str == \"void\") return new Void();\n }\n\n if (typeof token === \"object\" && !Array.isArray(token)) {\n let obj = token as Record;\n let propValue;\n\n // Divert target value to path\n if (obj[\"^->\"]) {\n propValue = obj[\"^->\"];\n return new DivertTargetValue(new Path(propValue.toString()));\n }\n\n // VariablePointerValue\n if (obj[\"^var\"]) {\n propValue = obj[\"^var\"];\n let varPtr = new VariablePointerValue(propValue.toString());\n if (\"ci\" in obj) {\n propValue = obj[\"ci\"];\n varPtr.contextIndex = parseInt(propValue);\n }\n return varPtr;\n }\n\n // Divert\n let isDivert = false;\n let pushesToStack = false;\n let divPushType = PushPopType.Function;\n let external = false;\n if ((propValue = obj[\"->\"])) {\n isDivert = true;\n } else if ((propValue = obj[\"f()\"])) {\n isDivert = true;\n pushesToStack = true;\n divPushType = PushPopType.Function;\n } else if ((propValue = obj[\"->t->\"])) {\n isDivert = true;\n pushesToStack = true;\n divPushType = PushPopType.Tunnel;\n } else if ((propValue = obj[\"x()\"])) {\n isDivert = true;\n external = true;\n pushesToStack = false;\n divPushType = PushPopType.Function;\n }\n\n if (isDivert) {\n let divert = new Divert();\n divert.pushesToStack = pushesToStack;\n divert.stackPushType = divPushType;\n divert.isExternal = external;\n\n let target = propValue.toString();\n\n if ((propValue = obj[\"var\"])) divert.variableDivertName = target;\n else divert.targetPathString = target;\n\n divert.isConditional = !!obj[\"c\"];\n\n if (external) {\n if ((propValue = obj[\"exArgs\"]))\n divert.externalArgs = parseInt(propValue);\n }\n\n return divert;\n }\n\n // Choice\n if ((propValue = obj[\"*\"])) {\n let choice = new ChoicePoint();\n choice.pathStringOnChoice = propValue.toString();\n\n if ((propValue = obj[\"flg\"])) choice.flags = parseInt(propValue);\n\n return choice;\n }\n\n // Variable reference\n if ((propValue = obj[\"VAR?\"])) {\n return new VariableReference(propValue.toString());\n } else if ((propValue = obj[\"CNT?\"])) {\n let readCountVarRef = new VariableReference();\n readCountVarRef.pathStringForCount = propValue.toString();\n return readCountVarRef;\n }\n\n // Variable assignment\n let isVarAss = false;\n let isGlobalVar = false;\n if ((propValue = obj[\"VAR=\"])) {\n isVarAss = true;\n isGlobalVar = true;\n } else if ((propValue = obj[\"temp=\"])) {\n isVarAss = true;\n isGlobalVar = false;\n }\n if (isVarAss) {\n let varName = propValue.toString();\n let isNewDecl = !obj[\"re\"];\n let varAss = new VariableAssignment(varName, isNewDecl);\n varAss.isGlobal = isGlobalVar;\n return varAss;\n }\n if (obj[\"#\"] !== undefined) {\n propValue = obj[\"#\"];\n return new Tag(propValue.toString());\n }\n\n // List value\n if ((propValue = obj[\"list\"])) {\n // var listContent = (Dictionary)propValue;\n let listContent = propValue as Record;\n let rawList = new InkList();\n if ((propValue = obj[\"origins\"])) {\n // var namesAsObjs = (List)propValue;\n let namesAsObjs = propValue as string[];\n // rawList.SetInitialOriginNames(namesAsObjs.Cast().ToList());\n rawList.SetInitialOriginNames(namesAsObjs);\n }\n\n for (let key in listContent) {\n if (listContent.hasOwnProperty(key)) {\n let nameToVal = listContent[key];\n let item = new InkListItem(key);\n let val = parseInt(nameToVal);\n rawList.Add(item, val);\n }\n }\n\n return new ListValue(rawList);\n }\n\n if (obj[\"originalChoicePath\"] != null) return this.JObjectToChoice(obj);\n }\n\n // Array is always a Runtime.Container\n if (Array.isArray(token)) {\n return this.JArrayToContainer(token);\n }\n\n if (token === null || token === undefined) return null;\n\n throw new Error(\n \"Failed to convert token to runtime object: \" +\n this.toJson(token, [\"parent\"])\n );\n }\n\n public static toJson(\n me: T,\n removes?: (keyof T)[],\n space?: number\n ): string {\n return JSON.stringify(\n me,\n (k, v) => (removes?.some((r) => r === k) ? undefined : v),\n space\n );\n }\n\n public static WriteRuntimeContainer(\n writer: SimpleJson.Writer,\n container: Container | null,\n withoutName: boolean = false\n ) {\n writer.WriteArrayStart();\n if (container === null) {\n return throwNullException(\"container\");\n }\n for (let c of container.content) this.WriteRuntimeObject(writer, c);\n\n let namedOnlyContent = container.namedOnlyContent;\n let countFlags = container.countFlags;\n let hasNameProperty = container.name != null && !withoutName;\n\n let hasTerminator =\n namedOnlyContent != null || countFlags > 0 || hasNameProperty;\n if (hasTerminator) {\n writer.WriteObjectStart();\n }\n\n if (namedOnlyContent != null) {\n for (let [key, value] of namedOnlyContent) {\n let name = key;\n let namedContainer = asOrNull(value, Container);\n writer.WritePropertyStart(name);\n this.WriteRuntimeContainer(writer, namedContainer, true);\n writer.WritePropertyEnd();\n }\n }\n\n if (countFlags > 0) writer.WriteIntProperty(\"#f\", countFlags);\n\n if (hasNameProperty) writer.WriteProperty(\"#n\", container.name);\n\n if (hasTerminator) writer.WriteObjectEnd();\n else writer.WriteNull();\n\n writer.WriteArrayEnd();\n }\n\n public static JArrayToContainer(jArray: any[]) {\n let container = new Container();\n container.content = this.JArrayToRuntimeObjList(jArray, true);\n\n let terminatingObj = jArray[jArray.length - 1] as Record;\n if (terminatingObj != null) {\n let namedOnlyContent = new Map();\n\n for (let key in terminatingObj) {\n if (key == \"#f\") {\n container.countFlags = parseInt(terminatingObj[key]);\n } else if (key == \"#n\") {\n container.name = terminatingObj[key].toString();\n } else {\n let namedContentItem = this.JTokenToRuntimeObject(\n terminatingObj[key]\n );\n // var namedSubContainer = namedContentItem as Container;\n let namedSubContainer = asOrNull(namedContentItem, Container);\n if (namedSubContainer) namedSubContainer.name = key;\n namedOnlyContent.set(key, namedContentItem);\n }\n }\n\n container.namedOnlyContent = namedOnlyContent;\n }\n\n return container;\n }\n\n public static JObjectToChoice(jObj: Record) {\n let choice = new Choice();\n choice.text = jObj[\"text\"].toString();\n choice.index = parseInt(jObj[\"index\"]);\n choice.sourcePath = jObj[\"originalChoicePath\"].toString();\n choice.originalThreadIndex = parseInt(jObj[\"originalThreadIndex\"]);\n choice.pathStringOnChoice = jObj[\"targetPath\"].toString();\n if (jObj[\"tags\"]) {\n choice.tags = jObj[\"tags\"];\n }\n return choice;\n }\n\n public static WriteChoice(writer: SimpleJson.Writer, choice: Choice) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"text\", choice.text);\n writer.WriteIntProperty(\"index\", choice.index);\n writer.WriteProperty(\"originalChoicePath\", choice.sourcePath);\n writer.WriteIntProperty(\"originalThreadIndex\", choice.originalThreadIndex);\n writer.WriteProperty(\"targetPath\", choice.pathStringOnChoice);\n if (choice.tags) {\n writer.WriteProperty(\"tags\", (w) => {\n w.WriteArrayStart();\n for (const tag of choice.tags!) {\n w.WriteStringStart();\n w.WriteStringInner(tag);\n w.WriteStringEnd();\n }\n w.WriteArrayEnd();\n });\n }\n writer.WriteObjectEnd();\n }\n\n public static WriteInkList(writer: SimpleJson.Writer, listVal: ListValue) {\n let rawList = listVal.value;\n if (rawList === null) {\n return throwNullException(\"rawList\");\n }\n\n writer.WriteObjectStart();\n writer.WritePropertyStart(\"list\");\n writer.WriteObjectStart();\n\n for (let [key, val] of rawList) {\n let item = InkListItem.fromSerializedKey(key);\n let itemVal = val;\n\n if (item.itemName === null) {\n return throwNullException(\"item.itemName\");\n }\n\n writer.WritePropertyNameStart();\n writer.WritePropertyNameInner(item.originName ? item.originName : \"?\");\n writer.WritePropertyNameInner(\".\");\n writer.WritePropertyNameInner(item.itemName);\n writer.WritePropertyNameEnd();\n\n writer.Write(itemVal);\n\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n\n writer.WritePropertyEnd();\n\n if (\n rawList.Count == 0 &&\n rawList.originNames != null &&\n rawList.originNames.length > 0\n ) {\n writer.WritePropertyStart(\"origins\");\n writer.WriteArrayStart();\n for (let name of rawList.originNames) writer.Write(name);\n writer.WriteArrayEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n }\n\n public static ListDefinitionsToJToken(origin: ListDefinitionsOrigin) {\n let result: Record = {};\n\n for (let def of origin.lists) {\n let listDefJson: Record = {};\n\n for (let [key, val] of def.items) {\n let item = InkListItem.fromSerializedKey(key);\n if (item.itemName === null) {\n return throwNullException(\"item.itemName\");\n }\n listDefJson[item.itemName] = val;\n }\n\n result[def.name] = listDefJson;\n }\n\n return result;\n }\n\n public static JTokenToListDefinitions(obj: Record) {\n // var defsObj = (Dictionary)obj;\n let defsObj = obj;\n\n let allDefs: ListDefinition[] = [];\n\n for (let key in defsObj) {\n if (defsObj.hasOwnProperty(key)) {\n let name = key.toString();\n // var listDefJson = (Dictionary)kv.Value;\n let listDefJson = defsObj[key] as Record;\n\n // Cast (string, object) to (string, int) for items\n let items: Map = new Map();\n\n for (let nameValueKey in listDefJson) {\n if (defsObj.hasOwnProperty(key)) {\n let nameValue = listDefJson[nameValueKey];\n items.set(nameValueKey, parseInt(nameValue));\n }\n }\n\n let def = new ListDefinition(name, items);\n allDefs.push(def);\n }\n }\n\n return new ListDefinitionsOrigin(allDefs);\n }\n\n private static _controlCommandNames = (() => {\n let _controlCommandNames: string[] = [];\n\n _controlCommandNames[ControlCommand.CommandType.EvalStart] = \"ev\";\n _controlCommandNames[ControlCommand.CommandType.EvalOutput] = \"out\";\n _controlCommandNames[ControlCommand.CommandType.EvalEnd] = \"/ev\";\n _controlCommandNames[ControlCommand.CommandType.Duplicate] = \"du\";\n _controlCommandNames[ControlCommand.CommandType.PopEvaluatedValue] = \"pop\";\n _controlCommandNames[ControlCommand.CommandType.PopFunction] = \"~ret\";\n _controlCommandNames[ControlCommand.CommandType.PopTunnel] = \"->->\";\n _controlCommandNames[ControlCommand.CommandType.BeginString] = \"str\";\n _controlCommandNames[ControlCommand.CommandType.EndString] = \"/str\";\n _controlCommandNames[ControlCommand.CommandType.NoOp] = \"nop\";\n _controlCommandNames[ControlCommand.CommandType.ChoiceCount] = \"choiceCnt\";\n _controlCommandNames[ControlCommand.CommandType.Turns] = \"turn\";\n _controlCommandNames[ControlCommand.CommandType.TurnsSince] = \"turns\";\n _controlCommandNames[ControlCommand.CommandType.ReadCount] = \"readc\";\n _controlCommandNames[ControlCommand.CommandType.Random] = \"rnd\";\n _controlCommandNames[ControlCommand.CommandType.SeedRandom] = \"srnd\";\n _controlCommandNames[ControlCommand.CommandType.VisitIndex] = \"visit\";\n _controlCommandNames[ControlCommand.CommandType.SequenceShuffleIndex] =\n \"seq\";\n _controlCommandNames[ControlCommand.CommandType.StartThread] = \"thread\";\n _controlCommandNames[ControlCommand.CommandType.Done] = \"done\";\n _controlCommandNames[ControlCommand.CommandType.End] = \"end\";\n _controlCommandNames[ControlCommand.CommandType.ListFromInt] = \"listInt\";\n _controlCommandNames[ControlCommand.CommandType.ListRange] = \"range\";\n _controlCommandNames[ControlCommand.CommandType.ListRandom] = \"lrnd\";\n _controlCommandNames[ControlCommand.CommandType.BeginTag] = \"#\";\n _controlCommandNames[ControlCommand.CommandType.EndTag] = \"/#\";\n\n for (let i = 0; i < ControlCommand.CommandType.TOTAL_VALUES; ++i) {\n if (_controlCommandNames[i] == null)\n throw new Error(\"Control command not accounted for in serialisation\");\n }\n\n return _controlCommandNames;\n })();\n}\n","import { PushPopType } from \"./PushPop\";\nimport { Path } from \"./Path\";\nimport { Story } from \"./Story\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { ListValue } from \"./Value\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { Pointer } from \"./Pointer\";\nimport { InkObject } from \"./Object\";\nimport { Debug } from \"./Debug\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\nimport { SimpleJson } from \"./SimpleJson\";\n\nexport class CallStack {\n get elements() {\n return this.callStack;\n }\n\n get depth() {\n return this.elements.length;\n }\n\n get currentElement() {\n let thread = this._threads[this._threads.length - 1];\n let cs = thread.callstack;\n return cs[cs.length - 1];\n }\n\n get currentElementIndex() {\n return this.callStack.length - 1;\n }\n\n get currentThread(): CallStack.Thread {\n return this._threads[this._threads.length - 1];\n }\n set currentThread(value: CallStack.Thread) {\n Debug.Assert(\n this._threads.length == 1,\n \"Shouldn't be directly setting the current thread when we have a stack of them\"\n );\n\n this._threads.length = 0;\n this._threads.push(value);\n }\n\n get canPop() {\n return this.callStack.length > 1;\n }\n\n constructor(storyContext: Story);\n constructor(toCopy: CallStack);\n constructor() {\n if (arguments[0] instanceof Story) {\n let storyContext = arguments[0] as Story;\n\n this._startOfRoot = Pointer.StartOf(storyContext.rootContentContainer);\n this.Reset();\n } else {\n let toCopy = arguments[0] as CallStack;\n\n this._threads = [];\n for (let otherThread of toCopy._threads) {\n this._threads.push(otherThread.Copy());\n }\n this._threadCounter = toCopy._threadCounter;\n this._startOfRoot = toCopy._startOfRoot.copy();\n }\n }\n\n public Reset() {\n this._threads = [];\n this._threads.push(new CallStack.Thread());\n\n this._threads[0].callstack.push(\n new CallStack.Element(PushPopType.Tunnel, this._startOfRoot)\n );\n }\n\n public SetJsonToken(jObject: Record, storyContext: Story) {\n this._threads.length = 0;\n\n // TODO: (List) jObject [\"threads\"];\n let jThreads: any[] = jObject[\"threads\"];\n\n for (let jThreadTok of jThreads) {\n // TODO: var jThreadObj = (Dictionary)jThreadTok;\n let jThreadObj = jThreadTok;\n let thread = new CallStack.Thread(jThreadObj, storyContext);\n this._threads.push(thread);\n }\n\n // TODO: (int)jObject [\"threadCounter\"];\n this._threadCounter = parseInt(jObject[\"threadCounter\"]);\n this._startOfRoot = Pointer.StartOf(storyContext.rootContentContainer);\n }\n public WriteJson(w: SimpleJson.Writer) {\n w.WriteObject((writer) => {\n writer.WritePropertyStart(\"threads\");\n writer.WriteArrayStart();\n\n for (let thread of this._threads) {\n thread.WriteJson(writer);\n }\n\n writer.WriteArrayEnd();\n writer.WritePropertyEnd();\n\n writer.WritePropertyStart(\"threadCounter\");\n writer.WriteInt(this._threadCounter);\n writer.WritePropertyEnd();\n });\n }\n\n public PushThread() {\n let newThread = this.currentThread.Copy();\n this._threadCounter++;\n newThread.threadIndex = this._threadCounter;\n this._threads.push(newThread);\n }\n\n public ForkThread() {\n let forkedThread = this.currentThread.Copy();\n this._threadCounter++;\n forkedThread.threadIndex = this._threadCounter;\n return forkedThread;\n }\n\n public PopThread() {\n if (this.canPopThread) {\n this._threads.splice(this._threads.indexOf(this.currentThread), 1); // should be equivalent to a pop()\n } else {\n throw new Error(\"Can't pop thread\");\n }\n }\n\n get canPopThread() {\n return this._threads.length > 1 && !this.elementIsEvaluateFromGame;\n }\n\n get elementIsEvaluateFromGame() {\n return this.currentElement.type == PushPopType.FunctionEvaluationFromGame;\n }\n\n public Push(\n type: PushPopType,\n externalEvaluationStackHeight: number = 0,\n outputStreamLengthWithPushed: number = 0\n ) {\n let element = new CallStack.Element(\n type,\n this.currentElement.currentPointer,\n false\n );\n\n element.evaluationStackHeightWhenPushed = externalEvaluationStackHeight;\n element.functionStartInOutputStream = outputStreamLengthWithPushed;\n\n this.callStack.push(element);\n }\n\n public CanPop(type: PushPopType | null = null) {\n if (!this.canPop) return false;\n\n if (type == null) return true;\n\n return this.currentElement.type == type;\n }\n\n public Pop(type: PushPopType | null = null) {\n if (this.CanPop(type)) {\n this.callStack.pop();\n return;\n } else {\n throw new Error(\"Mismatched push/pop in Callstack\");\n }\n }\n\n public GetTemporaryVariableWithName(\n name: string | null,\n contextIndex: number = -1\n ) {\n if (contextIndex == -1) contextIndex = this.currentElementIndex + 1;\n\n let contextElement = this.callStack[contextIndex - 1];\n\n let varValue = tryGetValueFromMap(\n contextElement.temporaryVariables,\n name,\n null\n );\n if (varValue.exists) {\n return varValue.result;\n } else {\n return null;\n }\n }\n\n public SetTemporaryVariable(\n name: string,\n value: any,\n declareNew: boolean,\n contextIndex: number = -1\n ) {\n if (contextIndex == -1) contextIndex = this.currentElementIndex + 1;\n\n let contextElement = this.callStack[contextIndex - 1];\n\n if (!declareNew && !contextElement.temporaryVariables.get(name)) {\n throw new Error(\"Could not find temporary variable to set: \" + name);\n }\n\n let oldValue = tryGetValueFromMap(\n contextElement.temporaryVariables,\n name,\n null\n );\n if (oldValue.exists)\n ListValue.RetainListOriginsForAssignment(oldValue.result, value);\n\n contextElement.temporaryVariables.set(name, value);\n }\n\n public ContextForVariableNamed(name: string) {\n if (this.currentElement.temporaryVariables.get(name)) {\n return this.currentElementIndex + 1;\n } else {\n return 0;\n }\n }\n\n public ThreadWithIndex(index: number) {\n let filtered = this._threads.filter((t) => {\n if (t.threadIndex == index) return t;\n });\n\n return filtered.length > 0 ? filtered[0] : null;\n }\n\n get callStack() {\n return this.currentThread.callstack;\n }\n\n get callStackTrace() {\n let sb = new StringBuilder();\n\n for (let t = 0; t < this._threads.length; t++) {\n let thread = this._threads[t];\n let isCurrent = t == this._threads.length - 1;\n sb.AppendFormat(\n \"=== THREAD {0}/{1} {2}===\\n\",\n t + 1,\n this._threads.length,\n isCurrent ? \"(current) \" : \"\"\n );\n\n for (let i = 0; i < thread.callstack.length; i++) {\n if (thread.callstack[i].type == PushPopType.Function)\n sb.Append(\" [FUNCTION] \");\n else sb.Append(\" [TUNNEL] \");\n\n let pointer = thread.callstack[i].currentPointer;\n if (!pointer.isNull) {\n sb.Append(\"\");\n }\n }\n }\n\n return sb.toString();\n }\n\n public _threads!: CallStack.Thread[]; // Banged because it's initialized in Reset().\n public _threadCounter: number = 0;\n public _startOfRoot: Pointer = Pointer.Null;\n}\n\nexport namespace CallStack {\n export class Element {\n public currentPointer: Pointer;\n public inExpressionEvaluation: boolean;\n public temporaryVariables: Map;\n public type: PushPopType;\n\n public evaluationStackHeightWhenPushed: number = 0;\n public functionStartInOutputStream: number = 0;\n\n constructor(\n type: PushPopType,\n pointer: Pointer,\n inExpressionEvaluation: boolean = false\n ) {\n this.currentPointer = pointer.copy();\n this.inExpressionEvaluation = inExpressionEvaluation;\n this.temporaryVariables = new Map();\n this.type = type;\n }\n\n public Copy() {\n let copy = new Element(\n this.type,\n this.currentPointer,\n this.inExpressionEvaluation\n );\n copy.temporaryVariables = new Map(this.temporaryVariables);\n copy.evaluationStackHeightWhenPushed =\n this.evaluationStackHeightWhenPushed;\n copy.functionStartInOutputStream = this.functionStartInOutputStream;\n return copy;\n }\n }\n\n export class Thread {\n public callstack: Element[];\n public threadIndex: number = 0;\n public previousPointer: Pointer = Pointer.Null;\n\n constructor();\n constructor(jThreadObj: any, storyContext: Story);\n constructor() {\n this.callstack = [];\n\n if (arguments[0] && arguments[1]) {\n let jThreadObj = arguments[0];\n let storyContext = arguments[1];\n\n // TODO: (int) jThreadObj['threadIndex'] can raise;\n this.threadIndex = parseInt(jThreadObj[\"threadIndex\"]);\n\n let jThreadCallstack = jThreadObj[\"callstack\"];\n\n for (let jElTok of jThreadCallstack) {\n let jElementObj = jElTok;\n\n // TODO: (int) jElementObj['type'] can raise;\n let pushPopType: PushPopType = parseInt(jElementObj[\"type\"]);\n\n let pointer = Pointer.Null;\n\n let currentContainerPathStr: string;\n // TODO: jElementObj.TryGetValue (\"cPath\", out currentContainerPathStrToken);\n let currentContainerPathStrToken = jElementObj[\"cPath\"];\n if (typeof currentContainerPathStrToken !== \"undefined\") {\n currentContainerPathStr = currentContainerPathStrToken.toString();\n\n let threadPointerResult = storyContext.ContentAtPath(\n new Path(currentContainerPathStr)\n );\n pointer.container = threadPointerResult.container;\n pointer.index = parseInt(jElementObj[\"idx\"]);\n\n if (threadPointerResult.obj == null)\n throw new Error(\n \"When loading state, internal story location couldn't be found: \" +\n currentContainerPathStr +\n \". Has the story changed since this save data was created?\"\n );\n else if (threadPointerResult.approximate) {\n if (pointer.container === null) {\n return throwNullException(\"pointer.container\");\n }\n storyContext.Warning(\n \"When loading state, exact internal story location couldn't be found: '\" +\n currentContainerPathStr +\n \"', so it was approximated to '\" +\n pointer.container.path.toString() +\n \"' to recover. Has the story changed since this save data was created?\"\n );\n }\n }\n\n let inExpressionEvaluation = !!jElementObj[\"exp\"];\n\n let el = new Element(pushPopType, pointer, inExpressionEvaluation);\n\n let temps = jElementObj[\"temp\"];\n if (typeof temps !== \"undefined\") {\n el.temporaryVariables =\n JsonSerialisation.JObjectToDictionaryRuntimeObjs(temps);\n } else {\n el.temporaryVariables.clear();\n }\n\n this.callstack.push(el);\n }\n\n let prevContentObjPath = jThreadObj[\"previousContentObject\"];\n if (typeof prevContentObjPath !== \"undefined\") {\n let prevPath = new Path(prevContentObjPath.toString());\n this.previousPointer = storyContext.PointerAtPath(prevPath);\n }\n }\n }\n\n public Copy() {\n let copy = new Thread();\n copy.threadIndex = this.threadIndex;\n for (let e of this.callstack) {\n copy.callstack.push(e.Copy());\n }\n copy.previousPointer = this.previousPointer.copy();\n return copy;\n }\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n\n writer.WritePropertyStart(\"callstack\");\n writer.WriteArrayStart();\n for (let el of this.callstack) {\n writer.WriteObjectStart();\n if (!el.currentPointer.isNull) {\n if (el.currentPointer.container === null) {\n return throwNullException(\"el.currentPointer.container\");\n }\n writer.WriteProperty(\n \"cPath\",\n el.currentPointer.container.path.componentsString\n );\n writer.WriteIntProperty(\"idx\", el.currentPointer.index);\n }\n\n writer.WriteProperty(\"exp\", el.inExpressionEvaluation);\n writer.WriteIntProperty(\"type\", el.type);\n\n if (el.temporaryVariables.size > 0) {\n writer.WritePropertyStart(\"temp\");\n JsonSerialisation.WriteDictionaryRuntimeObjs(\n writer,\n el.temporaryVariables\n );\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n }\n writer.WriteArrayEnd();\n writer.WritePropertyEnd();\n\n writer.WriteIntProperty(\"threadIndex\", this.threadIndex);\n\n if (!this.previousPointer.isNull) {\n let resolvedPointer = this.previousPointer.Resolve();\n if (resolvedPointer === null) {\n return throwNullException(\"this.previousPointer.Resolve()\");\n }\n writer.WriteProperty(\n \"previousContentObject\",\n resolvedPointer.path.toString()\n );\n }\n\n writer.WriteObjectEnd();\n }\n }\n}\n","import {\n AbstractValue,\n Value,\n VariablePointerValue,\n ListValue,\n IntValue,\n FloatValue,\n BoolValue,\n} from \"./Value\";\nimport { VariableAssignment } from \"./VariableAssignment\";\nimport { InkObject } from \"./Object\";\nimport { ListDefinitionsOrigin } from \"./ListDefinitionsOrigin\";\nimport { StoryException } from \"./StoryException\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { asOrThrows, asOrNull, isEquatable } from \"./TypeAssertion\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\nimport { CallStack } from \"./CallStack\";\nimport { StatePatch } from \"./StatePatch\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { InkList } from \"./Story\";\nimport { Path } from \"./Path\";\n\n// Fake class wrapper around VariableState to have correct typing\n// when using the Proxy syntax in typescript\nfunction VariablesStateAccessor(): new () => Pick {\n return class {} as any;\n}\n\ntype VariableStateValue = boolean | string | number | InkList | Path | null;\n\nexport class VariablesState extends VariablesStateAccessor<\n Record\n>() {\n // The way variableChangedEvent is a bit different than the reference implementation.\n // Originally it uses the C# += operator to add delegates, but in js we need to maintain\n // an actual collection of delegates (ie. callbacks) to register a new one, there is a\n // special ObserveVariableChange method below.\n public variableChangedEventCallbacks: Array<\n (variableName: string, newValue: InkObject) => void\n > = [];\n public variableChangedEvent(variableName: string, newValue: InkObject): void {\n for (let callback of this.variableChangedEventCallbacks) {\n callback(variableName, newValue);\n }\n }\n\n public patch: StatePatch | null = null;\n\n get batchObservingVariableChanges() {\n return this._batchObservingVariableChanges;\n }\n set batchObservingVariableChanges(value: boolean) {\n this._batchObservingVariableChanges = value;\n if (value) {\n this._changedVariablesForBatchObs = new Set();\n } else {\n if (this._changedVariablesForBatchObs != null) {\n for (let variableName of this._changedVariablesForBatchObs) {\n let currentValue = this._globalVariables.get(variableName);\n if (!currentValue) {\n throwNullException(\"currentValue\");\n } else {\n this.variableChangedEvent(variableName, currentValue);\n }\n }\n\n this._changedVariablesForBatchObs = null;\n }\n }\n }\n\n get callStack() {\n return this._callStack;\n }\n set callStack(callStack) {\n this._callStack = callStack;\n }\n\n private _batchObservingVariableChanges: boolean = false;\n\n // the original code uses a magic getter and setter for global variables,\n // allowing things like variableState['varname]. This is not quite possible\n // in js without a Proxy, so it is replaced with this $ function.\n public $(variableName: string): VariableStateValue;\n public $(variableName: string, value: VariableStateValue): void;\n public $(variableName: string, value?: any) {\n if (typeof value === \"undefined\") {\n let varContents = null;\n\n if (this.patch !== null) {\n varContents = this.patch.TryGetGlobal(variableName, null);\n if (varContents.exists)\n return (varContents.result as AbstractValue).valueObject;\n }\n\n varContents = this._globalVariables.get(variableName);\n\n if (typeof varContents === \"undefined\") {\n varContents = this._defaultGlobalVariables.get(variableName);\n }\n\n if (typeof varContents !== \"undefined\")\n return (varContents as AbstractValue).valueObject;\n else return null;\n } else {\n if (typeof this._defaultGlobalVariables.get(variableName) === \"undefined\")\n throw new StoryException(\n \"Cannot assign to a variable (\" +\n variableName +\n \") that hasn't been declared in the story\"\n );\n\n let val = Value.Create(value);\n if (val == null) {\n if (value == null) {\n throw new Error(\"Cannot pass null to VariableState\");\n } else {\n throw new Error(\n \"Invalid value passed to VariableState: \" + value.toString()\n );\n }\n }\n\n this.SetGlobal(variableName, val);\n }\n }\n\n constructor(\n callStack: CallStack,\n listDefsOrigin: ListDefinitionsOrigin | null\n ) {\n super();\n this._globalVariables = new Map();\n this._callStack = callStack;\n this._listDefsOrigin = listDefsOrigin;\n\n // if es6 proxies are available, use them.\n try {\n // the proxy is used to allow direct manipulation of global variables.\n // It first tries to access the objects own property, and if none is\n // found it delegates the call to the $ method, defined below\n let p = new Proxy(this, {\n get(target: any, name) {\n return name in target ? target[name] : target.$(name);\n },\n set(target: any, name, value) {\n if (name in target) target[name] = value;\n else target.$(name, value);\n return true; // returning a falsy value make the trap fail\n },\n });\n\n return p;\n } catch (e) {\n // the proxy object is not available in this context. we should warn the\n // dev but writing to the console feels a bit intrusive.\n // console.log(\"ES6 Proxy not available - direct manipulation of global variables can't work, use $() instead.\");\n }\n }\n\n public ApplyPatch() {\n if (this.patch === null) {\n return throwNullException(\"this.patch\");\n }\n\n for (let [namedVarKey, namedVarValue] of this.patch.globals) {\n this._globalVariables.set(namedVarKey, namedVarValue);\n }\n\n if (this._changedVariablesForBatchObs !== null) {\n for (let name of this.patch.changedVariables) {\n this._changedVariablesForBatchObs.add(name);\n }\n }\n\n this.patch = null;\n }\n\n public SetJsonToken(jToken: Record) {\n this._globalVariables.clear();\n\n for (let [varValKey, varValValue] of this._defaultGlobalVariables) {\n let loadedToken = jToken[varValKey];\n if (typeof loadedToken !== \"undefined\") {\n let tokenInkObject =\n JsonSerialisation.JTokenToRuntimeObject(loadedToken);\n if (tokenInkObject === null) {\n return throwNullException(\"tokenInkObject\");\n }\n this._globalVariables.set(varValKey, tokenInkObject);\n } else {\n this._globalVariables.set(varValKey, varValValue);\n }\n }\n }\n\n public static dontSaveDefaultValues: boolean = true;\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n for (let [keyValKey, keyValValue] of this._globalVariables) {\n let name = keyValKey;\n let val = keyValValue;\n\n if (VariablesState.dontSaveDefaultValues) {\n if (this._defaultGlobalVariables.has(name)) {\n let defaultVal = this._defaultGlobalVariables.get(name)!;\n if (this.RuntimeObjectsEqual(val, defaultVal)) continue;\n }\n }\n\n writer.WritePropertyStart(name);\n JsonSerialisation.WriteRuntimeObject(writer, val);\n writer.WritePropertyEnd();\n }\n writer.WriteObjectEnd();\n }\n\n public RuntimeObjectsEqual(\n obj1: InkObject | null,\n obj2: InkObject | null\n ): boolean {\n if (obj1 === null) {\n return throwNullException(\"obj1\");\n }\n if (obj2 === null) {\n return throwNullException(\"obj2\");\n }\n\n if (obj1.constructor !== obj2.constructor) return false;\n\n let boolVal = asOrNull(obj1, BoolValue);\n if (boolVal !== null) {\n return boolVal.value === asOrThrows(obj2, BoolValue).value;\n }\n\n let intVal = asOrNull(obj1, IntValue);\n if (intVal !== null) {\n return intVal.value === asOrThrows(obj2, IntValue).value;\n }\n\n let floatVal = asOrNull(obj1, FloatValue);\n if (floatVal !== null) {\n return floatVal.value === asOrThrows(obj2, FloatValue).value;\n }\n\n let val1 = asOrNull(obj1, Value);\n let val2 = asOrNull(obj2, Value);\n if (val1 !== null && val2 !== null) {\n if (isEquatable(val1.valueObject) && isEquatable(val2.valueObject)) {\n return val1.valueObject.Equals(val2.valueObject);\n } else {\n return val1.valueObject === val2.valueObject;\n }\n }\n\n throw new Error(\n \"FastRoughDefinitelyEquals: Unsupported runtime object type: \" +\n obj1.constructor.name\n );\n }\n\n public GetVariableWithName(\n name: string | null,\n contextIndex: number = -1\n ): InkObject | null {\n let varValue = this.GetRawVariableWithName(name, contextIndex);\n\n // var varPointer = varValue as VariablePointerValue;\n let varPointer = asOrNull(varValue, VariablePointerValue);\n if (varPointer !== null) {\n varValue = this.ValueAtVariablePointer(varPointer);\n }\n\n return varValue;\n }\n\n public TryGetDefaultVariableValue(name: string | null): InkObject | null {\n let val = tryGetValueFromMap(this._defaultGlobalVariables, name, null);\n return val.exists ? val.result : null;\n }\n\n public GlobalVariableExistsWithName(name: string) {\n return (\n this._globalVariables.has(name) ||\n (this._defaultGlobalVariables !== null &&\n this._defaultGlobalVariables.has(name))\n );\n }\n\n public GetRawVariableWithName(name: string | null, contextIndex: number) {\n let varValue: InkObject | null = null;\n\n if (contextIndex == 0 || contextIndex == -1) {\n let variableValue = null;\n if (this.patch !== null) {\n variableValue = this.patch.TryGetGlobal(name, null);\n if (variableValue.exists) return variableValue.result!;\n }\n\n // this is a conditional assignment\n variableValue = tryGetValueFromMap(this._globalVariables, name, null);\n if (variableValue.exists) return variableValue.result;\n\n if (this._defaultGlobalVariables !== null) {\n variableValue = tryGetValueFromMap(\n this._defaultGlobalVariables,\n name,\n null\n );\n if (variableValue.exists) return variableValue.result;\n }\n\n if (this._listDefsOrigin === null)\n return throwNullException(\"VariablesState._listDefsOrigin\");\n let listItemValue = this._listDefsOrigin.FindSingleItemListWithName(name);\n if (listItemValue) return listItemValue;\n }\n\n varValue = this._callStack.GetTemporaryVariableWithName(name, contextIndex);\n\n return varValue;\n }\n\n public ValueAtVariablePointer(pointer: VariablePointerValue) {\n return this.GetVariableWithName(pointer.variableName, pointer.contextIndex);\n }\n\n public Assign(varAss: VariableAssignment, value: InkObject) {\n let name = varAss.variableName;\n if (name === null) {\n return throwNullException(\"name\");\n }\n let contextIndex = -1;\n\n let setGlobal = false;\n if (varAss.isNewDeclaration) {\n setGlobal = varAss.isGlobal;\n } else {\n setGlobal = this.GlobalVariableExistsWithName(name);\n }\n\n if (varAss.isNewDeclaration) {\n // var varPointer = value as VariablePointerValue;\n let varPointer = asOrNull(value, VariablePointerValue);\n if (varPointer !== null) {\n let fullyResolvedVariablePointer =\n this.ResolveVariablePointer(varPointer);\n value = fullyResolvedVariablePointer;\n }\n } else {\n let existingPointer = null;\n do {\n // existingPointer = GetRawVariableWithName (name, contextIndex) as VariablePointerValue;\n existingPointer = asOrNull(\n this.GetRawVariableWithName(name, contextIndex),\n VariablePointerValue\n );\n if (existingPointer != null) {\n name = existingPointer.variableName;\n contextIndex = existingPointer.contextIndex;\n setGlobal = contextIndex == 0;\n }\n } while (existingPointer != null);\n }\n\n if (setGlobal) {\n this.SetGlobal(name, value);\n } else {\n this._callStack.SetTemporaryVariable(\n name,\n value,\n varAss.isNewDeclaration,\n contextIndex\n );\n }\n }\n\n public SnapshotDefaultGlobals() {\n this._defaultGlobalVariables = new Map(this._globalVariables);\n }\n\n public RetainListOriginsForAssignment(\n oldValue: InkObject,\n newValue: InkObject\n ) {\n let oldList = asOrThrows(oldValue, ListValue);\n let newList = asOrThrows(newValue, ListValue);\n\n if (oldList.value && newList.value && newList.value.Count == 0) {\n newList.value.SetInitialOriginNames(oldList.value.originNames);\n }\n }\n\n public SetGlobal(variableName: string | null, value: InkObject) {\n let oldValue = null;\n\n if (this.patch === null) {\n oldValue = tryGetValueFromMap(this._globalVariables, variableName, null);\n }\n\n if (this.patch !== null) {\n oldValue = this.patch.TryGetGlobal(variableName, null);\n if (!oldValue.exists) {\n oldValue = tryGetValueFromMap(\n this._globalVariables,\n variableName,\n null\n );\n }\n }\n\n ListValue.RetainListOriginsForAssignment(oldValue!.result!, value);\n\n if (variableName === null) {\n return throwNullException(\"variableName\");\n }\n\n if (this.patch !== null) {\n this.patch.SetGlobal(variableName, value);\n } else {\n this._globalVariables.set(variableName, value);\n }\n\n // TODO: Not sure !== is equivalent to !value.Equals(oldValue)\n if (\n this.variableChangedEvent !== null &&\n oldValue !== null &&\n value !== oldValue.result\n ) {\n if (this.batchObservingVariableChanges) {\n if (this._changedVariablesForBatchObs === null) {\n return throwNullException(\"this._changedVariablesForBatchObs\");\n }\n\n if (this.patch !== null) {\n this.patch.AddChangedVariable(variableName);\n } else if (this._changedVariablesForBatchObs !== null) {\n this._changedVariablesForBatchObs.add(variableName);\n }\n } else {\n this.variableChangedEvent(variableName, value);\n }\n }\n }\n\n public ResolveVariablePointer(varPointer: VariablePointerValue) {\n let contextIndex = varPointer.contextIndex;\n\n if (contextIndex == -1)\n contextIndex = this.GetContextIndexOfVariableNamed(\n varPointer.variableName\n );\n\n let valueOfVariablePointedTo = this.GetRawVariableWithName(\n varPointer.variableName,\n contextIndex\n );\n\n // var doubleRedirectionPointer = valueOfVariablePointedTo as VariablePointerValue;\n let doubleRedirectionPointer = asOrNull(\n valueOfVariablePointedTo,\n VariablePointerValue\n );\n if (doubleRedirectionPointer != null) {\n return doubleRedirectionPointer;\n } else {\n return new VariablePointerValue(varPointer.variableName, contextIndex);\n }\n }\n\n public GetContextIndexOfVariableNamed(varName: string) {\n if (this.GlobalVariableExistsWithName(varName)) return 0;\n\n return this._callStack.currentElementIndex;\n }\n\n /**\n * This function is specific to the js version of ink. It allows to register a\n * callback that will be called when a variable changes. The original code uses\n * `state.variableChangedEvent += callback` instead.\n *\n * @param {function} callback\n */\n public ObserveVariableChange(\n callback: (variableName: string, newValue: InkObject) => void\n ) {\n this.variableChangedEventCallbacks.push(callback);\n }\n\n private _globalVariables: Map;\n private _defaultGlobalVariables: Map = new Map();\n\n private _callStack: CallStack;\n private _changedVariablesForBatchObs: Set | null = new Set();\n private _listDefsOrigin: ListDefinitionsOrigin | null;\n}\n","// Taken from https://gist.github.com/blixt/f17b47c62508be59987b\n// Ink uses a seedable PRNG of which there is none in native javascript.\nexport class PRNG {\n private seed: number;\n\n constructor(seed: number) {\n this.seed = seed % 2147483647;\n if (this.seed <= 0) this.seed += 2147483646;\n }\n public next(): number {\n return (this.seed = (this.seed * 48271) % 2147483647);\n }\n public nextFloat(): number {\n return (this.next() - 1) / 2147483646;\n }\n}\n","import { InkObject } from \"./Object\";\nimport { Container } from \"./Container\";\n\nexport class StatePatch {\n get globals() {\n return this._globals;\n }\n get changedVariables() {\n return this._changedVariables;\n }\n get visitCounts() {\n return this._visitCounts;\n }\n get turnIndices() {\n return this._turnIndices;\n }\n\n constructor();\n constructor(toCopy: StatePatch | null);\n constructor() {\n if (arguments.length === 1 && arguments[0] !== null) {\n let toCopy = arguments[0] as StatePatch;\n this._globals = new Map(toCopy._globals);\n this._changedVariables = new Set(toCopy._changedVariables);\n this._visitCounts = new Map(toCopy._visitCounts);\n this._turnIndices = new Map(toCopy._turnIndices);\n } else {\n this._globals = new Map();\n this._changedVariables = new Set();\n this._visitCounts = new Map();\n this._turnIndices = new Map();\n }\n }\n\n public TryGetGlobal(name: string | null, /* out */ value: InkObject | null) {\n if (name !== null && this._globals.has(name)) {\n return { result: this._globals.get(name), exists: true };\n }\n\n return { result: value, exists: false };\n }\n\n public SetGlobal(name: string, value: InkObject) {\n this._globals.set(name, value);\n }\n\n public AddChangedVariable(name: string) {\n return this._changedVariables.add(name);\n }\n\n public TryGetVisitCount(container: Container, /* out */ count: number) {\n if (this._visitCounts.has(container)) {\n return { result: this._visitCounts.get(container), exists: true };\n }\n\n return { result: count, exists: false };\n }\n\n public SetVisitCount(container: Container, count: number) {\n this._visitCounts.set(container, count);\n }\n\n public SetTurnIndex(container: Container, index: number) {\n this._turnIndices.set(container, index);\n }\n\n public TryGetTurnIndex(container: Container, /* out */ index: number) {\n if (this._turnIndices.has(container)) {\n return { result: this._turnIndices.get(container), exists: true };\n }\n\n return { result: index, exists: false };\n }\n\n private _globals: Map;\n private _changedVariables: Set = new Set();\n private _visitCounts: Map = new Map();\n private _turnIndices: Map = new Map();\n}\n","export class SimpleJson {\n public static TextToDictionary(text: string) {\n return new SimpleJson.Reader(text).ToDictionary();\n }\n\n public static TextToArray(text: string) {\n return new SimpleJson.Reader(text).ToArray();\n }\n}\n\nexport namespace SimpleJson {\n export class Reader {\n constructor(text: string) {\n this._rootObject = JSON.parse(text);\n }\n\n public ToDictionary() {\n return this._rootObject as Record;\n }\n\n public ToArray() {\n return this._rootObject as any[];\n }\n\n private _rootObject: any[] | Record;\n }\n\n // In C#, this class writes json tokens directly to a StringWriter or\n // another stream. Here, a temporary hierarchy is created in the form\n // of a javascript object, which is serialised in the `toString` method.\n // See individual methods and properties for more information.\n export class Writer {\n public WriteObject(inner: (w: Writer) => void) {\n this.WriteObjectStart();\n inner(this);\n this.WriteObjectEnd();\n }\n\n // Add a new object.\n public WriteObjectStart() {\n this.StartNewObject(true);\n\n let newObject: Record = {};\n\n if (this.state === SimpleJson.Writer.State.Property) {\n // This object is created as the value of a property,\n // inside an other object.\n this.Assert(this.currentCollection !== null);\n this.Assert(this.currentPropertyName !== null);\n\n let propertyName = this._propertyNameStack.pop();\n this.currentCollection![propertyName!] = newObject;\n this._collectionStack.push(newObject);\n } else if (this.state === SimpleJson.Writer.State.Array) {\n // This object is created as the child of an array.\n this.Assert(this.currentCollection !== null);\n\n this.currentCollection!.push(newObject);\n this._collectionStack.push(newObject);\n } else {\n // This object is the root object.\n this.Assert(this.state === SimpleJson.Writer.State.None);\n this._jsonObject = newObject;\n this._collectionStack.push(newObject);\n }\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Object)\n );\n }\n\n public WriteObjectEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.Object);\n this._collectionStack.pop();\n this._stateStack.pop();\n }\n\n // Write a property name / value pair to the current object.\n public WriteProperty(\n name: any,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n innerOrContent: ((w: Writer) => void) | string | boolean | null\n ) {\n this.WritePropertyStart(name);\n if (arguments[1] instanceof Function) {\n let inner = arguments[1];\n inner(this);\n } else {\n let content: string | boolean | null = arguments[1];\n this.Write(content);\n }\n this.WritePropertyEnd();\n }\n\n // Int and Float are separate calls, since there both are\n // numbers in JavaScript, but need to be handled differently.\n\n public WriteIntProperty(name: any, content: number) {\n this.WritePropertyStart(name);\n this.WriteInt(content);\n this.WritePropertyEnd();\n }\n\n public WriteFloatProperty(name: any, content: number) {\n this.WritePropertyStart(name);\n this.WriteFloat(content);\n this.WritePropertyEnd();\n }\n\n // Prepare a new property name, which will be use to add the\n // new object when calling _addToCurrentObject() from a Write\n // method.\n public WritePropertyStart(name: any) {\n this.Assert(this.state === SimpleJson.Writer.State.Object);\n this._propertyNameStack.push(name);\n\n this.IncrementChildCount();\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Property)\n );\n }\n\n public WritePropertyEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.Property);\n this.Assert(this.childCount === 1);\n this._stateStack.pop();\n }\n\n // Prepare a new property name, except this time, the property name\n // will be created by concatenating all the strings passed to\n // WritePropertyNameInner.\n public WritePropertyNameStart() {\n this.Assert(this.state === SimpleJson.Writer.State.Object);\n this.IncrementChildCount();\n\n this._currentPropertyName = \"\";\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Property)\n );\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.PropertyName)\n );\n }\n\n public WritePropertyNameEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.PropertyName);\n this.Assert(this._currentPropertyName !== null);\n this._propertyNameStack.push(this._currentPropertyName!);\n this._currentPropertyName = null;\n this._stateStack.pop();\n }\n\n public WritePropertyNameInner(str: string) {\n this.Assert(this.state === SimpleJson.Writer.State.PropertyName);\n this.Assert(this._currentPropertyName !== null);\n this._currentPropertyName += str;\n }\n\n // Add a new array.\n public WriteArrayStart() {\n this.StartNewObject(true);\n\n let newObject: any[] = [];\n\n if (this.state === SimpleJson.Writer.State.Property) {\n // This array is created as the value of a property,\n // inside an object.\n this.Assert(this.currentCollection !== null);\n this.Assert(this.currentPropertyName !== null);\n\n let propertyName = this._propertyNameStack.pop();\n this.currentCollection![propertyName!] = newObject;\n this._collectionStack.push(newObject);\n } else if (this.state === SimpleJson.Writer.State.Array) {\n // This array is created as the child of another array.\n this.Assert(this.currentCollection !== null);\n\n this.currentCollection!.push(newObject);\n this._collectionStack.push(newObject);\n } else {\n // This array is the root object.\n this.Assert(this.state === SimpleJson.Writer.State.None);\n this._jsonObject = newObject;\n this._collectionStack.push(newObject);\n }\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Array)\n );\n }\n\n public WriteArrayEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.Array);\n this._collectionStack.pop();\n this._stateStack.pop();\n }\n\n // Add the value to the appropriate collection (array / object), given the current\n // context.\n public Write(\n value: number | string | boolean | null,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n escape: boolean = true\n ) {\n if (value === null) {\n console.error(\"Warning: trying to write a null value\");\n return;\n }\n\n this.StartNewObject(false);\n this._addToCurrentObject(value);\n }\n\n public WriteBool(value: boolean | null) {\n if (value === null) {\n return;\n }\n\n this.StartNewObject(false);\n this._addToCurrentObject(value);\n }\n\n public WriteInt(value: number | null) {\n if (value === null) {\n return;\n }\n\n this.StartNewObject(false);\n\n // Math.floor is used as a precaution:\n // 1. to ensure that the value is written as an integer\n // (without a fractional part -> 1 instead of 1.0), even\n // though it should be the default behaviour of\n // JSON.serialize;\n // 2. to ensure that if a floating number is passed\n // accidentally, it's converted to an integer.\n //\n // This guarantees savegame compatibility with the reference\n // implementation.\n this._addToCurrentObject(Math.floor(value));\n }\n\n // Since JSON doesn't support NaN and Infinity, these values\n // are converted here.\n public WriteFloat(value: number | null) {\n if (value === null) {\n return;\n }\n\n this.StartNewObject(false);\n if (value == Number.POSITIVE_INFINITY) {\n this._addToCurrentObject(3.4e38);\n } else if (value == Number.NEGATIVE_INFINITY) {\n this._addToCurrentObject(-3.4e38);\n } else if (isNaN(value)) {\n this._addToCurrentObject(0.0);\n } else {\n this._addToCurrentObject(value);\n }\n }\n\n public WriteNull() {\n this.StartNewObject(false);\n this._addToCurrentObject(null);\n }\n\n // Prepare a string before adding it to the current collection in\n // WriteStringEnd(). The string will be a concatenation of all the\n // strings passed to WriteStringInner.\n public WriteStringStart() {\n this.StartNewObject(false);\n this._currentString = \"\";\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.String)\n );\n }\n\n public WriteStringEnd() {\n this.Assert(this.state == SimpleJson.Writer.State.String);\n this._stateStack.pop();\n this._addToCurrentObject(this._currentString);\n this._currentString = null;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public WriteStringInner(str: string | null, escape: boolean = true) {\n this.Assert(this.state === SimpleJson.Writer.State.String);\n\n if (str === null) {\n console.error(\"Warning: trying to write a null string\");\n return;\n }\n\n this._currentString += str;\n }\n\n // Serialise the root object into a JSON string.\n public toString() {\n if (this._jsonObject === null) {\n return \"\";\n }\n\n return JSON.stringify(this._jsonObject);\n }\n\n // Prepare the state stack when adding new objects / values.\n private StartNewObject(container: boolean) {\n if (container) {\n this.Assert(\n this.state === SimpleJson.Writer.State.None ||\n this.state === SimpleJson.Writer.State.Property ||\n this.state === SimpleJson.Writer.State.Array\n );\n } else {\n this.Assert(\n this.state === SimpleJson.Writer.State.Property ||\n this.state === SimpleJson.Writer.State.Array\n );\n }\n\n if (this.state === SimpleJson.Writer.State.Property) {\n this.Assert(this.childCount === 0);\n }\n\n if (\n this.state === SimpleJson.Writer.State.Array ||\n this.state === SimpleJson.Writer.State.Property\n ) {\n this.IncrementChildCount();\n }\n }\n\n // These getters peek all the different stacks.\n\n private get state() {\n if (this._stateStack.length > 0) {\n return this._stateStack[this._stateStack.length - 1].type;\n } else {\n return SimpleJson.Writer.State.None;\n }\n }\n\n private get childCount() {\n if (this._stateStack.length > 0) {\n return this._stateStack[this._stateStack.length - 1].childCount;\n } else {\n return 0;\n }\n }\n\n private get currentCollection(): Record | null {\n if (this._collectionStack.length > 0) {\n return this._collectionStack[this._collectionStack.length - 1];\n } else {\n return null;\n }\n }\n\n private get currentPropertyName() {\n if (this._propertyNameStack.length > 0) {\n return this._propertyNameStack[this._propertyNameStack.length - 1];\n } else {\n return null;\n }\n }\n\n private IncrementChildCount() {\n this.Assert(this._stateStack.length > 0);\n let currEl = this._stateStack.pop()!;\n currEl.childCount++;\n this._stateStack.push(currEl);\n }\n\n private Assert(condition: boolean) {\n if (!condition) throw Error(\"Assert failed while writing JSON\");\n }\n\n // This method did not exist in the original C# code. It adds\n // the given value to the current collection (used by Write methods).\n private _addToCurrentObject(value: number | string | boolean | null) {\n this.Assert(this.currentCollection !== null);\n if (this.state === SimpleJson.Writer.State.Array) {\n this.Assert(Array.isArray(this.currentCollection));\n (this.currentCollection as any[]).push(value);\n } else if (this.state === SimpleJson.Writer.State.Property) {\n this.Assert(!Array.isArray(this.currentCollection));\n this.Assert(this.currentPropertyName !== null);\n (this.currentCollection as Record)[\n this.currentPropertyName!\n ] = value;\n this._propertyNameStack.pop();\n }\n }\n\n // In addition to `_stateStack` present in the original code,\n // this implementation of SimpleJson use two other stacks and two\n // temporary variables holding the current context.\n\n // Used to keep track of the current property name being built\n // with `WritePropertyNameStart`, `WritePropertyNameInner` and\n // `WritePropertyNameEnd`.\n private _currentPropertyName: string | null = null;\n\n // Used to keep track of the current string value being built\n // with `WriteStringStart`, `WriteStringInner` and\n // `WriteStringEnd`.\n private _currentString: string | null = null;\n\n private _stateStack: SimpleJson.Writer.StateElement[] = [];\n\n // Keep track of the current collection being built (either an array\n // or an object). For instance, at the '?' step during the hiarchy\n // creation, this hierarchy:\n // [3, {a: [b, ?]}] will have this corresponding stack:\n // (bottom) [Array, Object, Array] (top)\n private _collectionStack: Array> = [];\n\n // Keep track of the current property being assigned. For instance, at\n // the '?' step during the hiarchy creation, this hierarchy:\n // [3, {a: [b, {c: ?}]}] will have this corresponding stack:\n // (bottom) [a, c] (top)\n private _propertyNameStack: string[] = [];\n\n // Object containing the entire hiearchy.\n private _jsonObject: Record | any[] | null = null;\n }\n\n export namespace Writer {\n export enum State {\n None,\n Object,\n Array,\n Property,\n PropertyName,\n String,\n }\n\n export class StateElement {\n public type: SimpleJson.Writer.State = SimpleJson.Writer.State.None;\n public childCount: number = 0;\n\n constructor(type: SimpleJson.Writer.State) {\n this.type = type;\n }\n }\n }\n}\n","import { CallStack } from \"./CallStack\";\nimport { Choice } from \"./Choice\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { InkObject } from \"./Object\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { Story } from \"./Story\";\nimport { throwNullException } from \"./NullException\";\n\nexport class Flow {\n public name: string;\n public callStack: CallStack;\n public outputStream: InkObject[];\n public currentChoices: Choice[];\n\n constructor(name: String, story: Story);\n constructor(name: String, story: Story, jObject: Record);\n constructor() {\n let name = arguments[0] as string;\n let story = arguments[1] as Story;\n\n this.name = name;\n this.callStack = new CallStack(story);\n\n if (arguments[2]) {\n let jObject = arguments[2] as Record;\n\n this.callStack.SetJsonToken(jObject[\"callstack\"], story);\n this.outputStream = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"outputStream\"]\n );\n this.currentChoices = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"currentChoices\"]\n ) as Choice[];\n\n let jChoiceThreadsObj = jObject[\"choiceThreads\"];\n if (typeof jChoiceThreadsObj !== \"undefined\") {\n this.LoadFlowChoiceThreads(jChoiceThreadsObj, story);\n }\n } else {\n this.outputStream = [];\n this.currentChoices = [];\n }\n }\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n\n writer.WriteProperty(\"callstack\", (w) => this.callStack.WriteJson(w));\n writer.WriteProperty(\"outputStream\", (w) =>\n JsonSerialisation.WriteListRuntimeObjs(w, this.outputStream)\n );\n\n let hasChoiceThreads = false;\n for (let c of this.currentChoices) {\n if (c.threadAtGeneration === null)\n return throwNullException(\"c.threadAtGeneration\");\n\n c.originalThreadIndex = c.threadAtGeneration.threadIndex;\n\n if (this.callStack.ThreadWithIndex(c.originalThreadIndex) === null) {\n if (!hasChoiceThreads) {\n hasChoiceThreads = true;\n writer.WritePropertyStart(\"choiceThreads\");\n writer.WriteObjectStart();\n }\n\n writer.WritePropertyStart(c.originalThreadIndex);\n c.threadAtGeneration.WriteJson(writer);\n writer.WritePropertyEnd();\n }\n }\n\n if (hasChoiceThreads) {\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteProperty(\"currentChoices\", (w) => {\n w.WriteArrayStart();\n for (let c of this.currentChoices) {\n JsonSerialisation.WriteChoice(w, c);\n }\n w.WriteArrayEnd();\n });\n\n writer.WriteObjectEnd();\n }\n\n public LoadFlowChoiceThreads(\n jChoiceThreads: Record,\n story: Story\n ) {\n for (let choice of this.currentChoices) {\n let foundActiveThread = this.callStack.ThreadWithIndex(\n choice.originalThreadIndex\n );\n if (foundActiveThread !== null) {\n choice.threadAtGeneration = foundActiveThread.Copy();\n } else {\n let jSavedChoiceThread =\n jChoiceThreads[`${choice.originalThreadIndex}`];\n choice.threadAtGeneration = new CallStack.Thread(\n jSavedChoiceThread,\n story\n );\n }\n }\n }\n}\n","import { CallStack } from \"./CallStack\";\nimport { VariablesState } from \"./VariablesState\";\nimport { ValueType, Value, StringValue, ListValue } from \"./Value\";\nimport { PushPopType } from \"./PushPop\";\nimport { Tag } from \"./Tag\";\nimport { Glue } from \"./Glue\";\nimport { Path } from \"./Path\";\nimport { ControlCommand } from \"./ControlCommand\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { PRNG } from \"./PRNG\";\nimport { Void } from \"./Void\";\nimport { Pointer } from \"./Pointer\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { Choice } from \"./Choice\";\nimport { asOrNull, asOrThrows, nullIfUndefined } from \"./TypeAssertion\";\nimport { Debug } from \"./Debug\";\nimport { Container } from \"./Container\";\nimport { InkObject } from \"./Object\";\nimport { throwNullException } from \"./NullException\";\nimport { Story } from \"./Story\";\nimport { StatePatch } from \"./StatePatch\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { Flow } from \"./Flow\";\nimport { InkList } from \"./InkList\";\n\nexport class StoryState {\n // Backward compatible changes since v8:\n // v10: dynamic tags\n // v9: multi-flows\n public readonly kInkSaveStateVersion = 10;\n public readonly kMinCompatibleLoadVersion = 8;\n\n public onDidLoadState: (() => void) | null = null;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public ToJson(indented: boolean = false) {\n let writer = new SimpleJson.Writer();\n this.WriteJson(writer);\n return writer.toString();\n }\n public toJson(indented: boolean = false) {\n return this.ToJson(indented);\n }\n\n public LoadJson(json: string) {\n let jObject = SimpleJson.TextToDictionary(json);\n this.LoadJsonObj(jObject);\n if (this.onDidLoadState !== null) this.onDidLoadState();\n }\n\n public VisitCountAtPathString(pathString: string) {\n let visitCountOut;\n\n if (this._patch !== null) {\n let container = this.story.ContentAtPath(new Path(pathString)).container;\n if (container === null)\n throw new Error(\"Content at path not found: \" + pathString);\n\n visitCountOut = this._patch.TryGetVisitCount(container, 0);\n if (visitCountOut.exists) return visitCountOut.result;\n }\n\n visitCountOut = tryGetValueFromMap(this._visitCounts, pathString, null);\n if (visitCountOut.exists) return visitCountOut.result;\n\n return 0;\n }\n\n public VisitCountForContainer(container: Container | null): number {\n if (container === null) {\n return throwNullException(\"container\");\n }\n if (!container.visitsShouldBeCounted) {\n this.story.Error(\n \"Read count for target (\" +\n container.name +\n \" - on \" +\n container.debugMetadata +\n \") unknown. The story may need to be compiled with countAllVisits flag (-c).\"\n );\n return 0;\n }\n\n if (this._patch !== null) {\n let count = this._patch.TryGetVisitCount(container, 0);\n if (count.exists) {\n return count.result!;\n }\n }\n\n let containerPathStr = container.path.toString();\n let count2 = tryGetValueFromMap(this._visitCounts, containerPathStr, null);\n if (count2.exists) {\n return count2.result!;\n }\n\n return 0;\n }\n\n public IncrementVisitCountForContainer(container: Container) {\n if (this._patch !== null) {\n let currCount = this.VisitCountForContainer(container);\n currCount++;\n this._patch.SetVisitCount(container, currCount);\n return;\n }\n\n let containerPathStr = container.path.toString();\n let count = tryGetValueFromMap(this._visitCounts, containerPathStr, null);\n if (count.exists) {\n this._visitCounts.set(containerPathStr, count.result! + 1);\n } else {\n this._visitCounts.set(containerPathStr, 1);\n }\n }\n\n public RecordTurnIndexVisitToContainer(container: Container) {\n if (this._patch !== null) {\n this._patch.SetTurnIndex(container, this.currentTurnIndex);\n return;\n }\n\n let containerPathStr = container.path.toString();\n this._turnIndices.set(containerPathStr, this.currentTurnIndex);\n }\n\n public TurnsSinceForContainer(container: Container) {\n if (!container.turnIndexShouldBeCounted) {\n this.story.Error(\n \"TURNS_SINCE() for target (\" +\n container.name +\n \" - on \" +\n container.debugMetadata +\n \") unknown. The story may need to be compiled with countAllVisits flag (-c).\"\n );\n }\n\n if (this._patch !== null) {\n let index = this._patch.TryGetTurnIndex(container, 0);\n if (index.exists) {\n return this.currentTurnIndex - index.result!;\n }\n }\n\n let containerPathStr = container.path.toString();\n let index2 = tryGetValueFromMap(this._turnIndices, containerPathStr, 0);\n if (index2.exists) {\n return this.currentTurnIndex - index2.result!;\n } else {\n return -1;\n }\n }\n\n get callstackDepth() {\n return this.callStack.depth;\n }\n\n get outputStream() {\n return this._currentFlow.outputStream;\n }\n\n get currentChoices() {\n // If we can continue generating text content rather than choices,\n // then we reflect the choice list as being empty, since choices\n // should always come at the end.\n if (this.canContinue) return [];\n return this._currentFlow.currentChoices;\n }\n\n get generatedChoices() {\n return this._currentFlow.currentChoices;\n }\n\n get currentErrors() {\n return this._currentErrors;\n }\n private _currentErrors: string[] | null = null;\n\n get currentWarnings() {\n return this._currentWarnings;\n }\n private _currentWarnings: string[] | null = null;\n\n get variablesState() {\n return this._variablesState;\n }\n set variablesState(value) {\n this._variablesState = value;\n }\n private _variablesState: VariablesState;\n\n get callStack() {\n return this._currentFlow.callStack;\n }\n\n get evaluationStack() {\n return this._evaluationStack;\n }\n private _evaluationStack: InkObject[];\n\n public divertedPointer: Pointer = Pointer.Null;\n\n get currentTurnIndex() {\n return this._currentTurnIndex;\n }\n set currentTurnIndex(value) {\n this._currentTurnIndex = value;\n }\n private _currentTurnIndex: number = 0;\n\n public storySeed: number = 0;\n public previousRandom: number = 0;\n public didSafeExit: boolean = false;\n\n public story: Story;\n\n get currentPathString() {\n let pointer = this.currentPointer;\n if (pointer.isNull) {\n return null;\n } else {\n if (pointer.path === null) {\n return throwNullException(\"pointer.path\");\n }\n return pointer.path.toString();\n }\n }\n\n get currentPointer() {\n return this.callStack.currentElement.currentPointer.copy();\n }\n\n set currentPointer(value) {\n this.callStack.currentElement.currentPointer = value.copy();\n }\n\n get previousPointer() {\n return this.callStack.currentThread.previousPointer.copy();\n }\n\n set previousPointer(value) {\n this.callStack.currentThread.previousPointer = value.copy();\n }\n\n get canContinue() {\n return !this.currentPointer.isNull && !this.hasError;\n }\n\n get hasError() {\n return this.currentErrors != null && this.currentErrors.length > 0;\n }\n\n get hasWarning() {\n return this.currentWarnings != null && this.currentWarnings.length > 0;\n }\n\n get currentText() {\n if (this._outputStreamTextDirty) {\n let sb = new StringBuilder();\n\n let inTag: boolean = false;\n\n for (let outputObj of this.outputStream) {\n // var textContent = outputObj as StringValue;\n let textContent = asOrNull(outputObj, StringValue);\n if (!inTag && textContent !== null) {\n sb.Append(textContent.value);\n } else {\n let controlCommand = asOrNull(outputObj, ControlCommand);\n if (controlCommand !== null) {\n if (\n controlCommand.commandType == ControlCommand.CommandType.BeginTag\n ) {\n inTag = true;\n } else if (\n controlCommand.commandType == ControlCommand.CommandType.EndTag\n ) {\n inTag = false;\n }\n }\n }\n }\n\n this._currentText = this.CleanOutputWhitespace(sb.toString());\n this._outputStreamTextDirty = false;\n }\n\n return this._currentText;\n }\n private _currentText: string | null = null;\n\n public CleanOutputWhitespace(str: string) {\n let sb = new StringBuilder();\n\n let currentWhitespaceStart = -1;\n let startOfLine = 0;\n\n for (let i = 0; i < str.length; i++) {\n let c = str.charAt(i);\n\n let isInlineWhitespace = c == \" \" || c == \"\\t\";\n\n if (isInlineWhitespace && currentWhitespaceStart == -1)\n currentWhitespaceStart = i;\n\n if (!isInlineWhitespace) {\n if (\n c != \"\\n\" &&\n currentWhitespaceStart > 0 &&\n currentWhitespaceStart != startOfLine\n ) {\n sb.Append(\" \");\n }\n currentWhitespaceStart = -1;\n }\n\n if (c == \"\\n\") startOfLine = i + 1;\n\n if (!isInlineWhitespace) sb.Append(c);\n }\n\n return sb.toString();\n }\n\n get currentTags() {\n if (this._outputStreamTagsDirty) {\n this._currentTags = [];\n let inTag: boolean = false;\n let sb = new StringBuilder();\n\n for (let outputObj of this.outputStream) {\n let controlCommand = asOrNull(outputObj, ControlCommand);\n if (controlCommand != null) {\n if (\n controlCommand.commandType == ControlCommand.CommandType.BeginTag\n ) {\n if (inTag && sb.Length > 0) {\n let txt = this.CleanOutputWhitespace(sb.toString());\n this._currentTags.push(txt);\n sb.Clear();\n }\n inTag = true;\n } else if (\n controlCommand.commandType == ControlCommand.CommandType.EndTag\n ) {\n if (sb.Length > 0) {\n let txt = this.CleanOutputWhitespace(sb.toString());\n this._currentTags.push(txt);\n sb.Clear();\n }\n inTag = false;\n }\n } else if (inTag) {\n let strVal = asOrNull(outputObj, StringValue);\n if (strVal !== null) {\n sb.Append(strVal.value);\n }\n } else {\n let tag = asOrNull(outputObj, Tag);\n if (tag != null && tag.text != null && tag.text.length > 0) {\n this._currentTags.push(tag.text); // tag.text has whitespae already cleaned\n }\n }\n }\n\n if (sb.Length > 0) {\n let txt = this.CleanOutputWhitespace(sb.toString());\n this._currentTags.push(txt);\n sb.Clear();\n }\n\n this._outputStreamTagsDirty = false;\n }\n\n return this._currentTags;\n }\n private _currentTags: string[] | null = null;\n\n get currentFlowName() {\n return this._currentFlow.name;\n }\n\n get currentFlowIsDefaultFlow() {\n return this._currentFlow.name == this.kDefaultFlowName;\n }\n\n get aliveFlowNames() {\n if (this._aliveFlowNamesDirty) {\n this._aliveFlowNames = [];\n\n if (this._namedFlows != null) {\n for (let flowName of this._namedFlows.keys()) {\n if (flowName != this.kDefaultFlowName) {\n this._aliveFlowNames.push(flowName);\n }\n }\n }\n\n this._aliveFlowNamesDirty = false;\n }\n\n return this._aliveFlowNames;\n }\n\n get inExpressionEvaluation() {\n return this.callStack.currentElement.inExpressionEvaluation;\n }\n set inExpressionEvaluation(value) {\n this.callStack.currentElement.inExpressionEvaluation = value;\n }\n\n constructor(story: Story) {\n this.story = story;\n\n this._currentFlow = new Flow(this.kDefaultFlowName, story);\n this.OutputStreamDirty();\n\n this._aliveFlowNamesDirty = true;\n this._evaluationStack = [];\n\n this._variablesState = new VariablesState(\n this.callStack,\n story.listDefinitions\n );\n\n this._visitCounts = new Map();\n this._turnIndices = new Map();\n this.currentTurnIndex = -1;\n\n let timeSeed = new Date().getTime();\n this.storySeed = new PRNG(timeSeed).next() % 100;\n this.previousRandom = 0;\n\n this.GoToStart();\n }\n\n public GoToStart() {\n this.callStack.currentElement.currentPointer = Pointer.StartOf(\n this.story.mainContentContainer\n );\n }\n\n public SwitchFlow_Internal(flowName: string | null) {\n if (flowName === null)\n throw new Error(\"Must pass a non-null string to Story.SwitchFlow\");\n\n if (this._namedFlows === null) {\n this._namedFlows = new Map();\n this._namedFlows.set(this.kDefaultFlowName, this._currentFlow);\n }\n\n if (flowName === this._currentFlow.name) {\n return;\n }\n\n let flow: Flow;\n let content = tryGetValueFromMap(this._namedFlows, flowName, null);\n if (content.exists) {\n flow = content.result!;\n } else {\n flow = new Flow(flowName, this.story);\n this._namedFlows.set(flowName, flow);\n this._aliveFlowNamesDirty = true;\n }\n\n this._currentFlow = flow;\n this.variablesState.callStack = this._currentFlow.callStack;\n\n this.OutputStreamDirty();\n }\n\n public SwitchToDefaultFlow_Internal() {\n if (this._namedFlows === null) return;\n this.SwitchFlow_Internal(this.kDefaultFlowName);\n }\n\n public RemoveFlow_Internal(flowName: string | null) {\n if (flowName === null)\n throw new Error(\"Must pass a non-null string to Story.DestroyFlow\");\n if (flowName === this.kDefaultFlowName)\n throw new Error(\"Cannot destroy default flow\");\n\n if (this._currentFlow.name === flowName) {\n this.SwitchToDefaultFlow_Internal();\n }\n\n if (this._namedFlows === null)\n return throwNullException(\"this._namedFlows\");\n this._namedFlows.delete(flowName);\n this._aliveFlowNamesDirty = true;\n }\n\n public CopyAndStartPatching() {\n let copy = new StoryState(this.story);\n\n copy._patch = new StatePatch(this._patch);\n\n copy._currentFlow.name = this._currentFlow.name;\n copy._currentFlow.callStack = new CallStack(this._currentFlow.callStack);\n copy._currentFlow.currentChoices.push(...this._currentFlow.currentChoices);\n copy._currentFlow.outputStream.push(...this._currentFlow.outputStream);\n copy.OutputStreamDirty();\n\n if (this._namedFlows !== null) {\n copy._namedFlows = new Map();\n for (let [namedFlowKey, namedFlowValue] of this._namedFlows) {\n copy._namedFlows.set(namedFlowKey, namedFlowValue);\n copy._aliveFlowNamesDirty = true;\n }\n copy._namedFlows.set(this._currentFlow.name, copy._currentFlow);\n }\n\n if (this.hasError) {\n copy._currentErrors = [];\n copy._currentErrors.push(...(this.currentErrors || []));\n }\n\n if (this.hasWarning) {\n copy._currentWarnings = [];\n copy._currentWarnings.push(...(this.currentWarnings || []));\n }\n\n copy.variablesState = this.variablesState;\n copy.variablesState.callStack = copy.callStack;\n copy.variablesState.patch = copy._patch;\n\n copy.evaluationStack.push(...this.evaluationStack);\n\n if (!this.divertedPointer.isNull)\n copy.divertedPointer = this.divertedPointer.copy();\n\n copy.previousPointer = this.previousPointer.copy();\n\n copy._visitCounts = this._visitCounts;\n copy._turnIndices = this._turnIndices;\n\n copy.currentTurnIndex = this.currentTurnIndex;\n copy.storySeed = this.storySeed;\n copy.previousRandom = this.previousRandom;\n\n copy.didSafeExit = this.didSafeExit;\n\n return copy;\n }\n\n public RestoreAfterPatch() {\n this.variablesState.callStack = this.callStack;\n this.variablesState.patch = this._patch;\n }\n\n public ApplyAnyPatch() {\n if (this._patch === null) return;\n\n this.variablesState.ApplyPatch();\n\n for (let [key, value] of this._patch.visitCounts)\n this.ApplyCountChanges(key, value, true);\n\n for (let [key, value] of this._patch.turnIndices)\n this.ApplyCountChanges(key, value, false);\n\n this._patch = null;\n }\n\n public ApplyCountChanges(\n container: Container,\n newCount: number,\n isVisit: boolean\n ) {\n let counts = isVisit ? this._visitCounts : this._turnIndices;\n counts.set(container.path.toString(), newCount);\n }\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n\n writer.WritePropertyStart(\"flows\");\n writer.WriteObjectStart();\n\n // NOTE: Never pass `WriteJson` directly as an argument to `WriteProperty`.\n // Call it inside a function to make sure `this` is correctly bound\n // and passed down the call hierarchy.\n\n if (this._namedFlows !== null) {\n for (let [namedFlowKey, namedFlowValue] of this._namedFlows) {\n writer.WriteProperty(namedFlowKey, (w) => namedFlowValue.WriteJson(w));\n }\n } else {\n writer.WriteProperty(this._currentFlow.name, (w) =>\n this._currentFlow.WriteJson(w)\n );\n }\n\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n\n writer.WriteProperty(\"currentFlowName\", this._currentFlow.name);\n\n writer.WriteProperty(\"variablesState\", (w) =>\n this.variablesState.WriteJson(w)\n );\n\n writer.WriteProperty(\"evalStack\", (w) =>\n JsonSerialisation.WriteListRuntimeObjs(w, this.evaluationStack)\n );\n\n if (!this.divertedPointer.isNull) {\n if (this.divertedPointer.path === null) {\n return throwNullException(\"divertedPointer\");\n }\n writer.WriteProperty(\n \"currentDivertTarget\",\n this.divertedPointer.path.componentsString\n );\n }\n\n writer.WriteProperty(\"visitCounts\", (w) =>\n JsonSerialisation.WriteIntDictionary(w, this._visitCounts)\n );\n writer.WriteProperty(\"turnIndices\", (w) =>\n JsonSerialisation.WriteIntDictionary(w, this._turnIndices)\n );\n\n writer.WriteIntProperty(\"turnIdx\", this.currentTurnIndex);\n writer.WriteIntProperty(\"storySeed\", this.storySeed);\n writer.WriteIntProperty(\"previousRandom\", this.previousRandom);\n\n writer.WriteIntProperty(\"inkSaveVersion\", this.kInkSaveStateVersion);\n\n writer.WriteIntProperty(\"inkFormatVersion\", Story.inkVersionCurrent);\n\n writer.WriteObjectEnd();\n }\n\n public LoadJsonObj(value: Record) {\n let jObject = value;\n\n let jSaveVersion = jObject[\"inkSaveVersion\"];\n if (jSaveVersion == null) {\n throw new Error(\"ink save format incorrect, can't load.\");\n } else if (parseInt(jSaveVersion) < this.kMinCompatibleLoadVersion) {\n throw new Error(\n \"Ink save format isn't compatible with the current version (saw '\" +\n jSaveVersion +\n \"', but minimum is \" +\n this.kMinCompatibleLoadVersion +\n \"), so can't load.\"\n );\n }\n\n let flowsObj = jObject[\"flows\"];\n if (flowsObj != null) {\n let flowsObjDict = flowsObj as Record;\n\n // Single default flow\n if (Object.keys(flowsObjDict).length === 1) {\n this._namedFlows = null;\n } else if (this._namedFlows === null) {\n this._namedFlows = new Map();\n } else {\n this._namedFlows.clear();\n }\n\n let flowsObjDictEntries = Object.entries(flowsObjDict);\n for (let [namedFlowObjKey, namedFlowObjValue] of flowsObjDictEntries) {\n let name = namedFlowObjKey;\n let flowObj = namedFlowObjValue as Record;\n\n let flow = new Flow(name, this.story, flowObj);\n\n if (Object.keys(flowsObjDict).length === 1) {\n this._currentFlow = new Flow(name, this.story, flowObj);\n } else {\n if (this._namedFlows === null)\n return throwNullException(\"this._namedFlows\");\n this._namedFlows.set(name, flow);\n }\n }\n\n if (this._namedFlows != null && this._namedFlows.size > 1) {\n let currFlowName = jObject[\"currentFlowName\"] as string;\n // Adding a bang at the end, because we're trusting the save, as\n // done in upstream. If the save is corrupted, the execution\n // is undefined.\n this._currentFlow = this._namedFlows.get(currFlowName)!;\n }\n } else {\n this._namedFlows = null;\n this._currentFlow.name = this.kDefaultFlowName;\n this._currentFlow.callStack.SetJsonToken(\n jObject[\"callstackThreads\"] as Record,\n this.story\n );\n this._currentFlow.outputStream = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"outputStream\"] as any[]\n );\n this._currentFlow.currentChoices =\n JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"currentChoices\"] as any[]\n ) as Choice[];\n\n let jChoiceThreadsObj = jObject[\"choiceThreads\"];\n this._currentFlow.LoadFlowChoiceThreads(jChoiceThreadsObj, this.story);\n }\n\n this.OutputStreamDirty();\n this._aliveFlowNamesDirty = true;\n\n this.variablesState.SetJsonToken(jObject[\"variablesState\"]);\n this.variablesState.callStack = this._currentFlow.callStack;\n\n this._evaluationStack = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"evalStack\"]\n );\n\n let currentDivertTargetPath = jObject[\"currentDivertTarget\"];\n if (currentDivertTargetPath != null) {\n let divertPath = new Path(currentDivertTargetPath.toString());\n this.divertedPointer = this.story.PointerAtPath(divertPath);\n }\n\n this._visitCounts = JsonSerialisation.JObjectToIntDictionary(\n jObject[\"visitCounts\"]\n );\n this._turnIndices = JsonSerialisation.JObjectToIntDictionary(\n jObject[\"turnIndices\"]\n );\n this.currentTurnIndex = parseInt(jObject[\"turnIdx\"]);\n this.storySeed = parseInt(jObject[\"storySeed\"]);\n this.previousRandom = parseInt(jObject[\"previousRandom\"]);\n }\n\n public ResetErrors() {\n this._currentErrors = null;\n this._currentWarnings = null;\n }\n public ResetOutput(objs: InkObject[] | null = null) {\n this.outputStream.length = 0;\n if (objs !== null) this.outputStream.push(...objs);\n this.OutputStreamDirty();\n }\n\n public PushToOutputStream(obj: InkObject | null) {\n // var text = obj as StringValue;\n let text = asOrNull(obj, StringValue);\n if (text !== null) {\n let listText = this.TrySplittingHeadTailWhitespace(text);\n if (listText !== null) {\n for (let textObj of listText) {\n this.PushToOutputStreamIndividual(textObj);\n }\n this.OutputStreamDirty();\n return;\n }\n }\n\n this.PushToOutputStreamIndividual(obj);\n this.OutputStreamDirty();\n }\n\n public PopFromOutputStream(count: number) {\n this.outputStream.splice(this.outputStream.length - count, count);\n this.OutputStreamDirty();\n }\n\n public TrySplittingHeadTailWhitespace(single: StringValue) {\n let str = single.value;\n if (str === null) {\n return throwNullException(\"single.value\");\n }\n\n let headFirstNewlineIdx = -1;\n let headLastNewlineIdx = -1;\n for (let i = 0; i < str.length; i++) {\n let c = str[i];\n if (c == \"\\n\") {\n if (headFirstNewlineIdx == -1) headFirstNewlineIdx = i;\n headLastNewlineIdx = i;\n } else if (c == \" \" || c == \"\\t\") continue;\n else break;\n }\n\n let tailLastNewlineIdx = -1;\n let tailFirstNewlineIdx = -1;\n for (let i = str.length - 1; i >= 0; i--) {\n let c = str[i];\n if (c == \"\\n\") {\n if (tailLastNewlineIdx == -1) tailLastNewlineIdx = i;\n tailFirstNewlineIdx = i;\n } else if (c == \" \" || c == \"\\t\") continue;\n else break;\n }\n\n // No splitting to be done?\n if (headFirstNewlineIdx == -1 && tailLastNewlineIdx == -1) return null;\n\n let listTexts: StringValue[] = [];\n let innerStrStart = 0;\n let innerStrEnd = str.length;\n\n if (headFirstNewlineIdx != -1) {\n if (headFirstNewlineIdx > 0) {\n let leadingSpaces = new StringValue(\n str.substring(0, headFirstNewlineIdx)\n );\n listTexts.push(leadingSpaces);\n }\n listTexts.push(new StringValue(\"\\n\"));\n innerStrStart = headLastNewlineIdx + 1;\n }\n\n if (tailLastNewlineIdx != -1) {\n innerStrEnd = tailFirstNewlineIdx;\n }\n\n if (innerStrEnd > innerStrStart) {\n let innerStrText = str.substring(innerStrStart, innerStrEnd);\n listTexts.push(new StringValue(innerStrText));\n }\n\n if (tailLastNewlineIdx != -1 && tailFirstNewlineIdx > headLastNewlineIdx) {\n listTexts.push(new StringValue(\"\\n\"));\n if (tailLastNewlineIdx < str.length - 1) {\n let numSpaces = str.length - tailLastNewlineIdx - 1;\n let trailingSpaces = new StringValue(\n str.substring(\n tailLastNewlineIdx + 1,\n tailLastNewlineIdx + 1 + numSpaces\n )\n );\n listTexts.push(trailingSpaces);\n }\n }\n\n return listTexts;\n }\n\n public PushToOutputStreamIndividual(obj: InkObject | null) {\n let glue = asOrNull(obj, Glue);\n let text = asOrNull(obj, StringValue);\n\n let includeInOutput = true;\n\n if (glue) {\n this.TrimNewlinesFromOutputStream();\n includeInOutput = true;\n } else if (text) {\n let functionTrimIndex = -1;\n let currEl = this.callStack.currentElement;\n if (currEl.type == PushPopType.Function) {\n functionTrimIndex = currEl.functionStartInOutputStream;\n }\n\n let glueTrimIndex = -1;\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let o = this.outputStream[i];\n let c = o instanceof ControlCommand ? o : null;\n let g = o instanceof Glue ? o : null;\n\n if (g != null) {\n glueTrimIndex = i;\n break;\n } else if (\n c != null &&\n c.commandType == ControlCommand.CommandType.BeginString\n ) {\n if (i >= functionTrimIndex) {\n functionTrimIndex = -1;\n }\n break;\n }\n }\n\n let trimIndex = -1;\n if (glueTrimIndex != -1 && functionTrimIndex != -1)\n trimIndex = Math.min(functionTrimIndex, glueTrimIndex);\n else if (glueTrimIndex != -1) trimIndex = glueTrimIndex;\n else trimIndex = functionTrimIndex;\n\n if (trimIndex != -1) {\n if (text.isNewline) {\n includeInOutput = false;\n } else if (text.isNonWhitespace) {\n if (glueTrimIndex > -1) this.RemoveExistingGlue();\n\n if (functionTrimIndex > -1) {\n let callStackElements = this.callStack.elements;\n for (let i = callStackElements.length - 1; i >= 0; i--) {\n let el = callStackElements[i];\n if (el.type == PushPopType.Function) {\n el.functionStartInOutputStream = -1;\n } else {\n break;\n }\n }\n }\n }\n } else if (text.isNewline) {\n if (this.outputStreamEndsInNewline || !this.outputStreamContainsContent)\n includeInOutput = false;\n }\n }\n\n if (includeInOutput) {\n if (obj === null) {\n return throwNullException(\"obj\");\n }\n this.outputStream.push(obj);\n this.OutputStreamDirty();\n }\n }\n\n public TrimNewlinesFromOutputStream() {\n let removeWhitespaceFrom = -1;\n\n let i = this.outputStream.length - 1;\n while (i >= 0) {\n let obj = this.outputStream[i];\n let cmd = asOrNull(obj, ControlCommand);\n let txt = asOrNull(obj, StringValue);\n\n if (cmd != null || (txt != null && txt.isNonWhitespace)) {\n break;\n } else if (txt != null && txt.isNewline) {\n removeWhitespaceFrom = i;\n }\n i--;\n }\n\n // Remove the whitespace\n if (removeWhitespaceFrom >= 0) {\n i = removeWhitespaceFrom;\n while (i < this.outputStream.length) {\n let text = asOrNull(this.outputStream[i], StringValue);\n if (text) {\n this.outputStream.splice(i, 1);\n } else {\n i++;\n }\n }\n }\n\n this.OutputStreamDirty();\n }\n\n public RemoveExistingGlue() {\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let c = this.outputStream[i];\n if (c instanceof Glue) {\n this.outputStream.splice(i, 1);\n } else if (c instanceof ControlCommand) {\n break;\n }\n }\n\n this.OutputStreamDirty();\n }\n\n get outputStreamEndsInNewline() {\n if (this.outputStream.length > 0) {\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let obj = this.outputStream[i];\n if (obj instanceof ControlCommand) break;\n let text = this.outputStream[i];\n if (text instanceof StringValue) {\n if (text.isNewline) return true;\n else if (text.isNonWhitespace) break;\n }\n }\n }\n\n return false;\n }\n\n get outputStreamContainsContent() {\n for (let content of this.outputStream) {\n if (content instanceof StringValue) return true;\n }\n return false;\n }\n\n get inStringEvaluation() {\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let cmd = asOrNull(this.outputStream[i], ControlCommand);\n if (\n cmd instanceof ControlCommand &&\n cmd.commandType == ControlCommand.CommandType.BeginString\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n public PushEvaluationStack(obj: InkObject | null) {\n // var listValue = obj as ListValue;\n let listValue = asOrNull(obj, ListValue);\n if (listValue) {\n // Update origin when list is has something to indicate the list origin\n let rawList = listValue.value;\n if (rawList === null) {\n return throwNullException(\"rawList\");\n }\n\n if (rawList.originNames != null) {\n if (!rawList.origins) rawList.origins = [];\n rawList.origins.length = 0;\n\n for (let n of rawList.originNames) {\n if (this.story.listDefinitions === null)\n return throwNullException(\"StoryState.story.listDefinitions\");\n let def = this.story.listDefinitions.TryListGetDefinition(n, null);\n if (def.result === null)\n return throwNullException(\"StoryState def.result\");\n if (rawList.origins.indexOf(def.result) < 0)\n rawList.origins.push(def.result);\n }\n }\n }\n\n if (obj === null) {\n return throwNullException(\"obj\");\n }\n this.evaluationStack.push(obj);\n }\n\n public PopEvaluationStack(): InkObject;\n public PopEvaluationStack(numberOfObjects: number): InkObject[];\n public PopEvaluationStack(numberOfObjects?: number) {\n if (typeof numberOfObjects === \"undefined\") {\n let obj = this.evaluationStack.pop();\n return nullIfUndefined(obj);\n } else {\n if (numberOfObjects > this.evaluationStack.length) {\n throw new Error(\"trying to pop too many objects\");\n }\n\n let popped = this.evaluationStack.splice(\n this.evaluationStack.length - numberOfObjects,\n numberOfObjects\n );\n return nullIfUndefined(popped);\n }\n }\n\n public PeekEvaluationStack() {\n return this.evaluationStack[this.evaluationStack.length - 1];\n }\n\n public ForceEnd() {\n this.callStack.Reset();\n\n this._currentFlow.currentChoices.length = 0;\n\n this.currentPointer = Pointer.Null;\n this.previousPointer = Pointer.Null;\n\n this.didSafeExit = true;\n }\n\n public TrimWhitespaceFromFunctionEnd() {\n Debug.Assert(this.callStack.currentElement.type == PushPopType.Function);\n let functionStartPoint =\n this.callStack.currentElement.functionStartInOutputStream;\n\n if (functionStartPoint == -1) {\n functionStartPoint = 0;\n }\n\n for (let i = this.outputStream.length - 1; i >= functionStartPoint; i--) {\n let obj = this.outputStream[i];\n let txt = asOrNull(obj, StringValue);\n let cmd = asOrNull(obj, ControlCommand);\n\n if (txt == null) continue;\n if (cmd) break;\n\n if (txt.isNewline || txt.isInlineWhitespace) {\n this.outputStream.splice(i, 1);\n this.OutputStreamDirty();\n } else {\n break;\n }\n }\n }\n\n public PopCallStack(popType: PushPopType | null = null) {\n if (this.callStack.currentElement.type == PushPopType.Function)\n this.TrimWhitespaceFromFunctionEnd();\n\n this.callStack.Pop(popType);\n }\n\n public SetChosenPath(path: Path, incrementingTurnIndex: boolean) {\n // Changing direction, assume we need to clear current set of choices\n this._currentFlow.currentChoices.length = 0;\n\n let newPointer = this.story.PointerAtPath(path);\n if (!newPointer.isNull && newPointer.index == -1) newPointer.index = 0;\n\n this.currentPointer = newPointer;\n\n if (incrementingTurnIndex) {\n this.currentTurnIndex++;\n }\n }\n\n public StartFunctionEvaluationFromGame(\n funcContainer: Container,\n args: any[]\n ) {\n this.callStack.Push(\n PushPopType.FunctionEvaluationFromGame,\n this.evaluationStack.length\n );\n this.callStack.currentElement.currentPointer =\n Pointer.StartOf(funcContainer);\n\n this.PassArgumentsToEvaluationStack(args);\n }\n\n public PassArgumentsToEvaluationStack(args: any[] | null) {\n if (args !== null) {\n for (let i = 0; i < args.length; i++) {\n if (\n !(\n typeof args[i] === \"number\" ||\n typeof args[i] === \"string\" ||\n typeof args[i] === \"boolean\" ||\n args[i] instanceof InkList\n )\n ) {\n throw new Error(\n \"ink arguments when calling EvaluateFunction / ChoosePathStringWithParameters must be\" +\n \"number, string, bool or InkList. Argument was \" +\n (nullIfUndefined(args[i]) === null\n ? \"null\"\n : args[i].constructor.name)\n );\n }\n\n this.PushEvaluationStack(Value.Create(args[i]));\n }\n }\n }\n\n public TryExitFunctionEvaluationFromGame() {\n if (\n this.callStack.currentElement.type ==\n PushPopType.FunctionEvaluationFromGame\n ) {\n this.currentPointer = Pointer.Null;\n this.didSafeExit = true;\n return true;\n }\n\n return false;\n }\n\n public CompleteFunctionEvaluationFromGame() {\n if (\n this.callStack.currentElement.type !=\n PushPopType.FunctionEvaluationFromGame\n ) {\n throw new Error(\n \"Expected external function evaluation to be complete. Stack trace: \" +\n this.callStack.callStackTrace\n );\n }\n\n let originalEvaluationStackHeight =\n this.callStack.currentElement.evaluationStackHeightWhenPushed;\n\n let returnedObj: InkObject | null = null;\n while (this.evaluationStack.length > originalEvaluationStackHeight) {\n let poppedObj = this.PopEvaluationStack();\n if (returnedObj === null) returnedObj = poppedObj;\n }\n\n this.PopCallStack(PushPopType.FunctionEvaluationFromGame);\n\n if (returnedObj) {\n if (returnedObj instanceof Void) return null;\n\n // Some kind of value, if not void\n // var returnVal = returnedObj as Runtime.Value;\n let returnVal = asOrThrows(returnedObj, Value);\n\n // DivertTargets get returned as the string of components\n // (rather than a Path, which isn't public)\n if (returnVal.valueType == ValueType.DivertTarget) {\n return returnVal.valueObject.toString();\n }\n\n // Other types can just have their exact object type:\n // int, float, string. VariablePointers get returned as strings.\n return returnVal.valueObject;\n }\n\n return null;\n }\n\n public AddError(message: string, isWarning: boolean) {\n if (!isWarning) {\n if (this._currentErrors == null) this._currentErrors = [];\n this._currentErrors.push(message);\n } else {\n if (this._currentWarnings == null) this._currentWarnings = [];\n this._currentWarnings.push(message);\n }\n }\n\n public OutputStreamDirty() {\n this._outputStreamTextDirty = true;\n this._outputStreamTagsDirty = true;\n }\n\n private _visitCounts: Map;\n private _turnIndices: Map;\n\n private _outputStreamTextDirty = true;\n private _outputStreamTagsDirty = true;\n\n private _patch: StatePatch | null = null;\n\n private _currentFlow: Flow;\n private _aliveFlowNames: string[] | null = null;\n private _namedFlows: Map | null = null;\n private readonly kDefaultFlowName = \"DEFAULT_FLOW\";\n private _aliveFlowNamesDirty: boolean = true;\n}\n","// This is simple replacement of the Stopwatch class from the .NET Framework.\n// The original class can count time with much more accuracy than the Javascript version.\n// It might be worth considering using `window.performance` in the browser\n// or `process.hrtime()` in node.\nexport class Stopwatch {\n private startTime: number | undefined;\n\n constructor() {\n this.startTime = undefined;\n }\n\n get ElapsedMilliseconds(): number {\n if (typeof this.startTime === \"undefined\") {\n return 0;\n }\n return new Date().getTime() - this.startTime;\n }\n\n public Start() {\n this.startTime = new Date().getTime();\n }\n public Stop() {\n this.startTime = undefined;\n }\n}\n","// TODO: Unify with Compiler.\n\nexport type ErrorHandler = (message: string, type: ErrorType) => void;\n\nexport enum ErrorType {\n Author,\n Warning,\n Error,\n}\n","import { Container } from \"./Container\";\nimport { InkObject } from \"./Object\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { StoryState } from \"./StoryState\";\nimport { ControlCommand } from \"./ControlCommand\";\nimport { PushPopType } from \"./PushPop\";\nimport { ChoicePoint } from \"./ChoicePoint\";\nimport { Choice } from \"./Choice\";\nimport { Divert } from \"./Divert\";\nimport {\n Value,\n StringValue,\n IntValue,\n DivertTargetValue,\n VariablePointerValue,\n ListValue,\n} from \"./Value\";\nimport { Path } from \"./Path\";\nimport { Void } from \"./Void\";\nimport { Tag } from \"./Tag\";\nimport { VariableAssignment } from \"./VariableAssignment\";\nimport { VariableReference } from \"./VariableReference\";\nimport { NativeFunctionCall } from \"./NativeFunctionCall\";\nimport { StoryException } from \"./StoryException\";\nimport { PRNG } from \"./PRNG\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { ListDefinitionsOrigin } from \"./ListDefinitionsOrigin\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { Stopwatch } from \"./StopWatch\";\nimport { Pointer } from \"./Pointer\";\nimport { InkList, InkListItem, KeyValuePair } from \"./InkList\";\nimport { asOrNull, asOrThrows } from \"./TypeAssertion\";\nimport { DebugMetadata } from \"./DebugMetadata\";\nimport { throwNullException } from \"./NullException\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { ErrorHandler, ErrorType } from \"./Error\";\n\nexport { InkList } from \"./InkList\";\n\nif (!Number.isInteger) {\n Number.isInteger = function isInteger(nVal: any) {\n return (\n typeof nVal === \"number\" &&\n isFinite(nVal) &&\n nVal > -9007199254740992 &&\n nVal < 9007199254740992 &&\n Math.floor(nVal) === nVal\n );\n };\n}\n\nexport class Story extends InkObject {\n public static inkVersionCurrent = 21;\n\n public inkVersionMinimumCompatible = 18;\n\n get currentChoices() {\n let choices: Choice[] = [];\n\n if (this._state === null) {\n return throwNullException(\"this._state\");\n }\n for (let c of this._state.currentChoices) {\n if (!c.isInvisibleDefault) {\n c.index = choices.length;\n choices.push(c);\n }\n }\n\n return choices;\n }\n\n get currentText() {\n this.IfAsyncWeCant(\"call currentText since it's a work in progress\");\n return this.state.currentText;\n }\n\n get currentTags() {\n this.IfAsyncWeCant(\"call currentTags since it's a work in progress\");\n return this.state.currentTags;\n }\n\n get currentErrors() {\n return this.state.currentErrors;\n }\n\n get currentWarnings() {\n return this.state.currentWarnings;\n }\n\n get currentFlowName() {\n return this.state.currentFlowName;\n }\n\n get currentFlowIsDefaultFlow() {\n return this.state.currentFlowIsDefaultFlow;\n }\n\n get aliveFlowNames() {\n return this.state.aliveFlowNames;\n }\n\n get hasError() {\n return this.state.hasError;\n }\n\n get hasWarning() {\n return this.state.hasWarning;\n }\n\n get variablesState() {\n return this.state.variablesState;\n }\n\n get listDefinitions() {\n return this._listDefinitions;\n }\n\n get state() {\n return this._state;\n }\n\n public onError: ErrorHandler | null = null;\n\n public onDidContinue: (() => void) | null = null;\n\n public onMakeChoice: ((arg1: Choice) => void) | null = null;\n\n public onEvaluateFunction: ((arg1: string, arg2: any[]) => void) | null =\n null;\n\n public onCompleteEvaluateFunction:\n | ((arg1: string, arg2: any[], arg3: string, arg4: any) => void)\n | null = null;\n\n public onChoosePathString: ((arg1: string, arg2: any[]) => void) | null =\n null;\n\n // TODO: Implement Profiler\n public StartProfiling() {\n /* */\n }\n public EndProfiling() {\n /* */\n }\n\n constructor(contentContainer: Container, lists: ListDefinition[] | null);\n constructor(jsonString: string);\n constructor(json: Record);\n constructor() {\n super();\n\n // Discrimination between constructors\n let contentContainer: Container;\n let lists: ListDefinition[] | null = null;\n let json: Record | null = null;\n\n if (arguments[0] instanceof Container) {\n contentContainer = arguments[0] as Container;\n\n if (typeof arguments[1] !== \"undefined\") {\n lists = arguments[1] as ListDefinition[];\n }\n\n // ------ Story (Container contentContainer, List lists = null)\n this._mainContentContainer = contentContainer;\n // ------\n } else {\n if (typeof arguments[0] === \"string\") {\n let jsonString = arguments[0] as string;\n json = SimpleJson.TextToDictionary(jsonString);\n } else {\n json = arguments[0] as Record;\n }\n }\n\n // ------ Story (Container contentContainer, List lists = null)\n if (lists != null) this._listDefinitions = new ListDefinitionsOrigin(lists);\n\n this._externals = new Map();\n // ------\n\n // ------ Story(string jsonString) : this((Container)null)\n if (json !== null) {\n let rootObject: Record = json;\n\n let versionObj = rootObject[\"inkVersion\"];\n if (versionObj == null)\n throw new Error(\n \"ink version number not found. Are you sure it's a valid .ink.json file?\"\n );\n\n let formatFromFile = parseInt(versionObj);\n if (formatFromFile > Story.inkVersionCurrent) {\n throw new Error(\n \"Version of ink used to build story was newer than the current version of the engine\"\n );\n } else if (formatFromFile < this.inkVersionMinimumCompatible) {\n throw new Error(\n \"Version of ink used to build story is too old to be loaded by this version of the engine\"\n );\n } else if (formatFromFile != Story.inkVersionCurrent) {\n console.warn(\n \"WARNING: Version of ink used to build story doesn't match current version of engine. Non-critical, but recommend synchronising.\"\n );\n }\n\n let rootToken = rootObject[\"root\"];\n if (rootToken == null)\n throw new Error(\n \"Root node for ink not found. Are you sure it's a valid .ink.json file?\"\n );\n\n let listDefsObj;\n if ((listDefsObj = rootObject[\"listDefs\"])) {\n this._listDefinitions =\n JsonSerialisation.JTokenToListDefinitions(listDefsObj);\n }\n\n this._mainContentContainer = asOrThrows(\n JsonSerialisation.JTokenToRuntimeObject(rootToken),\n Container\n );\n\n this.ResetState();\n }\n // ------\n }\n\n // Merge together `public string ToJson()` and `void ToJson(SimpleJson.Writer writer)`.\n // Will only return a value if writer was not provided.\n public ToJson(writer?: SimpleJson.Writer): string | void {\n let shouldReturn = false;\n\n if (!writer) {\n shouldReturn = true;\n writer = new SimpleJson.Writer();\n }\n\n writer.WriteObjectStart();\n\n writer.WriteIntProperty(\"inkVersion\", Story.inkVersionCurrent);\n\n writer.WriteProperty(\"root\", (w) =>\n JsonSerialisation.WriteRuntimeContainer(w, this._mainContentContainer)\n );\n\n if (this._listDefinitions != null) {\n writer.WritePropertyStart(\"listDefs\");\n writer.WriteObjectStart();\n\n for (let def of this._listDefinitions.lists) {\n writer.WritePropertyStart(def.name);\n writer.WriteObjectStart();\n\n for (let [key, value] of def.items) {\n let item = InkListItem.fromSerializedKey(key);\n let val = value;\n writer.WriteIntProperty(item.itemName, val);\n }\n\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n\n if (shouldReturn) return writer.toString();\n }\n\n public ResetState() {\n this.IfAsyncWeCant(\"ResetState\");\n\n this._state = new StoryState(this);\n this._state.variablesState.ObserveVariableChange(\n this.VariableStateDidChangeEvent.bind(this)\n );\n\n this.ResetGlobals();\n }\n\n public ResetErrors() {\n if (this._state === null) {\n return throwNullException(\"this._state\");\n }\n this._state.ResetErrors();\n }\n\n public ResetCallstack() {\n this.IfAsyncWeCant(\"ResetCallstack\");\n if (this._state === null) {\n return throwNullException(\"this._state\");\n }\n this._state.ForceEnd();\n }\n\n public ResetGlobals() {\n if (this._mainContentContainer.namedContent.get(\"global decl\")) {\n let originalPointer = this.state.currentPointer.copy();\n\n this.ChoosePath(new Path(\"global decl\"), false);\n\n this.ContinueInternal();\n\n this.state.currentPointer = originalPointer;\n }\n\n this.state.variablesState.SnapshotDefaultGlobals();\n }\n\n public SwitchFlow(flowName: string) {\n this.IfAsyncWeCant(\"switch flow\");\n if (this._asyncSaving) {\n throw new Error(\n \"Story is already in background saving mode, can't switch flow to \" +\n flowName\n );\n }\n\n this.state.SwitchFlow_Internal(flowName);\n }\n\n public RemoveFlow(flowName: string) {\n this.state.RemoveFlow_Internal(flowName);\n }\n\n public SwitchToDefaultFlow() {\n this.state.SwitchToDefaultFlow_Internal();\n }\n\n public Continue() {\n this.ContinueAsync(0);\n return this.currentText;\n }\n\n get canContinue() {\n return this.state.canContinue;\n }\n\n get asyncContinueComplete() {\n return !this._asyncContinueActive;\n }\n\n public ContinueAsync(millisecsLimitAsync: number) {\n if (!this._hasValidatedExternals) this.ValidateExternalBindings();\n\n this.ContinueInternal(millisecsLimitAsync);\n }\n\n public ContinueInternal(millisecsLimitAsync = 0) {\n if (this._profiler != null) this._profiler.PreContinue();\n\n let isAsyncTimeLimited = millisecsLimitAsync > 0;\n this._recursiveContinueCount++;\n\n if (!this._asyncContinueActive) {\n this._asyncContinueActive = isAsyncTimeLimited;\n\n if (!this.canContinue) {\n throw new Error(\n \"Can't continue - should check canContinue before calling Continue\"\n );\n }\n\n this._state.didSafeExit = false;\n this._state.ResetOutput();\n\n if (this._recursiveContinueCount == 1)\n this._state.variablesState.batchObservingVariableChanges = true;\n }\n\n let durationStopwatch = new Stopwatch();\n durationStopwatch.Start();\n\n let outputStreamEndsInNewline = false;\n this._sawLookaheadUnsafeFunctionAfterNewline = false;\n do {\n try {\n outputStreamEndsInNewline = this.ContinueSingleStep();\n } catch (e) {\n if (!(e instanceof StoryException)) throw e;\n\n this.AddError(e.message, undefined, e.useEndLineNumber);\n break;\n }\n\n if (outputStreamEndsInNewline) break;\n\n if (\n this._asyncContinueActive &&\n durationStopwatch.ElapsedMilliseconds > millisecsLimitAsync\n ) {\n break;\n }\n } while (this.canContinue);\n\n durationStopwatch.Stop();\n\n if (outputStreamEndsInNewline || !this.canContinue) {\n if (this._stateSnapshotAtLastNewline !== null) {\n this.RestoreStateSnapshot();\n }\n\n if (!this.canContinue) {\n if (this.state.callStack.canPopThread)\n this.AddError(\n \"Thread available to pop, threads should always be flat by the end of evaluation?\"\n );\n\n if (\n this.state.generatedChoices.length == 0 &&\n !this.state.didSafeExit &&\n this._temporaryEvaluationContainer == null\n ) {\n if (this.state.callStack.CanPop(PushPopType.Tunnel))\n this.AddError(\n \"unexpectedly reached end of content. Do you need a '->->' to return from a tunnel?\"\n );\n else if (this.state.callStack.CanPop(PushPopType.Function))\n this.AddError(\n \"unexpectedly reached end of content. Do you need a '~ return'?\"\n );\n else if (!this.state.callStack.canPop)\n this.AddError(\n \"ran out of content. Do you need a '-> DONE' or '-> END'?\"\n );\n else\n this.AddError(\n \"unexpectedly reached end of content for unknown reason. Please debug compiler!\"\n );\n }\n }\n\n this.state.didSafeExit = false;\n this._sawLookaheadUnsafeFunctionAfterNewline = false;\n\n if (this._recursiveContinueCount == 1)\n this._state.variablesState.batchObservingVariableChanges = false;\n\n this._asyncContinueActive = false;\n if (this.onDidContinue !== null) this.onDidContinue();\n }\n\n this._recursiveContinueCount--;\n\n if (this._profiler != null) this._profiler.PostContinue();\n\n // In the following code, we're masking a lot of non-null assertion,\n // because testing for against `hasError` or `hasWarning` makes sure\n // the arrays are present and contain at least one element.\n if (this.state.hasError || this.state.hasWarning) {\n if (this.onError !== null) {\n if (this.state.hasError) {\n for (let err of this.state.currentErrors!) {\n this.onError(err, ErrorType.Error);\n }\n }\n if (this.state.hasWarning) {\n for (let err of this.state.currentWarnings!) {\n this.onError(err, ErrorType.Warning);\n }\n }\n this.ResetErrors();\n } else {\n let sb = new StringBuilder();\n sb.Append(\"Ink had \");\n if (this.state.hasError) {\n sb.Append(`${this.state.currentErrors!.length}`);\n sb.Append(\n this.state.currentErrors!.length == 1 ? \" error\" : \"errors\"\n );\n if (this.state.hasWarning) sb.Append(\" and \");\n }\n if (this.state.hasWarning) {\n sb.Append(`${this.state.currentWarnings!.length}`);\n sb.Append(\n this.state.currentWarnings!.length == 1 ? \" warning\" : \"warnings\"\n );\n if (this.state.hasWarning) sb.Append(\" and \");\n }\n sb.Append(\n \". It is strongly suggested that you assign an error handler to story.onError. The first issue was: \"\n );\n sb.Append(\n this.state.hasError\n ? this.state.currentErrors![0]\n : this.state.currentWarnings![0]\n );\n\n throw new StoryException(sb.toString());\n }\n }\n }\n\n public ContinueSingleStep() {\n if (this._profiler != null) this._profiler.PreStep();\n\n this.Step();\n\n if (this._profiler != null) this._profiler.PostStep();\n\n if (!this.canContinue && !this.state.callStack.elementIsEvaluateFromGame) {\n this.TryFollowDefaultInvisibleChoice();\n }\n\n if (this._profiler != null) this._profiler.PreSnapshot();\n\n if (!this.state.inStringEvaluation) {\n if (this._stateSnapshotAtLastNewline !== null) {\n if (this._stateSnapshotAtLastNewline.currentTags === null) {\n return throwNullException(\"this._stateAtLastNewline.currentTags\");\n }\n if (this.state.currentTags === null) {\n return throwNullException(\"this.state.currentTags\");\n }\n\n let change = this.CalculateNewlineOutputStateChange(\n this._stateSnapshotAtLastNewline.currentText,\n this.state.currentText,\n this._stateSnapshotAtLastNewline.currentTags.length,\n this.state.currentTags.length\n );\n\n if (\n change == Story.OutputStateChange.ExtendedBeyondNewline ||\n this._sawLookaheadUnsafeFunctionAfterNewline\n ) {\n this.RestoreStateSnapshot();\n\n return true;\n } else if (change == Story.OutputStateChange.NewlineRemoved) {\n this.DiscardSnapshot();\n }\n }\n\n if (this.state.outputStreamEndsInNewline) {\n if (this.canContinue) {\n if (this._stateSnapshotAtLastNewline == null) this.StateSnapshot();\n } else {\n this.DiscardSnapshot();\n }\n }\n }\n\n if (this._profiler != null) this._profiler.PostSnapshot();\n\n return false;\n }\n\n public CalculateNewlineOutputStateChange(\n prevText: string | null,\n currText: string | null,\n prevTagCount: number,\n currTagCount: number\n ) {\n if (prevText === null) {\n return throwNullException(\"prevText\");\n }\n if (currText === null) {\n return throwNullException(\"currText\");\n }\n\n let newlineStillExists =\n currText.length >= prevText.length &&\n prevText.length > 0 &&\n currText.charAt(prevText.length - 1) == \"\\n\";\n if (\n prevTagCount == currTagCount &&\n prevText.length == currText.length &&\n newlineStillExists\n )\n return Story.OutputStateChange.NoChange;\n\n if (!newlineStillExists) {\n return Story.OutputStateChange.NewlineRemoved;\n }\n\n if (currTagCount > prevTagCount)\n return Story.OutputStateChange.ExtendedBeyondNewline;\n\n for (let i = prevText.length; i < currText.length; i++) {\n let c = currText.charAt(i);\n if (c != \" \" && c != \"\\t\") {\n return Story.OutputStateChange.ExtendedBeyondNewline;\n }\n }\n\n return Story.OutputStateChange.NoChange;\n }\n\n public ContinueMaximally() {\n this.IfAsyncWeCant(\"ContinueMaximally\");\n\n let sb = new StringBuilder();\n\n while (this.canContinue) {\n sb.Append(this.Continue());\n }\n\n return sb.toString();\n }\n\n public ContentAtPath(path: Path) {\n return this.mainContentContainer.ContentAtPath(path);\n }\n\n public KnotContainerWithName(name: string) {\n let namedContainer = this.mainContentContainer.namedContent.get(name);\n if (namedContainer instanceof Container) return namedContainer;\n else return null;\n }\n\n public PointerAtPath(path: Path) {\n if (path.length == 0) return Pointer.Null;\n\n let p = new Pointer();\n\n let pathLengthToUse = path.length;\n\n let result = null;\n if (path.lastComponent === null) {\n return throwNullException(\"path.lastComponent\");\n }\n\n if (path.lastComponent.isIndex) {\n pathLengthToUse = path.length - 1;\n result = this.mainContentContainer.ContentAtPath(\n path,\n undefined,\n pathLengthToUse\n );\n p.container = result.container;\n p.index = path.lastComponent.index;\n } else {\n result = this.mainContentContainer.ContentAtPath(path);\n p.container = result.container;\n p.index = -1;\n }\n\n if (\n result.obj == null ||\n (result.obj == this.mainContentContainer && pathLengthToUse > 0)\n ) {\n this.Error(\n \"Failed to find content at path '\" +\n path +\n \"', and no approximation of it was possible.\"\n );\n } else if (result.approximate)\n this.Warning(\n \"Failed to find content at path '\" +\n path +\n \"', so it was approximated to: '\" +\n result.obj.path +\n \"'.\"\n );\n\n return p;\n }\n\n public StateSnapshot() {\n this._stateSnapshotAtLastNewline = this._state;\n this._state = this._state.CopyAndStartPatching();\n }\n\n public RestoreStateSnapshot() {\n if (this._stateSnapshotAtLastNewline === null) {\n throwNullException(\"_stateSnapshotAtLastNewline\");\n }\n this._stateSnapshotAtLastNewline.RestoreAfterPatch();\n\n this._state = this._stateSnapshotAtLastNewline;\n this._stateSnapshotAtLastNewline = null;\n\n if (!this._asyncSaving) {\n this._state.ApplyAnyPatch();\n }\n }\n\n public DiscardSnapshot() {\n if (!this._asyncSaving) this._state.ApplyAnyPatch();\n\n this._stateSnapshotAtLastNewline = null;\n }\n\n public CopyStateForBackgroundThreadSave() {\n this.IfAsyncWeCant(\"start saving on a background thread\");\n\n if (this._asyncSaving)\n throw new Error(\n \"Story is already in background saving mode, can't call CopyStateForBackgroundThreadSave again!\"\n );\n\n let stateToSave = this._state;\n this._state = this._state.CopyAndStartPatching();\n this._asyncSaving = true;\n return stateToSave;\n }\n\n public BackgroundSaveComplete() {\n if (this._stateSnapshotAtLastNewline === null) {\n this._state.ApplyAnyPatch();\n }\n\n this._asyncSaving = false;\n }\n\n public Step() {\n let shouldAddToStream = true;\n\n let pointer = this.state.currentPointer.copy();\n if (pointer.isNull) {\n return;\n }\n\n // Container containerToEnter = pointer.Resolve () as Container;\n let containerToEnter = asOrNull(pointer.Resolve(), Container);\n\n while (containerToEnter) {\n this.VisitContainer(containerToEnter, true);\n\n // No content? the most we can do is step past it\n if (containerToEnter.content.length == 0) {\n break;\n }\n\n pointer = Pointer.StartOf(containerToEnter);\n // containerToEnter = pointer.Resolve() as Container;\n containerToEnter = asOrNull(pointer.Resolve(), Container);\n }\n\n this.state.currentPointer = pointer.copy();\n\n if (this._profiler != null) this._profiler.Step(this.state.callStack);\n\n // Is the current content object:\n // - Normal content\n // - Or a logic/flow statement - if so, do it\n // Stop flow if we hit a stack pop when we're unable to pop (e.g. return/done statement in knot\n // that was diverted to rather than called as a function)\n let currentContentObj = pointer.Resolve();\n let isLogicOrFlowControl =\n this.PerformLogicAndFlowControl(currentContentObj);\n\n // Has flow been forced to end by flow control above?\n if (this.state.currentPointer.isNull) {\n return;\n }\n\n if (isLogicOrFlowControl) {\n shouldAddToStream = false;\n }\n\n // Choice with condition?\n // var choicePoint = currentContentObj as ChoicePoint;\n let choicePoint = asOrNull(currentContentObj, ChoicePoint);\n if (choicePoint) {\n let choice = this.ProcessChoice(choicePoint);\n if (choice) {\n this.state.generatedChoices.push(choice);\n }\n\n currentContentObj = null;\n shouldAddToStream = false;\n }\n\n // If the container has no content, then it will be\n // the \"content\" itself, but we skip over it.\n if (currentContentObj instanceof Container) {\n shouldAddToStream = false;\n }\n\n // Content to add to evaluation stack or the output stream\n if (shouldAddToStream) {\n // If we're pushing a variable pointer onto the evaluation stack, ensure that it's specific\n // to our current (possibly temporary) context index. And make a copy of the pointer\n // so that we're not editing the original runtime object.\n // var varPointer = currentContentObj as VariablePointerValue;\n let varPointer = asOrNull(currentContentObj, VariablePointerValue);\n if (varPointer && varPointer.contextIndex == -1) {\n // Create new object so we're not overwriting the story's own data\n let contextIdx = this.state.callStack.ContextForVariableNamed(\n varPointer.variableName\n );\n currentContentObj = new VariablePointerValue(\n varPointer.variableName,\n contextIdx\n );\n }\n\n // Expression evaluation content\n if (this.state.inExpressionEvaluation) {\n this.state.PushEvaluationStack(currentContentObj);\n }\n // Output stream content (i.e. not expression evaluation)\n else {\n this.state.PushToOutputStream(currentContentObj);\n }\n }\n\n // Increment the content pointer, following diverts if necessary\n this.NextContent();\n\n // Starting a thread should be done after the increment to the content pointer,\n // so that when returning from the thread, it returns to the content after this instruction.\n // var controlCmd = currentContentObj as ;\n let controlCmd = asOrNull(currentContentObj, ControlCommand);\n if (\n controlCmd &&\n controlCmd.commandType == ControlCommand.CommandType.StartThread\n ) {\n this.state.callStack.PushThread();\n }\n }\n\n public VisitContainer(container: Container, atStart: boolean) {\n if (!container.countingAtStartOnly || atStart) {\n if (container.visitsShouldBeCounted)\n this.state.IncrementVisitCountForContainer(container);\n\n if (container.turnIndexShouldBeCounted)\n this.state.RecordTurnIndexVisitToContainer(container);\n }\n }\n\n private _prevContainers: Container[] = [];\n public VisitChangedContainersDueToDivert() {\n let previousPointer = this.state.previousPointer.copy();\n let pointer = this.state.currentPointer.copy();\n\n if (pointer.isNull || pointer.index == -1) return;\n\n this._prevContainers.length = 0;\n if (!previousPointer.isNull) {\n // Container prevAncestor = previousPointer.Resolve() as Container ?? previousPointer.container as Container;\n let resolvedPreviousAncestor = previousPointer.Resolve();\n let prevAncestor =\n asOrNull(resolvedPreviousAncestor, Container) ||\n asOrNull(previousPointer.container, Container);\n while (prevAncestor) {\n this._prevContainers.push(prevAncestor);\n // prevAncestor = prevAncestor.parent as Container;\n prevAncestor = asOrNull(prevAncestor.parent, Container);\n }\n }\n\n let currentChildOfContainer = pointer.Resolve();\n\n if (currentChildOfContainer == null) return;\n\n // Container currentContainerAncestor = currentChildOfContainer.parent as Container;\n let currentContainerAncestor = asOrNull(\n currentChildOfContainer.parent,\n Container\n );\n let allChildrenEnteredAtStart = true;\n while (\n currentContainerAncestor &&\n (this._prevContainers.indexOf(currentContainerAncestor) < 0 ||\n currentContainerAncestor.countingAtStartOnly)\n ) {\n // Check whether this ancestor container is being entered at the start,\n // by checking whether the child object is the first.\n let enteringAtStart =\n currentContainerAncestor.content.length > 0 &&\n currentChildOfContainer == currentContainerAncestor.content[0] &&\n allChildrenEnteredAtStart;\n\n if (!enteringAtStart) allChildrenEnteredAtStart = false;\n\n // Mark a visit to this container\n this.VisitContainer(currentContainerAncestor, enteringAtStart);\n\n currentChildOfContainer = currentContainerAncestor;\n // currentContainerAncestor = currentContainerAncestor.parent as Container;\n currentContainerAncestor = asOrNull(\n currentContainerAncestor.parent,\n Container\n );\n }\n }\n\n public PopChoiceStringAndTags(tags: string[]) {\n let choiceOnlyStrVal = asOrThrows(\n this.state.PopEvaluationStack(),\n StringValue\n );\n\n while (\n this.state.evaluationStack.length > 0 &&\n asOrNull(this.state.PeekEvaluationStack(), Tag) != null\n ) {\n let tag = asOrNull(this.state.PopEvaluationStack(), Tag);\n if (tag) tags.push(tag.text);\n }\n return choiceOnlyStrVal.value;\n }\n\n public ProcessChoice(choicePoint: ChoicePoint) {\n let showChoice = true;\n\n // Don't create choice if choice point doesn't pass conditional\n if (choicePoint.hasCondition) {\n let conditionValue = this.state.PopEvaluationStack();\n if (!this.IsTruthy(conditionValue)) {\n showChoice = false;\n }\n }\n\n let startText = \"\";\n let choiceOnlyText = \"\";\n let tags: string[] = [];\n\n if (choicePoint.hasChoiceOnlyContent) {\n choiceOnlyText = this.PopChoiceStringAndTags(tags) || \"\";\n }\n\n if (choicePoint.hasStartContent) {\n startText = this.PopChoiceStringAndTags(tags) || \"\";\n }\n\n // Don't create choice if player has already read this content\n if (choicePoint.onceOnly) {\n let visitCount = this.state.VisitCountForContainer(\n choicePoint.choiceTarget\n );\n if (visitCount > 0) {\n showChoice = false;\n }\n }\n\n // We go through the full process of creating the choice above so\n // that we consume the content for it, since otherwise it'll\n // be shown on the output stream.\n if (!showChoice) {\n return null;\n }\n\n let choice = new Choice();\n choice.targetPath = choicePoint.pathOnChoice;\n choice.sourcePath = choicePoint.path.toString();\n choice.isInvisibleDefault = choicePoint.isInvisibleDefault;\n choice.threadAtGeneration = this.state.callStack.ForkThread();\n choice.tags = tags.reverse(); //C# is a stack\n choice.text = (startText + choiceOnlyText).replace(/^[ \\t]+|[ \\t]+$/g, \"\");\n\n return choice;\n }\n\n public IsTruthy(obj: InkObject) {\n let truthy = false;\n if (obj instanceof Value) {\n let val = obj;\n\n if (val instanceof DivertTargetValue) {\n let divTarget = val;\n this.Error(\n \"Shouldn't use a divert target (to \" +\n divTarget.targetPath +\n \") as a conditional value. Did you intend a function call 'likeThis()' or a read count check 'likeThis'? (no arrows)\"\n );\n return false;\n }\n\n return val.isTruthy;\n }\n return truthy;\n }\n\n public PerformLogicAndFlowControl(contentObj: InkObject | null) {\n if (contentObj == null) {\n return false;\n }\n\n // Divert\n if (contentObj instanceof Divert) {\n let currentDivert = contentObj;\n\n if (currentDivert.isConditional) {\n let conditionValue = this.state.PopEvaluationStack();\n\n // False conditional? Cancel divert\n if (!this.IsTruthy(conditionValue)) return true;\n }\n\n if (currentDivert.hasVariableTarget) {\n let varName = currentDivert.variableDivertName;\n\n let varContents =\n this.state.variablesState.GetVariableWithName(varName);\n\n if (varContents == null) {\n this.Error(\n \"Tried to divert using a target from a variable that could not be found (\" +\n varName +\n \")\"\n );\n } else if (!(varContents instanceof DivertTargetValue)) {\n // var intContent = varContents as IntValue;\n let intContent = asOrNull(varContents, IntValue);\n\n let errorMessage =\n \"Tried to divert to a target from a variable, but the variable (\" +\n varName +\n \") didn't contain a divert target, it \";\n if (intContent instanceof IntValue && intContent.value == 0) {\n errorMessage += \"was empty/null (the value 0).\";\n } else {\n errorMessage += \"contained '\" + varContents + \"'.\";\n }\n\n this.Error(errorMessage);\n }\n\n let target = asOrThrows(varContents, DivertTargetValue);\n this.state.divertedPointer = this.PointerAtPath(target.targetPath);\n } else if (currentDivert.isExternal) {\n this.CallExternalFunction(\n currentDivert.targetPathString,\n currentDivert.externalArgs\n );\n return true;\n } else {\n this.state.divertedPointer = currentDivert.targetPointer.copy();\n }\n\n if (currentDivert.pushesToStack) {\n this.state.callStack.Push(\n currentDivert.stackPushType,\n undefined,\n this.state.outputStream.length\n );\n }\n\n if (this.state.divertedPointer.isNull && !currentDivert.isExternal) {\n if (\n currentDivert &&\n currentDivert.debugMetadata &&\n currentDivert.debugMetadata.sourceName != null\n ) {\n this.Error(\n \"Divert target doesn't exist: \" +\n currentDivert.debugMetadata.sourceName\n );\n } else {\n this.Error(\"Divert resolution failed: \" + currentDivert);\n }\n }\n\n return true;\n }\n\n // Start/end an expression evaluation? Or print out the result?\n else if (contentObj instanceof ControlCommand) {\n let evalCommand = contentObj;\n\n switch (evalCommand.commandType) {\n case ControlCommand.CommandType.EvalStart:\n this.Assert(\n this.state.inExpressionEvaluation === false,\n \"Already in expression evaluation?\"\n );\n this.state.inExpressionEvaluation = true;\n break;\n\n case ControlCommand.CommandType.EvalEnd:\n this.Assert(\n this.state.inExpressionEvaluation === true,\n \"Not in expression evaluation mode\"\n );\n this.state.inExpressionEvaluation = false;\n break;\n\n case ControlCommand.CommandType.EvalOutput:\n // If the expression turned out to be empty, there may not be anything on the stack\n if (this.state.evaluationStack.length > 0) {\n let output = this.state.PopEvaluationStack();\n\n // Functions may evaluate to Void, in which case we skip output\n if (!(output instanceof Void)) {\n // TODO: Should we really always blanket convert to string?\n // It would be okay to have numbers in the output stream the\n // only problem is when exporting text for viewing, it skips over numbers etc.\n let text = new StringValue(output.toString());\n\n this.state.PushToOutputStream(text);\n }\n }\n break;\n\n case ControlCommand.CommandType.NoOp:\n break;\n\n case ControlCommand.CommandType.Duplicate:\n this.state.PushEvaluationStack(this.state.PeekEvaluationStack());\n break;\n\n case ControlCommand.CommandType.PopEvaluatedValue:\n this.state.PopEvaluationStack();\n break;\n\n case ControlCommand.CommandType.PopFunction:\n case ControlCommand.CommandType.PopTunnel:\n let popType =\n evalCommand.commandType == ControlCommand.CommandType.PopFunction\n ? PushPopType.Function\n : PushPopType.Tunnel;\n\n let overrideTunnelReturnTarget: DivertTargetValue | null = null;\n if (popType == PushPopType.Tunnel) {\n let popped = this.state.PopEvaluationStack();\n // overrideTunnelReturnTarget = popped as DivertTargetValue;\n overrideTunnelReturnTarget = asOrNull(popped, DivertTargetValue);\n if (overrideTunnelReturnTarget === null) {\n this.Assert(\n popped instanceof Void,\n \"Expected void if ->-> doesn't override target\"\n );\n }\n }\n\n if (this.state.TryExitFunctionEvaluationFromGame()) {\n break;\n } else if (\n this.state.callStack.currentElement.type != popType ||\n !this.state.callStack.canPop\n ) {\n let names: Map = new Map();\n names.set(\n PushPopType.Function,\n \"function return statement (~ return)\"\n );\n names.set(PushPopType.Tunnel, \"tunnel onwards statement (->->)\");\n\n let expected = names.get(this.state.callStack.currentElement.type);\n if (!this.state.callStack.canPop) {\n expected = \"end of flow (-> END or choice)\";\n }\n\n let errorMsg =\n \"Found \" + names.get(popType) + \", when expected \" + expected;\n\n this.Error(errorMsg);\n } else {\n this.state.PopCallStack();\n\n if (overrideTunnelReturnTarget)\n this.state.divertedPointer = this.PointerAtPath(\n overrideTunnelReturnTarget.targetPath\n );\n }\n break;\n\n case ControlCommand.CommandType.BeginString:\n this.state.PushToOutputStream(evalCommand);\n\n this.Assert(\n this.state.inExpressionEvaluation === true,\n \"Expected to be in an expression when evaluating a string\"\n );\n this.state.inExpressionEvaluation = false;\n break;\n\n // Leave it to story.currentText and story.currentTags to sort out the text from the tags\n // This is mostly because we can't always rely on the existence of EndTag, and we don't want\n // to try and flatten dynamic tags to strings every time \\n is pushed to output\n case ControlCommand.CommandType.BeginTag:\n this.state.PushToOutputStream(evalCommand);\n break;\n\n // EndTag has 2 modes:\n // - When in string evaluation (for choices)\n // - Normal\n //\n // The only way you could have an EndTag in the middle of\n // string evaluation is if we're currently generating text for a\n // choice, such as:\n //\n // + choice # tag\n //\n // In the above case, the ink will be run twice:\n // - First, to generate the choice text. String evaluation\n // will be on, and the final string will be pushed to the\n // evaluation stack, ready to be popped to make a Choice\n // object.\n // - Second, when ink generates text after choosing the choice.\n // On this ocassion, it's not in string evaluation mode.\n //\n // On the writing side, we disallow manually putting tags within\n // strings like this:\n //\n // {\"hello # world\"}\n //\n // So we know that the tag must be being generated as part of\n // choice content. Therefore, when the tag has been generated,\n // we push it onto the evaluation stack in the exact same way\n // as the string for the choice content.\n case ControlCommand.CommandType.EndTag: {\n if (this.state.inStringEvaluation) {\n let contentStackForTag: InkObject[] = [];\n let outputCountConsumed = 0;\n for (let i = this.state.outputStream.length - 1; i >= 0; --i) {\n let obj = this.state.outputStream[i];\n outputCountConsumed++;\n\n // var command = obj as ControlCommand;\n let command = asOrNull(obj, ControlCommand);\n if (command != null) {\n if (\n command.commandType == ControlCommand.CommandType.BeginTag\n ) {\n break;\n } else {\n this.Error(\n \"Unexpected ControlCommand while extracting tag from choice\"\n );\n break;\n }\n }\n if (obj instanceof StringValue) {\n contentStackForTag.push(obj);\n }\n }\n\n // Consume the content that was produced for this string\n this.state.PopFromOutputStream(outputCountConsumed);\n // Build string out of the content we collected\n let sb = new StringBuilder();\n for (let strVal of contentStackForTag.reverse()) {\n sb.Append(strVal.toString());\n }\n let choiceTag = new Tag(\n this.state.CleanOutputWhitespace(sb.toString())\n );\n // Pushing to the evaluation stack means it gets picked up\n // when a Choice is generated from the next Choice Point.\n this.state.PushEvaluationStack(choiceTag);\n } else {\n // Otherwise! Simply push EndTag, so that in the output stream we\n // have a structure of: [BeginTag, \"the tag content\", EndTag]\n this.state.PushToOutputStream(evalCommand);\n }\n break;\n }\n\n case ControlCommand.CommandType.EndString: {\n let contentStackForString: InkObject[] = [];\n let contentToRetain: InkObject[] = [];\n\n let outputCountConsumed = 0;\n for (let i = this.state.outputStream.length - 1; i >= 0; --i) {\n let obj = this.state.outputStream[i];\n\n outputCountConsumed++;\n\n // var command = obj as ControlCommand;\n let command = asOrNull(obj, ControlCommand);\n if (\n command &&\n command.commandType == ControlCommand.CommandType.BeginString\n ) {\n break;\n }\n if (obj instanceof Tag) {\n contentToRetain.push(obj);\n }\n if (obj instanceof StringValue) {\n contentStackForString.push(obj);\n }\n }\n\n // Consume the content that was produced for this string\n this.state.PopFromOutputStream(outputCountConsumed);\n\n // Rescue the tags that we want actually to keep on the output stack\n // rather than consume as part of the string we're building.\n // At the time of writing, this only applies to Tag objects generated\n // by choices, which are pushed to the stack during string generation.\n for (let rescuedTag of contentToRetain)\n this.state.PushToOutputStream(rescuedTag);\n\n // The C# version uses a Stack for contentStackForString, but we're\n // using a simple array, so we need to reverse it before using it\n contentStackForString = contentStackForString.reverse();\n\n // Build string out of the content we collected\n let sb = new StringBuilder();\n for (let c of contentStackForString) {\n sb.Append(c.toString());\n }\n\n // Return to expression evaluation (from content mode)\n this.state.inExpressionEvaluation = true;\n this.state.PushEvaluationStack(new StringValue(sb.toString()));\n break;\n }\n\n case ControlCommand.CommandType.ChoiceCount:\n let choiceCount = this.state.generatedChoices.length;\n this.state.PushEvaluationStack(new IntValue(choiceCount));\n break;\n\n case ControlCommand.CommandType.Turns:\n this.state.PushEvaluationStack(\n new IntValue(this.state.currentTurnIndex + 1)\n );\n break;\n\n case ControlCommand.CommandType.TurnsSince:\n case ControlCommand.CommandType.ReadCount:\n let target = this.state.PopEvaluationStack();\n if (!(target instanceof DivertTargetValue)) {\n let extraNote = \"\";\n if (target instanceof IntValue)\n extraNote =\n \". Did you accidentally pass a read count ('knot_name') instead of a target ('-> knot_name')?\";\n this.Error(\n \"TURNS_SINCE / READ_COUNT expected a divert target (knot, stitch, label name), but saw \" +\n target +\n extraNote\n );\n break;\n }\n\n // var divertTarget = target as DivertTargetValue;\n let divertTarget = asOrThrows(target, DivertTargetValue);\n // var container = ContentAtPath (divertTarget.targetPath).correctObj as Container;\n let container = asOrNull(\n this.ContentAtPath(divertTarget.targetPath).correctObj,\n Container\n );\n\n let eitherCount;\n if (container != null) {\n if (\n evalCommand.commandType == ControlCommand.CommandType.TurnsSince\n )\n eitherCount = this.state.TurnsSinceForContainer(container);\n else eitherCount = this.state.VisitCountForContainer(container);\n } else {\n if (\n evalCommand.commandType == ControlCommand.CommandType.TurnsSince\n )\n eitherCount = -1;\n else eitherCount = 0;\n\n this.Warning(\n \"Failed to find container for \" +\n evalCommand.toString() +\n \" lookup at \" +\n divertTarget.targetPath.toString()\n );\n }\n\n this.state.PushEvaluationStack(new IntValue(eitherCount));\n break;\n\n case ControlCommand.CommandType.Random: {\n let maxInt = asOrNull(this.state.PopEvaluationStack(), IntValue);\n let minInt = asOrNull(this.state.PopEvaluationStack(), IntValue);\n\n if (minInt == null || minInt instanceof IntValue === false)\n return this.Error(\n \"Invalid value for minimum parameter of RANDOM(min, max)\"\n );\n\n if (maxInt == null || maxInt instanceof IntValue === false)\n return this.Error(\n \"Invalid value for maximum parameter of RANDOM(min, max)\"\n );\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (maxInt.value === null) {\n return throwNullException(\"maxInt.value\");\n }\n if (minInt.value === null) {\n return throwNullException(\"minInt.value\");\n }\n\n // This code is differs a bit from the reference implementation, since\n // JavaScript has no true integers. Hence integer arithmetics and\n // interger overflows don't apply here. A loss of precision can\n // happen with big numbers however.\n //\n // The case where 'randomRange' is lower than zero is handled below,\n // so there's no need to test against Number.MIN_SAFE_INTEGER.\n let randomRange = maxInt.value - minInt.value + 1;\n if (!isFinite(randomRange) || randomRange > Number.MAX_SAFE_INTEGER) {\n randomRange = Number.MAX_SAFE_INTEGER;\n this.Error(\n \"RANDOM was called with a range that exceeds the size that ink numbers can use.\"\n );\n }\n if (randomRange <= 0)\n this.Error(\n \"RANDOM was called with minimum as \" +\n minInt.value +\n \" and maximum as \" +\n maxInt.value +\n \". The maximum must be larger\"\n );\n\n let resultSeed = this.state.storySeed + this.state.previousRandom;\n let random = new PRNG(resultSeed);\n\n let nextRandom = random.next();\n let chosenValue = (nextRandom % randomRange) + minInt.value;\n this.state.PushEvaluationStack(new IntValue(chosenValue));\n\n // Next random number (rather than keeping the Random object around)\n this.state.previousRandom = nextRandom;\n break;\n }\n\n case ControlCommand.CommandType.SeedRandom:\n let seed = asOrNull(this.state.PopEvaluationStack(), IntValue);\n if (seed == null || seed instanceof IntValue === false)\n return this.Error(\"Invalid value passed to SEED_RANDOM\");\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (seed.value === null) {\n return throwNullException(\"minInt.value\");\n }\n\n this.state.storySeed = seed.value;\n this.state.previousRandom = 0;\n\n this.state.PushEvaluationStack(new Void());\n break;\n\n case ControlCommand.CommandType.VisitIndex:\n let count =\n this.state.VisitCountForContainer(\n this.state.currentPointer.container\n ) - 1; // index not count\n this.state.PushEvaluationStack(new IntValue(count));\n break;\n\n case ControlCommand.CommandType.SequenceShuffleIndex:\n let shuffleIndex = this.NextSequenceShuffleIndex();\n this.state.PushEvaluationStack(new IntValue(shuffleIndex));\n break;\n\n case ControlCommand.CommandType.StartThread:\n // Handled in main step function\n break;\n\n case ControlCommand.CommandType.Done:\n // We may exist in the context of the initial\n // act of creating the thread, or in the context of\n // evaluating the content.\n if (this.state.callStack.canPopThread) {\n this.state.callStack.PopThread();\n }\n\n // In normal flow - allow safe exit without warning\n else {\n this.state.didSafeExit = true;\n\n // Stop flow in current thread\n this.state.currentPointer = Pointer.Null;\n }\n\n break;\n\n // Force flow to end completely\n case ControlCommand.CommandType.End:\n this.state.ForceEnd();\n break;\n\n case ControlCommand.CommandType.ListFromInt:\n // var intVal = state.PopEvaluationStack () as IntValue;\n let intVal = asOrNull(this.state.PopEvaluationStack(), IntValue);\n // var listNameVal = state.PopEvaluationStack () as StringValue;\n let listNameVal = asOrThrows(\n this.state.PopEvaluationStack(),\n StringValue\n );\n\n if (intVal === null) {\n throw new StoryException(\n \"Passed non-integer when creating a list element from a numerical value.\"\n );\n }\n\n let generatedListValue = null;\n\n if (this.listDefinitions === null) {\n return throwNullException(\"this.listDefinitions\");\n }\n let foundListDef = this.listDefinitions.TryListGetDefinition(\n listNameVal.value,\n null\n );\n if (foundListDef.exists) {\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (intVal.value === null) {\n return throwNullException(\"minInt.value\");\n }\n\n let foundItem = foundListDef.result!.TryGetItemWithValue(\n intVal.value,\n InkListItem.Null\n );\n if (foundItem.exists) {\n generatedListValue = new ListValue(\n foundItem.result!,\n intVal.value\n );\n }\n } else {\n throw new StoryException(\n \"Failed to find LIST called \" + listNameVal.value\n );\n }\n\n if (generatedListValue == null) generatedListValue = new ListValue();\n\n this.state.PushEvaluationStack(generatedListValue);\n break;\n\n case ControlCommand.CommandType.ListRange:\n let max = asOrNull(this.state.PopEvaluationStack(), Value);\n let min = asOrNull(this.state.PopEvaluationStack(), Value);\n\n // var targetList = state.PopEvaluationStack () as ListValue;\n let targetList = asOrNull(this.state.PopEvaluationStack(), ListValue);\n\n if (targetList === null || min === null || max === null)\n throw new StoryException(\n \"Expected list, minimum and maximum for LIST_RANGE\"\n );\n\n if (targetList.value === null) {\n return throwNullException(\"targetList.value\");\n }\n let result = targetList.value.ListWithSubRange(\n min.valueObject,\n max.valueObject\n );\n\n this.state.PushEvaluationStack(new ListValue(result));\n break;\n\n case ControlCommand.CommandType.ListRandom: {\n let listVal = this.state.PopEvaluationStack() as ListValue;\n if (listVal === null)\n throw new StoryException(\"Expected list for LIST_RANDOM\");\n\n let list = listVal.value;\n\n let newList: InkList | null = null;\n\n if (list === null) {\n throw throwNullException(\"list\");\n }\n if (list.Count == 0) {\n newList = new InkList();\n } else {\n // Generate a random index for the element to take\n let resultSeed = this.state.storySeed + this.state.previousRandom;\n let random = new PRNG(resultSeed);\n\n let nextRandom = random.next();\n let listItemIndex = nextRandom % list.Count;\n\n // This bit is a little different from the original\n // C# code, since iterators do not work in the same way.\n // First, we iterate listItemIndex - 1 times, calling next().\n // The listItemIndex-th time is made outside of the loop,\n // in order to retrieve the value.\n let listEnumerator = list.entries();\n for (let i = 0; i <= listItemIndex - 1; i++) {\n listEnumerator.next();\n }\n let value = listEnumerator.next().value;\n let randomItem: KeyValuePair = {\n Key: InkListItem.fromSerializedKey(value[0]),\n Value: value[1],\n };\n\n // Origin list is simply the origin of the one element\n if (randomItem.Key.originName === null) {\n return throwNullException(\"randomItem.Key.originName\");\n }\n newList = new InkList(randomItem.Key.originName, this);\n newList.Add(randomItem.Key, randomItem.Value);\n\n this.state.previousRandom = nextRandom;\n }\n\n this.state.PushEvaluationStack(new ListValue(newList));\n break;\n }\n\n default:\n this.Error(\"unhandled ControlCommand: \" + evalCommand);\n break;\n }\n\n return true;\n }\n\n // Variable assignment\n else if (contentObj instanceof VariableAssignment) {\n let varAss = contentObj;\n let assignedVal = this.state.PopEvaluationStack();\n\n this.state.variablesState.Assign(varAss, assignedVal);\n\n return true;\n }\n\n // Variable reference\n else if (contentObj instanceof VariableReference) {\n let varRef = contentObj;\n let foundValue = null;\n\n // Explicit read count value\n if (varRef.pathForCount != null) {\n let container = varRef.containerForCount;\n let count = this.state.VisitCountForContainer(container);\n foundValue = new IntValue(count);\n }\n\n // Normal variable reference\n else {\n foundValue = this.state.variablesState.GetVariableWithName(varRef.name);\n\n if (foundValue == null) {\n this.Warning(\n \"Variable not found: '\" +\n varRef.name +\n \"'. Using default value of 0 (false). This can happen with temporary variables if the declaration hasn't yet been hit. Globals are always given a default value on load if a value doesn't exist in the save state.\"\n );\n foundValue = new IntValue(0);\n }\n }\n\n this.state.PushEvaluationStack(foundValue);\n\n return true;\n }\n\n // Native function call\n else if (contentObj instanceof NativeFunctionCall) {\n let func = contentObj;\n let funcParams = this.state.PopEvaluationStack(func.numberOfParameters);\n let result = func.Call(funcParams);\n this.state.PushEvaluationStack(result);\n return true;\n }\n\n // No control content, must be ordinary content\n return false;\n }\n\n public ChoosePathString(\n path: string,\n resetCallstack = true,\n args: any[] = []\n ) {\n this.IfAsyncWeCant(\"call ChoosePathString right now\");\n if (this.onChoosePathString !== null) this.onChoosePathString(path, args);\n\n if (resetCallstack) {\n this.ResetCallstack();\n } else {\n if (this.state.callStack.currentElement.type == PushPopType.Function) {\n let funcDetail = \"\";\n let container =\n this.state.callStack.currentElement.currentPointer.container;\n if (container != null) {\n funcDetail = \"(\" + container.path.toString() + \") \";\n }\n throw new Error(\n \"Story was running a function \" +\n funcDetail +\n \"when you called ChoosePathString(\" +\n path +\n \") - this is almost certainly not not what you want! Full stack trace: \\n\" +\n this.state.callStack.callStackTrace\n );\n }\n }\n\n this.state.PassArgumentsToEvaluationStack(args);\n this.ChoosePath(new Path(path));\n }\n\n public IfAsyncWeCant(activityStr: string) {\n if (this._asyncContinueActive)\n throw new Error(\n \"Can't \" +\n activityStr +\n \". Story is in the middle of a ContinueAsync(). Make more ContinueAsync() calls or a single Continue() call beforehand.\"\n );\n }\n\n public ChoosePath(p: Path, incrementingTurnIndex: boolean = true) {\n this.state.SetChosenPath(p, incrementingTurnIndex);\n\n // Take a note of newly visited containers for read counts etc\n this.VisitChangedContainersDueToDivert();\n }\n\n public ChooseChoiceIndex(choiceIdx: number) {\n choiceIdx = choiceIdx;\n let choices = this.currentChoices;\n this.Assert(\n choiceIdx >= 0 && choiceIdx < choices.length,\n \"choice out of range\"\n );\n\n let choiceToChoose = choices[choiceIdx];\n if (this.onMakeChoice !== null) this.onMakeChoice(choiceToChoose);\n\n if (choiceToChoose.threadAtGeneration === null) {\n return throwNullException(\"choiceToChoose.threadAtGeneration\");\n }\n if (choiceToChoose.targetPath === null) {\n return throwNullException(\"choiceToChoose.targetPath\");\n }\n\n this.state.callStack.currentThread = choiceToChoose.threadAtGeneration;\n\n this.ChoosePath(choiceToChoose.targetPath);\n }\n\n public HasFunction(functionName: string) {\n try {\n return this.KnotContainerWithName(functionName) != null;\n } catch (e) {\n return false;\n }\n }\n\n public EvaluateFunction(\n functionName: string,\n args: any[] = [],\n returnTextOutput: boolean = false\n ): Story.EvaluateFunctionTextOutput | any {\n // EvaluateFunction behaves slightly differently than the C# version.\n // In C#, you can pass a (second) parameter `out textOutput` to get the\n // text outputted by the function. This is not possible in js. Instead,\n // we maintain the regular signature (functionName, args), plus an\n // optional third parameter returnTextOutput. If set to true, we will\n // return both the textOutput and the returned value, as an object.\n\n if (this.onEvaluateFunction !== null)\n this.onEvaluateFunction(functionName, args);\n\n this.IfAsyncWeCant(\"evaluate a function\");\n\n if (functionName == null) {\n throw new Error(\"Function is null\");\n } else if (functionName == \"\" || functionName.trim() == \"\") {\n throw new Error(\"Function is empty or white space.\");\n }\n\n let funcContainer = this.KnotContainerWithName(functionName);\n if (funcContainer == null) {\n throw new Error(\"Function doesn't exist: '\" + functionName + \"'\");\n }\n\n let outputStreamBefore: InkObject[] = [];\n outputStreamBefore.push(...this.state.outputStream);\n this._state.ResetOutput();\n\n this.state.StartFunctionEvaluationFromGame(funcContainer, args);\n\n // Evaluate the function, and collect the string output\n let stringOutput = new StringBuilder();\n while (this.canContinue) {\n stringOutput.Append(this.Continue());\n }\n let textOutput = stringOutput.toString();\n\n this._state.ResetOutput(outputStreamBefore);\n\n let result = this.state.CompleteFunctionEvaluationFromGame();\n if (this.onCompleteEvaluateFunction != null)\n this.onCompleteEvaluateFunction(functionName, args, textOutput, result);\n\n return returnTextOutput ? { returned: result, output: textOutput } : result;\n }\n\n public EvaluateExpression(exprContainer: Container) {\n let startCallStackHeight = this.state.callStack.elements.length;\n\n this.state.callStack.Push(PushPopType.Tunnel);\n\n this._temporaryEvaluationContainer = exprContainer;\n\n this.state.GoToStart();\n\n let evalStackHeight = this.state.evaluationStack.length;\n\n this.Continue();\n\n this._temporaryEvaluationContainer = null;\n\n // Should have fallen off the end of the Container, which should\n // have auto-popped, but just in case we didn't for some reason,\n // manually pop to restore the state (including currentPath).\n if (this.state.callStack.elements.length > startCallStackHeight) {\n this.state.PopCallStack();\n }\n\n let endStackHeight = this.state.evaluationStack.length;\n if (endStackHeight > evalStackHeight) {\n return this.state.PopEvaluationStack();\n } else {\n return null;\n }\n }\n\n public allowExternalFunctionFallbacks: boolean = false;\n\n public CallExternalFunction(\n funcName: string | null,\n numberOfArguments: number\n ) {\n if (funcName === null) {\n return throwNullException(\"funcName\");\n }\n let funcDef = this._externals.get(funcName);\n let fallbackFunctionContainer = null;\n\n let foundExternal = typeof funcDef !== \"undefined\";\n\n if (\n foundExternal &&\n !funcDef!.lookAheadSafe &&\n this._stateSnapshotAtLastNewline !== null\n ) {\n this._sawLookaheadUnsafeFunctionAfterNewline = true;\n return;\n }\n\n if (!foundExternal) {\n if (this.allowExternalFunctionFallbacks) {\n fallbackFunctionContainer = this.KnotContainerWithName(funcName);\n this.Assert(\n fallbackFunctionContainer !== null,\n \"Trying to call EXTERNAL function '\" +\n funcName +\n \"' which has not been bound, and fallback ink function could not be found.\"\n );\n\n // Divert direct into fallback function and we're done\n this.state.callStack.Push(\n PushPopType.Function,\n undefined,\n this.state.outputStream.length\n );\n this.state.divertedPointer = Pointer.StartOf(fallbackFunctionContainer);\n return;\n } else {\n this.Assert(\n false,\n \"Trying to call EXTERNAL function '\" +\n funcName +\n \"' which has not been bound (and ink fallbacks disabled).\"\n );\n }\n }\n\n // Pop arguments\n let args: any[] = [];\n for (let i = 0; i < numberOfArguments; ++i) {\n // var poppedObj = state.PopEvaluationStack () as Value;\n let poppedObj = asOrThrows(this.state.PopEvaluationStack(), Value);\n let valueObj = poppedObj.valueObject;\n args.push(valueObj);\n }\n\n // Reverse arguments from the order they were popped,\n // so they're the right way round again.\n args.reverse();\n\n // Run the function!\n let funcResult = funcDef!.function(args);\n\n // Convert return value (if any) to the a type that the ink engine can use\n let returnObj = null;\n if (funcResult != null) {\n returnObj = Value.Create(funcResult);\n this.Assert(\n returnObj !== null,\n \"Could not create ink value from returned object of type \" +\n typeof funcResult\n );\n } else {\n returnObj = new Void();\n }\n\n this.state.PushEvaluationStack(returnObj);\n }\n\n public BindExternalFunctionGeneral(\n funcName: string,\n func: Story.ExternalFunction,\n lookaheadSafe: boolean = true\n ) {\n this.IfAsyncWeCant(\"bind an external function\");\n this.Assert(\n !this._externals.has(funcName),\n \"Function '\" + funcName + \"' has already been bound.\"\n );\n this._externals.set(funcName, {\n function: func,\n lookAheadSafe: lookaheadSafe,\n });\n }\n\n public TryCoerce(value: any) {\n // We're skipping type coercition in this implementation. First of, js\n // is loosely typed, so it's not that important. Secondly, there is no\n // clean way (AFAIK) for the user to describe what type of parameters\n // they expect.\n return value;\n }\n\n public BindExternalFunction(\n funcName: string,\n func: Story.ExternalFunction,\n lookaheadSafe: boolean = false\n ) {\n this.Assert(func != null, \"Can't bind a null function\");\n\n this.BindExternalFunctionGeneral(\n funcName,\n (args: any) => {\n this.Assert(\n args.length >= func.length,\n \"External function expected \" + func.length + \" arguments\"\n );\n\n let coercedArgs = [];\n for (let i = 0, l = args.length; i < l; i++) {\n coercedArgs[i] = this.TryCoerce(args[i]);\n }\n return func.apply(null, coercedArgs);\n },\n lookaheadSafe\n );\n }\n\n public UnbindExternalFunction(funcName: string) {\n this.IfAsyncWeCant(\"unbind an external a function\");\n this.Assert(\n this._externals.has(funcName),\n \"Function '\" + funcName + \"' has not been bound.\"\n );\n this._externals.delete(funcName);\n }\n\n public ValidateExternalBindings(): void;\n public ValidateExternalBindings(\n c: Container | null,\n missingExternals: Set\n ): void;\n public ValidateExternalBindings(\n o: InkObject | null,\n missingExternals: Set\n ): void;\n public ValidateExternalBindings() {\n let c: Container | null = null;\n let o: InkObject | null = null;\n let missingExternals: Set = arguments[1] || new Set();\n\n if (arguments[0] instanceof Container) {\n c = arguments[0];\n }\n\n if (arguments[0] instanceof InkObject) {\n o = arguments[0];\n }\n\n if (c === null && o === null) {\n this.ValidateExternalBindings(\n this._mainContentContainer,\n missingExternals\n );\n this._hasValidatedExternals = true;\n\n // No problem! Validation complete\n if (missingExternals.size == 0) {\n this._hasValidatedExternals = true;\n } else {\n let message = \"Error: Missing function binding for external\";\n message += missingExternals.size > 1 ? \"s\" : \"\";\n message += \": '\";\n message += Array.from(missingExternals).join(\"', '\");\n message += \"' \";\n message += this.allowExternalFunctionFallbacks\n ? \", and no fallback ink function found.\"\n : \" (ink fallbacks disabled)\";\n\n this.Error(message);\n }\n } else if (c != null) {\n for (let innerContent of c.content) {\n let container = innerContent as Container;\n if (container == null || !container.hasValidName)\n this.ValidateExternalBindings(innerContent, missingExternals);\n }\n for (let [, value] of c.namedContent) {\n this.ValidateExternalBindings(\n asOrNull(value, InkObject),\n missingExternals\n );\n }\n } else if (o != null) {\n let divert = asOrNull(o, Divert);\n if (divert && divert.isExternal) {\n let name = divert.targetPathString;\n if (name === null) {\n return throwNullException(\"name\");\n }\n if (!this._externals.has(name)) {\n if (this.allowExternalFunctionFallbacks) {\n let fallbackFound =\n this.mainContentContainer.namedContent.has(name);\n if (!fallbackFound) {\n missingExternals.add(name);\n }\n } else {\n missingExternals.add(name);\n }\n }\n }\n }\n }\n\n public ObserveVariable(\n variableName: string,\n observer: Story.VariableObserver\n ) {\n this.IfAsyncWeCant(\"observe a new variable\");\n\n if (this._variableObservers === null) this._variableObservers = new Map();\n\n if (!this.state.variablesState.GlobalVariableExistsWithName(variableName))\n throw new Error(\n \"Cannot observe variable '\" +\n variableName +\n \"' because it wasn't declared in the ink story.\"\n );\n\n if (this._variableObservers.has(variableName)) {\n this._variableObservers.get(variableName)!.push(observer);\n } else {\n this._variableObservers.set(variableName, [observer]);\n }\n }\n\n public ObserveVariables(\n variableNames: string[],\n observers: Story.VariableObserver[]\n ) {\n for (let i = 0, l = variableNames.length; i < l; i++) {\n this.ObserveVariable(variableNames[i], observers[i]);\n }\n }\n\n public RemoveVariableObserver(\n observer?: Story.VariableObserver,\n specificVariableName?: string\n ) {\n // A couple of things to know about this method:\n //\n // 1. Since `RemoveVariableObserver` is exposed to the JavaScript world,\n // optionality is marked as `undefined` rather than `null`.\n // To keep things simple, null-checks are performed using regular\n // equality operators, where undefined == null.\n //\n // 2. Since C# delegates are translated to arrays of functions,\n // -= becomes a call to splice and null-checks are replaced by\n // emptiness-checks.\n //\n this.IfAsyncWeCant(\"remove a variable observer\");\n\n if (this._variableObservers === null) return;\n\n if (specificVariableName != null) {\n if (this._variableObservers.has(specificVariableName)) {\n if (observer != null) {\n let variableObservers =\n this._variableObservers.get(specificVariableName);\n if (variableObservers != null) {\n variableObservers.splice(variableObservers.indexOf(observer), 1);\n if (variableObservers.length === 0) {\n this._variableObservers.delete(specificVariableName);\n }\n }\n } else {\n this._variableObservers.delete(specificVariableName);\n }\n }\n } else if (observer != null) {\n let keys = this._variableObservers.keys();\n for (let varName of keys) {\n let variableObservers = this._variableObservers.get(varName);\n if (variableObservers != null) {\n variableObservers.splice(variableObservers.indexOf(observer), 1);\n if (variableObservers.length === 0) {\n this._variableObservers.delete(varName);\n }\n }\n }\n }\n }\n\n public VariableStateDidChangeEvent(\n variableName: string,\n newValueObj: InkObject\n ) {\n if (this._variableObservers === null) return;\n\n let observers = this._variableObservers.get(variableName);\n if (typeof observers !== \"undefined\") {\n if (!(newValueObj instanceof Value)) {\n throw new Error(\n \"Tried to get the value of a variable that isn't a standard type\"\n );\n }\n // var val = newValueObj as Value;\n let val = asOrThrows(newValueObj, Value);\n\n for (let observer of observers) {\n observer(variableName, val.valueObject);\n }\n }\n }\n\n get globalTags() {\n return this.TagsAtStartOfFlowContainerWithPathString(\"\");\n }\n\n public TagsForContentAtPath(path: string) {\n return this.TagsAtStartOfFlowContainerWithPathString(path);\n }\n\n public TagsAtStartOfFlowContainerWithPathString(pathString: string) {\n let path = new Path(pathString);\n\n let flowContainer = this.ContentAtPath(path).container;\n if (flowContainer === null) {\n return throwNullException(\"flowContainer\");\n }\n while (true) {\n let firstContent: InkObject = flowContainer.content[0];\n if (firstContent instanceof Container) flowContainer = firstContent;\n else break;\n }\n\n let inTag = false;\n let tags: string[] | null = null;\n\n for (let c of flowContainer.content) {\n // var tag = c as Runtime.Tag;\n let command = asOrNull(c, ControlCommand);\n\n if (command != null) {\n if (command.commandType == ControlCommand.CommandType.BeginTag) {\n inTag = true;\n } else if (command.commandType == ControlCommand.CommandType.EndTag) {\n inTag = false;\n }\n } else if (inTag) {\n let str = asOrNull(c, StringValue);\n if (str !== null) {\n if (tags === null) tags = [];\n if (str.value !== null) tags.push(str.value);\n } else {\n this.Error(\n \"Tag contained non-text content. Only plain text is allowed when using globalTags or TagsAtContentPath. If you want to evaluate dynamic content, you need to use story.Continue().\"\n );\n }\n } else {\n break;\n }\n }\n\n return tags;\n }\n\n public BuildStringOfHierarchy() {\n let sb = new StringBuilder();\n\n this.mainContentContainer.BuildStringOfHierarchy(\n sb,\n 0,\n this.state.currentPointer.Resolve()\n );\n\n return sb.toString();\n }\n\n public BuildStringOfContainer(container: Container) {\n let sb = new StringBuilder();\n container.BuildStringOfHierarchy(\n sb,\n 0,\n this.state.currentPointer.Resolve()\n );\n return sb.toString();\n }\n\n public NextContent() {\n this.state.previousPointer = this.state.currentPointer.copy();\n\n if (!this.state.divertedPointer.isNull) {\n this.state.currentPointer = this.state.divertedPointer.copy();\n this.state.divertedPointer = Pointer.Null;\n\n this.VisitChangedContainersDueToDivert();\n\n if (!this.state.currentPointer.isNull) {\n return;\n }\n }\n\n let successfulPointerIncrement = this.IncrementContentPointer();\n\n if (!successfulPointerIncrement) {\n let didPop = false;\n\n if (this.state.callStack.CanPop(PushPopType.Function)) {\n this.state.PopCallStack(PushPopType.Function);\n\n if (this.state.inExpressionEvaluation) {\n this.state.PushEvaluationStack(new Void());\n }\n\n didPop = true;\n } else if (this.state.callStack.canPopThread) {\n this.state.callStack.PopThread();\n\n didPop = true;\n } else {\n this.state.TryExitFunctionEvaluationFromGame();\n }\n\n if (didPop && !this.state.currentPointer.isNull) {\n this.NextContent();\n }\n }\n }\n\n public IncrementContentPointer() {\n let successfulIncrement = true;\n\n let pointer = this.state.callStack.currentElement.currentPointer.copy();\n pointer.index++;\n\n if (pointer.container === null) {\n return throwNullException(\"pointer.container\");\n }\n while (pointer.index >= pointer.container.content.length) {\n successfulIncrement = false;\n\n // Container nextAncestor = pointer.container.parent as Container;\n let nextAncestor = asOrNull(pointer.container.parent, Container);\n if (nextAncestor instanceof Container === false) {\n break;\n }\n\n let indexInAncestor = nextAncestor!.content.indexOf(pointer.container);\n if (indexInAncestor == -1) {\n break;\n }\n\n pointer = new Pointer(nextAncestor, indexInAncestor);\n\n pointer.index++;\n\n successfulIncrement = true;\n if (pointer.container === null) {\n return throwNullException(\"pointer.container\");\n }\n }\n\n if (!successfulIncrement) pointer = Pointer.Null;\n\n this.state.callStack.currentElement.currentPointer = pointer.copy();\n\n return successfulIncrement;\n }\n\n public TryFollowDefaultInvisibleChoice() {\n let allChoices = this._state.currentChoices;\n\n let invisibleChoices = allChoices.filter((c) => c.isInvisibleDefault);\n\n if (\n invisibleChoices.length == 0 ||\n allChoices.length > invisibleChoices.length\n )\n return false;\n\n let choice = invisibleChoices[0];\n\n if (choice.targetPath === null) {\n return throwNullException(\"choice.targetPath\");\n }\n\n if (choice.threadAtGeneration === null) {\n return throwNullException(\"choice.threadAtGeneration\");\n }\n\n this.state.callStack.currentThread = choice.threadAtGeneration;\n\n if (this._stateSnapshotAtLastNewline !== null) {\n this.state.callStack.currentThread = this.state.callStack.ForkThread();\n }\n\n this.ChoosePath(choice.targetPath, false);\n\n return true;\n }\n\n public NextSequenceShuffleIndex() {\n // var numElementsIntVal = state.PopEvaluationStack () as IntValue;\n let numElementsIntVal = asOrNull(this.state.PopEvaluationStack(), IntValue);\n if (!(numElementsIntVal instanceof IntValue)) {\n this.Error(\"expected number of elements in sequence for shuffle index\");\n return 0;\n }\n\n let seqContainer = this.state.currentPointer.container;\n if (seqContainer === null) {\n return throwNullException(\"seqContainer\");\n }\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (numElementsIntVal.value === null) {\n return throwNullException(\"numElementsIntVal.value\");\n }\n let numElements = numElementsIntVal.value;\n\n // var seqCountVal = state.PopEvaluationStack () as IntValue;\n let seqCountVal = asOrThrows(this.state.PopEvaluationStack(), IntValue);\n let seqCount = seqCountVal.value;\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (seqCount === null) {\n return throwNullException(\"seqCount\");\n }\n\n let loopIndex = seqCount / numElements;\n let iterationIndex = seqCount % numElements;\n\n let seqPathStr = seqContainer.path.toString();\n let sequenceHash = 0;\n for (let i = 0, l = seqPathStr.length; i < l; i++) {\n sequenceHash += seqPathStr.charCodeAt(i) || 0;\n }\n let randomSeed = sequenceHash + loopIndex + this.state.storySeed;\n let random = new PRNG(Math.floor(randomSeed));\n\n let unpickedIndices = [];\n for (let i = 0; i < numElements; ++i) {\n unpickedIndices.push(i);\n }\n\n for (let i = 0; i <= iterationIndex; ++i) {\n let chosen = random.next() % unpickedIndices.length;\n let chosenIndex = unpickedIndices[chosen];\n unpickedIndices.splice(chosen, 1);\n\n if (i == iterationIndex) {\n return chosenIndex;\n }\n }\n\n throw new Error(\"Should never reach here\");\n }\n\n public Error(message: string, useEndLineNumber = false): never {\n let e = new StoryException(message);\n e.useEndLineNumber = useEndLineNumber;\n throw e;\n }\n\n public Warning(message: string) {\n this.AddError(message, true);\n }\n\n public AddError(\n message: string,\n isWarning = false,\n useEndLineNumber = false\n ) {\n let dm = this.currentDebugMetadata;\n\n let errorTypeStr = isWarning ? \"WARNING\" : \"ERROR\";\n\n if (dm != null) {\n let lineNum = useEndLineNumber ? dm.endLineNumber : dm.startLineNumber;\n message =\n \"RUNTIME \" +\n errorTypeStr +\n \": '\" +\n dm.fileName +\n \"' line \" +\n lineNum +\n \": \" +\n message;\n } else if (!this.state.currentPointer.isNull) {\n message =\n \"RUNTIME \" +\n errorTypeStr +\n \": (\" +\n this.state.currentPointer +\n \"): \" +\n message;\n } else {\n message = \"RUNTIME \" + errorTypeStr + \": \" + message;\n }\n\n this.state.AddError(message, isWarning);\n\n // In a broken state don't need to know about any other errors.\n if (!isWarning) this.state.ForceEnd();\n }\n\n public Assert(condition: boolean, message: string | null = null) {\n if (condition == false) {\n if (message == null) {\n message = \"Story assert\";\n }\n\n throw new Error(message + \" \" + this.currentDebugMetadata);\n }\n }\n\n get currentDebugMetadata(): DebugMetadata | null {\n let dm: DebugMetadata | null;\n\n let pointer = this.state.currentPointer;\n if (!pointer.isNull && pointer.Resolve() !== null) {\n dm = pointer.Resolve()!.debugMetadata;\n if (dm !== null) {\n return dm;\n }\n }\n\n for (let i = this.state.callStack.elements.length - 1; i >= 0; --i) {\n pointer = this.state.callStack.elements[i].currentPointer;\n if (!pointer.isNull && pointer.Resolve() !== null) {\n dm = pointer.Resolve()!.debugMetadata;\n if (dm !== null) {\n return dm;\n }\n }\n }\n\n for (let i = this.state.outputStream.length - 1; i >= 0; --i) {\n let outputObj = this.state.outputStream[i];\n dm = outputObj.debugMetadata;\n if (dm !== null) {\n return dm;\n }\n }\n\n return null;\n }\n\n get mainContentContainer() {\n if (this._temporaryEvaluationContainer) {\n return this._temporaryEvaluationContainer;\n } else {\n return this._mainContentContainer;\n }\n }\n\n /**\n * `_mainContentContainer` is almost guaranteed to be set in the\n * constructor, unless the json is malformed.\n */\n private _mainContentContainer!: Container;\n private _listDefinitions: ListDefinitionsOrigin | null = null;\n\n private _externals: Map;\n private _variableObservers: Map | null =\n null;\n private _hasValidatedExternals: boolean = false;\n\n private _temporaryEvaluationContainer: Container | null = null;\n\n /**\n * `state` is almost guaranteed to be set in the constructor, unless\n * using the compiler-specific constructor which will likely not be used in\n * the real world.\n */\n private _state!: StoryState;\n\n private _asyncContinueActive: boolean = false;\n private _stateSnapshotAtLastNewline: StoryState | null = null;\n private _sawLookaheadUnsafeFunctionAfterNewline: boolean = false;\n\n private _recursiveContinueCount: number = 0;\n\n private _asyncSaving: boolean = false;\n\n private _profiler: any | null = null; // TODO: Profiler\n}\n\nexport namespace Story {\n export enum OutputStateChange {\n NoChange = 0,\n ExtendedBeyondNewline = 1,\n NewlineRemoved = 2,\n }\n\n export interface EvaluateFunctionTextOutput {\n returned: any;\n output: string;\n }\n\n export interface ExternalFunctionDef {\n function: ExternalFunction;\n lookAheadSafe: boolean;\n }\n\n export type VariableObserver = (variableName: string, newValue: any) => void;\n export type ExternalFunction = (...args: any) => any;\n}\n","import { AuthorWarning } from \"./AuthorWarning\";\nimport { ConstantDeclaration } from \"./Declaration/ConstantDeclaration\";\nimport { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../engine/ControlCommand\";\nimport { ErrorHandler } from \"../../../engine/Error\";\nimport { ErrorType } from \"../ErrorType\";\nimport { Expression } from \"./Expression/Expression\";\nimport { ExternalDeclaration } from \"./Declaration/ExternalDeclaration\";\nimport { FlowBase } from \"./Flow/FlowBase\";\nimport { FlowLevel } from \"./Flow/FlowLevel\";\nimport { IncludedFile } from \"./IncludedFile\";\nimport { ListDefinition } from \"./List/ListDefinition\";\nimport { ListElementDefinition } from \"./List/ListElementDefinition\";\nimport { ParsedObject } from \"./Object\";\nimport { Story as RuntimeStory } from \"../../../engine/Story\";\nimport { SymbolType } from \"./SymbolType\";\nimport { Text } from \"./Text\";\nimport { VariableAssignment as RuntimeVariableAssignment } from \"../../../engine/VariableAssignment\";\nimport { Identifier } from \"./Identifier\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\nimport { ClosestFlowBase } from \"./Flow/ClosestFlowBase\";\nimport { FunctionCall } from \"./FunctionCall\";\nimport { Path } from \"./Path\";\nimport { VariableAssignment } from \"./Variable/VariableAssignment\";\n\nexport class Story extends FlowBase {\n public static readonly IsReservedKeyword = (name?: string): boolean => {\n switch (name) {\n case \"true\":\n case \"false\":\n case \"not\":\n case \"return\":\n case \"else\":\n case \"VAR\":\n case \"CONST\":\n case \"temp\":\n case \"LIST\":\n case \"function\":\n return true;\n }\n\n return false;\n };\n\n private _errorHandler: ErrorHandler | null = null;\n private _hadError: boolean = false;\n private _hadWarning: boolean = false;\n private _dontFlattenContainers: Set = new Set();\n private _listDefs: Map = new Map();\n\n get flowLevel(): FlowLevel {\n return FlowLevel.Story;\n }\n\n get hadError(): boolean {\n return this._hadError;\n }\n\n get hadWarning(): boolean {\n return this._hadWarning;\n }\n\n public constants: Map = new Map();\n public externals: Map = new Map();\n\n // Build setting for exporting:\n // When true, the visit count for *all* knots, stitches, choices,\n // and gathers is counted. When false, only those that are direclty\n // referenced by the ink are recorded. Use this flag to allow game-side\n // querying of arbitrary knots/stitches etc.\n // Storing all counts is more robust and future proof (updates to the story file\n // that reference previously uncounted visits are possible, but generates a much\n // larger safe file, with a lot of potentially redundant counts.\n public countAllVisits: boolean = false;\n\n constructor(toplevelObjects: ParsedObject[], isInclude: boolean = false) {\n // Don't do anything much on construction, leave it lightweight until\n // the ExportRuntime method is called.\n super(null, toplevelObjects, null, false, isInclude);\n }\n\n get typeName(): string {\n return \"Story\";\n }\n\n // Before this function is called, we have IncludedFile objects interspersed\n // in our content wherever an include statement was.\n // So that the include statement can be added in a sensible place (e.g. the\n // top of the file) without side-effects of jumping into a knot that was\n // defined in that include, we separate knots and stitches from anything\n // else defined at the top scope of the included file.\n //\n // Algorithm: For each IncludedFile we find, split its contents into\n // knots/stiches and any other content. Insert the normal content wherever\n // the include statement was, and append the knots/stitches to the very\n // end of the main story.\n public PreProcessTopLevelObjects(topLevelContent: ParsedObject[]): void {\n super.PreProcessTopLevelObjects(topLevelContent);\n\n const flowsFromOtherFiles = [];\n\n // Inject included files\n for (let obj of topLevelContent) {\n if (obj instanceof IncludedFile) {\n const file: IncludedFile = obj;\n\n // Remove the IncludedFile itself\n const posOfObj = topLevelContent.indexOf(obj);\n topLevelContent.splice(posOfObj, 1);\n\n // When an included story fails to load, the include\n // line itself is still valid, so we have to handle it here\n if (file.includedStory) {\n const nonFlowContent: ParsedObject[] = [];\n const subStory = file.includedStory;\n // Allow empty file\n if (subStory.content != null) {\n for (const subStoryObj of subStory.content) {\n if (subStoryObj instanceof FlowBase) {\n flowsFromOtherFiles.push(subStoryObj);\n } else {\n nonFlowContent.push(subStoryObj);\n }\n }\n\n // Add newline on the end of the include\n nonFlowContent.push(new Text(\"\\n\"));\n\n // Add contents of the file in its place\n topLevelContent.splice(posOfObj, 0, ...nonFlowContent);\n\n // Skip past the content of this sub story\n // (since it will already have recursively included\n // any lines from other files)\n }\n }\n\n // Include object has been removed, with possible content inserted,\n // and position of 'i' will have been determined already.\n continue;\n }\n }\n\n // Add the flows we collected from the included files to the\n // end of our list of our content\n topLevelContent.splice(0, 0, ...flowsFromOtherFiles);\n }\n\n public readonly ExportRuntime = (\n errorHandler: ErrorHandler | null = null\n ): RuntimeStory | null => {\n this._errorHandler = errorHandler;\n\n // Find all constants before main export begins, so that VariableReferences know\n // whether to generate a runtime variable reference or the literal value\n this.constants = new Map();\n for (const constDecl of this.FindAll(ConstantDeclaration)()) {\n // Check for duplicate definitions\n const existingDefinition: Expression = this.constants.get(\n constDecl.constantName!\n ) as any;\n\n if (existingDefinition) {\n if (!existingDefinition.Equals(constDecl.expression)) {\n const errorMsg = `CONST '${constDecl.constantName}' has been redefined with a different value. Multiple definitions of the same CONST are valid so long as they contain the same value. Initial definition was on ${existingDefinition.debugMetadata}.`;\n this.Error(errorMsg, constDecl, false);\n }\n }\n\n this.constants.set(constDecl.constantName!, constDecl.expression);\n }\n\n // List definitions are treated like constants too - they should be usable\n // from other variable declarations.\n this._listDefs = new Map();\n for (const listDef of this.FindAll(ListDefinition)()) {\n if (listDef.identifier?.name) {\n this._listDefs.set(listDef.identifier?.name, listDef);\n }\n }\n\n this.externals = new Map();\n\n // Resolution of weave point names has to come first, before any runtime code generation\n // since names have to be ready before diverts start getting created.\n // (It used to be done in the constructor for a weave, but didn't allow us to generate\n // errors when name resolution failed.)\n this.ResolveWeavePointNaming();\n\n // Get default implementation of runtimeObject, which calls ContainerBase's generation method\n const rootContainer = this.runtimeObject as RuntimeContainer;\n\n // Export initialisation of global variables\n // TODO: We *could* add this as a declarative block to the story itself...\n const variableInitialisation = new RuntimeContainer();\n variableInitialisation.AddContent(RuntimeControlCommand.EvalStart());\n\n // Global variables are those that are local to the story and marked as global\n const runtimeLists = [];\n for (const [key, value] of this.variableDeclarations) {\n if (value.isGlobalDeclaration) {\n if (value.listDefinition) {\n this._listDefs.set(key, value.listDefinition);\n variableInitialisation.AddContent(\n value.listDefinition.runtimeObject!\n );\n\n runtimeLists.push(value.listDefinition.runtimeListDefinition);\n } else {\n if (!value.expression) {\n throw new Error();\n }\n value.expression.GenerateIntoContainer(variableInitialisation);\n }\n\n const runtimeVarAss = new RuntimeVariableAssignment(key, true);\n runtimeVarAss.isGlobal = true;\n variableInitialisation.AddContent(runtimeVarAss);\n }\n }\n\n variableInitialisation.AddContent(RuntimeControlCommand.EvalEnd());\n variableInitialisation.AddContent(RuntimeControlCommand.End());\n\n if (this.variableDeclarations.size > 0) {\n variableInitialisation.name = \"global decl\";\n rootContainer.AddToNamedContentOnly(variableInitialisation);\n }\n\n // Signal that it's safe to exit without error, even if there are no choices generated\n // (this only happens at the end of top level content that isn't in any particular knot)\n rootContainer.AddContent(RuntimeControlCommand.Done());\n\n // Replace runtimeObject with Story object instead of the Runtime.Container generated by Parsed.ContainerBase\n const runtimeStory = new RuntimeStory(rootContainer, runtimeLists);\n\n this.runtimeObject = runtimeStory;\n\n if (this.hadError) {\n return null;\n }\n\n // Optimisation step - inline containers that can be\n this.FlattenContainersIn(rootContainer);\n\n // Now that the story has been fulled parsed into a hierarchy,\n // and the derived runtime hierarchy has been built, we can\n // resolve referenced symbols such as variables and paths.\n // e.g. for paths \" -> knotName --> stitchName\" into an INKPath (knotName.stitchName)\n // We don't make any assumptions that the INKPath follows the same\n // conventions as the script format, so we resolve to actual objects before\n // translating into an INKPath. (This also allows us to choose whether\n // we want the paths to be absolute)\n this.ResolveReferences(this);\n\n if (this.hadError) {\n return null;\n }\n\n runtimeStory.ResetState();\n\n return runtimeStory;\n };\n\n public readonly ResolveList = (listName: string): ListDefinition | null => {\n let list: ListDefinition | null | undefined = this._listDefs.get(listName);\n if (!list) {\n return null;\n }\n\n return list;\n };\n\n public readonly ResolveListItem = (\n listName: string | null,\n itemName: string,\n source: ParsedObject | null = null\n ): ListElementDefinition | null => {\n let listDef: ListDefinition | null | undefined = null;\n\n // Search a specific list if we know its name (i.e. the form listName.itemName)\n if (listName) {\n if (!(listDef = this._listDefs.get(listName))) {\n return null;\n }\n\n return listDef.ItemNamed(itemName);\n } else {\n // Otherwise, try to search all lists\n\n let foundItem: ListElementDefinition | null = null;\n let originalFoundList: ListDefinition | null = null;\n\n for (const [, value] of this._listDefs.entries()) {\n const itemInThisList = value.ItemNamed(itemName);\n if (itemInThisList) {\n if (foundItem) {\n this.Error(\n `Ambiguous item name '${itemName}' found in multiple sets, including ${\n originalFoundList!.identifier\n } and ${value!.identifier}`,\n source,\n false\n );\n } else {\n foundItem = itemInThisList;\n originalFoundList = value!;\n }\n }\n }\n\n return foundItem;\n }\n };\n\n public readonly FlattenContainersIn = (container: RuntimeContainer): void => {\n // Need to create a collection to hold the inner containers\n // because otherwise we'd end up modifying during iteration\n const innerContainers = new Set();\n if (container.content) {\n for (const c of container.content) {\n const innerContainer = asOrNull(c, RuntimeContainer);\n if (innerContainer) {\n innerContainers.add(innerContainer);\n }\n }\n }\n\n // Can't flatten the named inner containers, but we can at least\n // iterate through their children\n if (container.namedContent) {\n for (const [, value] of container.namedContent) {\n const namedInnerContainer = asOrNull(value, RuntimeContainer);\n if (namedInnerContainer) {\n innerContainers.add(namedInnerContainer);\n }\n }\n }\n\n for (const innerContainer of innerContainers) {\n this.TryFlattenContainer(innerContainer);\n this.FlattenContainersIn(innerContainer);\n }\n };\n\n public readonly TryFlattenContainer = (container: RuntimeContainer): void => {\n if (\n (container.namedContent && container.namedContent.size > 0) ||\n container.hasValidName ||\n this._dontFlattenContainers.has(container)\n ) {\n return;\n }\n\n // Inline all the content in container into the parent\n const parentContainer = asOrNull(container.parent, RuntimeContainer);\n if (parentContainer) {\n let contentIdx = parentContainer.content.indexOf(container);\n parentContainer.content.splice(contentIdx, 1);\n\n const dm = container.ownDebugMetadata;\n\n if (container.content) {\n for (const innerContent of container.content) {\n innerContent.parent = null;\n if (dm !== null && innerContent.ownDebugMetadata === null) {\n innerContent.debugMetadata = dm;\n }\n\n parentContainer.InsertContent(innerContent, contentIdx);\n contentIdx += 1;\n }\n }\n }\n };\n\n public readonly Error = (\n message: string,\n source: ParsedObject | null | undefined,\n isWarning: boolean | null | undefined\n ) => {\n let errorType: ErrorType = isWarning ? ErrorType.Warning : ErrorType.Error;\n\n let sb = \"\";\n if (source instanceof AuthorWarning) {\n sb += \"TODO: \";\n errorType = ErrorType.Author;\n } else if (isWarning) {\n sb += \"WARNING: \";\n } else {\n sb += \"ERROR: \";\n }\n\n if (\n source &&\n source.debugMetadata !== null &&\n source.debugMetadata.startLineNumber >= 1\n ) {\n if (source.debugMetadata.fileName != null) {\n sb += `'${source.debugMetadata.fileName}' `;\n }\n\n sb += `line ${source.debugMetadata.startLineNumber}: `;\n }\n\n sb += message;\n\n message = sb;\n\n if (this._errorHandler !== null) {\n this._errorHandler(message, errorType);\n } else {\n throw new Error(message);\n }\n\n this._hadError = errorType === ErrorType.Error;\n this._hadWarning = errorType === ErrorType.Warning;\n };\n\n public readonly ResetError = (): void => {\n this._hadError = false;\n this._hadWarning = false;\n };\n\n public readonly IsExternal = (namedFuncTarget: string): boolean =>\n this.externals.has(namedFuncTarget);\n\n public readonly AddExternal = (decl: ExternalDeclaration): void => {\n if (this.externals.has(decl.name!)) {\n this.Error(\n `Duplicate EXTERNAL definition of '${decl.name}'`,\n decl,\n false\n );\n } else if (decl.name) {\n this.externals.set(decl.name, decl);\n }\n };\n\n public readonly DontFlattenContainer = (\n container: RuntimeContainer\n ): void => {\n this._dontFlattenContainers.add(container);\n };\n\n public readonly NameConflictError = (\n obj: ParsedObject,\n name: string,\n existingObj: ParsedObject,\n typeNameToPrint: string\n ): void => {\n obj.Error(\n `${typeNameToPrint} '${name}': name has already been used for a ${existingObj.typeName.toLowerCase()} on ${\n existingObj.debugMetadata\n }`\n );\n };\n\n // Check given symbol type against everything that's of a higher priority in the ordered SymbolType enum (above).\n // When the given symbol type level is reached, we early-out / return.\n public readonly CheckForNamingCollisions = (\n obj: ParsedObject,\n identifier: Identifier,\n symbolType: SymbolType,\n typeNameOverride: string = \"\"\n ): void => {\n const typeNameToPrint: string = typeNameOverride || obj.typeName;\n if (Story.IsReservedKeyword(identifier?.name)) {\n obj.Error(\n `'${identifier}' cannot be used for the name of a ${typeNameToPrint.toLowerCase()} because it's a reserved keyword`\n );\n return;\n } else if (FunctionCall.IsBuiltIn(identifier?.name || \"\")) {\n obj.Error(\n `'${identifier}' cannot be used for the name of a ${typeNameToPrint.toLowerCase()} because it's a built in function`\n );\n\n return;\n }\n\n // Top level knots\n const maybeKnotOrFunction = this.ContentWithNameAtLevel(\n identifier?.name || \"\",\n FlowLevel.Knot\n );\n\n const knotOrFunction = asOrNull(maybeKnotOrFunction, FlowBase);\n\n if (\n knotOrFunction &&\n (knotOrFunction !== obj || symbolType === SymbolType.Arg)\n ) {\n this.NameConflictError(\n obj,\n identifier?.name || \"\",\n knotOrFunction,\n typeNameToPrint\n );\n return;\n }\n\n if (symbolType < SymbolType.List) {\n return;\n }\n\n // Lists\n for (const [key, value] of this._listDefs) {\n if (\n identifier?.name === key &&\n obj !== value &&\n value.variableAssignment !== obj\n ) {\n this.NameConflictError(obj, identifier?.name, value, typeNameToPrint);\n }\n\n // We don't check for conflicts between individual elements in\n // different lists because they are namespaced.\n if (!(obj instanceof ListElementDefinition)) {\n for (const item of value.itemDefinitions) {\n if (identifier?.name === item.name) {\n this.NameConflictError(\n obj,\n identifier?.name || \"\",\n item,\n typeNameToPrint\n );\n }\n }\n }\n }\n\n // Don't check for VAR->VAR conflicts because that's handled separately\n // (necessary since checking looks up in a dictionary)\n if (symbolType <= SymbolType.Var) {\n return;\n }\n\n // Global variable collision\n const varDecl: VariableAssignment | null =\n (identifier?.name && this.variableDeclarations.get(identifier?.name)) ||\n null;\n if (\n varDecl &&\n varDecl !== obj &&\n varDecl.isGlobalDeclaration &&\n varDecl.listDefinition == null\n ) {\n this.NameConflictError(\n obj,\n identifier?.name || \"\",\n varDecl,\n typeNameToPrint\n );\n }\n\n if (symbolType < SymbolType.SubFlowAndWeave) {\n return;\n }\n\n // Stitches, Choices and Gathers\n const path = new Path(identifier);\n const targetContent = path.ResolveFromContext(obj);\n if (targetContent && targetContent !== obj) {\n this.NameConflictError(\n obj,\n identifier?.name || \"\",\n targetContent,\n typeNameToPrint\n );\n return;\n }\n\n if (symbolType < SymbolType.Arg) {\n return;\n }\n\n // Arguments to the current flow\n if (symbolType !== SymbolType.Arg) {\n let flow: FlowBase | null = asOrNull(obj, FlowBase);\n if (!flow) {\n flow = ClosestFlowBase(obj);\n }\n\n if (flow && flow.hasParameters && flow.args) {\n for (const arg of flow.args) {\n if (arg.identifier?.name === identifier?.name) {\n obj.Error(\n `${typeNameToPrint} '${identifier}': name has already been used for a argument to ${flow.identifier} on ${flow.debugMetadata}`\n );\n\n return;\n }\n }\n }\n }\n };\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { Expression } from \"./Expression\";\nimport { ParsedObject } from \"../Object\";\nimport { Text } from \"../Text\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class StringExpression extends Expression {\n get isSingleString() {\n if (this.content.length !== 1) {\n return false;\n }\n\n const c = this.content[0];\n if (!(c instanceof Text)) {\n return false;\n }\n\n return true;\n }\n\n constructor(content: ParsedObject[]) {\n super();\n\n this.AddContent(content);\n }\n\n get typeName(): string {\n return \"String\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n container.AddContent(RuntimeControlCommand.BeginString());\n\n for (const c of this.content) {\n container.AddContent(c.runtimeObject);\n }\n\n container.AddContent(RuntimeControlCommand.EndString());\n };\n\n public readonly toString = (): string => {\n let sb = \"\";\n for (const c of this.content) {\n sb += c;\n }\n\n return sb;\n };\n\n // Equals override necessary in order to check for CONST multiple definition equality\n public Equals(obj: ParsedObject): boolean {\n const otherStr = asOrNull(obj, StringExpression);\n if (otherStr === null) {\n return false;\n }\n\n // Can only compare direct equality on single strings rather than\n // complex string expressions that contain dynamic logic\n if (!this.isSingleString || !otherStr.isSingleString) {\n return false;\n }\n\n const thisTxt = this.toString();\n const otherTxt = otherStr.toString();\n return thisTxt === otherTxt;\n }\n}\n","import { ParsedObject } from \"./Object\";\nimport { ControlCommand } from \"../../../engine/ControlCommand\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\n\nexport class Tag extends ParsedObject {\n public isStart: boolean;\n public inChoice: boolean;\n\n constructor(isStart: boolean, inChoice: boolean = false) {\n super();\n this.isStart = isStart;\n this.inChoice = inChoice;\n }\n get typeName(): string {\n return \"Tag\";\n }\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n if (this.isStart) {\n return ControlCommand.BeginTag();\n } else {\n return ControlCommand.EndTag();\n }\n };\n\n public readonly toString = () => {\n if (this.isStart) {\n return \"#StartTag\";\n } else {\n return \"#EndTag\";\n }\n };\n}\n\nimport { Tag as RuntimeTag } from \"../../../engine/Tag\";\nimport { Wrap } from \"./Wrap\";\nexport class LegacyTag extends Wrap {\n constructor(tag: RuntimeTag) {\n super(tag);\n }\n get typeName(): string {\n return \"Tag\";\n }\n}\n","import { IFileHandler } from \"../IFileHandler\";\n\n// This class replaces upstream's DefaultFileHandler. It doesn't perform any\n// resolution and warns the user about providing a proper file handler when\n// INCLUDE statements are parsed. Since the JavaScript parser can be executed in\n// different environments, we let the user decide which FileHandler is best for\n// their use-case. See PosixFileHandler and JsonFileHandler.\nexport class DefaultFileHandler implements IFileHandler {\n constructor(public readonly rootPath?: string) {}\n\n readonly ResolveInkFilename = (): string => {\n throw Error(\n \"Can't resolve filename because no FileHandler was provided when instantiating the parser / compiler.\"\n );\n };\n\n readonly LoadInkFileContents = (): string => {\n throw Error(\n \"Can't load ink content because no FileHandler was provided when instantiating the parser / compiler.\"\n );\n };\n}\n","import { Argument } from \"./ParsedHierarchy/Argument\";\nimport { AuthorWarning } from \"./ParsedHierarchy/AuthorWarning\";\nimport { BinaryExpression } from \"./ParsedHierarchy/Expression/BinaryExpression\";\nimport { CharacterRange } from \"./CharacterRange\";\nimport { CharacterSet } from \"./CharacterSet\";\nimport { Choice } from \"./ParsedHierarchy/Choice\";\nimport { CommentEliminator } from \"./CommentEliminator\";\nimport { Conditional } from \"./ParsedHierarchy/Conditional/Conditional\";\nimport { ConditionalSingleBranch } from \"./ParsedHierarchy/Conditional/ConditionalSingleBranch\";\nimport { ContentList } from \"./ParsedHierarchy/ContentList\";\nimport { ConstantDeclaration } from \"./ParsedHierarchy/Declaration/ConstantDeclaration\";\nimport { CustomFlags } from \"./CustomFlags\";\nimport { DebugMetadata } from \"../../engine/DebugMetadata\";\nimport { Divert } from \"./ParsedHierarchy/Divert/Divert\";\nimport { DivertTarget } from \"./ParsedHierarchy/Divert/DivertTarget\";\nimport { Expression } from \"./ParsedHierarchy/Expression/Expression\";\nimport { ErrorHandler } from \"../../engine/Error\";\nimport { ExternalDeclaration } from \"./ParsedHierarchy/Declaration/ExternalDeclaration\";\nimport { FlowDecl } from \"./FlowDecl\";\nimport { FunctionCall } from \"./ParsedHierarchy/FunctionCall\";\nimport { Gather } from \"./ParsedHierarchy/Gather/Gather\";\nimport { Glue } from \"./ParsedHierarchy/Glue\";\nimport { Glue as RuntimeGlue } from \"../../engine/Glue\";\nimport { IFileHandler } from \"../IFileHandler\";\nimport { IncDecExpression } from \"./ParsedHierarchy/Expression/IncDecExpression\";\nimport { IncludedFile } from \"./ParsedHierarchy/IncludedFile\";\nimport { InfixOperator } from \"./InfixOperator\";\nimport { Knot } from \"./ParsedHierarchy/Knot\";\nimport { List } from \"./ParsedHierarchy/List/List\";\nimport { ListDefinition } from \"./ParsedHierarchy/List/ListDefinition\";\nimport { ListElementDefinition } from \"./ParsedHierarchy/List/ListElementDefinition\";\nimport { MultipleConditionExpression } from \"./ParsedHierarchy/Expression/MultipleConditionExpression\";\nimport { ParsedObject } from \"./ParsedHierarchy/Object\";\nimport { Path } from \"./ParsedHierarchy/Path\";\nimport { ReturnType } from \"./ParsedHierarchy/ReturnType\";\nimport { Sequence } from \"./ParsedHierarchy/Sequence/Sequence\";\nimport { SequenceType } from \"./ParsedHierarchy/Sequence/SequenceType\";\nimport { StatementLevel } from \"./StatementLevel\";\nimport { Stitch } from \"./ParsedHierarchy/Stitch\";\nimport { Story } from \"./ParsedHierarchy/Story\";\nimport { StringExpression } from \"./ParsedHierarchy/Expression/StringExpression\";\nimport {\n StringParser,\n SpecificParseRule,\n ParseRule,\n ParseRuleReturn,\n ParseSuccess,\n} from \"./StringParser/StringParser\";\nimport { StringParserElement } from \"./StringParser/StringParserElement\";\nimport { Tag } from \"./ParsedHierarchy/Tag\";\nimport { Text } from \"./ParsedHierarchy/Text\";\nimport { TunnelOnwards } from \"./ParsedHierarchy/TunnelOnwards\";\nimport { VariableAssignment } from \"./ParsedHierarchy/Variable/VariableAssignment\";\nimport { VariableReference } from \"./ParsedHierarchy/Variable/VariableReference\";\nimport { UnaryExpression } from \"./ParsedHierarchy/Expression/UnaryExpression\";\nimport { asOrNull, filterUndef } from \"../../engine/TypeAssertion\";\nimport { Identifier } from \"./ParsedHierarchy/Identifier\";\nimport { NumberExpression } from \"./ParsedHierarchy/Expression/NumberExpression\";\nimport { ErrorType } from \"./ErrorType\";\nimport { DefaultFileHandler } from \"../FileHandler/DefaultFileHandler\";\n\nexport class InkParser extends StringParser {\n /**\n * Begin base InkParser section.\n */\n\n get fileHandler(): IFileHandler {\n if (!this._fileHandler) {\n throw new Error(\"No FileHandler defined\");\n }\n return this._fileHandler;\n }\n\n set fileHandler(value: IFileHandler) {\n this._fileHandler = value;\n }\n\n constructor(\n str: string,\n filename: string | null = null,\n externalErrorHandler: ErrorHandler | null = null,\n rootParser: InkParser | null = null,\n fileHandler: IFileHandler | null = null\n ) {\n super(str);\n\n this._filename = filename;\n this.RegisterExpressionOperators();\n this.GenerateStatementLevelRules();\n\n this.errorHandler = this.OnStringParserError;\n\n this._externalErrorHandler = externalErrorHandler;\n\n if (fileHandler === null) {\n this._fileHandler = new DefaultFileHandler();\n } else {\n this._fileHandler = fileHandler;\n }\n\n if (rootParser === null) {\n this._rootParser = this;\n this._openFilenames = [];\n\n if (this._filename !== null) {\n const fullRootInkPath = this.fileHandler.ResolveInkFilename(\n this._filename\n );\n this._openFilenames.push(fullRootInkPath);\n }\n } else {\n this._rootParser = rootParser;\n }\n }\n\n // Main entry point\n // NOTE: This method is named Parse() in upstream.\n public readonly ParseStory = (): Story => {\n const topLevelContent: ParsedObject[] = this.StatementsAtLevel(\n StatementLevel.Top\n );\n\n // Note we used to return null if there were any errors, but this would mean\n // that include files would return completely empty rather than attempting to\n // continue with errors. Returning an empty include files meant that anything\n // that *did* compile successfully would otherwise be ignored, generating way\n // more errors than necessary.\n return new Story(topLevelContent, this._rootParser !== this);\n };\n\n public readonly SeparatedList = (\n mainRule: SpecificParseRule,\n separatorRule: ParseRule\n ): ParseRuleReturn[] | null => {\n const firstElement: ParseRuleReturn = this.Parse(mainRule);\n if (firstElement === null) {\n return null;\n }\n\n const allElements = [];\n allElements.push(firstElement);\n\n do {\n const nextElementRuleId: number = this.BeginRule();\n let sep = separatorRule();\n if (sep === null) {\n this.FailRule(nextElementRuleId);\n break;\n }\n\n const nextElement = this.Parse(mainRule);\n if (nextElement === null) {\n this.FailRule(nextElementRuleId);\n break;\n }\n\n this.SucceedRule(nextElementRuleId);\n allElements.push(nextElement);\n } while (true);\n\n return allElements;\n };\n\n public PreProcessInputString(str: string): string {\n const commentEliminator = new CommentEliminator(str);\n return commentEliminator.Process();\n }\n\n public readonly CreateDebugMetadata = (\n stateAtStart: StringParserElement | null,\n stateAtEnd: StringParserElement\n ): DebugMetadata => {\n const md = new DebugMetadata();\n md.startLineNumber = (stateAtStart?.lineIndex || 0) + 1;\n md.endLineNumber = stateAtEnd.lineIndex + 1;\n md.startCharacterNumber = (stateAtStart?.characterInLineIndex || 0) + 1;\n md.endCharacterNumber = stateAtEnd.characterInLineIndex + 1;\n md.fileName = this._filename;\n\n return md;\n };\n\n public readonly RuleDidSucceed = (\n result: ParseRuleReturn,\n stateAtStart: StringParserElement | null,\n stateAtEnd: StringParserElement\n ): void => {\n // Apply DebugMetadata based on the state at the start of the rule\n // (i.e. use line number as it was at the start of the rule)\n const parsedObj = asOrNull(result, ParsedObject);\n if (parsedObj) {\n parsedObj.debugMetadata = this.CreateDebugMetadata(\n stateAtStart,\n stateAtEnd\n );\n }\n\n // A list of objects that doesn't already have metadata?\n const parsedListObjs: ParsedObject[] | null = Array.isArray(result)\n ? (result as ParsedObject[])\n : null;\n if (parsedListObjs !== null) {\n for (const parsedListObj of parsedListObjs) {\n const singleObj = asOrNull(parsedListObj, ParsedObject);\n if (!singleObj) continue;\n if (!parsedListObj.hasOwnDebugMetadata) {\n parsedListObj.debugMetadata = this.CreateDebugMetadata(\n stateAtStart,\n stateAtEnd\n );\n }\n }\n }\n\n const id = asOrNull(result, Identifier);\n if (id != null) {\n id.debugMetadata = this.CreateDebugMetadata(stateAtStart, stateAtEnd);\n }\n };\n\n get parsingStringExpression(): boolean {\n return this.GetFlag(Number(CustomFlags.ParsingString));\n }\n\n set parsingStringExpression(value: boolean) {\n this.SetFlag(Number(CustomFlags.ParsingString), value);\n }\n\n get tagActive(): boolean {\n return this.GetFlag(Number(CustomFlags.TagActive));\n }\n\n set tagActive(value: boolean) {\n this.SetFlag(Number(CustomFlags.TagActive), value);\n }\n\n public readonly OnStringParserError = (\n message: string,\n index: number,\n lineIndex: number = 0,\n isWarning: boolean = false\n ): void => {\n const warningType: string = isWarning ? \"WARNING:\" : \"ERROR:\";\n let fullMessage: string = warningType;\n\n if (this._filename !== null) {\n fullMessage += ` '${this._filename}'`;\n }\n\n fullMessage += ` line ${lineIndex + 1}: ${message}`;\n\n if (this._externalErrorHandler !== null) {\n this._externalErrorHandler(\n fullMessage,\n isWarning ? ErrorType.Warning : ErrorType.Error\n );\n } else {\n throw new Error(fullMessage);\n }\n };\n\n public readonly AuthorWarning = (): AuthorWarning | null => {\n this.Whitespace();\n\n const identifier = this.Parse(\n this.IdentifierWithMetadata\n ) as unknown as Identifier | null;\n if (identifier === null || identifier.name !== \"TODO\") {\n return null;\n }\n\n this.Whitespace();\n this.ParseString(\":\");\n this.Whitespace();\n\n const message = this.ParseUntilCharactersFromString(\"\\n\\r\");\n\n if (message) {\n return new AuthorWarning(message);\n }\n\n return null;\n };\n\n /**\n * End base InkParser section.\n */\n\n /**\n * Begin CharacterRanges section.\n */\n\n public static readonly LatinBasic: CharacterRange = CharacterRange.Define(\n \"\\u0041\",\n \"\\u007A\",\n new CharacterSet().AddRange(\"\\u005B\", \"\\u0060\")\n );\n\n public static readonly LatinExtendedA: CharacterRange = CharacterRange.Define(\n \"\\u0100\",\n \"\\u017F\"\n // no excludes here\n );\n\n public static readonly LatinExtendedB: CharacterRange = CharacterRange.Define(\n \"\\u0180\",\n \"\\u024F\"\n // no excludes here\n );\n\n public static readonly Greek: CharacterRange = CharacterRange.Define(\n \"\\u0370\",\n \"\\u03FF\",\n new CharacterSet()\n .AddRange(\"\\u0378\", \"\\u0385\")\n .AddCharacters(\"\\u0374\\u0375\\u0378\\u0387\\u038B\\u038D\\u03A2\")\n );\n\n public static readonly Cyrillic: CharacterRange = CharacterRange.Define(\n \"\\u0400\",\n \"\\u04FF\",\n new CharacterSet().AddRange(\"\\u0482\", \"\\u0489\")\n );\n\n public static readonly Armenian: CharacterRange = CharacterRange.Define(\n \"\\u0530\",\n \"\\u058F\",\n new CharacterSet()\n .AddCharacters(\"\\u0530\")\n .AddRange(\"\\u0557\", \"\\u0560\")\n .AddRange(\"\\u0588\", \"\\u058E\")\n );\n\n public static readonly Hebrew: CharacterRange = CharacterRange.Define(\n \"\\u0590\",\n \"\\u05FF\",\n new CharacterSet()\n );\n\n public static readonly Arabic: CharacterRange = CharacterRange.Define(\n \"\\u0600\",\n \"\\u06FF\",\n new CharacterSet()\n );\n\n public static readonly Korean: CharacterRange = CharacterRange.Define(\n \"\\uAC00\",\n \"\\uD7AF\",\n new CharacterSet()\n );\n\n private readonly ExtendIdentifierCharacterRanges = (\n identifierCharSet: CharacterSet\n ): void => {\n const characterRanges = InkParser.ListAllCharacterRanges();\n for (const charRange of characterRanges) {\n identifierCharSet.AddCharacters(charRange.ToCharacterSet());\n }\n };\n\n /// \n /// Gets an array of representing all of the currently supported\n /// non-ASCII character ranges that can be used in identifier names.\n /// \n /// \n /// An array of representing all of the currently supported\n /// non-ASCII character ranges that can be used in identifier names.\n /// \n public static readonly ListAllCharacterRanges = (): CharacterRange[] => [\n InkParser.LatinBasic,\n InkParser.LatinExtendedA,\n InkParser.LatinExtendedB,\n InkParser.Arabic,\n InkParser.Armenian,\n InkParser.Cyrillic,\n InkParser.Greek,\n InkParser.Hebrew,\n InkParser.Korean,\n ];\n\n /**\n * End CharacterRanges section.\n */\n\n /**\n * Begin Choices section.\n */\n\n public _parsingChoice: boolean = false;\n\n public readonly Choice = (): Choice | null => {\n let onceOnlyChoice: boolean = true;\n let bullets = this.Interleave(\n this.OptionalExclude(this.Whitespace),\n this.String(\"*\")\n );\n\n if (!bullets) {\n bullets = this.Interleave(\n this.OptionalExclude(this.Whitespace),\n this.String(\"+\")\n );\n\n if (bullets === null) {\n return null;\n }\n\n onceOnlyChoice = false;\n }\n\n // Optional name for the choice\n const optionalName: Identifier = this.Parse(\n this.BracketedName\n ) as Identifier;\n\n this.Whitespace();\n\n // Optional condition for whether the choice should be shown to the player\n const conditionExpr: Expression = this.Parse(\n this.ChoiceCondition\n ) as Expression;\n\n this.Whitespace();\n\n // Ordinarily we avoid parser state variables like these, since\n // nesting would require us to store them in a stack. But since you should\n // never be able to nest choices within choice content, it's fine here.\n if (this._parsingChoice) {\n throw new Error(\n \"Already parsing a choice - shouldn't have nested choices\"\n );\n }\n\n this._parsingChoice = true;\n\n let startContent: ContentList | null = null;\n const startTextAndLogic = this.Parse(\n this.MixedTextAndLogic\n ) as ParsedObject[];\n if (startTextAndLogic) {\n startContent = new ContentList(startTextAndLogic);\n }\n\n let optionOnlyContent: ContentList | null = null;\n let innerContent: ContentList | null = null;\n\n // Check for a the weave style format:\n // * \"Hello[.\"],\" he said.\n const hasWeaveStyleInlineBrackets: boolean = this.ParseString(\"[\") !== null;\n if (hasWeaveStyleInlineBrackets) {\n this.EndTagIfNecessary(startContent);\n\n const optionOnlyTextAndLogic = this.Parse(\n this.MixedTextAndLogic\n ) as ParsedObject[];\n\n if (optionOnlyTextAndLogic !== null) {\n optionOnlyContent = new ContentList(optionOnlyTextAndLogic);\n }\n\n this.Expect(this.String(\"]\"), \"closing ']' for weave-style option\");\n\n this.EndTagIfNecessary(optionOnlyContent);\n\n let innerTextAndLogic = this.Parse(\n this.MixedTextAndLogic\n ) as ParsedObject[];\n if (innerTextAndLogic !== null) {\n innerContent = new ContentList(innerTextAndLogic);\n }\n }\n\n this.Whitespace();\n\n this.EndTagIfNecessary(innerContent ?? startContent);\n\n // Finally, now we know we're at the end of the main choice body, parse\n // any diverts separately.\n const diverts: ParsedObject[] = this.Parse(\n this.MultiDivert\n ) as ParsedObject[];\n\n this._parsingChoice = false;\n\n this.Whitespace();\n\n // Completely empty choice without even an empty divert?\n const emptyContent: boolean =\n !startContent && !innerContent && !optionOnlyContent;\n\n if (emptyContent && diverts === null) {\n this.Warning(\n \"Choice is completely empty. Interpretting as a default fallback choice. Add a divert arrow to remove this warning: * ->\"\n );\n }\n\n if (!startContent && hasWeaveStyleInlineBrackets && !optionOnlyContent) {\n // * [] some text\n this.Warning(\n \"Blank choice - if you intended a default fallback choice, use the `* ->` syntax\"\n );\n }\n\n if (!innerContent) {\n innerContent = new ContentList();\n }\n\n this.EndTagIfNecessary(innerContent);\n\n // Normal diverts on the end of a choice - simply add to the normal content\n if (diverts !== null) {\n for (const divObj of diverts) {\n // may be TunnelOnwards\n const div = asOrNull(divObj, Divert);\n\n // Empty divert serves no purpose other than to say\n // \"this choice is intentionally left blank\"\n // (as an invisible default choice)\n if (div && div.isEmpty) {\n continue;\n }\n\n innerContent.AddContent(divObj);\n }\n }\n\n // Terminate main content with a newline since this is the end of the line\n // Note that this will be redundant if the diverts above definitely take\n // the flow away permanently.\n innerContent.AddContent(new Text(\"\\n\"));\n\n const choice = new Choice(startContent!, optionOnlyContent!, innerContent);\n if (optionalName) choice.identifier = optionalName;\n choice.indentationDepth = bullets.length;\n choice.hasWeaveStyleInlineBrackets = hasWeaveStyleInlineBrackets;\n choice.condition = conditionExpr;\n choice.onceOnly = onceOnlyChoice;\n choice.isInvisibleDefault = emptyContent;\n return choice;\n };\n\n public readonly ChoiceCondition = (): Expression | null => {\n const conditions = this.Interleave(\n this.ChoiceSingleCondition,\n this.ChoiceConditionsSpace\n );\n\n if (conditions === null) {\n return null;\n } else if (conditions.length === 1) {\n return conditions[0];\n }\n\n return new MultipleConditionExpression(conditions);\n };\n\n public readonly ChoiceConditionsSpace = (): typeof ParseSuccess => {\n // Both optional\n // Newline includes initial end of line whitespace\n this.Newline();\n this.Whitespace();\n\n return ParseSuccess;\n };\n\n public readonly ChoiceSingleCondition = (): Expression | null => {\n if (this.ParseString(\"{\") === null) {\n return null;\n }\n\n const condExpr = this.Expect(\n this.Expression,\n \"choice condition inside { }\"\n ) as Expression;\n\n this.DisallowIncrement(condExpr);\n this.Expect(this.String(\"}\"), \"closing '}' for choice condition\");\n\n return condExpr;\n };\n\n public readonly Gather = (): Gather | null => {\n const gatherDashCountObj: number = this.Parse(this.GatherDashes) as number;\n if (gatherDashCountObj === null) {\n return null;\n }\n\n const gatherDashCount: number = Number(gatherDashCountObj);\n\n // Optional name for the gather\n const optionalName: Identifier = this.Parse(\n this.BracketedName\n ) as Identifier;\n\n const gather = new Gather(optionalName, gatherDashCount);\n\n // Optional newline before gather's content begins\n this.Newline();\n\n return gather;\n };\n\n public readonly GatherDashes = (): number | null => {\n this.Whitespace();\n\n let gatherDashCount: number = 0;\n while (this.ParseDashNotArrow() !== null) {\n gatherDashCount += 1;\n this.Whitespace();\n }\n\n if (gatherDashCount === 0) {\n return null;\n }\n\n return gatherDashCount as number;\n };\n\n public readonly ParseDashNotArrow = () => {\n const ruleId = this.BeginRule();\n\n if (\n this.ParseString(\"->\") === null &&\n this.ParseSingleCharacter() === \"-\"\n ) {\n return this.SucceedRule(ruleId);\n }\n\n return this.FailRule(ruleId);\n };\n\n public readonly BracketedName = (): Identifier | null => {\n if (this.ParseString(\"(\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n const name = this.Parse(this.IdentifierWithMetadata) as Identifier | null;\n if (name === null) {\n return null;\n }\n\n this.Whitespace();\n\n this.Expect(this.String(\")\"), \"closing ')' for bracketed name\");\n\n return name;\n };\n\n /**\n * End Choices section.\n */\n\n /**\n * Begin Conditional section.\n */\n\n public readonly InnerConditionalContent = (\n initialQueryExpression: Expression\n ): Conditional | null => {\n if (initialQueryExpression === undefined) {\n const initialQueryExpression = this.Parse(this.ConditionExpression);\n const conditional = this.Parse(() =>\n this.InnerConditionalContent(initialQueryExpression as Expression)\n ) as Conditional;\n\n if (conditional === null) {\n return null;\n }\n\n return conditional;\n }\n\n let alternatives: ConditionalSingleBranch[] | null;\n const canBeInline: boolean = initialQueryExpression !== null;\n const isInline: boolean = this.Parse(this.Newline) === null;\n\n if (isInline && !canBeInline) {\n return null;\n }\n\n if (isInline) {\n // Inline innards\n alternatives = this.InlineConditionalBranches();\n } else {\n // Multiline innards\n alternatives = this.MultilineConditionalBranches();\n\n if (alternatives === null) {\n // Allow single piece of content within multi-line expression, e.g.:\n // { true:\n // Some content that isn't preceded by '-'\n // }\n if (initialQueryExpression) {\n let soleContent: ParsedObject[] = this.StatementsAtLevel(\n StatementLevel.InnerBlock\n );\n if (soleContent !== null) {\n const soleBranch = new ConditionalSingleBranch(soleContent);\n alternatives = [soleBranch];\n\n // Also allow a final \"- else:\" clause\n const elseBranch = this.Parse(\n this.SingleMultilineCondition\n ) as ConditionalSingleBranch;\n if (elseBranch) {\n if (!elseBranch.isElse) {\n this.ErrorWithParsedObject(\n \"Expected an '- else:' clause here rather than an extra condition\",\n elseBranch\n );\n\n elseBranch.isElse = true;\n }\n\n alternatives.push(elseBranch);\n }\n }\n }\n\n // Still null?\n if (alternatives === null) {\n return null;\n }\n } else if (\n alternatives.length === 1 &&\n alternatives[0].isElse &&\n initialQueryExpression\n ) {\n // Empty true branch - didn't get parsed, but should insert one for semantic correctness,\n // and to make sure that any evaluation stack values get tidied up correctly.\n const emptyTrueBranch = new ConditionalSingleBranch(null);\n emptyTrueBranch.isTrueBranch = true;\n alternatives.unshift(emptyTrueBranch);\n }\n\n // Like a switch statement\n // { initialQueryExpression:\n // ... match the expression\n // }\n if (initialQueryExpression) {\n let earlierBranchesHaveOwnExpression: boolean = false;\n for (let ii = 0; ii < alternatives.length; ++ii) {\n const branch = alternatives[ii];\n const isLast: boolean = ii === alternatives.length - 1;\n\n // Matching equality with initial query expression\n // We set this flag even for the \"else\" clause so that\n // it knows to tidy up the evaluation stack at the end\n\n // Match query\n if (branch.ownExpression) {\n branch.matchingEquality = true;\n earlierBranchesHaveOwnExpression = true;\n } else if (earlierBranchesHaveOwnExpression && isLast) {\n // Else (final branch)\n branch.matchingEquality = true;\n branch.isElse = true;\n } else {\n // Binary condition:\n // { trueOrFalse:\n // - when true\n // - when false\n // }\n if (!isLast && alternatives.length > 2) {\n this.ErrorWithParsedObject(\n \"Only final branch can be an 'else'. Did you miss a ':'?\",\n branch\n );\n } else {\n if (ii === 0) {\n branch.isTrueBranch = true;\n } else {\n branch.isElse = true;\n }\n }\n }\n }\n } else {\n // No initial query, so just a multi-line conditional. e.g.:\n // {\n // - x > 3: greater than three\n // - x == 3: equal to three\n // - x < 3: less than three\n // }\n\n for (let ii = 0; ii < alternatives.length; ++ii) {\n const alt = alternatives[ii];\n const isLast: boolean = ii === alternatives.length - 1;\n\n if (alt.ownExpression === null) {\n if (isLast) {\n alt.isElse = true;\n } else {\n if (alt.isElse) {\n // Do we ALSO have a valid \"else\" at the end? Let's report the error there.\n const finalClause = alternatives[alternatives.length - 1];\n if (finalClause.isElse) {\n this.ErrorWithParsedObject(\n \"Multiple 'else' cases. Can have a maximum of one, at the end.\",\n finalClause\n );\n } else {\n this.ErrorWithParsedObject(\n \"'else' case in conditional should always be the final one\",\n alt\n );\n }\n } else {\n this.ErrorWithParsedObject(\n \"Branch doesn't have condition. Are you missing a ':'? \",\n alt\n );\n }\n }\n }\n }\n\n if (\n alternatives.length === 1 &&\n alternatives[0].ownExpression === null\n ) {\n this.ErrorWithParsedObject(\n \"Condition block with no conditions\",\n alternatives[0]\n );\n }\n }\n }\n\n // TODO: Come up with water-tight error conditions... it's quite a flexible system!\n // e.g.\n // - inline conditionals must have exactly 1 or 2 alternatives\n // - multiline expression shouldn't have mixed existence of branch-conditions?\n if (alternatives === null) {\n return null;\n }\n\n for (const branch of alternatives) {\n branch.isInline = isInline;\n }\n\n const cond = new Conditional(initialQueryExpression, alternatives);\n\n return cond;\n };\n\n public readonly InlineConditionalBranches = ():\n | ConditionalSingleBranch[]\n | null => {\n const listOfLists = this.Interleave(\n this.MixedTextAndLogic,\n this.Exclude(this.String(\"|\")),\n null,\n false\n );\n\n if (listOfLists === null || listOfLists.length === 0) {\n return null;\n }\n\n const result: ConditionalSingleBranch[] = [];\n\n if (listOfLists.length > 2) {\n this.Error(\n \"Expected one or two alternatives separated by '|' in inline conditional\"\n );\n } else {\n const trueBranch = new ConditionalSingleBranch(listOfLists[0]);\n trueBranch.isTrueBranch = true;\n result.push(trueBranch);\n\n if (listOfLists.length > 1) {\n const elseBranch = new ConditionalSingleBranch(listOfLists[1]);\n elseBranch.isElse = true;\n result.push(elseBranch);\n }\n }\n\n return result;\n };\n\n public readonly MultilineConditionalBranches = ():\n | ConditionalSingleBranch[]\n | null => {\n this.MultilineWhitespace();\n\n const multipleConditions = this.OneOrMore(this.SingleMultilineCondition);\n if (multipleConditions === null) {\n return null;\n }\n\n this.MultilineWhitespace();\n\n return multipleConditions as ConditionalSingleBranch[];\n };\n\n public readonly SingleMultilineCondition =\n (): ConditionalSingleBranch | null => {\n this.Whitespace();\n\n if (\n // Make sure we're not accidentally parsing a divert\n this.ParseString(\"->\") !== null ||\n this.ParseString(\"-\") === null\n ) {\n return null;\n }\n\n this.Whitespace();\n\n let expr: Expression | null = null;\n const isElse: boolean = this.Parse(this.ElseExpression) !== null;\n\n if (!isElse) {\n expr = this.Parse(this.ConditionExpression) as Expression;\n }\n\n let content: ParsedObject[] = this.StatementsAtLevel(\n StatementLevel.InnerBlock\n );\n if (expr === null && content === null) {\n this.Error(\"expected content for the conditional branch following '-'\");\n\n // Recover\n content = [new Text(\"\")];\n }\n\n // Allow additional multiline whitespace, if the statements were empty (valid)\n // then their surrounding multiline whitespacce needs to be handled manually.\n // e.g.\n // { x:\n // - 1: // intentionally left blank, but newline needs to be parsed\n // - 2: etc\n // }\n this.MultilineWhitespace();\n\n const branch = new ConditionalSingleBranch(content);\n branch.ownExpression = expr;\n branch.isElse = isElse;\n\n return branch;\n };\n\n public readonly ConditionExpression = (): ParsedObject | null => {\n const expr = this.Parse(this.Expression) as ParsedObject;\n if (expr === null) {\n return null;\n }\n\n this.DisallowIncrement(expr);\n\n this.Whitespace();\n\n if (this.ParseString(\":\") === null) {\n return null;\n }\n\n return expr;\n };\n\n public readonly ElseExpression = (): typeof ParseSuccess | null => {\n if (this.ParseString(\"else\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n if (this.ParseString(\":\") === null) {\n return null;\n }\n\n return ParseSuccess;\n };\n\n /**\n * End Conditional section.\n */\n\n /**\n * Begin Content section.\n */\n\n public _nonTextPauseCharacters: CharacterSet | null = null;\n public _nonTextEndCharacters: CharacterSet | null = null;\n public _notTextEndCharactersChoice: CharacterSet | null = null;\n public _notTextEndCharactersString: CharacterSet | null = null;\n\n public readonly TrimEndWhitespace = (\n mixedTextAndLogicResults: ParsedObject[],\n terminateWithSpace: boolean\n ): void => {\n // Trim whitespace from end\n if (mixedTextAndLogicResults.length > 0) {\n const lastObjIdx = mixedTextAndLogicResults.length - 1;\n const lastObj = mixedTextAndLogicResults[lastObjIdx];\n if (lastObj instanceof Text) {\n const textObj: Text = lastObj;\n textObj.text = textObj.text.replace(new RegExp(/[ \\t]+$/g), \"\");\n\n if (terminateWithSpace) {\n textObj.text += \" \";\n } else if (textObj.text.length === 0) {\n // No content left at all? trim the whole object\n mixedTextAndLogicResults.splice(lastObjIdx, 1);\n\n // Recurse in case there's more whitespace\n this.TrimEndWhitespace(mixedTextAndLogicResults, false);\n }\n }\n }\n };\n\n public readonly LineOfMixedTextAndLogic = (): ParsedObject[] | null => {\n // Consume any whitespace at the start of the line\n // (Except for escaped whitespace)\n this.Parse(this.Whitespace);\n\n let result: ParsedObject[] = this.Parse(\n this.MixedTextAndLogic\n ) as ParsedObject[];\n\n if (!result || !result.length) {\n return null;\n }\n\n // Warn about accidentally writing \"return\" without \"~\"\n const firstText = result[0] as Text;\n if (firstText && firstText.text && firstText.text.startsWith(\"return\")) {\n this.Warning(\n \"Do you need a '~' before 'return'? If not, perhaps use a glue: <> (since it's lowercase) or rewrite somehow?\"\n );\n }\n\n if (result.length === 0) {\n return null;\n }\n\n const lastObj = result[result.length - 1];\n if (!(lastObj instanceof Divert)) {\n this.TrimEndWhitespace(result, false);\n }\n\n this.EndTagIfNecessary(result);\n\n // If the line doens't actually contain any normal text content\n // but is in fact entirely a tag, then let's not append\n // a newline, since we want the tag (or tags) to be associated\n // with the line below rather than being completely independent.\n let lineIsPureTag =\n result.length > 0 && result[0] instanceof Tag && result[0].isStart;\n\n if (!lineIsPureTag) {\n result.push(new Text(\"\\n\"));\n }\n\n this.Expect(this.EndOfLine, \"end of line\", this.SkipToNextLine);\n return result;\n };\n\n public readonly MixedTextAndLogic = (): ParsedObject[] | null => {\n // Check for disallowed \"~\" within this context\n const disallowedTilde = this.ParseObject(this.Spaced(this.String(\"~\")));\n if (disallowedTilde !== null) {\n this.Error(\n \"You shouldn't use a '~' here - tildas are for logic that's on its own line. To do inline logic, use { curly braces } instead\"\n );\n }\n\n // Either, or both interleaved\n let results: ParsedObject[] = this.Interleave(\n this.Optional(this.ContentText),\n this.Optional(this.InlineLogicOrGlueOrStartTag)\n );\n\n // Terminating divert?\n // (When parsing content for the text of a choice, diverts aren't allowed.\n // The divert on the end of the body of a choice is handled specially.)\n if (!this._parsingChoice) {\n const diverts: ParsedObject[] = this.Parse(\n this.MultiDivert\n ) as ParsedObject[];\n if (diverts !== null) {\n // May not have had any results at all if there's *only* a divert!\n if (results === null) {\n results = [];\n }\n\n // End previously active tag if necessary\n this.EndTagIfNecessary(results);\n\n this.TrimEndWhitespace(results, true);\n\n results.push(...diverts);\n }\n }\n\n if (!results) {\n return null;\n }\n\n return results;\n };\n\n public readonly ContentText = () => {\n return this.ContentTextAllowingEscapeChar();\n };\n\n public readonly ContentTextAllowingEscapeChar = (): Text | null => {\n let sb: string | null = null;\n\n do {\n let str = this.Parse(this.ContentTextNoEscape);\n const gotEscapeChar: boolean = this.ParseString(\"\\\\\") !== null;\n\n if (gotEscapeChar || str !== null) {\n if (sb === null) {\n sb = \"\";\n }\n\n if (str !== null) {\n sb += String(str);\n }\n\n if (gotEscapeChar) {\n const c: string = this.ParseSingleCharacter();\n sb += c;\n }\n } else {\n break;\n }\n } while (true);\n\n if (sb !== null) {\n return new Text(sb);\n }\n\n return null;\n };\n\n // Content text is an unusual parse rule compared with most since it's\n // less about saying \"this is is the small selection of stuff that we parse\"\n // and more \"we parse ANYTHING except this small selection of stuff\".\n public readonly ContentTextNoEscape = (): string | null => {\n // Eat through text, pausing at the following characters, and\n // attempt to parse the nonTextRule.\n // \"-\": possible start of divert or start of gather\n // \"<\": possible start of glue\n if (this._nonTextPauseCharacters === null) {\n this._nonTextPauseCharacters = new CharacterSet(\"-<\");\n }\n\n // If we hit any of these characters, we stop *immediately* without bothering to even check the nonTextRule\n // \"{\" for start of logic\n // \"|\" for mid logic branch\n if (this._nonTextEndCharacters === null) {\n this._nonTextEndCharacters = new CharacterSet(\"{}|\\n\\r\\\\#\");\n this._notTextEndCharactersChoice = new CharacterSet(\n this._nonTextEndCharacters\n );\n this._notTextEndCharactersChoice.AddCharacters(\"[]\");\n this._notTextEndCharactersString = new CharacterSet(\n this._nonTextEndCharacters\n );\n this._notTextEndCharactersString.AddCharacters('\"');\n }\n\n // When the ParseUntil pauses, check these rules in case they evaluate successfully\n const nonTextRule: ParseRule = () =>\n this.OneOf([\n this.ParseDivertArrow,\n this.ParseThreadArrow,\n this.EndOfLine,\n this.Glue,\n ]);\n\n let endChars: CharacterSet | null = null;\n if (this.parsingStringExpression) {\n endChars = this._notTextEndCharactersString;\n } else if (this._parsingChoice) {\n endChars = this._notTextEndCharactersChoice;\n } else {\n endChars = this._nonTextEndCharacters;\n }\n\n const pureTextContent: string = this.ParseUntil(\n nonTextRule,\n this._nonTextPauseCharacters,\n endChars\n );\n\n if (pureTextContent !== null) {\n return pureTextContent;\n }\n\n return null;\n };\n\n /**\n * End Content section.\n */\n\n /**\n * Begin Divert section.\n */\n\n public readonly MultiDivert = (): ParsedObject[] | null => {\n this.Whitespace();\n\n let diverts: ParsedObject[] = [];\n\n // Try single thread first\n const threadDivert = this.Parse(this.StartThread) as ParsedObject;\n if (threadDivert) {\n diverts = [threadDivert];\n\n return diverts;\n }\n\n // Normal diverts and tunnels\n const arrowsAndDiverts = this.Interleave(\n this.ParseDivertArrowOrTunnelOnwards,\n this.DivertIdentifierWithArguments\n );\n\n if (!arrowsAndDiverts) {\n return null;\n }\n\n diverts = [];\n\n this.EndTagIfNecessary(diverts);\n\n // Possible patterns:\n // -> -- explicit gather\n // ->-> -- tunnel onwards\n // -> div -- normal divert\n // ->-> div -- tunnel onwards, followed by override divert\n // -> div -> -- normal tunnel\n // -> div ->-> -- tunnel then tunnel continue\n // -> div -> div -- tunnel then divert\n // -> div -> div -> -- tunnel then tunnel\n // -> div -> div ->->\n // -> div -> div ->-> div (etc)\n\n // Look at the arrows and diverts\n for (let ii = 0; ii < arrowsAndDiverts.length; ++ii) {\n const isArrow: boolean = ii % 2 === 0;\n\n // Arrow string\n if (isArrow) {\n // Tunnel onwards\n if ((arrowsAndDiverts[ii] as any) === \"->->\") {\n const tunnelOnwardsPlacementValid: boolean =\n ii === 0 ||\n ii === arrowsAndDiverts.length - 1 ||\n ii === arrowsAndDiverts.length - 2;\n\n if (!tunnelOnwardsPlacementValid) {\n this.Error(\n \"Tunnel onwards '->->' must only come at the begining or the start of a divert\"\n );\n }\n\n const tunnelOnwards = new TunnelOnwards();\n if (ii < arrowsAndDiverts.length - 1) {\n const tunnelOnwardDivert = asOrNull(\n arrowsAndDiverts[ii + 1],\n Divert\n );\n tunnelOnwards.divertAfter = tunnelOnwardDivert;\n }\n\n diverts.push(tunnelOnwards);\n\n // Not allowed to do anything after a tunnel onwards.\n // If we had anything left it would be caused in the above Error for\n // the positioning of a ->->\n break;\n }\n } else {\n // Divert\n const divert = arrowsAndDiverts[ii] as Divert;\n // More to come? (further arrows) Must be tunnelling.\n if (ii < arrowsAndDiverts.length - 1) {\n divert.isTunnel = true;\n }\n\n diverts.push(divert);\n }\n }\n\n // Single -> (used for default choices)\n if (diverts.length === 0 && arrowsAndDiverts.length === 1) {\n const gatherDivert = new Divert(null);\n gatherDivert.isEmpty = true;\n diverts.push(gatherDivert);\n\n if (!this._parsingChoice) {\n this.Error(\"Empty diverts (->) are only valid on choices\");\n }\n }\n\n return diverts;\n };\n\n public readonly StartThread = (): Divert | null => {\n this.Whitespace();\n\n if (this.ParseThreadArrow() === null) {\n return null;\n }\n\n this.Whitespace();\n\n const divert = this.Expect(\n this.DivertIdentifierWithArguments,\n \"target for new thread\",\n () => new Divert(null)\n ) as Divert;\n\n divert.isThread = true;\n\n return divert;\n };\n\n public readonly DivertIdentifierWithArguments = (): Divert | null => {\n this.Whitespace();\n\n const targetComponents: Identifier[] = this.Parse(\n this.DotSeparatedDivertPathComponents\n ) as Identifier[];\n\n if (!targetComponents) {\n return null;\n }\n\n this.Whitespace();\n\n const optionalArguments = this.Parse(\n this.ExpressionFunctionCallArguments\n ) as Expression[];\n\n this.Whitespace();\n\n const targetPath = new Path(targetComponents);\n\n return new Divert(targetPath, optionalArguments);\n };\n\n public readonly SingleDivert = (): Divert | null => {\n const diverts = this.Parse(this.MultiDivert) as ParsedObject[];\n if (!diverts) {\n return null;\n }\n\n // Ideally we'd report errors if we get the\n // wrong kind of divert, but unfortunately we\n // have to hack around the fact that sequences use\n // a very similar syntax.\n // i.e. if you have a multi-divert at the start\n // of a sequence, it initially tries to parse it\n // as a divert target (part of an expression of\n // a conditional) and gives errors. So instead\n // we just have to blindly reject it as a single\n // divert, and give a slightly less nice error\n // when you DO use a multi divert as a divert taret.\n\n if (diverts.length !== 1) {\n return null;\n }\n\n const singleDivert = diverts[0];\n if (singleDivert instanceof TunnelOnwards) {\n return null;\n }\n\n const divert = diverts[0] as Divert;\n if (divert.isTunnel) {\n return null;\n }\n\n return divert;\n };\n\n public readonly DotSeparatedDivertPathComponents = (): Identifier[] =>\n this.Interleave(\n this.Spaced(this.IdentifierWithMetadata),\n this.Exclude(this.String(\".\"))\n );\n\n public readonly ParseDivertArrowOrTunnelOnwards = (): string | null => {\n let numArrows: number = 0;\n while (this.ParseString(\"->\") !== null) {\n numArrows += 1;\n }\n\n if (numArrows === 0) {\n return null;\n } else if (numArrows === 1) {\n return \"->\";\n } else if (numArrows === 2) {\n return \"->->\";\n }\n\n this.Error(\n \"Unexpected number of arrows in divert. Should only have '->' or '->->'\"\n );\n\n return \"->->\";\n };\n\n public readonly ParseDivertArrow = () => this.ParseString(\"->\");\n\n public readonly ParseThreadArrow = () => this.ParseString(\"<-\");\n\n /**\n * End Divert section.\n */\n\n /**\n * Begin Expressions section.\n */\n\n public _binaryOperators: InfixOperator[] = [];\n public _maxBinaryOpLength: number = 0;\n\n public readonly TempDeclarationOrAssignment = (): ParsedObject | null => {\n this.Whitespace();\n\n const isNewDeclaration: boolean = this.ParseTempKeyword();\n\n this.Whitespace();\n\n let varIdentifier: Identifier | null = null;\n if (isNewDeclaration) {\n varIdentifier = this.Expect(\n this.IdentifierWithMetadata,\n \"variable name\"\n ) as Identifier;\n } else {\n varIdentifier = this.Parse(this.IdentifierWithMetadata) as Identifier;\n }\n\n if (varIdentifier === null) {\n return null;\n }\n\n this.Whitespace();\n\n // += -=\n const isIncrement: boolean = this.ParseString(\"+\") !== null;\n const isDecrement: boolean = this.ParseString(\"-\") !== null;\n\n if (isIncrement && isDecrement) {\n this.Error(\"Unexpected sequence '+-'\");\n }\n\n if (this.ParseString(\"=\") === null) {\n // Definitely in an assignment expression?\n if (isNewDeclaration) {\n this.Error(\"Expected '='\");\n }\n\n return null;\n }\n\n const assignedExpression: Expression = this.Expect(\n this.Expression,\n \"value expression to be assigned\"\n ) as Expression;\n\n if (isIncrement || isDecrement) {\n const result = new IncDecExpression(\n varIdentifier,\n assignedExpression,\n isIncrement\n );\n return result;\n }\n\n const result = new VariableAssignment({\n variableIdentifier: varIdentifier,\n assignedExpression,\n isTemporaryNewDeclaration: isNewDeclaration,\n });\n\n return result;\n };\n\n public readonly DisallowIncrement = (expr: ParsedObject): void => {\n if (expr instanceof IncDecExpression) {\n this.Error(\n \"Can't use increment/decrement here. It can only be used on a ~ line\"\n );\n }\n };\n\n public readonly ParseTempKeyword = () => {\n const ruleId = this.BeginRule();\n\n if (this.Parse(this.Identifier) === \"temp\") {\n this.SucceedRule(ruleId);\n return true;\n }\n\n this.FailRule(ruleId);\n return false;\n };\n\n public readonly ReturnStatement = (): ReturnType | null => {\n this.Whitespace();\n\n const returnOrDone = this.Parse(this.Identifier);\n if (returnOrDone !== \"return\") {\n return null;\n }\n\n this.Whitespace();\n\n const expr = this.Parse(this.Expression) as Expression;\n\n const returnObj = new ReturnType(expr);\n\n return returnObj;\n };\n\n // Pratt Parser\n // aka \"Top down operator precedence parser\"\n // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/\n // Algorithm overview:\n // The two types of precedence are handled in two different ways:\n // ((((a . b) . c) . d) . e)\t\t\t#1\n // (a . (b . (c . (d . e))))\t\t\t#2\n // Where #1 is automatically handled by successive loops within the main 'while' in this function,\n // so long as continuing operators have lower (or equal) precedence (e.g. imagine some series of \"*\"s then \"+\" above.\n // ...and #2 is handled by recursion of the right hand term in the binary expression parser.\n // (see link for advice on how to extend for postfix and mixfix operators)\n public readonly Expression = (\n minimumPrecedence: number = 0\n ): Expression | null => {\n this.Whitespace();\n\n // First parse a unary expression e.g. \"-a\" or parethensised \"(1 + 2)\"\n let expr = this.ExpressionUnary();\n if (expr === null) {\n return null;\n }\n\n this.Whitespace();\n\n // Attempt to parse (possibly multiple) continuing infix expressions (e.g. 1 + 2 + 3)\n while (true) {\n const ruleId = this.BeginRule();\n\n // Operator\n const infixOp = this.ParseInfixOperator();\n if (infixOp !== null && infixOp.precedence > minimumPrecedence) {\n // Expect right hand side of operator\n const expectationMessage = `right side of '${infixOp.type}' expression`;\n const multiaryExpr = this.Expect(\n () => this.ExpressionInfixRight(expr, infixOp),\n expectationMessage\n );\n\n if (multiaryExpr === null) {\n // Fail for operator and right-hand side of multiary expression\n this.FailRule(ruleId);\n\n return null;\n }\n\n expr = this.SucceedRule(ruleId, multiaryExpr) as Expression;\n\n continue;\n }\n\n this.FailRule(ruleId);\n break;\n }\n\n this.Whitespace();\n\n return expr;\n };\n\n public readonly ExpressionUnary = (): Expression | null => {\n // Divert target is a special case - it can't have any other operators\n // applied to it, and we also want to check for it first so that we don't\n // confuse \"->\" for subtraction.\n const divertTarget = this.Parse(this.ExpressionDivertTarget) as Expression;\n if (divertTarget !== null) {\n return divertTarget;\n }\n\n let prefixOp: string = this.OneOf([\n this.String(\"-\"),\n this.String(\"!\"),\n ]) as string;\n\n // Don't parse like the string rules above, in case its actually\n // a variable that simply starts with \"not\", e.g. \"notable\".\n // This rule uses the Identifier rule, which will scan as much text\n // as possible before returning.\n if (prefixOp === null) {\n prefixOp = this.Parse(this.ExpressionNot) as string;\n }\n\n this.Whitespace();\n\n // - Since we allow numbers at the start of variable names, variable names are checked before literals\n // - Function calls before variable names in case we see parentheses\n let expr = this.OneOf([\n this.ExpressionList,\n this.ExpressionParen,\n this.ExpressionFunctionCall,\n this.ExpressionVariableName,\n this.ExpressionLiteral,\n ]) as Expression | null;\n\n // Only recurse immediately if we have one of the (usually optional) unary ops\n if (expr === null && prefixOp !== null) {\n expr = this.ExpressionUnary();\n }\n\n if (expr === null) {\n return null;\n } else if (prefixOp !== null) {\n expr = UnaryExpression.WithInner(expr, prefixOp) as Expression;\n }\n\n this.Whitespace();\n\n const postfixOp = this.OneOf([this.String(\"++\"), this.String(\"--\")]);\n\n if (postfixOp !== null) {\n const isInc: boolean = postfixOp === \"++\";\n\n if (!(expr instanceof VariableReference)) {\n this.Error(\n `can only increment and decrement variables, but saw '${expr}'.`\n );\n\n // Drop down and succeed without the increment after reporting error\n } else {\n const varRef = expr as VariableReference;\n expr = new IncDecExpression(varRef.identifier, isInc);\n }\n }\n\n return expr;\n };\n\n public readonly ExpressionNot = (): string | null => {\n const id = this.Identifier();\n if (id === \"not\") {\n return id;\n }\n\n return null;\n };\n\n public readonly ExpressionLiteral = (): Expression =>\n this.OneOf([\n this.ExpressionFloat,\n this.ExpressionInt,\n this.ExpressionBool,\n this.ExpressionString,\n ]) as Expression;\n\n public readonly ExpressionDivertTarget = (): Expression | null => {\n this.Whitespace();\n\n const divert = this.Parse(this.SingleDivert) as Divert;\n if (!divert || (divert && divert.isThread)) {\n return null;\n }\n\n this.Whitespace();\n\n return new DivertTarget(divert);\n };\n\n public readonly ExpressionInt = (): NumberExpression | null => {\n const intOrNull: number = this.ParseInt() as number;\n if (intOrNull === null) {\n return null;\n }\n\n return new NumberExpression(intOrNull, \"int\");\n };\n\n public readonly ExpressionFloat = (): NumberExpression | null => {\n const floatOrNull: number = this.ParseFloat() as number;\n if (floatOrNull === null) {\n return null;\n }\n\n return new NumberExpression(floatOrNull, \"float\");\n };\n\n public readonly ExpressionString = (): StringExpression | null => {\n const openQuote = this.ParseString('\"');\n if (openQuote === null) {\n return null;\n }\n\n // Set custom parser state flag so that within the text parser,\n // it knows to treat the quote character (\") as an end character\n this.parsingStringExpression = true;\n\n let textAndLogic: ParsedObject[] = this.Parse(\n this.MixedTextAndLogic\n ) as ParsedObject[];\n\n this.Expect(this.String('\"'), \"close quote for string expression\");\n\n this.parsingStringExpression = false;\n\n if (textAndLogic === null) {\n textAndLogic = [new Text(\"\")];\n } else if (textAndLogic.find((c) => c instanceof Divert)) {\n this.Error(\"String expressions cannot contain diverts (->)\");\n }\n\n return new StringExpression(textAndLogic);\n };\n\n public readonly ExpressionBool = (): NumberExpression | null => {\n const id = this.Parse(this.Identifier);\n if (id === \"true\") {\n return new NumberExpression(true, \"bool\");\n } else if (id === \"false\") {\n return new NumberExpression(false, \"bool\");\n }\n\n return null;\n };\n\n public readonly ExpressionFunctionCall = (): Expression | null => {\n const iden = this.Parse(this.IdentifierWithMetadata);\n if (iden === null) {\n return null;\n }\n\n this.Whitespace();\n\n const args = this.Parse(\n this.ExpressionFunctionCallArguments\n ) as Expression[];\n if (args === null) {\n return null;\n }\n\n return new FunctionCall(iden as Identifier, args);\n };\n\n public readonly ExpressionFunctionCallArguments = (): Expression[] | null => {\n if (this.ParseString(\"(\") === null) {\n return null;\n }\n\n // \"Exclude\" requires the rule to succeed, but causes actual comma string to be excluded from the list of results\n const commas: ParseRule = this.Exclude(this.String(\",\"));\n let args = this.Interleave(this.Expression, commas);\n if (args === null) {\n args = [];\n }\n\n this.Whitespace();\n\n this.Expect(this.String(\")\"), \"closing ')' for function call\");\n\n return args;\n };\n\n public readonly ExpressionVariableName = (): Expression | null => {\n const path = this.Interleave(\n this.IdentifierWithMetadata,\n this.Exclude(this.Spaced(this.String(\".\")))\n );\n\n if (path === null || Story.IsReservedKeyword(path[0].name)) {\n return null;\n }\n\n return new VariableReference(path);\n };\n\n public readonly ExpressionParen = (): Expression | null => {\n if (this.ParseString(\"(\") === null) {\n return null;\n }\n\n const innerExpr = this.Parse(this.Expression) as Expression;\n if (innerExpr === null) {\n return null;\n }\n\n this.Whitespace();\n\n this.Expect(this.String(\")\"), \"closing parenthesis ')' for expression\");\n\n return innerExpr;\n };\n\n public readonly ExpressionInfixRight = (\n left: Expression | null,\n op: InfixOperator\n ) => {\n if (!left) {\n return null;\n }\n\n this.Whitespace();\n\n const right = this.Parse(() =>\n this.Expression(op.precedence)\n ) as Expression;\n if (right) {\n // We assume that the character we use for the operator's type is the same\n // as that used internally by e.g. Runtime.Expression.Add, Runtime.Expression.Multiply etc\n const expr = new BinaryExpression(left, right, op.type);\n return expr;\n }\n\n return null;\n };\n\n private readonly ParseInfixOperator = (): InfixOperator | null => {\n for (const op of this._binaryOperators) {\n const ruleId: number = this.BeginRule();\n\n if (this.ParseString(op.type) !== null) {\n if (op.requireWhitespace) {\n if (this.Whitespace() === null) {\n this.FailRule(ruleId);\n\n continue;\n }\n }\n\n return this.SucceedRule(ruleId, op) as InfixOperator;\n }\n\n this.FailRule(ruleId);\n }\n\n return null;\n };\n\n public readonly ExpressionList = (): List | null => {\n this.Whitespace();\n\n if (this.ParseString(\"(\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n // When list has:\n // - 0 elements (null list) - this is okay, it's an empty list: \"()\"\n // - 1 element - it could be confused for a single non-list related\n // identifier expression in brackets, but this is a useless thing\n // to do, so we reserve that syntax for a list with one item.\n // - 2 or more elements - normal!\n const memberNames: Identifier[] = this.SeparatedList(\n this.ListMember,\n this.Spaced(this.String(\",\"))\n ) as Identifier[];\n\n this.Whitespace();\n\n // May have failed to parse the inner list - the parentheses may\n // be for a normal expression\n if (this.ParseString(\")\") === null) {\n return null;\n }\n return new List(memberNames);\n };\n\n public readonly ListMember = (): Identifier | null => {\n this.Whitespace();\n\n let identifier: Identifier = this.Parse(\n this.IdentifierWithMetadata\n ) as Identifier;\n if (identifier === null) {\n return null;\n }\n\n const dot = this.ParseString(\".\");\n if (dot !== null) {\n const identifier2: Identifier = this.Expect(\n this.IdentifierWithMetadata,\n `element name within the set ${identifier}`\n ) as Identifier;\n\n identifier.name += `.${identifier2?.name}`;\n }\n\n this.Whitespace();\n\n return identifier;\n };\n\n public readonly RegisterExpressionOperators = () => {\n // These will be tried in order, so we need \"<=\" before \"<\"\n // for correctness\n\n this.RegisterBinaryOperator(\"&&\", 1);\n this.RegisterBinaryOperator(\"||\", 1);\n this.RegisterBinaryOperator(\"and\", 1, true);\n this.RegisterBinaryOperator(\"or\", 1, true);\n this.RegisterBinaryOperator(\"==\", 2);\n this.RegisterBinaryOperator(\">=\", 2);\n this.RegisterBinaryOperator(\"<=\", 2);\n this.RegisterBinaryOperator(\"<\", 2);\n this.RegisterBinaryOperator(\">\", 2);\n this.RegisterBinaryOperator(\"!=\", 2);\n\n // (apples, oranges) + cabbages has (oranges, cabbages) === true\n this.RegisterBinaryOperator(\"?\", 3);\n this.RegisterBinaryOperator(\"has\", 3, true);\n this.RegisterBinaryOperator(\"!?\", 3);\n this.RegisterBinaryOperator(\"hasnt\", 3, true);\n this.RegisterBinaryOperator(\"^\", 3);\n\n this.RegisterBinaryOperator(\"+\", 4);\n this.RegisterBinaryOperator(\"-\", 5);\n this.RegisterBinaryOperator(\"*\", 6);\n this.RegisterBinaryOperator(\"/\", 7);\n\n this.RegisterBinaryOperator(\"%\", 8);\n this.RegisterBinaryOperator(\"mod\", 8, true);\n };\n\n public readonly RegisterBinaryOperator = (\n op: string,\n precedence: number,\n requireWhitespace: boolean = false\n ): void => {\n const infix = new InfixOperator(op, precedence, requireWhitespace);\n this._binaryOperators.push(infix);\n this._maxBinaryOpLength = Math.max(this._maxBinaryOpLength, op.length);\n };\n\n /**\n * End Expressions section.\n */\n\n /**\n * Begin Include section.\n */\n\n private _rootParser: InkParser;\n private _openFilenames: string[] = [];\n\n public readonly IncludeStatement = () => {\n this.Whitespace();\n\n if (this.ParseString(\"INCLUDE\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n let filename: string = this.Expect(\n () => this.ParseUntilCharactersFromString(\"\\n\\r\"),\n \"filename for include statement\"\n ) as string;\n\n filename = filename.replace(new RegExp(/[ \\t]+$/g), \"\");\n\n // Working directory should already have been set up relative to the root ink file.\n const fullFilename = this.fileHandler.ResolveInkFilename(filename);\n\n if (this.FilenameIsAlreadyOpen(fullFilename)) {\n this.Error(\n `Recursive INCLUDE detected: '${fullFilename}' is already open.`\n );\n this.ParseUntilCharactersFromString(\"\\r\\n\");\n return new IncludedFile(null);\n } else {\n this.AddOpenFilename(fullFilename);\n }\n\n let includedStory: Story | null = null;\n let includedString: string = \"\";\n try {\n includedString =\n this._rootParser.fileHandler.LoadInkFileContents(fullFilename);\n } catch (err) {\n this.Error(`Failed to load: '${filename}'.\\nError:${err}`);\n }\n\n if (includedString != null) {\n const parser: InkParser = new InkParser(\n includedString,\n filename,\n this._externalErrorHandler,\n this._rootParser,\n this.fileHandler\n );\n\n includedStory = parser.ParseStory();\n }\n\n this.RemoveOpenFilename(fullFilename);\n\n // Return valid IncludedFile object even if there were errors when parsing.\n // We don't want to attempt to re-parse the include line as something else,\n // and we want to include the bits that *are* valid, so we don't generate\n // more errors than necessary.\n return new IncludedFile(includedStory);\n };\n\n public readonly FilenameIsAlreadyOpen = (fullFilename: string): boolean =>\n this._rootParser._openFilenames.includes(fullFilename);\n\n public readonly AddOpenFilename = (fullFilename: string): void => {\n this._rootParser._openFilenames.push(fullFilename);\n };\n\n public readonly RemoveOpenFilename = (fullFilename: string) => {\n this._rootParser._openFilenames.splice(\n this._rootParser._openFilenames.indexOf(fullFilename),\n 1\n );\n };\n\n /**\n * End Include section.\n */\n\n /**\n * Begin Knot section.\n */\n\n public readonly KnotDefinition = (): Knot | null => {\n const knotDecl: FlowDecl = this.Parse(this.KnotDeclaration) as FlowDecl;\n if (knotDecl === null) {\n return null;\n }\n\n this.Expect(\n this.EndOfLine,\n \"end of line after knot name definition\",\n this.SkipToNextLine\n );\n\n const innerKnotStatements: ParseRule = (): ParsedObject[] =>\n this.StatementsAtLevel(StatementLevel.Knot);\n\n const content = this.Expect(\n innerKnotStatements,\n \"at least one line within the knot\",\n this.KnotStitchNoContentRecoveryRule\n ) as ParsedObject[];\n\n return new Knot(knotDecl.name, content, knotDecl.args, knotDecl.isFunction);\n };\n\n public readonly KnotDeclaration = (): FlowDecl | null => {\n this.Whitespace();\n\n if (this.KnotTitleEquals() === null) {\n return null;\n }\n\n this.Whitespace();\n\n const identifier: Identifier = this.Parse(\n this.IdentifierWithMetadata\n ) as Identifier;\n let knotName: Identifier;\n\n const isFunc: boolean = identifier?.name === \"function\";\n if (isFunc) {\n this.Expect(this.Whitespace, \"whitespace after the 'function' keyword\");\n\n knotName = this.Parse(this.IdentifierWithMetadata) as Identifier;\n } else {\n knotName = identifier;\n }\n\n if (knotName === null) {\n this.Error(`Expected the name of the ${isFunc ? \"function\" : \"knot\"}`);\n knotName = new Identifier(\"\"); // prevent later null ref\n }\n\n this.Whitespace();\n\n const parameterNames: Argument[] = this.Parse(\n this.BracketedKnotDeclArguments\n ) as Argument[];\n\n this.Whitespace();\n\n // Optional equals after name\n this.Parse(this.KnotTitleEquals);\n\n return new FlowDecl(knotName, parameterNames, isFunc);\n };\n\n public readonly KnotTitleEquals = (): string | null => {\n // 2+ \"=\" starts a knot\n const multiEquals = this.ParseCharactersFromString(\"=\");\n if (multiEquals === null || multiEquals.length <= 1) {\n return null;\n }\n\n return multiEquals;\n };\n\n public readonly StitchDefinition = (): ParseRuleReturn => {\n const decl = this.Parse(this.StitchDeclaration) as FlowDecl;\n if (decl === null) {\n return null;\n }\n\n this.Expect(\n this.EndOfLine,\n \"end of line after stitch name\",\n this.SkipToNextLine\n );\n\n const innerStitchStatements: ParseRule = () =>\n this.StatementsAtLevel(StatementLevel.Stitch);\n\n const content = this.Expect(\n innerStitchStatements,\n \"at least one line within the stitch\",\n this.KnotStitchNoContentRecoveryRule\n ) as ParsedObject[];\n\n return new Stitch(decl.name, content, decl.args, decl.isFunction);\n };\n\n public readonly StitchDeclaration = (): FlowDecl | null => {\n this.Whitespace();\n\n // Single \"=\" to define a stitch\n if (this.ParseString(\"=\") === null) {\n return null;\n }\n\n // If there's more than one \"=\", that's actually a knot definition (or divert), so this rule should fail\n if (this.ParseString(\"=\") !== null) {\n return null;\n }\n\n this.Whitespace();\n\n // Stitches aren't allowed to be functions, but we parse it anyway and report the error later\n const isFunc: boolean = this.ParseString(\"function\") !== null;\n if (isFunc) {\n this.Whitespace();\n }\n\n const stitchName: Identifier = this.Parse(\n this.IdentifierWithMetadata\n ) as Identifier;\n if (stitchName === null) {\n return null;\n }\n\n this.Whitespace();\n\n const flowArgs: Argument[] = this.Parse(\n this.BracketedKnotDeclArguments\n ) as Argument[];\n\n this.Whitespace();\n\n return new FlowDecl(stitchName, flowArgs, isFunc);\n };\n\n public readonly KnotStitchNoContentRecoveryRule = (): ParseRuleReturn => {\n // Jump ahead to the next knot or the end of the file\n this.ParseUntil(this.KnotDeclaration, new CharacterSet(\"=\"), null);\n\n const recoveredFlowContent: ParsedObject[] = [new Text(\"\")];\n\n return recoveredFlowContent;\n };\n\n public readonly BracketedKnotDeclArguments = (): Argument[] | null => {\n if (this.ParseString(\"(\") === null) {\n return null;\n }\n\n let flowArguments = this.Interleave(\n this.Spaced(this.FlowDeclArgument),\n this.Exclude(this.String(\",\"))\n );\n\n this.Expect(this.String(\")\"), \"closing ')' for parameter list\");\n\n // If no parameters, create an empty list so that this method is type safe and\n // doesn't attempt to return the ParseSuccess object\n if (flowArguments === null) {\n flowArguments = [];\n }\n\n return flowArguments;\n };\n\n public readonly FlowDeclArgument = (): Argument | null => {\n // Possible forms:\n // name\n // -> name (variable divert target argument\n // ref name\n // ref -> name (variable divert target by reference)\n const firstIden = this.Parse(this.IdentifierWithMetadata) as Identifier;\n this.Whitespace();\n\n const divertArrow = this.ParseDivertArrow();\n\n this.Whitespace();\n\n const secondIden = this.Parse(this.IdentifierWithMetadata) as Identifier;\n\n if (firstIden == null && secondIden === null) {\n return null;\n }\n\n const flowArg = new Argument();\n if (divertArrow !== null) {\n flowArg.isDivertTarget = true;\n }\n\n // Passing by reference\n if (firstIden !== null && firstIden.name === \"ref\") {\n if (secondIden === null) {\n this.Error(\"Expected an parameter name after 'ref'\");\n }\n\n flowArg.identifier = secondIden;\n flowArg.isByReference = true;\n } else {\n // Simple argument name\n if (flowArg.isDivertTarget) {\n flowArg.identifier = secondIden;\n } else {\n flowArg.identifier = firstIden;\n }\n\n if (flowArg.identifier === null) {\n this.Error(\"Expected an parameter name\");\n }\n\n flowArg.isByReference = false;\n }\n\n return flowArg;\n };\n\n public readonly ExternalDeclaration = (): ExternalDeclaration | null => {\n this.Whitespace();\n\n const external = this.Parse(\n this.IdentifierWithMetadata\n ) as Identifier | null;\n if (external === null || external.name != \"EXTERNAL\") {\n return null;\n }\n\n this.Whitespace();\n\n const funcIdentifier: Identifier =\n (this.Expect(\n this.IdentifierWithMetadata,\n \"name of external function\"\n ) as Identifier | null) || new Identifier(\"\");\n\n this.Whitespace();\n\n let parameterNames = this.Expect(\n this.BracketedKnotDeclArguments,\n `declaration of arguments for EXTERNAL, even if empty, i.e. 'EXTERNAL ${funcIdentifier}()'`\n ) as Argument[];\n\n if (parameterNames === null) {\n parameterNames = [];\n }\n\n const argNames = parameterNames\n .map((arg) => arg.identifier?.name)\n .filter(filterUndef);\n\n return new ExternalDeclaration(funcIdentifier, argNames);\n };\n\n /**\n * End Knot section.\n */\n\n /**\n * Start Logic section.\n */\n\n private _identifierCharSet: CharacterSet | null = null;\n\n get identifierCharSet(): CharacterSet {\n if (this._identifierCharSet === null) {\n (this._identifierCharSet = new CharacterSet())\n .AddRange(\"A\", \"Z\")\n .AddRange(\"a\", \"z\")\n .AddRange(\"0\", \"9\")\n .Add(\"_\");\n\n // Enable non-ASCII characters for story identifiers.\n this.ExtendIdentifierCharacterRanges(this._identifierCharSet);\n }\n\n return this._identifierCharSet;\n }\n\n public readonly LogicLine = (): ParsedObject | null => {\n this.Whitespace();\n\n if (this.ParseString(\"~\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n // Some example lines we need to be able to distinguish between:\n // ~ temp x = 5 -- var decl + assign\n // ~ temp x -- var decl\n // ~ x = 5 -- var assign\n // ~ x -- expr (not var decl or assign)\n // ~ f() -- expr\n // We don't treat variable decl/assign as an expression since we don't want an assignment\n // to have a return value, or to be used in compound expressions.\n const afterTilde: ParseRule = () =>\n this.OneOf([\n this.ReturnStatement,\n this.TempDeclarationOrAssignment,\n this.Expression,\n ]);\n\n let result = this.Expect(\n afterTilde,\n \"expression after '~'\",\n this.SkipToNextLine\n ) as ParsedObject;\n\n // Prevent further errors, already reported expected expression and have skipped to next line.\n if (result === null) {\n return new ContentList();\n }\n\n // Parse all expressions, but tell the writer off if they did something useless like:\n // ~ 5 + 4\n // And even:\n // ~ false && myFunction()\n // ...since it's bad practice, and won't do what they expect if\n // they're expecting C's lazy evaluation.\n if (\n result instanceof Expression &&\n !(result instanceof FunctionCall || result instanceof IncDecExpression)\n ) {\n this.Error(\n \"Logic following a '~' can't be that type of expression. It can only be something like:\\n\\t~ return\\n\\t~ var x = blah\\n\\t~ x++\\n\\t~ myFunction()\"\n );\n }\n\n // Line is pure function call? e.g.\n // ~ f()\n // Add extra pop to make sure we tidy up after ourselves.\n // We no longer need anything on the evaluation stack.\n const funCall = asOrNull(result, FunctionCall);\n if (funCall) {\n funCall.shouldPopReturnedValue = true;\n }\n\n // If the expression contains a function call, then it could produce a text side effect,\n // in which case it needs a newline on the end. e.g.\n // ~ printMyName()\n // ~ x = 1 + returnAValueAndAlsoPrintStuff()\n // If no text gets printed, then the extra newline will have to be culled later.\n // Multiple newlines on the output will be removed, so there will be no \"leak\" for\n // long running calculations. It's disappointingly messy though :-/\n if (result.Find(FunctionCall)() !== null) {\n result = new ContentList(\n result as unknown as ParsedObject[],\n new Text(\"\\n\")\n );\n }\n\n this.Expect(this.EndOfLine, \"end of line\", this.SkipToNextLine);\n\n return result as ParsedObject;\n };\n\n public readonly VariableDeclaration = (): ParsedObject | null => {\n this.Whitespace();\n\n const id = this.Parse(this.Identifier);\n if (id !== \"VAR\") {\n return null;\n }\n\n this.Whitespace();\n\n const varName = this.Expect(\n this.IdentifierWithMetadata,\n \"variable name\"\n ) as Identifier;\n\n this.Whitespace();\n\n this.Expect(\n this.String(\"=\"),\n \"the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)\"\n );\n\n this.Whitespace();\n\n const definition = this.Expect(this.Expression, \"initial value for \");\n\n const expr = definition as Expression;\n\n if (expr) {\n const check =\n expr instanceof NumberExpression ||\n expr instanceof StringExpression ||\n expr instanceof DivertTarget ||\n expr instanceof VariableReference ||\n expr instanceof List;\n\n if (!check) {\n this.Error(\n \"initial value for a variable must be a number, constant, list or divert target\"\n );\n }\n\n if (this.Parse(this.ListElementDefinitionSeparator) !== null) {\n this.Error(\n \"Unexpected ','. If you're trying to declare a new list, use the LIST keyword, not VAR\"\n );\n } else if (expr instanceof StringExpression) {\n // Ensure string expressions are simple\n const strExpr = expr as StringExpression;\n if (!strExpr.isSingleString) {\n this.Error(\"Constant strings cannot contain any logic.\");\n }\n }\n\n const result = new VariableAssignment({\n assignedExpression: expr,\n isGlobalDeclaration: true,\n variableIdentifier: varName,\n });\n\n return result;\n }\n\n return null;\n };\n\n public readonly ListDeclaration = (): VariableAssignment | null => {\n this.Whitespace();\n\n const id = this.Parse(this.Identifier);\n if (id != \"LIST\") {\n return null;\n }\n\n this.Whitespace();\n\n const varName = this.Expect(\n this.IdentifierWithMetadata,\n \"list name\"\n ) as Identifier;\n\n this.Whitespace();\n\n this.Expect(\n this.String(\"=\"),\n \"the '=' for an assignment of the list definition\"\n );\n\n this.Whitespace();\n\n const definition = this.Expect(\n this.ListDefinition,\n \"list item names\"\n ) as ListDefinition;\n\n if (definition) {\n definition.identifier = new Identifier(varName.name);\n return new VariableAssignment({\n variableIdentifier: varName,\n listDef: definition,\n });\n }\n\n return null;\n };\n\n public readonly ListDefinition = (): ListDefinition | null => {\n this.AnyWhitespace();\n\n const allElements = this.SeparatedList(\n this.ListElementDefinition,\n this.ListElementDefinitionSeparator\n ) as ListElementDefinition[];\n\n if (allElements === null) {\n return null;\n }\n\n return new ListDefinition(allElements);\n };\n\n public readonly ListElementDefinitionSeparator = (): string | null => {\n this.AnyWhitespace();\n\n if (this.ParseString(\",\") === null) {\n return null;\n }\n\n this.AnyWhitespace();\n\n return \",\";\n };\n\n public readonly ListElementDefinition = () => {\n const inInitialList = this.ParseString(\"(\") !== null;\n let needsToCloseParen = inInitialList;\n\n this.Whitespace();\n\n const name = this.Parse(this.IdentifierWithMetadata) as Identifier | null;\n if (name === null) {\n return null;\n }\n\n this.Whitespace();\n\n if (inInitialList) {\n if (this.ParseString(\")\") != null) {\n needsToCloseParen = false;\n this.Whitespace();\n }\n }\n\n let elementValue: number | null = null;\n if (this.ParseString(\"=\") !== null) {\n this.Whitespace();\n\n const elementValueNum = this.Expect(\n this.ExpressionInt,\n \"value to be assigned to list item\"\n ) as NumberExpression;\n\n if (elementValueNum !== null) {\n elementValue = elementValueNum.value as number;\n }\n\n if (needsToCloseParen) {\n this.Whitespace();\n\n if (this.ParseString(\")\") !== null) {\n needsToCloseParen = false;\n }\n }\n }\n\n if (needsToCloseParen) {\n this.Error(\"Expected closing ')'\");\n }\n\n return new ListElementDefinition(name, inInitialList, elementValue);\n };\n\n public readonly ConstDeclaration = (): ParsedObject | null => {\n this.Whitespace();\n\n const id = this.Parse(this.Identifier);\n if (id !== \"CONST\") {\n return null;\n }\n\n this.Whitespace();\n\n const varName = this.Expect(\n this.IdentifierWithMetadata,\n \"constant name\"\n ) as Identifier;\n\n this.Whitespace();\n\n this.Expect(\n this.String(\"=\"),\n \"the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)\"\n );\n\n this.Whitespace();\n\n const expr = this.Expect(\n this.Expression,\n \"initial value for \"\n ) as Expression;\n\n const check =\n expr instanceof NumberExpression ||\n expr instanceof DivertTarget ||\n expr instanceof StringExpression;\n\n if (!check) {\n this.Error(\n \"initial value for a constant must be a number or divert target\"\n );\n } else if (expr instanceof StringExpression) {\n // Ensure string expressions are simple\n const strExpr = expr as StringExpression;\n if (!strExpr.isSingleString) {\n this.Error(\"Constant strings cannot contain any logic.\");\n }\n }\n\n const result = new ConstantDeclaration(varName, expr);\n\n return result;\n };\n\n public readonly InlineLogicOrGlueOrStartTag = (): ParsedObject =>\n this.OneOf([this.InlineLogic, this.Glue, this.StartTag]) as ParsedObject;\n\n public readonly Glue = (): Glue | null => {\n // Don't want to parse whitespace, since it might be important\n // surrounding the glue.\n const glueStr = this.ParseString(\"<>\");\n if (glueStr !== null) {\n return new Glue(new RuntimeGlue());\n }\n\n return null;\n };\n\n public readonly InlineLogic = () => {\n if (this.ParseString(\"{\") === null) {\n return null;\n }\n\n let wasParsingString = this.parsingStringExpression;\n let wasTagActive = this.tagActive;\n\n this.Whitespace();\n\n const logic = this.Expect(\n this.InnerLogic,\n \"some kind of logic, conditional or sequence within braces: { ... }\"\n ) as ParsedObject;\n\n if (logic === null) {\n this.parsingStringExpression = wasParsingString;\n return null;\n }\n\n this.DisallowIncrement(logic);\n\n let contentList = asOrNull(logic, ContentList);\n if (!contentList) {\n contentList = new ContentList(logic as unknown as ParsedObject[]);\n }\n\n this.Whitespace();\n\n this.Expect(this.String(\"}\"), \"closing brace '}' for inline logic\");\n\n // Allow nested strings and logic\n this.parsingStringExpression = wasParsingString;\n\n // Difference between:\n //\n // 1) A thing # {image}.jpg\n // 2) A {red #red|blue #blue} sequence.\n //\n // When logic ends in (1) we still want tag to continue.\n // When logic ends in (2) we want to auto-end the tag.\n // Side note: we simply disallow tags within strings.\n if (!wasTagActive) this.EndTagIfNecessary(contentList);\n\n return contentList;\n };\n\n public readonly InnerLogic = (): ParsedObject | null => {\n this.Whitespace();\n\n // Explicitly try the combinations of inner logic\n // that could potentially have conflicts first.\n\n // Explicit sequence annotation?\n const explicitSeqType: SequenceType = this.ParseObject(\n this.SequenceTypeAnnotation\n ) as SequenceType;\n\n if (explicitSeqType !== null) {\n const contentLists = this.Expect(\n this.InnerSequenceObjects,\n \"sequence elements (for cycle/stoping etc)\"\n ) as ContentList[];\n\n if (contentLists === null) {\n return null;\n }\n\n return new Sequence(contentLists, explicitSeqType);\n }\n\n // Conditional with expression?\n const initialQueryExpression = this.Parse(\n this.ConditionExpression\n ) as Expression;\n if (initialQueryExpression) {\n const conditional = this.Expect(\n () => this.InnerConditionalContent(initialQueryExpression),\n \"conditional content following query\"\n ) as Conditional;\n\n return conditional;\n }\n\n // Now try to evaluate each of the \"full\" rules in turn\n const rules: ParseRule[] = [\n // Conditional still necessary, since you can have a multi-line conditional\n // without an initial query expression:\n // {\n // - true: this is true\n // - false: this is false\n // }\n this.InnerConditionalContent as ParseRule,\n this.InnerSequence,\n this.InnerExpression,\n ];\n\n //let wasTagActiveAtStartOfScope = this.tagActive;\n\n // Adapted from \"OneOf\" structuring rule except that in\n // order for the rule to succeed, it has to maximally\n // cover the entire string within the { }. Used to\n // differentiate between:\n // {myVar} -- Expression (try first)\n // {my content is jolly} -- sequence with single element\n for (const rule of rules) {\n const ruleId: number = this.BeginRule();\n\n const result: ParsedObject = this.ParseObject(rule) as ParsedObject;\n if (result) {\n // Not yet at end?\n if (this.Peek(this.Spaced(this.String(\"}\"))) === null) {\n this.FailRule(ruleId);\n } else {\n // Full parse of content within braces\n return this.SucceedRule(ruleId, result) as ParsedObject;\n }\n } else {\n this.FailRule(ruleId);\n }\n }\n\n return null;\n };\n\n public readonly InnerExpression = (): ParsedObject => {\n const expr = this.Parse(this.Expression) as Expression;\n if (expr) {\n expr.outputWhenComplete = true;\n }\n\n return expr;\n };\n\n public readonly IdentifierWithMetadata = (): Identifier | null => {\n const id = this.Identifier();\n if (id === null) {\n return null;\n }\n return new Identifier(id);\n };\n\n // Note: we allow identifiers that start with a number,\n // but not if they *only* comprise numbers\n public readonly Identifier = (): string | null => {\n // Parse remaining characters (if any)\n const name = this.ParseCharactersFromCharSet(this.identifierCharSet);\n if (name === null) {\n return null;\n }\n\n // Reject if it's just a number\n let isNumberCharsOnly: boolean = true;\n for (let c of name) {\n if (!(c >= \"0\" && c <= \"9\")) {\n isNumberCharsOnly = false;\n break;\n }\n }\n\n if (isNumberCharsOnly) {\n return null;\n }\n\n return name;\n };\n\n /**\n * End Logic section.\n */\n\n /**\n * Begin Sequences section.\n */\n\n public _sequenceTypeSymbols: CharacterSet = new CharacterSet(\"!&~$\");\n\n public readonly InnerSequence = (): Sequence | null => {\n this.Whitespace();\n\n // Default sequence type\n let seqType: SequenceType = SequenceType.Stopping;\n\n // Optional explicit sequence type\n const parsedSeqType: SequenceType = this.Parse(\n this.SequenceTypeAnnotation\n ) as SequenceType;\n\n if (parsedSeqType !== null) {\n seqType = parsedSeqType;\n }\n\n const contentLists = this.Parse(this.InnerSequenceObjects) as ContentList[];\n if (contentLists === null || contentLists.length <= 1) {\n return null;\n }\n\n return new Sequence(contentLists, seqType);\n };\n\n public readonly SequenceTypeAnnotation = (): ParseRuleReturn => {\n let annotation = this.Parse(\n this.SequenceTypeSymbolAnnotation\n ) as SequenceType;\n\n if (annotation === null) {\n annotation = this.Parse(this.SequenceTypeWordAnnotation) as SequenceType;\n }\n\n if (annotation === null) {\n return null;\n }\n\n switch (annotation) {\n case SequenceType.Once:\n case SequenceType.Cycle:\n case SequenceType.Stopping:\n case SequenceType.Shuffle:\n // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison\n case SequenceType.Shuffle | SequenceType.Stopping:\n // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison\n case SequenceType.Shuffle | SequenceType.Once:\n break;\n default:\n this.Error(`Sequence type combination not supported: ${annotation}`);\n return SequenceType.Stopping;\n }\n\n return annotation;\n };\n\n public readonly SequenceTypeSymbolAnnotation = (): ParseRuleReturn => {\n if (this._sequenceTypeSymbols === null) {\n this._sequenceTypeSymbols = new CharacterSet(\"!&~$ \");\n }\n\n let sequenceType = 0 as SequenceType;\n const sequenceAnnotations = this.ParseCharactersFromCharSet(\n this._sequenceTypeSymbols\n );\n\n if (sequenceAnnotations === null) {\n return null;\n }\n\n for (const symbolChar of sequenceAnnotations) {\n switch (symbolChar) {\n case \"!\":\n sequenceType |= SequenceType.Once;\n break;\n case \"&\":\n sequenceType |= SequenceType.Cycle;\n break;\n case \"~\":\n sequenceType |= SequenceType.Shuffle;\n break;\n case \"$\":\n sequenceType |= SequenceType.Stopping;\n break;\n }\n }\n\n if (sequenceType === (0 as SequenceType)) {\n return null;\n }\n\n return sequenceType;\n };\n\n public readonly SequenceTypeWordAnnotation = (): ParseRuleReturn => {\n const sequenceTypes = this.Interleave(\n this.SequenceTypeSingleWord,\n this.Exclude(this.Whitespace)\n );\n\n if (sequenceTypes === null || sequenceTypes.length === 0) {\n return null;\n }\n\n if (this.ParseString(\":\") === null) {\n return null;\n }\n\n let combinedSequenceType = 0 as SequenceType;\n for (const seqType of sequenceTypes) {\n combinedSequenceType |= seqType!;\n }\n\n return combinedSequenceType;\n };\n\n public readonly SequenceTypeSingleWord = () => {\n let seqType: SequenceType | null = null;\n\n const word = this.Parse(this.IdentifierWithMetadata) as Identifier | null;\n\n if (word !== null) {\n switch (word.name) {\n case \"once\":\n seqType = SequenceType.Once;\n break;\n case \"cycle\":\n seqType = SequenceType.Cycle;\n break;\n case \"shuffle\":\n seqType = SequenceType.Shuffle;\n break;\n case \"stopping\":\n seqType = SequenceType.Stopping;\n break;\n }\n }\n\n if (seqType === null) {\n return null;\n }\n\n return seqType;\n };\n\n public readonly InnerSequenceObjects = (): ContentList[] => {\n const multiline = this.Parse(this.Newline) !== null;\n\n let result: ContentList[] | null = null;\n if (multiline) {\n result = this.Parse(this.InnerMultilineSequenceObjects) as ContentList[];\n } else {\n result = this.Parse(this.InnerInlineSequenceObjects) as ContentList[];\n }\n\n return result;\n };\n\n public readonly InnerInlineSequenceObjects = (): ContentList[] | null => {\n const interleavedContentAndPipes = this.Interleave(\n this.Optional(this.MixedTextAndLogic),\n this.String(\"|\"),\n null,\n false\n );\n\n if (interleavedContentAndPipes === null) {\n return null;\n }\n\n const result = [];\n\n // The content and pipes won't necessarily be perfectly interleaved in the sense that\n // the content can be missing, but in that case it's intended that there's blank content.\n let justHadContent: boolean = false;\n for (const contentOrPipe of interleavedContentAndPipes) {\n // Pipe/separator\n if ((contentOrPipe as any) === \"|\") {\n // Expected content, saw pipe - need blank content now\n if (!justHadContent) {\n // Add blank content\n result.push(new ContentList());\n }\n\n justHadContent = false;\n } else {\n // Real content\n const content = contentOrPipe as unknown as ParsedObject[];\n if (content === null) {\n this.Error(\n `Expected content, but got ${contentOrPipe as unknown as string} (this is an ink compiler bug!)`\n );\n } else {\n result.push(new ContentList(content));\n }\n\n justHadContent = true;\n }\n }\n\n // Ended in a pipe? Need to insert final blank content\n if (!justHadContent) {\n result.push(new ContentList());\n }\n\n return result;\n };\n\n public readonly InnerMultilineSequenceObjects = (): ContentList[] | null => {\n this.MultilineWhitespace();\n\n const contentLists = this.OneOrMore(\n this.SingleMultilineSequenceElement\n ) as ContentList[];\n if (contentLists === null) {\n return null;\n }\n\n return contentLists;\n };\n\n public readonly SingleMultilineSequenceElement = () => {\n this.Whitespace();\n\n // Make sure we're not accidentally parsing a divert\n if (this.ParseString(\"->\") !== null) {\n return null;\n }\n\n if (this.ParseString(\"-\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n const content: ParsedObject[] = this.StatementsAtLevel(\n StatementLevel.InnerBlock\n );\n\n if (content === null) {\n this.MultilineWhitespace();\n } else {\n // Add newline at the start of each branch\n content.unshift(new Text(\"\\n\"));\n }\n\n return new ContentList(content);\n };\n\n /**\n * End Sequences section.\n */\n\n /**\n * Begin Statements section.\n */\n\n private _statementRulesAtLevel: ParseRule[][] = [];\n private _statementBreakRulesAtLevel: ParseRule[][] = [];\n\n public readonly StatementsAtLevel = (\n level: StatementLevel\n ): ParsedObject[] => {\n // Check for error: Should not be allowed gather dashes within an inner block\n if (level === StatementLevel.InnerBlock) {\n const badGatherDashCount = this.Parse(this.GatherDashes) as ParsedObject;\n if (badGatherDashCount !== null) {\n this.Error(\n \"You can't use a gather (the dashes) within the { curly braces } context. For multi-line sequences and conditions, you should only use one dash.\"\n );\n }\n }\n\n return this.Interleave(\n this.Optional(this.MultilineWhitespace),\n () => this.StatementAtLevel(level),\n () => this.StatementsBreakForLevel(level)\n );\n };\n\n public readonly StatementAtLevel = (level: StatementLevel): ParsedObject => {\n const rulesAtLevel: ParseRule[] =\n this._statementRulesAtLevel[level as number];\n const statement = this.OneOf(rulesAtLevel) as ReturnType;\n\n // For some statements, allow them to parse, but create errors, since\n // writers may think they can use the statement, so it's useful to have\n // the error message.\n if (level === StatementLevel.Top) {\n if (statement instanceof ReturnType) {\n this.Error(\"should not have return statement outside of a knot\");\n }\n }\n\n return statement;\n };\n\n public readonly StatementsBreakForLevel = (\n level: StatementLevel\n ): ParseRuleReturn => {\n this.Whitespace();\n\n const breakRules: ParseRule[] =\n this._statementBreakRulesAtLevel[level as number];\n const breakRuleResult = this.OneOf(breakRules);\n if (breakRuleResult === null) {\n return null;\n }\n\n return breakRuleResult;\n };\n\n public readonly GenerateStatementLevelRules = () => {\n const levels: StatementLevel[] = Object.values(\n StatementLevel\n ) as StatementLevel[];\n\n this._statementRulesAtLevel = \"f\"\n .repeat(levels.length)\n .split(\"f\")\n .map(() => []);\n\n this._statementBreakRulesAtLevel = \"f\"\n .repeat(levels.length)\n .split(\"f\")\n .map(() => []);\n\n for (const level of levels) {\n const rulesAtLevel: ParseRule[] = [];\n const breakingRules: ParseRule[] = [];\n\n // Diverts can go anywhere\n rulesAtLevel.push(this.Line(this.MultiDivert));\n\n // Knots can only be parsed at Top/Global scope\n if (level >= StatementLevel.Top) {\n rulesAtLevel.push(this.KnotDefinition);\n }\n\n rulesAtLevel.push(this.Line(this.Choice));\n\n rulesAtLevel.push(this.Line(this.AuthorWarning));\n\n // Gather lines would be confused with multi-line block separators, like\n // within a multi-line if statement\n if (level > StatementLevel.InnerBlock) {\n rulesAtLevel.push(this.Gather);\n }\n\n // Stitches (and gathers) can (currently) only go in Knots and top level\n if (level >= StatementLevel.Knot) {\n rulesAtLevel.push(this.StitchDefinition);\n }\n\n // Global variable declarations can go anywhere\n rulesAtLevel.push(this.Line(this.ListDeclaration));\n rulesAtLevel.push(this.Line(this.VariableDeclaration));\n rulesAtLevel.push(this.Line(this.ConstDeclaration));\n rulesAtLevel.push(this.Line(this.ExternalDeclaration));\n\n // Global include can go anywhere\n rulesAtLevel.push(this.Line(this.IncludeStatement));\n\n // Normal logic / text can go anywhere\n rulesAtLevel.push(this.LogicLine);\n rulesAtLevel.push(this.LineOfMixedTextAndLogic);\n\n // --------\n // Breaking rules\n\n // Break current knot with a new knot\n if (level <= StatementLevel.Knot) {\n breakingRules.push(this.KnotDeclaration);\n }\n\n // Break current stitch with a new stitch\n if (level <= StatementLevel.Stitch) {\n breakingRules.push(this.StitchDeclaration);\n }\n\n // Breaking an inner block (like a multi-line condition statement)\n if (level <= StatementLevel.InnerBlock) {\n breakingRules.push(this.ParseDashNotArrow);\n breakingRules.push(this.String(\"}\"));\n }\n\n this._statementRulesAtLevel[level as number] = rulesAtLevel;\n this._statementBreakRulesAtLevel[level as number] = breakingRules;\n }\n };\n\n public readonly SkipToNextLine = (): typeof ParseSuccess => {\n this.ParseUntilCharactersFromString(\"\\n\\r\");\n this.ParseNewline();\n\n return ParseSuccess;\n };\n\n // Modifier to turn a rule into one that expects a newline on the end.\n // e.g. anywhere you can use \"MixedTextAndLogic\" as a rule, you can use\n // \"Line(MixedTextAndLogic)\" to specify that it expects a newline afterwards.\n public readonly Line =\n (inlineRule: ParseRule): ParseRule =>\n () => {\n const result = this.ParseObject(inlineRule);\n if (result === null) {\n return null;\n }\n\n this.Expect(this.EndOfLine, \"end of line\", this.SkipToNextLine);\n\n return result;\n };\n\n /**\n * End Statements section.\n */\n\n /**\n * Begin Tags section.\n */\n\n public readonly StartTag = (): ParsedObject | null => {\n this.Whitespace();\n\n if (this.ParseString(\"#\") === null) {\n return null;\n }\n\n if (this.parsingStringExpression) {\n this.Error(\n \"Tags aren't allowed inside of strings. Please use \\\\# if you want a hash symbol.\"\n );\n }\n\n let result: ParsedObject | null = null;\n if (this.tagActive) {\n let contentList = new ContentList();\n contentList.AddContent(new Tag(/*isStart:*/ false));\n contentList.AddContent(new Tag(/*isStart:*/ true));\n result = contentList;\n } else {\n result = new Tag(/*isStart:*/ true);\n }\n this.tagActive = true;\n\n this.Whitespace();\n\n return result;\n };\n\n public EndTagIfNecessary(outputContentList: ParsedObject[] | null): void;\n public EndTagIfNecessary(outputContentList: ContentList | null): void;\n public EndTagIfNecessary(\n outputContentList: ParsedObject[] | ContentList | null\n ): void {\n if (this.tagActive) {\n if (outputContentList != null) {\n if (outputContentList instanceof ContentList) {\n outputContentList.AddContent(new Tag(/*isStart:*/ false));\n } else {\n outputContentList.push(new Tag(/*isStart:*/ false));\n }\n }\n this.tagActive = false;\n }\n }\n\n /**\n * End Tags section.\n */\n\n /**\n * Begin Whitespace section.\n */\n\n private _inlineWhitespaceChars: CharacterSet = new CharacterSet(\" \\t\");\n\n // Handles both newline and endOfFile\n public readonly EndOfLine = () => this.OneOf([this.Newline, this.EndOfFile]);\n\n // Allow whitespace before the actual newline\n public readonly Newline = (): typeof ParseSuccess | null => {\n this.Whitespace();\n\n const gotNewline: boolean = this.ParseNewline() !== null;\n\n // Optional \\r, definite \\n to support Windows (\\r\\n) and Mac/Unix (\\n)\n\n if (!gotNewline) {\n return null;\n }\n\n return ParseSuccess;\n };\n\n public readonly EndOfFile = (): typeof ParseSuccess | null => {\n this.Whitespace();\n\n if (!this.endOfInput) return null;\n\n return ParseSuccess;\n };\n\n // General purpose space, returns N-count newlines (fails if no newlines)\n public readonly MultilineWhitespace = (): typeof ParseSuccess | null => {\n let newlines: ParseRuleReturn[] | null = this.OneOrMore(this.Newline);\n if (newlines === null) {\n return null;\n }\n\n // Use content field of Token to say how many newlines there were\n // (in most circumstances it's unimportant)\n const numNewlines: number = newlines.length;\n if (numNewlines >= 1) {\n return ParseSuccess;\n }\n\n return null;\n };\n\n public readonly Whitespace = (): typeof ParseSuccess | null => {\n const doneParsed = this.ParseCharactersFromCharSet(\n this._inlineWhitespaceChars\n );\n\n if (doneParsed !== null) {\n return ParseSuccess;\n }\n\n return null;\n };\n\n public readonly Spaced =\n (rule: ParseRule): ParseRule =>\n () => {\n this.Whitespace();\n\n const result = this.ParseObject(rule);\n if (result === null) {\n return null;\n }\n\n this.Whitespace();\n\n return result;\n };\n\n public readonly AnyWhitespace = (): typeof ParseSuccess | null => {\n let anyWhitespace: boolean = false;\n\n while (this.OneOf([this.Whitespace, this.MultilineWhitespace]) !== null) {\n anyWhitespace = true;\n }\n\n return anyWhitespace ? ParseSuccess : null;\n };\n\n public readonly MultiSpaced =\n (rule: ParseRule): ParseRuleReturn =>\n () => {\n this.AnyWhitespace();\n\n const result = this.ParseObject(rule);\n if (result === null) {\n return null;\n }\n\n this.AnyWhitespace();\n\n return result;\n };\n\n private _filename: string | null = null;\n private _externalErrorHandler: ErrorHandler | null = null;\n private _fileHandler: IFileHandler | null = null;\n\n /**\n * End Whitespace section.\n */\n}\n","import { CompilerOptions } from \"./CompilerOptions\";\nimport { DebugSourceRange } from \"./DebugSourceRange\";\nimport { ErrorType } from \"./Parser/ErrorType\";\nimport { InkParser } from \"./Parser/InkParser\";\nimport { Story } from \"../engine/Story\";\nimport { Story as ParsedStory } from \"./Parser/ParsedHierarchy/Story\";\nimport { DebugMetadata } from \"../engine/DebugMetadata\";\nimport { StringValue } from \"../engine/Value\";\nimport { asOrNull } from \"../engine/TypeAssertion\";\n\nexport { CompilerOptions } from \"./CompilerOptions\";\nexport { InkParser } from \"./Parser/InkParser\";\nexport { StatementLevel } from \"./Parser/StatementLevel\";\nexport { JsonFileHandler } from \"./FileHandler/JsonFileHandler\";\nexport { InkList, Story } from \"../engine/Story\";\n\nexport class Compiler {\n private _errors: string[] = [];\n get errors(): string[] {\n return this._errors;\n }\n\n private _warnings: string[] = [];\n get warnings(): string[] {\n return this._warnings;\n }\n\n private _authorMessages: string[] = [];\n get authorMessages(): string[] {\n return this._authorMessages;\n }\n\n private _inputString: string;\n get inputString(): string {\n return this._inputString;\n }\n\n private _options: CompilerOptions;\n get options(): CompilerOptions {\n return this._options;\n }\n\n private _parsedStory: ParsedStory | null = null;\n get parsedStory(): ParsedStory {\n if (!this._parsedStory) {\n throw new Error();\n }\n\n return this._parsedStory;\n }\n\n private _runtimeStory: Story | null = null;\n get runtimeStory(): Story {\n if (!this._runtimeStory) {\n throw new Error(\"Compilation failed.\");\n }\n\n return this._runtimeStory;\n }\n\n private _parser: InkParser | null = null;\n get parser(): InkParser {\n if (!this._parser) {\n throw new Error();\n }\n\n return this._parser;\n }\n\n private _debugSourceRanges: DebugSourceRange[] = [];\n get debugSourceRanges(): DebugSourceRange[] {\n return this._debugSourceRanges;\n }\n\n constructor(inkSource: string, options: CompilerOptions | null = null) {\n this._inputString = inkSource;\n this._options = options || new CompilerOptions();\n }\n\n public readonly Compile = (): Story => {\n this._parser = new InkParser(\n this.inputString,\n this.options.sourceFilename || null,\n this.OnError,\n null,\n this.options.fileHandler\n );\n\n this._parsedStory = this.parser.ParseStory();\n\n if (this.errors.length === 0) {\n this.parsedStory.countAllVisits = this.options.countAllVisits;\n this._runtimeStory = this.parsedStory.ExportRuntime(this.OnError);\n } else {\n this._runtimeStory = null;\n }\n\n return this.runtimeStory;\n };\n\n public readonly RetrieveDebugSourceForLatestContent = (): void => {\n for (const outputObj of this.runtimeStory.state.outputStream) {\n const textContent = asOrNull(outputObj, StringValue);\n if (textContent !== null) {\n const range = new DebugSourceRange(\n textContent.value?.length || 0,\n textContent.debugMetadata,\n textContent.value || \"unknown\"\n );\n\n this.debugSourceRanges.push(range);\n }\n }\n };\n\n public readonly DebugMetadataForContentAtOffset = (\n offset: number\n ): DebugMetadata | null => {\n let currOffset = 0;\n\n let lastValidMetadata: DebugMetadata | null = null;\n for (const range of this.debugSourceRanges) {\n if (range.debugMetadata !== null) {\n lastValidMetadata = range.debugMetadata;\n }\n\n if (offset >= currOffset && offset < currOffset + range.length) {\n return lastValidMetadata;\n }\n\n currOffset += range.length;\n }\n\n return null;\n };\n\n public readonly OnError = (message: string, errorType: ErrorType) => {\n switch (errorType) {\n case ErrorType.Author:\n this._authorMessages.push(message);\n break;\n\n case ErrorType.Warning:\n this._warnings.push(message);\n break;\n\n case ErrorType.Error:\n this._errors.push(message);\n break;\n }\n\n if (this.options.errorHandler !== null) {\n this.options.errorHandler(message, errorType);\n }\n };\n}\n","import { IFileHandler } from \"../IFileHandler\";\n\nexport class JsonFileHandler implements IFileHandler {\n constructor(public readonly fileHierarchy: Record) {}\n\n readonly ResolveInkFilename = (filename: string): string => {\n if (Object.keys(this.fileHierarchy).includes(filename)) return filename;\n throw new Error(\n `Cannot locate ${filename}. Are you trying a relative import ? This is not yet implemented.`\n );\n };\n\n readonly LoadInkFileContents = (filename: string): string => {\n if (Object.keys(this.fileHierarchy).includes(filename)) {\n return this.fileHierarchy[filename];\n } else {\n throw new Error(`Cannot open ${filename}.`);\n }\n };\n}\n"],"names":["CompilerOptions","constructor","sourceFilename","arguments","length","undefined","pluginNames","countAllVisits","errorHandler","fileHandler","this","DebugSourceRange","debugMetadata","text","ErrorType","Argument","identifier","isByReference","isDivertTarget","typeName","asOrNull","obj","type","unsafeTypeAssertion","asOrThrows","Error","asINamedContentOrNull","hasValidName","name","nullIfUndefined","isEquatable","Equals","filterUndef","element","ParsedObject","_this","_alreadyHadError","_alreadyHadWarning","_debugMetadata","_runtimeObject","content","parent","GetType","AddContent","subContent","sub","Array","isArray","ss","hasOwnProperty","push","InsertContent","index","splice","Find","queryFunc","tObj","nestedResult","FindAll","foundSoFar","found","Warning","message","source","value","hasOwnDebugMetadata","Boolean","story","ancestor","runtimeObject","GenerateRuntimeObject","runtimePath","path","containerForCounting","ancestry","result","reverse","ResolveReferences","context","isWarning","AuthorWarning","warningMessage","super","Path","_components","_componentsString","_isRelative","componentsString","Component","head","tail","concat","relative","isRelative","componentCount","tailComps","slice","self","lastComponent","lastComponentIdx","containsNamedComponent","i","l","isIndex","GetComponent","PathByAppendingPath","pathToAppend","p","upwardMoves","isParent","join","substring","componentStrings","split","str","test","parseInt","toString","otherPath","PathByAppendingComponent","c","Debug","ValueType","PushPopType","parentId","indexOrName","static","otherComp","Assert","condition","console","warn","trace","AssertType","variable","NullException","throwNullException","InkObject","_path","ownDebugMetadata","DebugLineNumberOfPath","root","rootContentContainer","targetContent","ContentAtPath","dm","startLineNumber","comps","child","container","Container","namedChild","unshift","indexOf","ResolvePath","nearestContainer","contentContainer","ConvertPathToRelative","globalPath","ownPath","minPathLength","Math","min","lastSharedPathCompIndex","ownComp","numUpwardsMoves","newPathComps","up","ToParent","down","CompactPathString","globalPathStr","relativePathStr","Copy","SetChild","prop","StringBuilder","string","Length","Append","AppendLine","AppendFormat","format","_len","args","_key","replace","match","num","Clear","InkListItem","originName","itemName","nameParts","Null","isNull","fullName","otherItem","copy","serialized","JSON","stringify","key","parse","isLikeInkListItem","inkListItem","item","InkList","Map","origins","_originNames","otherList","otherOriginNames","originNames","singleOriginListName","originStory","SetInitialOriginName","listDefinitions","def","TryListGetDefinition","exists","singleElement","Add","Key","Value","myListItem","listValue","_a","FindSingleItemListWithName","AddItem","itemOrItemName","origin","intVal","TryGetValueForItem","foundListDef","ContainsItemWithName","itemVal","ValueForItem","ContainsItemNamed","fromSerializedKey","ContainsKey","has","serializedKey","set","Remove","delete","Count","size","originOfMaxItem","maxOriginName","maxItem","every","initialOriginName","SetInitialOriginNames","initialOriginNames","max","minItem","inverse","list","items","all","Union","union","Intersect","intersection","HasIntersection","Without","listToRemove","Contains","what","GreaterThan","GreaterThanOrEquals","LessThan","LessThanOrEquals","MaxAsList","MinAsList","ListWithSubRange","minBound","maxBound","ordered","orderedItems","minValue","maxValue","Number","MAX_SAFE_INTEGER","isInteger","subList","otherInkList","sort","x","y","localeCompare","sb","valueOf","NaN","StoryException","useEndLineNumber","tryGetValueFromMap","map","val","get","AbstractValue","preferredNumberType","Int","IntValue","Float","isNaN","FloatValue","BoolValue","StringValue","String","DivertTargetValue","ListValue","Create","valueObject","BadCastException","targetType","valueType","isTruthy","Bool","Cast","newType","_isNewline","_isInlineWhitespace","isNewline","isInlineWhitespace","isNonWhitespace","parsedInt","defaultValue","tryParseInt","parsedFloat","parseFloat","tryParseFloat","DivertTarget","targetPath","VariablePointerValue","variableName","contextIndex","_contextIndex","VariablePointer","List","listOrSingleItem","singleValue","oldValue","newValue","oldList","newList","SearchResult","approximate","correctObj","searchResult","_content","namedContent","visitsShouldBeCounted","turnIndexShouldBeCounted","countingAtStartOnly","_pathToFirstLeafContent","namedOnlyContent","namedOnlyContentDict","inkObject","named","existingNamedOnly","AddToNamedContentOnly","countFlags","flags","CountFlags","Visits","Turns","CountStartOnly","flag","pathToFirstLeafContent","internalPathToFirstLeafContent","components","contentObjOrList","contentList","contentObj","TryAddNamedContent","namedContentObj","partialPathStart","partialPathLength","currentContainer","currentObj","comp","foundObj","ContentWithPathComponent","AddContentsOfContainer","otherContainer","component","foundContent","BuildStringOfHierarchy","indentation","pointedObj","appendIndentation","onlyNamed","ControlCommand","commandType","_commandType","CommandType","NotSet","EvalStart","EvalOutput","EvalEnd","Duplicate","PopEvaluatedValue","PopFunction","PopTunnel","BeginString","EndString","NoOp","ChoiceCount","TurnsSince","ReadCount","Random","SeedRandom","VisitIndex","SequenceShuffleIndex","StartThread","Done","End","ListFromInt","ListRange","ListRandom","BeginTag","EndTag","Expression","_prototypeRuntimeConstantExpression","outputWhenComplete","RuntimeContainer","RuntimeControlCommand","GenerateIntoContainer","GenerateConstantIntoContainer","runtimeObj","Void","NativeFunctionCall","functionName","GenerateNativeFunctionsIfNecessary","_nativeFunctions","_name","_isPrototype","_prototype","numberOfParameters","_numberOfParameters","Call","parameters","hasList","CallBinaryListOperation","coercedParams","CoerceValuesToSingleType","coercedType","CallType","parametersOfSingleType","param1","valType","val1","paramCount","_operationFuncs","opForTypeObj","val2","opForType","resultVal","CallListIncrementOperation","v1","v2","op","asBooleanOrThrows","listIntParams","listVal","resultInkList","listItemKey","listItemValue","listItem","intOp","targetInt","itemOrigin","incrementedItem","TryGetItemWithValue","parametersIn","specialCaseList","parametersOut","inkObjectVal","castedValue","t","AddIntBinaryOp","Subtract","Multiply","Divide","floor","Mod","AddIntUnaryOp","Negate","Equal","Greater","Less","NotEquals","Not","And","Or","Max","Min","Pow","pow","Floor","Identity","Ceiling","AddFloatBinaryOp","AddFloatUnaryOp","ceil","AddStringBinaryOp","Has","includes","Hasnt","AddListBinaryOp","AddListUnaryOp","Invert","All","ListMin","ListMax","ValueOfList","divertTargetsEqual","d1","d2","divertTargetsNotEqual","AddOpToNativeFunc","AddOpFuncForType","nativeFunc","NumberExpression","subtype","isInt","isFloat","isBool","numberExpression","UnaryExpression","nativeNameForOp","inner","innerExpression","CallWithName","WithInner","innerNumber","BinaryExpression","left","right","opName","leftExpression","rightExpression","NativeNameForOp","leftUnary","CharacterSet","arg","Set","add","AddRange","start","end","charCodeAt","fromCharCode","AddCharacters","chars","FromRange","CharacterRange","_start","_end","excludes","_correspondingCharSet","_excludes","ToCharacterSet","ii","Define","ChoicePoint","onceOnly","_pathOnChoice","hasCondition","hasStartContent","hasChoiceOnlyContent","isInvisibleDefault","pathOnChoice","choiceTargetObj","choiceTarget","pathStringOnChoice","Pointer","Resolve","Divert","_targetPath","targetObj","targetPointer","_targetPointer","StartOf","targetPathString","hasVariableTarget","variableDivertName","stackPushType","pushesToStack","isExternal","externalArgs","isConditional","otherDivert","targetStr","Function","SymbolType","isNewDeclaration","isGlobal","runtimeChoice","_runtimeChoice","_condition","runtimeContainer","_innerContentContainer","innerContentContainer","startContent","choiceOnlyContent","innerContent","_outerContainer","_returnToR1","_returnToR2","_r1Label","_r2Label","_divertToStartContentOuter","_divertToStartContentInner","_startContentRuntimeContainer","hasWeaveStyleInlineBrackets","varAssign","RuntimeVariableAssignment","RuntimeDivert","varDivert","choiceOnlyRuntimeContent","innerChoiceOnlyContent","indentationDepth","CheckForNamingCollisions","SubFlowAndWeave","StringParserElement","characterIndex","characterInLineIndex","lineIndex","reportedErrorInScope","uniqueId","customFlags","CopyFrom","fromElement","_uniqueIdCounter","SquashFrom","StringParserState","currentElement","_stack","_numElements","errorReportedAlreadyInScope","stackHeight","Push","prevElement","newElement","Pop","expectedRuleId","Peek","PeekPenultimate","Squash","penultimateEl","lastEl","NoteErrorReported","el","ParseSuccess","Symbol","StringParser","ParseRule","hadError","BeginRule","state","FailRule","CancelRule","SucceedRule","stateAtSucceedRule","stateAtBeginRule","RuleDidSucceed","finalResult","Expect","rule","recoveryRule","ParseObject","butSaw","lineRemainder","LineRemainder","ErrorOnLine","ErrorWithParsedObject","lineNumber","errorType","ParseUntilCharactersFromString","SetFlag","trueOrFalse","GetFlag","ruleId","stackHeightBefore","Parse","OneOf","array","OneOrMore","results","Optional","Exclude","OptionalExclude","ParseString","TryAddResultToList","flatten","resultCollection","Interleave","ruleA","ruleB","untilTerminator","firstA","lastMainResult","outerResult","remainingLength","cli","li","success","tempIdx","_chars","ParseSingleCharacter","maxCount","ParseCharactersFromString","ParseUntilCharactersFromCharSet","charSet","ParseCharactersFromCharSet","maxCountOrShouldIncludeStrChars","shouldIncludeChars","startIndex","count","ParseInt","oldIndex","oldCharacterInLineIndex","negative","parsedString","numbersCharacterSet","MIN_SAFE_INTEGER","ParseFloat","leadingInt","afterDecimalPointStr","ParseNewline","strPreProc","PreProcessInputString","inputString","currentCharacter","endOfInput","remainingString","ParseUntil","stopRule","pauseCharacters","endCharacters","pauseAndEnd","values","ruleResultAtPause","partialParsedString","pauseCharacter","CommentEliminator","_commentOrNewlineStartCharacter","_commentBlockEndCharacter","_newlineCharacters","Process","stringList","CommentsAndNewlines","MainInk","newLines","ParseSingleComment","EndOfLineComment","BlockComment","startLineIndex","commentResult","repeat","Conditional","initialCondition","branches","_reJoinTarget","branch","branchContainer","ownExpression","isElse","pathToReJoin","returnDivert","Text","ConstantDeclaration","constantName","constantIdentifier","expression","_expression","assignedExpression","Var","FlowLevel","Gather","_b","baseTargetLevel","baseLevelIsAmbiguous","Story","_baseTargetLevel","firstComponent","numberOfComponents","dotSeparatedComponents","_dotSeparatedComponents","filter","argOne","argTwo","WeavePoint","ResolveFromContext","baseTargetObject","ResolveBaseTarget","ResolveTailComponents","originalContext","firstComp","ancestorContext","deepSearch","foundBase","GetChildFromContext","rootTarget","foundComponent","compName","minimumExpectedLevel","foundFlow","FlowBase","flowLevel","childName","minimumLevel","forceDeepSearch","ambiguousChildLevel","weaveContext","Weave","WeavePointNamed","flowContext","shouldDeepSearch","Knot","ContentWithNameAtLevel","Object","ReturnType","returnedExpression","ClosestFlowBase","iamFlowbase","Identifier","hasParameters","subFlowsByName","_subFlowsByName","isFunction","topLevelObjects","isIncludedStory","_rootWeave","_startingSubFlowDivert","_startingSubFlowRuntime","_firstChildFlow","variableDeclarations","SplitWeaveAndSubFlowContent","contentObjs","isRootStory","weaveObjs","subFlowObjs","subFlow","finalContent","ResolveVariableWithName","varName","fromNode","ownerFlow","isArgument","isTemporary","AddNewVariableDeclaration","varDecl","varab","prevDeclError","ResolveWeavePointNaming","foundReturn","CheckForDisallowedFunctionFlowControl","Stitch","GenerateArgumentVariableAssignments","contentIdx","childFlow","childFlowRuntime","existingChild","errorMsg","ValidateTermination","WarningInTermination","paramName","assign","level","weavePointResult","DeepSearchForAnyLevelContent","weaveResultSelf","deepResult","allDiverts","divert","isFunctionCall","allChoices","Choice","choice","terminatingObject","terminatingDivert","isTunnel","target","PreProcessTopLevelObjects","_","Arg","jj","symbolType","ContentList","objects","dontFlatten","TrimTrailingWhitespace","RegExp","contentObjRuntime","DontFlattenContainer","moreObjects","containerForCount","pathForCount","pathStringForCount","VariableReference","pathIdentifiers","id","runtimeVarRef","_runtimeVarRef","isConstantReference","isListItemReference","constantValue","constants","RuntimeVariableReference","listItemName","listName","ResolveListItem","parsedPath","targetForCount","targetFlow","FunctionCall","proxyDivert","_proxyDivert","runtimeDivert","isChoiceCount","isTurns","isTurnsSince","isRandom","isSeedRandom","isListRange","isListRandom","isReadCount","_divertTargetToCount","_variableReferenceToCount","shouldPopReturnedValue","foundList","ResolveList","usingProxyDivert","divertTarget","variableDivertTarget","CallExistsWithName","nativeCall","msg","RuntimeInkList","strArgs","attemptingTurnCountOfVariableTarget","targetObject","IsBuiltIn","MultipleConditionExpression","subExpressions","conditionExpressions","isFirst","conditionExpr","_runtimeDivert","runtimeDivertTargetValue","_runtimeDivertTargetValue","otherDivTarget","isDone","isEnd","usageContext","badUsage","foundUsage","usageParent","binaryExprParent","funcCall","ConditionalSingleBranch","parentFunc","isEmpty","isThread","ResolveTargetContent","CheckArgumentValidity","requiresArgCodeGen","targetArguments","argToPass","argExpected","varRef","varPointer","Tunnel","PathAsVariableName","variableTargetName","flowBaseScope","resolveResult","argument","find","a","numArgs","butClause","flowArg","divArgExpr","knotCountPath","CheckExternalArgumentValidity","externalName","external","externals","externalArgCount","argumentNames","ownArgCount","returnString","targetWasFound","isBuiltIn","IsExternal","RuntimePath","GatherPointToResolve","targetRuntimeObj","SequenceDivertToResolve","SequenceType","Sequence","elementContentLists","sequenceType","_sequenceDivertsToResolve","once","Once","cycle","Cycle","stopping","Stopping","shuffle","Shuffle","seqBranchCount","sequenceElements","postShuffleNoOp","lastIdx","skipShuffleDivert","AddDivertToResolve","elementCountToShuffle","postSequenceNoOp","elIndex","sequenceDivert","contentContainerForSequenceBranch","seqBranchCompleteDivert","elementContentList","seqElObject","toResolve","TunnelOnwards","_overrideDivertTarget","_divertAfter","divertAfter","returnRuntimeObj","returnRuntimeContainer","evalStart","evalEnd","cmd","returnDivertObj","_items","_itemNameToValues","ContainsItem","ListDefinition","runtimeListDefinition","allItems","e","itemDefinitions","seriesValue","RuntimeListDefinition","variableAssignment","_elementsByName","ItemNamed","initialValues","itemDef","inInitialList","RuntimeInkListItem","currentValue","explicitValue","VariableAssignment","variableIdentifier","isNewTemporaryDeclaration","isGlobalDeclaration","listDefinition","isDeclaration","_ref","isTemporaryNewDeclaration","listDef","_runtimeAssignment","newDeclScope","Temp","variableReference","resolvedVarAssignment","rootContainer","_rootContainer","namedWeavePoints","_namedWeavePoints","lastParsedSignificantObject","lastObject","lastText","IsGlobalDeclaration","lastWeave","cont","indentIndex","previousWeavePoint","addContentToPreviousWeavePoint","hasSeenChoiceInSection","_unnamedGatherCount","_choiceCount","looseEnds","gatherPointsToResolve","w","weavePoint","existingWeavePoint","existingObj","_c","ConstructWeaveHierarchyFromIndentation","weaveIndentIdx","baseIndentIndex","innerWeaveStartIdx","innerWeaveObj","weaveContentCount","weaveContent","weave","DetermineBaseIndentationFromContent","AddRuntimeForWeavePoint","AddRuntimeForNestedWeave","AddGeneralRuntimeContent","PassLooseEndsToAncestors","AddRuntimeForGather","gather","autoEnter","gatherContainer","looseEndWeavePoint","looseEnd","looseWeavePoint","WeavePointHasLooseEnd","closestInnerWeaveAncestor","closestOuterWeaveAncestor","nested","weaveAncestor","received","ReceiveLooseEnd","receivingWeave","childWeaveLooseEnd","varAss","ContentThatFollowsWeavePoint","returned","parentWeave","laterObj","badTerminationHandler","looseEndFlow","ValidateFlowOfObjectsTerminates","BadNestedTerminationHandler","terminatingObj","conditional","toLowerCase","objFlow","defaultObj","terminated","flowObj","d","innerDivert","CheckForWeavePointNamingCollisions","ancestorFlows","flow","weavePointName","otherContentWithName","isNestedWeave","gatherPoint","_ownExpression","_contentContainer","_conditionalDivert","_innerWeave","isTrueBranch","matchingEquality","isInline","startsWith","duplicatesStackValue","needsEval","GenerateRuntimeForContent","CustomFlags","DebugMetadata","endLineNumber","startCharacterNumber","endCharacterNumber","fileName","sourceName","Merge","newDebugMetadata","ExternalDeclaration","AddExternal","FlowDecl","Wrap","_objToWrap","glue","Glue","IncDecExpression","varIdentifier","isIncOrExpression","isInc","varResolveResult","incrementDecrementWord","IncludedFile","includedStory","InfixOperator","precedence","requireWhitespace","parentStory","stitchName","knotWithStitchName","stitch","itemIdentifierList","runtimeRawList","itemIdentifier","ListElementDefinition","parentList","indentifier","ListItem","StatementLevel","exports","baseToString","tagText","threadAtGeneration","sourcePath","tags","originalThreadIndex","ListDefinitionsOrigin","lists","_lists","_allUnambiguousListValueCache","listOfLists","definition","JsonSerialisation","jArray","skipLast","jTok","JTokenToRuntimeObject","writer","dictionary","WriteObjectStart","WritePropertyStart","WriteRuntimeObject","WritePropertyEnd","WriteObjectEnd","WriteArrayStart","WriteArrayEnd","dict","WriteIntProperty","WriteRuntimeContainer","divTypeKey","WriteProperty","choicePoint","boolVal","WriteBool","WriteInt","floatVal","WriteFloat","strVal","Write","WriteStringStart","WriteStringInner","WriteStringEnd","WriteInkList","divTargetVal","varPtrVal","controlCmd","_controlCommandNames","readCountPath","tag","Tag","WriteChoice","jObject","token","firstChar","propValue","varPtr","isDivert","divPushType","readCountVarRef","isVarAss","isGlobalVar","isNewDecl","listContent","rawList","namesAsObjs","nameToVal","JObjectToChoice","JArrayToContainer","toJson","me","removes","space","k","v","some","r","withoutName","hasNameProperty","hasTerminator","namedContainer","WriteNull","JArrayToRuntimeObjList","namedContentItem","namedSubContainer","jObj","WritePropertyNameStart","WritePropertyNameInner","WritePropertyNameEnd","listDefJson","defsObj","allDefs","nameValueKey","nameValue","TOTAL_VALUES","CallStack","elements","callStack","depth","cs","_threads","callstack","currentElementIndex","currentThread","canPop","_threadCounter","_startOfRoot","storyContext","Reset","toCopy","otherThread","Thread","Element","SetJsonToken","jThreads","jThreadTok","jThreadObj","thread","WriteJson","WriteObject","PushThread","newThread","threadIndex","ForkThread","forkedThread","PopThread","canPopThread","elementIsEvaluateFromGame","FunctionEvaluationFromGame","externalEvaluationStackHeight","outputStreamLengthWithPushed","currentPointer","evaluationStackHeightWhenPushed","functionStartInOutputStream","CanPop","pop","GetTemporaryVariableWithName","varValue","temporaryVariables","SetTemporaryVariable","declareNew","contextElement","RetainListOriginsForAssignment","ContextForVariableNamed","ThreadWithIndex","filtered","callStackTrace","isCurrent","pointer","inExpressionEvaluation","previousPointer","jThreadCallstack","jElTok","currentContainerPathStr","jElementObj","pushPopType","currentContainerPathStrToken","threadPointerResult","temps","JObjectToDictionaryRuntimeObjs","clear","prevContentObjPath","prevPath","PointerAtPath","WriteDictionaryRuntimeObjs","resolvedPointer","VariablesState","variableChangedEvent","callback","variableChangedEventCallbacks","batchObservingVariableChanges","_batchObservingVariableChanges","_changedVariablesForBatchObs","_globalVariables","_callStack","$","varContents","patch","TryGetGlobal","_defaultGlobalVariables","SetGlobal","listDefsOrigin","_listDefsOrigin","Proxy","ApplyPatch","namedVarKey","namedVarValue","globals","changedVariables","jToken","varValKey","varValValue","loadedToken","tokenInkObject","keyValKey","keyValValue","dontSaveDefaultValues","defaultVal","RuntimeObjectsEqual","obj1","obj2","GetVariableWithName","GetRawVariableWithName","ValueAtVariablePointer","TryGetDefaultVariableValue","GlobalVariableExistsWithName","variableValue","Assign","setGlobal","ResolveVariablePointer","existingPointer","SnapshotDefaultGlobals","AddChangedVariable","GetContextIndexOfVariableNamed","doubleRedirectionPointer","ObserveVariableChange","PRNG","seed","next","nextFloat","StatePatch","_globals","_changedVariables","visitCounts","_visitCounts","turnIndices","_turnIndices","TryGetVisitCount","SetVisitCount","SetTurnIndex","TryGetTurnIndex","SimpleJson","Reader","ToDictionary","ToArray","_rootObject","Writer","_currentPropertyName","_currentString","_stateStack","_collectionStack","_propertyNameStack","_jsonObject","StartNewObject","newObject","State","Property","currentCollection","currentPropertyName","propertyName","None","StateElement","innerOrContent","WriteFloatProperty","IncrementChildCount","childCount","PropertyName","_addToCurrentObject","error","POSITIVE_INFINITY","NEGATIVE_INFINITY","currEl","Flow","outputStream","currentChoices","jChoiceThreadsObj","LoadFlowChoiceThreads","WriteListRuntimeObjs","hasChoiceThreads","jChoiceThreads","foundActiveThread","jSavedChoiceThread","StoryState","ToJson","indented","LoadJson","json","TextToDictionary","LoadJsonObj","onDidLoadState","VisitCountAtPathString","pathString","visitCountOut","_patch","VisitCountForContainer","containerPathStr","count2","IncrementVisitCountForContainer","currCount","RecordTurnIndexVisitToContainer","currentTurnIndex","TurnsSinceForContainer","index2","callstackDepth","_currentFlow","canContinue","generatedChoices","currentErrors","_currentErrors","currentWarnings","_currentWarnings","variablesState","_variablesState","evaluationStack","_evaluationStack","_currentTurnIndex","currentPathString","hasError","hasWarning","currentText","_outputStreamTextDirty","inTag","outputObj","textContent","controlCommand","_currentText","CleanOutputWhitespace","currentWhitespaceStart","startOfLine","charAt","currentTags","_outputStreamTagsDirty","_currentTags","txt","currentFlowName","currentFlowIsDefaultFlow","kDefaultFlowName","aliveFlowNames","_aliveFlowNamesDirty","_aliveFlowNames","_namedFlows","flowName","keys","kInkSaveStateVersion","kMinCompatibleLoadVersion","divertedPointer","storySeed","previousRandom","didSafeExit","OutputStreamDirty","timeSeed","Date","getTime","GoToStart","mainContentContainer","SwitchFlow_Internal","SwitchToDefaultFlow_Internal","RemoveFlow_Internal","CopyAndStartPatching","namedFlowKey","namedFlowValue","RestoreAfterPatch","ApplyAnyPatch","ApplyCountChanges","newCount","isVisit","WriteIntDictionary","inkVersionCurrent","jSaveVersion","flowsObj","flowsObjDict","flowsObjDictEntries","entries","namedFlowObjKey","namedFlowObjValue","currFlowName","currentDivertTargetPath","divertPath","JObjectToIntDictionary","ResetErrors","ResetOutput","objs","PushToOutputStream","listText","TrySplittingHeadTailWhitespace","textObj","PushToOutputStreamIndividual","PopFromOutputStream","single","headFirstNewlineIdx","headLastNewlineIdx","tailLastNewlineIdx","tailFirstNewlineIdx","listTexts","innerStrStart","innerStrEnd","leadingSpaces","innerStrText","numSpaces","trailingSpaces","includeInOutput","TrimNewlinesFromOutputStream","functionTrimIndex","glueTrimIndex","o","trimIndex","RemoveExistingGlue","callStackElements","outputStreamEndsInNewline","outputStreamContainsContent","removeWhitespaceFrom","inStringEvaluation","PushEvaluationStack","n","PopEvaluationStack","numberOfObjects","PeekEvaluationStack","ForceEnd","TrimWhitespaceFromFunctionEnd","functionStartPoint","PopCallStack","popType","SetChosenPath","incrementingTurnIndex","newPointer","StartFunctionEvaluationFromGame","funcContainer","PassArgumentsToEvaluationStack","TryExitFunctionEvaluationFromGame","CompleteFunctionEvaluationFromGame","originalEvaluationStackHeight","returnedObj","poppedObj","returnVal","AddError","Stopwatch","startTime","ElapsedMilliseconds","Start","Stop","nVal","isFinite","choices","_state","IfAsyncWeCant","_listDefinitions","StartProfiling","EndProfiling","inkVersionMinimumCompatible","onError","onDidContinue","onMakeChoice","onEvaluateFunction","onCompleteEvaluateFunction","onChoosePathString","_prevContainers","allowExternalFunctionFallbacks","_variableObservers","_hasValidatedExternals","_temporaryEvaluationContainer","_asyncContinueActive","_stateSnapshotAtLastNewline","_sawLookaheadUnsafeFunctionAfterNewline","_recursiveContinueCount","_asyncSaving","_profiler","_mainContentContainer","jsonString","_externals","rootObject","versionObj","formatFromFile","listDefsObj","rootToken","JTokenToListDefinitions","ResetState","shouldReturn","VariableStateDidChangeEvent","bind","ResetGlobals","ResetCallstack","originalPointer","ChoosePath","ContinueInternal","SwitchFlow","RemoveFlow","SwitchToDefaultFlow","Continue","ContinueAsync","asyncContinueComplete","millisecsLimitAsync","ValidateExternalBindings","PreContinue","isAsyncTimeLimited","durationStopwatch","ContinueSingleStep","RestoreStateSnapshot","PostContinue","err","PreStep","Step","PostStep","TryFollowDefaultInvisibleChoice","PreSnapshot","change","CalculateNewlineOutputStateChange","OutputStateChange","ExtendedBeyondNewline","NewlineRemoved","DiscardSnapshot","StateSnapshot","PostSnapshot","prevText","currText","prevTagCount","currTagCount","newlineStillExists","NoChange","ContinueMaximally","KnotContainerWithName","pathLengthToUse","CopyStateForBackgroundThreadSave","stateToSave","BackgroundSaveComplete","shouldAddToStream","containerToEnter","VisitContainer","currentContentObj","isLogicOrFlowControl","PerformLogicAndFlowControl","ProcessChoice","contextIdx","NextContent","atStart","VisitChangedContainersDueToDivert","prevAncestor","currentChildOfContainer","currentContainerAncestor","allChildrenEnteredAtStart","enteringAtStart","PopChoiceStringAndTags","choiceOnlyStrVal","showChoice","conditionValue","IsTruthy","startText","choiceOnlyText","divTarget","currentDivert","intContent","errorMessage","CallExternalFunction","evalCommand","output","overrideTunnelReturnTarget","popped","names","expected","contentStackForTag","outputCountConsumed","command","choiceTag","contentStackForString","contentToRetain","rescuedTag","choiceCount","extraNote","eitherCount","maxInt","minInt","randomRange","resultSeed","nextRandom","chosenValue","shuffleIndex","NextSequenceShuffleIndex","listNameVal","generatedListValue","foundItem","targetList","listItemIndex","listEnumerator","randomItem","assignedVal","foundValue","func","funcParams","ChoosePathString","resetCallstack","funcDetail","activityStr","ChooseChoiceIndex","choiceIdx","choiceToChoose","HasFunction","EvaluateFunction","returnTextOutput","trim","outputStreamBefore","stringOutput","textOutput","EvaluateExpression","exprContainer","startCallStackHeight","evalStackHeight","funcName","numberOfArguments","funcDef","fallbackFunctionContainer","foundExternal","lookAheadSafe","valueObj","funcResult","function","returnObj","BindExternalFunctionGeneral","lookaheadSafe","TryCoerce","BindExternalFunction","coercedArgs","apply","UnbindExternalFunction","missingExternals","from","ObserveVariable","observer","ObserveVariables","variableNames","observers","RemoveVariableObserver","specificVariableName","variableObservers","newValueObj","globalTags","TagsAtStartOfFlowContainerWithPathString","TagsForContentAtPath","flowContainer","firstContent","BuildStringOfContainer","IncrementContentPointer","didPop","successfulIncrement","nextAncestor","indexInAncestor","invisibleChoices","numElementsIntVal","seqContainer","numElements","seqCount","loopIndex","iterationIndex","seqPathStr","sequenceHash","randomSeed","random","unpickedIndices","chosen","chosenIndex","currentDebugMetadata","errorTypeStr","lineNum","_hadError","hadWarning","_hadWarning","toplevelObjects","_errorHandler","_dontFlattenContainers","_listDefs","ExportRuntime","constDecl","existingDefinition","variableInitialisation","runtimeLists","runtimeVarAss","runtimeStory","RuntimeStory","FlattenContainersIn","originalFoundList","itemInThisList","innerContainers","innerContainer","namedInnerContainer","TryFlattenContainer","parentContainer","Author","ResetError","namedFuncTarget","decl","NameConflictError","typeNameToPrint","IsReservedKeyword","knotOrFunction","topLevelContent","flowsFromOtherFiles","file","posOfObj","nonFlowContent","subStory","subStoryObj","StringExpression","isSingleString","otherStr","isStart","inChoice","DefaultFileHandler","rootPath","ResolveInkFilename","LoadInkFileContents","InkParser","_fileHandler","filename","externalErrorHandler","rootParser","ParseStory","StatementsAtLevel","Top","_rootParser","SeparatedList","mainRule","separatorRule","firstElement","allElements","nextElementRuleId","nextElement","CreateDebugMetadata","stateAtStart","stateAtEnd","md","_filename","parsedObj","parsedListObjs","parsedListObj","OnStringParserError","fullMessage","_externalErrorHandler","Whitespace","IdentifierWithMetadata","ExtendIdentifierCharacterRanges","identifierCharSet","characterRanges","ListAllCharacterRanges","charRange","_parsingChoice","onceOnlyChoice","bullets","optionalName","BracketedName","ChoiceCondition","startTextAndLogic","MixedTextAndLogic","optionOnlyContent","EndTagIfNecessary","optionOnlyTextAndLogic","innerTextAndLogic","diverts","MultiDivert","emptyContent","divObj","div","conditions","ChoiceSingleCondition","ChoiceConditionsSpace","Newline","condExpr","DisallowIncrement","gatherDashCountObj","GatherDashes","gatherDashCount","ParseDashNotArrow","InnerConditionalContent","initialQueryExpression","ConditionExpression","alternatives","canBeInline","InlineConditionalBranches","MultilineConditionalBranches","soleContent","InnerBlock","elseBranch","SingleMultilineCondition","emptyTrueBranch","earlierBranchesHaveOwnExpression","isLast","alt","finalClause","trueBranch","MultilineWhitespace","multipleConditions","expr","ElseExpression","_nonTextPauseCharacters","_nonTextEndCharacters","_notTextEndCharactersChoice","_notTextEndCharactersString","TrimEndWhitespace","mixedTextAndLogicResults","terminateWithSpace","lastObjIdx","lastObj","LineOfMixedTextAndLogic","firstText","EndOfLine","SkipToNextLine","Spaced","ContentText","InlineLogicOrGlueOrStartTag","ContentTextAllowingEscapeChar","ContentTextNoEscape","gotEscapeChar","endChars","parsingStringExpression","pureTextContent","nonTextRule","ParseDivertArrow","ParseThreadArrow","threadDivert","arrowsAndDiverts","ParseDivertArrowOrTunnelOnwards","DivertIdentifierWithArguments","tunnelOnwards","tunnelOnwardDivert","gatherDivert","targetComponents","DotSeparatedDivertPathComponents","optionalArguments","ExpressionFunctionCallArguments","SingleDivert","numArrows","_binaryOperators","_maxBinaryOpLength","TempDeclarationOrAssignment","ParseTempKeyword","isIncrement","isDecrement","ReturnStatement","minimumPrecedence","ExpressionUnary","infixOp","ParseInfixOperator","expectationMessage","multiaryExpr","ExpressionInfixRight","ExpressionDivertTarget","prefixOp","ExpressionNot","ExpressionList","ExpressionParen","ExpressionFunctionCall","ExpressionVariableName","ExpressionLiteral","postfixOp","ExpressionFloat","ExpressionInt","ExpressionBool","ExpressionString","intOrNull","floatOrNull","textAndLogic","iden","commas","innerExpr","memberNames","ListMember","identifier2","RegisterExpressionOperators","RegisterBinaryOperator","infix","_openFilenames","IncludeStatement","fullFilename","FilenameIsAlreadyOpen","AddOpenFilename","includedString","RemoveOpenFilename","KnotDefinition","knotDecl","KnotDeclaration","innerKnotStatements","KnotStitchNoContentRecoveryRule","KnotTitleEquals","knotName","isFunc","parameterNames","BracketedKnotDeclArguments","multiEquals","StitchDefinition","StitchDeclaration","innerStitchStatements","flowArgs","flowArguments","FlowDeclArgument","firstIden","divertArrow","secondIden","funcIdentifier","argNames","_identifierCharSet","LogicLine","afterTilde","funCall","VariableDeclaration","ListElementDefinitionSeparator","ListDeclaration","AnyWhitespace","needsToCloseParen","elementValue","elementValueNum","ConstDeclaration","InlineLogic","StartTag","RuntimeGlue","wasParsingString","wasTagActive","tagActive","logic","InnerLogic","explicitSeqType","SequenceTypeAnnotation","contentLists","InnerSequenceObjects","rules","InnerSequence","InnerExpression","isNumberCharsOnly","_sequenceTypeSymbols","seqType","parsedSeqType","annotation","SequenceTypeSymbolAnnotation","SequenceTypeWordAnnotation","sequenceAnnotations","symbolChar","sequenceTypes","SequenceTypeSingleWord","combinedSequenceType","word","InnerMultilineSequenceObjects","InnerInlineSequenceObjects","interleavedContentAndPipes","justHadContent","contentOrPipe","SingleMultilineSequenceElement","_statementRulesAtLevel","_statementBreakRulesAtLevel","StatementAtLevel","StatementsBreakForLevel","rulesAtLevel","statement","breakRules","breakRuleResult","GenerateStatementLevelRules","levels","breakingRules","Line","inlineRule","_inlineWhitespaceChars","EndOfFile","newlines","anyWhitespace","MultiSpaced","fullRootInkPath","ParsingString","TagActive","outputContentList","LatinBasic","LatinExtendedA","LatinExtendedB","Greek","Cyrillic","Armenian","Hebrew","Arabic","Korean","errors","_errors","warnings","_warnings","authorMessages","_authorMessages","_inputString","options","_options","parsedStory","_parsedStory","_runtimeStory","parser","_parser","debugSourceRanges","_debugSourceRanges","inkSource","Compile","OnError","RetrieveDebugSourceForLatestContent","range","DebugMetadataForContentAtOffset","offset","currOffset","lastValidMetadata","fileHierarchy"],"mappings":"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"} \ No newline at end of file diff --git a/prototype/ink-full.js.map.old b/prototype/ink-full.js.map.old new file mode 100644 index 0000000..6af66bd --- /dev/null +++ b/prototype/ink-full.js.map.old @@ -0,0 +1 @@ +{"version":3,"file":"ink-full.js","sources":["../src/compiler/CompilerOptions.ts","../src/compiler/Parser/ErrorType.ts","../src/compiler/DebugSourceRange.ts","../src/compiler/Parser/ParsedHierarchy/Argument.ts","../src/engine/TypeAssertion.ts","../src/compiler/Parser/ParsedHierarchy/Object.ts","../src/engine/Debug.ts","../src/compiler/Parser/ParsedHierarchy/AuthorWarning.ts","../src/engine/Path.ts","../src/engine/NullException.ts","../src/engine/Object.ts","../src/engine/StringBuilder.ts","../src/engine/InkList.ts","../src/engine/StoryException.ts","../src/engine/TryGetResult.ts","../src/engine/Value.ts","../src/engine/SearchResult.ts","../src/engine/Container.ts","../src/engine/ControlCommand.ts","../src/compiler/Parser/ParsedHierarchy/Expression/Expression.ts","../src/engine/Void.ts","../src/engine/NativeFunctionCall.ts","../src/compiler/Parser/ParsedHierarchy/Expression/NumberExpression.ts","../src/compiler/Parser/ParsedHierarchy/Expression/UnaryExpression.ts","../src/compiler/Parser/ParsedHierarchy/Expression/BinaryExpression.ts","../src/compiler/Parser/CharacterSet.ts","../src/compiler/Parser/CharacterRange.ts","../src/engine/ChoicePoint.ts","../src/engine/PushPop.ts","../src/engine/Pointer.ts","../src/compiler/Parser/ParsedHierarchy/SymbolType.ts","../src/engine/Divert.ts","../src/engine/VariableAssignment.ts","../src/compiler/Parser/ParsedHierarchy/Choice.ts","../src/compiler/Parser/StringParser/StringParserElement.ts","../src/compiler/Parser/StringParser/StringParserState.ts","../src/compiler/Parser/StringParser/StringParser.ts","../src/compiler/Parser/CommentEliminator.ts","../src/compiler/Parser/ParsedHierarchy/Flow/FlowLevel.ts","../src/compiler/Parser/ParsedHierarchy/Conditional/Conditional.ts","../src/compiler/Parser/ParsedHierarchy/Text.ts","../src/compiler/Parser/ParsedHierarchy/Declaration/ConstantDeclaration.ts","../src/compiler/Parser/ParsedHierarchy/Gather/Gather.ts","../src/compiler/Parser/ParsedHierarchy/Path.ts","../src/compiler/Parser/ParsedHierarchy/ReturnType.ts","../src/compiler/Parser/ParsedHierarchy/Flow/ClosestFlowBase.ts","../src/compiler/Parser/ParsedHierarchy/Identifier.ts","../src/compiler/Parser/ParsedHierarchy/Flow/FlowBase.ts","../src/compiler/Parser/ParsedHierarchy/ContentList.ts","../src/engine/VariableReference.ts","../src/compiler/Parser/ParsedHierarchy/Variable/VariableReference.ts","../src/compiler/Parser/ParsedHierarchy/FunctionCall.ts","../src/compiler/Parser/ParsedHierarchy/Expression/MultipleConditionExpression.ts","../src/compiler/Parser/ParsedHierarchy/Sequence/SequenceType.ts","../src/compiler/Parser/ParsedHierarchy/Divert/DivertTarget.ts","../src/compiler/Parser/ParsedHierarchy/Divert/Divert.ts","../src/compiler/Parser/ParsedHierarchy/Gather/GatherPointToResolve.ts","../src/compiler/Parser/ParsedHierarchy/Sequence/SequenceDivertToResolve.ts","../src/compiler/Parser/ParsedHierarchy/Sequence/Sequence.ts","../src/compiler/Parser/CustomFlags.ts","../src/compiler/Parser/ParsedHierarchy/TunnelOnwards.ts","../src/engine/ListDefinition.ts","../src/compiler/Parser/ParsedHierarchy/List/ListDefinition.ts","../src/compiler/Parser/ParsedHierarchy/Variable/VariableAssignment.ts","../src/compiler/Parser/ParsedHierarchy/Weave.ts","../src/compiler/Parser/ParsedHierarchy/Conditional/ConditionalSingleBranch.ts","../src/engine/DebugMetadata.ts","../src/compiler/Parser/StatementLevel.ts","../src/compiler/Parser/ParsedHierarchy/Declaration/ExternalDeclaration.ts","../src/compiler/Parser/FlowDecl.ts","../src/compiler/Parser/ParsedHierarchy/Glue.ts","../src/compiler/Parser/ParsedHierarchy/Wrap.ts","../src/engine/Glue.ts","../src/compiler/Parser/ParsedHierarchy/Expression/IncDecExpression.ts","../src/compiler/Parser/ParsedHierarchy/IncludedFile.ts","../src/compiler/Parser/InfixOperator.ts","../src/compiler/Parser/ParsedHierarchy/Knot.ts","../src/compiler/Parser/ParsedHierarchy/List/List.ts","../src/compiler/Parser/ParsedHierarchy/List/ListElementDefinition.ts","../src/compiler/Parser/ParsedHierarchy/Stitch.ts","../src/engine/Tag.ts","../src/engine/Choice.ts","../src/engine/ListDefinitionsOrigin.ts","../src/engine/JsonSerialisation.ts","../src/engine/CallStack.ts","../src/engine/VariablesState.ts","../src/engine/PRNG.ts","../src/engine/StatePatch.ts","../src/engine/SimpleJson.ts","../src/engine/Flow.ts","../src/engine/Error.ts","../src/engine/StoryState.ts","../src/engine/StopWatch.ts","../src/engine/Story.ts","../src/compiler/Parser/ParsedHierarchy/Story.ts","../src/compiler/Parser/ParsedHierarchy/Expression/StringExpression.ts","../src/compiler/Parser/ParsedHierarchy/Tag.ts","../src/compiler/FileHandler/DefaultFileHandler.ts","../src/compiler/Parser/InkParser.ts","../src/compiler/FileHandler/JsonFileHandler.ts","../src/compiler/Compiler.ts"],"sourcesContent":["import { ErrorHandler } from \"../engine/Error\";\nimport { IFileHandler } from \"./IFileHandler\";\n\nexport class CompilerOptions {\n constructor(\n public readonly sourceFilename: string | null = null,\n public readonly pluginNames: string[] = [],\n public readonly countAllVisits: boolean = false,\n public readonly errorHandler: ErrorHandler | null = null,\n public readonly fileHandler: IFileHandler | null = null\n ) {}\n}\n","// TODO: Unifify with Engine.\n\nexport enum ErrorType {\n Author,\n Warning,\n Error,\n}\n","import { DebugMetadata } from \"../engine/DebugMetadata\";\n\nexport class DebugSourceRange {\n constructor(\n public readonly length: number,\n public readonly debugMetadata: DebugMetadata | null,\n public text: string\n ) {}\n}\n","import { Identifier } from \"./Identifier\";\n\nexport class Argument {\n constructor(\n public identifier: Identifier | null = null,\n public isByReference: boolean | null = null,\n public isDivertTarget: boolean | null = null\n ) {}\n}\n","import { INamedContent } from \"./INamedContent\";\n\nexport function asOrNull(\n obj: any,\n type: (new (...arg: any[]) => T) | (Function & { prototype: T })\n): T | null {\n if (obj instanceof type) {\n return unsafeTypeAssertion(obj, type);\n } else {\n return null;\n }\n}\n\nexport function asOrThrows(\n obj: any,\n type: (new (...arg: any[]) => T) | (Function & { prototype: T })\n): T | never {\n if (obj instanceof type) {\n return unsafeTypeAssertion(obj, type);\n } else {\n throw new Error(`${obj} is not of type ${type}`);\n }\n}\n\nexport function asNumberOrThrows(obj: any) {\n if (typeof obj === \"number\") {\n return obj as number;\n } else {\n throw new Error(`${obj} is not a number`);\n }\n}\n\nexport function asBooleanOrThrows(obj: any) {\n if (typeof obj === \"boolean\") {\n return obj as boolean;\n } else {\n throw new Error(`${obj} is not a boolean`);\n }\n}\n\n// So here, in the reference implementation, contentObj is casted to an INamedContent\n// but here we use js-style duck typing: if it implements the same props as the interface,\n// we treat it as valid.\nexport function asINamedContentOrNull(obj: any): INamedContent | null {\n if (obj.hasValidName && obj.name) {\n return obj as INamedContent;\n }\n\n return null;\n}\n\nexport function nullIfUndefined(obj: T | undefined): T | null {\n if (typeof obj === \"undefined\") {\n return null;\n }\n\n return obj;\n}\n\nexport function isEquatable(type: any) {\n return typeof type === \"object\" && typeof type.Equals === \"function\";\n}\n\nfunction unsafeTypeAssertion(\n obj: any,\n type: (new () => T) | (Function & { prototype: T })\n) {\n return obj as T;\n}\n\nexport function filterUndef(element: T | undefined): element is T {\n return element != undefined;\n}\n","import { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { DebugMetadata } from \"../../../engine/DebugMetadata\";\nimport { FindQueryFunc } from \"./FindQueryFunc\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Path as RuntimePath } from \"../../../engine/Path\";\nimport { Story } from \"./Story\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\n\nexport abstract class ParsedObject {\n public abstract readonly GenerateRuntimeObject: () => RuntimeObject | null;\n\n private _alreadyHadError: boolean = false;\n private _alreadyHadWarning: boolean = false;\n private _debugMetadata: DebugMetadata | null = null;\n private _runtimeObject: RuntimeObject | null = null;\n\n public content: ParsedObject[] = [];\n public parent: ParsedObject | null = null;\n\n get debugMetadata() {\n if (this._debugMetadata === null && this.parent) {\n return this.parent.debugMetadata;\n }\n\n return this._debugMetadata;\n }\n\n set debugMetadata(value: DebugMetadata | null) {\n this._debugMetadata = value;\n }\n\n get hasOwnDebugMetadata(): boolean {\n return Boolean(this.debugMetadata);\n }\n\n get typeName(): string {\n return \"ParsedObject\";\n }\n\n public readonly GetType = (): string => this.typeName;\n\n get story(): Story {\n let ancestor: ParsedObject = this;\n while (ancestor.parent) {\n ancestor = ancestor.parent;\n }\n\n return ancestor as Story;\n }\n\n get runtimeObject(): RuntimeObject {\n if (!this._runtimeObject) {\n this._runtimeObject = this.GenerateRuntimeObject();\n if (this._runtimeObject) {\n this._runtimeObject.debugMetadata = this.debugMetadata;\n }\n }\n\n return this._runtimeObject as RuntimeObject;\n }\n\n set runtimeObject(value: RuntimeObject) {\n this._runtimeObject = value;\n }\n\n get runtimePath(): RuntimePath {\n if (!this.runtimeObject.path) {\n throw new Error();\n }\n\n return this.runtimeObject.path;\n }\n\n // When counting visits and turns since, different object\n // types may have different containers that needs to be counted.\n // For most it'll just be the object's main runtime object,\n // but for e.g. choices, it'll be the target container.\n get containerForCounting(): RuntimeContainer | null {\n return this.runtimeObject as RuntimeContainer;\n }\n\n get ancestry(): ParsedObject[] {\n let result = [];\n\n let ancestor = this.parent;\n while (ancestor) {\n result.push(ancestor);\n ancestor = ancestor.parent;\n }\n\n result = result.reverse();\n\n return result;\n }\n\n /*\n get descriptionOfScope(): string {\n const locationNames: string[] = [];\n\n let ancestor: ParsedObject | null = this;\n while (ancestor) {\n var ancestorFlow = ancestor as FlowBase;\n if (ancestorFlow && ancestorFlow.name != null) {\n locationNames.push(`'${ancestorFlow.name}'`);\n }\n ancestor = ancestor.parent;\n }\n\n let scopeSB = '';\n if (locationNames.length > 0) {\n const locationsListStr = locationNames.join(', ');\n scopeSB += `${locationsListStr} and`;\n }\n\n scopeSB += 'at top scope';\n\n return scopeSB;\n }\n*/\n\n // Return the object so that method can be chained easily\n public readonly AddContent = (\n subContent: V\n ) => {\n if (this.content === null) {\n this.content = [];\n }\n\n const sub = Array.isArray(subContent) ? subContent : [subContent];\n\n // Make resilient to content not existing, which can happen\n // in the case of parse errors where we've already reported\n // an error but still want a valid structure so we can\n // carry on parsing.\n for (const ss of sub) {\n if (ss.hasOwnProperty(\"parent\")) {\n ss.parent = this;\n }\n this.content.push(ss);\n }\n\n if (Array.isArray(subContent)) {\n return;\n } else {\n return subContent;\n }\n };\n\n public readonly InsertContent = (\n index: number,\n subContent: T\n ): T => {\n if (this.content === null) {\n this.content = [];\n }\n\n subContent.parent = this;\n this.content.splice(index, 0, subContent);\n\n return subContent;\n };\n\n public readonly Find =\n (\n type: (new (...arg: any[]) => T) | (Function & { prototype: T })\n ) =>\n (queryFunc: FindQueryFunc | null = null): T | null => {\n let tObj = asOrNull(this, type) as any as T;\n if (tObj !== null && (queryFunc === null || queryFunc(tObj) === true)) {\n return tObj;\n }\n\n if (this.content === null) {\n return null;\n }\n\n for (const obj of this.content) {\n let nestedResult = obj.Find && obj.Find(type)(queryFunc);\n if (nestedResult) {\n return nestedResult as T;\n }\n }\n\n return null;\n };\n\n public readonly FindAll =\n (\n type: (new (...arg: any[]) => T) | (Function & { prototype: T })\n ) =>\n (queryFunc?: FindQueryFunc, foundSoFar?: T[]): T[] => {\n const found = Array.isArray(foundSoFar) ? foundSoFar : [];\n\n const tObj = asOrNull(this, type);\n if (tObj !== null && (!queryFunc || queryFunc(tObj) === true)) {\n found.push(tObj);\n }\n\n if (this.content === null) {\n return [];\n }\n\n for (const obj of this.content) {\n obj.FindAll && obj.FindAll(type)(queryFunc, found);\n }\n\n return found;\n };\n\n public ResolveReferences(context: Story) {\n if (this.content !== null) {\n for (const obj of this.content) {\n obj.ResolveReferences(context);\n }\n }\n }\n\n public Error(\n message: string,\n source: ParsedObject | null = null,\n isWarning: boolean = false\n ): void {\n if (source === null) {\n source = this;\n }\n\n // Only allow a single parsed object to have a single error *directly* associated with it\n if (\n (source._alreadyHadError && !isWarning) ||\n (source._alreadyHadWarning && isWarning)\n ) {\n return;\n }\n\n if (this.parent) {\n this.parent.Error(message, source, isWarning);\n } else {\n throw new Error(`No parent object to send error to: ${message}`);\n }\n\n if (isWarning) {\n source._alreadyHadWarning = true;\n } else {\n source._alreadyHadError = true;\n }\n }\n\n public readonly Warning = (\n message: string,\n source: ParsedObject | null = null\n ): void => {\n this.Error(message, source, true);\n };\n}\n","export namespace Debug {\n export function AssertType(\n variable: any,\n type: new () => T,\n message: string\n ): void | never {\n Assert(variable instanceof type, message);\n }\n\n export function Assert(condition: boolean, message?: string): void | never {\n if (!condition) {\n if (typeof message !== \"undefined\") {\n console.warn(message);\n }\n\n if (console.trace) {\n console.trace();\n }\n\n throw new Error(\"\");\n }\n }\n}\n","import { ParsedObject } from \"./Object\";\n\nexport class AuthorWarning extends ParsedObject {\n constructor(public readonly warningMessage: string) {\n super();\n }\n\n get typeName(): string {\n return \"AuthorWarning\";\n }\n\n public readonly GenerateRuntimeObject = (): null => {\n this.Warning(this.warningMessage);\n return null;\n };\n}\n","export class Path {\n public static parentId = \"^\";\n\n public _isRelative: boolean;\n public _components: Path.Component[];\n public _componentsString: string | null;\n\n constructor();\n constructor(componentsString: string);\n constructor(head: Path.Component, tail: Path);\n constructor(head: Path.Component[], relative?: boolean);\n constructor() {\n this._components = [];\n this._componentsString = null;\n this._isRelative = false;\n\n if (typeof arguments[0] == \"string\") {\n let componentsString = arguments[0] as string;\n this.componentsString = componentsString;\n } else if (\n arguments[0] instanceof Path.Component &&\n arguments[1] instanceof Path\n ) {\n let head = arguments[0] as Path.Component;\n let tail = arguments[1] as Path;\n this._components.push(head);\n this._components = this._components.concat(tail._components);\n } else if (arguments[0] instanceof Array) {\n let head = arguments[0] as Path.Component[];\n let relative = !!arguments[1] as boolean;\n this._components = this._components.concat(head);\n this._isRelative = relative;\n }\n }\n get isRelative() {\n return this._isRelative;\n }\n get componentCount(): number {\n return this._components.length;\n }\n get head(): Path.Component | null {\n if (this._components.length > 0) {\n return this._components[0];\n } else {\n return null;\n }\n }\n get tail(): Path {\n if (this._components.length >= 2) {\n // careful, the original code uses length-1 here. This is because the second argument of\n // List.GetRange is a number of elements to extract, wherease Array.slice uses an index\n let tailComps = this._components.slice(1, this._components.length);\n return new Path(tailComps);\n } else {\n return Path.self;\n }\n }\n get length(): number {\n return this._components.length;\n }\n get lastComponent(): Path.Component | null {\n let lastComponentIdx = this._components.length - 1;\n if (lastComponentIdx >= 0) {\n return this._components[lastComponentIdx];\n } else {\n return null;\n }\n }\n get containsNamedComponent(): boolean {\n for (let i = 0, l = this._components.length; i < l; i++) {\n if (!this._components[i].isIndex) {\n return true;\n }\n }\n return false;\n }\n static get self(): Path {\n let path = new Path();\n path._isRelative = true;\n return path;\n }\n\n public GetComponent(index: number): Path.Component {\n return this._components[index];\n }\n public PathByAppendingPath(pathToAppend: Path): Path {\n let p = new Path();\n\n let upwardMoves = 0;\n for (let i = 0; i < pathToAppend._components.length; ++i) {\n if (pathToAppend._components[i].isParent) {\n upwardMoves++;\n } else {\n break;\n }\n }\n\n for (let i = 0; i < this._components.length - upwardMoves; ++i) {\n p._components.push(this._components[i]);\n }\n\n for (let i = upwardMoves; i < pathToAppend._components.length; ++i) {\n p._components.push(pathToAppend._components[i]);\n }\n\n return p;\n }\n get componentsString(): string {\n if (this._componentsString == null) {\n this._componentsString = this._components.join(\".\");\n if (this.isRelative)\n this._componentsString = \".\" + this._componentsString;\n }\n\n return this._componentsString;\n }\n set componentsString(value: string) {\n this._components.length = 0;\n\n this._componentsString = value;\n\n if (this._componentsString == null || this._componentsString == \"\") return;\n\n if (this._componentsString[0] == \".\") {\n this._isRelative = true;\n this._componentsString = this._componentsString.substring(1);\n }\n\n let componentStrings = this._componentsString.split(\".\");\n for (let str of componentStrings) {\n // we need to distinguish between named components that start with a number, eg \"42somewhere\", and indexed components\n // the normal parseInt won't do for the detection because it's too relaxed.\n // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt\n if (/^(\\-|\\+)?([0-9]+|Infinity)$/.test(str)) {\n this._components.push(new Path.Component(parseInt(str)));\n } else {\n this._components.push(new Path.Component(str));\n }\n }\n }\n public toString(): string {\n return this.componentsString;\n }\n public Equals(otherPath: Path | null): boolean {\n if (otherPath == null) return false;\n\n if (otherPath._components.length != this._components.length) return false;\n\n if (otherPath.isRelative != this.isRelative) return false;\n\n // the original code uses SequenceEqual here, so we need to iterate over the components manually.\n for (let i = 0, l = otherPath._components.length; i < l; i++) {\n // it's not quite clear whether this test should use Equals or a simple == operator,\n // see https://github.com/y-lohse/inkjs/issues/22\n if (!otherPath._components[i].Equals(this._components[i])) return false;\n }\n\n return true;\n }\n public PathByAppendingComponent(c: Path.Component): Path {\n let p = new Path();\n p._components.push(...this._components);\n p._components.push(c);\n return p;\n }\n}\n\nexport namespace Path {\n export class Component {\n public readonly index: number;\n public readonly name: string | null;\n\n constructor(indexOrName: string | number) {\n this.index = -1;\n this.name = null;\n if (typeof indexOrName == \"string\") {\n this.name = indexOrName;\n } else {\n this.index = indexOrName;\n }\n }\n get isIndex(): boolean {\n return this.index >= 0;\n }\n get isParent(): boolean {\n return this.name == Path.parentId;\n }\n\n public static ToParent(): Component {\n return new Component(Path.parentId);\n }\n public toString(): string | null {\n if (this.isIndex) {\n return this.index.toString();\n } else {\n return this.name;\n }\n }\n public Equals(otherComp: Component): boolean {\n if (otherComp != null && otherComp.isIndex == this.isIndex) {\n if (this.isIndex) {\n return this.index == otherComp.index;\n } else {\n return this.name == otherComp.name;\n }\n }\n\n return false;\n }\n }\n}\n","/**\n * In the original C# code, a SystemException would be thrown when passing\n * null to methods expected a valid instance. Javascript has no such\n * concept, but TypeScript will not allow `null` to be passed to methods\n * explicitely requiring a valid type.\n *\n * Whenever TypeScript complain about the possibility of a `null` value,\n * check the offending value and it it's null, throw this exception using\n * `throwNullException(name: string)`.\n */\nexport class NullException extends Error {}\n\n/**\n * Throw a NullException.\n *\n * @param name a short description of the offending value (often its name within the code).\n */\nexport function throwNullException(name: string): never {\n throw new NullException(`${name} is null or undefined`);\n}\n","import { Path } from \"./Path\";\nimport { Container } from \"./Container\";\nimport { Debug } from \"./Debug\";\nimport { asOrNull, asINamedContentOrNull } from \"./TypeAssertion\";\nimport { throwNullException } from \"./NullException\";\nimport { SearchResult } from \"./SearchResult\";\nimport { DebugMetadata } from \"./DebugMetadata\";\n\nexport class InkObject {\n public parent: InkObject | null = null;\n\n get debugMetadata(): DebugMetadata | null {\n if (this._debugMetadata === null) {\n if (this.parent) {\n return this.parent.debugMetadata;\n }\n }\n\n return this._debugMetadata;\n }\n\n set debugMetadata(value) {\n this._debugMetadata = value;\n }\n\n get ownDebugMetadata() {\n return this._debugMetadata;\n }\n\n private _debugMetadata: DebugMetadata | null = null;\n\n public DebugLineNumberOfPath(path: Path) {\n if (path === null) return null;\n\n // Try to get a line number from debug metadata\n let root = this.rootContentContainer;\n if (root) {\n let targetContent = root.ContentAtPath(path).obj;\n if (targetContent) {\n let dm = targetContent.debugMetadata;\n if (dm !== null) {\n return dm.startLineNumber;\n }\n }\n }\n\n return null;\n }\n\n get path() {\n if (this._path == null) {\n if (this.parent == null) {\n this._path = new Path();\n } else {\n let comps: Path.Component[] = [];\n\n let child: InkObject = this;\n let container = asOrNull(child.parent, Container);\n\n while (container !== null) {\n let namedChild = asINamedContentOrNull(child);\n if (namedChild != null && namedChild.hasValidName) {\n if (namedChild.name === null)\n return throwNullException(\"namedChild.name\");\n comps.unshift(new Path.Component(namedChild.name!));\n } else {\n comps.unshift(new Path.Component(container.content.indexOf(child)));\n }\n\n child = container;\n container = asOrNull(container.parent, Container);\n }\n\n this._path = new Path(comps);\n }\n }\n\n return this._path;\n }\n private _path: Path | null = null;\n\n public ResolvePath(path: Path | null): SearchResult {\n if (path === null) return throwNullException(\"path\");\n if (path.isRelative) {\n let nearestContainer = asOrNull(this, Container);\n\n if (nearestContainer === null) {\n Debug.Assert(\n this.parent !== null,\n \"Can't resolve relative path because we don't have a parent\"\n );\n nearestContainer = asOrNull(this.parent, Container);\n Debug.Assert(\n nearestContainer !== null,\n \"Expected parent to be a container\"\n );\n Debug.Assert(path.GetComponent(0).isParent);\n path = path.tail;\n }\n\n if (nearestContainer === null) {\n return throwNullException(\"nearestContainer\");\n }\n return nearestContainer.ContentAtPath(path);\n } else {\n let contentContainer = this.rootContentContainer;\n if (contentContainer === null) {\n return throwNullException(\"contentContainer\");\n }\n return contentContainer.ContentAtPath(path);\n }\n }\n\n public ConvertPathToRelative(globalPath: Path) {\n let ownPath = this.path;\n\n let minPathLength = Math.min(globalPath.length, ownPath.length);\n let lastSharedPathCompIndex = -1;\n\n for (let i = 0; i < minPathLength; ++i) {\n let ownComp = ownPath.GetComponent(i);\n let otherComp = globalPath.GetComponent(i);\n\n if (ownComp.Equals(otherComp)) {\n lastSharedPathCompIndex = i;\n } else {\n break;\n }\n }\n\n // No shared path components, so just use global path\n if (lastSharedPathCompIndex == -1) return globalPath;\n\n let numUpwardsMoves = ownPath.componentCount - 1 - lastSharedPathCompIndex;\n\n let newPathComps: Path.Component[] = [];\n\n for (let up = 0; up < numUpwardsMoves; ++up)\n newPathComps.push(Path.Component.ToParent());\n\n for (\n let down = lastSharedPathCompIndex + 1;\n down < globalPath.componentCount;\n ++down\n )\n newPathComps.push(globalPath.GetComponent(down));\n\n let relativePath = new Path(newPathComps, true);\n return relativePath;\n }\n\n public CompactPathString(otherPath: Path) {\n let globalPathStr = null;\n let relativePathStr = null;\n\n if (otherPath.isRelative) {\n relativePathStr = otherPath.componentsString;\n globalPathStr = this.path.PathByAppendingPath(otherPath).componentsString;\n } else {\n let relativePath = this.ConvertPathToRelative(otherPath);\n relativePathStr = relativePath.componentsString;\n globalPathStr = otherPath.componentsString;\n }\n\n if (relativePathStr.length < globalPathStr.length) return relativePathStr;\n else return globalPathStr;\n }\n\n get rootContentContainer() {\n let ancestor: InkObject = this;\n while (ancestor.parent) {\n ancestor = ancestor.parent;\n }\n return asOrNull(ancestor, Container);\n }\n\n public Copy(): InkObject {\n throw Error(\"Not Implemented: Doesn't support copying\");\n }\n // SetChild works slightly diferently in the js implementation.\n // Since we can't pass an objets property by reference, we instead pass\n // the object and the property string.\n // TODO: This method can probably be rewritten with type-safety in mind.\n public SetChild(obj: any, prop: any, value: any) {\n if (obj[prop]) obj[prop] = null;\n\n obj[prop] = value;\n\n if (obj[prop]) obj[prop].parent = this;\n }\n\n public Equals(obj: any) {\n return obj === this;\n }\n}\n","export class StringBuilder {\n private string: string;\n\n constructor(str?: string) {\n str = typeof str !== \"undefined\" ? str.toString() : \"\";\n this.string = str;\n }\n get Length(): number {\n return this.string.length;\n }\n public Append(str: string | null) {\n if (str !== null) {\n this.string += str;\n }\n }\n public AppendLine(str?: string) {\n if (typeof str !== \"undefined\") this.Append(str);\n this.string += \"\\n\";\n }\n public AppendFormat(format: string, ...args: any[]) {\n // taken from http://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format\n this.string += format.replace(/{(\\d+)}/g, (match: string, num: number) =>\n typeof args[num] != \"undefined\" ? args[num] : match\n );\n }\n public toString(): string {\n return this.string;\n }\n\n public Clear() {\n this.string = \"\";\n }\n}\n","import { throwNullException } from \"./NullException\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { Story } from \"./Story\";\n\nexport class InkListItem implements IInkListItem {\n // InkListItem is a struct\n\n public readonly originName: string | null = null;\n public readonly itemName: string | null = null;\n\n constructor(originName: string | null, itemName: string | null);\n constructor(fullName: string | null);\n constructor() {\n if (typeof arguments[1] !== \"undefined\") {\n let originName = arguments[0] as string | null;\n let itemName = arguments[1] as string | null;\n\n this.originName = originName;\n this.itemName = itemName;\n } else if (arguments[0]) {\n let fullName = arguments[0] as string;\n\n let nameParts = fullName.toString().split(\".\");\n this.originName = nameParts[0];\n this.itemName = nameParts[1];\n }\n }\n public static get Null() {\n return new InkListItem(null, null);\n }\n public get isNull() {\n return this.originName == null && this.itemName == null;\n }\n get fullName() {\n return (\n (this.originName !== null ? this.originName : \"?\") + \".\" + this.itemName\n );\n }\n public toString(): string {\n return this.fullName;\n }\n public Equals(obj: InkListItem) {\n if (obj instanceof InkListItem) {\n let otherItem = obj;\n return (\n otherItem.itemName == this.itemName &&\n otherItem.originName == this.originName\n );\n }\n\n return false;\n }\n\n // These methods did not exist in the original C# code. Their purpose is to\n // make `InkListItem` mimics the value-type semantics of the original\n // struct. Please refer to the end of this file, for a more in-depth\n // explanation.\n\n /**\n * Returns a shallow clone of the current instance.\n */\n public copy() {\n return new InkListItem(this.originName, this.itemName);\n }\n /**\n * Returns a `SerializedInkListItem` representing the current\n * instance. The result is intended to be used as a key inside a Map.\n */\n public serialized(): SerializedInkListItem {\n // We are simply using a JSON representation as a value-typed key.\n return JSON.stringify({\n originName: this.originName,\n itemName: this.itemName,\n });\n }\n\n /**\n * Reconstructs a `InkListItem` from the given SerializedInkListItem.\n */\n public static fromSerializedKey(key: SerializedInkListItem): InkListItem {\n let obj = JSON.parse(key);\n if (!InkListItem.isLikeInkListItem(obj)) return InkListItem.Null;\n\n let inkListItem = obj as IInkListItem;\n\n return new InkListItem(inkListItem.originName, inkListItem.itemName);\n }\n\n /**\n * Determines whether the given item is sufficiently `InkListItem`-like\n * to be used as a template when reconstructing the InkListItem.\n */\n private static isLikeInkListItem(item: any) {\n if (typeof item !== \"object\") return false;\n if (!item.hasOwnProperty(\"originName\") || !item.hasOwnProperty(\"itemName\"))\n return false;\n if (typeof item.originName !== \"string\" && typeof item.originName !== null)\n return false;\n if (typeof item.itemName !== \"string\" && typeof item.itemName !== null)\n return false;\n\n return true;\n }\n}\n\nexport class InkList extends Map {\n public origins: ListDefinition[] | null = null;\n public _originNames: string[] | null = [];\n\n constructor();\n constructor(otherList: InkList);\n constructor(singleOriginListName: string, originStory: Story);\n constructor(singleElement: KeyValuePair);\n constructor() {\n // Trying to be smart here, this emulates the constructor inheritance found\n // in the original code, but only if otherList is an InkList. IIFE FTW.\n super(\n (() => {\n if (arguments[0] instanceof InkList) {\n return arguments[0];\n } else {\n return [];\n }\n })()\n );\n\n if (arguments[0] instanceof InkList) {\n let otherList = arguments[0] as InkList;\n\n let otherOriginNames = otherList.originNames as string[];\n if (otherOriginNames !== null)\n this._originNames = otherOriginNames.slice();\n if (otherList.origins !== null) {\n this.origins = otherList.origins.slice();\n }\n } else if (typeof arguments[0] === \"string\") {\n let singleOriginListName = arguments[0] as string;\n let originStory = arguments[1] as Story;\n this.SetInitialOriginName(singleOriginListName);\n\n if (originStory.listDefinitions === null) {\n return throwNullException(\"originStory.listDefinitions\");\n }\n let def = originStory.listDefinitions.TryListGetDefinition(\n singleOriginListName,\n null\n );\n if (def.exists) {\n // Throwing now, because if the value is `null` it will\n // eventually throw down the line.\n if (def.result === null) {\n return throwNullException(\"def.result\");\n }\n this.origins = [def.result];\n } else {\n throw new Error(\n \"InkList origin could not be found in story when constructing new list: \" +\n singleOriginListName\n );\n }\n } else if (\n typeof arguments[0] === \"object\" &&\n arguments[0].hasOwnProperty(\"Key\") &&\n arguments[0].hasOwnProperty(\"Value\")\n ) {\n let singleElement = arguments[0] as KeyValuePair;\n this.Add(singleElement.Key, singleElement.Value);\n }\n }\n\n public static FromString(myListItem: string, originStory: Story) {\n let listValue =\n originStory.listDefinitions?.FindSingleItemListWithName(myListItem);\n if (listValue) {\n if (listValue.value === null) {\n return throwNullException(\"listValue.value\");\n }\n return new InkList(listValue.value);\n } else {\n throw new Error(\n \"Could not find the InkListItem from the string '\" +\n myListItem +\n \"' to create an InkList because it doesn't exist in the original list definition in ink.\"\n );\n }\n }\n\n public AddItem(itemOrItemName: InkListItem | string | null) {\n if (itemOrItemName instanceof InkListItem) {\n let item = itemOrItemName;\n\n if (item.originName == null) {\n this.AddItem(item.itemName);\n return;\n }\n\n if (this.origins === null) return throwNullException(\"this.origins\");\n\n for (let origin of this.origins) {\n if (origin.name == item.originName) {\n let intVal = origin.TryGetValueForItem(item, 0);\n if (intVal.exists) {\n this.Add(item, intVal.result);\n return;\n } else {\n throw new Error(\n \"Could not add the item \" +\n item +\n \" to this list because it doesn't exist in the original list definition in ink.\"\n );\n }\n }\n }\n\n throw new Error(\n \"Failed to add item to list because the item was from a new list definition that wasn't previously known to this list. Only items from previously known lists can be used, so that the int value can be found.\"\n );\n } else {\n let itemName = itemOrItemName as string | null;\n\n let foundListDef: ListDefinition | null = null;\n\n if (this.origins === null) return throwNullException(\"this.origins\");\n\n for (let origin of this.origins) {\n if (itemName === null) return throwNullException(\"itemName\");\n\n if (origin.ContainsItemWithName(itemName)) {\n if (foundListDef != null) {\n throw new Error(\n \"Could not add the item \" +\n itemName +\n \" to this list because it could come from either \" +\n origin.name +\n \" or \" +\n foundListDef.name\n );\n } else {\n foundListDef = origin;\n }\n }\n }\n\n if (foundListDef == null)\n throw new Error(\n \"Could not add the item \" +\n itemName +\n \" to this list because it isn't known to any list definitions previously associated with this list.\"\n );\n\n let item = new InkListItem(foundListDef.name, itemName);\n let itemVal = foundListDef.ValueForItem(item);\n this.Add(item, itemVal);\n }\n }\n public ContainsItemNamed(itemName: string | null) {\n for (let [key] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (item.itemName == itemName) return true;\n }\n\n return false;\n }\n public ContainsKey(key: InkListItem) {\n return this.has(key.serialized());\n }\n public Add(key: InkListItem, value: number) {\n let serializedKey = key.serialized();\n if (this.has(serializedKey)) {\n // Throw an exception to match the C# behavior.\n throw new Error(`The Map already contains an entry for ${key}`);\n }\n this.set(serializedKey, value);\n }\n public Remove(key: InkListItem) {\n return this.delete(key.serialized());\n }\n get Count() {\n return this.size;\n }\n get originOfMaxItem(): ListDefinition | null {\n if (this.origins == null) return null;\n\n let maxOriginName = this.maxItem.Key.originName;\n let result = null;\n this.origins.every((origin) => {\n if (origin.name == maxOriginName) {\n result = origin;\n return false;\n } else return true;\n });\n\n return result;\n }\n get originNames(): string[] {\n if (this.Count > 0) {\n if (this._originNames == null && this.Count > 0) this._originNames = [];\n else {\n if (!this._originNames) this._originNames = [];\n this._originNames.length = 0;\n }\n\n for (let [key] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (item.originName === null)\n return throwNullException(\"item.originName\");\n this._originNames.push(item.originName);\n }\n }\n\n return this._originNames as string[];\n }\n public SetInitialOriginName(initialOriginName: string) {\n this._originNames = [initialOriginName];\n }\n public SetInitialOriginNames(initialOriginNames: string[]) {\n if (initialOriginNames == null) this._originNames = null;\n else this._originNames = initialOriginNames.slice(); // store a copy\n }\n get maxItem() {\n let max: KeyValuePair = {\n Key: InkListItem.Null,\n Value: 0,\n };\n for (let [key, value] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (max.Key.isNull || value > max.Value)\n max = { Key: item, Value: value };\n }\n\n return max;\n }\n get minItem() {\n let min: KeyValuePair = {\n Key: InkListItem.Null,\n Value: 0,\n };\n for (let [key, value] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (min.Key.isNull || value < min.Value) {\n min = { Key: item, Value: value };\n }\n }\n return min;\n }\n get inverse() {\n let list = new InkList();\n if (this.origins != null) {\n for (let origin of this.origins) {\n for (let [key, value] of origin.items) {\n let item = InkListItem.fromSerializedKey(key);\n if (!this.ContainsKey(item)) list.Add(item, value);\n }\n }\n }\n return list;\n }\n get all() {\n let list = new InkList();\n if (this.origins != null) {\n for (let origin of this.origins) {\n for (let [key, value] of origin.items) {\n let item = InkListItem.fromSerializedKey(key);\n list.set(item.serialized(), value);\n }\n }\n }\n return list;\n }\n public Union(otherList: InkList) {\n let union = new InkList(this);\n for (let [key, value] of otherList) {\n union.set(key, value);\n }\n return union;\n }\n public Intersect(otherList: InkList) {\n let intersection = new InkList();\n for (let [key, value] of this) {\n if (otherList.has(key)) intersection.set(key, value);\n }\n\n return intersection;\n }\n public HasIntersection(otherList: InkList): boolean {\n for (let [key] of this) {\n if (otherList.has(key)) return true;\n }\n return false;\n }\n public Without(listToRemove: InkList) {\n let result = new InkList(this);\n for (let [key] of listToRemove) {\n result.delete(key);\n }\n\n return result;\n }\n\n public Contains(key: string): boolean;\n public Contains(otherList: InkList): boolean;\n public Contains(what: string | InkList): boolean {\n if (typeof what == \"string\") return this.ContainsItemNamed(what);\n const otherList = what;\n if (otherList.size == 0 || this.size == 0) return false;\n for (let [key] of otherList) {\n if (!this.has(key)) return false;\n }\n\n return true;\n }\n public GreaterThan(otherList: InkList) {\n if (this.Count == 0) return false;\n if (otherList.Count == 0) return true;\n\n return this.minItem.Value > otherList.maxItem.Value;\n }\n public GreaterThanOrEquals(otherList: InkList) {\n if (this.Count == 0) return false;\n if (otherList.Count == 0) return true;\n\n return (\n this.minItem.Value >= otherList.minItem.Value &&\n this.maxItem.Value >= otherList.maxItem.Value\n );\n }\n public LessThan(otherList: InkList) {\n if (otherList.Count == 0) return false;\n if (this.Count == 0) return true;\n\n return this.maxItem.Value < otherList.minItem.Value;\n }\n public LessThanOrEquals(otherList: InkList) {\n if (otherList.Count == 0) return false;\n if (this.Count == 0) return true;\n\n return (\n this.maxItem.Value <= otherList.maxItem.Value &&\n this.minItem.Value <= otherList.minItem.Value\n );\n }\n public MaxAsList() {\n if (this.Count > 0) return new InkList(this.maxItem);\n else return new InkList();\n }\n public MinAsList() {\n if (this.Count > 0) return new InkList(this.minItem);\n else return new InkList();\n }\n public ListWithSubRange(minBound: any, maxBound: any) {\n if (this.Count == 0) return new InkList();\n\n let ordered = this.orderedItems;\n\n let minValue = 0;\n let maxValue = Number.MAX_SAFE_INTEGER;\n\n if (Number.isInteger(minBound)) {\n minValue = minBound;\n } else {\n if (minBound instanceof InkList && minBound.Count > 0)\n minValue = minBound.minItem.Value;\n }\n\n if (Number.isInteger(maxBound)) {\n maxValue = maxBound;\n } else {\n if (minBound instanceof InkList && minBound.Count > 0)\n maxValue = maxBound.maxItem.Value;\n }\n\n let subList = new InkList();\n subList.SetInitialOriginNames(this.originNames);\n for (let item of ordered) {\n if (item.Value >= minValue && item.Value <= maxValue) {\n subList.Add(item.Key, item.Value);\n }\n }\n\n return subList;\n }\n public Equals(otherInkList: InkList) {\n if (otherInkList instanceof InkList === false) return false;\n if (otherInkList.Count != this.Count) return false;\n\n for (let [key] of this) {\n if (!otherInkList.has(key)) return false;\n }\n\n return true;\n }\n // GetHashCode not implemented\n get orderedItems() {\n // List>\n let ordered = new Array>();\n\n for (let [key, value] of this) {\n let item = InkListItem.fromSerializedKey(key);\n ordered.push({ Key: item, Value: value });\n }\n\n ordered.sort((x, y) => {\n if (x.Key.originName === null) {\n return throwNullException(\"x.Key.originName\");\n }\n if (y.Key.originName === null) {\n return throwNullException(\"y.Key.originName\");\n }\n\n if (x.Value == y.Value) {\n return x.Key.originName.localeCompare(y.Key.originName);\n } else {\n // TODO: refactor this bit into a numberCompareTo method?\n if (x.Value < y.Value) return -1;\n return x.Value > y.Value ? 1 : 0;\n }\n });\n\n return ordered;\n }\n public toString() {\n let ordered = this.orderedItems;\n\n let sb = new StringBuilder();\n for (let i = 0; i < ordered.length; i++) {\n if (i > 0) sb.Append(\", \");\n\n let item = ordered[i].Key;\n if (item.itemName === null) return throwNullException(\"item.itemName\");\n sb.Append(item.itemName);\n }\n\n return sb.toString();\n }\n // casting a InkList to a Number, for somereason, actually gives a number.\n // This messes up the type detection when creating a Value from a InkList.\n // Returning NaN here prevents that.\n public valueOf() {\n return NaN;\n }\n}\n\n/**\n * In the original C# code, `InkListItem` was defined as value type, meaning\n * that two `InkListItem` would be considered equal as long as they held the\n * same values. This doesn't hold true in Javascript, as `InkListItem` is a\n * reference type (Javascript doesn't allow the creation of custom value types).\n *\n * The key equality of Map objects is based on the \"SameValueZero\" algorithm;\n * since `InkListItem` is a value type, two keys will only be considered\n * equal if they are, in fact, the same object. As we are trying to emulate\n * the original behavior as close as possible, this will lead to unforeseen\n * side effects.\n *\n * In order to have a key equality based on value semantics, we'll convert\n * `InkListItem` to a valid string representation and use this representation\n * as a key (strings are value types in Javascript). Rather than using the\n * type `string` directly, we'll alias it to `SerializedInkListItem` and use\n * this type as the key for our Map-based `InkList`.\n *\n * Reducing `InkListItem` to a JSON representation would not be bulletproof\n * in the general case, but for our needs it works well. The major downside of\n * this method is that we will have to to reconstruct the original `InkListItem`\n * every time we'll need to access its properties.\n */\nexport type SerializedInkListItem = string;\n\n/**\n * An interface inherited by `InkListItem`, defining exposed\n * properties. It's mainly used when deserializing a `InkListItem` from its\n * key (`SerializedInkListItem`)\n */\ninterface IInkListItem {\n readonly originName: string | null;\n readonly itemName: string | null;\n}\nexport interface KeyValuePair {\n Key: K;\n Value: V;\n}\n","export class StoryException extends Error {\n public useEndLineNumber: boolean;\n public message: string;\n public name: string;\n\n constructor(message: string) {\n super(message);\n this.useEndLineNumber = false;\n this.message = message;\n this.name = \"StoryException\";\n }\n}\n","/**\n * This interface normalize the `TryGet` behavior found in the original\n * C# project. Any `TryGet` method will return a object conforming to this\n * interface.\n *\n * The original function returns a boolean and has a second parameter called\n * item that is an `out`. Both are needed and we can't just return the item\n * because it'll always be truthy. Instead, we return an object containing\n * whether the result exists (`exists`) and the result itself (`result`).\n *\n * For instance a `TryGet` prototype would look like this:\n```\nTryGetItemWithValue(val: number, item: InkListItem): TryGetResult{\n```\n *\n * On the other hand, dealing with the result can be done in the following way:\n```\nvar item = item.TryGetItemWithValue(intVal, InkListItem.Null);\nif (item.exists) {\n\tconsole.log(item.result)\n}\n```\n *\n */\nexport interface TryGetResult {\n result: T;\n exists: boolean;\n}\n\nexport function tryGetValueFromMap(\n map: Map | null,\n key: K,\n /* out */ value: V\n): TryGetResult {\n if (map === null) {\n return { result: value, exists: false };\n }\n\n let val = map.get(key);\n\n if (typeof val === \"undefined\") {\n return { result: value, exists: false };\n } else {\n return { result: val, exists: true };\n }\n}\n\nexport function tryParseInt(\n value: any,\n /* out */ defaultValue: number = 0\n): TryGetResult {\n let val = parseInt(value);\n\n if (!Number.isNaN(val)) {\n return { result: val, exists: true };\n } else {\n return { result: defaultValue, exists: false };\n }\n}\n\nexport function tryParseFloat(\n value: any,\n /* out */ defaultValue: number = 0\n): TryGetResult {\n let val = parseFloat(value);\n\n if (!Number.isNaN(val)) {\n return { result: val, exists: true };\n } else {\n return { result: defaultValue, exists: false };\n }\n}\n","import { InkObject } from \"./Object\";\nimport { Path } from \"./Path\";\nimport { InkList, InkListItem } from \"./InkList\";\nimport { StoryException } from \"./StoryException\";\nimport { asOrNull, asOrThrows } from \"./TypeAssertion\";\nimport { tryParseInt, tryParseFloat } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\n\nexport abstract class AbstractValue extends InkObject {\n public abstract get valueType(): ValueType;\n public abstract get isTruthy(): boolean;\n public abstract get valueObject(): any;\n\n public abstract Cast(newType: ValueType): Value;\n\n public static Create(\n val: any,\n preferredNumberType?: ValueType\n ): Value | null {\n // This code doesn't exist in upstream and is simply here to enforce\n // the creation of the proper number value.\n // If `preferredNumberType` is not provided or if value doesn't match\n // `preferredNumberType`, this conditional does nothing.\n if (preferredNumberType) {\n if (\n preferredNumberType === (ValueType.Int as ValueType) &&\n Number.isInteger(Number(val))\n ) {\n return new IntValue(Number(val));\n } else if (\n preferredNumberType === (ValueType.Float as ValueType) &&\n !isNaN(val)\n ) {\n return new FloatValue(Number(val));\n }\n }\n\n if (typeof val === \"boolean\") {\n return new BoolValue(Boolean(val));\n }\n\n // https://github.com/y-lohse/inkjs/issues/425\n // Changed condition sequence, because Number('') is\n // parsed to 0, which made setting string to empty\n // impossible\n if (typeof val === \"string\") {\n return new StringValue(String(val));\n } else if (Number.isInteger(Number(val))) {\n return new IntValue(Number(val));\n } else if (!isNaN(val)) {\n return new FloatValue(Number(val));\n } else if (val instanceof Path) {\n return new DivertTargetValue(asOrThrows(val, Path));\n } else if (val instanceof InkList) {\n return new ListValue(asOrThrows(val, InkList));\n }\n\n return null;\n }\n public Copy() {\n return asOrThrows(AbstractValue.Create(this.valueObject), InkObject);\n }\n public BadCastException(targetType: ValueType) {\n return new StoryException(\n \"Can't cast \" +\n this.valueObject +\n \" from \" +\n this.valueType +\n \" to \" +\n targetType\n );\n }\n}\n\nexport abstract class Value<\n T extends { toString: () => string }\n> extends AbstractValue {\n public value: T | null;\n\n constructor(val: T | null) {\n super();\n this.value = val;\n }\n public get valueObject() {\n return this.value;\n }\n public toString() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value.toString();\n }\n}\n\nexport class BoolValue extends Value {\n constructor(val: boolean) {\n super(val || false);\n }\n public get isTruthy() {\n return Boolean(this.value);\n }\n public get valueType() {\n return ValueType.Bool;\n }\n\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Int) {\n return new IntValue(this.value ? 1 : 0);\n }\n\n if (newType == ValueType.Float) {\n return new FloatValue(this.value ? 1.0 : 0.0);\n }\n\n if (newType == ValueType.String) {\n return new StringValue(this.value ? \"true\" : \"false\");\n }\n\n throw this.BadCastException(newType);\n }\n\n public toString() {\n return this.value ? \"true\" : \"false\";\n }\n}\n\nexport class IntValue extends Value {\n constructor(val: number) {\n super(val || 0);\n }\n public get isTruthy() {\n return this.value != 0;\n }\n public get valueType() {\n return ValueType.Int;\n }\n\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Bool) {\n return new BoolValue(this.value === 0 ? false : true);\n }\n\n if (newType == ValueType.Float) {\n return new FloatValue(this.value);\n }\n\n if (newType == ValueType.String) {\n return new StringValue(\"\" + this.value);\n }\n\n throw this.BadCastException(newType);\n }\n}\n\nexport class FloatValue extends Value {\n constructor(val: number) {\n super(val || 0.0);\n }\n public get isTruthy() {\n return this.value != 0.0;\n }\n public get valueType() {\n return ValueType.Float;\n }\n\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Bool) {\n return new BoolValue(this.value === 0.0 ? false : true);\n }\n\n if (newType == ValueType.Int) {\n return new IntValue(this.value);\n }\n\n if (newType == ValueType.String) {\n return new StringValue(\"\" + this.value);\n }\n\n throw this.BadCastException(newType);\n }\n}\n\nexport class StringValue extends Value {\n public _isNewline: boolean;\n public _isInlineWhitespace: boolean;\n\n constructor(val: string) {\n super(val || \"\");\n\n this._isNewline = this.value == \"\\n\";\n this._isInlineWhitespace = true;\n\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (this.value.length > 0) {\n this.value.split(\"\").every((c) => {\n if (c != \" \" && c != \"\\t\") {\n this._isInlineWhitespace = false;\n return false;\n }\n\n return true;\n });\n }\n }\n public get valueType() {\n return ValueType.String;\n }\n public get isTruthy() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value.length > 0;\n }\n public get isNewline() {\n return this._isNewline;\n }\n public get isInlineWhitespace() {\n return this._isInlineWhitespace;\n }\n public get isNonWhitespace() {\n return !this.isNewline && !this.isInlineWhitespace;\n }\n\n public Cast(newType: ValueType): Value {\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Int) {\n let parsedInt = tryParseInt(this.value);\n if (parsedInt.exists) {\n return new IntValue(parsedInt.result);\n } else {\n throw this.BadCastException(newType);\n }\n }\n\n if (newType == ValueType.Float) {\n let parsedFloat = tryParseFloat(this.value);\n if (parsedFloat.exists) {\n return new FloatValue(parsedFloat.result);\n } else {\n throw this.BadCastException(newType);\n }\n }\n\n throw this.BadCastException(newType);\n }\n}\n\nexport class DivertTargetValue extends Value {\n constructor(targetPath: Path | null = null) {\n super(targetPath);\n }\n public get valueType() {\n return ValueType.DivertTarget;\n }\n public get targetPath() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value;\n }\n public set targetPath(value: Path) {\n this.value = value;\n }\n public get isTruthy(): never {\n throw new Error(\"Shouldn't be checking the truthiness of a divert target\");\n }\n\n public Cast(newType: ValueType): Value {\n if (newType == this.valueType) return this;\n\n throw this.BadCastException(newType);\n }\n public toString() {\n return \"DivertTargetValue(\" + this.targetPath + \")\";\n }\n}\n\nexport class VariablePointerValue extends Value {\n public _contextIndex: number;\n\n constructor(variableName: string, contextIndex: number = -1) {\n super(variableName);\n\n this._contextIndex = contextIndex;\n }\n\n public get contextIndex() {\n return this._contextIndex;\n }\n public set contextIndex(value: number) {\n this._contextIndex = value;\n }\n public get variableName() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value;\n }\n public set variableName(value: string) {\n this.value = value;\n }\n public get valueType() {\n return ValueType.VariablePointer;\n }\n\n public get isTruthy(): never {\n throw new Error(\n \"Shouldn't be checking the truthiness of a variable pointer\"\n );\n }\n\n public Cast(newType: ValueType): Value {\n if (newType == this.valueType) return this;\n\n throw this.BadCastException(newType);\n }\n public toString() {\n return \"VariablePointerValue(\" + this.variableName + \")\";\n }\n public Copy() {\n return new VariablePointerValue(this.variableName, this.contextIndex);\n }\n}\n\nexport class ListValue extends Value {\n public get isTruthy() {\n if (this.value === null) {\n return throwNullException(\"this.value\");\n }\n return this.value.Count > 0;\n }\n public get valueType() {\n return ValueType.List;\n }\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == ValueType.Int) {\n let max = this.value.maxItem;\n if (max.Key.isNull) return new IntValue(0);\n else return new IntValue(max.Value);\n } else if (newType == ValueType.Float) {\n let max = this.value.maxItem;\n if (max.Key.isNull) return new FloatValue(0.0);\n else return new FloatValue(max.Value);\n } else if (newType == ValueType.String) {\n let max = this.value.maxItem;\n if (max.Key.isNull) return new StringValue(\"\");\n else {\n return new StringValue(max.Key.toString());\n }\n }\n\n if (newType == this.valueType) return this;\n\n throw this.BadCastException(newType);\n }\n constructor();\n constructor(list: InkList);\n constructor(listOrSingleItem: InkListItem, singleValue: number);\n constructor(listOrSingleItem?: InkListItem | InkList, singleValue?: number) {\n super(null);\n\n if (!listOrSingleItem && !singleValue) {\n this.value = new InkList();\n } else if (listOrSingleItem instanceof InkList) {\n this.value = new InkList(listOrSingleItem);\n } else if (\n listOrSingleItem instanceof InkListItem &&\n typeof singleValue === \"number\"\n ) {\n this.value = new InkList({\n Key: listOrSingleItem,\n Value: singleValue,\n });\n }\n }\n public static RetainListOriginsForAssignment(\n oldValue: InkObject | null,\n newValue: InkObject\n ) {\n let oldList = asOrNull(oldValue, ListValue);\n let newList = asOrNull(newValue, ListValue);\n\n if (newList && newList.value === null)\n return throwNullException(\"newList.value\");\n if (oldList && oldList.value === null)\n return throwNullException(\"oldList.value\");\n\n // When assigning the empty list, try to retain any initial origin names\n if (oldList && newList && newList.value!.Count == 0)\n newList.value!.SetInitialOriginNames(oldList.value!.originNames);\n }\n}\n\nexport enum ValueType {\n Bool = -1,\n Int = 0,\n Float = 1,\n List = 2,\n String = 3,\n DivertTarget = 4,\n VariablePointer = 5,\n}\n","import { InkObject } from \"./Object\";\nimport { Container } from \"./Container\";\n\nexport class SearchResult {\n public obj: InkObject | null = null;\n public approximate: boolean = false;\n\n get correctObj() {\n return this.approximate ? null : this.obj;\n }\n\n get container() {\n return this.obj instanceof Container ? this.obj : null;\n }\n\n public copy() {\n let searchResult = new SearchResult();\n searchResult.obj = this.obj;\n searchResult.approximate = this.approximate;\n\n return searchResult;\n }\n}\n","import { StringValue } from \"./Value\";\nimport { throwNullException } from \"./NullException\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { INamedContent } from \"./INamedContent\";\nimport { InkObject } from \"./Object\";\nimport { SearchResult } from \"./SearchResult\";\nimport { Path } from \"./Path\";\nimport { Debug } from \"./Debug\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { asINamedContentOrNull, asOrNull, asOrThrows } from \"./TypeAssertion\";\n\nexport class Container extends InkObject implements INamedContent {\n public name: string | null = null;\n\n public _content: InkObject[] = [];\n public namedContent: Map = new Map();\n\n public visitsShouldBeCounted: boolean = false;\n public turnIndexShouldBeCounted: boolean = false;\n public countingAtStartOnly: boolean = false;\n\n public _pathToFirstLeafContent: Path | null = null;\n\n get hasValidName() {\n return this.name != null && this.name.length > 0;\n }\n get content() {\n return this._content;\n }\n set content(value: InkObject[]) {\n this.AddContent(value);\n }\n get namedOnlyContent() {\n let namedOnlyContentDict: Map | null = new Map();\n\n for (let [key, value] of this.namedContent) {\n let inkObject = asOrThrows(value, InkObject);\n namedOnlyContentDict.set(key, inkObject);\n }\n\n for (let c of this.content) {\n let named = asINamedContentOrNull(c);\n if (named != null && named.hasValidName) {\n namedOnlyContentDict.delete(named.name!);\n }\n }\n\n if (namedOnlyContentDict.size == 0) namedOnlyContentDict = null;\n\n return namedOnlyContentDict;\n }\n set namedOnlyContent(value: Map | null) {\n let existingNamedOnly = this.namedOnlyContent;\n if (existingNamedOnly != null) {\n for (let [key] of existingNamedOnly) {\n this.namedContent.delete(key);\n }\n }\n\n if (value == null) return;\n\n for (let [, val] of value) {\n let named = asINamedContentOrNull(val);\n if (named != null) this.AddToNamedContentOnly(named);\n }\n }\n get countFlags(): number {\n let flags: Container.CountFlags = 0;\n if (this.visitsShouldBeCounted) flags |= Container.CountFlags.Visits;\n if (this.turnIndexShouldBeCounted) flags |= Container.CountFlags.Turns;\n if (this.countingAtStartOnly) flags |= Container.CountFlags.CountStartOnly;\n\n if (flags == Container.CountFlags.CountStartOnly) {\n flags = 0;\n }\n\n return flags;\n }\n set countFlags(value: number) {\n let flag: Container.CountFlags = value;\n if ((flag & Container.CountFlags.Visits) > 0)\n this.visitsShouldBeCounted = true;\n if ((flag & Container.CountFlags.Turns) > 0)\n this.turnIndexShouldBeCounted = true;\n if ((flag & Container.CountFlags.CountStartOnly) > 0)\n this.countingAtStartOnly = true;\n }\n get pathToFirstLeafContent() {\n if (this._pathToFirstLeafContent == null)\n this._pathToFirstLeafContent = this.path.PathByAppendingPath(\n this.internalPathToFirstLeafContent\n );\n\n return this._pathToFirstLeafContent;\n }\n get internalPathToFirstLeafContent() {\n let components: Path.Component[] = [];\n let container: Container = this;\n while (container instanceof Container) {\n if (container.content.length > 0) {\n components.push(new Path.Component(0));\n container = container.content[0] as Container;\n }\n }\n return new Path(components);\n }\n\n public AddContent(contentObjOrList: InkObject | InkObject[]) {\n if (contentObjOrList instanceof Array) {\n let contentList = contentObjOrList as InkObject[];\n\n for (let c of contentList) {\n this.AddContent(c);\n }\n } else {\n let contentObj = contentObjOrList as InkObject;\n\n this._content.push(contentObj);\n\n if (contentObj.parent) {\n throw new Error(\"content is already in \" + contentObj.parent);\n }\n\n contentObj.parent = this;\n\n this.TryAddNamedContent(contentObj);\n }\n }\n public TryAddNamedContent(contentObj: InkObject) {\n let namedContentObj = asINamedContentOrNull(contentObj);\n if (namedContentObj != null && namedContentObj.hasValidName) {\n this.AddToNamedContentOnly(namedContentObj);\n }\n }\n public AddToNamedContentOnly(namedContentObj: INamedContent) {\n Debug.AssertType(\n namedContentObj,\n InkObject,\n \"Can only add Runtime.Objects to a Runtime.Container\"\n );\n let runtimeObj = asOrThrows(namedContentObj, InkObject);\n runtimeObj.parent = this;\n\n if (namedContentObj.name === null)\n return throwNullException(\"namedContentObj.name\");\n this.namedContent.set(namedContentObj.name!, namedContentObj);\n }\n public ContentAtPath(\n path: Path,\n partialPathStart: number = 0,\n partialPathLength: number = -1\n ) {\n if (partialPathLength == -1) partialPathLength = path.length;\n\n let result = new SearchResult();\n result.approximate = false;\n\n let currentContainer: Container | null = this;\n let currentObj: InkObject = this;\n\n for (let i = partialPathStart; i < partialPathLength; ++i) {\n let comp = path.GetComponent(i);\n if (currentContainer == null) {\n result.approximate = true;\n break;\n }\n\n let foundObj: InkObject | null =\n currentContainer.ContentWithPathComponent(comp);\n\n if (foundObj == null) {\n result.approximate = true;\n break;\n }\n\n currentObj = foundObj;\n currentContainer = asOrNull(foundObj, Container);\n }\n\n result.obj = currentObj;\n\n return result;\n }\n public InsertContent(contentObj: InkObject, index: number) {\n this.content.splice(index, 0, contentObj);\n\n if (contentObj.parent) {\n throw new Error(\"content is already in \" + contentObj.parent);\n }\n\n contentObj.parent = this;\n\n this.TryAddNamedContent(contentObj);\n }\n public AddContentsOfContainer(otherContainer: Container) {\n this.content.push(...otherContainer.content);\n\n for (let obj of otherContainer.content) {\n obj.parent = this;\n this.TryAddNamedContent(obj);\n }\n }\n public ContentWithPathComponent(component: Path.Component): InkObject | null {\n if (component.isIndex) {\n if (component.index >= 0 && component.index < this.content.length) {\n return this.content[component.index];\n } else {\n return null;\n }\n } else if (component.isParent) {\n return this.parent;\n } else {\n if (component.name === null) {\n return throwNullException(\"component.name\");\n }\n let foundContent = tryGetValueFromMap(\n this.namedContent,\n component.name,\n null\n );\n if (foundContent.exists) {\n return asOrThrows(foundContent.result, InkObject);\n } else {\n return null;\n }\n }\n }\n public BuildStringOfHierarchy(): string;\n public BuildStringOfHierarchy(\n sb: StringBuilder,\n indentation: number,\n pointedObj: InkObject | null\n ): string;\n public BuildStringOfHierarchy() {\n let sb: StringBuilder;\n if (arguments.length == 0) {\n sb = new StringBuilder();\n this.BuildStringOfHierarchy(sb, 0, null);\n return sb.toString();\n }\n\n sb = arguments[0] as StringBuilder;\n let indentation = arguments[1] as number;\n let pointedObj = arguments[2] as InkObject | null;\n\n function appendIndentation() {\n const spacesPerIndent = 4; // Truly const in the original code\n for (let i = 0; i < spacesPerIndent * indentation; ++i) {\n sb.Append(\" \");\n }\n }\n\n appendIndentation();\n sb.Append(\"[\");\n\n if (this.hasValidName) {\n sb.AppendFormat(\" ({0})\", this.name);\n }\n\n if (this == pointedObj) {\n sb.Append(\" <---\");\n }\n\n sb.AppendLine();\n\n indentation++;\n\n for (let i = 0; i < this.content.length; ++i) {\n let obj = this.content[i];\n\n if (obj instanceof Container) {\n let container = obj as Container;\n\n container.BuildStringOfHierarchy(sb, indentation, pointedObj);\n } else {\n appendIndentation();\n if (obj instanceof StringValue) {\n sb.Append('\"');\n sb.Append(obj.toString().replace(\"\\n\", \"\\\\n\"));\n sb.Append('\"');\n } else {\n sb.Append(obj.toString());\n }\n }\n\n if (i != this.content.length - 1) {\n sb.Append(\",\");\n }\n\n if (!(obj instanceof Container) && obj == pointedObj) {\n sb.Append(\" <---\");\n }\n\n sb.AppendLine();\n }\n\n let onlyNamed: Map = new Map();\n\n for (let [key, value] of this.namedContent) {\n if (this.content.indexOf(asOrThrows(value, InkObject)) >= 0) {\n continue;\n } else {\n onlyNamed.set(key, value);\n }\n }\n\n if (onlyNamed.size > 0) {\n appendIndentation();\n sb.AppendLine(\"-- named: --\");\n\n for (let [, value] of onlyNamed) {\n Debug.AssertType(\n value,\n Container,\n \"Can only print out named Containers\"\n );\n let container = value as Container;\n container.BuildStringOfHierarchy(sb, indentation, pointedObj);\n sb.AppendLine();\n }\n }\n\n indentation--;\n\n appendIndentation();\n sb.Append(\"]\");\n }\n}\n\nexport namespace Container {\n export enum CountFlags {\n Visits = 1,\n Turns = 2,\n CountStartOnly = 4,\n }\n}\n","import { InkObject } from \"./Object\";\n\nexport class ControlCommand extends InkObject {\n private _commandType: ControlCommand.CommandType;\n\n get commandType(): ControlCommand.CommandType {\n return this._commandType;\n }\n\n constructor(\n commandType: ControlCommand.CommandType = ControlCommand.CommandType.NotSet\n ) {\n super();\n this._commandType = commandType;\n }\n\n public Copy() {\n return new ControlCommand(this.commandType);\n }\n public static EvalStart() {\n return new ControlCommand(ControlCommand.CommandType.EvalStart);\n }\n public static EvalOutput() {\n return new ControlCommand(ControlCommand.CommandType.EvalOutput);\n }\n public static EvalEnd() {\n return new ControlCommand(ControlCommand.CommandType.EvalEnd);\n }\n public static Duplicate() {\n return new ControlCommand(ControlCommand.CommandType.Duplicate);\n }\n public static PopEvaluatedValue() {\n return new ControlCommand(ControlCommand.CommandType.PopEvaluatedValue);\n }\n public static PopFunction() {\n return new ControlCommand(ControlCommand.CommandType.PopFunction);\n }\n public static PopTunnel() {\n return new ControlCommand(ControlCommand.CommandType.PopTunnel);\n }\n public static BeginString() {\n return new ControlCommand(ControlCommand.CommandType.BeginString);\n }\n public static EndString() {\n return new ControlCommand(ControlCommand.CommandType.EndString);\n }\n public static NoOp() {\n return new ControlCommand(ControlCommand.CommandType.NoOp);\n }\n public static ChoiceCount() {\n return new ControlCommand(ControlCommand.CommandType.ChoiceCount);\n }\n public static Turns() {\n return new ControlCommand(ControlCommand.CommandType.Turns);\n }\n public static TurnsSince() {\n return new ControlCommand(ControlCommand.CommandType.TurnsSince);\n }\n public static ReadCount() {\n return new ControlCommand(ControlCommand.CommandType.ReadCount);\n }\n public static Random() {\n return new ControlCommand(ControlCommand.CommandType.Random);\n }\n public static SeedRandom() {\n return new ControlCommand(ControlCommand.CommandType.SeedRandom);\n }\n public static VisitIndex() {\n return new ControlCommand(ControlCommand.CommandType.VisitIndex);\n }\n public static SequenceShuffleIndex() {\n return new ControlCommand(ControlCommand.CommandType.SequenceShuffleIndex);\n }\n public static StartThread() {\n return new ControlCommand(ControlCommand.CommandType.StartThread);\n }\n public static Done() {\n return new ControlCommand(ControlCommand.CommandType.Done);\n }\n public static End() {\n return new ControlCommand(ControlCommand.CommandType.End);\n }\n public static ListFromInt() {\n return new ControlCommand(ControlCommand.CommandType.ListFromInt);\n }\n public static ListRange() {\n return new ControlCommand(ControlCommand.CommandType.ListRange);\n }\n public static ListRandom() {\n return new ControlCommand(ControlCommand.CommandType.ListRandom);\n }\n public static BeginTag() {\n return new ControlCommand(ControlCommand.CommandType.BeginTag);\n }\n public static EndTag() {\n return new ControlCommand(ControlCommand.CommandType.EndTag);\n }\n public toString() {\n return this.commandType.toString();\n }\n}\n\nexport namespace ControlCommand {\n export enum CommandType {\n NotSet = -1,\n EvalStart, // 0\n EvalOutput, // 1\n EvalEnd, // 2\n Duplicate, // 3\n PopEvaluatedValue, // 4\n PopFunction, // 5\n PopTunnel, // 6\n BeginString, // 7\n EndString, // 8\n NoOp, // 9\n ChoiceCount, // 10\n Turns, // 11\n TurnsSince, // 12\n ReadCount, // 13\n Random, // 14\n SeedRandom, // 15\n VisitIndex, // 16\n SequenceShuffleIndex, // 17\n StartThread, // 18\n Done, // 19\n End, // 20\n ListFromInt, // 21\n ListRange, // 22\n ListRandom, // 23\n BeginTag, // 24\n EndTag, // 25\n\n TOTAL_VALUES,\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\n\nexport abstract class Expression extends ParsedObject {\n public abstract GenerateIntoContainer: (container: RuntimeContainer) => void;\n\n private _prototypeRuntimeConstantExpression: RuntimeContainer | null = null;\n public outputWhenComplete: boolean = false;\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n\n // Tell Runtime to start evaluating the following content as an expression\n container.AddContent(RuntimeControlCommand.EvalStart());\n\n this.GenerateIntoContainer(container);\n\n // Tell Runtime to output the result of the expression evaluation to the output stream\n if (this.outputWhenComplete) {\n container.AddContent(RuntimeControlCommand.EvalOutput());\n }\n\n // Tell Runtime to stop evaluating the content as an expression\n container.AddContent(RuntimeControlCommand.EvalEnd());\n\n return container;\n };\n\n // When generating the value of a constant expression,\n // we can't just keep generating the same constant expression into\n // different places where the constant value is referenced, since then\n // the same runtime objects would be used in multiple places, which\n // is impossible since each runtime object should have one parent.\n // Instead, we generate a prototype of the runtime object(s), then\n // copy them each time they're used.\n public readonly GenerateConstantIntoContainer = (\n container: RuntimeContainer\n ): void => {\n if (this._prototypeRuntimeConstantExpression === null) {\n this._prototypeRuntimeConstantExpression = new RuntimeContainer();\n this.GenerateIntoContainer(this._prototypeRuntimeConstantExpression);\n }\n\n for (const runtimeObj of this._prototypeRuntimeConstantExpression.content) {\n const copy = runtimeObj.Copy();\n if (copy) {\n container.AddContent(copy);\n }\n }\n };\n\n get typeName(): string {\n return \"Expression\";\n }\n\n public Equals(obj: ParsedObject): boolean {\n return false;\n }\n\n public readonly toString = () => \"No string value in JavaScript.\";\n}\n","import { InkObject } from \"./Object\";\n\nexport class Void extends InkObject {}\n","import { Value, ValueType, IntValue, ListValue, BoolValue } from \"./Value\";\nimport { StoryException } from \"./StoryException\";\nimport { Void } from \"./Void\";\nimport { Path } from \"./Path\";\nimport { InkList, InkListItem } from \"./InkList\";\nimport { InkObject } from \"./Object\";\nimport { asOrNull, asOrThrows, asBooleanOrThrows } from \"./TypeAssertion\";\nimport { throwNullException } from \"./NullException\";\n\ntype BinaryOp = (left: T, right: T) => any;\ntype UnaryOp = (val: T) => any;\n\nexport class NativeFunctionCall extends InkObject {\n public static readonly Add: string = \"+\";\n public static readonly Subtract: string = \"-\";\n public static readonly Divide: string = \"/\";\n public static readonly Multiply: string = \"*\";\n public static readonly Mod: string = \"%\";\n public static readonly Negate: string = \"_\";\n public static readonly Equal: string = \"==\";\n public static readonly Greater: string = \">\";\n public static readonly Less: string = \"<\";\n public static readonly GreaterThanOrEquals: string = \">=\";\n public static readonly LessThanOrEquals: string = \"<=\";\n public static readonly NotEquals: string = \"!=\";\n public static readonly Not: string = \"!\";\n public static readonly And: string = \"&&\";\n public static readonly Or: string = \"||\";\n public static readonly Min: string = \"MIN\";\n public static readonly Max: string = \"MAX\";\n public static readonly Pow: string = \"POW\";\n public static readonly Floor: string = \"FLOOR\";\n public static readonly Ceiling: string = \"CEILING\";\n public static readonly Int: string = \"INT\";\n public static readonly Float: string = \"FLOAT\";\n public static readonly Has: string = \"?\";\n public static readonly Hasnt: string = \"!?\";\n public static readonly Intersect: string = \"^\";\n public static readonly ListMin: string = \"LIST_MIN\";\n public static readonly ListMax: string = \"LIST_MAX\";\n public static readonly All: string = \"LIST_ALL\";\n public static readonly Count: string = \"LIST_COUNT\";\n public static readonly ValueOfList: string = \"LIST_VALUE\";\n public static readonly Invert: string = \"LIST_INVERT\";\n\n public static CallWithName(functionName: string) {\n return new NativeFunctionCall(functionName);\n }\n\n public static CallExistsWithName(functionName: string) {\n this.GenerateNativeFunctionsIfNecessary();\n return this._nativeFunctions!.get(functionName);\n }\n\n get name() {\n if (this._name === null)\n return throwNullException(\"NativeFunctionCall._name\");\n return this._name;\n }\n set name(value: string) {\n this._name = value;\n if (!this._isPrototype) {\n if (NativeFunctionCall._nativeFunctions === null)\n throwNullException(\"NativeFunctionCall._nativeFunctions\");\n else\n this._prototype =\n NativeFunctionCall._nativeFunctions.get(this._name) || null;\n }\n }\n public _name: string | null = null;\n\n get numberOfParameters() {\n if (this._prototype) {\n return this._prototype.numberOfParameters;\n } else {\n return this._numberOfParameters;\n }\n }\n set numberOfParameters(value: number) {\n this._numberOfParameters = value;\n }\n public _numberOfParameters: number = 0;\n\n public Call(parameters: InkObject[]): InkObject | null {\n if (this._prototype) {\n return this._prototype.Call(parameters);\n }\n\n if (this.numberOfParameters != parameters.length) {\n throw new Error(\"Unexpected number of parameters\");\n }\n\n let hasList = false;\n for (let p of parameters) {\n if (p instanceof Void)\n throw new StoryException(\n 'Attempting to perform operation on a void value. Did you forget to \"return\" a value from a function you called here?'\n );\n if (p instanceof ListValue) hasList = true;\n }\n\n if (parameters.length == 2 && hasList) {\n return this.CallBinaryListOperation(parameters);\n }\n\n let coercedParams = this.CoerceValuesToSingleType(parameters);\n let coercedType = coercedParams[0].valueType;\n\n if (coercedType == ValueType.Int) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.Float) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.String) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.DivertTarget) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.List) {\n return this.CallType(coercedParams);\n }\n\n return null;\n }\n\n public CallType(parametersOfSingleType: Array>) {\n let param1 = asOrThrows(parametersOfSingleType[0], Value);\n let valType = param1.valueType;\n\n let val1 = param1 as Value;\n\n let paramCount = parametersOfSingleType.length;\n\n if (paramCount == 2 || paramCount == 1) {\n if (this._operationFuncs === null)\n return throwNullException(\"NativeFunctionCall._operationFuncs\");\n let opForTypeObj = this._operationFuncs.get(valType);\n if (!opForTypeObj) {\n const key = ValueType[valType];\n throw new StoryException(\n \"Cannot perform operation \" + this.name + \" on \" + key\n );\n }\n\n if (paramCount == 2) {\n let param2 = asOrThrows(parametersOfSingleType[1], Value);\n\n let val2 = param2 as Value;\n\n let opForType = opForTypeObj as BinaryOp;\n\n if (val1.value === null || val2.value === null)\n return throwNullException(\"NativeFunctionCall.Call BinaryOp values\");\n let resultVal = opForType(val1.value, val2.value);\n\n return Value.Create(resultVal);\n } else {\n let opForType = opForTypeObj as UnaryOp;\n\n if (val1.value === null)\n return throwNullException(\"NativeFunctionCall.Call UnaryOp value\");\n let resultVal = opForType(val1.value);\n\n // This code is different from upstream. Since JavaScript treats\n // integers and floats as the same numbers, it's impossible\n // to force an number to be either an integer or a float.\n //\n // It can be useful to force a specific number type\n // (especially for divisions), so the result of INT() & FLOAT()\n // is coerced to the the proper value type.\n //\n // Note that we also force all other unary operation to\n // return the same value type, although this is only\n // meaningful for numbers. See `Value.Create`.\n if (this.name === NativeFunctionCall.Int) {\n return Value.Create(resultVal, ValueType.Int);\n } else if (this.name === NativeFunctionCall.Float) {\n return Value.Create(resultVal, ValueType.Float);\n } else {\n return Value.Create(resultVal, param1.valueType);\n }\n }\n } else {\n throw new Error(\n \"Unexpected number of parameters to NativeFunctionCall: \" +\n parametersOfSingleType.length\n );\n }\n }\n\n public CallBinaryListOperation(parameters: InkObject[]) {\n if (\n (this.name == \"+\" || this.name == \"-\") &&\n parameters[0] instanceof ListValue &&\n parameters[1] instanceof IntValue\n )\n return this.CallListIncrementOperation(parameters);\n\n let v1 = asOrThrows(parameters[0], Value);\n let v2 = asOrThrows(parameters[1], Value);\n\n if (\n (this.name == \"&&\" || this.name == \"||\") &&\n (v1.valueType != ValueType.List || v2.valueType != ValueType.List)\n ) {\n if (this._operationFuncs === null)\n return throwNullException(\"NativeFunctionCall._operationFuncs\");\n let op = this._operationFuncs.get(ValueType.Int) as BinaryOp;\n if (op === null)\n return throwNullException(\n \"NativeFunctionCall.CallBinaryListOperation op\"\n );\n let result = asBooleanOrThrows(\n op(v1.isTruthy ? 1 : 0, v2.isTruthy ? 1 : 0)\n );\n return new BoolValue(result);\n }\n\n if (v1.valueType == ValueType.List && v2.valueType == ValueType.List)\n return this.CallType([v1, v2]);\n\n throw new StoryException(\n \"Can not call use \" +\n this.name +\n \" operation on \" +\n ValueType[v1.valueType] +\n \" and \" +\n ValueType[v2.valueType]\n );\n }\n\n public CallListIncrementOperation(listIntParams: InkObject[]) {\n let listVal = asOrThrows(listIntParams[0], ListValue);\n let intVal = asOrThrows(listIntParams[1], IntValue);\n\n let resultInkList = new InkList();\n\n if (listVal.value === null)\n return throwNullException(\n \"NativeFunctionCall.CallListIncrementOperation listVal.value\"\n );\n for (let [listItemKey, listItemValue] of listVal.value) {\n let listItem = InkListItem.fromSerializedKey(listItemKey);\n\n if (this._operationFuncs === null)\n return throwNullException(\"NativeFunctionCall._operationFuncs\");\n let intOp = this._operationFuncs.get(ValueType.Int) as BinaryOp;\n\n if (intVal.value === null)\n return throwNullException(\n \"NativeFunctionCall.CallListIncrementOperation intVal.value\"\n );\n let targetInt = intOp(listItemValue, intVal.value);\n\n let itemOrigin = null;\n if (listVal.value.origins === null)\n return throwNullException(\n \"NativeFunctionCall.CallListIncrementOperation listVal.value.origins\"\n );\n for (let origin of listVal.value.origins) {\n if (origin.name == listItem.originName) {\n itemOrigin = origin;\n break;\n }\n }\n if (itemOrigin != null) {\n let incrementedItem = itemOrigin.TryGetItemWithValue(\n targetInt,\n InkListItem.Null\n );\n if (incrementedItem.exists)\n resultInkList.Add(incrementedItem.result, targetInt);\n }\n }\n\n return new ListValue(resultInkList);\n }\n\n public CoerceValuesToSingleType(parametersIn: InkObject[]) {\n let valType = ValueType.Int;\n\n let specialCaseList: null | ListValue = null;\n\n for (let obj of parametersIn) {\n let val = asOrThrows(obj, Value);\n if (val.valueType > valType) {\n valType = val.valueType;\n }\n\n if (val.valueType == ValueType.List) {\n specialCaseList = asOrNull(val, ListValue);\n }\n }\n\n let parametersOut = [];\n\n if (ValueType[valType] == ValueType[ValueType.List]) {\n for (let inkObjectVal of parametersIn) {\n let val = asOrThrows(inkObjectVal, Value);\n if (val.valueType == ValueType.List) {\n parametersOut.push(val);\n } else if (val.valueType == ValueType.Int) {\n let intVal = parseInt(val.valueObject);\n\n specialCaseList = asOrThrows(specialCaseList, ListValue);\n if (specialCaseList.value === null)\n return throwNullException(\n \"NativeFunctionCall.CoerceValuesToSingleType specialCaseList.value\"\n );\n let list = specialCaseList.value.originOfMaxItem;\n\n if (list === null)\n return throwNullException(\n \"NativeFunctionCall.CoerceValuesToSingleType list\"\n );\n let item = list.TryGetItemWithValue(intVal, InkListItem.Null);\n if (item.exists) {\n let castedValue = new ListValue(item.result, intVal);\n parametersOut.push(castedValue);\n } else\n throw new StoryException(\n \"Could not find List item with the value \" +\n intVal +\n \" in \" +\n list.name\n );\n } else {\n const key = ValueType[val.valueType];\n throw new StoryException(\n \"Cannot mix Lists and \" + key + \" values in this operation\"\n );\n }\n }\n } else {\n for (let inkObjectVal of parametersIn) {\n let val = asOrThrows(inkObjectVal, Value);\n let castedValue = val.Cast(valType);\n parametersOut.push(castedValue);\n }\n }\n\n return parametersOut;\n }\n\n constructor(name: string);\n constructor(name: string, numberOfParameters: number);\n constructor();\n constructor() {\n super();\n\n if (arguments.length === 0) {\n NativeFunctionCall.GenerateNativeFunctionsIfNecessary();\n } else if (arguments.length === 1) {\n let name = arguments[0];\n NativeFunctionCall.GenerateNativeFunctionsIfNecessary();\n this.name = name;\n } else if (arguments.length === 2) {\n let name = arguments[0];\n let numberOfParameters = arguments[1];\n\n this._isPrototype = true;\n this.name = name;\n this.numberOfParameters = numberOfParameters;\n }\n }\n\n public static Identity(t: T): any {\n return t;\n }\n\n public static GenerateNativeFunctionsIfNecessary() {\n if (this._nativeFunctions == null) {\n this._nativeFunctions = new Map();\n\n // Int operations\n this.AddIntBinaryOp(this.Add, (x, y) => x + y);\n this.AddIntBinaryOp(this.Subtract, (x, y) => x - y);\n this.AddIntBinaryOp(this.Multiply, (x, y) => x * y);\n this.AddIntBinaryOp(this.Divide, (x, y) => Math.floor(x / y));\n this.AddIntBinaryOp(this.Mod, (x, y) => x % y);\n this.AddIntUnaryOp(this.Negate, (x) => -x);\n\n this.AddIntBinaryOp(this.Equal, (x, y) => x == y);\n this.AddIntBinaryOp(this.Greater, (x, y) => x > y);\n this.AddIntBinaryOp(this.Less, (x, y) => x < y);\n this.AddIntBinaryOp(this.GreaterThanOrEquals, (x, y) => x >= y);\n this.AddIntBinaryOp(this.LessThanOrEquals, (x, y) => x <= y);\n this.AddIntBinaryOp(this.NotEquals, (x, y) => x != y);\n this.AddIntUnaryOp(this.Not, (x) => x == 0);\n\n this.AddIntBinaryOp(this.And, (x, y) => x != 0 && y != 0);\n this.AddIntBinaryOp(this.Or, (x, y) => x != 0 || y != 0);\n\n this.AddIntBinaryOp(this.Max, (x, y) => Math.max(x, y));\n this.AddIntBinaryOp(this.Min, (x, y) => Math.min(x, y));\n\n this.AddIntBinaryOp(this.Pow, (x, y) => Math.pow(x, y));\n this.AddIntUnaryOp(this.Floor, NativeFunctionCall.Identity);\n this.AddIntUnaryOp(this.Ceiling, NativeFunctionCall.Identity);\n this.AddIntUnaryOp(this.Int, NativeFunctionCall.Identity);\n this.AddIntUnaryOp(this.Float, (x) => x);\n\n // Float operations\n this.AddFloatBinaryOp(this.Add, (x, y) => x + y);\n this.AddFloatBinaryOp(this.Subtract, (x, y) => x - y);\n this.AddFloatBinaryOp(this.Multiply, (x, y) => x * y);\n this.AddFloatBinaryOp(this.Divide, (x, y) => x / y);\n this.AddFloatBinaryOp(this.Mod, (x, y) => x % y);\n this.AddFloatUnaryOp(this.Negate, (x) => -x);\n\n this.AddFloatBinaryOp(this.Equal, (x, y) => x == y);\n this.AddFloatBinaryOp(this.Greater, (x, y) => x > y);\n this.AddFloatBinaryOp(this.Less, (x, y) => x < y);\n this.AddFloatBinaryOp(this.GreaterThanOrEquals, (x, y) => x >= y);\n this.AddFloatBinaryOp(this.LessThanOrEquals, (x, y) => x <= y);\n this.AddFloatBinaryOp(this.NotEquals, (x, y) => x != y);\n this.AddFloatUnaryOp(this.Not, (x) => x == 0.0);\n\n this.AddFloatBinaryOp(this.And, (x, y) => x != 0.0 && y != 0.0);\n this.AddFloatBinaryOp(this.Or, (x, y) => x != 0.0 || y != 0.0);\n\n this.AddFloatBinaryOp(this.Max, (x, y) => Math.max(x, y));\n this.AddFloatBinaryOp(this.Min, (x, y) => Math.min(x, y));\n\n this.AddFloatBinaryOp(this.Pow, (x, y) => Math.pow(x, y));\n this.AddFloatUnaryOp(this.Floor, (x) => Math.floor(x));\n this.AddFloatUnaryOp(this.Ceiling, (x) => Math.ceil(x));\n this.AddFloatUnaryOp(this.Int, (x) => Math.floor(x));\n this.AddFloatUnaryOp(this.Float, NativeFunctionCall.Identity);\n\n // String operations\n this.AddStringBinaryOp(this.Add, (x, y) => x + y); // concat\n this.AddStringBinaryOp(this.Equal, (x, y) => x === y);\n this.AddStringBinaryOp(this.NotEquals, (x, y) => !(x === y));\n this.AddStringBinaryOp(this.Has, (x, y) => x.includes(y));\n this.AddStringBinaryOp(this.Hasnt, (x, y) => !x.includes(y));\n\n this.AddListBinaryOp(this.Add, (x, y) => x.Union(y));\n this.AddListBinaryOp(this.Subtract, (x, y) => x.Without(y));\n this.AddListBinaryOp(this.Has, (x, y) => x.Contains(y));\n this.AddListBinaryOp(this.Hasnt, (x, y) => !x.Contains(y));\n this.AddListBinaryOp(this.Intersect, (x, y) => x.Intersect(y));\n\n this.AddListBinaryOp(this.Equal, (x, y) => x.Equals(y));\n this.AddListBinaryOp(this.Greater, (x, y) => x.GreaterThan(y));\n this.AddListBinaryOp(this.Less, (x, y) => x.LessThan(y));\n this.AddListBinaryOp(this.GreaterThanOrEquals, (x, y) =>\n x.GreaterThanOrEquals(y)\n );\n this.AddListBinaryOp(this.LessThanOrEquals, (x, y) =>\n x.LessThanOrEquals(y)\n );\n this.AddListBinaryOp(this.NotEquals, (x, y) => !x.Equals(y));\n\n this.AddListBinaryOp(this.And, (x, y) => x.Count > 0 && y.Count > 0);\n this.AddListBinaryOp(this.Or, (x, y) => x.Count > 0 || y.Count > 0);\n\n this.AddListUnaryOp(this.Not, (x) => (x.Count == 0 ? 1 : 0));\n\n this.AddListUnaryOp(this.Invert, (x) => x.inverse);\n this.AddListUnaryOp(this.All, (x) => x.all);\n this.AddListUnaryOp(this.ListMin, (x) => x.MinAsList());\n this.AddListUnaryOp(this.ListMax, (x) => x.MaxAsList());\n this.AddListUnaryOp(this.Count, (x) => x.Count);\n this.AddListUnaryOp(this.ValueOfList, (x) => x.maxItem.Value);\n\n let divertTargetsEqual = (d1: Path, d2: Path) => d1.Equals(d2);\n let divertTargetsNotEqual = (d1: Path, d2: Path) => !d1.Equals(d2);\n this.AddOpToNativeFunc(\n this.Equal,\n 2,\n ValueType.DivertTarget,\n divertTargetsEqual\n );\n this.AddOpToNativeFunc(\n this.NotEquals,\n 2,\n ValueType.DivertTarget,\n divertTargetsNotEqual\n );\n }\n }\n\n public AddOpFuncForType(\n valType: ValueType,\n op: UnaryOp | BinaryOp\n ): void {\n if (this._operationFuncs == null) {\n this._operationFuncs = new Map();\n }\n\n this._operationFuncs.set(valType, op);\n }\n\n public static AddOpToNativeFunc(\n name: string,\n args: number,\n valType: ValueType,\n op: UnaryOp | BinaryOp\n ): void {\n if (this._nativeFunctions === null)\n return throwNullException(\"NativeFunctionCall._nativeFunctions\");\n let nativeFunc = this._nativeFunctions.get(name);\n if (!nativeFunc) {\n nativeFunc = new NativeFunctionCall(name, args);\n this._nativeFunctions.set(name, nativeFunc);\n }\n\n nativeFunc.AddOpFuncForType(valType, op);\n }\n\n public static AddIntBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.Int, op);\n }\n public static AddIntUnaryOp(name: string, op: UnaryOp) {\n this.AddOpToNativeFunc(name, 1, ValueType.Int, op);\n }\n\n public static AddFloatBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.Float, op);\n }\n public static AddFloatUnaryOp(name: string, op: UnaryOp) {\n this.AddOpToNativeFunc(name, 1, ValueType.Float, op);\n }\n\n public static AddStringBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.String, op);\n }\n\n public static AddListBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.List, op);\n }\n public static AddListUnaryOp(name: string, op: UnaryOp) {\n this.AddOpToNativeFunc(name, 1, ValueType.List, op);\n }\n\n public toString() {\n return 'Native \"' + this.name + '\"';\n }\n\n public _prototype: NativeFunctionCall | null = null;\n public _isPrototype: boolean = false;\n public _operationFuncs: Map | UnaryOp> | null =\n null;\n public static _nativeFunctions: Map | null = null;\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"./Expression\";\nimport { BoolValue, FloatValue, IntValue } from \"../../../../engine/Value\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\nimport { ParsedObject } from \"../Object\";\n\n// This class is named Number in the C# codebase\n// but this conflict with the built-in Number class\nexport class NumberExpression extends Expression {\n public value: number | boolean;\n public subtype: \"int\" | \"float\" | \"bool\";\n\n constructor(value: number | boolean, subtype: \"int\" | \"float\" | \"bool\") {\n super();\n\n if (\n (typeof value === \"number\" && !Number.isNaN(value)) ||\n typeof value == \"boolean\"\n ) {\n this.value = value;\n this.subtype = subtype;\n } else {\n throw new Error(\"Unexpected object type in NumberExpression.\");\n }\n }\n\n get typeName(): string {\n return \"Number\";\n }\n\n public isInt = (): boolean => this.subtype == \"int\";\n\n public isFloat = (): boolean => this.subtype == \"float\";\n\n public isBool = (): boolean => this.subtype == \"bool\";\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n if (this.isInt()) {\n container.AddContent(new IntValue(this.value as number));\n } else if (this.isFloat()) {\n container.AddContent(new FloatValue(this.value as number));\n } else if (this.isBool()) {\n container.AddContent(new BoolValue(this.value as boolean));\n }\n };\n\n public readonly toString = (): string => String(this.value);\n\n public Equals(obj: ParsedObject): boolean {\n const numberExpression = asOrNull(obj, NumberExpression);\n if (!numberExpression) return false;\n\n return (\n numberExpression.subtype == this.subtype &&\n numberExpression.value == this.value\n );\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"./Expression\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\nimport { NumberExpression } from \"./NumberExpression\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class UnaryExpression extends Expression {\n get nativeNameForOp(): string {\n // Replace \"-\" with \"_\" to make it unique (compared to subtraction)\n if (this.op === \"-\") {\n return \"_\";\n } else if (this.op === \"not\") {\n return \"!\";\n }\n\n return this.op;\n }\n\n public innerExpression: Expression;\n\n // Attempt to flatten inner expression immediately\n // e.g. convert (-(5)) into (-5)\n public static readonly WithInner = (\n inner: Expression,\n op: string\n ): Expression => {\n const innerNumber = asOrNull(inner, NumberExpression);\n\n if (innerNumber) {\n if (op === \"-\") {\n if (innerNumber.isInt()) {\n return new NumberExpression(-innerNumber.value, \"int\");\n } else if (innerNumber.isFloat()) {\n return new NumberExpression(-innerNumber.value, \"float\");\n }\n } else if (op == \"!\" || op == \"not\") {\n if (innerNumber.isInt()) {\n return new NumberExpression(innerNumber.value == 0, \"bool\");\n } else if (innerNumber.isFloat()) {\n return new NumberExpression(innerNumber.value == 0.0, \"bool\");\n } else if (innerNumber.isBool()) {\n return new NumberExpression(!innerNumber.value, \"bool\");\n }\n }\n\n throw new Error(\"Unexpected operation or number type\");\n }\n\n // Normal fallback\n const unary = new UnaryExpression(inner, op);\n\n return unary;\n };\n\n constructor(inner: Expression, public readonly op: string) {\n super();\n\n this.innerExpression = this.AddContent(inner) as Expression;\n }\n\n get typeName(): string {\n return \"UnaryExpression\";\n }\n\n public readonly GenerateIntoContainer = (container: RuntimeContainer) => {\n this.innerExpression.GenerateIntoContainer(container);\n container.AddContent(NativeFunctionCall.CallWithName(this.nativeNameForOp));\n };\n\n public readonly toString = (): string =>\n this.nativeNameForOp + this.innerExpression;\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"./Expression\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\nimport { Story } from \"../Story\";\nimport { UnaryExpression } from \"./UnaryExpression\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class BinaryExpression extends Expression {\n public readonly leftExpression: Expression;\n public readonly rightExpression: Expression;\n\n constructor(left: Expression, right: Expression, public opName: string) {\n super();\n\n this.leftExpression = this.AddContent(left) as Expression;\n this.rightExpression = this.AddContent(right) as Expression;\n\n this.opName = opName;\n }\n\n get typeName(): string {\n return \"BinaryExpression\";\n }\n\n public readonly GenerateIntoContainer = (container: RuntimeContainer) => {\n this.leftExpression.GenerateIntoContainer(container);\n this.rightExpression.GenerateIntoContainer(container);\n this.opName = this.NativeNameForOp(this.opName);\n container.AddContent(NativeFunctionCall.CallWithName(this.opName));\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n // Check for the following case:\n //\n // (not A) ? B\n //\n // Since this easy to accidentally do:\n //\n // not A ? B\n //\n // when you intend:\n //\n // not (A ? B)\n if (this.NativeNameForOp(this.opName) === \"?\") {\n const leftUnary = asOrNull(this.leftExpression, UnaryExpression);\n if (\n leftUnary !== null &&\n (leftUnary.op === \"not\" || leftUnary.op === \"!\")\n ) {\n this.Error(\n `Using 'not' or '!' here negates '${leftUnary.innerExpression}' rather than the result of the '?' or 'has' operator. You need to add parentheses around the (A ? B) expression.`\n );\n }\n }\n }\n\n public readonly NativeNameForOp = (opName: string): string => {\n if (opName === \"and\") {\n return \"&&\";\n } else if (opName === \"or\") {\n return \"||\";\n } else if (opName === \"mod\") {\n return \"%\";\n } else if (opName === \"has\") {\n return \"?\";\n } else if (opName === \"hasnt\") {\n return \"!?\";\n }\n\n return opName;\n };\n\n public readonly toString = (): string =>\n `(${this.leftExpression} ${this.opName} ${this.rightExpression})`;\n}\n","export class CharacterSet {\n public static readonly FromRange = (\n start: string,\n end: string\n ): CharacterSet => new CharacterSet().AddRange(start, end);\n\n public set: Set = new Set();\n\n constructor(arg?: string | string[] | CharacterSet) {\n if (arg) {\n this.AddCharacters(arg);\n }\n }\n\n public readonly Add = (arg: string) => this.set.add(arg);\n\n public readonly AddRange = (start: string, end: string): CharacterSet => {\n for (let c = start.charCodeAt(0); c <= end.charCodeAt(0); ++c) {\n this.Add(String.fromCharCode(c));\n }\n\n return this;\n };\n\n public readonly AddCharacters = (\n chars: string | string[] | CharacterSet\n ): CharacterSet => {\n if (typeof chars === \"string\" || Array.isArray(chars)) {\n for (const c of chars) {\n this.Add(c);\n }\n } else {\n for (const c of chars.set) {\n this.Add(c);\n }\n }\n\n return this;\n };\n}\n","import { CharacterSet } from \"./CharacterSet\";\n\n/// \n/// A class representing a character range. Allows for lazy-loading a corresponding character set.\n/// \nexport class CharacterRange {\n public static Define = (\n start: string,\n end: string,\n excludes: string[] | CharacterSet = []\n ): CharacterRange => new CharacterRange(start, end, excludes);\n\n private _correspondingCharSet: CharacterSet = new CharacterSet();\n private _excludes = new Set();\n\n constructor(\n private _start: string,\n private _end: string,\n excludes: string[] | CharacterSet = []\n ) {\n if (excludes instanceof CharacterSet) {\n this._excludes = excludes.set;\n } else {\n for (const item of excludes) {\n this._excludes.add(item);\n }\n }\n }\n\n get start(): string {\n return this._start;\n }\n\n get end(): string {\n return this._end;\n }\n\n /// \n /// Returns a character set instance corresponding to the character range\n /// represented by the current instance.\n /// \n /// \n /// The internal character set is created once and cached in memory.\n /// \n /// The char set.\n public readonly ToCharacterSet = (): CharacterSet => {\n if (this._correspondingCharSet.set.size === 0) {\n for (\n let ii = this.start.charCodeAt(0), c = String.fromCharCode(ii);\n ii <= this.end.charCodeAt(0);\n ii += 1\n ) {\n if (!this._excludes.has(c)) {\n this._correspondingCharSet.AddCharacters(c);\n }\n }\n }\n\n return this._correspondingCharSet;\n };\n}\n","import { InkObject } from \"./Object\";\nimport { Path } from \"./Path\";\nimport { Container } from \"./Container\";\nimport { throwNullException } from \"./NullException\";\n\nexport class ChoicePoint extends InkObject {\n public _pathOnChoice: Path | null = null;\n public hasCondition: boolean = false;\n public hasStartContent: boolean = false;\n public hasChoiceOnlyContent: boolean = false;\n public isInvisibleDefault: boolean = false;\n public onceOnly: boolean = true;\n\n constructor(onceOnly: boolean = true) {\n super();\n this.onceOnly = onceOnly;\n }\n get pathOnChoice(): Path | null {\n if (this._pathOnChoice != null && this._pathOnChoice.isRelative) {\n let choiceTargetObj = this.choiceTarget;\n if (choiceTargetObj) {\n this._pathOnChoice = choiceTargetObj.path;\n }\n }\n return this._pathOnChoice;\n }\n set pathOnChoice(value: Path | null) {\n this._pathOnChoice = value;\n }\n get choiceTarget(): Container | null {\n if (this._pathOnChoice === null)\n return throwNullException(\"ChoicePoint._pathOnChoice\");\n return this.ResolvePath(this._pathOnChoice).container;\n }\n get pathStringOnChoice(): string {\n if (this.pathOnChoice === null)\n return throwNullException(\"ChoicePoint.pathOnChoice\");\n return this.CompactPathString(this.pathOnChoice);\n }\n set pathStringOnChoice(value: string) {\n this.pathOnChoice = new Path(value);\n }\n get flags(): number {\n let flags = 0;\n if (this.hasCondition) flags |= 1;\n if (this.hasStartContent) flags |= 2;\n if (this.hasChoiceOnlyContent) flags |= 4;\n if (this.isInvisibleDefault) flags |= 8;\n if (this.onceOnly) flags |= 16;\n return flags;\n }\n set flags(value: number) {\n this.hasCondition = (value & 1) > 0;\n this.hasStartContent = (value & 2) > 0;\n this.hasChoiceOnlyContent = (value & 4) > 0;\n this.isInvisibleDefault = (value & 8) > 0;\n this.onceOnly = (value & 16) > 0;\n }\n public toString(): string {\n if (this.pathOnChoice === null)\n return throwNullException(\"ChoicePoint.pathOnChoice\");\n // int? targetLineNum = DebugLineNumberOfPath (pathOnChoice);\n let targetLineNum = null;\n let targetString = this.pathOnChoice.toString();\n\n if (targetLineNum != null) {\n targetString = \" line \" + targetLineNum + \"(\" + targetString + \")\";\n }\n\n return \"Choice: -> \" + targetString;\n }\n}\n","export enum PushPopType {\n Tunnel = 0,\n Function = 1,\n FunctionEvaluationFromGame = 2,\n}\n","import { Path } from \"./Path\";\nimport { Container } from \"./Container\";\nimport { InkObject } from \"./Object\";\n\nexport class Pointer {\n public container: Container | null = null;\n public index: number = -1;\n\n constructor();\n constructor(container: Container | null, index: number);\n constructor() {\n if (arguments.length === 2) {\n this.container = arguments[0];\n this.index = arguments[1];\n }\n }\n\n public Resolve(): InkObject | null {\n if (this.index < 0) return this.container;\n if (this.container == null) return null;\n if (this.container.content.length == 0) return this.container;\n if (this.index >= this.container.content.length) return null;\n\n return this.container.content[this.index];\n }\n\n get isNull(): boolean {\n return this.container == null;\n }\n\n get path(): Path | null {\n if (this.isNull) return null;\n\n if (this.index >= 0)\n return this.container!.path.PathByAppendingComponent(\n new Path.Component(this.index)\n );\n else return this.container!.path;\n }\n\n public toString(): string {\n if (!this.container) return \"Ink Pointer (null)\";\n\n return (\n \"Ink Pointer -> \" +\n this.container.path.toString() +\n \" -- index \" +\n this.index\n );\n }\n\n // This method does not exist in the original C# code, but is here to maintain the\n // value semantics of Pointer.\n public copy(): Pointer {\n return new Pointer(this.container, this.index);\n }\n\n public static StartOf(container: Container | null): Pointer {\n return new Pointer(container, 0);\n }\n\n public static get Null(): Pointer {\n return new Pointer(null, -1);\n }\n}\n","export enum SymbolType {\n Knot = 0,\n List = 1,\n ListItem = 2,\n Var = 3,\n SubFlowAndWeave = 4,\n Arg = 5,\n Temp = 6,\n}\n","import { Path } from \"./Path\";\nimport { PushPopType } from \"./PushPop\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { InkObject } from \"./Object\";\nimport { Pointer } from \"./Pointer\";\nimport { Container } from \"./Container\";\nimport { throwNullException } from \"./NullException\";\n\nexport class Divert extends InkObject {\n get targetPath() {\n if (this._targetPath != null && this._targetPath.isRelative) {\n let targetObj = this.targetPointer.Resolve();\n if (targetObj) {\n this._targetPath = targetObj.path;\n }\n }\n\n return this._targetPath;\n }\n set targetPath(value: Path | null) {\n this._targetPath = value;\n this._targetPointer = Pointer.Null;\n }\n\n public _targetPath: Path | null = null;\n\n get targetPointer() {\n if (this._targetPointer.isNull) {\n let targetObj = this.ResolvePath(this._targetPath).obj;\n\n if (this._targetPath === null)\n return throwNullException(\"this._targetPath\");\n if (this._targetPath.lastComponent === null)\n return throwNullException(\"this._targetPath.lastComponent\");\n\n if (this._targetPath.lastComponent.isIndex) {\n if (targetObj === null) return throwNullException(\"targetObj\");\n this._targetPointer.container =\n targetObj.parent instanceof Container ? targetObj.parent : null;\n this._targetPointer.index = this._targetPath.lastComponent.index;\n } else {\n this._targetPointer = Pointer.StartOf(\n targetObj instanceof Container ? targetObj : null\n );\n }\n }\n\n return this._targetPointer.copy();\n }\n\n public _targetPointer: Pointer = Pointer.Null;\n\n get targetPathString() {\n if (this.targetPath == null) return null;\n\n return this.CompactPathString(this.targetPath);\n }\n set targetPathString(value: string | null) {\n if (value == null) {\n this.targetPath = null;\n } else {\n this.targetPath = new Path(value);\n }\n }\n\n public variableDivertName: string | null = null;\n get hasVariableTarget() {\n return this.variableDivertName != null;\n }\n\n public pushesToStack: boolean = false;\n public stackPushType: PushPopType = 0;\n\n public isExternal: boolean = false;\n public externalArgs: number = 0;\n\n public isConditional: boolean = false;\n\n constructor(stackPushType?: PushPopType) {\n super();\n this.pushesToStack = false;\n\n if (typeof stackPushType !== \"undefined\") {\n this.pushesToStack = true;\n this.stackPushType = stackPushType;\n }\n }\n\n public Equals(obj: Divert | null) {\n let otherDivert = obj;\n if (otherDivert instanceof Divert) {\n if (this.hasVariableTarget == otherDivert.hasVariableTarget) {\n if (this.hasVariableTarget) {\n return this.variableDivertName == otherDivert.variableDivertName;\n } else {\n if (this.targetPath === null)\n return throwNullException(\"this.targetPath\");\n return this.targetPath.Equals(otherDivert.targetPath);\n }\n }\n }\n return false;\n }\n\n public toString() {\n if (this.hasVariableTarget) {\n return \"Divert(variable: \" + this.variableDivertName + \")\";\n } else if (this.targetPath == null) {\n return \"Divert(null)\";\n } else {\n let sb = new StringBuilder();\n\n let targetStr = this.targetPath.toString();\n // int? targetLineNum = DebugLineNumberOfPath (targetPath);\n let targetLineNum = null;\n if (targetLineNum != null) {\n targetStr = \"line \" + targetLineNum;\n }\n\n sb.Append(\"Divert\");\n\n if (this.isConditional) sb.Append(\"?\");\n\n if (this.pushesToStack) {\n if (this.stackPushType == PushPopType.Function) {\n sb.Append(\" function\");\n } else {\n sb.Append(\" tunnel\");\n }\n }\n\n sb.Append(\" -> \");\n sb.Append(this.targetPathString);\n\n sb.Append(\" (\");\n sb.Append(targetStr);\n sb.Append(\")\");\n\n return sb.toString();\n }\n }\n}\n","import { InkObject } from \"./Object\";\n\nexport class VariableAssignment extends InkObject {\n public readonly variableName: string | null;\n public readonly isNewDeclaration: boolean;\n public isGlobal: boolean;\n\n constructor(variableName: string | null, isNewDeclaration: boolean) {\n super();\n this.variableName = variableName || null;\n this.isNewDeclaration = !!isNewDeclaration;\n this.isGlobal = false;\n }\n\n public toString(): string {\n return \"VarAssign to \" + this.variableName;\n }\n}\n","import { ChoicePoint } from \"../../../engine/ChoicePoint\";\nimport { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ContentList } from \"./ContentList\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../engine/ControlCommand\";\nimport { Divert as RuntimeDivert } from \"../../../engine/Divert\";\nimport { DivertTargetValue } from \"../../../engine/Value\";\nimport { INamedContent } from \"../../../engine/INamedContent\";\nimport { IWeavePoint } from \"./IWeavePoint\";\nimport { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Path as RuntimePath } from \"../../../engine/Path\";\nimport { Story } from \"./Story\";\nimport { SymbolType } from \"./SymbolType\";\nimport { VariableAssignment as RuntimeVariableAssignment } from \"../../../engine/VariableAssignment\";\nimport { Expression } from \"./Expression/Expression\";\nimport { Identifier } from \"./Identifier\";\n\nexport class Choice extends ParsedObject implements IWeavePoint, INamedContent {\n private _condition: Expression | null = null;\n private _innerContentContainer: RuntimeContainer | null = null;\n private _outerContainer: RuntimeContainer | null = null;\n private _runtimeChoice: ChoicePoint | null = null;\n get runtimeChoice(): ChoicePoint {\n if (!this._runtimeChoice) {\n throw new Error();\n }\n\n return this._runtimeChoice;\n }\n\n private _returnToR1: DivertTargetValue | null = null;\n private _returnToR2: DivertTargetValue | null = null;\n private _r1Label: RuntimeContainer | null = null;\n private _r2Label: RuntimeContainer | null = null;\n private _divertToStartContentOuter: RuntimeDivert | null = null;\n private _divertToStartContentInner: RuntimeDivert | null = null;\n private _startContentRuntimeContainer: RuntimeContainer | null = null;\n\n public startContent: ContentList;\n public choiceOnlyContent: ContentList;\n public innerContent: ContentList;\n public identifier?: Identifier;\n get name() {\n return this.identifier?.name || null;\n }\n public onceOnly: boolean;\n public isInvisibleDefault: boolean = false;\n public indentationDepth: number;\n public hasWeaveStyleInlineBrackets: boolean = false;\n\n get condition() {\n return this._condition;\n }\n\n set condition(value) {\n this._condition = value;\n if (value) {\n this.AddContent(value as ParsedObject);\n }\n }\n\n // Required for IWeavePoint interface\n // Choice's target container. Used by weave to append any extra\n // nested weave content into.\n get runtimeContainer() {\n return this._innerContentContainer;\n }\n\n get innerContentContainer() {\n return this._innerContentContainer;\n }\n\n get containerForCounting() {\n return this._innerContentContainer;\n }\n\n // Override runtimePath to point to the Choice's target content (after it's chosen),\n // as opposed to the default implementation which would point to the choice itself\n // (or it's outer container), which is what runtimeObject is.\n get runtimePath(): RuntimePath {\n if (!this.innerContentContainer || !this.innerContentContainer.path) {\n throw new Error();\n }\n\n return this.innerContentContainer.path;\n }\n\n constructor(\n startContent: ContentList,\n choiceOnlyContent: ContentList,\n innerContent: ContentList\n ) {\n super();\n\n this.startContent = startContent;\n this.choiceOnlyContent = choiceOnlyContent;\n this.innerContent = innerContent;\n this.indentationDepth = 1;\n\n if (startContent) {\n this.AddContent(this.startContent);\n }\n\n if (choiceOnlyContent) {\n this.AddContent(this.choiceOnlyContent);\n }\n\n if (innerContent) {\n this.AddContent(this.innerContent);\n }\n\n this.onceOnly = true; // default\n }\n\n get typeName(): string {\n return \"Choice\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n this._outerContainer = new RuntimeContainer();\n\n // Content names for different types of choice:\n // * start content [choice only content] inner content\n // * start content -> divert\n // * start content\n // * [choice only content]\n\n // Hmm, this structure has become slightly insane!\n //\n // [\n // EvalStart\n // assign $r = $r1 -- return target = return label 1\n // BeginString\n // -> s\n // [(r1)] -- return label 1 (after start content)\n // EndString\n // BeginString\n // ... choice only content\n // EndEval\n // Condition expression\n // choice: -> \"c-0\"\n // (s) = [\n // start content\n // -> r -- goto return label 1 or 2\n // ]\n // ]\n //\n // in parent's container: (the inner content for the choice)\n //\n // (c-0) = [\n // EvalStart\n // assign $r = $r2 -- return target = return label 2\n // EndEval\n // -> s\n // [(r2)] -- return label 1 (after start content)\n // inner content\n // ]\n //\n\n this._runtimeChoice = new ChoicePoint(this.onceOnly);\n this._runtimeChoice.isInvisibleDefault = this.isInvisibleDefault;\n\n if (this.startContent || this.choiceOnlyContent || this.condition) {\n this._outerContainer.AddContent(RuntimeControlCommand.EvalStart());\n }\n\n // Start content is put into a named container that's referenced both\n // when displaying the choice initially, and when generating the text\n // when the choice is chosen.\n if (this.startContent) {\n // Generate start content and return\n // - We can't use a function since it uses a call stack element, which would\n // put temporary values out of scope. Instead we manually divert around.\n // - $r is a variable divert target contains the return point\n this._returnToR1 = new DivertTargetValue();\n this._outerContainer.AddContent(this._returnToR1);\n\n const varAssign = new RuntimeVariableAssignment(\"$r\", true);\n this._outerContainer.AddContent(varAssign);\n\n // Mark the start of the choice text generation, so that the runtime\n // knows where to rewind to to extract the content from the output stream.\n this._outerContainer.AddContent(RuntimeControlCommand.BeginString());\n\n this._divertToStartContentOuter = new RuntimeDivert();\n this._outerContainer.AddContent(this._divertToStartContentOuter);\n\n // Start content itself in a named container\n this._startContentRuntimeContainer =\n this.startContent.GenerateRuntimeObject() as RuntimeContainer;\n this._startContentRuntimeContainer.name = \"s\";\n\n // Effectively, the \"return\" statement - return to the point specified by $r\n const varDivert = new RuntimeDivert();\n varDivert.variableDivertName = \"$r\";\n this._startContentRuntimeContainer.AddContent(varDivert);\n\n // Add the container\n this._outerContainer.AddToNamedContentOnly(\n this._startContentRuntimeContainer\n );\n\n // This is the label to return to\n this._r1Label = new RuntimeContainer();\n this._r1Label.name = \"$r1\";\n this._outerContainer.AddContent(this._r1Label);\n\n this._outerContainer.AddContent(RuntimeControlCommand.EndString());\n\n this._runtimeChoice.hasStartContent = true;\n }\n\n // Choice only content - mark the start, then generate it directly into the outer container\n if (this.choiceOnlyContent) {\n this._outerContainer.AddContent(RuntimeControlCommand.BeginString());\n\n const choiceOnlyRuntimeContent =\n this.choiceOnlyContent.GenerateRuntimeObject() as RuntimeContainer;\n this._outerContainer.AddContentsOfContainer(choiceOnlyRuntimeContent);\n\n this._outerContainer.AddContent(RuntimeControlCommand.EndString());\n\n this._runtimeChoice.hasChoiceOnlyContent = true;\n }\n\n // Generate any condition for this choice\n if (this.condition) {\n this.condition.GenerateIntoContainer(this._outerContainer);\n this._runtimeChoice.hasCondition = true;\n }\n\n if (this.startContent || this.choiceOnlyContent || this.condition) {\n this._outerContainer.AddContent(RuntimeControlCommand.EvalEnd());\n }\n\n // Add choice itself\n this._outerContainer.AddContent(this._runtimeChoice);\n\n // Container that choice points to for when it's chosen\n this._innerContentContainer = new RuntimeContainer();\n\n // Repeat start content by diverting to its container\n if (this.startContent) {\n // Set the return point when jumping back into the start content\n // - In this case, it's the $r2 point, within the choice content \"c\".\n this._returnToR2 = new DivertTargetValue();\n this._innerContentContainer.AddContent(RuntimeControlCommand.EvalStart());\n this._innerContentContainer.AddContent(this._returnToR2);\n this._innerContentContainer.AddContent(RuntimeControlCommand.EvalEnd());\n const varAssign = new RuntimeVariableAssignment(\"$r\", true);\n this._innerContentContainer.AddContent(varAssign);\n\n // Main divert into start content\n this._divertToStartContentInner = new RuntimeDivert();\n this._innerContentContainer.AddContent(this._divertToStartContentInner);\n\n // Define label to return to\n this._r2Label = new RuntimeContainer();\n this._r2Label.name = \"$r2\";\n this._innerContentContainer.AddContent(this._r2Label);\n }\n\n // Choice's own inner content\n if (this.innerContent) {\n const innerChoiceOnlyContent =\n this.innerContent.GenerateRuntimeObject() as RuntimeContainer;\n this._innerContentContainer.AddContentsOfContainer(\n innerChoiceOnlyContent\n );\n }\n\n if (this.story.countAllVisits) {\n this._innerContentContainer.visitsShouldBeCounted = true;\n }\n\n this._innerContentContainer.countingAtStartOnly = true;\n\n return this._outerContainer;\n };\n\n public ResolveReferences(context: Story): void {\n // Weave style choice - target own content container\n if (this._innerContentContainer) {\n this.runtimeChoice.pathOnChoice = this._innerContentContainer.path;\n\n if (this.onceOnly) {\n this._innerContentContainer.visitsShouldBeCounted = true;\n }\n }\n\n if (this._returnToR1) {\n if (!this._r1Label) {\n throw new Error();\n }\n\n this._returnToR1.targetPath = this._r1Label.path;\n }\n\n if (this._returnToR2) {\n if (!this._r2Label) {\n throw new Error();\n }\n\n this._returnToR2.targetPath = this._r2Label.path;\n }\n\n if (this._divertToStartContentOuter) {\n if (!this._startContentRuntimeContainer) {\n throw new Error();\n }\n\n this._divertToStartContentOuter.targetPath =\n this._startContentRuntimeContainer.path;\n }\n\n if (this._divertToStartContentInner) {\n if (!this._startContentRuntimeContainer) {\n throw new Error();\n }\n\n this._divertToStartContentInner.targetPath =\n this._startContentRuntimeContainer.path;\n }\n\n super.ResolveReferences(context);\n\n if (this.identifier && (this.identifier?.name || \"\").length > 0) {\n context.CheckForNamingCollisions(\n this as ParsedObject,\n this.identifier,\n SymbolType.SubFlowAndWeave\n );\n }\n }\n\n public readonly toString = () => {\n if (this.choiceOnlyContent !== null) {\n return `* ${this.startContent}[${this.choiceOnlyContent}]...`;\n }\n\n return `* ${this.startContent}...`;\n };\n}\n","export class StringParserElement {\n public static _uniqueIdCounter: number = 1000;\n\n public characterIndex: number = 0;\n public characterInLineIndex: number = 0;\n public lineIndex: number = 0;\n public reportedErrorInScope: boolean = false;\n public uniqueId: number = 0;\n public customFlags: number = 0;\n\n public readonly CopyFrom = (fromElement: StringParserElement): void => {\n StringParserElement._uniqueIdCounter++;\n this.uniqueId = StringParserElement._uniqueIdCounter;\n this.characterIndex = fromElement.characterIndex;\n this.characterInLineIndex = fromElement.characterInLineIndex;\n this.lineIndex = fromElement.lineIndex;\n this.customFlags = fromElement.customFlags;\n this.reportedErrorInScope = false;\n };\n\n // Squash is used when succeeding from a rule,\n // so only the state information we wanted to carry forward is\n // retained. e.g. characterIndex and lineIndex are global,\n // however uniqueId is specific to the individual rule,\n // and likewise, custom flags are designed for the temporary\n // state of the individual rule too.\n public readonly SquashFrom = (fromElement: StringParserElement): void => {\n this.characterIndex = fromElement.characterIndex;\n this.characterInLineIndex = fromElement.characterInLineIndex;\n this.lineIndex = fromElement.lineIndex;\n this.reportedErrorInScope = fromElement.reportedErrorInScope;\n this.customFlags = fromElement.customFlags;\n };\n}\n","import { StringParserElement } from \"./StringParserElement\";\n\nexport class StringParserState {\n private _stack: StringParserElement[] = [];\n private _numElements: number = 0;\n\n get currentElement(): StringParserElement {\n return this._stack[this._numElements - 1];\n }\n\n get lineIndex(): number {\n return this.currentElement.lineIndex;\n }\n\n set lineIndex(value: number) {\n this.currentElement.lineIndex = value;\n }\n\n get characterIndex(): number {\n return this.currentElement.characterIndex;\n }\n\n set characterIndex(value: number) {\n this.currentElement.characterIndex = value;\n }\n\n get characterInLineIndex(): number {\n return this.currentElement.characterInLineIndex;\n }\n\n set characterInLineIndex(value: number) {\n this.currentElement.characterInLineIndex = value;\n }\n\n get customFlags(): number {\n return this.currentElement.customFlags;\n }\n\n set customFlags(value: number) {\n this.currentElement.customFlags = value;\n }\n\n get errorReportedAlreadyInScope(): boolean {\n return this.currentElement.reportedErrorInScope;\n }\n\n get stackHeight(): number {\n return this._numElements;\n }\n\n constructor() {\n const kExpectedMaxStackDepth = 200;\n for (let i = 0; i < kExpectedMaxStackDepth; i++) {\n this._stack[i] = new StringParserElement();\n }\n this._numElements = 1;\n }\n\n public readonly StringParserState = (): void => {\n const kExpectedMaxStackDepth: number = 200;\n this._stack = new Array(kExpectedMaxStackDepth);\n\n for (let ii = 0; ii < kExpectedMaxStackDepth; ++ii) {\n this._stack[ii] = new StringParserElement();\n }\n\n this._numElements = 1;\n };\n\n public readonly Push = (): number => {\n if (this._numElements >= this._stack.length && this._numElements > 0) {\n throw new Error(\"Stack overflow in parser state.\");\n }\n\n const prevElement = this._stack[this._numElements - 1];\n const newElement = this._stack[this._numElements];\n this._numElements++;\n\n newElement.CopyFrom(prevElement);\n\n return newElement.uniqueId;\n };\n\n public readonly Pop = (expectedRuleId: number): void => {\n if (this._numElements == 1) {\n throw new Error(\n \"Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?\"\n );\n }\n\n if (this.currentElement.uniqueId != expectedRuleId) {\n throw new Error(\n \"Mismatched rule IDs while Poping - do you have mismatched Begin/Succeed/Fail?\"\n );\n }\n\n // Restore state\n this._numElements -= 1;\n };\n\n public Peek = (expectedRuleId: number) => {\n if (this.currentElement.uniqueId != expectedRuleId) {\n throw new Error(\n \"Mismatched rule IDs while Peeking - do you have mismatched Begin/Succeed/Fail?\"\n );\n }\n\n return this._stack[this._numElements - 1];\n };\n\n public readonly PeekPenultimate = (): StringParserElement | null => {\n if (this._numElements >= 2) {\n return this._stack[this._numElements - 2];\n }\n\n return null;\n };\n\n // Reduce stack height while maintaining currentElement\n // Remove second last element: i.e. \"squash last two elements together\"\n // Used when succeeding from a rule (and ONLY when succeeding, since\n // the state of the top element is retained).\n public readonly Squash = (): void => {\n if (this._numElements < 2) {\n throw new Error(\n \"Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?\"\n );\n }\n\n const penultimateEl = this._stack[this._numElements - 2];\n const lastEl = this._stack[this._numElements - 1];\n\n penultimateEl.SquashFrom(lastEl);\n\n this._numElements -= 1;\n };\n\n public readonly NoteErrorReported = (): void => {\n for (const el of this._stack) {\n el.reportedErrorInScope = true;\n }\n };\n}\n","import { CharacterSet } from \"../CharacterSet\";\nimport { ParsedObject } from \"../ParsedHierarchy/Object\";\nimport { StringParserState } from \"./StringParserState\";\nimport { StringParserElement } from \"./StringParserElement\";\n\nexport const ParseSuccess = Symbol(\"ParseSuccessStruct\");\n\nexport type ParseRule = () => ParseRuleReturn;\n\nexport type ParseRuleReturn =\n | object\n | string\n | null\n | number\n | typeof StringParser[\"ParseSuccess\"];\n\nexport type SpecificParseRule = T;\n\nexport class StringParser {\n public ParseRule: ParseRule | null = null;\n\n public static readonly ParseSuccess: typeof ParseSuccess = ParseSuccess;\n public static readonly numbersCharacterSet = new CharacterSet(\"0123456789\");\n\n private _chars: string[];\n\n public errorHandler:\n | null\n | ((\n message: string,\n index: number,\n lineIndex?: number,\n isWarning?: boolean\n ) => void) = null;\n public state: StringParserState;\n public hadError: boolean = false;\n\n constructor(str: string) {\n const strPreProc = this.PreProcessInputString(str);\n this.state = new StringParserState();\n\n if (str) {\n this._chars = strPreProc.split(\"\");\n } else {\n this._chars = [];\n }\n\n this.inputString = strPreProc;\n }\n\n get currentCharacter(): string {\n if (this.index >= 0 && this.remainingLength > 0) {\n return this._chars[this.index];\n }\n\n return \"0\";\n }\n\n // Don't do anything by default, but provide ability for subclasses\n // to manipulate the string before it's used as input (converted to a char array)\n public PreProcessInputString(str: string): string {\n return str;\n }\n\n //--------------------------------\n // Parse state\n //--------------------------------\n\n public readonly BeginRule = (): number => this.state.Push();\n\n public readonly FailRule = (expectedRuleId: number): ParseRuleReturn => {\n this.state.Pop(expectedRuleId);\n return null;\n };\n\n public readonly CancelRule = (expectedRuleId: number): void => {\n this.state.Pop(expectedRuleId);\n };\n\n public readonly SucceedRule = (\n expectedRuleId: number,\n result: ParseRuleReturn = null\n ): ParseRuleReturn => {\n // Get state at point where this rule stared evaluating\n const stateAtSucceedRule = this.state.Peek(expectedRuleId);\n const stateAtBeginRule = this.state.PeekPenultimate();\n\n // Allow subclass to receive callback\n if (this.RuleDidSucceed) {\n this.RuleDidSucceed(result, stateAtBeginRule, stateAtSucceedRule);\n }\n\n // Flatten state stack so that we maintain the same values,\n // but remove one level in the stack.\n this.state.Squash();\n\n let finalResult: ParseRuleReturn = result;\n if (finalResult === null) {\n finalResult = StringParser.ParseSuccess;\n }\n\n return finalResult;\n };\n\n public RuleDidSucceed?: (\n result: ParseRuleReturn,\n startState: StringParserElement | null,\n endState: StringParserElement\n ) => void;\n\n public readonly Expect = (\n rule: ParseRule,\n message: string | null = null,\n recoveryRule: ParseRule | null = null\n ): ParseRuleReturn => {\n let result: ParseRuleReturn = this.ParseObject(rule);\n if (result === null) {\n if (message === null) {\n message = rule.name;\n }\n\n let butSaw: string;\n const lineRemainder: string = this.LineRemainder();\n if (lineRemainder === null || lineRemainder.length === 0) {\n butSaw = \"end of line\";\n } else {\n butSaw = `'${lineRemainder}'`;\n }\n\n this.Error(`Expected ${message} but saw ${butSaw}`);\n\n if (recoveryRule !== null) {\n result = recoveryRule();\n }\n }\n\n return result;\n };\n\n public Error = (message: string, isWarning: boolean = false): void => {\n this.ErrorOnLine(message, this.lineIndex + 1, isWarning);\n };\n\n public readonly ErrorWithParsedObject = (\n message: string,\n result: ParsedObject,\n isWarning: boolean = false\n ): void => {\n this.ErrorOnLine(\n message,\n result.debugMetadata ? result.debugMetadata.startLineNumber : -1,\n isWarning\n );\n };\n\n public readonly ErrorOnLine = (\n message: string,\n lineNumber: number,\n isWarning: boolean\n ): void => {\n if (!this.state.errorReportedAlreadyInScope) {\n const errorType = isWarning ? \"Warning\" : \"Error\";\n\n if (!this.errorHandler) {\n throw new Error(`${errorType} on line ${lineNumber}: ${message}`);\n } else {\n this.errorHandler(message, this.index, lineNumber - 1, isWarning);\n }\n\n this.state.NoteErrorReported();\n }\n\n if (!isWarning) {\n this.hadError = true;\n }\n };\n\n public readonly Warning = (message: string): void =>\n this.Error(message, true);\n\n get endOfInput(): boolean {\n return this.index >= this._chars.length;\n }\n\n get remainingString(): string {\n return this._chars\n .slice(this.index, this.index + this.remainingLength)\n .join(\"\");\n }\n\n public readonly LineRemainder = (): string =>\n this.Peek(() => this.ParseUntilCharactersFromString(\"\\n\\r\")) as string;\n\n get remainingLength() {\n return this._chars.length - this.index;\n }\n\n public inputString: string;\n\n get lineIndex() {\n return this.state.lineIndex;\n }\n\n set lineIndex(value: number) {\n this.state.lineIndex = value;\n }\n\n set characterInLineIndex(value: number) {\n this.state.characterInLineIndex = value;\n }\n\n get characterInLineIndex() {\n return this.state.characterInLineIndex;\n }\n\n get index(): number {\n // If we want subclass parsers to be able to set the index directly,\n // then we would need to know what the lineIndex of the new\n // index would be - would we have to step through manually\n // counting the newlines to do so?\n return this.state.characterIndex;\n }\n\n set index(value: number) {\n this.state.characterIndex = value;\n }\n\n public readonly SetFlag = (flag: number, trueOrFalse: boolean): void => {\n if (trueOrFalse) {\n this.state.customFlags |= flag;\n } else {\n this.state.customFlags &= ~flag;\n }\n };\n\n public readonly GetFlag = (flag: number): boolean =>\n Boolean(this.state.customFlags & flag);\n\n //--------------------------------\n // Structuring\n //--------------------------------\n\n public ParseObject = (rule: ParseRule): ParseRuleReturn => {\n const ruleId: number = this.BeginRule();\n const stackHeightBefore = this.state.stackHeight;\n const result = rule();\n\n if (stackHeightBefore !== this.state.stackHeight) {\n throw new Error(\"Mismatched Begin/Fail/Succeed rules\");\n }\n\n if (result === null) {\n return this.FailRule(ruleId);\n }\n\n this.SucceedRule(ruleId, result);\n\n return result;\n };\n\n public readonly Parse = (\n rule: SpecificParseRule\n ): ParseRuleReturn => {\n const ruleId: number = this.BeginRule();\n\n const result: ParseRuleReturn = rule();\n if (result === null) {\n this.FailRule(ruleId);\n return null;\n }\n\n this.SucceedRule(ruleId, result);\n\n return result;\n };\n\n public readonly OneOf = (array: ParseRule[]): ParseRuleReturn => {\n for (const rule of array) {\n const result = this.ParseObject(rule);\n if (result !== null) {\n return result;\n }\n }\n\n return null;\n };\n\n public readonly OneOrMore = (rule: ParseRule): ParseRuleReturn[] | null => {\n const results: ParseRuleReturn[] = [];\n let result: ParseRuleReturn = null;\n\n do {\n result = this.ParseObject(rule);\n if (result !== null) {\n results.push(result);\n }\n } while (result !== null);\n\n if (results.length > 0) {\n return results;\n }\n\n return null;\n };\n\n public readonly Optional =\n (rule: ParseRule): ParseRule =>\n () => {\n const result = this.ParseObject(rule);\n if (result === null) return StringParser.ParseSuccess;\n return result;\n };\n\n // Return ParseSuccess instead the real result so that it gets excluded\n // from result arrays (e.g. Interleave)\n public readonly Exclude =\n (rule: ParseRule): ParseRule =>\n () =>\n this.ParseObject(rule) && StringParser.ParseSuccess;\n\n // Combination of both of the above\n public readonly OptionalExclude =\n (rule: ParseRule): ParseRule =>\n () => {\n this.ParseObject(rule);\n return StringParser.ParseSuccess;\n };\n\n // Convenience method for creating more readable ParseString rules that can be combined\n // in other structuring rules (like OneOf etc)\n // e.g. OneOf(String(\"one\"), String(\"two\"))\n public readonly String =\n (str: string): ParseRule =>\n () =>\n this.ParseString(str);\n\n private readonly TryAddResultToList = (\n result: ParseRuleReturn,\n list: T[],\n flatten: boolean = true\n ): void => {\n if (result === StringParser.ParseSuccess) {\n return;\n }\n\n if (flatten && Array.isArray(result)) {\n const resultCollection = result as ParseRuleReturn[];\n if (resultCollection !== null) {\n for (const obj of resultCollection) {\n list.push(obj as any);\n }\n\n return;\n }\n }\n\n list.push(result as any);\n };\n\n public readonly Interleave = (\n ruleA: ParseRule,\n ruleB: ParseRule,\n untilTerminator: ParseRule | null = null,\n flatten: boolean = true\n ): T[] => {\n const ruleId: number = this.BeginRule();\n const results: T[] = [];\n\n // First outer padding\n const firstA = this.ParseObject(ruleA);\n if (firstA === null) {\n return this.FailRule(ruleId) as any;\n } else {\n this.TryAddResultToList(firstA, results, flatten);\n }\n\n let lastMainResult: ParseRuleReturn | null = null;\n let outerResult: ParseRuleReturn | null = null;\n do {\n // \"until\" condition hit?\n if (untilTerminator !== null && this.Peek(untilTerminator) !== null) {\n break;\n }\n\n // Main inner\n lastMainResult = this.ParseObject(ruleB);\n if (lastMainResult === null) {\n break;\n } else {\n this.TryAddResultToList(lastMainResult, results, flatten);\n }\n\n // Outer result (i.e. last A in ABA)\n outerResult = null;\n if (lastMainResult !== null) {\n outerResult = this.ParseObject(ruleA);\n\n if (outerResult === null) {\n break;\n } else {\n this.TryAddResultToList(outerResult, results, flatten);\n }\n }\n\n // Stop if there are no results, or if both are the placeholder \"ParseSuccess\" (i.e. Optional success rather than a true value)\n } while (\n (lastMainResult !== null || outerResult !== null) &&\n !(\n (lastMainResult as any) === StringParser.ParseSuccess &&\n outerResult == StringParser.ParseSuccess\n ) &&\n this.remainingLength > 0\n );\n\n if (results.length === 0) {\n return this.FailRule(ruleId) as T[];\n }\n\n return this.SucceedRule(ruleId, results) as T[];\n };\n\n //--------------------------------\n // Basic string parsing\n //--------------------------------\n\n public readonly ParseString = (str: string): string | null => {\n if (str.length > this.remainingLength) {\n return null;\n }\n\n const ruleId: number = this.BeginRule();\n\n // Optimisation from profiling:\n // Store in temporary local variables\n // since they're properties that would have to access\n // the rule stack every time otherwise.\n let i: number = this.index;\n let cli: number = this.characterInLineIndex;\n let li: number = this.lineIndex;\n\n let success: boolean = true;\n for (let tempIdx = 0; tempIdx < str.length; tempIdx += 1) {\n const c = str[tempIdx];\n\n if (this._chars[i] !== c) {\n success = false;\n break;\n }\n if (c === \"\\n\") {\n li++;\n cli = -1;\n }\n\n i++;\n cli++;\n }\n\n this.index = i;\n this.characterInLineIndex = cli;\n this.lineIndex = li;\n\n if (success) {\n return this.SucceedRule(ruleId, str) as any;\n }\n\n return this.FailRule(ruleId) as any;\n };\n\n public readonly ParseSingleCharacter = (): string => {\n if (this.remainingLength > 0) {\n const c = this._chars[this.index];\n if (c === \"\\n\") {\n this.lineIndex += 1;\n this.characterInLineIndex = -1;\n }\n\n this.index += 1;\n this.characterInLineIndex += 1;\n\n return c;\n }\n\n return \"0\";\n };\n\n public readonly ParseUntilCharactersFromString = (\n str: string,\n maxCount: number = -1\n ): string | null => this.ParseCharactersFromString(str, false, maxCount);\n\n public readonly ParseUntilCharactersFromCharSet = (\n charSet: CharacterSet,\n maxCount: number = -1\n ): string | null => this.ParseCharactersFromCharSet(charSet, false, maxCount);\n\n public readonly ParseCharactersFromString = (\n str: string,\n maxCountOrShouldIncludeStrChars: boolean | number = -1,\n maxCount: number = -1\n ): string | null => {\n const charSet = new CharacterSet(str);\n if (typeof maxCountOrShouldIncludeStrChars === \"number\") {\n return this.ParseCharactersFromCharSet(\n charSet,\n true,\n maxCountOrShouldIncludeStrChars\n );\n }\n\n return this.ParseCharactersFromCharSet(\n charSet,\n maxCountOrShouldIncludeStrChars,\n maxCount\n );\n };\n\n public readonly ParseCharactersFromCharSet = (\n charSet: CharacterSet,\n shouldIncludeChars: boolean = true,\n maxCount: number = -1\n ): string | null => {\n if (maxCount === -1) {\n maxCount = Number.MAX_SAFE_INTEGER;\n }\n\n const startIndex: number = this.index;\n\n // Optimisation from profiling:\n // Store in temporary local variables\n // since they're properties that would have to access\n // the rule stack every time otherwise.\n let ii: number = this.index;\n let cli: number = this.characterInLineIndex;\n let li: number = this.lineIndex;\n let count: number = 0;\n while (\n ii < this._chars.length &&\n charSet.set.has(this._chars[ii]) === shouldIncludeChars &&\n count < maxCount\n ) {\n if (this._chars[ii] === \"\\n\") {\n li += 1;\n cli = -1;\n }\n\n ii += 1;\n cli += 1;\n count += 1;\n }\n\n this.index = ii;\n this.characterInLineIndex = cli;\n this.lineIndex = li;\n\n const lastCharIndex: number = this.index;\n if (lastCharIndex > startIndex) {\n return this._chars.slice(startIndex, this.index).join(\"\");\n }\n\n return null;\n };\n\n public readonly Peek = (rule: ParseRule): ParseRuleReturn => {\n const ruleId: number = this.BeginRule();\n const result: ParseRuleReturn = rule();\n this.CancelRule(ruleId);\n\n return result;\n };\n\n public ParseUntil(\n stopRule: ParseRule,\n pauseCharacters: CharacterSet | null = null,\n endCharacters: CharacterSet | null = null\n ): string {\n const ruleId: number = this.BeginRule();\n const pauseAndEnd: CharacterSet = new CharacterSet();\n if (pauseCharacters !== null) {\n pauseAndEnd.set = new Set([\n ...pauseAndEnd.set.values(),\n ...pauseCharacters.set.values(),\n ]);\n }\n\n if (endCharacters !== null) {\n pauseAndEnd.set = new Set([\n ...pauseAndEnd.set.values(),\n ...endCharacters.set.values(),\n ]);\n }\n\n let parsedString = \"\";\n let ruleResultAtPause: ParseRuleReturn | null = null;\n\n // Keep attempting to parse strings up to the pause (and end) points.\n // - At each of the pause points, attempt to parse according to the rule\n // - When the end point is reached (or EOF), we're done\n do {\n // TODO: Perhaps if no pause or end characters are passed, we should check *every* character for stopRule?\n const partialParsedString: string | null =\n this.ParseUntilCharactersFromCharSet(pauseAndEnd);\n\n if (partialParsedString) {\n parsedString += partialParsedString;\n }\n\n // Attempt to run the parse rule at this pause point\n ruleResultAtPause = this.Peek(stopRule);\n\n // Rule completed - we're done\n if (ruleResultAtPause !== null) {\n break;\n } else {\n if (this.endOfInput) {\n break;\n }\n\n // Reached a pause point, but rule failed. Step past and continue parsing string\n const pauseCharacter: string = this.currentCharacter;\n if (\n pauseCharacters !== null &&\n pauseCharacters.set.has(pauseCharacter)\n ) {\n parsedString += pauseCharacter;\n if (pauseCharacter === \"\\n\") {\n this.lineIndex += 1;\n this.characterInLineIndex = -1;\n }\n\n this.index += 1;\n this.characterInLineIndex += 1;\n\n continue;\n } else {\n break;\n }\n }\n } while (true);\n\n if (parsedString.length > 0) {\n return this.SucceedRule(ruleId, String(parsedString)) as string;\n }\n\n return this.FailRule(ruleId) as string;\n }\n\n // No need to Begin/End rule since we never parse a newline, so keeping oldIndex is good enough\n public readonly ParseInt = (): number | null => {\n const oldIndex: number = this.index;\n const oldCharacterInLineIndex: number = this.characterInLineIndex;\n const negative: boolean = this.ParseString(\"-\") !== null;\n\n // Optional whitespace\n this.ParseCharactersFromString(\" \\t\");\n\n const parsedString = this.ParseCharactersFromCharSet(\n StringParser.numbersCharacterSet\n );\n if (parsedString === null) {\n // Roll back and fail\n this.index = oldIndex;\n this.characterInLineIndex = oldCharacterInLineIndex;\n\n return null;\n }\n\n let parsedInt: number;\n if (!Number.isNaN(Number(parsedString))) {\n parsedInt = Number(parsedString);\n return negative ? -parsedInt : parsedInt;\n }\n\n this.Error(\n \"Failed to read integer value: \" +\n parsedString +\n \". Perhaps it's out of the range of acceptable numbers ink supports? (\" +\n Number.MIN_SAFE_INTEGER +\n \" to \" +\n Number.MAX_SAFE_INTEGER +\n \")\"\n );\n\n return null;\n };\n\n // No need to Begin/End rule since we never parse a newline, so keeping oldIndex is good enough\n public readonly ParseFloat = (): number | null => {\n const oldIndex: number = this.index;\n const oldCharacterInLineIndex: number = this.characterInLineIndex;\n\n const leadingInt: number | null = this.ParseInt();\n if (leadingInt !== null) {\n if (this.ParseString(\".\") !== null) {\n const afterDecimalPointStr = this.ParseCharactersFromCharSet(\n StringParser.numbersCharacterSet\n );\n\n return Number(`${leadingInt}.${afterDecimalPointStr}`);\n }\n }\n\n // Roll back and fail\n this.index = oldIndex;\n this.characterInLineIndex = oldCharacterInLineIndex;\n\n return null;\n };\n\n public readonly ParseNewline = (): string => {\n const ruleId: number = this.BeginRule();\n\n // Optional \\r, definite \\n to support Windows (\\r\\n) and Mac/Unix (\\n)\n // 2nd May 2016: Always collapse \\r\\n to just \\n\n this.ParseString(\"\\r\");\n\n if (this.ParseString(\"\\n\") === null) {\n return this.FailRule(ruleId) as string;\n }\n\n return this.SucceedRule(ruleId, \"\\n\") as string;\n };\n}\n","import { CharacterSet } from \"./CharacterSet\";\nimport { StringParser } from \"./StringParser/StringParser\";\n\n/// \n/// Pre-pass before main ink parser runs. It actually performs two main tasks:\n/// - comment elimination to simplify the parse rules in the main parser\n/// - Conversion of Windows line endings (\\r\\n) to the simpler Unix style (\\n), so\n/// we don't have to worry about them later.\n/// \nexport class CommentEliminator extends StringParser {\n public _commentOrNewlineStartCharacter = new CharacterSet(\"/\\r\\n\");\n public _commentBlockEndCharacter = new CharacterSet(\"*\");\n public _newlineCharacters = new CharacterSet(\"\\n\\r\");\n\n public readonly Process = (): string => {\n // Make both comments and non-comments optional to handle trivial empty file case (or *only* comments)\n const stringList: string[] = this.Interleave(\n this.Optional(this.CommentsAndNewlines),\n this.Optional(this.MainInk)\n );\n\n if (stringList !== null) {\n return stringList.join(\"\");\n } else {\n return \"\";\n }\n };\n\n public readonly MainInk = () =>\n this.ParseUntil(\n this.CommentsAndNewlines,\n this._commentOrNewlineStartCharacter,\n null\n );\n\n public readonly CommentsAndNewlines = () => {\n let newLines: string[] = this.Interleave(\n this.Optional(this.ParseNewline),\n this.Optional(this.ParseSingleComment)\n );\n\n if (newLines !== null) {\n return newLines.join(\"\");\n }\n\n return null;\n };\n\n // Valid comments always return either an empty string or pure newlines,\n // which we want to keep so that line numbers stay the same\n public readonly ParseSingleComment = () =>\n this.OneOf([this.EndOfLineComment, this.BlockComment]);\n\n public readonly EndOfLineComment = () => {\n if (this.ParseString(\"//\") === null) {\n return null;\n }\n\n this.ParseUntilCharactersFromCharSet(this._newlineCharacters);\n\n return \"\";\n };\n\n public readonly BlockComment = () => {\n if (this.ParseString(\"/*\") === null) {\n return null;\n }\n\n const startLineIndex: number = this.lineIndex;\n const commentResult = this.ParseUntil(\n this.String(\"*/\"),\n this._commentBlockEndCharacter,\n null\n );\n\n if (!this.endOfInput) {\n this.ParseString(\"*/\");\n }\n\n // Count the number of lines that were inside the block, and replicate them as newlines\n // so that the line indexing still works from the original source\n if (commentResult != null) {\n return \"\\n\".repeat(this.lineIndex - startLineIndex);\n }\n\n // No comment at all\n return null;\n };\n\n public PreProcessInputString(str: string): string {\n return str;\n }\n}\n","export enum FlowLevel {\n Story, // 0\n Knot, // 1\n Stitch, // 2\n // not actually a FlowBase, but used for diverts\n WeavePoint, // 3\n}\n","import { ConditionalSingleBranch } from \"./ConditionalSingleBranch\";\nimport { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { Expression } from \"../Expression/Expression\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Story } from \"../Story\";\n\nexport class Conditional extends ParsedObject {\n private _reJoinTarget: RuntimeControlCommand | null = null;\n\n constructor(\n public initialCondition: Expression,\n public branches: ConditionalSingleBranch[]\n ) {\n super();\n\n if (this.initialCondition) {\n this.AddContent(this.initialCondition);\n }\n\n if (this.branches !== null) {\n this.AddContent(this.branches);\n }\n }\n\n get typeName(): string {\n return \"Conditional\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n\n // Initial condition\n if (this.initialCondition) {\n container.AddContent(this.initialCondition.runtimeObject);\n }\n\n // Individual branches\n for (const branch of this.branches) {\n const branchContainer = branch.runtimeObject;\n container.AddContent(branchContainer);\n }\n\n // If it's a switch-like conditional, each branch\n // will have a \"duplicate\" operation for the original\n // switched value. If there's no final else clause\n // and we fall all the way through, we need to clean up.\n // (An else clause doesn't dup but it *does* pop)\n if (\n this.initialCondition !== null &&\n this.branches[0].ownExpression !== null &&\n !this.branches[this.branches.length - 1].isElse\n ) {\n container.AddContent(RuntimeControlCommand.PopEvaluatedValue());\n }\n\n // Target for branches to rejoin to\n this._reJoinTarget = RuntimeControlCommand.NoOp();\n container.AddContent(this._reJoinTarget);\n\n return container;\n };\n\n public ResolveReferences(context: Story): void {\n const pathToReJoin = this._reJoinTarget!.path;\n\n for (const branch of this.branches) {\n if (!branch.returnDivert) {\n throw new Error();\n }\n\n branch.returnDivert.targetPath = pathToReJoin;\n }\n\n super.ResolveReferences(context);\n }\n}\n","import { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { StringValue } from \"../../../engine/Value\";\n\nexport class Text extends ParsedObject {\n constructor(public text: string) {\n super();\n }\n get typeName(): string {\n return \"Text\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject =>\n new StringValue(this.text);\n\n public readonly toString = (): string => this.text;\n}\n","import { Expression } from \"../Expression/Expression\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Story } from \"../Story\";\nimport { SymbolType } from \"../SymbolType\";\nimport { Identifier } from \"../Identifier\";\n\nexport class ConstantDeclaration extends ParsedObject {\n get constantName(): string | undefined {\n return this.constantIdentifier?.name;\n }\n public constantIdentifier: Identifier;\n\n private _expression: Expression | null = null;\n\n get expression(): Expression {\n if (!this._expression) {\n throw new Error();\n }\n\n return this._expression;\n }\n\n constructor(name: Identifier, assignedExpression: Expression) {\n super();\n\n this.constantIdentifier = name;\n\n // Defensive programming in case parsing of assignedExpression failed\n if (assignedExpression) {\n this._expression = this.AddContent(assignedExpression) as Expression;\n }\n }\n\n get typeName(): string {\n return \"CONST\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject | null => {\n // Global declarations don't generate actual procedural\n // runtime objects, but instead add a global variable to the story itself.\n // The story then initialises them all in one go at the start of the game.\n return null;\n };\n\n public ResolveReferences(context: Story) {\n super.ResolveReferences(context);\n context.CheckForNamingCollisions(\n this,\n this.constantIdentifier,\n SymbolType.Var\n );\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { INamedContent } from \"../../../../engine/INamedContent\";\nimport { IWeavePoint } from \"../IWeavePoint\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Story } from \"../Story\";\nimport { SymbolType } from \"../SymbolType\";\nimport { Identifier } from \"../Identifier\";\n\nexport class Gather extends ParsedObject implements INamedContent, IWeavePoint {\n get name(): string | null {\n return this.identifier?.name || null;\n }\n public identifier?: Identifier;\n\n get runtimeContainer(): RuntimeContainer {\n return this.runtimeObject as RuntimeContainer;\n }\n\n constructor(\n identifier: Identifier | null,\n public readonly indentationDepth: number\n ) {\n super();\n\n if (identifier) this.identifier = identifier;\n }\n\n get typeName(): string {\n return \"Gather\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n container.name = this.name;\n\n if (this.story.countAllVisits) {\n container.visitsShouldBeCounted = true;\n }\n\n container.countingAtStartOnly = true;\n\n // A gather can have null content, e.g. it's just purely a line with \"-\"\n if (this.content) {\n for (const c of this.content) {\n container.AddContent(c.runtimeObject);\n }\n }\n\n return container;\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n if (this.identifier && (this.identifier.name || \"\").length > 0) {\n context.CheckForNamingCollisions(\n this,\n this.identifier,\n SymbolType.SubFlowAndWeave\n );\n }\n }\n\n public readonly toString = (): string =>\n `- ${this.identifier?.name ? \"(\" + this.identifier?.name + \")\" : \"gather\"}`;\n}\n","import { asOrNull, filterUndef } from \"../../../engine/TypeAssertion\";\nimport { FlowBase } from \"./Flow/FlowBase\";\nimport { FlowLevel } from \"./Flow/FlowLevel\";\nimport { Identifier } from \"./Identifier\";\nimport { ParsedObject } from \"./Object\";\nimport { Weave } from \"./Weave\";\n\nexport class Path {\n private _baseTargetLevel: FlowLevel | null;\n private components: Identifier[] | null;\n\n get baseTargetLevel() {\n if (this.baseLevelIsAmbiguous) {\n return FlowLevel.Story;\n }\n\n return this._baseTargetLevel;\n }\n\n get baseLevelIsAmbiguous(): boolean {\n return !this._baseTargetLevel;\n }\n\n get firstComponent(): string | null {\n if (this.components == null || !this.components.length) {\n return null;\n }\n\n return this.components[0].name;\n }\n\n get numberOfComponents(): number {\n return this.components ? this.components.length : 0;\n }\n\n private _dotSeparatedComponents: string | null = null;\n\n get dotSeparatedComponents(): string {\n if (this._dotSeparatedComponents == null) {\n this._dotSeparatedComponents = (this.components ? this.components : [])\n .map((c) => c.name)\n .filter(filterUndef)\n .join(\".\");\n }\n return this._dotSeparatedComponents;\n }\n\n constructor(\n argOne: FlowLevel | Identifier[] | Identifier,\n argTwo?: Identifier[]\n ) {\n if (Object.values(FlowLevel).includes(argOne as FlowLevel)) {\n this._baseTargetLevel = argOne as FlowLevel;\n this.components = argTwo || [];\n } else if (Array.isArray(argOne)) {\n this._baseTargetLevel = null;\n this.components = argOne || [];\n } else {\n this._baseTargetLevel = null;\n this.components = [argOne as Identifier];\n }\n }\n\n get typeName(): string {\n return \"Path\";\n }\n\n public readonly toString = (): string => {\n if (this.components === null || this.components.length === 0) {\n if (this.baseTargetLevel === FlowLevel.WeavePoint) {\n return \"-> \";\n }\n\n return \"\";\n }\n\n return `-> ${this.dotSeparatedComponents}`;\n };\n\n public readonly ResolveFromContext = (\n context: ParsedObject\n ): ParsedObject | null => {\n if (this.components == null || this.components.length == 0) {\n return null;\n }\n\n // Find base target of path from current context. e.g.\n // ==> BASE.sub.sub\n let baseTargetObject = this.ResolveBaseTarget(context);\n if (baseTargetObject === null) {\n return null;\n }\n\n // Given base of path, resolve final target by working deeper into hierarchy\n // e.g. ==> base.mid.FINAL\n if (this.components.length > 1) {\n return this.ResolveTailComponents(baseTargetObject);\n }\n\n return baseTargetObject;\n };\n\n // Find the root object from the base, i.e. root from:\n // root.sub1.sub2\n public readonly ResolveBaseTarget = (\n originalContext: ParsedObject\n ): ParsedObject | null => {\n const firstComp = this.firstComponent;\n\n // Work up the ancestry to find the node that has the named object\n let ancestorContext: ParsedObject | null = originalContext;\n while (ancestorContext) {\n // Only allow deep search when searching deeper from original context.\n // Don't allow search upward *then* downward, since that's searching *everywhere*!\n // Allowed examples:\n // - From an inner gather of a stitch, you should search up to find a knot called 'x'\n // at the root of a story, but not a stitch called 'x' in that knot.\n // - However, from within a knot, you should be able to find a gather/choice\n // anywhere called 'x'\n // (that latter example is quite loose, but we allow it)\n const deepSearch: boolean = ancestorContext === originalContext;\n\n const foundBase = this.GetChildFromContext(\n ancestorContext,\n firstComp,\n null,\n deepSearch\n );\n\n if (foundBase) {\n return foundBase;\n }\n\n ancestorContext = ancestorContext.parent;\n }\n\n return null;\n };\n\n // Find the final child from path given root, i.e.:\n // root.sub.finalChild\n public readonly ResolveTailComponents = (\n rootTarget: ParsedObject\n ): ParsedObject | null => {\n let foundComponent: ParsedObject | null = rootTarget;\n\n if (!this.components) return null;\n\n for (let ii = 1; ii < this.components.length; ++ii) {\n const compName = this.components[ii].name;\n\n let minimumExpectedLevel: FlowLevel;\n let foundFlow = asOrNull(foundComponent, FlowBase);\n if (foundFlow !== null) {\n minimumExpectedLevel = (foundFlow.flowLevel + 1) as FlowLevel;\n } else {\n minimumExpectedLevel = FlowLevel.WeavePoint;\n }\n\n foundComponent = this.GetChildFromContext(\n foundComponent,\n compName,\n minimumExpectedLevel\n );\n\n if (foundComponent === null) {\n break;\n }\n }\n\n return foundComponent;\n };\n\n // See whether \"context\" contains a child with a given name at a given flow level\n // Can either be a named knot/stitch (a FlowBase) or a weave point within a Weave (Choice or Gather)\n // This function also ignores any other object types that are neither FlowBase nor Weave.\n // Called from both ResolveBase (force deep) and ResolveTail for the individual components.\n public readonly GetChildFromContext = (\n context: ParsedObject,\n childName: string | null,\n minimumLevel: FlowLevel | null,\n forceDeepSearch: boolean = false\n ): ParsedObject | null => {\n // null childLevel means that we don't know where to find it\n const ambiguousChildLevel: boolean = minimumLevel === null;\n\n // Search for WeavePoint within Weave\n const weaveContext = asOrNull(context, Weave);\n if (\n childName &&\n weaveContext !== null &&\n (ambiguousChildLevel || minimumLevel === FlowLevel.WeavePoint)\n ) {\n return weaveContext.WeavePointNamed(childName) as ParsedObject;\n }\n\n // Search for content within Flow (either a sub-Flow or a WeavePoint)\n let flowContext = asOrNull(context, FlowBase);\n if (childName && flowContext !== null) {\n // When searching within a Knot, allow a deep searches so that\n // named weave points (choices and gathers) can be found within any stitch\n // Otherwise, we just search within the immediate object.\n const shouldDeepSearch =\n forceDeepSearch || flowContext.flowLevel === FlowLevel.Knot;\n\n return flowContext.ContentWithNameAtLevel(\n childName,\n minimumLevel,\n shouldDeepSearch\n );\n }\n\n return null;\n };\n}\n","import { Expression } from \"./Expression/Expression\";\nimport { ParsedObject } from \"./Object\";\nimport { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../engine/ControlCommand\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Void } from \"../../../engine/Void\";\n\nexport class ReturnType extends ParsedObject {\n public returnedExpression: Expression | null = null;\n\n constructor(returnedExpression: Expression | null = null) {\n super();\n\n if (returnedExpression) {\n this.returnedExpression = this.AddContent(\n returnedExpression\n ) as Expression;\n }\n }\n\n get typeName(): string {\n return \"ReturnType\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n\n if (this.returnedExpression) {\n // Evaluate expression\n container.AddContent(this.returnedExpression.runtimeObject);\n } else {\n // Return Runtime.Void when there's no expression to evaluate\n // (This evaluation will just add the Void object to the evaluation stack)\n container.AddContent(RuntimeControlCommand.EvalStart());\n container.AddContent(new Void());\n container.AddContent(RuntimeControlCommand.EvalEnd());\n }\n\n // Then pop the call stack\n // (the evaluated expression will leave the return value on the evaluation stack)\n container.AddContent(RuntimeControlCommand.PopFunction());\n\n return container;\n };\n}\n","// import { FlowBase } from './FlowBase';\n\nexport function ClosestFlowBase(obj: any): any | null {\n let ancestor = obj.parent;\n while (ancestor) {\n if (ancestor.hasOwnProperty(\"iamFlowbase\") && ancestor.iamFlowbase()) {\n return ancestor as any;\n }\n\n ancestor = ancestor.parent;\n }\n\n return null;\n}\n","import { DebugMetadata } from \"../../../engine/DebugMetadata\";\n\nexport class Identifier {\n public name: string;\n public debugMetadata: DebugMetadata | null = null;\n\n constructor(name: string) {\n this.name = name;\n }\n\n get typeName(): string {\n return \"Identifier\";\n }\n\n public static Done(): Identifier {\n return new Identifier(\"DONE\");\n }\n\n public readonly toString = (): string => this.name || \"undefined identifer\";\n}\n","import { Argument } from \"../Argument\";\nimport { Choice } from \"../Choice\";\nimport { Divert } from \"../Divert/Divert\";\nimport { DivertTarget } from \"../Divert/DivertTarget\";\nimport { FlowLevel } from \"./FlowLevel\";\nimport { Gather } from \"../Gather/Gather\";\nimport { INamedContent } from \"../../../../engine/INamedContent\";\n// import { Knot } from '../Knot';\nimport { ParsedObject } from \"../Object\";\nimport { Path } from \"../Path\";\nimport { ReturnType } from \"../ReturnType\";\nimport { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { VariableAssignment as RuntimeVariableAssignment } from \"../../../../engine/VariableAssignment\";\n//import { Story } from '../Story';\nimport { SymbolType } from \"../SymbolType\";\nimport { VariableAssignment } from \"../Variable/VariableAssignment\";\nimport { Weave } from \"../Weave\";\nimport { ClosestFlowBase } from \"./ClosestFlowBase\";\nimport { Identifier } from \"../Identifier\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\ntype VariableResolveResult = {\n found: boolean;\n isGlobal: boolean;\n isArgument: boolean;\n isTemporary: boolean;\n ownerFlow: FlowBase;\n};\n\n// Base class for Knots and Stitches\nexport abstract class FlowBase extends ParsedObject implements INamedContent {\n public abstract readonly flowLevel: FlowLevel;\n\n public _rootWeave: Weave | null = null;\n public _subFlowsByName: Map = new Map();\n public _startingSubFlowDivert: RuntimeDivert | null = null;\n public _startingSubFlowRuntime: RuntimeObject | null = null;\n public _firstChildFlow: FlowBase | null = null;\n public variableDeclarations: Map = new Map();\n\n get hasParameters() {\n return this.args !== null && this.args.length > 0;\n }\n\n get subFlowsByName() {\n return this._subFlowsByName;\n }\n\n get typeName(): string {\n if (this.isFunction) {\n return \"Function\";\n }\n\n return String(this.flowLevel);\n }\n\n get name(): string | null {\n return this.identifier?.name || null;\n }\n\n public identifier: Identifier | null = null;\n public args: Argument[] | null = null;\n\n constructor(\n identifier: Identifier | null,\n topLevelObjects: ParsedObject[] | null = null,\n args: Argument[] | null = null,\n public readonly isFunction: boolean = false,\n isIncludedStory: boolean = false\n ) {\n super();\n\n this.identifier = identifier;\n this.args = args;\n\n if (topLevelObjects === null) {\n topLevelObjects = [];\n }\n\n // Used by story to add includes\n this.PreProcessTopLevelObjects(topLevelObjects);\n\n topLevelObjects = this.SplitWeaveAndSubFlowContent(\n topLevelObjects,\n this.GetType() == \"Story\" && !isIncludedStory\n );\n\n this.AddContent(topLevelObjects);\n }\n\n public iamFlowbase = () => true;\n\n public readonly SplitWeaveAndSubFlowContent = (\n contentObjs: ParsedObject[],\n isRootStory: boolean\n ): ParsedObject[] => {\n const weaveObjs: ParsedObject[] = [];\n const subFlowObjs: ParsedObject[] = [];\n\n this._subFlowsByName = new Map();\n\n for (const obj of contentObjs) {\n const subFlow = asOrNull(obj, FlowBase);\n if (subFlow) {\n if (this._firstChildFlow === null) {\n this._firstChildFlow = subFlow;\n }\n\n subFlowObjs.push(obj);\n if (subFlow.identifier?.name) {\n this._subFlowsByName.set(subFlow.identifier?.name, subFlow);\n }\n } else {\n weaveObjs.push(obj);\n }\n }\n\n // Implicit final gather in top level story for ending without warning that you run out of content\n if (isRootStory) {\n weaveObjs.push(\n new Gather(null, 1),\n new Divert(new Path(Identifier.Done()))\n );\n }\n\n const finalContent: ParsedObject[] = [];\n\n if (weaveObjs.length > 0) {\n this._rootWeave = new Weave(weaveObjs, 0);\n finalContent.push(this._rootWeave);\n }\n\n if (subFlowObjs.length > 0) {\n finalContent.push(...subFlowObjs);\n }\n return finalContent;\n };\n\n public PreProcessTopLevelObjects(_: ParsedObject[]): void {\n // empty by default, used by Story to process included file references\n }\n\n public VariableResolveResult?: VariableResolveResult | null | undefined;\n\n public ResolveVariableWithName = (\n varName: string,\n fromNode: ParsedObject\n ): VariableResolveResult => {\n const result: VariableResolveResult = {} as any;\n\n // Search in the stitch / knot that owns the node first\n const ownerFlow = fromNode === null ? this : ClosestFlowBase(fromNode);\n\n if (ownerFlow) {\n // Argument\n if (ownerFlow.args !== null) {\n for (const arg of ownerFlow.args) {\n if (arg.identifier?.name === varName) {\n result.found = true;\n result.isArgument = true;\n result.ownerFlow = ownerFlow;\n return result;\n }\n }\n }\n\n // Temp\n if (\n ownerFlow !== this.story &&\n ownerFlow.variableDeclarations.has(varName)\n ) {\n result.found = true;\n result.ownerFlow = ownerFlow;\n result.isTemporary = true;\n\n return result;\n }\n }\n\n // Global\n if (this.story.variableDeclarations.has(varName)) {\n result.found = true;\n result.ownerFlow = this.story;\n result.isGlobal = true;\n\n return result;\n }\n\n result.found = false;\n\n return result;\n };\n\n public AddNewVariableDeclaration = (varDecl: VariableAssignment): void => {\n const varName = varDecl.variableName;\n if (this.variableDeclarations.has(varName)) {\n const varab = this.variableDeclarations.get(varName)!;\n let prevDeclError = \"\";\n const debugMetadata = varab.debugMetadata;\n if (debugMetadata) {\n prevDeclError = ` (${varab.debugMetadata})`;\n }\n\n this.Error(\n `found declaration variable '${varName}' that was already declared${prevDeclError}`,\n varDecl,\n false\n );\n\n return;\n }\n\n this.variableDeclarations.set(varDecl.variableName, varDecl);\n };\n\n public ResolveWeavePointNaming = (): void => {\n // Find all weave points and organise them by name ready for\n // diverting. Also detect naming collisions.\n if (this._rootWeave) {\n this._rootWeave.ResolveWeavePointNaming();\n }\n\n for (const [, value] of this._subFlowsByName) {\n if (value.hasOwnProperty(\"ResolveWeavePointNaming\")) {\n value.ResolveWeavePointNaming();\n }\n }\n };\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n let foundReturn: ReturnType | null = null;\n if (this.isFunction) {\n this.CheckForDisallowedFunctionFlowControl();\n } else if (\n this.flowLevel === FlowLevel.Knot ||\n this.flowLevel === FlowLevel.Stitch\n ) {\n // Non-functon: Make sure knots and stitches don't attempt to use Return statement\n foundReturn = this.Find(ReturnType)();\n\n if (foundReturn !== null) {\n this.Error(\n `Return statements can only be used in knots that are declared as functions: == function ${this.identifier} ==`,\n foundReturn\n );\n }\n }\n\n const container = new RuntimeContainer();\n container.name = this.identifier?.name as string;\n\n if (this.story.countAllVisits) {\n container.visitsShouldBeCounted = true;\n }\n\n this.GenerateArgumentVariableAssignments(container);\n\n // Run through content defined for this knot/stitch:\n // - First of all, any initial content before a sub-stitch\n // or any weave content is added to the main content container\n // - The first inner knot/stitch is automatically entered, while\n // the others are only accessible by an explicit divert\n // - The exception to this rule is if the knot/stitch takes\n // parameters, in which case it can't be auto-entered.\n // - Any Choices and Gathers (i.e. IWeavePoint) found are\n // processsed by GenerateFlowContent.\n let contentIdx: number = 0;\n while (this.content !== null && contentIdx < this.content.length) {\n const obj: ParsedObject = this.content[contentIdx];\n\n // Inner knots and stitches\n if (obj instanceof FlowBase) {\n const childFlow: FlowBase = obj;\n const childFlowRuntime = childFlow.runtimeObject;\n\n // First inner stitch - automatically step into it\n // 20/09/2016 - let's not auto step into knots\n if (\n contentIdx === 0 &&\n !childFlow.hasParameters &&\n this.flowLevel === FlowLevel.Knot\n ) {\n this._startingSubFlowDivert = new RuntimeDivert();\n container.AddContent(this._startingSubFlowDivert);\n this._startingSubFlowRuntime = childFlowRuntime;\n }\n\n // Check for duplicate knots/stitches with same name\n const namedChild = childFlowRuntime as RuntimeObject & INamedContent;\n const existingChild: INamedContent | null =\n container.namedContent.get(namedChild.name!) || null;\n\n if (existingChild) {\n const errorMsg = `${this.GetType()} already contains flow named '${\n namedChild.name\n }' (at ${(existingChild as any as RuntimeObject).debugMetadata})`;\n this.Error(errorMsg, childFlow);\n }\n\n container.AddToNamedContentOnly(namedChild);\n } else if (obj) {\n // Other content (including entire Weaves that were grouped in the constructor)\n // At the time of writing, all FlowBases have a maximum of one piece of \"other content\"\n // and it's always the root Weave\n container.AddContent(obj.runtimeObject);\n }\n\n contentIdx += 1;\n }\n\n // CHECK FOR FINAL LOOSE ENDS!\n // Notes:\n // - Functions don't need to terminate - they just implicitly return\n // - If return statement was found, don't continue finding warnings for missing control flow,\n // since it's likely that a return statement has been used instead of a ->-> or something,\n // or the writer failed to mark the knot as a function.\n // - _rootWeave may be null if it's a knot that only has stitches\n if (\n this.flowLevel !== FlowLevel.Story &&\n !this.isFunction &&\n this._rootWeave !== null &&\n foundReturn === null\n ) {\n this._rootWeave.ValidateTermination(this.WarningInTermination);\n }\n\n return container;\n };\n\n public readonly GenerateArgumentVariableAssignments = (\n container: RuntimeContainer\n ): void => {\n if (this.args === null || this.args.length === 0) {\n return;\n }\n\n // Assign parameters in reverse since they'll be popped off the evaluation stack\n // No need to generate EvalStart and EvalEnd since there's nothing being pushed\n // back onto the evaluation stack.\n for (let ii = this.args.length - 1; ii >= 0; --ii) {\n const paramName = this.args[ii].identifier?.name || null;\n const assign = new RuntimeVariableAssignment(paramName, true);\n container.AddContent(assign);\n }\n };\n\n public readonly ContentWithNameAtLevel = (\n name: string,\n level: FlowLevel | null = null,\n deepSearch: boolean = false\n ): ParsedObject | null => {\n // Referencing self?\n if (level === this.flowLevel || level === null) {\n if (name === this.identifier?.name) {\n return this;\n }\n }\n\n if (level === FlowLevel.WeavePoint || level === null) {\n let weavePointResult: ParsedObject | null = null;\n\n if (this._rootWeave) {\n weavePointResult = this._rootWeave.WeavePointNamed(\n name\n ) as ParsedObject;\n if (weavePointResult) {\n return weavePointResult;\n }\n }\n\n // Stop now if we only wanted a result if it's a weave point?\n if (level === FlowLevel.WeavePoint) {\n return deepSearch ? this.DeepSearchForAnyLevelContent(name) : null;\n }\n }\n\n // If this flow would be incapable of containing the requested level, early out\n // (e.g. asking for a Knot from a Stitch)\n if (level !== null && level < this.flowLevel) {\n return null;\n }\n\n let subFlow: FlowBase | null = this._subFlowsByName.get(name) || null;\n\n if (subFlow && (level === null || level === subFlow.flowLevel)) {\n return subFlow;\n }\n\n return deepSearch ? this.DeepSearchForAnyLevelContent(name) : null;\n };\n\n public readonly DeepSearchForAnyLevelContent = (name: string) => {\n const weaveResultSelf = this.ContentWithNameAtLevel(\n name,\n FlowLevel.WeavePoint,\n false\n );\n\n if (weaveResultSelf) {\n return weaveResultSelf;\n }\n\n for (const [, value] of this._subFlowsByName) {\n const deepResult = value.ContentWithNameAtLevel(name, null, true);\n\n if (deepResult) {\n return deepResult;\n }\n }\n\n return null;\n };\n\n public ResolveReferences(context: any): void {\n if (this._startingSubFlowDivert) {\n if (!this._startingSubFlowRuntime) {\n throw new Error();\n }\n\n this._startingSubFlowDivert.targetPath =\n this._startingSubFlowRuntime.path;\n }\n\n super.ResolveReferences(context);\n\n // Check validity of parameter names\n if (this.args !== null) {\n for (const arg of this.args) {\n context.CheckForNamingCollisions(\n this,\n arg.identifier,\n SymbolType.Arg,\n \"argument\"\n );\n }\n\n // Separately, check for duplicate arugment names, since they aren't Parsed.Objects,\n // so have to be checked independently.\n for (let ii = 0; ii < this.args.length; ii += 1) {\n for (let jj = ii + 1; jj < this.args.length; jj += 1) {\n if (\n this.args[ii].identifier?.name == this.args[jj].identifier?.name\n ) {\n this.Error(\n `Multiple arguments with the same name: '${this.args[ii].identifier}'`\n );\n }\n }\n }\n }\n\n // Check naming collisions for knots and stitches\n if (this.flowLevel !== FlowLevel.Story) {\n // Weave points aren't FlowBases, so this will only be knot or stitch\n const symbolType =\n this.flowLevel === FlowLevel.Knot\n ? SymbolType.Knot\n : SymbolType.SubFlowAndWeave;\n\n context.CheckForNamingCollisions(this, this.identifier, symbolType);\n }\n }\n\n public readonly CheckForDisallowedFunctionFlowControl = (): void => {\n // if (!(this instanceof Knot)) { // cannont use Knot here because of circular dependancy\n if (this.flowLevel !== FlowLevel.Knot) {\n this.Error(\n \"Functions cannot be stitches - i.e. they should be defined as '== function myFunc ==' rather than internal to another knot.\"\n );\n }\n\n // Not allowed sub-flows\n for (const [key, value] of this._subFlowsByName) {\n this.Error(\n `Functions may not contain stitches, but saw '${key}' within the function '${this.identifier}'`,\n value\n );\n }\n\n if (!this._rootWeave) {\n throw new Error();\n }\n\n const allDiverts = this._rootWeave.FindAll(Divert)();\n for (const divert of allDiverts) {\n if (!divert.isFunctionCall && !(divert.parent instanceof DivertTarget)) {\n this.Error(\n `Functions may not contain diverts, but saw '${divert}'`,\n divert\n );\n }\n }\n\n const allChoices = this._rootWeave.FindAll(Choice)();\n for (const choice of allChoices) {\n this.Error(\n `Functions may not contain choices, but saw '${choice}'`,\n choice\n );\n }\n };\n\n public readonly WarningInTermination = (terminatingObject: ParsedObject) => {\n let message: string =\n \"Apparent loose end exists where the flow runs out. Do you need a '-> DONE' statement, choice or divert?\";\n if (terminatingObject.parent === this._rootWeave && this._firstChildFlow) {\n message = `${message} Note that if you intend to enter '${this._firstChildFlow.identifier}' next, you need to divert to it explicitly.`;\n }\n\n const terminatingDivert = asOrNull(terminatingObject, Divert);\n if (terminatingDivert && terminatingDivert.isTunnel) {\n message += ` When final tunnel to '${terminatingDivert.target} ->' returns it won't have anywhere to go.`;\n }\n\n this.Warning(message, terminatingObject);\n };\n\n public readonly toString = (): string =>\n `${this.typeName} '${this.identifier}'`;\n}\n","import { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Text } from \"./Text\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\n\nexport class ContentList extends ParsedObject {\n public dontFlatten: boolean = false;\n\n get runtimeContainer(): RuntimeContainer {\n return this.runtimeObject as RuntimeContainer;\n }\n\n constructor(objects?: ParsedObject[], ...moreObjects: ParsedObject[]) {\n super();\n\n if (objects) {\n this.AddContent(objects);\n }\n\n if (moreObjects) {\n this.AddContent(moreObjects);\n }\n }\n\n get typeName(): string {\n return \"ContentList\";\n }\n\n public readonly TrimTrailingWhitespace = (): void => {\n for (let ii = this.content.length - 1; ii >= 0; --ii) {\n const text = asOrNull(this.content[ii], Text);\n if (text === null) {\n break;\n }\n\n text.text = text.text.replace(new RegExp(/[ \\t]/g), \"\");\n if (text.text.length === 0) {\n this.content.splice(ii, 1);\n } else {\n break;\n }\n }\n };\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n if (this.content !== null) {\n for (const obj of this.content) {\n const contentObjRuntime = obj.runtimeObject;\n\n // Some objects (e.g. author warnings) don't generate runtime objects\n if (contentObjRuntime) {\n container.AddContent(contentObjRuntime);\n }\n }\n }\n\n if (this.dontFlatten) {\n this.story.DontFlattenContainer(container);\n }\n\n return container;\n };\n\n public toString = (): string => `ContentList(${this.content.join(\", \")})`;\n}\n","import { InkObject } from \"./Object\";\nimport { Path } from \"./Path\";\n\nexport class VariableReference extends InkObject {\n public name: string | null;\n public pathForCount: Path | null = null;\n\n get containerForCount() {\n if (this.pathForCount === null) return null;\n return this.ResolvePath(this.pathForCount).container;\n }\n get pathStringForCount() {\n if (this.pathForCount === null) return null;\n\n return this.CompactPathString(this.pathForCount);\n }\n set pathStringForCount(value: string | null) {\n if (value === null) this.pathForCount = null;\n else this.pathForCount = new Path(value);\n }\n\n constructor(name: string | null = null) {\n super();\n this.name = name;\n }\n\n public toString() {\n if (this.name != null) {\n return \"var(\" + this.name + \")\";\n } else {\n let pathStr = this.pathStringForCount;\n return \"read_count(\" + pathStr + \")\";\n }\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ContentList } from \"../ContentList\";\nimport { Expression } from \"../Expression/Expression\";\nimport { FlowBase } from \"../Flow/FlowBase\";\nimport { ParsedObject } from \"../Object\";\nimport { Path } from \"../Path\";\nimport { Story } from \"../Story\";\nimport { VariableReference as RuntimeVariableReference } from \"../../../../engine/VariableReference\";\nimport { Weave } from \"../Weave\";\nimport { Identifier } from \"../Identifier\";\nimport { asOrNull, filterUndef } from \"../../../../engine/TypeAssertion\";\n\nexport class VariableReference extends Expression {\n private _runtimeVarRef: RuntimeVariableReference | null = null;\n\n // - Normal variables have a single item in their \"path\"\n // - Knot/stitch names for read counts are actual dot-separated paths\n // (though this isn't actually used at time of writing)\n // - List names are dot separated: listName.itemName (or just itemName)\n get name() {\n return this.path.join(\".\");\n }\n\n get path(): string[] {\n return this.pathIdentifiers.map((id) => id.name!).filter(filterUndef);\n }\n\n get identifier(): Identifier | null {\n if (!this.pathIdentifiers || this.pathIdentifiers.length == 0) {\n return null;\n }\n const name = this.path.join(\".\");\n const id = new Identifier(name);\n\n return id;\n }\n\n // Only known after GenerateIntoContainer has run\n public isConstantReference: boolean = false;\n public isListItemReference: boolean = false;\n\n get runtimeVarRef() {\n return this._runtimeVarRef;\n }\n\n constructor(public readonly pathIdentifiers: Identifier[]) {\n super();\n }\n\n get typeName(): string {\n return \"ref\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n let constantValue: Expression | null | undefined = this.story.constants.get(\n this.name\n );\n\n // If it's a constant reference, just generate the literal expression value\n // It's okay to access the constants at code generation time, since the\n // first thing the ExportRuntime function does it search for all the constants\n // in the story hierarchy, so they're all available.\n if (constantValue) {\n constantValue.GenerateConstantIntoContainer(container);\n this.isConstantReference = true;\n\n return;\n }\n\n this._runtimeVarRef = new RuntimeVariableReference(this.name);\n\n // List item reference?\n // Path might be to a list (listName.listItemName or just listItemName)\n if (this.path.length === 1 || this.path.length === 2) {\n let listItemName: string = \"\";\n let listName: string = \"\";\n\n if (this.path.length === 1) {\n listItemName = this.path[0];\n } else {\n listName = this.path[0];\n listItemName = this.path[1];\n }\n\n const listItem = this.story.ResolveListItem(listName, listItemName, this);\n\n if (listItem) {\n this.isListItemReference = true;\n }\n }\n\n container.AddContent(this._runtimeVarRef);\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n // Work is already done if it's a constant or list item reference\n if (this.isConstantReference || this.isListItemReference) {\n return;\n }\n\n // Is it a read count?\n const parsedPath = new Path(this.pathIdentifiers);\n const targetForCount: ParsedObject | null =\n parsedPath.ResolveFromContext(this);\n if (targetForCount) {\n if (!targetForCount.containerForCounting) {\n throw new Error();\n }\n\n targetForCount.containerForCounting.visitsShouldBeCounted = true;\n\n // If this is an argument to a function that wants a variable to be\n // passed by reference, then the Parsed.Divert will have generated a\n // Runtime.VariablePointerValue instead of allowing this object\n // to generate its RuntimeVariableReference. This only happens under\n // error condition since we shouldn't be passing a read count by\n // reference, but we don't want it to crash!\n if (this._runtimeVarRef === null) {\n return;\n }\n\n this._runtimeVarRef.pathForCount = targetForCount.runtimePath;\n this._runtimeVarRef.name = null;\n\n // Check for very specific writer error: getting read count and\n // printing it as content rather than as a piece of logic\n // e.g. Writing {myFunc} instead of {myFunc()}\n let targetFlow = asOrNull(targetForCount, FlowBase);\n if (targetFlow && targetFlow.isFunction) {\n // Is parent context content rather than logic?\n if (\n this.parent instanceof Weave ||\n this.parent instanceof ContentList ||\n this.parent instanceof FlowBase\n ) {\n this.Warning(\n `'${targetFlow.identifier}' being used as read count rather than being called as function. Perhaps you intended to write ${targetFlow.identifier}()`\n );\n }\n }\n\n return;\n }\n\n // Couldn't find this multi-part path at all, whether as a divert\n // target or as a list item reference.\n if (this.path.length > 1) {\n let errorMsg = `Could not find target for read count: ${parsedPath}`;\n if (this.path.length <= 2) {\n errorMsg += `, or couldn't find list item with the name ${this.path.join(\n \",\"\n )}`;\n }\n\n this.Error(errorMsg);\n\n return;\n }\n\n if (!context.ResolveVariableWithName(this.name, this).found) {\n this.Error(`Unresolved variable: ${this.name}`, this);\n }\n }\n\n public readonly toString = (): string => `{${this.path.join(\".\")}}`;\n}\n","import { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../engine/ControlCommand\";\nimport { Divert } from \"./Divert/Divert\";\nimport { Divert as RuntimeDivert } from \"../../../engine/Divert\";\nimport { DivertTarget } from \"./Divert/DivertTarget\";\nimport { Expression } from \"./Expression/Expression\";\nimport { InkList as RuntimeInkList } from \"../../../engine/InkList\";\nimport { ListValue } from \"../../../engine/Value\";\nimport { NativeFunctionCall } from \"../../../engine/NativeFunctionCall\";\nimport { NumberExpression } from \"./Expression/NumberExpression\";\nimport { Path } from \"./Path\";\nimport { Story } from \"./Story\";\nimport { StringValue } from \"../../../engine/Value\";\nimport { VariableReference } from \"./Variable/VariableReference\";\nimport { Identifier } from \"./Identifier\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\n\nexport class FunctionCall extends Expression {\n public static readonly IsBuiltIn = (name: string): boolean => {\n if (NativeFunctionCall.CallExistsWithName(name)) {\n return true;\n }\n\n return (\n name === \"CHOICE_COUNT\" ||\n name === \"TURNS_SINCE\" ||\n name === \"TURNS\" ||\n name === \"RANDOM\" ||\n name === \"SEED_RANDOM\" ||\n name === \"LIST_VALUE\" ||\n name === \"LIST_RANDOM\" ||\n name === \"READ_COUNT\"\n );\n };\n\n private _proxyDivert: Divert;\n get proxyDivert(): Divert {\n return this._proxyDivert;\n }\n private _divertTargetToCount: DivertTarget | null = null;\n private _variableReferenceToCount: VariableReference | null = null;\n\n get name(): string {\n return (this._proxyDivert.target as Path).firstComponent || \"\";\n }\n\n get args(): Expression[] {\n return this._proxyDivert.args;\n }\n\n get runtimeDivert(): RuntimeDivert {\n return this._proxyDivert.runtimeDivert;\n }\n\n get isChoiceCount(): boolean {\n return this.name === \"CHOICE_COUNT\";\n }\n\n get isTurns(): boolean {\n return this.name === \"TURNS\";\n }\n\n get isTurnsSince(): boolean {\n return this.name === \"TURNS_SINCE\";\n }\n\n get isRandom(): boolean {\n return this.name === \"RANDOM\";\n }\n\n get isSeedRandom(): boolean {\n return this.name === \"SEED_RANDOM\";\n }\n\n get isListRange(): boolean {\n return this.name === \"LIST_RANGE\";\n }\n\n get isListRandom(): boolean {\n return this.name === \"LIST_RANDOM\";\n }\n\n get isReadCount(): boolean {\n return this.name === \"READ_COUNT\";\n }\n\n public shouldPopReturnedValue: boolean = false;\n\n constructor(functionName: Identifier, args: Expression[]) {\n super();\n\n this._proxyDivert = new Divert(new Path(functionName), args);\n this._proxyDivert.isFunctionCall = true;\n this.AddContent(this._proxyDivert);\n }\n\n get typeName(): string {\n return \"FunctionCall\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n const foundList = this.story.ResolveList(this.name);\n\n let usingProxyDivert: boolean = false;\n\n if (this.isChoiceCount) {\n if (this.args.length > 0) {\n this.Error(\"The CHOICE_COUNT() function shouldn't take any arguments\");\n }\n\n container.AddContent(RuntimeControlCommand.ChoiceCount());\n } else if (this.isTurns) {\n if (this.args.length > 0) {\n this.Error(\"The TURNS() function shouldn't take any arguments\");\n }\n\n container.AddContent(RuntimeControlCommand.Turns());\n } else if (this.isTurnsSince || this.isReadCount) {\n const divertTarget = asOrNull(this.args[0], DivertTarget);\n const variableDivertTarget = asOrNull(this.args[0], VariableReference);\n\n if (\n this.args.length !== 1 ||\n (divertTarget === null && variableDivertTarget === null)\n ) {\n this.Error(\n `The ${this.name}() function should take one argument: a divert target to the target knot, stitch, gather or choice you want to check. e.g. TURNS_SINCE(-> myKnot)`\n );\n return;\n }\n\n if (divertTarget) {\n this._divertTargetToCount = divertTarget;\n this.AddContent(this._divertTargetToCount);\n\n this._divertTargetToCount.GenerateIntoContainer(container);\n } else if (variableDivertTarget) {\n this._variableReferenceToCount = variableDivertTarget;\n this.AddContent(this._variableReferenceToCount);\n\n this._variableReferenceToCount.GenerateIntoContainer(container);\n }\n\n if (this.isTurnsSince) {\n container.AddContent(RuntimeControlCommand.TurnsSince());\n } else {\n container.AddContent(RuntimeControlCommand.ReadCount());\n }\n } else if (this.isRandom) {\n if (this.args.length !== 2) {\n this.Error(\n \"RANDOM should take 2 parameters: a minimum and a maximum integer\"\n );\n }\n\n // We can type check single values, but not complex expressions\n for (let ii = 0; ii < this.args.length; ii += 1) {\n const num = asOrNull(this.args[ii], NumberExpression);\n if (num && !num.isInt()) {\n const paramName: string = ii === 0 ? \"minimum\" : \"maximum\";\n this.Error(`RANDOM's ${paramName} parameter should be an integer`);\n }\n\n this.args[ii].GenerateIntoContainer(container);\n }\n\n container.AddContent(RuntimeControlCommand.Random());\n } else if (this.isSeedRandom) {\n if (this.args.length !== 1) {\n this.Error(\"SEED_RANDOM should take 1 parameter - an integer seed\");\n }\n\n const num = asOrNull(this.args[0], NumberExpression);\n if (num && !num.isInt()) {\n this.Error(\"SEED_RANDOM's parameter should be an integer seed\");\n }\n\n this.args[0].GenerateIntoContainer(container);\n\n container.AddContent(RuntimeControlCommand.SeedRandom());\n } else if (this.isListRange) {\n if (this.args.length !== 3) {\n this.Error(\n \"LIST_RANGE should take 3 parameters - a list, a min and a max\"\n );\n }\n\n for (let ii = 0; ii < this.args.length; ii += 1) {\n this.args[ii].GenerateIntoContainer(container);\n }\n\n container.AddContent(RuntimeControlCommand.ListRange());\n } else if (this.isListRandom) {\n if (this.args.length !== 1) {\n this.Error(\"LIST_RANDOM should take 1 parameter - a list\");\n }\n\n this.args[0].GenerateIntoContainer(container);\n\n container.AddContent(RuntimeControlCommand.ListRandom());\n } else if (NativeFunctionCall.CallExistsWithName(this.name)) {\n const nativeCall = NativeFunctionCall.CallWithName(this.name);\n if (nativeCall.numberOfParameters !== this.args.length) {\n let msg = `${name} should take ${nativeCall.numberOfParameters} parameter`;\n if (nativeCall.numberOfParameters > 1) {\n msg += \"s\";\n }\n\n this.Error(msg);\n }\n\n for (let ii = 0; ii < this.args.length; ii += 1) {\n this.args[ii].GenerateIntoContainer(container);\n }\n\n container.AddContent(NativeFunctionCall.CallWithName(this.name));\n } else if (foundList !== null) {\n if (this.args.length > 1) {\n this.Error(\n \"Can currently only construct a list from one integer (or an empty list from a given list definition)\"\n );\n }\n\n // List item from given int\n if (this.args.length === 1) {\n container.AddContent(new StringValue(this.name));\n this.args[0].GenerateIntoContainer(container);\n container.AddContent(RuntimeControlCommand.ListFromInt());\n } else {\n // Empty list with given origin.\n const list = new RuntimeInkList();\n list.SetInitialOriginName(this.name);\n container.AddContent(new ListValue(list));\n }\n } else {\n // Normal function call\n container.AddContent(this._proxyDivert.runtimeObject);\n usingProxyDivert = true;\n }\n\n // Don't attempt to resolve as a divert if we're not doing a normal function call\n if (!usingProxyDivert) {\n this.content.splice(this.content.indexOf(this._proxyDivert), 1);\n }\n\n // Function calls that are used alone on a tilda-based line:\n // ~ func()\n // Should tidy up any returned value from the evaluation stack,\n // since it's unused.\n if (this.shouldPopReturnedValue) {\n container.AddContent(RuntimeControlCommand.PopEvaluatedValue());\n }\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n // If we aren't using the proxy divert after all (e.g. if\n // it's a native function call), but we still have arguments,\n // we need to make sure they get resolved since the proxy divert\n // is no longer in the content array.\n if (!this.content.includes(this._proxyDivert) && this.args !== null) {\n for (const arg of this.args) {\n arg.ResolveReferences(context);\n }\n }\n\n if (this._divertTargetToCount) {\n const divert = this._divertTargetToCount.divert;\n const attemptingTurnCountOfVariableTarget =\n divert.runtimeDivert.variableDivertName != null;\n\n if (attemptingTurnCountOfVariableTarget) {\n this.Error(\n `When getting the TURNS_SINCE() of a variable target, remove the '->' - i.e. it should just be TURNS_SINCE(${divert.runtimeDivert.variableDivertName})`\n );\n\n return;\n }\n\n const targetObject = divert.targetContent;\n if (targetObject === null) {\n if (!attemptingTurnCountOfVariableTarget) {\n this.Error(\n `Failed to find target for TURNS_SINCE: '${divert.target}'`\n );\n }\n } else {\n if (!targetObject.containerForCounting) {\n throw new Error();\n }\n\n targetObject.containerForCounting.turnIndexShouldBeCounted = true;\n }\n } else if (this._variableReferenceToCount) {\n const runtimeVarRef = this._variableReferenceToCount.runtimeVarRef;\n if (!runtimeVarRef) {\n throw new Error();\n }\n\n if (runtimeVarRef.pathForCount !== null) {\n this.Error(\n `Should be '${name}'(-> '${this._variableReferenceToCount.name}). Usage without the '->' only makes sense for variable targets.`\n );\n }\n }\n }\n\n public readonly toString = (): string => {\n const strArgs = this.args.join(\", \");\n return `${this.name}(${strArgs})`;\n };\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"./Expression\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\n\nexport class MultipleConditionExpression extends Expression {\n get subExpressions(): Expression[] {\n return this.content as Expression[];\n }\n\n constructor(conditionExpressions: Expression[]) {\n super();\n\n this.AddContent(conditionExpressions);\n }\n\n get typeName(): string {\n return \"MultipleConditionExpression\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n // A && B && C && D\n // => (((A B &&) C &&) D &&) etc\n let isFirst: boolean = true;\n for (const conditionExpr of this.subExpressions) {\n conditionExpr.GenerateIntoContainer(container);\n\n if (!isFirst) {\n container.AddContent(NativeFunctionCall.CallWithName(\"&&\"));\n }\n\n isFirst = false;\n }\n };\n}\n","export enum SequenceType {\n Stopping = 1, // default\n Cycle = 2,\n Shuffle = 4,\n Once = 8,\n}\n","import { BinaryExpression } from \"../Expression/BinaryExpression\";\nimport { Choice } from \"../Choice\";\nimport { Conditional } from \"../Conditional/Conditional\";\nimport { ConditionalSingleBranch } from \"../Conditional/ConditionalSingleBranch\";\nimport { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ParsedObject } from \"../Object\";\nimport { Divert } from \"./Divert\";\nimport { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { DivertTargetValue } from \"../../../../engine/Value\";\nimport { Expression } from \"../Expression/Expression\";\nimport { FlowBase } from \"../Flow/FlowBase\";\nimport { FunctionCall } from \"../FunctionCall\";\nimport { MultipleConditionExpression } from \"../Expression/MultipleConditionExpression\";\nimport { Story } from \"../Story\";\nimport { VariableReference } from \"../Variable/VariableReference\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class DivertTarget extends Expression {\n private _runtimeDivert: RuntimeDivert | null = null;\n get runtimeDivert(): RuntimeDivert {\n if (!this._runtimeDivert) {\n throw new Error();\n }\n\n return this._runtimeDivert;\n }\n\n private _runtimeDivertTargetValue: DivertTargetValue | null = null;\n get runtimeDivertTargetValue(): DivertTargetValue {\n if (!this._runtimeDivertTargetValue) {\n throw new Error();\n }\n\n return this._runtimeDivertTargetValue;\n }\n\n public divert: Divert;\n\n constructor(divert: Divert) {\n super();\n\n this.divert = this.AddContent(divert) as Divert;\n }\n\n get typeName(): string {\n return \"DivertTarget\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n this.divert.GenerateRuntimeObject();\n\n this._runtimeDivert = this.divert.runtimeDivert as RuntimeDivert;\n this._runtimeDivertTargetValue = new DivertTargetValue();\n\n container.AddContent(this.runtimeDivertTargetValue);\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n if (this.divert.isDone || this.divert.isEnd) {\n this.Error(\n `Can't use -> DONE or -> END as variable divert targets`,\n this\n );\n\n return;\n }\n\n let usageContext: ParsedObject | null = this;\n while (usageContext && usageContext instanceof Expression) {\n let badUsage: boolean = false;\n let foundUsage: boolean = false;\n\n const usageParent: any = (usageContext as Expression).parent;\n if (usageParent instanceof BinaryExpression) {\n // Only allowed to compare for equality\n\n const binaryExprParent = usageParent;\n if (\n binaryExprParent.opName !== \"==\" &&\n binaryExprParent.opName !== \"!=\"\n ) {\n badUsage = true;\n } else {\n if (\n !(\n binaryExprParent.leftExpression instanceof DivertTarget ||\n binaryExprParent.leftExpression instanceof VariableReference\n )\n ) {\n badUsage = true;\n } else if (\n !(\n binaryExprParent.rightExpression instanceof DivertTarget ||\n binaryExprParent.rightExpression instanceof VariableReference\n )\n ) {\n badUsage = true;\n }\n }\n\n foundUsage = true;\n } else if (usageParent instanceof FunctionCall) {\n const funcCall = usageParent;\n if (!funcCall.isTurnsSince && !funcCall.isReadCount) {\n badUsage = true;\n }\n\n foundUsage = true;\n } else if (usageParent instanceof Expression) {\n badUsage = true;\n foundUsage = true;\n } else if (usageParent instanceof MultipleConditionExpression) {\n badUsage = true;\n foundUsage = true;\n } else if (\n usageParent instanceof Choice &&\n (usageParent as Choice).condition === usageContext\n ) {\n badUsage = true;\n foundUsage = true;\n } else if (\n usageParent instanceof Conditional ||\n usageParent instanceof ConditionalSingleBranch\n ) {\n badUsage = true;\n foundUsage = true;\n }\n\n if (badUsage) {\n this.Error(\n `Can't use a divert target like that. Did you intend to call '${this.divert.target}' as a function: likeThis(), or check the read count: likeThis, with no arrows?`,\n this\n );\n }\n\n if (foundUsage) {\n break;\n }\n\n usageContext = usageParent;\n }\n\n // Example ink for this case:\n //\n // VAR x = -> blah\n //\n // ...which means that \"blah\" is expected to be a literal stitch target rather\n // than a variable name. We can't really intelligently recover from this (e.g. if blah happens to\n // contain a divert target itself) since really we should be generating a variable reference\n // rather than a concrete DivertTarget, so we list it as an error.\n if (this.runtimeDivert.hasVariableTarget) {\n if (!this.divert.target) {\n throw new Error();\n }\n\n this.Error(\n `Since '${this.divert.target.dotSeparatedComponents}' is a variable, it shouldn't be preceded by '->' here.`\n );\n }\n\n // Main resolve\n this.runtimeDivert.targetPath &&\n (this.runtimeDivertTargetValue.targetPath =\n this.runtimeDivert.targetPath);\n\n // Tell hard coded (yet variable) divert targets that they also need to be counted\n // TODO: Only detect DivertTargets that are values rather than being used directly for\n // read or turn counts. Should be able to detect this by looking for other uses of containerForCounting\n let targetContent = this.divert.targetContent;\n if (targetContent !== null) {\n let target = targetContent.containerForCounting;\n if (target !== null) {\n // Purpose is known: used directly in TURNS_SINCE(-> divTarg)\n const parentFunc = asOrNull(this.parent, FunctionCall);\n if (parentFunc && parentFunc.isTurnsSince) {\n target.turnIndexShouldBeCounted = true;\n } else {\n // Unknown purpose, count everything\n target.visitsShouldBeCounted = true;\n target.turnIndexShouldBeCounted = true;\n }\n }\n\n // Unfortunately not possible:\n // https://github.com/inkle/ink/issues/538\n //\n // VAR func = -> double\n //\n // === function double(ref x)\n // ~ x = x * 2\n //\n // Because when generating the parameters for a function\n // to be called, it needs to know ahead of time when\n // compiling whether to pass a variable reference or value.\n //\n let targetFlow = asOrNull(targetContent, FlowBase);\n if (targetFlow != null && targetFlow.args !== null) {\n for (const arg of targetFlow.args) {\n if (arg.isByReference) {\n this.Error(\n `Can't store a divert target to a knot or function that has by-reference arguments ('${targetFlow.identifier}' has 'ref ${arg.identifier}').`\n );\n }\n }\n }\n }\n }\n\n // Equals override necessary in order to check for CONST multiple definition equality\n public readonly Equals = (obj: ParsedObject): boolean => {\n const otherDivTarget = asOrNull(obj, DivertTarget);\n if (\n !otherDivTarget ||\n !this.divert.target ||\n !otherDivTarget.divert.target\n ) {\n return false;\n }\n\n const targetStr = this.divert.target.dotSeparatedComponents;\n const otherTargetStr = otherDivTarget.divert.target.dotSeparatedComponents;\n\n return targetStr === otherTargetStr;\n };\n}\n","import { Argument } from \"../Argument\";\nimport { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { DivertTarget } from \"./DivertTarget\";\nimport { Expression } from \"../Expression/Expression\";\nimport { FlowBase } from \"../Flow/FlowBase\";\nimport { FunctionCall } from \"../FunctionCall\";\nimport { ParsedObject } from \"../Object\";\nimport { Path } from \"../Path\";\nimport { Path as RuntimePath } from \"../../../../engine/Path\";\nimport { PushPopType } from \"../../../../engine/PushPop\";\nimport { Story } from \"../Story\";\nimport { VariablePointerValue } from \"../../../../engine/Value\";\nimport { VariableReference } from \"../Variable/VariableReference\";\nimport { ClosestFlowBase } from \"../Flow/ClosestFlowBase\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class Divert extends ParsedObject {\n public readonly args: Expression[] = [];\n\n public readonly target: Path | null = null;\n public targetContent: ParsedObject | null = null;\n private _runtimeDivert: RuntimeDivert | null = null;\n get runtimeDivert(): RuntimeDivert {\n if (!this._runtimeDivert) {\n throw new Error();\n }\n\n return this._runtimeDivert;\n }\n\n set runtimeDivert(value: RuntimeDivert) {\n this._runtimeDivert = value;\n }\n\n public isFunctionCall: boolean = false;\n public isEmpty: boolean = false;\n public isTunnel: boolean = false;\n public isThread: boolean = false;\n\n get isEnd(): boolean {\n return Boolean(this.target && this.target.dotSeparatedComponents === \"END\");\n }\n\n get isDone(): boolean {\n return Boolean(\n this.target && this.target.dotSeparatedComponents === \"DONE\"\n );\n }\n\n constructor(target?: Path | null | undefined, args?: Expression[]) {\n super();\n\n if (target) {\n this.target = target;\n }\n\n if (args) {\n this.args = args;\n this.AddContent(args);\n }\n }\n\n get typeName(): string {\n return \"Divert\";\n }\n\n public readonly GenerateRuntimeObject = () => {\n // End = end flow immediately\n // Done = return from thread or instruct the flow that it's safe to exit\n if (this.isEnd) {\n return RuntimeControlCommand.End();\n } else if (this.isDone) {\n return RuntimeControlCommand.Done();\n }\n\n this.runtimeDivert = new RuntimeDivert();\n\n // Normally we resolve the target content during the\n // Resolve phase, since we expect all runtime objects to\n // be available in order to find the final runtime path for\n // the destination. However, we need to resolve the target\n // (albeit without the runtime target) early so that\n // we can get information about the arguments - whether\n // they're by reference - since it affects the code we\n // generate here.\n this.ResolveTargetContent();\n\n this.CheckArgumentValidity();\n\n // Passing arguments to the knot\n const requiresArgCodeGen = this.args !== null && this.args.length > 0;\n if (\n requiresArgCodeGen ||\n this.isFunctionCall ||\n this.isTunnel ||\n this.isThread\n ) {\n const container = new RuntimeContainer();\n\n // Generate code for argument evaluation\n // This argument generation is coded defensively - it should\n // attempt to generate the code for all the parameters, even if\n // they don't match the expected arguments. This is so that the\n // parameter objects themselves are generated correctly and don't\n // get into a state of attempting to resolve references etc\n // without being generated.\n if (requiresArgCodeGen) {\n // Function calls already in an evaluation context\n if (!this.isFunctionCall) {\n container.AddContent(RuntimeControlCommand.EvalStart());\n }\n\n let targetArguments: Argument[] | null = null;\n if (this.targetContent) {\n targetArguments = (this.targetContent as FlowBase).args;\n }\n\n for (let ii = 0; ii < this.args.length; ++ii) {\n const argToPass: Expression = this.args[ii];\n let argExpected: Argument | null = null;\n if (targetArguments && ii < targetArguments.length) {\n argExpected = targetArguments[ii];\n }\n\n // Pass by reference: argument needs to be a variable reference\n if (argExpected && argExpected.isByReference) {\n const varRef = asOrNull(argToPass, VariableReference);\n if (!varRef) {\n this.Error(\n `Expected variable name to pass by reference to 'ref ${argExpected.identifier}' but saw ${argToPass}`\n );\n\n break;\n }\n\n // Check that we're not attempting to pass a read count by reference\n const targetPath = new Path(varRef.pathIdentifiers);\n const targetForCount: ParsedObject | null =\n targetPath.ResolveFromContext(this);\n if (targetForCount) {\n this.Error(\n `can't pass a read count by reference. '${\n targetPath.dotSeparatedComponents\n }' is a knot/stitch/label, but '${\n this.target!.dotSeparatedComponents\n }' requires the name of a VAR to be passed.`\n );\n\n break;\n }\n\n const varPointer = new VariablePointerValue(varRef.name);\n container.AddContent(varPointer);\n } else {\n // Normal value being passed: evaluate it as normal\n argToPass.GenerateIntoContainer(container);\n }\n }\n\n // Function calls were already in an evaluation context\n if (!this.isFunctionCall) {\n container.AddContent(RuntimeControlCommand.EvalEnd());\n }\n }\n\n // Starting a thread? A bit like a push to the call stack below... but not.\n // It sort of puts the call stack on a thread stack (argh!) - forks the full flow.\n if (this.isThread) {\n container.AddContent(RuntimeControlCommand.StartThread());\n } else if (this.isFunctionCall || this.isTunnel) {\n // If this divert is a function call, tunnel, we push to the call stack\n // so we can return again\n this.runtimeDivert.pushesToStack = true;\n this.runtimeDivert.stackPushType = this.isFunctionCall\n ? PushPopType.Function\n : PushPopType.Tunnel;\n }\n\n // Jump into the \"function\" (knot/stitch)\n container.AddContent(this.runtimeDivert);\n\n return container;\n }\n\n // Simple divert\n return this.runtimeDivert;\n };\n\n // When the divert is to a target that's actually a variable name\n // rather than an explicit knot/stitch name, try interpretting it\n // as such by getting the variable name.\n public readonly PathAsVariableName = () =>\n this.target ? this.target.firstComponent : null;\n\n public readonly ResolveTargetContent = (): void => {\n if (this.isEmpty || this.isEnd) {\n return;\n }\n\n if (this.targetContent === null) {\n // Is target of this divert a variable name that will be de-referenced\n // at runtime? If so, there won't be any further reference resolution\n // we can do at this point.\n let variableTargetName = this.PathAsVariableName();\n if (variableTargetName !== null) {\n const flowBaseScope = asOrNull(ClosestFlowBase(this), FlowBase);\n if (flowBaseScope) {\n const resolveResult = flowBaseScope.ResolveVariableWithName(\n variableTargetName,\n this\n );\n\n if (resolveResult.found) {\n // Make sure that the flow was typed correctly, given that we know that this\n // is meant to be a divert target\n if (\n resolveResult.isArgument &&\n resolveResult.ownerFlow &&\n resolveResult.ownerFlow.args\n ) {\n let argument = resolveResult.ownerFlow.args.find(\n (a) => a.identifier?.name == variableTargetName\n );\n\n if (argument && !argument.isDivertTarget) {\n this.Error(\n `Since '${argument.identifier}' is used as a variable divert target (on ${this.debugMetadata}), it should be marked as: -> ${argument.identifier}`,\n resolveResult.ownerFlow\n );\n }\n }\n\n this.runtimeDivert.variableDivertName = variableTargetName;\n return;\n }\n }\n }\n\n if (!this.target) {\n throw new Error();\n }\n\n this.targetContent = this.target.ResolveFromContext(this);\n }\n };\n\n public ResolveReferences(context: Story): void {\n if (this.isEmpty || this.isEnd || this.isDone) {\n return;\n } else if (!this.runtimeDivert) {\n throw new Error();\n }\n\n if (this.targetContent) {\n this.runtimeDivert.targetPath = this.targetContent.runtimePath;\n }\n\n // Resolve children (the arguments)\n super.ResolveReferences(context);\n\n // May be null if it's a built in function (e.g. TURNS_SINCE)\n // or if it's a variable target.\n let targetFlow = asOrNull(this.targetContent, FlowBase);\n if (targetFlow) {\n if (!targetFlow.isFunction && this.isFunctionCall) {\n super.Error(\n `${targetFlow.identifier} hasn't been marked as a function, but it's being called as one. Do you need to delcare the knot as '== function ${targetFlow.identifier} =='?`\n );\n } else if (\n targetFlow.isFunction &&\n !this.isFunctionCall &&\n !(this.parent instanceof DivertTarget)\n ) {\n super.Error(\n targetFlow.identifier +\n \" can't be diverted to. It can only be called as a function since it's been marked as such: '\" +\n targetFlow.identifier +\n \"(...)'\"\n );\n }\n }\n\n // Check validity of target content\n const targetWasFound = this.targetContent !== null;\n let isBuiltIn: boolean = false;\n let isExternal: boolean = false;\n\n if (!this.target) {\n throw new Error();\n } else if (this.target.numberOfComponents === 1) {\n if (!this.target.firstComponent) {\n throw new Error();\n }\n\n // BuiltIn means TURNS_SINCE, CHOICE_COUNT, RANDOM or SEED_RANDOM\n isBuiltIn = FunctionCall.IsBuiltIn(this.target.firstComponent);\n\n // Client-bound function?\n isExternal = context.IsExternal(this.target.firstComponent);\n\n if (isBuiltIn || isExternal) {\n if (!this.isFunctionCall) {\n super.Error(\n `${this.target.firstComponent} must be called as a function: ~ ${this.target.firstComponent}()`\n );\n }\n\n if (isExternal) {\n this.runtimeDivert.isExternal = true;\n if (this.args !== null) {\n this.runtimeDivert.externalArgs = this.args.length;\n }\n\n this.runtimeDivert.pushesToStack = false;\n this.runtimeDivert.targetPath = new RuntimePath(\n this.target.firstComponent\n );\n\n this.CheckExternalArgumentValidity(context);\n }\n\n return;\n }\n }\n\n // Variable target?\n if (this.runtimeDivert.variableDivertName != null) {\n return;\n }\n\n if (!targetWasFound && !isBuiltIn && !isExternal) {\n this.Error(`target not found: '${this.target}'`);\n }\n }\n\n // Returns false if there's an error\n public readonly CheckArgumentValidity = (): void => {\n if (this.isEmpty) {\n return;\n }\n\n // Argument passing: Check for errors in number of arguments\n let numArgs = 0;\n if (this.args !== null && this.args.length > 0) {\n numArgs = this.args.length;\n }\n\n // Missing content?\n // Can't check arguments properly. It'll be due to some\n // other error though, so although there's a problem and\n // we report false, we don't need to report a specific error.\n // It may also be because it's a valid call to an external\n // function, that we check at the resolve stage.\n if (this.targetContent === null) {\n return;\n }\n\n const targetFlow = asOrNull(this.targetContent, FlowBase);\n\n // No error, crikey!\n if (numArgs === 0 && (targetFlow === null || !targetFlow.hasParameters)) {\n return;\n } else if (targetFlow === null && numArgs > 0) {\n this.Error(\n \"target needs to be a knot or stitch in order to pass arguments\"\n );\n return;\n } else if (\n targetFlow !== null &&\n (targetFlow.args === null || (!targetFlow.args && numArgs > 0))\n ) {\n this.Error(`target (${targetFlow.name}) doesn't take parameters`);\n return;\n } else if (this.parent instanceof DivertTarget) {\n if (numArgs > 0) {\n this.Error(`can't store arguments in a divert target variable`);\n }\n\n return;\n }\n\n const paramCount = targetFlow!.args!.length;\n if (paramCount !== numArgs) {\n let butClause: string;\n if (numArgs === 0) {\n butClause = \"but there weren't any passed to it\";\n } else if (numArgs < paramCount) {\n butClause = `but only got ${numArgs}`;\n } else {\n butClause = `but got ${numArgs}`;\n }\n\n this.Error(\n `to '${\n targetFlow!.identifier\n }' requires ${paramCount} arguments, ${butClause}`\n );\n\n return;\n }\n\n // Light type-checking for divert target arguments\n for (let ii = 0; ii < paramCount; ++ii) {\n const flowArg: Argument = targetFlow!.args![ii];\n const divArgExpr: Expression = this.args[ii];\n\n // Expecting a divert target as an argument, let's do some basic type checking\n if (flowArg.isDivertTarget) {\n // Not passing a divert target or any kind of variable reference?\n let varRef = asOrNull(divArgExpr, VariableReference);\n if (!(divArgExpr instanceof DivertTarget) && varRef === null) {\n this.Error(\n `Target '${\n targetFlow!.identifier\n }' expects a divert target for the parameter named -> ${\n flowArg.identifier\n } but saw ${divArgExpr}`,\n divArgExpr\n );\n } else if (varRef) {\n // Passing 'a' instead of '-> a'?\n // i.e. read count instead of divert target\n // Unfortunately have to manually resolve here since we're still in code gen\n const knotCountPath = new Path(varRef.pathIdentifiers);\n const targetForCount: ParsedObject | null =\n knotCountPath.ResolveFromContext(varRef);\n if (targetForCount) {\n this.Error(\n `Passing read count of '${knotCountPath.dotSeparatedComponents}' instead of a divert target. You probably meant '${knotCountPath}'`\n );\n }\n }\n }\n }\n\n if (targetFlow === null) {\n this.Error(\n \"Can't call as a function or with arguments unless it's a knot or stitch\"\n );\n return;\n }\n\n return;\n };\n\n public readonly CheckExternalArgumentValidity = (context: Story): void => {\n const externalName: string | null = this.target\n ? this.target.firstComponent\n : null;\n const external = context.externals.get(externalName as any);\n if (!external) {\n throw new Error(\"external not found\");\n }\n\n const externalArgCount: number = external.argumentNames.length;\n let ownArgCount = 0;\n if (this.args) {\n ownArgCount = this.args.length;\n }\n\n if (ownArgCount !== externalArgCount) {\n this.Error(\n `incorrect number of arguments sent to external function '${externalName}'. Expected ${externalArgCount} but got ${ownArgCount}`\n );\n }\n };\n\n public Error(\n message: string,\n source: ParsedObject | null = null,\n isWarning: boolean = false\n ): void {\n // Could be getting an error from a nested Divert\n if (source !== this && source) {\n super.Error(message, source);\n return;\n }\n\n if (this.isFunctionCall) {\n super.Error(`Function call ${message}`, source, isWarning);\n } else {\n super.Error(`Divert ${message}`, source, isWarning);\n }\n }\n\n public toString = (): string => {\n let returnString = \"\";\n if (this.target !== null) {\n returnString += this.target.toString();\n } else {\n return \"-> \";\n }\n\n if (this.isTunnel) {\n returnString += \" ->\";\n }\n if (this.isFunctionCall) {\n returnString += \" ()\";\n }\n\n return returnString;\n };\n}\n","import { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\n\nexport class GatherPointToResolve {\n constructor(\n public divert: RuntimeDivert,\n public targetRuntimeObj: RuntimeObject\n ) {}\n}\n","import { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\n\nexport class SequenceDivertToResolve {\n constructor(\n public divert: RuntimeDivert,\n public targetContent: RuntimeObject\n ) {}\n}\n","import { ContentList } from \"../ContentList\";\nimport { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { IntValue } from \"../../../../engine/Value\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { SequenceDivertToResolve } from \"./SequenceDivertToResolve\";\nimport { SequenceType } from \"./SequenceType\";\nimport { Story } from \"../Story\";\nimport { Weave } from \"../Weave\";\n\nexport class Sequence extends ParsedObject {\n private _sequenceDivertsToResolve: SequenceDivertToResolve[] = [];\n\n public sequenceElements: ParsedObject[];\n\n constructor(\n elementContentLists: ContentList[],\n public readonly sequenceType: SequenceType\n ) {\n super();\n\n this.sequenceType = sequenceType;\n this.sequenceElements = [];\n\n for (const elementContentList of elementContentLists) {\n const contentObjs = elementContentList.content;\n let seqElObject: ParsedObject | null = null;\n\n // Don't attempt to create a weave for the sequence element\n // if the content list is empty. Weaves don't like it!\n if (contentObjs === null || contentObjs.length === 0) {\n seqElObject = elementContentList;\n } else {\n seqElObject = new Weave(contentObjs);\n }\n\n this.sequenceElements.push(seqElObject);\n this.AddContent(seqElObject);\n }\n }\n\n get typeName(): string {\n return \"Sequence\";\n }\n\n // Generate runtime code that looks like:\n //\n // chosenIndex = MIN(sequence counter, num elements) e.g. for \"Stopping\"\n // if chosenIndex == 0, divert to s0\n // if chosenIndex == 1, divert to s1 [etc]\n //\n // - s0:\n // \n // divert to no-op\n // - s1:\n // \n // divert to no-op\n // - s2:\n // empty branch if using \"once\"\n // divert to no-op\n //\n // no-op\n //\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n container.visitsShouldBeCounted = true;\n container.countingAtStartOnly = true;\n\n this._sequenceDivertsToResolve = [];\n\n // Get sequence read count\n container.AddContent(RuntimeControlCommand.EvalStart());\n container.AddContent(RuntimeControlCommand.VisitIndex());\n\n const once: boolean = (this.sequenceType & SequenceType.Once) > 0;\n const cycle: boolean = (this.sequenceType & SequenceType.Cycle) > 0;\n const stopping: boolean = (this.sequenceType & SequenceType.Stopping) > 0;\n const shuffle: boolean = (this.sequenceType & SequenceType.Shuffle) > 0;\n\n let seqBranchCount = this.sequenceElements.length;\n if (once) {\n seqBranchCount += 1;\n }\n\n // Chosen sequence index:\n // - Stopping: take the MIN(read count, num elements - 1)\n // - Once: take the MIN(read count, num elements)\n // (the last one being empty)\n if (stopping || once) {\n //var limit = stopping ? seqBranchCount-1 : seqBranchCount;\n container.AddContent(new IntValue(seqBranchCount - 1));\n container.AddContent(NativeFunctionCall.CallWithName(\"MIN\"));\n } else if (cycle) {\n // - Cycle: take (read count % num elements)\n container.AddContent(new IntValue(this.sequenceElements.length));\n container.AddContent(NativeFunctionCall.CallWithName(\"%\"));\n }\n\n // Shuffle\n if (shuffle) {\n // Create point to return to when sequence is complete\n const postShuffleNoOp = RuntimeControlCommand.NoOp();\n\n // When visitIndex == lastIdx, we skip the shuffle\n if (once || stopping) {\n // if( visitIndex == lastIdx ) -> skipShuffle\n const lastIdx = stopping\n ? this.sequenceElements.length - 1\n : this.sequenceElements.length;\n\n container.AddContent(RuntimeControlCommand.Duplicate());\n container.AddContent(new IntValue(lastIdx));\n container.AddContent(NativeFunctionCall.CallWithName(\"==\"));\n\n const skipShuffleDivert = new RuntimeDivert();\n skipShuffleDivert.isConditional = true;\n container.AddContent(skipShuffleDivert);\n\n this.AddDivertToResolve(skipShuffleDivert, postShuffleNoOp);\n }\n\n // This one's a bit more complex! Choose the index at runtime.\n let elementCountToShuffle = this.sequenceElements.length;\n if (stopping) {\n elementCountToShuffle -= 1;\n }\n\n container.AddContent(new IntValue(elementCountToShuffle));\n container.AddContent(RuntimeControlCommand.SequenceShuffleIndex());\n if (once || stopping) {\n container.AddContent(postShuffleNoOp);\n }\n }\n\n container.AddContent(RuntimeControlCommand.EvalEnd());\n\n // Create point to return to when sequence is complete\n const postSequenceNoOp = RuntimeControlCommand.NoOp();\n\n // Each of the main sequence branches, and one extra empty branch if\n // we have a \"once\" sequence.\n for (let elIndex = 0; elIndex < seqBranchCount; elIndex += 1) {\n // This sequence element:\n // if( chosenIndex == this index ) divert to this sequence element\n // duplicate chosen sequence index, since it'll be consumed by \"==\"\n container.AddContent(RuntimeControlCommand.EvalStart());\n container.AddContent(RuntimeControlCommand.Duplicate());\n container.AddContent(new IntValue(elIndex));\n container.AddContent(NativeFunctionCall.CallWithName(\"==\"));\n container.AddContent(RuntimeControlCommand.EvalEnd());\n\n // Divert branch for this sequence element\n const sequenceDivert = new RuntimeDivert();\n sequenceDivert.isConditional = true;\n container.AddContent(sequenceDivert);\n\n let contentContainerForSequenceBranch: RuntimeContainer;\n\n // Generate content for this sequence element\n if (elIndex < this.sequenceElements.length) {\n const el = this.sequenceElements[elIndex];\n contentContainerForSequenceBranch =\n el.runtimeObject as RuntimeContainer;\n } else {\n // Final empty branch for \"once\" sequences\n contentContainerForSequenceBranch = new RuntimeContainer();\n }\n\n contentContainerForSequenceBranch.name = `s${elIndex}`;\n contentContainerForSequenceBranch.InsertContent(\n RuntimeControlCommand.PopEvaluatedValue(),\n 0\n );\n\n // When sequence element is complete, divert back to end of sequence\n const seqBranchCompleteDivert = new RuntimeDivert();\n contentContainerForSequenceBranch.AddContent(seqBranchCompleteDivert);\n container.AddToNamedContentOnly(contentContainerForSequenceBranch);\n\n // Save the diverts for reference resolution later (in ResolveReferences)\n this.AddDivertToResolve(\n sequenceDivert,\n contentContainerForSequenceBranch\n );\n this.AddDivertToResolve(seqBranchCompleteDivert, postSequenceNoOp);\n }\n\n container.AddContent(postSequenceNoOp);\n\n return container;\n };\n\n public readonly AddDivertToResolve = (\n divert: RuntimeDivert,\n targetContent: RuntimeObject\n ) => {\n this._sequenceDivertsToResolve.push(\n new SequenceDivertToResolve(divert, targetContent)\n );\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n for (const toResolve of this._sequenceDivertsToResolve) {\n toResolve.divert.targetPath = toResolve.targetContent.path;\n }\n }\n}\n","export enum CustomFlags {\n ParsingString = 0x1,\n TagActive = 0x2,\n}\n","import { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../engine/ControlCommand\";\nimport { Divert } from \"./Divert/Divert\";\nimport { Divert as RuntimeDivert } from \"../../../engine/Divert\";\nimport { DivertTargetValue } from \"../../../engine/Value\";\nimport { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Story } from \"./Story\";\nimport { Void } from \"../../../engine/Void\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\nimport { VariableReference } from \"../../../engine/VariableReference\";\n\nexport class TunnelOnwards extends ParsedObject {\n private _overrideDivertTarget: DivertTargetValue | null = null;\n\n private _divertAfter: Divert | null = null;\n get divertAfter() {\n return this._divertAfter;\n }\n\n set divertAfter(value) {\n this._divertAfter = value;\n if (this._divertAfter) {\n this.AddContent(this._divertAfter);\n }\n }\n\n get typeName(): string {\n return \"TunnelOnwards\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n const container = new RuntimeContainer();\n\n // Set override path for tunnel onwards (or nothing)\n container.AddContent(RuntimeControlCommand.EvalStart());\n\n if (this.divertAfter) {\n // Generate runtime object's generated code and steal the arguments runtime code\n const returnRuntimeObj = this.divertAfter.GenerateRuntimeObject();\n const returnRuntimeContainer = returnRuntimeObj as RuntimeContainer;\n if (returnRuntimeContainer) {\n // Steal all code for generating arguments from the divert\n const args = this.divertAfter.args;\n if (args !== null && args.length > 0) {\n // Steal everything betwen eval start and eval end\n let evalStart = -1;\n let evalEnd = -1;\n for (\n let ii = 0;\n ii < returnRuntimeContainer.content.length;\n ii += 1\n ) {\n const cmd = returnRuntimeContainer.content[\n ii\n ] as RuntimeControlCommand;\n if (cmd) {\n if (\n evalStart == -1 &&\n cmd.commandType === RuntimeControlCommand.CommandType.EvalStart\n ) {\n evalStart = ii;\n } else if (\n cmd.commandType === RuntimeControlCommand.CommandType.EvalEnd\n ) {\n evalEnd = ii;\n }\n }\n }\n\n for (let ii = evalStart + 1; ii < evalEnd; ii += 1) {\n const obj = returnRuntimeContainer.content[ii];\n obj.parent = null; // prevent error of being moved between owners\n container.AddContent(returnRuntimeContainer.content[ii]);\n }\n }\n }\n // Supply the divert target for the tunnel onwards target, either variable or more commonly, the explicit name\n // var returnDivertObj = returnRuntimeObj as Runtime.Divert;\n let returnDivertObj = asOrNull(returnRuntimeObj, RuntimeDivert);\n if (returnDivertObj != null && returnDivertObj.hasVariableTarget) {\n let runtimeVarRef = new VariableReference(\n returnDivertObj.variableDivertName\n );\n container.AddContent(runtimeVarRef);\n } else {\n this._overrideDivertTarget = new DivertTargetValue();\n container.AddContent(this._overrideDivertTarget);\n }\n } else {\n // No divert after tunnel onwards\n container.AddContent(new Void());\n }\n\n container.AddContent(RuntimeControlCommand.EvalEnd());\n container.AddContent(RuntimeControlCommand.PopTunnel());\n\n return container;\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n if (this.divertAfter && this.divertAfter.targetContent) {\n this._overrideDivertTarget!.targetPath =\n this.divertAfter.targetContent.runtimePath;\n }\n }\n\n public toString = (): string => {\n return ` -> ${this._divertAfter}`;\n };\n}\n","import { InkListItem, SerializedInkListItem } from \"./InkList\";\nimport { TryGetResult } from \"./TryGetResult\";\n\nexport class ListDefinition {\n public _name: string;\n public _items: Map | null;\n public _itemNameToValues: Map;\n\n constructor(name: string, items: Map | null) {\n this._name = name || \"\";\n this._items = null;\n this._itemNameToValues = items || new Map();\n }\n get name() {\n return this._name;\n }\n get items() {\n if (this._items == null) {\n this._items = new Map();\n for (let [key, value] of this._itemNameToValues) {\n let item = new InkListItem(this.name, key);\n this._items.set(item.serialized(), value);\n }\n }\n\n return this._items;\n }\n\n public ValueForItem(item: InkListItem) {\n if (!item.itemName) return 0;\n\n let intVal = this._itemNameToValues.get(item.itemName);\n if (typeof intVal !== \"undefined\") return intVal;\n else return 0;\n }\n public ContainsItem(item: InkListItem) {\n if (!item.itemName) return false;\n if (item.originName != this.name) return false;\n\n return this._itemNameToValues.has(item.itemName);\n }\n public ContainsItemWithName(itemName: string) {\n return this._itemNameToValues.has(itemName);\n }\n public TryGetItemWithValue(\n val: number,\n /* out */ item: InkListItem\n ): TryGetResult {\n for (let [key, value] of this._itemNameToValues) {\n if (value == val) {\n item = new InkListItem(this.name, key);\n return { result: item, exists: true };\n }\n }\n\n item = InkListItem.Null;\n return { result: item, exists: false };\n }\n public TryGetValueForItem(\n item: InkListItem,\n /* out */ intVal: number\n ): TryGetResult {\n if (!item.itemName) return { result: 0, exists: false };\n let value = this._itemNameToValues.get(item.itemName);\n\n if (!value) return { result: 0, exists: false };\n return { result: value, exists: true };\n }\n}\n","import { InkList as RuntimeInkList } from \"../../../../engine/InkList\";\nimport { InkListItem as RuntimeInkListItem } from \"../../../../engine/InkList\";\nimport { ListDefinition as RuntimeListDefinition } from \"../../../../engine/ListDefinition\";\nimport { ListElementDefinition } from \"./ListElementDefinition\";\nimport { ListValue } from \"../../../../engine/Value\";\nimport { ParsedObject } from \"../Object\";\nimport { Story } from \"../Story\";\nimport { SymbolType } from \"../SymbolType\";\nimport { VariableAssignment } from \"../Variable/VariableAssignment\";\nimport { Identifier } from \"../Identifier\";\n\nexport class ListDefinition extends ParsedObject {\n public identifier: Identifier | null = null;\n public variableAssignment: VariableAssignment | null = null;\n\n get typeName() {\n return \"ListDefinition\";\n }\n\n private _elementsByName: Map | null = null;\n\n get runtimeListDefinition(): RuntimeListDefinition {\n const allItems: Map = new Map();\n for (const e of this.itemDefinitions) {\n if (!allItems.has(e.name!)) {\n allItems.set(e.name!, e.seriesValue);\n } else {\n this.Error(\n `List '${this.identifier}' contains duplicate items called '${e.name}'`\n );\n }\n }\n\n return new RuntimeListDefinition(this.identifier?.name || \"\", allItems);\n }\n\n public readonly ItemNamed = (\n itemName: string\n ): ListElementDefinition | null => {\n if (this._elementsByName === null) {\n this._elementsByName = new Map();\n\n for (const el of this.itemDefinitions) {\n this._elementsByName.set(el.name!, el);\n }\n }\n\n const foundElement = this._elementsByName.get(itemName) || null;\n\n return foundElement;\n };\n\n constructor(public itemDefinitions: ListElementDefinition[]) {\n super();\n\n let currentValue = 1;\n for (const e of this.itemDefinitions) {\n if (e.explicitValue !== null) {\n currentValue = e.explicitValue;\n }\n\n e.seriesValue = currentValue;\n\n currentValue += 1;\n }\n\n this.AddContent(itemDefinitions as any);\n }\n\n public readonly GenerateRuntimeObject = (): ListValue => {\n const initialValues = new RuntimeInkList();\n for (const itemDef of this.itemDefinitions) {\n if (itemDef.inInitialList) {\n const item = new RuntimeInkListItem(\n this.identifier?.name || null,\n itemDef.name || null\n );\n initialValues.Add(item, itemDef.seriesValue);\n }\n }\n\n // Set origin name, so\n initialValues.SetInitialOriginName(this.identifier?.name || \"\");\n\n return new ListValue(initialValues);\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n context.CheckForNamingCollisions(this, this.identifier!, SymbolType.List);\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"../Expression/Expression\";\nimport { FlowBase } from \"../Flow/FlowBase\";\nimport { ClosestFlowBase } from \"../Flow/ClosestFlowBase\";\nimport { ListDefinition } from \"../List/ListDefinition\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Story } from \"../Story\";\nimport { SymbolType } from \"../SymbolType\";\nimport { VariableAssignment as RuntimeVariableAssignment } from \"../../../../engine/VariableAssignment\";\nimport { VariableReference } from \"./VariableReference\";\nimport { Identifier } from \"../Identifier\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class VariableAssignment extends ParsedObject {\n private _runtimeAssignment: RuntimeVariableAssignment | null = null;\n\n get variableName(): string {\n return this.variableIdentifier.name!;\n }\n public readonly variableIdentifier: Identifier;\n public readonly expression: Expression | null = null;\n public readonly listDefinition: ListDefinition | null = null;\n public readonly isGlobalDeclaration: boolean;\n public readonly isNewTemporaryDeclaration: boolean;\n\n get typeName() {\n if (this.isNewTemporaryDeclaration) {\n return \"temp\";\n } else if (this.isGlobalDeclaration) {\n if (this.listDefinition !== null) {\n return \"LIST\";\n }\n return \"VAR\";\n }\n\n return \"variable assignment\";\n }\n\n get isDeclaration(): boolean {\n return this.isGlobalDeclaration || this.isNewTemporaryDeclaration;\n }\n\n constructor({\n assignedExpression,\n isGlobalDeclaration,\n isTemporaryNewDeclaration,\n listDef,\n variableIdentifier,\n }: {\n readonly assignedExpression?: Expression;\n readonly isGlobalDeclaration?: boolean;\n readonly isTemporaryNewDeclaration?: boolean;\n readonly listDef?: ListDefinition;\n readonly variableIdentifier: Identifier;\n }) {\n super();\n\n this.variableIdentifier = variableIdentifier;\n this.isGlobalDeclaration = Boolean(isGlobalDeclaration);\n this.isNewTemporaryDeclaration = Boolean(isTemporaryNewDeclaration);\n\n // Defensive programming in case parsing of assignedExpression failed\n if (listDef instanceof ListDefinition) {\n this.listDefinition = this.AddContent(listDef) as ListDefinition;\n this.listDefinition.variableAssignment = this;\n\n // List definitions are always global\n this.isGlobalDeclaration = true;\n } else if (assignedExpression) {\n this.expression = this.AddContent(assignedExpression) as Expression;\n }\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject | null => {\n let newDeclScope: FlowBase | null | undefined = null;\n if (this.isGlobalDeclaration) {\n newDeclScope = this.story;\n } else if (this.isNewTemporaryDeclaration) {\n newDeclScope = ClosestFlowBase(this);\n }\n\n if (newDeclScope) {\n newDeclScope.AddNewVariableDeclaration(this);\n }\n\n // Global declarations don't generate actual procedural\n // runtime objects, but instead add a global variable to the story itself.\n // The story then initialises them all in one go at the start of the game.\n if (this.isGlobalDeclaration) {\n return null;\n }\n\n const container = new RuntimeContainer();\n\n // The expression's runtimeObject is actually another nested container\n if (this.expression) {\n container.AddContent(this.expression.runtimeObject);\n } else if (this.listDefinition) {\n container.AddContent(this.listDefinition.runtimeObject);\n }\n\n this._runtimeAssignment = new RuntimeVariableAssignment(\n this.variableName,\n this.isNewTemporaryDeclaration\n );\n\n container.AddContent(this._runtimeAssignment);\n\n return container;\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n // List definitions are checked for conflicts separately\n if (this.isDeclaration && this.listDefinition === null) {\n context.CheckForNamingCollisions(\n this,\n this.variableIdentifier,\n this.isGlobalDeclaration ? SymbolType.Var : SymbolType.Temp\n );\n }\n\n // Initial VAR x = [intialValue] declaration, not re-assignment\n if (this.isGlobalDeclaration) {\n const variableReference = asOrNull(this.expression, VariableReference);\n if (\n variableReference &&\n !variableReference.isConstantReference &&\n !variableReference.isListItemReference\n ) {\n this.Error(\n \"global variable assignments cannot refer to other variables, only literal values, constants and list items\"\n );\n }\n }\n\n if (!this.isNewTemporaryDeclaration) {\n const resolvedVarAssignment = context.ResolveVariableWithName(\n this.variableName,\n this\n );\n\n if (!resolvedVarAssignment.found) {\n if (this.variableName in this.story.constants) {\n this.Error(\n `Can't re-assign to a constant (do you need to use VAR when declaring '${this.variableName}'?)`,\n this\n );\n } else {\n this.Error(\n `Variable could not be found to assign to: '${this.variableName}'`,\n this\n );\n }\n }\n\n // A runtime assignment may not have been generated if it's the initial global declaration,\n // since these are hoisted out and handled specially in Story.ExportRuntime.\n if (this._runtimeAssignment) {\n this._runtimeAssignment.isGlobal = resolvedVarAssignment.isGlobal;\n }\n }\n }\n\n public readonly toString = (): string =>\n `${\n this.isGlobalDeclaration\n ? \"VAR\"\n : this.isNewTemporaryDeclaration\n ? \"~ temp\"\n : \"\"\n } ${this.variableName}`;\n}\n","import { AuthorWarning } from \"./AuthorWarning\";\nimport { Choice } from \"./Choice\";\nimport { Conditional } from \"./Conditional/Conditional\";\nimport { ConstantDeclaration } from \"./Declaration/ConstantDeclaration\";\nimport { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { Divert } from \"./Divert/Divert\";\nimport { Divert as RuntimeDivert } from \"../../../engine/Divert\";\nimport { DivertTarget } from \"./Divert/DivertTarget\";\nimport { FlowBase } from \"./Flow/FlowBase\";\nimport { Gather } from \"./Gather/Gather\";\nimport { GatherPointToResolve } from \"./Gather/GatherPointToResolve\";\nimport { IWeavePoint } from \"./IWeavePoint\";\nimport { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Sequence } from \"./Sequence/Sequence\";\nimport { Story } from \"./Story\";\nimport { Text } from \"./Text\";\nimport { TunnelOnwards } from \"./TunnelOnwards\";\nimport { VariableAssignment } from \"./Variable/VariableAssignment\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\n\ntype BadTerminationHandler = (terminatingObj: ParsedObject) => void;\n\n// Used by the FlowBase when constructing the weave flow from\n// a flat list of content objects.\nexport class Weave extends ParsedObject {\n // Containers can be chained as multiple gather points\n // get created as the same indentation level.\n // rootContainer is always the first in the chain, while\n // currentContainer is the latest.\n get rootContainer(): RuntimeContainer {\n if (!this._rootContainer) {\n this._rootContainer = this.GenerateRuntimeObject();\n }\n\n return this._rootContainer;\n }\n\n // Keep track of previous weave point (Choice or Gather)\n // at the current indentation level:\n // - to add ordinary content to be nested under it\n // - to add nested content under it when it's indented\n // - to remove it from the list of loose ends when\n // - it has indented content since it's no longer a loose end\n // - it's a gather and it has a choice added to it\n public previousWeavePoint: IWeavePoint | null = null;\n public addContentToPreviousWeavePoint: boolean = false;\n\n // Used for determining whether the next Gather should auto-enter\n public hasSeenChoiceInSection: boolean = false;\n\n public currentContainer: RuntimeContainer | null = null;\n public baseIndentIndex: number;\n\n private _unnamedGatherCount: number = 0;\n private _choiceCount: number = 0;\n private _rootContainer: RuntimeContainer | null = null;\n private _namedWeavePoints: Map = new Map();\n get namedWeavePoints() {\n return this._namedWeavePoints;\n }\n\n // Loose ends are:\n // - Choices or Gathers that need to be joined up\n // - Explicit Divert to gather points (i.e. \"->\" without a target)\n public looseEnds: IWeavePoint[] = [];\n\n public gatherPointsToResolve: GatherPointToResolve[] = [];\n\n get lastParsedSignificantObject(): ParsedObject | null {\n if (this.content.length === 0) {\n return null;\n }\n\n // Don't count extraneous newlines or VAR/CONST declarations,\n // since they're \"empty\" statements outside of the main flow.\n let lastObject: ParsedObject | null = null;\n for (let ii = this.content.length - 1; ii >= 0; --ii) {\n lastObject = this.content[ii];\n\n let lastText = asOrNull(lastObject, Text);\n if (lastText && lastText.text === \"\\n\") {\n continue;\n }\n\n if (this.IsGlobalDeclaration(lastObject)) {\n continue;\n }\n\n break;\n }\n\n const lastWeave = asOrNull(lastObject, Weave);\n if (lastWeave) {\n lastObject = lastWeave.lastParsedSignificantObject;\n }\n\n return lastObject;\n }\n\n constructor(cont: ParsedObject[], indentIndex: number = -1) {\n super();\n\n if (indentIndex == -1) {\n this.baseIndentIndex = this.DetermineBaseIndentationFromContent(cont);\n } else {\n this.baseIndentIndex = indentIndex;\n }\n\n this.AddContent(cont);\n\n this.ConstructWeaveHierarchyFromIndentation();\n }\n\n get typeName(): string {\n return \"Weave\";\n }\n\n public readonly ResolveWeavePointNaming = (): void => {\n const namedWeavePoints = [\n ...this.FindAll(Gather)(\n (w) => !(w.name === null || w.name === undefined)\n ),\n ...this.FindAll(Choice)(\n (w) => !(w.name === null || w.name === undefined)\n ),\n ];\n this._namedWeavePoints = new Map();\n\n for (const weavePoint of namedWeavePoints) {\n // Check for weave point naming collisions\n const existingWeavePoint: IWeavePoint | null | undefined =\n this.namedWeavePoints.get(weavePoint.identifier?.name || \"\");\n\n if (existingWeavePoint) {\n const typeName =\n existingWeavePoint instanceof Gather ? \"gather\" : \"choice\";\n const existingObj: ParsedObject = existingWeavePoint;\n\n this.Error(\n `A ${typeName} with the same label name '${\n weavePoint.name\n }' already exists in this context on line ${\n existingObj.debugMetadata\n ? existingObj.debugMetadata.startLineNumber\n : \"NO DEBUG METADATA AVAILABLE\"\n }`,\n weavePoint as ParsedObject\n );\n }\n if (weavePoint.identifier?.name) {\n this.namedWeavePoints.set(weavePoint.identifier?.name, weavePoint);\n }\n }\n };\n\n public readonly ConstructWeaveHierarchyFromIndentation = (): void => {\n // Find nested indentation and convert to a proper object hierarchy\n // (i.e. indented content is replaced with a Weave object that contains\n // that nested content)\n let contentIdx = 0;\n while (contentIdx < this.content.length) {\n const obj: ParsedObject = this.content[contentIdx];\n\n // Choice or Gather\n if (obj instanceof Choice || obj instanceof Gather) {\n const weavePoint: IWeavePoint = obj;\n const weaveIndentIdx = weavePoint.indentationDepth - 1;\n\n // Inner level indentation - recurse\n if (weaveIndentIdx > this.baseIndentIndex) {\n // Step through content until indent jumps out again\n let innerWeaveStartIdx = contentIdx;\n while (contentIdx < this.content.length) {\n const innerWeaveObj =\n asOrNull(this.content[contentIdx], Choice) ||\n asOrNull(this.content[contentIdx], Gather);\n if (innerWeaveObj !== null) {\n const innerIndentIdx = innerWeaveObj.indentationDepth - 1;\n if (innerIndentIdx <= this.baseIndentIndex) {\n break;\n }\n }\n\n contentIdx += 1;\n }\n\n const weaveContentCount = contentIdx - innerWeaveStartIdx;\n const weaveContent = this.content.slice(\n innerWeaveStartIdx,\n innerWeaveStartIdx + weaveContentCount\n );\n\n this.content.splice(innerWeaveStartIdx, weaveContentCount);\n\n const weave = new Weave(weaveContent, weaveIndentIdx);\n this.InsertContent(innerWeaveStartIdx, weave);\n\n // Continue iteration from this point\n contentIdx = innerWeaveStartIdx;\n }\n }\n\n contentIdx += 1;\n }\n };\n\n // When the indentation wasn't told to us at construction time using\n // a choice point with a known indentation level, we may be told to\n // determine the indentation level by incrementing from our closest ancestor.\n public readonly DetermineBaseIndentationFromContent = (\n contentList: ParsedObject[]\n ): number => {\n for (const obj of contentList) {\n if (obj instanceof Choice || obj instanceof Gather) {\n return obj.indentationDepth - 1;\n }\n }\n\n // No weave points, so it doesn't matter\n return 0;\n };\n\n public readonly GenerateRuntimeObject = (): RuntimeContainer => {\n this._rootContainer = new RuntimeContainer();\n this.currentContainer = this._rootContainer;\n this.looseEnds = [];\n this.gatherPointsToResolve = [];\n\n // Iterate through content for the block at this level of indentation\n // - Normal content is nested under Choices and Gathers\n // - Blocks that are further indented cause recursion\n // - Keep track of loose ends so that they can be diverted to Gathers\n for (const obj of this.content) {\n // Choice or Gather\n if (obj instanceof Choice || obj instanceof Gather) {\n this.AddRuntimeForWeavePoint(obj as IWeavePoint);\n } else {\n // Non-weave point\n if (obj instanceof Weave) {\n // Nested weave\n const weave = obj;\n this.AddRuntimeForNestedWeave(weave);\n this.gatherPointsToResolve.splice(\n 0,\n 0,\n ...weave.gatherPointsToResolve\n );\n } else {\n // Other object\n // May be complex object that contains statements - e.g. a multi-line conditional\n this.AddGeneralRuntimeContent(obj.runtimeObject);\n }\n }\n }\n\n // Pass any loose ends up the hierarhcy\n this.PassLooseEndsToAncestors();\n\n return this._rootContainer;\n };\n\n // Found gather point:\n // - gather any loose ends\n // - set the gather as the main container to dump new content in\n public readonly AddRuntimeForGather = (gather: Gather): void => {\n // Determine whether this Gather should be auto-entered:\n // - It is auto-entered if there were no choices in the last section\n // - A section is \"since the previous gather\" - so reset now\n const autoEnter = !this.hasSeenChoiceInSection;\n this.hasSeenChoiceInSection = false;\n\n const gatherContainer = gather.runtimeContainer;\n\n if (!gather.name) {\n // Use disallowed character so it's impossible to have a name collision\n gatherContainer.name = `g-${this._unnamedGatherCount}`;\n this._unnamedGatherCount += 1;\n }\n\n if (autoEnter) {\n if (!this.currentContainer) {\n throw new Error();\n }\n\n // Auto-enter: include in main content\n this.currentContainer.AddContent(gatherContainer);\n } else {\n // Don't auto-enter:\n // Add this gather to the main content, but only accessible\n // by name so that it isn't stepped into automatically, but only via\n // a divert from a loose end.\n this.rootContainer.AddToNamedContentOnly(gatherContainer);\n }\n\n // Consume loose ends: divert them to this gather\n for (const looseEndWeavePoint of this.looseEnds) {\n const looseEnd = looseEndWeavePoint as ParsedObject;\n\n // Skip gather loose ends that are at the same level\n // since they'll be handled by the auto-enter code below\n // that only jumps into the gather if (current runtime choices == 0)\n if (looseEnd instanceof Gather) {\n const prevGather = looseEnd;\n if (prevGather.indentationDepth == gather.indentationDepth) {\n continue;\n }\n }\n\n let divert: RuntimeDivert | null = null;\n if (looseEnd instanceof Divert) {\n divert = looseEnd.runtimeObject as RuntimeDivert;\n } else {\n divert = new RuntimeDivert();\n const looseWeavePoint = looseEnd as IWeavePoint;\n if (!looseWeavePoint.runtimeContainer) {\n throw new Error();\n }\n\n looseWeavePoint.runtimeContainer.AddContent(divert);\n }\n\n // Pass back knowledge of this loose end being diverted\n // to the FlowBase so that it can maintain a list of them,\n // and resolve the divert references later\n this.gatherPointsToResolve.push(\n new GatherPointToResolve(divert, gatherContainer)\n );\n }\n\n this.looseEnds = [];\n\n // Replace the current container itself\n this.currentContainer = gatherContainer;\n };\n\n public readonly AddRuntimeForWeavePoint = (weavePoint: IWeavePoint): void => {\n // Current level Gather\n if (weavePoint instanceof Gather) {\n this.AddRuntimeForGather(weavePoint);\n }\n\n // Current level choice\n else if (weavePoint instanceof Choice) {\n if (!this.currentContainer) {\n throw new Error();\n }\n\n // Gathers that contain choices are no longer loose ends\n // (same as when weave points get nested content)\n if (this.previousWeavePoint instanceof Gather) {\n this.looseEnds.splice(\n this.looseEnds.indexOf(this.previousWeavePoint),\n 1\n );\n }\n\n // Add choice point content\n const choice = weavePoint; //, Choice);\n\n this.currentContainer.AddContent(choice.runtimeObject);\n if (!choice.innerContentContainer) {\n throw new Error();\n } //guaranteed not to happen\n\n // Add choice's inner content to self\n choice.innerContentContainer.name = `c-${this._choiceCount}`;\n this.currentContainer.AddToNamedContentOnly(choice.innerContentContainer);\n this._choiceCount += 1;\n\n this.hasSeenChoiceInSection = true;\n }\n\n // Keep track of loose ends\n this.addContentToPreviousWeavePoint = false; // default\n if (this.WeavePointHasLooseEnd(weavePoint)) {\n this.looseEnds.push(weavePoint);\n\n const looseChoice = asOrNull(weavePoint, Choice);\n if (looseChoice) {\n this.addContentToPreviousWeavePoint = true;\n }\n }\n\n this.previousWeavePoint = weavePoint;\n };\n\n // Add nested block at a greater indentation level\n public readonly AddRuntimeForNestedWeave = (nestedResult: Weave): void => {\n // Add this inner block to current container\n // (i.e. within the main container, or within the last defined Choice/Gather)\n this.AddGeneralRuntimeContent(nestedResult.rootContainer);\n\n // Now there's a deeper indentation level, the previous weave point doesn't\n // count as a loose end (since it will have content to go to)\n if (this.previousWeavePoint !== null) {\n this.looseEnds.splice(this.looseEnds.indexOf(this.previousWeavePoint), 1);\n\n this.addContentToPreviousWeavePoint = false;\n }\n };\n\n // Normal content gets added into the latest Choice or Gather by default,\n // unless there hasn't been one yet.\n public readonly AddGeneralRuntimeContent = (content: RuntimeObject): void => {\n // Content is allowed to evaluate runtimeObject to null\n // (e.g. AuthorWarning, which doesn't make it into the runtime)\n if (content === null) {\n return;\n }\n\n if (this.addContentToPreviousWeavePoint) {\n if (\n !this.previousWeavePoint ||\n !this.previousWeavePoint.runtimeContainer\n ) {\n throw new Error();\n }\n\n this.previousWeavePoint.runtimeContainer.AddContent(content);\n } else {\n if (!this.currentContainer) {\n throw new Error();\n }\n\n this.currentContainer.AddContent(content);\n }\n };\n\n public readonly PassLooseEndsToAncestors = () => {\n if (this.looseEnds.length === 0) {\n return;\n }\n\n // Search for Weave ancestor to pass loose ends to for gathering.\n // There are two types depending on whether the current weave\n // is separated by a conditional or sequence.\n // - An \"inner\" weave is one that is directly connected to the current\n // weave - i.e. you don't have to pass through a conditional or\n // sequence to get to it. We're allowed to pass all loose ends to\n // one of these.\n // - An \"outer\" weave is one that is outside of a conditional/sequence\n // that the current weave is nested within. We're only allowed to\n // pass gathers (i.e. 'normal flow') loose ends up there, not normal\n // choices. The rule is that choices have to be diverted explicitly\n // by the author since it's ambiguous where flow should go otherwise.\n //\n // e.g.:\n //\n // - top <- e.g. outer weave\n // {true:\n // * choice <- e.g. inner weave\n // * * choice 2\n // more content <- e.g. current weave\n // * choice 2\n // }\n // - more of outer weave\n //\n let closestInnerWeaveAncestor: Weave | null = null;\n let closestOuterWeaveAncestor: Weave | null = null;\n\n // Find inner and outer ancestor weaves as defined above.\n let nested = false;\n for (\n let ancestor = this.parent;\n ancestor !== null;\n ancestor = ancestor.parent\n ) {\n // Found ancestor?\n const weaveAncestor = asOrNull(ancestor, Weave);\n if (weaveAncestor) {\n if (!nested && closestInnerWeaveAncestor === null) {\n closestInnerWeaveAncestor = weaveAncestor;\n }\n\n if (nested && closestOuterWeaveAncestor === null) {\n closestOuterWeaveAncestor = weaveAncestor;\n }\n }\n\n // Weaves nested within Sequences or Conditionals are\n // \"sealed\" - any loose ends require explicit diverts.\n if (ancestor instanceof Sequence || ancestor instanceof Conditional) {\n nested = true;\n }\n }\n\n // No weave to pass loose ends to at all?\n if (\n closestInnerWeaveAncestor === null &&\n closestOuterWeaveAncestor === null\n ) {\n return;\n }\n\n // Follow loose end passing logic as defined above\n for (let ii = this.looseEnds.length - 1; ii >= 0; ii -= 1) {\n const looseEnd = this.looseEnds[ii];\n let received = false;\n\n if (nested) {\n // This weave is nested within a conditional or sequence:\n // - choices can only be passed up to direct ancestor (\"inner\") weaves\n // - gathers can be passed up to either, but favour the closer (inner) weave\n // if there is one\n if (looseEnd instanceof Choice && closestInnerWeaveAncestor !== null) {\n closestInnerWeaveAncestor.ReceiveLooseEnd(looseEnd);\n received = true;\n } else if (!(looseEnd instanceof Choice)) {\n const receivingWeave =\n closestInnerWeaveAncestor || closestOuterWeaveAncestor;\n if (receivingWeave !== null) {\n receivingWeave.ReceiveLooseEnd(looseEnd);\n received = true;\n }\n }\n } else {\n // No nesting, all loose ends can be safely passed up\n if (closestInnerWeaveAncestor?.hasOwnProperty(\"ReceiveLooseEnd\")) {\n closestInnerWeaveAncestor!.ReceiveLooseEnd(looseEnd);\n }\n received = true;\n }\n\n if (received) {\n this.looseEnds.splice(ii, 1);\n }\n }\n };\n\n public readonly ReceiveLooseEnd = (childWeaveLooseEnd: IWeavePoint): void => {\n this.looseEnds.push(childWeaveLooseEnd);\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n // Check that choices nested within conditionals and sequences are terminated\n if (this.looseEnds !== null && this.looseEnds.length > 0) {\n let isNestedWeave = false;\n for (\n let ancestor = this.parent;\n ancestor !== null;\n ancestor = ancestor.parent\n ) {\n if (ancestor instanceof Sequence || ancestor instanceof Conditional) {\n isNestedWeave = true;\n break;\n }\n }\n\n if (isNestedWeave) {\n this.ValidateTermination(this.BadNestedTerminationHandler);\n }\n }\n\n for (const gatherPoint of this.gatherPointsToResolve) {\n gatherPoint.divert.targetPath = gatherPoint.targetRuntimeObj.path;\n }\n\n this.CheckForWeavePointNamingCollisions();\n }\n\n public readonly WeavePointNamed = (name: string): IWeavePoint | null => {\n if (!this.namedWeavePoints) {\n return null;\n }\n\n let weavePointResult: IWeavePoint | null | undefined =\n this.namedWeavePoints.get(name);\n if (weavePointResult) {\n return weavePointResult;\n }\n\n return null;\n };\n\n // Global VARs and CONSTs are treated as \"outside of the flow\"\n // when iterating over content that follows loose ends\n public readonly IsGlobalDeclaration = (obj: ParsedObject) => {\n const varAss = asOrNull(obj, VariableAssignment);\n if (varAss && varAss.isGlobalDeclaration && varAss.isDeclaration) {\n return true;\n }\n\n const constDecl = asOrNull(obj, ConstantDeclaration);\n if (constDecl) {\n return true;\n }\n\n return false;\n };\n\n // While analysing final loose ends, we look to see whether there\n // are any diverts etc which choices etc divert from\n public readonly ContentThatFollowsWeavePoint = (\n weavePoint: IWeavePoint\n ): ParsedObject[] => {\n const returned = [];\n const obj = weavePoint as ParsedObject;\n\n // Inner content first (e.g. for a choice)\n if (obj.content !== null) {\n for (const contentObj of obj.content) {\n // Global VARs and CONSTs are treated as \"outside of the flow\"\n if (this.IsGlobalDeclaration(contentObj)) {\n continue;\n }\n\n returned.push(contentObj);\n }\n }\n\n const parentWeave = asOrNull(obj.parent, Weave);\n if (parentWeave === null) {\n throw new Error(\"Expected weave point parent to be weave?\");\n }\n\n const weavePointIdx = parentWeave.content.indexOf(obj);\n for (let ii = weavePointIdx + 1; ii < parentWeave.content.length; ii += 1) {\n const laterObj = parentWeave.content[ii];\n\n // Global VARs and CONSTs are treated as \"outside of the flow\"\n if (this.IsGlobalDeclaration(laterObj)) {\n continue;\n }\n\n // End of the current flow\n // if (laterObj instanceof IWeavePoint) // cannot test on interface in ts\n if (laterObj instanceof Choice || laterObj instanceof Gather) {\n break;\n }\n\n // Other weaves will be have their own loose ends\n if (laterObj instanceof Weave) {\n break;\n }\n\n returned.push(laterObj);\n }\n\n return returned;\n };\n\n public readonly ValidateTermination = (\n badTerminationHandler: BadTerminationHandler\n ): void => {\n // Don't worry if the last object in the flow is a \"TODO\",\n // even if there are other loose ends in other places\n if (this.lastParsedSignificantObject instanceof AuthorWarning) {\n return;\n }\n\n // By now, any sub-weaves will have passed loose ends up to the root weave (this).\n // So there are 2 possible situations:\n // - There are loose ends from somewhere in the flow.\n // These aren't necessarily \"real\" loose ends - they're weave points\n // that don't connect to any lower weave points, so we just\n // have to check that they terminate properly.\n // - This weave is just a list of content with no actual weave points,\n // so we just need to check that the list of content terminates.\n\n const hasLooseEnds: boolean =\n this.looseEnds !== null && this.looseEnds.length > 0;\n\n if (hasLooseEnds) {\n for (const looseEnd of this.looseEnds) {\n const looseEndFlow = this.ContentThatFollowsWeavePoint(looseEnd);\n this.ValidateFlowOfObjectsTerminates(\n looseEndFlow,\n looseEnd as ParsedObject,\n badTerminationHandler\n );\n }\n } else {\n // No loose ends... is there any inner weaving at all?\n // If not, make sure the single content stream is terminated correctly\n //\n // If there's any actual weaving, assume that content is\n // terminated correctly since we would've had a loose end otherwise\n for (const obj of this.content) {\n if (obj instanceof Choice || obj instanceof Divert) {\n return;\n }\n }\n\n // Straight linear flow? Check it terminates\n this.ValidateFlowOfObjectsTerminates(\n this.content,\n this,\n badTerminationHandler\n );\n }\n };\n\n readonly BadNestedTerminationHandler: BadTerminationHandler = (\n terminatingObj\n ) => {\n let conditional: Conditional | null = null;\n for (\n let ancestor = terminatingObj.parent;\n ancestor !== null;\n ancestor = ancestor.parent\n ) {\n if (ancestor instanceof Sequence || ancestor instanceof Conditional) {\n conditional = asOrNull(ancestor, Conditional);\n break;\n }\n }\n\n let errorMsg =\n \"Choices nested in conditionals or sequences need to explicitly divert afterwards.\";\n\n // Tutorialise proper choice syntax if this looks like a single choice within a condition, e.g.\n // { condition:\n // * choice\n // }\n if (conditional !== null) {\n let numChoices = conditional.FindAll(Choice)().length;\n if (numChoices === 1) {\n errorMsg = `Choices with conditions should be written: '* {condition} choice'. Otherwise, ${errorMsg.toLowerCase()}`;\n }\n }\n\n this.Error(errorMsg, terminatingObj);\n };\n\n public readonly ValidateFlowOfObjectsTerminates = (\n objFlow: ParsedObject[],\n defaultObj: ParsedObject,\n badTerminationHandler: BadTerminationHandler\n ) => {\n let terminated = false;\n let terminatingObj: ParsedObject = defaultObj;\n for (const flowObj of objFlow) {\n const divert = flowObj.Find(Divert)(\n (d) =>\n !d.isThread &&\n !d.isTunnel &&\n !d.isFunctionCall &&\n !(d.parent instanceof DivertTarget)\n );\n\n if (divert !== null) {\n terminated = true;\n }\n\n if (flowObj.Find(TunnelOnwards)() != null) {\n terminated = true;\n break;\n }\n\n terminatingObj = flowObj;\n }\n\n if (!terminated) {\n // Author has left a note to self here - clearly we don't need\n // to leave them with another warning since they know what they're doing.\n if (terminatingObj instanceof AuthorWarning) {\n return;\n }\n\n badTerminationHandler(terminatingObj);\n }\n };\n\n public readonly WeavePointHasLooseEnd = (\n weavePoint: IWeavePoint\n ): boolean => {\n // No content, must be a loose end.\n if (weavePoint.content === null) {\n return true;\n }\n\n // If a weave point is diverted from, it doesn't have a loose end.\n // Detect a divert object within a weavePoint's main content\n // Work backwards since we're really interested in the end,\n // although it doesn't actually make a difference!\n // (content after a divert will simply be inaccessible)\n for (let ii = weavePoint.content.length - 1; ii >= 0; --ii) {\n let innerDivert = asOrNull(weavePoint.content[ii], Divert);\n if (innerDivert) {\n const willReturn =\n innerDivert.isThread ||\n innerDivert.isTunnel ||\n innerDivert.isFunctionCall;\n if (!willReturn) {\n return false;\n }\n }\n }\n\n return true;\n };\n\n // Enforce rule that weave points must not have the same\n // name as any stitches or knots upwards in the hierarchy\n public readonly CheckForWeavePointNamingCollisions = (): void => {\n if (!this.namedWeavePoints) {\n return;\n }\n\n const ancestorFlows = [];\n for (const obj of this.ancestry) {\n const flow = asOrNull(obj, FlowBase);\n if (flow) {\n ancestorFlows.push(flow);\n } else {\n break;\n }\n }\n\n for (const [weavePointName, weavePoint] of this.namedWeavePoints) {\n for (const flow of ancestorFlows) {\n // Shallow search\n const otherContentWithName =\n flow.ContentWithNameAtLevel(weavePointName);\n if (otherContentWithName && otherContentWithName !== weavePoint) {\n const errorMsg = `${weavePoint.GetType()} '${weavePointName}' has the same label name as a ${otherContentWithName.GetType()} (on ${\n otherContentWithName.debugMetadata\n })`;\n this.Error(errorMsg, weavePoint);\n }\n }\n }\n };\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { Divert as RuntimeDivert } from \"../../../../engine/Divert\";\nimport { Expression } from \"../Expression/Expression\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\nimport { StringValue } from \"../../../../engine/Value\";\nimport { Story } from \"../Story\";\nimport { Text } from \"../Text\";\nimport { Weave } from \"../Weave\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class ConditionalSingleBranch extends ParsedObject {\n public _contentContainer: RuntimeContainer | null = null;\n public _conditionalDivert: RuntimeDivert | null = null;\n public _ownExpression: Expression | null = null;\n public _innerWeave: Weave | null = null;\n // bool condition, e.g.:\n // { 5 == 4:\n // - the true branch\n // - the false branch\n // }\n public isTrueBranch: boolean = false;\n\n // When each branch has its own expression like a switch statement,\n // this is non-null. e.g.\n // { x:\n // - 4: the value of x is four (ownExpression is the value 4)\n // - 3: the value of x is three\n // }\n get ownExpression() {\n return this._ownExpression;\n }\n\n set ownExpression(value) {\n this._ownExpression = value;\n if (this._ownExpression) {\n this.AddContent(this._ownExpression);\n }\n }\n\n // In the above example, match equality of x with 4 for the first branch.\n // This is as opposed to simply evaluating boolean equality for each branch,\n // example when shouldMatchEquality is FALSE:\n // {\n // 3 > 2: This will happen\n // 2 > 3: This won't happen\n // }\n public matchingEquality: boolean = false;\n\n public isElse: boolean = false;\n public isInline: boolean = false;\n\n public returnDivert: RuntimeDivert | null = null;\n\n constructor(content?: ParsedObject[] | null | undefined) {\n super();\n\n // Branches are allowed to be empty\n if (content) {\n this._innerWeave = new Weave(content);\n this.AddContent(this._innerWeave);\n }\n }\n\n get typeName(): string {\n return \"ConditionalSingleBranch\";\n }\n\n // Runtime content can be summarised as follows:\n // - Evaluate an expression if necessary to branch on\n // - Branch to a named container if true\n // - Divert back to main flow\n // (owner Conditional is in control of this target point)\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n // Check for common mistake, of putting \"else:\" instead of \"- else:\"\n if (this._innerWeave) {\n for (const c of this._innerWeave.content) {\n const text = asOrNull(c, Text);\n if (text) {\n // Don't need to trim at the start since the parser handles that already\n if (text.text.startsWith(\"else:\")) {\n this.Warning(\n \"Saw the text 'else:' which is being treated as content. Did you mean '- else:'?\",\n text\n );\n }\n }\n }\n }\n\n const container = new RuntimeContainer();\n\n // Are we testing against a condition that's used for more than just this\n // branch? If so, the first thing we need to do is replicate the value that's\n // on the evaluation stack so that we don't fully consume it, in case other\n // branches need to use it.\n const duplicatesStackValue: boolean = this.matchingEquality && !this.isElse;\n\n if (duplicatesStackValue) {\n container.AddContent(RuntimeControlCommand.Duplicate());\n }\n\n this._conditionalDivert = new RuntimeDivert();\n\n // else clause is unconditional catch-all, otherwise the divert is conditional\n this._conditionalDivert.isConditional = !this.isElse;\n\n // Need extra evaluation?\n if (!this.isTrueBranch && !this.isElse) {\n const needsEval: boolean = this.ownExpression !== null;\n if (needsEval) {\n container.AddContent(RuntimeControlCommand.EvalStart());\n }\n\n if (this.ownExpression) {\n this.ownExpression.GenerateIntoContainer(container);\n }\n\n // Uses existing duplicated value\n if (this.matchingEquality) {\n container.AddContent(NativeFunctionCall.CallWithName(\"==\"));\n }\n\n if (needsEval) {\n container.AddContent(RuntimeControlCommand.EvalEnd());\n }\n }\n\n // Will pop from stack if conditional\n container.AddContent(this._conditionalDivert);\n\n this._contentContainer = this.GenerateRuntimeForContent();\n this._contentContainer.name = \"b\";\n\n // Multi-line conditionals get a newline at the start of each branch\n // (as opposed to the start of the multi-line conditional since the condition\n // may evaluate to false.)\n if (!this.isInline) {\n this._contentContainer.InsertContent(new StringValue(\"\\n\"), 0);\n }\n\n if (duplicatesStackValue || (this.isElse && this.matchingEquality)) {\n this._contentContainer.InsertContent(\n RuntimeControlCommand.PopEvaluatedValue(),\n 0\n );\n }\n\n container.AddToNamedContentOnly(this._contentContainer);\n\n this.returnDivert = new RuntimeDivert();\n this._contentContainer.AddContent(this.returnDivert);\n\n return container;\n };\n\n public readonly GenerateRuntimeForContent = (): RuntimeContainer => {\n // Empty branch - create empty container\n if (this._innerWeave === null) {\n return new RuntimeContainer();\n }\n\n return this._innerWeave.rootContainer;\n };\n\n public ResolveReferences(context: Story): void {\n if (!this._conditionalDivert || !this._contentContainer) {\n throw new Error();\n }\n\n this._conditionalDivert.targetPath = this._contentContainer.path;\n super.ResolveReferences(context);\n }\n}\n","export class DebugMetadata {\n public startLineNumber: number = 0;\n public endLineNumber: number = 0;\n public startCharacterNumber: number = 0;\n public endCharacterNumber: number = 0;\n public fileName: string | null = null;\n public sourceName: string | null = null;\n\n public Merge(dm: DebugMetadata) {\n let newDebugMetadata = new DebugMetadata();\n\n newDebugMetadata.fileName = this.fileName;\n newDebugMetadata.sourceName = this.sourceName;\n\n if (this.startLineNumber < dm.startLineNumber) {\n newDebugMetadata.startLineNumber = this.startLineNumber;\n newDebugMetadata.startCharacterNumber = this.startCharacterNumber;\n } else if (this.startLineNumber > dm.startLineNumber) {\n newDebugMetadata.startLineNumber = dm.startLineNumber;\n newDebugMetadata.startCharacterNumber = dm.startCharacterNumber;\n } else {\n newDebugMetadata.startLineNumber = this.startLineNumber;\n newDebugMetadata.startCharacterNumber = Math.min(\n this.startCharacterNumber,\n dm.startCharacterNumber\n );\n }\n\n if (this.endLineNumber > dm.endLineNumber) {\n newDebugMetadata.endLineNumber = this.endLineNumber;\n newDebugMetadata.endCharacterNumber = this.endCharacterNumber;\n } else if (this.endLineNumber < dm.endLineNumber) {\n newDebugMetadata.endLineNumber = dm.endLineNumber;\n newDebugMetadata.endCharacterNumber = dm.endCharacterNumber;\n } else {\n newDebugMetadata.endLineNumber = this.endLineNumber;\n newDebugMetadata.endCharacterNumber = Math.max(\n this.endCharacterNumber,\n dm.endCharacterNumber\n );\n }\n\n return newDebugMetadata;\n }\n\n public toString() {\n if (this.fileName !== null) {\n return `line ${this.startLineNumber} of ${this.fileName}\"`;\n } else {\n return \"line \" + this.startLineNumber;\n }\n }\n}\n","export enum StatementLevel {\n InnerBlock,\n Stitch,\n Knot,\n Top,\n}\n","import { INamedContent } from \"../../../../engine/INamedContent\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Identifier } from \"../Identifier\";\n\nexport class ExternalDeclaration extends ParsedObject implements INamedContent {\n public get name(): string | null {\n return this.identifier?.name || null;\n }\n\n constructor(\n public readonly identifier: Identifier,\n public readonly argumentNames: string[]\n ) {\n super();\n }\n\n get typeName(): string {\n return \"EXTERNAL\";\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject | null => {\n this.story.AddExternal(this);\n\n // No runtime code exists for an external, only metadata\n return null;\n };\n\n public toString(): string {\n return `EXTERNAL ${this.identifier?.name}`;\n }\n}\n","import { Argument } from \"./ParsedHierarchy/Argument\";\nimport { Identifier } from \"./ParsedHierarchy/Identifier\";\n\nexport class FlowDecl {\n constructor(\n public readonly name: Identifier,\n public readonly args: Argument[],\n public readonly isFunction: boolean\n ) {}\n}\n","import { Glue as RuntimeGlue } from \"../../../engine/Glue\";\nimport { Wrap } from \"./Wrap\";\n\nexport class Glue extends Wrap {\n constructor(glue: RuntimeGlue) {\n super(glue);\n }\n\n get typeName(): string {\n return \"Glue\";\n }\n}\n","import { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\n\nexport class Wrap extends ParsedObject {\n constructor(private _objToWrap: T) {\n super();\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => this._objToWrap;\n}\n","import { InkObject } from \"./Object\";\n\nexport class Glue extends InkObject {\n public toString() {\n return \"Glue\";\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ContentList } from \"../ContentList\";\nimport { Expression } from \"./Expression\";\nimport { FlowBase } from \"../Flow/FlowBase\";\nimport { NativeFunctionCall } from \"../../../../engine/NativeFunctionCall\";\nimport { IntValue } from \"../../../../engine/Value\";\nimport { Story } from \"../Story\";\nimport { VariableAssignment as RuntimeVariableAssignment } from \"../../../../engine/VariableAssignment\";\nimport { VariableReference as RuntimeVariableReference } from \"../../../../engine/VariableReference\";\nimport { Weave } from \"../Weave\";\nimport { Identifier } from \"../Identifier\";\n\nexport class IncDecExpression extends Expression {\n private _runtimeAssignment: RuntimeVariableAssignment | null = null;\n\n public isInc: boolean;\n public expression: Expression | null = null;\n\n constructor(\n public readonly varIdentifier: Identifier | null,\n isIncOrExpression: boolean | Expression,\n isInc?: boolean\n ) {\n super();\n\n if (isIncOrExpression instanceof Expression) {\n this.expression = isIncOrExpression;\n this.AddContent(this.expression);\n this.isInc = Boolean(isInc);\n } else {\n this.isInc = isIncOrExpression as boolean;\n }\n }\n\n get typeName(): string {\n return \"IncDecExpression\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n // x = x + y\n // ^^^ ^ ^ ^\n // 4 1 3 2\n // Reverse polish notation: (x 1 +) (assign to x)\n\n // 1.\n container.AddContent(\n new RuntimeVariableReference(this.varIdentifier?.name || null)\n );\n\n // 2.\n // - Expression used in the form ~ x += y\n // - Simple version: ~ x++\n if (this.expression) {\n this.expression.GenerateIntoContainer(container);\n } else {\n container.AddContent(new IntValue(1));\n }\n\n // 3.\n container.AddContent(\n NativeFunctionCall.CallWithName(this.isInc ? \"+\" : \"-\")\n );\n\n // 4.\n this._runtimeAssignment = new RuntimeVariableAssignment(\n this.varIdentifier?.name || null,\n false\n );\n container.AddContent(this._runtimeAssignment);\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n const varResolveResult = context.ResolveVariableWithName(\n this.varIdentifier?.name || \"\",\n this\n );\n\n if (!varResolveResult.found) {\n this.Error(\n `variable for ${this.incrementDecrementWord} could not be found: '${this.varIdentifier}' after searching: {this.descriptionOfScope}`\n );\n }\n\n if (!this._runtimeAssignment) {\n throw new Error();\n }\n\n this._runtimeAssignment.isGlobal = varResolveResult.isGlobal;\n\n if (\n !(this.parent instanceof Weave) &&\n !(this.parent instanceof FlowBase) &&\n !(this.parent instanceof ContentList)\n ) {\n this.Error(`Can't use ${this.incrementDecrementWord} as sub-expression`);\n }\n }\n\n get incrementDecrementWord(): \"increment\" | \"decrement\" {\n if (this.isInc) {\n return \"increment\";\n }\n\n return \"decrement\";\n }\n\n public readonly toString = (): string => {\n if (this.expression) {\n return `${this.varIdentifier?.name}${this.isInc ? \" += \" : \" -= \"}${\n this.expression\n }`;\n }\n\n return `${this.varIdentifier?.name}` + (this.isInc ? \"++\" : \"--\");\n };\n}\n","import { ParsedObject } from \"./Object\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\nimport { Story } from \"./Story\";\n\nexport class IncludedFile extends ParsedObject {\n constructor(public readonly includedStory: Story | null) {\n super();\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject | null => {\n // Left to the main story to process\n return null;\n };\n}\n","export class InfixOperator {\n constructor(\n public readonly type: string,\n public readonly precedence: number,\n public readonly requireWhitespace: boolean\n ) {}\n\n public readonly toString = (): string => this.type;\n}\n","import { Argument } from \"./Argument\";\nimport { FlowBase } from \"./Flow/FlowBase\";\nimport { FlowLevel } from \"./Flow/FlowLevel\";\nimport { Identifier } from \"./Identifier\";\nimport { ParsedObject } from \"./Object\";\nimport { Story } from \"./Story\";\n\nexport class Knot extends FlowBase {\n get flowLevel(): FlowLevel {\n return FlowLevel.Knot;\n }\n\n constructor(\n name: Identifier,\n topLevelObjects: ParsedObject[],\n args: Argument[],\n isFunction: boolean\n ) {\n super(name, topLevelObjects, args, isFunction);\n }\n\n get typeName(): string {\n return this.isFunction ? \"Function\" : \"Knot\";\n }\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n\n let parentStory = this.story;\n\n // Enforce rule that stitches must not have the same\n // name as any knots that exist in the story\n for (const stitchName in this.subFlowsByName) {\n const knotWithStitchName = parentStory.ContentWithNameAtLevel(\n stitchName,\n FlowLevel.Knot,\n false\n );\n\n if (knotWithStitchName) {\n const stitch = this.subFlowsByName.get(stitchName);\n const errorMsg = `Stitch '${\n stitch ? stitch.name : \"NO STITCH FOUND\"\n }' has the same name as a knot (on ${\n knotWithStitchName.debugMetadata\n })`;\n this.Error(errorMsg, stitch);\n }\n }\n }\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { Expression } from \"../Expression/Expression\";\nimport { InkList as RuntimeInkList } from \"../../../../engine/InkList\";\nimport { InkListItem as RuntimeInkListItem } from \"../../../../engine/InkList\";\nimport { ListElementDefinition } from \"./ListElementDefinition\";\nimport { ListValue } from \"../../../../engine/Value\";\nimport { Identifier } from \"../Identifier\";\n\nexport class List extends Expression {\n constructor(public readonly itemIdentifierList: Identifier[]) {\n super();\n }\n\n get typeName(): string {\n return \"List\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n const runtimeRawList = new RuntimeInkList();\n\n if (this.itemIdentifierList != null) {\n for (const itemIdentifier of this.itemIdentifierList) {\n const nameParts = itemIdentifier?.name?.split(\".\") || [];\n\n let listName: string | null = null;\n let listItemName: string = \"\";\n if (nameParts.length > 1) {\n listName = nameParts[0];\n listItemName = nameParts[1];\n } else {\n listItemName = nameParts[0];\n }\n\n const listItem = this.story.ResolveListItem(\n listName,\n listItemName,\n this\n ) as ListElementDefinition;\n\n if (listItem === null) {\n if (listName === null) {\n this.Error(\n `Could not find list definition that contains item '${itemIdentifier}'`\n );\n } else {\n this.Error(`Could not find list item ${itemIdentifier}`);\n }\n } else {\n if (listItem.parent == null) {\n this.Error(\n `Could not find list definition for item ${itemIdentifier}`\n );\n return;\n }\n if (!listName) {\n listName = listItem.parent.identifier?.name || null;\n }\n\n const item = new RuntimeInkListItem(listName, listItem.name || null);\n\n if (runtimeRawList.has(item.serialized())) {\n this.Warning(`Duplicate of item '${itemIdentifier}' in list.`);\n } else {\n runtimeRawList.Add(item, listItem.seriesValue);\n }\n }\n }\n }\n\n container.AddContent(new ListValue(runtimeRawList));\n };\n}\n","import { ListDefinition } from \"./ListDefinition\";\nimport { ParsedObject } from \"../Object\";\nimport { InkObject as RuntimeObject } from \"../../../../engine/Object\";\nimport { Story } from \"../Story\";\nimport { SymbolType } from \"../SymbolType\";\nimport { Identifier } from \"../Identifier\";\n\nexport class ListElementDefinition extends ParsedObject {\n public seriesValue: number = 0;\n\n public parent: ListDefinition | null = null;\n\n get fullName(): string {\n const parentList = this.parent;\n if (parentList === null) {\n throw new Error(\"Can't get full name without a parent list.\");\n }\n\n return `${parentList.identifier?.name}.${this.name}`;\n }\n\n get typeName(): string {\n return \"ListElement\";\n }\n\n get name(): string | null {\n return this.indentifier?.name || null;\n }\n\n constructor(\n public readonly indentifier: Identifier,\n public readonly inInitialList: boolean,\n public readonly explicitValue: number | null = null\n ) {\n super();\n this.parent = super.parent as ListDefinition;\n }\n\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n throw new Error(\"Not implemented.\");\n };\n\n public ResolveReferences(context: Story): void {\n super.ResolveReferences(context);\n context.CheckForNamingCollisions(\n this,\n this.indentifier,\n SymbolType.ListItem\n );\n }\n\n public readonly toString = (): string => this.fullName;\n}\n","import { Argument } from \"./Argument\";\nimport { FlowBase } from \"./Flow/FlowBase\";\nimport { FlowLevel } from \"./Flow/FlowLevel\";\nimport { Identifier } from \"./Identifier\";\nimport { ParsedObject } from \"./Object\";\n\nexport class Stitch extends FlowBase {\n get flowLevel(): FlowLevel {\n return FlowLevel.Stitch;\n }\n\n constructor(\n name: Identifier,\n topLevelObjects: ParsedObject[],\n args: Argument[],\n isFunction: boolean\n ) {\n super(name, topLevelObjects, args, isFunction);\n }\n\n get typeName(): string {\n return \"Stitch\";\n }\n\n public toString = (): string => {\n return `${\n this.parent !== null ? this.parent + \" > \" : \"\"\n }${super.toString()}`;\n };\n}\n","import { InkObject } from \"./Object\";\n\n// New version of tags is dynamic - it constructs the tags\n// at runtime based on BeginTag and EndTag control commands.\n// Plain text that's in the output stream is turned into tags\n// when you do story.currentTags.\n// The only place this is used is when flattening tags down\n// to string in advance, during dynamic string generation if\n// there's a tag embedded in it. See how ControlCommand.EndString\n// is implemented in Story.cs for more details + comment\nexport class Tag extends InkObject {\n public readonly text: string;\n\n constructor(tagText: string) {\n super();\n this.text = tagText.toString() || \"\";\n }\n\n public toString(): string {\n return \"# \" + this.text;\n }\n}\n","import { Path } from \"./Path\";\nimport { CallStack } from \"./CallStack\";\nimport { throwNullException } from \"./NullException\";\nimport { InkObject } from \"./Object\";\n\nexport class Choice extends InkObject {\n public text: string = \"\";\n public index: number = 0;\n public threadAtGeneration: CallStack.Thread | null = null;\n public sourcePath: string = \"\";\n public targetPath: Path | null = null;\n public isInvisibleDefault: boolean = false;\n public tags: string[] | null = null;\n public originalThreadIndex: number = 0;\n\n get pathStringOnChoice(): string {\n if (this.targetPath === null)\n return throwNullException(\"Choice.targetPath\");\n return this.targetPath.toString();\n }\n set pathStringOnChoice(value: string) {\n this.targetPath = new Path(value);\n }\n}\n","import { InkListItem } from \"./InkList\";\nimport { ListValue } from \"./Value\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { TryGetResult } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\n\nexport class ListDefinitionsOrigin {\n protected _lists: Map;\n protected _allUnambiguousListValueCache: Map;\n\n constructor(lists: ListDefinition[]) {\n this._lists = new Map();\n this._allUnambiguousListValueCache = new Map();\n\n for (let list of lists) {\n this._lists.set(list.name, list);\n\n for (let [key, val] of list.items) {\n let item = InkListItem.fromSerializedKey(key);\n let listValue = new ListValue(item, val);\n\n if (!item.itemName) {\n throw new Error(\"item.itemName is null or undefined.\");\n }\n\n this._allUnambiguousListValueCache.set(item.itemName, listValue);\n this._allUnambiguousListValueCache.set(item.fullName, listValue);\n }\n }\n }\n get lists(): ListDefinition[] {\n let listOfLists: ListDefinition[] = [];\n\n for (let [, value] of this._lists) {\n listOfLists.push(value);\n }\n\n return listOfLists;\n }\n public TryListGetDefinition(\n name: string | null,\n /* out */ def: ListDefinition | null\n ): TryGetResult {\n if (name === null) {\n return { result: def, exists: false };\n }\n // initially, this function returns a boolean and the second parameter is an out.\n let definition = this._lists.get(name);\n if (!definition) return { result: def, exists: false };\n\n return { result: definition, exists: true };\n }\n public FindSingleItemListWithName(name: string | null) {\n if (name === null) {\n return throwNullException(\"name\");\n }\n let val = this._allUnambiguousListValueCache.get(name);\n\n if (typeof val !== \"undefined\") {\n return val;\n }\n\n return null;\n }\n}\n","import { Container } from \"./Container\";\nimport {\n Value,\n IntValue,\n FloatValue,\n StringValue,\n DivertTargetValue,\n VariablePointerValue,\n ListValue,\n BoolValue,\n} from \"./Value\";\nimport { Glue } from \"./Glue\";\nimport { ControlCommand } from \"./ControlCommand\";\nimport { PushPopType } from \"./PushPop\";\nimport { Divert } from \"./Divert\";\nimport { ChoicePoint } from \"./ChoicePoint\";\nimport { VariableReference } from \"./VariableReference\";\nimport { VariableAssignment } from \"./VariableAssignment\";\nimport { NativeFunctionCall } from \"./NativeFunctionCall\";\nimport { Void } from \"./Void\";\nimport { Tag } from \"./Tag\";\nimport { Path } from \"./Path\";\nimport { Choice } from \"./Choice\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { ListDefinitionsOrigin } from \"./ListDefinitionsOrigin\";\nimport { InkListItem, InkList } from \"./InkList\";\nimport { InkObject } from \"./Object\";\nimport { asOrNull } from \"./TypeAssertion\";\nimport { throwNullException } from \"./NullException\";\nimport { SimpleJson } from \"./SimpleJson\";\n\nexport class JsonSerialisation {\n public static JArrayToRuntimeObjList(\n jArray: any[],\n skipLast: boolean = false\n ) {\n let count = jArray.length;\n if (skipLast) count--;\n\n let list: InkObject[] = [];\n\n for (let i = 0; i < count; i++) {\n let jTok = jArray[i];\n let runtimeObj = this.JTokenToRuntimeObject(jTok);\n if (runtimeObj === null) {\n return throwNullException(\"runtimeObj\");\n }\n list.push(runtimeObj);\n }\n\n return list;\n }\n\n public static WriteDictionaryRuntimeObjs(\n writer: SimpleJson.Writer,\n dictionary: Map\n ) {\n writer.WriteObjectStart();\n for (let [key, value] of dictionary) {\n writer.WritePropertyStart(key);\n this.WriteRuntimeObject(writer, value);\n writer.WritePropertyEnd();\n }\n writer.WriteObjectEnd();\n }\n\n public static WriteListRuntimeObjs(\n writer: SimpleJson.Writer,\n list: InkObject[]\n ) {\n writer.WriteArrayStart();\n for (let value of list) {\n this.WriteRuntimeObject(writer, value);\n }\n writer.WriteArrayEnd();\n }\n\n public static WriteIntDictionary(\n writer: SimpleJson.Writer,\n dict: Map\n ) {\n writer.WriteObjectStart();\n for (let [key, value] of dict) {\n writer.WriteIntProperty(key, value);\n }\n writer.WriteObjectEnd();\n }\n\n public static WriteRuntimeObject(\n writer: SimpleJson.Writer,\n obj: InkObject\n ): void {\n let container = asOrNull(obj, Container);\n if (container) {\n this.WriteRuntimeContainer(writer, container);\n return;\n }\n\n let divert = asOrNull(obj, Divert);\n if (divert) {\n let divTypeKey = \"->\";\n if (divert.isExternal) {\n divTypeKey = \"x()\";\n } else if (divert.pushesToStack) {\n if (divert.stackPushType == PushPopType.Function) {\n divTypeKey = \"f()\";\n } else if (divert.stackPushType == PushPopType.Tunnel) {\n divTypeKey = \"->t->\";\n }\n }\n\n let targetStr;\n if (divert.hasVariableTarget) {\n targetStr = divert.variableDivertName;\n } else {\n targetStr = divert.targetPathString;\n }\n\n writer.WriteObjectStart();\n writer.WriteProperty(divTypeKey, targetStr);\n\n if (divert.hasVariableTarget) {\n writer.WriteProperty(\"var\", true);\n }\n\n if (divert.isConditional) {\n writer.WriteProperty(\"c\", true);\n }\n\n if (divert.externalArgs > 0) {\n writer.WriteIntProperty(\"exArgs\", divert.externalArgs);\n }\n\n writer.WriteObjectEnd();\n return;\n }\n\n let choicePoint = asOrNull(obj, ChoicePoint);\n if (choicePoint) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"*\", choicePoint.pathStringOnChoice);\n writer.WriteIntProperty(\"flg\", choicePoint.flags);\n writer.WriteObjectEnd();\n return;\n }\n\n let boolVal = asOrNull(obj, BoolValue);\n if (boolVal) {\n writer.WriteBool(boolVal.value);\n return;\n }\n\n let intVal = asOrNull(obj, IntValue);\n if (intVal) {\n writer.WriteInt(intVal.value);\n return;\n }\n\n let floatVal = asOrNull(obj, FloatValue);\n if (floatVal) {\n writer.WriteFloat(floatVal.value);\n return;\n }\n\n let strVal = asOrNull(obj, StringValue);\n if (strVal) {\n if (strVal.isNewline) {\n writer.Write(\"\\n\", false);\n } else {\n writer.WriteStringStart();\n writer.WriteStringInner(\"^\");\n writer.WriteStringInner(strVal.value);\n writer.WriteStringEnd();\n }\n return;\n }\n\n let listVal = asOrNull(obj, ListValue);\n if (listVal) {\n this.WriteInkList(writer, listVal);\n return;\n }\n\n let divTargetVal = asOrNull(obj, DivertTargetValue);\n if (divTargetVal) {\n writer.WriteObjectStart();\n if (divTargetVal.value === null) {\n return throwNullException(\"divTargetVal.value\");\n }\n writer.WriteProperty(\"^->\", divTargetVal.value.componentsString);\n writer.WriteObjectEnd();\n\n return;\n }\n\n let varPtrVal = asOrNull(obj, VariablePointerValue);\n if (varPtrVal) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"^var\", varPtrVal.value);\n writer.WriteIntProperty(\"ci\", varPtrVal.contextIndex);\n writer.WriteObjectEnd();\n return;\n }\n\n let glue = asOrNull(obj, Glue);\n if (glue) {\n writer.Write(\"<>\");\n return;\n }\n\n let controlCmd = asOrNull(obj, ControlCommand);\n if (controlCmd) {\n writer.Write(\n JsonSerialisation._controlCommandNames[controlCmd.commandType]\n );\n return;\n }\n\n let nativeFunc = asOrNull(obj, NativeFunctionCall);\n if (nativeFunc) {\n let name = nativeFunc.name;\n\n if (name == \"^\") name = \"L^\";\n\n writer.Write(name);\n return;\n }\n\n let varRef = asOrNull(obj, VariableReference);\n if (varRef) {\n writer.WriteObjectStart();\n let readCountPath = varRef.pathStringForCount;\n if (readCountPath != null) {\n writer.WriteProperty(\"CNT?\", readCountPath);\n } else {\n writer.WriteProperty(\"VAR?\", varRef.name);\n }\n\n writer.WriteObjectEnd();\n return;\n }\n\n let varAss = asOrNull(obj, VariableAssignment);\n if (varAss) {\n writer.WriteObjectStart();\n\n let key = varAss.isGlobal ? \"VAR=\" : \"temp=\";\n writer.WriteProperty(key, varAss.variableName);\n\n // Reassignment?\n if (!varAss.isNewDeclaration) writer.WriteProperty(\"re\", true);\n\n writer.WriteObjectEnd();\n\n return;\n }\n\n let voidObj = asOrNull(obj, Void);\n if (voidObj) {\n writer.Write(\"void\");\n return;\n }\n\n let tag = asOrNull(obj, Tag);\n if (tag) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"#\", tag.text);\n writer.WriteObjectEnd();\n return;\n }\n\n let choice = asOrNull(obj, Choice);\n if (choice) {\n this.WriteChoice(writer, choice);\n return;\n }\n\n throw new Error(\"Failed to convert runtime object to Json token: \" + obj);\n }\n\n public static JObjectToDictionaryRuntimeObjs(jObject: Record) {\n let dict: Map = new Map();\n\n for (let key in jObject) {\n if (jObject.hasOwnProperty(key)) {\n let inkObject = this.JTokenToRuntimeObject(jObject[key]);\n if (inkObject === null) {\n return throwNullException(\"inkObject\");\n }\n dict.set(key, inkObject);\n }\n }\n\n return dict;\n }\n\n public static JObjectToIntDictionary(jObject: Record) {\n let dict: Map = new Map();\n for (let key in jObject) {\n if (jObject.hasOwnProperty(key)) {\n dict.set(key, parseInt(jObject[key]));\n }\n }\n return dict;\n }\n\n public static JTokenToRuntimeObject(token: any): InkObject | null {\n if (\n (typeof token === \"number\" && !isNaN(token)) ||\n typeof token === \"boolean\"\n ) {\n return Value.Create(token);\n }\n\n if (typeof token === \"string\") {\n let str = token.toString();\n\n // String value\n let firstChar = str[0];\n if (firstChar == \"^\") return new StringValue(str.substring(1));\n else if (firstChar == \"\\n\" && str.length == 1)\n return new StringValue(\"\\n\");\n\n // Glue\n if (str == \"<>\") return new Glue();\n\n // Control commands (would looking up in a hash set be faster?)\n for (let i = 0; i < JsonSerialisation._controlCommandNames.length; ++i) {\n let cmdName = JsonSerialisation._controlCommandNames[i];\n if (str == cmdName) {\n return new ControlCommand(i);\n }\n }\n\n // Native functions\n if (str == \"L^\") str = \"^\";\n if (NativeFunctionCall.CallExistsWithName(str))\n return NativeFunctionCall.CallWithName(str);\n\n // Pop\n if (str == \"->->\") return ControlCommand.PopTunnel();\n else if (str == \"~ret\") return ControlCommand.PopFunction();\n\n // Void\n if (str == \"void\") return new Void();\n }\n\n if (typeof token === \"object\" && !Array.isArray(token)) {\n let obj = token as Record;\n let propValue;\n\n // Divert target value to path\n if (obj[\"^->\"]) {\n propValue = obj[\"^->\"];\n return new DivertTargetValue(new Path(propValue.toString()));\n }\n\n // VariablePointerValue\n if (obj[\"^var\"]) {\n propValue = obj[\"^var\"];\n let varPtr = new VariablePointerValue(propValue.toString());\n if (\"ci\" in obj) {\n propValue = obj[\"ci\"];\n varPtr.contextIndex = parseInt(propValue);\n }\n return varPtr;\n }\n\n // Divert\n let isDivert = false;\n let pushesToStack = false;\n let divPushType = PushPopType.Function;\n let external = false;\n if ((propValue = obj[\"->\"])) {\n isDivert = true;\n } else if ((propValue = obj[\"f()\"])) {\n isDivert = true;\n pushesToStack = true;\n divPushType = PushPopType.Function;\n } else if ((propValue = obj[\"->t->\"])) {\n isDivert = true;\n pushesToStack = true;\n divPushType = PushPopType.Tunnel;\n } else if ((propValue = obj[\"x()\"])) {\n isDivert = true;\n external = true;\n pushesToStack = false;\n divPushType = PushPopType.Function;\n }\n\n if (isDivert) {\n let divert = new Divert();\n divert.pushesToStack = pushesToStack;\n divert.stackPushType = divPushType;\n divert.isExternal = external;\n\n let target = propValue.toString();\n\n if ((propValue = obj[\"var\"])) divert.variableDivertName = target;\n else divert.targetPathString = target;\n\n divert.isConditional = !!obj[\"c\"];\n\n if (external) {\n if ((propValue = obj[\"exArgs\"]))\n divert.externalArgs = parseInt(propValue);\n }\n\n return divert;\n }\n\n // Choice\n if ((propValue = obj[\"*\"])) {\n let choice = new ChoicePoint();\n choice.pathStringOnChoice = propValue.toString();\n\n if ((propValue = obj[\"flg\"])) choice.flags = parseInt(propValue);\n\n return choice;\n }\n\n // Variable reference\n if ((propValue = obj[\"VAR?\"])) {\n return new VariableReference(propValue.toString());\n } else if ((propValue = obj[\"CNT?\"])) {\n let readCountVarRef = new VariableReference();\n readCountVarRef.pathStringForCount = propValue.toString();\n return readCountVarRef;\n }\n\n // Variable assignment\n let isVarAss = false;\n let isGlobalVar = false;\n if ((propValue = obj[\"VAR=\"])) {\n isVarAss = true;\n isGlobalVar = true;\n } else if ((propValue = obj[\"temp=\"])) {\n isVarAss = true;\n isGlobalVar = false;\n }\n if (isVarAss) {\n let varName = propValue.toString();\n let isNewDecl = !obj[\"re\"];\n let varAss = new VariableAssignment(varName, isNewDecl);\n varAss.isGlobal = isGlobalVar;\n return varAss;\n }\n if (obj[\"#\"] !== undefined) {\n propValue = obj[\"#\"];\n return new Tag(propValue.toString());\n }\n\n // List value\n if ((propValue = obj[\"list\"])) {\n // var listContent = (Dictionary)propValue;\n let listContent = propValue as Record;\n let rawList = new InkList();\n if ((propValue = obj[\"origins\"])) {\n // var namesAsObjs = (List)propValue;\n let namesAsObjs = propValue as string[];\n // rawList.SetInitialOriginNames(namesAsObjs.Cast().ToList());\n rawList.SetInitialOriginNames(namesAsObjs);\n }\n\n for (let key in listContent) {\n if (listContent.hasOwnProperty(key)) {\n let nameToVal = listContent[key];\n let item = new InkListItem(key);\n let val = parseInt(nameToVal);\n rawList.Add(item, val);\n }\n }\n\n return new ListValue(rawList);\n }\n\n if (obj[\"originalChoicePath\"] != null) return this.JObjectToChoice(obj);\n }\n\n // Array is always a Runtime.Container\n if (Array.isArray(token)) {\n return this.JArrayToContainer(token);\n }\n\n if (token === null || token === undefined) return null;\n\n throw new Error(\n \"Failed to convert token to runtime object: \" +\n this.toJson(token, [\"parent\"])\n );\n }\n\n public static toJson(\n me: T,\n removes?: (keyof T)[],\n space?: number\n ): string {\n return JSON.stringify(\n me,\n (k, v) => (removes?.some((r) => r === k) ? undefined : v),\n space\n );\n }\n\n public static WriteRuntimeContainer(\n writer: SimpleJson.Writer,\n container: Container | null,\n withoutName: boolean = false\n ) {\n writer.WriteArrayStart();\n if (container === null) {\n return throwNullException(\"container\");\n }\n for (let c of container.content) this.WriteRuntimeObject(writer, c);\n\n let namedOnlyContent = container.namedOnlyContent;\n let countFlags = container.countFlags;\n let hasNameProperty = container.name != null && !withoutName;\n\n let hasTerminator =\n namedOnlyContent != null || countFlags > 0 || hasNameProperty;\n if (hasTerminator) {\n writer.WriteObjectStart();\n }\n\n if (namedOnlyContent != null) {\n for (let [key, value] of namedOnlyContent) {\n let name = key;\n let namedContainer = asOrNull(value, Container);\n writer.WritePropertyStart(name);\n this.WriteRuntimeContainer(writer, namedContainer, true);\n writer.WritePropertyEnd();\n }\n }\n\n if (countFlags > 0) writer.WriteIntProperty(\"#f\", countFlags);\n\n if (hasNameProperty) writer.WriteProperty(\"#n\", container.name);\n\n if (hasTerminator) writer.WriteObjectEnd();\n else writer.WriteNull();\n\n writer.WriteArrayEnd();\n }\n\n public static JArrayToContainer(jArray: any[]) {\n let container = new Container();\n container.content = this.JArrayToRuntimeObjList(jArray, true);\n\n let terminatingObj = jArray[jArray.length - 1] as Record;\n if (terminatingObj != null) {\n let namedOnlyContent = new Map();\n\n for (let key in terminatingObj) {\n if (key == \"#f\") {\n container.countFlags = parseInt(terminatingObj[key]);\n } else if (key == \"#n\") {\n container.name = terminatingObj[key].toString();\n } else {\n let namedContentItem = this.JTokenToRuntimeObject(\n terminatingObj[key]\n );\n // var namedSubContainer = namedContentItem as Container;\n let namedSubContainer = asOrNull(namedContentItem, Container);\n if (namedSubContainer) namedSubContainer.name = key;\n namedOnlyContent.set(key, namedContentItem);\n }\n }\n\n container.namedOnlyContent = namedOnlyContent;\n }\n\n return container;\n }\n\n public static JObjectToChoice(jObj: Record) {\n let choice = new Choice();\n choice.text = jObj[\"text\"].toString();\n choice.index = parseInt(jObj[\"index\"]);\n choice.sourcePath = jObj[\"originalChoicePath\"].toString();\n choice.originalThreadIndex = parseInt(jObj[\"originalThreadIndex\"]);\n choice.pathStringOnChoice = jObj[\"targetPath\"].toString();\n return choice;\n }\n\n public static WriteChoice(writer: SimpleJson.Writer, choice: Choice) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"text\", choice.text);\n writer.WriteIntProperty(\"index\", choice.index);\n writer.WriteProperty(\"originalChoicePath\", choice.sourcePath);\n writer.WriteIntProperty(\"originalThreadIndex\", choice.originalThreadIndex);\n writer.WriteProperty(\"targetPath\", choice.pathStringOnChoice);\n writer.WriteObjectEnd();\n }\n\n public static WriteInkList(writer: SimpleJson.Writer, listVal: ListValue) {\n let rawList = listVal.value;\n if (rawList === null) {\n return throwNullException(\"rawList\");\n }\n\n writer.WriteObjectStart();\n writer.WritePropertyStart(\"list\");\n writer.WriteObjectStart();\n\n for (let [key, val] of rawList) {\n let item = InkListItem.fromSerializedKey(key);\n let itemVal = val;\n\n if (item.itemName === null) {\n return throwNullException(\"item.itemName\");\n }\n\n writer.WritePropertyNameStart();\n writer.WritePropertyNameInner(item.originName ? item.originName : \"?\");\n writer.WritePropertyNameInner(\".\");\n writer.WritePropertyNameInner(item.itemName);\n writer.WritePropertyNameEnd();\n\n writer.Write(itemVal);\n\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n\n writer.WritePropertyEnd();\n\n if (\n rawList.Count == 0 &&\n rawList.originNames != null &&\n rawList.originNames.length > 0\n ) {\n writer.WritePropertyStart(\"origins\");\n writer.WriteArrayStart();\n for (let name of rawList.originNames) writer.Write(name);\n writer.WriteArrayEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n }\n\n public static ListDefinitionsToJToken(origin: ListDefinitionsOrigin) {\n let result: Record = {};\n\n for (let def of origin.lists) {\n let listDefJson: Record = {};\n\n for (let [key, val] of def.items) {\n let item = InkListItem.fromSerializedKey(key);\n if (item.itemName === null) {\n return throwNullException(\"item.itemName\");\n }\n listDefJson[item.itemName] = val;\n }\n\n result[def.name] = listDefJson;\n }\n\n return result;\n }\n\n public static JTokenToListDefinitions(obj: Record) {\n // var defsObj = (Dictionary)obj;\n let defsObj = obj;\n\n let allDefs: ListDefinition[] = [];\n\n for (let key in defsObj) {\n if (defsObj.hasOwnProperty(key)) {\n let name = key.toString();\n // var listDefJson = (Dictionary)kv.Value;\n let listDefJson = defsObj[key] as Record;\n\n // Cast (string, object) to (string, int) for items\n let items: Map = new Map();\n\n for (let nameValueKey in listDefJson) {\n if (defsObj.hasOwnProperty(key)) {\n let nameValue = listDefJson[nameValueKey];\n items.set(nameValueKey, parseInt(nameValue));\n }\n }\n\n let def = new ListDefinition(name, items);\n allDefs.push(def);\n }\n }\n\n return new ListDefinitionsOrigin(allDefs);\n }\n\n private static _controlCommandNames = (() => {\n let _controlCommandNames: string[] = [];\n\n _controlCommandNames[ControlCommand.CommandType.EvalStart] = \"ev\";\n _controlCommandNames[ControlCommand.CommandType.EvalOutput] = \"out\";\n _controlCommandNames[ControlCommand.CommandType.EvalEnd] = \"/ev\";\n _controlCommandNames[ControlCommand.CommandType.Duplicate] = \"du\";\n _controlCommandNames[ControlCommand.CommandType.PopEvaluatedValue] = \"pop\";\n _controlCommandNames[ControlCommand.CommandType.PopFunction] = \"~ret\";\n _controlCommandNames[ControlCommand.CommandType.PopTunnel] = \"->->\";\n _controlCommandNames[ControlCommand.CommandType.BeginString] = \"str\";\n _controlCommandNames[ControlCommand.CommandType.EndString] = \"/str\";\n _controlCommandNames[ControlCommand.CommandType.NoOp] = \"nop\";\n _controlCommandNames[ControlCommand.CommandType.ChoiceCount] = \"choiceCnt\";\n _controlCommandNames[ControlCommand.CommandType.Turns] = \"turn\";\n _controlCommandNames[ControlCommand.CommandType.TurnsSince] = \"turns\";\n _controlCommandNames[ControlCommand.CommandType.ReadCount] = \"readc\";\n _controlCommandNames[ControlCommand.CommandType.Random] = \"rnd\";\n _controlCommandNames[ControlCommand.CommandType.SeedRandom] = \"srnd\";\n _controlCommandNames[ControlCommand.CommandType.VisitIndex] = \"visit\";\n _controlCommandNames[ControlCommand.CommandType.SequenceShuffleIndex] =\n \"seq\";\n _controlCommandNames[ControlCommand.CommandType.StartThread] = \"thread\";\n _controlCommandNames[ControlCommand.CommandType.Done] = \"done\";\n _controlCommandNames[ControlCommand.CommandType.End] = \"end\";\n _controlCommandNames[ControlCommand.CommandType.ListFromInt] = \"listInt\";\n _controlCommandNames[ControlCommand.CommandType.ListRange] = \"range\";\n _controlCommandNames[ControlCommand.CommandType.ListRandom] = \"lrnd\";\n _controlCommandNames[ControlCommand.CommandType.BeginTag] = \"#\";\n _controlCommandNames[ControlCommand.CommandType.EndTag] = \"/#\";\n\n for (let i = 0; i < ControlCommand.CommandType.TOTAL_VALUES; ++i) {\n if (_controlCommandNames[i] == null)\n throw new Error(\"Control command not accounted for in serialisation\");\n }\n\n return _controlCommandNames;\n })();\n}\n","import { PushPopType } from \"./PushPop\";\nimport { Path } from \"./Path\";\nimport { Story } from \"./Story\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { ListValue } from \"./Value\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { Pointer } from \"./Pointer\";\nimport { InkObject } from \"./Object\";\nimport { Debug } from \"./Debug\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\nimport { SimpleJson } from \"./SimpleJson\";\n\nexport class CallStack {\n get elements() {\n return this.callStack;\n }\n\n get depth() {\n return this.elements.length;\n }\n\n get currentElement() {\n let thread = this._threads[this._threads.length - 1];\n let cs = thread.callstack;\n return cs[cs.length - 1];\n }\n\n get currentElementIndex() {\n return this.callStack.length - 1;\n }\n\n get currentThread(): CallStack.Thread {\n return this._threads[this._threads.length - 1];\n }\n set currentThread(value: CallStack.Thread) {\n Debug.Assert(\n this._threads.length == 1,\n \"Shouldn't be directly setting the current thread when we have a stack of them\"\n );\n\n this._threads.length = 0;\n this._threads.push(value);\n }\n\n get canPop() {\n return this.callStack.length > 1;\n }\n\n constructor(storyContext: Story);\n constructor(toCopy: CallStack);\n constructor() {\n if (arguments[0] instanceof Story) {\n let storyContext = arguments[0] as Story;\n\n this._startOfRoot = Pointer.StartOf(storyContext.rootContentContainer);\n this.Reset();\n } else {\n let toCopy = arguments[0] as CallStack;\n\n this._threads = [];\n for (let otherThread of toCopy._threads) {\n this._threads.push(otherThread.Copy());\n }\n this._threadCounter = toCopy._threadCounter;\n this._startOfRoot = toCopy._startOfRoot.copy();\n }\n }\n\n public Reset() {\n this._threads = [];\n this._threads.push(new CallStack.Thread());\n\n this._threads[0].callstack.push(\n new CallStack.Element(PushPopType.Tunnel, this._startOfRoot)\n );\n }\n\n public SetJsonToken(jObject: Record, storyContext: Story) {\n this._threads.length = 0;\n\n // TODO: (List) jObject [\"threads\"];\n let jThreads: any[] = jObject[\"threads\"];\n\n for (let jThreadTok of jThreads) {\n // TODO: var jThreadObj = (Dictionary)jThreadTok;\n let jThreadObj = jThreadTok;\n let thread = new CallStack.Thread(jThreadObj, storyContext);\n this._threads.push(thread);\n }\n\n // TODO: (int)jObject [\"threadCounter\"];\n this._threadCounter = parseInt(jObject[\"threadCounter\"]);\n this._startOfRoot = Pointer.StartOf(storyContext.rootContentContainer);\n }\n public WriteJson(w: SimpleJson.Writer) {\n w.WriteObject((writer) => {\n writer.WritePropertyStart(\"threads\");\n writer.WriteArrayStart();\n\n for (let thread of this._threads) {\n thread.WriteJson(writer);\n }\n\n writer.WriteArrayEnd();\n writer.WritePropertyEnd();\n\n writer.WritePropertyStart(\"threadCounter\");\n writer.WriteInt(this._threadCounter);\n writer.WritePropertyEnd();\n });\n }\n\n public PushThread() {\n let newThread = this.currentThread.Copy();\n this._threadCounter++;\n newThread.threadIndex = this._threadCounter;\n this._threads.push(newThread);\n }\n\n public ForkThread() {\n let forkedThread = this.currentThread.Copy();\n this._threadCounter++;\n forkedThread.threadIndex = this._threadCounter;\n return forkedThread;\n }\n\n public PopThread() {\n if (this.canPopThread) {\n this._threads.splice(this._threads.indexOf(this.currentThread), 1); // should be equivalent to a pop()\n } else {\n throw new Error(\"Can't pop thread\");\n }\n }\n\n get canPopThread() {\n return this._threads.length > 1 && !this.elementIsEvaluateFromGame;\n }\n\n get elementIsEvaluateFromGame() {\n return this.currentElement.type == PushPopType.FunctionEvaluationFromGame;\n }\n\n public Push(\n type: PushPopType,\n externalEvaluationStackHeight: number = 0,\n outputStreamLengthWithPushed: number = 0\n ) {\n let element = new CallStack.Element(\n type,\n this.currentElement.currentPointer,\n false\n );\n\n element.evaluationStackHeightWhenPushed = externalEvaluationStackHeight;\n element.functionStartInOutputStream = outputStreamLengthWithPushed;\n\n this.callStack.push(element);\n }\n\n public CanPop(type: PushPopType | null = null) {\n if (!this.canPop) return false;\n\n if (type == null) return true;\n\n return this.currentElement.type == type;\n }\n\n public Pop(type: PushPopType | null = null) {\n if (this.CanPop(type)) {\n this.callStack.pop();\n return;\n } else {\n throw new Error(\"Mismatched push/pop in Callstack\");\n }\n }\n\n public GetTemporaryVariableWithName(\n name: string | null,\n contextIndex: number = -1\n ) {\n if (contextIndex == -1) contextIndex = this.currentElementIndex + 1;\n\n let contextElement = this.callStack[contextIndex - 1];\n\n let varValue = tryGetValueFromMap(\n contextElement.temporaryVariables,\n name,\n null\n );\n if (varValue.exists) {\n return varValue.result;\n } else {\n return null;\n }\n }\n\n public SetTemporaryVariable(\n name: string,\n value: any,\n declareNew: boolean,\n contextIndex: number = -1\n ) {\n if (contextIndex == -1) contextIndex = this.currentElementIndex + 1;\n\n let contextElement = this.callStack[contextIndex - 1];\n\n if (!declareNew && !contextElement.temporaryVariables.get(name)) {\n throw new Error(\"Could not find temporary variable to set: \" + name);\n }\n\n let oldValue = tryGetValueFromMap(\n contextElement.temporaryVariables,\n name,\n null\n );\n if (oldValue.exists)\n ListValue.RetainListOriginsForAssignment(oldValue.result, value);\n\n contextElement.temporaryVariables.set(name, value);\n }\n\n public ContextForVariableNamed(name: string) {\n if (this.currentElement.temporaryVariables.get(name)) {\n return this.currentElementIndex + 1;\n } else {\n return 0;\n }\n }\n\n public ThreadWithIndex(index: number) {\n let filtered = this._threads.filter((t) => {\n if (t.threadIndex == index) return t;\n });\n\n return filtered.length > 0 ? filtered[0] : null;\n }\n\n get callStack() {\n return this.currentThread.callstack;\n }\n\n get callStackTrace() {\n let sb = new StringBuilder();\n\n for (let t = 0; t < this._threads.length; t++) {\n let thread = this._threads[t];\n let isCurrent = t == this._threads.length - 1;\n sb.AppendFormat(\n \"=== THREAD {0}/{1} {2}===\\n\",\n t + 1,\n this._threads.length,\n isCurrent ? \"(current) \" : \"\"\n );\n\n for (let i = 0; i < thread.callstack.length; i++) {\n if (thread.callstack[i].type == PushPopType.Function)\n sb.Append(\" [FUNCTION] \");\n else sb.Append(\" [TUNNEL] \");\n\n let pointer = thread.callstack[i].currentPointer;\n if (!pointer.isNull) {\n sb.Append(\"\");\n }\n }\n }\n\n return sb.toString();\n }\n\n public _threads!: CallStack.Thread[]; // Banged because it's initialized in Reset().\n public _threadCounter: number = 0;\n public _startOfRoot: Pointer = Pointer.Null;\n}\n\nexport namespace CallStack {\n export class Element {\n public currentPointer: Pointer;\n public inExpressionEvaluation: boolean;\n public temporaryVariables: Map;\n public type: PushPopType;\n\n public evaluationStackHeightWhenPushed: number = 0;\n public functionStartInOutputStream: number = 0;\n\n constructor(\n type: PushPopType,\n pointer: Pointer,\n inExpressionEvaluation: boolean = false\n ) {\n this.currentPointer = pointer.copy();\n this.inExpressionEvaluation = inExpressionEvaluation;\n this.temporaryVariables = new Map();\n this.type = type;\n }\n\n public Copy() {\n let copy = new Element(\n this.type,\n this.currentPointer,\n this.inExpressionEvaluation\n );\n copy.temporaryVariables = new Map(this.temporaryVariables);\n copy.evaluationStackHeightWhenPushed =\n this.evaluationStackHeightWhenPushed;\n copy.functionStartInOutputStream = this.functionStartInOutputStream;\n return copy;\n }\n }\n\n export class Thread {\n public callstack: Element[];\n public threadIndex: number = 0;\n public previousPointer: Pointer = Pointer.Null;\n\n constructor();\n constructor(jThreadObj: any, storyContext: Story);\n constructor() {\n this.callstack = [];\n\n if (arguments[0] && arguments[1]) {\n let jThreadObj = arguments[0];\n let storyContext = arguments[1];\n\n // TODO: (int) jThreadObj['threadIndex'] can raise;\n this.threadIndex = parseInt(jThreadObj[\"threadIndex\"]);\n\n let jThreadCallstack = jThreadObj[\"callstack\"];\n\n for (let jElTok of jThreadCallstack) {\n let jElementObj = jElTok;\n\n // TODO: (int) jElementObj['type'] can raise;\n let pushPopType: PushPopType = parseInt(jElementObj[\"type\"]);\n\n let pointer = Pointer.Null;\n\n let currentContainerPathStr: string;\n // TODO: jElementObj.TryGetValue (\"cPath\", out currentContainerPathStrToken);\n let currentContainerPathStrToken = jElementObj[\"cPath\"];\n if (typeof currentContainerPathStrToken !== \"undefined\") {\n currentContainerPathStr = currentContainerPathStrToken.toString();\n\n let threadPointerResult = storyContext.ContentAtPath(\n new Path(currentContainerPathStr)\n );\n pointer.container = threadPointerResult.container;\n pointer.index = parseInt(jElementObj[\"idx\"]);\n\n if (threadPointerResult.obj == null)\n throw new Error(\n \"When loading state, internal story location couldn't be found: \" +\n currentContainerPathStr +\n \". Has the story changed since this save data was created?\"\n );\n else if (threadPointerResult.approximate) {\n if (pointer.container === null) {\n return throwNullException(\"pointer.container\");\n }\n storyContext.Warning(\n \"When loading state, exact internal story location couldn't be found: '\" +\n currentContainerPathStr +\n \"', so it was approximated to '\" +\n pointer.container.path.toString() +\n \"' to recover. Has the story changed since this save data was created?\"\n );\n }\n }\n\n let inExpressionEvaluation = !!jElementObj[\"exp\"];\n\n let el = new Element(pushPopType, pointer, inExpressionEvaluation);\n\n let temps = jElementObj[\"temp\"];\n if (typeof temps !== \"undefined\") {\n el.temporaryVariables =\n JsonSerialisation.JObjectToDictionaryRuntimeObjs(temps);\n } else {\n el.temporaryVariables.clear();\n }\n\n this.callstack.push(el);\n }\n\n let prevContentObjPath = jThreadObj[\"previousContentObject\"];\n if (typeof prevContentObjPath !== \"undefined\") {\n let prevPath = new Path(prevContentObjPath.toString());\n this.previousPointer = storyContext.PointerAtPath(prevPath);\n }\n }\n }\n\n public Copy() {\n let copy = new Thread();\n copy.threadIndex = this.threadIndex;\n for (let e of this.callstack) {\n copy.callstack.push(e.Copy());\n }\n copy.previousPointer = this.previousPointer.copy();\n return copy;\n }\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n\n writer.WritePropertyStart(\"callstack\");\n writer.WriteArrayStart();\n for (let el of this.callstack) {\n writer.WriteObjectStart();\n if (!el.currentPointer.isNull) {\n if (el.currentPointer.container === null) {\n return throwNullException(\"el.currentPointer.container\");\n }\n writer.WriteProperty(\n \"cPath\",\n el.currentPointer.container.path.componentsString\n );\n writer.WriteIntProperty(\"idx\", el.currentPointer.index);\n }\n\n writer.WriteProperty(\"exp\", el.inExpressionEvaluation);\n writer.WriteIntProperty(\"type\", el.type);\n\n if (el.temporaryVariables.size > 0) {\n writer.WritePropertyStart(\"temp\");\n JsonSerialisation.WriteDictionaryRuntimeObjs(\n writer,\n el.temporaryVariables\n );\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n }\n writer.WriteArrayEnd();\n writer.WritePropertyEnd();\n\n writer.WriteIntProperty(\"threadIndex\", this.threadIndex);\n\n if (!this.previousPointer.isNull) {\n let resolvedPointer = this.previousPointer.Resolve();\n if (resolvedPointer === null) {\n return throwNullException(\"this.previousPointer.Resolve()\");\n }\n writer.WriteProperty(\n \"previousContentObject\",\n resolvedPointer.path.toString()\n );\n }\n\n writer.WriteObjectEnd();\n }\n }\n}\n","import {\n AbstractValue,\n Value,\n VariablePointerValue,\n ListValue,\n IntValue,\n FloatValue,\n BoolValue,\n} from \"./Value\";\nimport { VariableAssignment } from \"./VariableAssignment\";\nimport { InkObject } from \"./Object\";\nimport { ListDefinitionsOrigin } from \"./ListDefinitionsOrigin\";\nimport { StoryException } from \"./StoryException\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { asOrThrows, asOrNull, isEquatable } from \"./TypeAssertion\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\nimport { CallStack } from \"./CallStack\";\nimport { StatePatch } from \"./StatePatch\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { InkList } from \"./Story\";\nimport { Path } from \"./Path\";\n\n// Fake class wrapper around VariableState to have correct typing\n// when using the Proxy syntax in typescript\nfunction VariablesStateAccessor(): new () => Pick {\n return class {} as any;\n}\n\ntype VariableStateValue = boolean | string | number | InkList | Path | null;\n\nexport class VariablesState extends VariablesStateAccessor<\n Record\n>() {\n // The way variableChangedEvent is a bit different than the reference implementation.\n // Originally it uses the C# += operator to add delegates, but in js we need to maintain\n // an actual collection of delegates (ie. callbacks) to register a new one, there is a\n // special ObserveVariableChange method below.\n public variableChangedEventCallbacks: Array<\n (variableName: string, newValue: InkObject) => void\n > = [];\n public variableChangedEvent(variableName: string, newValue: InkObject): void {\n for (let callback of this.variableChangedEventCallbacks) {\n callback(variableName, newValue);\n }\n }\n\n public patch: StatePatch | null = null;\n\n get batchObservingVariableChanges() {\n return this._batchObservingVariableChanges;\n }\n set batchObservingVariableChanges(value: boolean) {\n this._batchObservingVariableChanges = value;\n if (value) {\n this._changedVariablesForBatchObs = new Set();\n } else {\n if (this._changedVariablesForBatchObs != null) {\n for (let variableName of this._changedVariablesForBatchObs) {\n let currentValue = this._globalVariables.get(variableName);\n if (!currentValue) {\n throwNullException(\"currentValue\");\n } else {\n this.variableChangedEvent(variableName, currentValue);\n }\n }\n\n this._changedVariablesForBatchObs = null;\n }\n }\n }\n\n get callStack() {\n return this._callStack;\n }\n set callStack(callStack) {\n this._callStack = callStack;\n }\n\n private _batchObservingVariableChanges: boolean = false;\n\n // the original code uses a magic getter and setter for global variables,\n // allowing things like variableState['varname]. This is not quite possible\n // in js without a Proxy, so it is replaced with this $ function.\n public $(variableName: string): VariableStateValue;\n public $(variableName: string, value: VariableStateValue): void;\n public $(variableName: string, value?: any) {\n if (typeof value === \"undefined\") {\n let varContents = null;\n\n if (this.patch !== null) {\n varContents = this.patch.TryGetGlobal(variableName, null);\n if (varContents.exists)\n return (varContents.result as AbstractValue).valueObject;\n }\n\n varContents = this._globalVariables.get(variableName);\n\n if (typeof varContents === \"undefined\") {\n varContents = this._defaultGlobalVariables.get(variableName);\n }\n\n if (typeof varContents !== \"undefined\")\n return (varContents as AbstractValue).valueObject;\n else return null;\n } else {\n if (typeof this._defaultGlobalVariables.get(variableName) === \"undefined\")\n throw new StoryException(\n \"Cannot assign to a variable (\" +\n variableName +\n \") that hasn't been declared in the story\"\n );\n\n let val = Value.Create(value);\n if (val == null) {\n if (value == null) {\n throw new Error(\"Cannot pass null to VariableState\");\n } else {\n throw new Error(\n \"Invalid value passed to VariableState: \" + value.toString()\n );\n }\n }\n\n this.SetGlobal(variableName, val);\n }\n }\n\n constructor(\n callStack: CallStack,\n listDefsOrigin: ListDefinitionsOrigin | null\n ) {\n super();\n this._globalVariables = new Map();\n this._callStack = callStack;\n this._listDefsOrigin = listDefsOrigin;\n\n // if es6 proxies are available, use them.\n try {\n // the proxy is used to allow direct manipulation of global variables.\n // It first tries to access the objects own property, and if none is\n // found it delegates the call to the $ method, defined below\n let p = new Proxy(this, {\n get(target: any, name) {\n return name in target ? target[name] : target.$(name);\n },\n set(target: any, name, value) {\n if (name in target) target[name] = value;\n else target.$(name, value);\n return true; // returning a falsy value make the trap fail\n },\n });\n\n return p;\n } catch (e) {\n // the proxy object is not available in this context. we should warn the\n // dev but writing to the console feels a bit intrusive.\n // console.log(\"ES6 Proxy not available - direct manipulation of global variables can't work, use $() instead.\");\n }\n }\n\n public ApplyPatch() {\n if (this.patch === null) {\n return throwNullException(\"this.patch\");\n }\n\n for (let [namedVarKey, namedVarValue] of this.patch.globals) {\n this._globalVariables.set(namedVarKey, namedVarValue);\n }\n\n if (this._changedVariablesForBatchObs !== null) {\n for (let name of this.patch.changedVariables) {\n this._changedVariablesForBatchObs.add(name);\n }\n }\n\n this.patch = null;\n }\n\n public SetJsonToken(jToken: Record) {\n this._globalVariables.clear();\n\n for (let [varValKey, varValValue] of this._defaultGlobalVariables) {\n let loadedToken = jToken[varValKey];\n if (typeof loadedToken !== \"undefined\") {\n let tokenInkObject =\n JsonSerialisation.JTokenToRuntimeObject(loadedToken);\n if (tokenInkObject === null) {\n return throwNullException(\"tokenInkObject\");\n }\n this._globalVariables.set(varValKey, tokenInkObject);\n } else {\n this._globalVariables.set(varValKey, varValValue);\n }\n }\n }\n\n public static dontSaveDefaultValues: boolean = true;\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n for (let [keyValKey, keyValValue] of this._globalVariables) {\n let name = keyValKey;\n let val = keyValValue;\n\n if (VariablesState.dontSaveDefaultValues) {\n if (this._defaultGlobalVariables.has(name)) {\n let defaultVal = this._defaultGlobalVariables.get(name)!;\n if (this.RuntimeObjectsEqual(val, defaultVal)) continue;\n }\n }\n\n writer.WritePropertyStart(name);\n JsonSerialisation.WriteRuntimeObject(writer, val);\n writer.WritePropertyEnd();\n }\n writer.WriteObjectEnd();\n }\n\n public RuntimeObjectsEqual(\n obj1: InkObject | null,\n obj2: InkObject | null\n ): boolean {\n if (obj1 === null) {\n return throwNullException(\"obj1\");\n }\n if (obj2 === null) {\n return throwNullException(\"obj2\");\n }\n\n if (obj1.constructor !== obj2.constructor) return false;\n\n let boolVal = asOrNull(obj1, BoolValue);\n if (boolVal !== null) {\n return boolVal.value === asOrThrows(obj2, BoolValue).value;\n }\n\n let intVal = asOrNull(obj1, IntValue);\n if (intVal !== null) {\n return intVal.value === asOrThrows(obj2, IntValue).value;\n }\n\n let floatVal = asOrNull(obj1, FloatValue);\n if (floatVal !== null) {\n return floatVal.value === asOrThrows(obj2, FloatValue).value;\n }\n\n let val1 = asOrNull(obj1, Value);\n let val2 = asOrNull(obj2, Value);\n if (val1 !== null && val2 !== null) {\n if (isEquatable(val1.valueObject) && isEquatable(val2.valueObject)) {\n return val1.valueObject.Equals(val2.valueObject);\n } else {\n return val1.valueObject === val2.valueObject;\n }\n }\n\n throw new Error(\n \"FastRoughDefinitelyEquals: Unsupported runtime object type: \" +\n obj1.constructor.name\n );\n }\n\n public GetVariableWithName(\n name: string | null,\n contextIndex: number = -1\n ): InkObject | null {\n let varValue = this.GetRawVariableWithName(name, contextIndex);\n\n // var varPointer = varValue as VariablePointerValue;\n let varPointer = asOrNull(varValue, VariablePointerValue);\n if (varPointer !== null) {\n varValue = this.ValueAtVariablePointer(varPointer);\n }\n\n return varValue;\n }\n\n public TryGetDefaultVariableValue(name: string | null): InkObject | null {\n let val = tryGetValueFromMap(this._defaultGlobalVariables, name, null);\n return val.exists ? val.result : null;\n }\n\n public GlobalVariableExistsWithName(name: string) {\n return (\n this._globalVariables.has(name) ||\n (this._defaultGlobalVariables !== null &&\n this._defaultGlobalVariables.has(name))\n );\n }\n\n public GetRawVariableWithName(name: string | null, contextIndex: number) {\n let varValue: InkObject | null = null;\n\n if (contextIndex == 0 || contextIndex == -1) {\n let variableValue = null;\n if (this.patch !== null) {\n variableValue = this.patch.TryGetGlobal(name, null);\n if (variableValue.exists) return variableValue.result!;\n }\n\n // this is a conditional assignment\n variableValue = tryGetValueFromMap(this._globalVariables, name, null);\n if (variableValue.exists) return variableValue.result;\n\n if (this._defaultGlobalVariables !== null) {\n variableValue = tryGetValueFromMap(\n this._defaultGlobalVariables,\n name,\n null\n );\n if (variableValue.exists) return variableValue.result;\n }\n\n if (this._listDefsOrigin === null)\n return throwNullException(\"VariablesState._listDefsOrigin\");\n let listItemValue = this._listDefsOrigin.FindSingleItemListWithName(name);\n if (listItemValue) return listItemValue;\n }\n\n varValue = this._callStack.GetTemporaryVariableWithName(name, contextIndex);\n\n return varValue;\n }\n\n public ValueAtVariablePointer(pointer: VariablePointerValue) {\n return this.GetVariableWithName(pointer.variableName, pointer.contextIndex);\n }\n\n public Assign(varAss: VariableAssignment, value: InkObject) {\n let name = varAss.variableName;\n if (name === null) {\n return throwNullException(\"name\");\n }\n let contextIndex = -1;\n\n let setGlobal = false;\n if (varAss.isNewDeclaration) {\n setGlobal = varAss.isGlobal;\n } else {\n setGlobal = this.GlobalVariableExistsWithName(name);\n }\n\n if (varAss.isNewDeclaration) {\n // var varPointer = value as VariablePointerValue;\n let varPointer = asOrNull(value, VariablePointerValue);\n if (varPointer !== null) {\n let fullyResolvedVariablePointer =\n this.ResolveVariablePointer(varPointer);\n value = fullyResolvedVariablePointer;\n }\n } else {\n let existingPointer = null;\n do {\n // existingPointer = GetRawVariableWithName (name, contextIndex) as VariablePointerValue;\n existingPointer = asOrNull(\n this.GetRawVariableWithName(name, contextIndex),\n VariablePointerValue\n );\n if (existingPointer != null) {\n name = existingPointer.variableName;\n contextIndex = existingPointer.contextIndex;\n setGlobal = contextIndex == 0;\n }\n } while (existingPointer != null);\n }\n\n if (setGlobal) {\n this.SetGlobal(name, value);\n } else {\n this._callStack.SetTemporaryVariable(\n name,\n value,\n varAss.isNewDeclaration,\n contextIndex\n );\n }\n }\n\n public SnapshotDefaultGlobals() {\n this._defaultGlobalVariables = new Map(this._globalVariables);\n }\n\n public RetainListOriginsForAssignment(\n oldValue: InkObject,\n newValue: InkObject\n ) {\n let oldList = asOrThrows(oldValue, ListValue);\n let newList = asOrThrows(newValue, ListValue);\n\n if (oldList.value && newList.value && newList.value.Count == 0) {\n newList.value.SetInitialOriginNames(oldList.value.originNames);\n }\n }\n\n public SetGlobal(variableName: string | null, value: InkObject) {\n let oldValue = null;\n\n if (this.patch === null) {\n oldValue = tryGetValueFromMap(this._globalVariables, variableName, null);\n }\n\n if (this.patch !== null) {\n oldValue = this.patch.TryGetGlobal(variableName, null);\n if (!oldValue.exists) {\n oldValue = tryGetValueFromMap(\n this._globalVariables,\n variableName,\n null\n );\n }\n }\n\n ListValue.RetainListOriginsForAssignment(oldValue!.result!, value);\n\n if (variableName === null) {\n return throwNullException(\"variableName\");\n }\n\n if (this.patch !== null) {\n this.patch.SetGlobal(variableName, value);\n } else {\n this._globalVariables.set(variableName, value);\n }\n\n // TODO: Not sure !== is equivalent to !value.Equals(oldValue)\n if (\n this.variableChangedEvent !== null &&\n oldValue !== null &&\n value !== oldValue.result\n ) {\n if (this.batchObservingVariableChanges) {\n if (this._changedVariablesForBatchObs === null) {\n return throwNullException(\"this._changedVariablesForBatchObs\");\n }\n\n if (this.patch !== null) {\n this.patch.AddChangedVariable(variableName);\n } else if (this._changedVariablesForBatchObs !== null) {\n this._changedVariablesForBatchObs.add(variableName);\n }\n } else {\n this.variableChangedEvent(variableName, value);\n }\n }\n }\n\n public ResolveVariablePointer(varPointer: VariablePointerValue) {\n let contextIndex = varPointer.contextIndex;\n\n if (contextIndex == -1)\n contextIndex = this.GetContextIndexOfVariableNamed(\n varPointer.variableName\n );\n\n let valueOfVariablePointedTo = this.GetRawVariableWithName(\n varPointer.variableName,\n contextIndex\n );\n\n // var doubleRedirectionPointer = valueOfVariablePointedTo as VariablePointerValue;\n let doubleRedirectionPointer = asOrNull(\n valueOfVariablePointedTo,\n VariablePointerValue\n );\n if (doubleRedirectionPointer != null) {\n return doubleRedirectionPointer;\n } else {\n return new VariablePointerValue(varPointer.variableName, contextIndex);\n }\n }\n\n public GetContextIndexOfVariableNamed(varName: string) {\n if (this.GlobalVariableExistsWithName(varName)) return 0;\n\n return this._callStack.currentElementIndex;\n }\n\n /**\n * This function is specific to the js version of ink. It allows to register a\n * callback that will be called when a variable changes. The original code uses\n * `state.variableChangedEvent += callback` instead.\n *\n * @param {function} callback\n */\n public ObserveVariableChange(\n callback: (variableName: string, newValue: InkObject) => void\n ) {\n this.variableChangedEventCallbacks.push(callback);\n }\n\n private _globalVariables: Map;\n private _defaultGlobalVariables: Map = new Map();\n\n private _callStack: CallStack;\n private _changedVariablesForBatchObs: Set | null = new Set();\n private _listDefsOrigin: ListDefinitionsOrigin | null;\n}\n","// Taken from https://gist.github.com/blixt/f17b47c62508be59987b\n// Ink uses a seedable PRNG of which there is none in native javascript.\nexport class PRNG {\n private seed: number;\n\n constructor(seed: number) {\n this.seed = seed % 2147483647;\n if (this.seed <= 0) this.seed += 2147483646;\n }\n public next(): number {\n return (this.seed = (this.seed * 48271) % 2147483647);\n }\n public nextFloat(): number {\n return (this.next() - 1) / 2147483646;\n }\n}\n","import { InkObject } from \"./Object\";\nimport { Container } from \"./Container\";\n\nexport class StatePatch {\n get globals() {\n return this._globals;\n }\n get changedVariables() {\n return this._changedVariables;\n }\n get visitCounts() {\n return this._visitCounts;\n }\n get turnIndices() {\n return this._turnIndices;\n }\n\n constructor();\n constructor(toCopy: StatePatch | null);\n constructor() {\n if (arguments.length === 1 && arguments[0] !== null) {\n let toCopy = arguments[0] as StatePatch;\n this._globals = new Map(toCopy._globals);\n this._changedVariables = new Set(toCopy._changedVariables);\n this._visitCounts = new Map(toCopy._visitCounts);\n this._turnIndices = new Map(toCopy._turnIndices);\n } else {\n this._globals = new Map();\n this._changedVariables = new Set();\n this._visitCounts = new Map();\n this._turnIndices = new Map();\n }\n }\n\n public TryGetGlobal(name: string | null, /* out */ value: InkObject | null) {\n if (name !== null && this._globals.has(name)) {\n return { result: this._globals.get(name), exists: true };\n }\n\n return { result: value, exists: false };\n }\n\n public SetGlobal(name: string, value: InkObject) {\n this._globals.set(name, value);\n }\n\n public AddChangedVariable(name: string) {\n return this._changedVariables.add(name);\n }\n\n public TryGetVisitCount(container: Container, /* out */ count: number) {\n if (this._visitCounts.has(container)) {\n return { result: this._visitCounts.get(container), exists: true };\n }\n\n return { result: count, exists: false };\n }\n\n public SetVisitCount(container: Container, count: number) {\n this._visitCounts.set(container, count);\n }\n\n public SetTurnIndex(container: Container, index: number) {\n this._turnIndices.set(container, index);\n }\n\n public TryGetTurnIndex(container: Container, /* out */ index: number) {\n if (this._turnIndices.has(container)) {\n return { result: this._turnIndices.get(container), exists: true };\n }\n\n return { result: index, exists: false };\n }\n\n private _globals: Map;\n private _changedVariables: Set = new Set();\n private _visitCounts: Map = new Map();\n private _turnIndices: Map = new Map();\n}\n","export class SimpleJson {\n public static TextToDictionary(text: string) {\n return new SimpleJson.Reader(text).ToDictionary();\n }\n\n public static TextToArray(text: string) {\n return new SimpleJson.Reader(text).ToArray();\n }\n}\n\nexport namespace SimpleJson {\n export class Reader {\n constructor(text: string) {\n this._rootObject = JSON.parse(text);\n }\n\n public ToDictionary() {\n return this._rootObject as Record;\n }\n\n public ToArray() {\n return this._rootObject as any[];\n }\n\n private _rootObject: any[] | Record;\n }\n\n // In C#, this class writes json tokens directly to a StringWriter or\n // another stream. Here, a temporary hierarchy is created in the form\n // of a javascript object, which is serialised in the `toString` method.\n // See individual methods and properties for more information.\n export class Writer {\n public WriteObject(inner: (w: Writer) => void) {\n this.WriteObjectStart();\n inner(this);\n this.WriteObjectEnd();\n }\n\n // Add a new object.\n public WriteObjectStart() {\n this.StartNewObject(true);\n\n let newObject: Record = {};\n\n if (this.state === SimpleJson.Writer.State.Property) {\n // This object is created as the value of a property,\n // inside an other object.\n this.Assert(this.currentCollection !== null);\n this.Assert(this.currentPropertyName !== null);\n\n let propertyName = this._propertyNameStack.pop();\n this.currentCollection![propertyName!] = newObject;\n this._collectionStack.push(newObject);\n } else if (this.state === SimpleJson.Writer.State.Array) {\n // This object is created as the child of an array.\n this.Assert(this.currentCollection !== null);\n\n this.currentCollection!.push(newObject);\n this._collectionStack.push(newObject);\n } else {\n // This object is the root object.\n this.Assert(this.state === SimpleJson.Writer.State.None);\n this._jsonObject = newObject;\n this._collectionStack.push(newObject);\n }\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Object)\n );\n }\n\n public WriteObjectEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.Object);\n this._collectionStack.pop();\n this._stateStack.pop();\n }\n\n // Write a property name / value pair to the current object.\n public WriteProperty(\n name: any,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n innerOrContent: ((w: Writer) => void) | string | boolean | null\n ) {\n this.WritePropertyStart(name);\n if (arguments[1] instanceof Function) {\n let inner = arguments[1];\n inner(this);\n } else {\n let content: string | boolean | null = arguments[1];\n this.Write(content);\n }\n this.WritePropertyEnd();\n }\n\n // Int and Float are separate calls, since there both are\n // numbers in JavaScript, but need to be handled differently.\n\n public WriteIntProperty(name: any, content: number) {\n this.WritePropertyStart(name);\n this.WriteInt(content);\n this.WritePropertyEnd();\n }\n\n public WriteFloatProperty(name: any, content: number) {\n this.WritePropertyStart(name);\n this.WriteFloat(content);\n this.WritePropertyEnd();\n }\n\n // Prepare a new property name, which will be use to add the\n // new object when calling _addToCurrentObject() from a Write\n // method.\n public WritePropertyStart(name: any) {\n this.Assert(this.state === SimpleJson.Writer.State.Object);\n this._propertyNameStack.push(name);\n\n this.IncrementChildCount();\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Property)\n );\n }\n\n public WritePropertyEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.Property);\n this.Assert(this.childCount === 1);\n this._stateStack.pop();\n }\n\n // Prepare a new property name, except this time, the property name\n // will be created by concatenating all the strings passed to\n // WritePropertyNameInner.\n public WritePropertyNameStart() {\n this.Assert(this.state === SimpleJson.Writer.State.Object);\n this.IncrementChildCount();\n\n this._currentPropertyName = \"\";\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Property)\n );\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.PropertyName)\n );\n }\n\n public WritePropertyNameEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.PropertyName);\n this.Assert(this._currentPropertyName !== null);\n this._propertyNameStack.push(this._currentPropertyName!);\n this._currentPropertyName = null;\n this._stateStack.pop();\n }\n\n public WritePropertyNameInner(str: string) {\n this.Assert(this.state === SimpleJson.Writer.State.PropertyName);\n this.Assert(this._currentPropertyName !== null);\n this._currentPropertyName += str;\n }\n\n // Add a new array.\n public WriteArrayStart() {\n this.StartNewObject(true);\n\n let newObject: any[] = [];\n\n if (this.state === SimpleJson.Writer.State.Property) {\n // This array is created as the value of a property,\n // inside an object.\n this.Assert(this.currentCollection !== null);\n this.Assert(this.currentPropertyName !== null);\n\n let propertyName = this._propertyNameStack.pop();\n this.currentCollection![propertyName!] = newObject;\n this._collectionStack.push(newObject);\n } else if (this.state === SimpleJson.Writer.State.Array) {\n // This array is created as the child of another array.\n this.Assert(this.currentCollection !== null);\n\n this.currentCollection!.push(newObject);\n this._collectionStack.push(newObject);\n } else {\n // This array is the root object.\n this.Assert(this.state === SimpleJson.Writer.State.None);\n this._jsonObject = newObject;\n this._collectionStack.push(newObject);\n }\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Array)\n );\n }\n\n public WriteArrayEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.Array);\n this._collectionStack.pop();\n this._stateStack.pop();\n }\n\n // Add the value to the appropriate collection (array / object), given the current\n // context.\n public Write(\n value: number | string | boolean | null,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n escape: boolean = true\n ) {\n if (value === null) {\n console.error(\"Warning: trying to write a null value\");\n return;\n }\n\n this.StartNewObject(false);\n this._addToCurrentObject(value);\n }\n\n public WriteBool(value: boolean | null) {\n if (value === null) {\n return;\n }\n\n this.StartNewObject(false);\n this._addToCurrentObject(value);\n }\n\n public WriteInt(value: number | null) {\n if (value === null) {\n return;\n }\n\n this.StartNewObject(false);\n\n // Math.floor is used as a precaution:\n // 1. to ensure that the value is written as an integer\n // (without a fractional part -> 1 instead of 1.0), even\n // though it should be the default behaviour of\n // JSON.serialize;\n // 2. to ensure that if a floating number is passed\n // accidentally, it's converted to an integer.\n //\n // This guarantees savegame compatibility with the reference\n // implementation.\n this._addToCurrentObject(Math.floor(value));\n }\n\n // Since JSON doesn't support NaN and Infinity, these values\n // are converted here.\n public WriteFloat(value: number | null) {\n if (value === null) {\n return;\n }\n\n this.StartNewObject(false);\n if (value == Number.POSITIVE_INFINITY) {\n this._addToCurrentObject(3.4e38);\n } else if (value == Number.NEGATIVE_INFINITY) {\n this._addToCurrentObject(-3.4e38);\n } else if (isNaN(value)) {\n this._addToCurrentObject(0.0);\n } else {\n this._addToCurrentObject(value);\n }\n }\n\n public WriteNull() {\n this.StartNewObject(false);\n this._addToCurrentObject(null);\n }\n\n // Prepare a string before adding it to the current collection in\n // WriteStringEnd(). The string will be a concatenation of all the\n // strings passed to WriteStringInner.\n public WriteStringStart() {\n this.StartNewObject(false);\n this._currentString = \"\";\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.String)\n );\n }\n\n public WriteStringEnd() {\n this.Assert(this.state == SimpleJson.Writer.State.String);\n this._stateStack.pop();\n this._addToCurrentObject(this._currentString);\n this._currentString = null;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public WriteStringInner(str: string | null, escape: boolean = true) {\n this.Assert(this.state === SimpleJson.Writer.State.String);\n\n if (str === null) {\n console.error(\"Warning: trying to write a null string\");\n return;\n }\n\n this._currentString += str;\n }\n\n // Serialise the root object into a JSON string.\n public toString() {\n if (this._jsonObject === null) {\n return \"\";\n }\n\n return JSON.stringify(this._jsonObject);\n }\n\n // Prepare the state stack when adding new objects / values.\n private StartNewObject(container: boolean) {\n if (container) {\n this.Assert(\n this.state === SimpleJson.Writer.State.None ||\n this.state === SimpleJson.Writer.State.Property ||\n this.state === SimpleJson.Writer.State.Array\n );\n } else {\n this.Assert(\n this.state === SimpleJson.Writer.State.Property ||\n this.state === SimpleJson.Writer.State.Array\n );\n }\n\n if (this.state === SimpleJson.Writer.State.Property) {\n this.Assert(this.childCount === 0);\n }\n\n if (\n this.state === SimpleJson.Writer.State.Array ||\n this.state === SimpleJson.Writer.State.Property\n ) {\n this.IncrementChildCount();\n }\n }\n\n // These getters peek all the different stacks.\n\n private get state() {\n if (this._stateStack.length > 0) {\n return this._stateStack[this._stateStack.length - 1].type;\n } else {\n return SimpleJson.Writer.State.None;\n }\n }\n\n private get childCount() {\n if (this._stateStack.length > 0) {\n return this._stateStack[this._stateStack.length - 1].childCount;\n } else {\n return 0;\n }\n }\n\n private get currentCollection() {\n if (this._collectionStack.length > 0) {\n return this._collectionStack[this._collectionStack.length - 1];\n } else {\n return null;\n }\n }\n\n private get currentPropertyName() {\n if (this._propertyNameStack.length > 0) {\n return this._propertyNameStack[this._propertyNameStack.length - 1];\n } else {\n return null;\n }\n }\n\n private IncrementChildCount() {\n this.Assert(this._stateStack.length > 0);\n let currEl = this._stateStack.pop()!;\n currEl.childCount++;\n this._stateStack.push(currEl);\n }\n\n private Assert(condition: boolean) {\n if (!condition) throw Error(\"Assert failed while writing JSON\");\n }\n\n // This method did not exist in the original C# code. It adds\n // the given value to the current collection (used by Write methods).\n private _addToCurrentObject(value: number | string | boolean | null) {\n this.Assert(this.currentCollection !== null);\n if (this.state === SimpleJson.Writer.State.Array) {\n this.Assert(Array.isArray(this.currentCollection));\n (this.currentCollection as any[]).push(value);\n } else if (this.state === SimpleJson.Writer.State.Property) {\n this.Assert(!Array.isArray(this.currentCollection));\n this.Assert(this.currentPropertyName !== null);\n (this.currentCollection as Record)[\n this.currentPropertyName!\n ] = value;\n this._propertyNameStack.pop();\n }\n }\n\n // In addition to `_stateStack` present in the original code,\n // this implementation of SimpleJson use two other stacks and two\n // temporary variables holding the current context.\n\n // Used to keep track of the current property name being built\n // with `WritePropertyNameStart`, `WritePropertyNameInner` and\n // `WritePropertyNameEnd`.\n private _currentPropertyName: string | null = null;\n\n // Used to keep track of the current string value being built\n // with `WriteStringStart`, `WriteStringInner` and\n // `WriteStringEnd`.\n private _currentString: string | null = null;\n\n private _stateStack: SimpleJson.Writer.StateElement[] = [];\n\n // Keep track of the current collection being built (either an array\n // or an object). For instance, at the '?' step during the hiarchy\n // creation, this hierarchy:\n // [3, {a: [b, ?]}] will have this corresponding stack:\n // (bottom) [Array, Object, Array] (top)\n private _collectionStack: Array> = [];\n\n // Keep track of the current property being assigned. For instance, at\n // the '?' step during the hiarchy creation, this hierarchy:\n // [3, {a: [b, {c: ?}]}] will have this corresponding stack:\n // (bottom) [a, c] (top)\n private _propertyNameStack: string[] = [];\n\n // Object containing the entire hiearchy.\n private _jsonObject: Record | any[] | null = null;\n }\n\n export namespace Writer {\n export enum State {\n None,\n Object,\n Array,\n Property,\n PropertyName,\n String,\n }\n\n export class StateElement {\n public type: SimpleJson.Writer.State = SimpleJson.Writer.State.None;\n public childCount: number = 0;\n\n constructor(type: SimpleJson.Writer.State) {\n this.type = type;\n }\n }\n }\n}\n","import { CallStack } from \"./CallStack\";\nimport { Choice } from \"./Choice\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { InkObject } from \"./Object\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { Story } from \"./Story\";\nimport { throwNullException } from \"./NullException\";\n\nexport class Flow {\n public name: string;\n public callStack: CallStack;\n public outputStream: InkObject[];\n public currentChoices: Choice[];\n\n constructor(name: String, story: Story);\n constructor(name: String, story: Story, jObject: Record);\n constructor() {\n let name = arguments[0] as string;\n let story = arguments[1] as Story;\n\n this.name = name;\n this.callStack = new CallStack(story);\n\n if (arguments[2]) {\n let jObject = arguments[2] as Record;\n\n this.callStack.SetJsonToken(jObject[\"callstack\"], story);\n this.outputStream = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"outputStream\"]\n );\n this.currentChoices = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"currentChoices\"]\n ) as Choice[];\n\n let jChoiceThreadsObj = jObject[\"choiceThreads\"];\n if (typeof jChoiceThreadsObj !== \"undefined\") {\n this.LoadFlowChoiceThreads(jChoiceThreadsObj, story);\n }\n } else {\n this.outputStream = [];\n this.currentChoices = [];\n }\n }\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n\n writer.WriteProperty(\"callstack\", (w) => this.callStack.WriteJson(w));\n writer.WriteProperty(\"outputStream\", (w) =>\n JsonSerialisation.WriteListRuntimeObjs(w, this.outputStream)\n );\n\n let hasChoiceThreads = false;\n for (let c of this.currentChoices) {\n if (c.threadAtGeneration === null)\n return throwNullException(\"c.threadAtGeneration\");\n\n c.originalThreadIndex = c.threadAtGeneration.threadIndex;\n\n if (this.callStack.ThreadWithIndex(c.originalThreadIndex) === null) {\n if (!hasChoiceThreads) {\n hasChoiceThreads = true;\n writer.WritePropertyStart(\"choiceThreads\");\n writer.WriteObjectStart();\n }\n\n writer.WritePropertyStart(c.originalThreadIndex);\n c.threadAtGeneration.WriteJson(writer);\n writer.WritePropertyEnd();\n }\n }\n\n if (hasChoiceThreads) {\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteProperty(\"currentChoices\", (w) => {\n w.WriteArrayStart();\n for (let c of this.currentChoices) {\n JsonSerialisation.WriteChoice(w, c);\n }\n w.WriteArrayEnd();\n });\n\n writer.WriteObjectEnd();\n }\n\n public LoadFlowChoiceThreads(\n jChoiceThreads: Record,\n story: Story\n ) {\n for (let choice of this.currentChoices) {\n let foundActiveThread = this.callStack.ThreadWithIndex(\n choice.originalThreadIndex\n );\n if (foundActiveThread !== null) {\n choice.threadAtGeneration = foundActiveThread.Copy();\n } else {\n let jSavedChoiceThread =\n jChoiceThreads[`${choice.originalThreadIndex}`];\n choice.threadAtGeneration = new CallStack.Thread(\n jSavedChoiceThread,\n story\n );\n }\n }\n }\n}\n","// TODO: Unify with Compiler.\n\nexport type ErrorHandler = (message: string, type: ErrorType) => void;\n\nexport enum ErrorType {\n Author,\n Warning,\n Error,\n}\n","import { CallStack } from \"./CallStack\";\nimport { VariablesState } from \"./VariablesState\";\nimport { ValueType, Value, StringValue, ListValue } from \"./Value\";\nimport { PushPopType } from \"./PushPop\";\nimport { Tag } from \"./Tag\";\nimport { Glue } from \"./Glue\";\nimport { Path } from \"./Path\";\nimport { ControlCommand } from \"./ControlCommand\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { PRNG } from \"./PRNG\";\nimport { Void } from \"./Void\";\nimport { Pointer } from \"./Pointer\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { Choice } from \"./Choice\";\nimport { asOrNull, asOrThrows, nullIfUndefined } from \"./TypeAssertion\";\nimport { Debug } from \"./Debug\";\nimport { Container } from \"./Container\";\nimport { InkObject } from \"./Object\";\nimport { throwNullException } from \"./NullException\";\nimport { Story } from \"./Story\";\nimport { StatePatch } from \"./StatePatch\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { Flow } from \"./Flow\";\nimport { InkList } from \"./InkList\";\n\nexport class StoryState {\n // Backward compatible changes since v8:\n // v10: dynamic tags\n // v9: multi-flows\n public readonly kInkSaveStateVersion = 10;\n public readonly kMinCompatibleLoadVersion = 8;\n\n public onDidLoadState: (() => void) | null = null;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public ToJson(indented: boolean = false) {\n let writer = new SimpleJson.Writer();\n this.WriteJson(writer);\n return writer.toString();\n }\n public toJson(indented: boolean = false) {\n return this.ToJson(indented);\n }\n\n public LoadJson(json: string) {\n let jObject = SimpleJson.TextToDictionary(json);\n this.LoadJsonObj(jObject);\n if (this.onDidLoadState !== null) this.onDidLoadState();\n }\n\n public VisitCountAtPathString(pathString: string) {\n let visitCountOut;\n\n if (this._patch !== null) {\n let container = this.story.ContentAtPath(new Path(pathString)).container;\n if (container === null)\n throw new Error(\"Content at path not found: \" + pathString);\n\n visitCountOut = this._patch.TryGetVisitCount(container, 0);\n if (visitCountOut.exists) return visitCountOut.result;\n }\n\n visitCountOut = tryGetValueFromMap(this._visitCounts, pathString, null);\n if (visitCountOut.exists) return visitCountOut.result;\n\n return 0;\n }\n\n public VisitCountForContainer(container: Container | null): number {\n if (container === null) {\n return throwNullException(\"container\");\n }\n if (!container.visitsShouldBeCounted) {\n this.story.Error(\n \"Read count for target (\" +\n container.name +\n \" - on \" +\n container.debugMetadata +\n \") unknown. The story may need to be compiled with countAllVisits flag (-c).\"\n );\n return 0;\n }\n\n if (this._patch !== null) {\n let count = this._patch.TryGetVisitCount(container, 0);\n if (count.exists) {\n return count.result!;\n }\n }\n\n let containerPathStr = container.path.toString();\n let count2 = tryGetValueFromMap(this._visitCounts, containerPathStr, null);\n if (count2.exists) {\n return count2.result!;\n }\n\n return 0;\n }\n\n public IncrementVisitCountForContainer(container: Container) {\n if (this._patch !== null) {\n let currCount = this.VisitCountForContainer(container);\n currCount++;\n this._patch.SetVisitCount(container, currCount);\n return;\n }\n\n let containerPathStr = container.path.toString();\n let count = tryGetValueFromMap(this._visitCounts, containerPathStr, null);\n if (count.exists) {\n this._visitCounts.set(containerPathStr, count.result! + 1);\n } else {\n this._visitCounts.set(containerPathStr, 1);\n }\n }\n\n public RecordTurnIndexVisitToContainer(container: Container) {\n if (this._patch !== null) {\n this._patch.SetTurnIndex(container, this.currentTurnIndex);\n return;\n }\n\n let containerPathStr = container.path.toString();\n this._turnIndices.set(containerPathStr, this.currentTurnIndex);\n }\n\n public TurnsSinceForContainer(container: Container) {\n if (!container.turnIndexShouldBeCounted) {\n this.story.Error(\n \"TURNS_SINCE() for target (\" +\n container.name +\n \" - on \" +\n container.debugMetadata +\n \") unknown. The story may need to be compiled with countAllVisits flag (-c).\"\n );\n }\n\n if (this._patch !== null) {\n let index = this._patch.TryGetTurnIndex(container, 0);\n if (index.exists) {\n return this.currentTurnIndex - index.result!;\n }\n }\n\n let containerPathStr = container.path.toString();\n let index2 = tryGetValueFromMap(this._turnIndices, containerPathStr, 0);\n if (index2.exists) {\n return this.currentTurnIndex - index2.result!;\n } else {\n return -1;\n }\n }\n\n get callstackDepth() {\n return this.callStack.depth;\n }\n\n get outputStream() {\n return this._currentFlow.outputStream;\n }\n\n get currentChoices() {\n // If we can continue generating text content rather than choices,\n // then we reflect the choice list as being empty, since choices\n // should always come at the end.\n if (this.canContinue) return [];\n return this._currentFlow.currentChoices;\n }\n\n get generatedChoices() {\n return this._currentFlow.currentChoices;\n }\n\n get currentErrors() {\n return this._currentErrors;\n }\n private _currentErrors: string[] | null = null;\n\n get currentWarnings() {\n return this._currentWarnings;\n }\n private _currentWarnings: string[] | null = null;\n\n get variablesState() {\n return this._variablesState;\n }\n set variablesState(value) {\n this._variablesState = value;\n }\n private _variablesState: VariablesState;\n\n get callStack() {\n return this._currentFlow.callStack;\n }\n\n get evaluationStack() {\n return this._evaluationStack;\n }\n private _evaluationStack: InkObject[];\n\n public divertedPointer: Pointer = Pointer.Null;\n\n get currentTurnIndex() {\n return this._currentTurnIndex;\n }\n set currentTurnIndex(value) {\n this._currentTurnIndex = value;\n }\n private _currentTurnIndex: number = 0;\n\n public storySeed: number = 0;\n public previousRandom: number = 0;\n public didSafeExit: boolean = false;\n\n public story: Story;\n\n get currentPathString() {\n let pointer = this.currentPointer;\n if (pointer.isNull) {\n return null;\n } else {\n if (pointer.path === null) {\n return throwNullException(\"pointer.path\");\n }\n return pointer.path.toString();\n }\n }\n\n get currentPointer() {\n return this.callStack.currentElement.currentPointer.copy();\n }\n\n set currentPointer(value) {\n this.callStack.currentElement.currentPointer = value.copy();\n }\n\n get previousPointer() {\n return this.callStack.currentThread.previousPointer.copy();\n }\n\n set previousPointer(value) {\n this.callStack.currentThread.previousPointer = value.copy();\n }\n\n get canContinue() {\n return !this.currentPointer.isNull && !this.hasError;\n }\n\n get hasError() {\n return this.currentErrors != null && this.currentErrors.length > 0;\n }\n\n get hasWarning() {\n return this.currentWarnings != null && this.currentWarnings.length > 0;\n }\n\n get currentText() {\n if (this._outputStreamTextDirty) {\n let sb = new StringBuilder();\n\n let inTag: boolean = false;\n\n for (let outputObj of this.outputStream) {\n // var textContent = outputObj as StringValue;\n let textContent = asOrNull(outputObj, StringValue);\n if (!inTag && textContent !== null) {\n sb.Append(textContent.value);\n } else {\n let controlCommand = asOrNull(outputObj, ControlCommand);\n if (controlCommand !== null) {\n if (\n controlCommand.commandType == ControlCommand.CommandType.BeginTag\n ) {\n inTag = true;\n } else if (\n controlCommand.commandType == ControlCommand.CommandType.EndTag\n ) {\n inTag = false;\n }\n }\n }\n }\n\n this._currentText = this.CleanOutputWhitespace(sb.toString());\n this._outputStreamTextDirty = false;\n }\n\n return this._currentText;\n }\n private _currentText: string | null = null;\n\n public CleanOutputWhitespace(str: string) {\n let sb = new StringBuilder();\n\n let currentWhitespaceStart = -1;\n let startOfLine = 0;\n\n for (let i = 0; i < str.length; i++) {\n let c = str.charAt(i);\n\n let isInlineWhitespace = c == \" \" || c == \"\\t\";\n\n if (isInlineWhitespace && currentWhitespaceStart == -1)\n currentWhitespaceStart = i;\n\n if (!isInlineWhitespace) {\n if (\n c != \"\\n\" &&\n currentWhitespaceStart > 0 &&\n currentWhitespaceStart != startOfLine\n ) {\n sb.Append(\" \");\n }\n currentWhitespaceStart = -1;\n }\n\n if (c == \"\\n\") startOfLine = i + 1;\n\n if (!isInlineWhitespace) sb.Append(c);\n }\n\n return sb.toString();\n }\n\n get currentTags() {\n if (this._outputStreamTagsDirty) {\n this._currentTags = [];\n let inTag: boolean = false;\n let sb = new StringBuilder();\n\n for (let outputObj of this.outputStream) {\n let controlCommand = asOrNull(outputObj, ControlCommand);\n if (controlCommand != null) {\n if (\n controlCommand.commandType == ControlCommand.CommandType.BeginTag\n ) {\n if (inTag && sb.Length > 0) {\n let txt = this.CleanOutputWhitespace(sb.toString());\n this._currentTags.push(txt);\n sb.Clear();\n }\n inTag = true;\n } else if (\n controlCommand.commandType == ControlCommand.CommandType.EndTag\n ) {\n if (sb.Length > 0) {\n let txt = this.CleanOutputWhitespace(sb.toString());\n this._currentTags.push(txt);\n sb.Clear();\n }\n inTag = false;\n }\n } else if (inTag) {\n let strVal = asOrNull(outputObj, StringValue);\n if (strVal !== null) {\n sb.Append(strVal.value);\n }\n } else {\n let tag = asOrNull(outputObj, Tag);\n if (tag != null && tag.text != null && tag.text.length > 0) {\n this._currentTags.push(tag.text); // tag.text has whitespae already cleaned\n }\n }\n }\n\n if (sb.Length > 0) {\n let txt = this.CleanOutputWhitespace(sb.toString());\n this._currentTags.push(txt);\n sb.Clear();\n }\n\n this._outputStreamTagsDirty = false;\n }\n\n return this._currentTags;\n }\n private _currentTags: string[] | null = null;\n\n get currentFlowName() {\n return this._currentFlow.name;\n }\n\n get currentFlowIsDefaultFlow() {\n return this._currentFlow.name == this.kDefaultFlowName;\n }\n\n get aliveFlowNames() {\n if (this._aliveFlowNamesDirty) {\n this._aliveFlowNames = [];\n\n if (this._namedFlows != null) {\n for (let flowName of this._namedFlows.keys()) {\n if (flowName != this.kDefaultFlowName) {\n this._aliveFlowNames.push(flowName);\n }\n }\n }\n\n this._aliveFlowNamesDirty = false;\n }\n\n return this._aliveFlowNames;\n }\n\n get inExpressionEvaluation() {\n return this.callStack.currentElement.inExpressionEvaluation;\n }\n set inExpressionEvaluation(value) {\n this.callStack.currentElement.inExpressionEvaluation = value;\n }\n\n constructor(story: Story) {\n this.story = story;\n\n this._currentFlow = new Flow(this.kDefaultFlowName, story);\n this.OutputStreamDirty();\n\n this._aliveFlowNamesDirty = true;\n this._evaluationStack = [];\n\n this._variablesState = new VariablesState(\n this.callStack,\n story.listDefinitions\n );\n\n this._visitCounts = new Map();\n this._turnIndices = new Map();\n this.currentTurnIndex = -1;\n\n let timeSeed = new Date().getTime();\n this.storySeed = new PRNG(timeSeed).next() % 100;\n this.previousRandom = 0;\n\n this.GoToStart();\n }\n\n public GoToStart() {\n this.callStack.currentElement.currentPointer = Pointer.StartOf(\n this.story.mainContentContainer\n );\n }\n\n public SwitchFlow_Internal(flowName: string | null) {\n if (flowName === null)\n throw new Error(\"Must pass a non-null string to Story.SwitchFlow\");\n\n if (this._namedFlows === null) {\n this._namedFlows = new Map();\n this._namedFlows.set(this.kDefaultFlowName, this._currentFlow);\n }\n\n if (flowName === this._currentFlow.name) {\n return;\n }\n\n let flow: Flow;\n let content = tryGetValueFromMap(this._namedFlows, flowName, null);\n if (content.exists) {\n flow = content.result!;\n } else {\n flow = new Flow(flowName, this.story);\n this._namedFlows.set(flowName, flow);\n this._aliveFlowNamesDirty = true;\n }\n\n this._currentFlow = flow;\n this.variablesState.callStack = this._currentFlow.callStack;\n\n this.OutputStreamDirty();\n }\n\n public SwitchToDefaultFlow_Internal() {\n if (this._namedFlows === null) return;\n this.SwitchFlow_Internal(this.kDefaultFlowName);\n }\n\n public RemoveFlow_Internal(flowName: string | null) {\n if (flowName === null)\n throw new Error(\"Must pass a non-null string to Story.DestroyFlow\");\n if (flowName === this.kDefaultFlowName)\n throw new Error(\"Cannot destroy default flow\");\n\n if (this._currentFlow.name === flowName) {\n this.SwitchToDefaultFlow_Internal();\n }\n\n if (this._namedFlows === null)\n return throwNullException(\"this._namedFlows\");\n this._namedFlows.delete(flowName);\n this._aliveFlowNamesDirty = true;\n }\n\n public CopyAndStartPatching() {\n let copy = new StoryState(this.story);\n\n copy._patch = new StatePatch(this._patch);\n\n copy._currentFlow.name = this._currentFlow.name;\n copy._currentFlow.callStack = new CallStack(this._currentFlow.callStack);\n copy._currentFlow.currentChoices.push(...this._currentFlow.currentChoices);\n copy._currentFlow.outputStream.push(...this._currentFlow.outputStream);\n copy.OutputStreamDirty();\n\n if (this._namedFlows !== null) {\n copy._namedFlows = new Map();\n for (let [namedFlowKey, namedFlowValue] of this._namedFlows) {\n copy._namedFlows.set(namedFlowKey, namedFlowValue);\n copy._aliveFlowNamesDirty = true;\n }\n copy._namedFlows.set(this._currentFlow.name, copy._currentFlow);\n }\n\n if (this.hasError) {\n copy._currentErrors = [];\n copy._currentErrors.push(...(this.currentErrors || []));\n }\n\n if (this.hasWarning) {\n copy._currentWarnings = [];\n copy._currentWarnings.push(...(this.currentWarnings || []));\n }\n\n copy.variablesState = this.variablesState;\n copy.variablesState.callStack = copy.callStack;\n copy.variablesState.patch = copy._patch;\n\n copy.evaluationStack.push(...this.evaluationStack);\n\n if (!this.divertedPointer.isNull)\n copy.divertedPointer = this.divertedPointer.copy();\n\n copy.previousPointer = this.previousPointer.copy();\n\n copy._visitCounts = this._visitCounts;\n copy._turnIndices = this._turnIndices;\n\n copy.currentTurnIndex = this.currentTurnIndex;\n copy.storySeed = this.storySeed;\n copy.previousRandom = this.previousRandom;\n\n copy.didSafeExit = this.didSafeExit;\n\n return copy;\n }\n\n public RestoreAfterPatch() {\n this.variablesState.callStack = this.callStack;\n this.variablesState.patch = this._patch;\n }\n\n public ApplyAnyPatch() {\n if (this._patch === null) return;\n\n this.variablesState.ApplyPatch();\n\n for (let [key, value] of this._patch.visitCounts)\n this.ApplyCountChanges(key, value, true);\n\n for (let [key, value] of this._patch.turnIndices)\n this.ApplyCountChanges(key, value, false);\n\n this._patch = null;\n }\n\n public ApplyCountChanges(\n container: Container,\n newCount: number,\n isVisit: boolean\n ) {\n let counts = isVisit ? this._visitCounts : this._turnIndices;\n counts.set(container.path.toString(), newCount);\n }\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n\n writer.WritePropertyStart(\"flows\");\n writer.WriteObjectStart();\n\n // NOTE: Never pass `WriteJson` directly as an argument to `WriteProperty`.\n // Call it inside a function to make sure `this` is correctly bound\n // and passed down the call hierarchy.\n\n if (this._namedFlows !== null) {\n for (let [namedFlowKey, namedFlowValue] of this._namedFlows) {\n writer.WriteProperty(namedFlowKey, (w) => namedFlowValue.WriteJson(w));\n }\n } else {\n writer.WriteProperty(this._currentFlow.name, (w) =>\n this._currentFlow.WriteJson(w)\n );\n }\n\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n\n writer.WriteProperty(\"currentFlowName\", this._currentFlow.name);\n\n writer.WriteProperty(\"variablesState\", (w) =>\n this.variablesState.WriteJson(w)\n );\n\n writer.WriteProperty(\"evalStack\", (w) =>\n JsonSerialisation.WriteListRuntimeObjs(w, this.evaluationStack)\n );\n\n if (!this.divertedPointer.isNull) {\n if (this.divertedPointer.path === null) {\n return throwNullException(\"divertedPointer\");\n }\n writer.WriteProperty(\n \"currentDivertTarget\",\n this.divertedPointer.path.componentsString\n );\n }\n\n writer.WriteProperty(\"visitCounts\", (w) =>\n JsonSerialisation.WriteIntDictionary(w, this._visitCounts)\n );\n writer.WriteProperty(\"turnIndices\", (w) =>\n JsonSerialisation.WriteIntDictionary(w, this._turnIndices)\n );\n\n writer.WriteIntProperty(\"turnIdx\", this.currentTurnIndex);\n writer.WriteIntProperty(\"storySeed\", this.storySeed);\n writer.WriteIntProperty(\"previousRandom\", this.previousRandom);\n\n writer.WriteIntProperty(\"inkSaveVersion\", this.kInkSaveStateVersion);\n\n writer.WriteIntProperty(\"inkFormatVersion\", Story.inkVersionCurrent);\n\n writer.WriteObjectEnd();\n }\n\n public LoadJsonObj(value: Record) {\n let jObject = value;\n\n let jSaveVersion = jObject[\"inkSaveVersion\"];\n if (jSaveVersion == null) {\n throw new Error(\"ink save format incorrect, can't load.\");\n } else if (parseInt(jSaveVersion) < this.kMinCompatibleLoadVersion) {\n throw new Error(\n \"Ink save format isn't compatible with the current version (saw '\" +\n jSaveVersion +\n \"', but minimum is \" +\n this.kMinCompatibleLoadVersion +\n \"), so can't load.\"\n );\n }\n\n let flowsObj = jObject[\"flows\"];\n if (flowsObj != null) {\n let flowsObjDict = flowsObj as Record;\n\n // Single default flow\n if (Object.keys(flowsObjDict).length === 1) {\n this._namedFlows = null;\n } else if (this._namedFlows === null) {\n this._namedFlows = new Map();\n } else {\n this._namedFlows.clear();\n }\n\n let flowsObjDictEntries = Object.entries(flowsObjDict);\n for (let [namedFlowObjKey, namedFlowObjValue] of flowsObjDictEntries) {\n let name = namedFlowObjKey;\n let flowObj = namedFlowObjValue as Record;\n\n let flow = new Flow(name, this.story, flowObj);\n\n if (Object.keys(flowsObjDict).length === 1) {\n this._currentFlow = new Flow(name, this.story, flowObj);\n } else {\n if (this._namedFlows === null)\n return throwNullException(\"this._namedFlows\");\n this._namedFlows.set(name, flow);\n }\n }\n\n if (this._namedFlows != null && this._namedFlows.size > 1) {\n let currFlowName = jObject[\"currentFlowName\"] as string;\n // Adding a bang at the end, because we're trusting the save, as\n // done in upstream. If the save is corrupted, the execution\n // is undefined.\n this._currentFlow = this._namedFlows.get(currFlowName)!;\n }\n } else {\n this._namedFlows = null;\n this._currentFlow.name = this.kDefaultFlowName;\n this._currentFlow.callStack.SetJsonToken(\n jObject[\"callstackThreads\"] as Record,\n this.story\n );\n this._currentFlow.outputStream = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"outputStream\"] as any[]\n );\n this._currentFlow.currentChoices =\n JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"currentChoices\"] as any[]\n ) as Choice[];\n\n let jChoiceThreadsObj = jObject[\"choiceThreads\"];\n this._currentFlow.LoadFlowChoiceThreads(jChoiceThreadsObj, this.story);\n }\n\n this.OutputStreamDirty();\n this._aliveFlowNamesDirty = true;\n\n this.variablesState.SetJsonToken(jObject[\"variablesState\"]);\n this.variablesState.callStack = this._currentFlow.callStack;\n\n this._evaluationStack = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"evalStack\"]\n );\n\n let currentDivertTargetPath = jObject[\"currentDivertTarget\"];\n if (currentDivertTargetPath != null) {\n let divertPath = new Path(currentDivertTargetPath.toString());\n this.divertedPointer = this.story.PointerAtPath(divertPath);\n }\n\n this._visitCounts = JsonSerialisation.JObjectToIntDictionary(\n jObject[\"visitCounts\"]\n );\n this._turnIndices = JsonSerialisation.JObjectToIntDictionary(\n jObject[\"turnIndices\"]\n );\n this.currentTurnIndex = parseInt(jObject[\"turnIdx\"]);\n this.storySeed = parseInt(jObject[\"storySeed\"]);\n this.previousRandom = parseInt(jObject[\"previousRandom\"]);\n }\n\n public ResetErrors() {\n this._currentErrors = null;\n this._currentWarnings = null;\n }\n public ResetOutput(objs: InkObject[] | null = null) {\n this.outputStream.length = 0;\n if (objs !== null) this.outputStream.push(...objs);\n this.OutputStreamDirty();\n }\n\n public PushToOutputStream(obj: InkObject | null) {\n // var text = obj as StringValue;\n let text = asOrNull(obj, StringValue);\n if (text !== null) {\n let listText = this.TrySplittingHeadTailWhitespace(text);\n if (listText !== null) {\n for (let textObj of listText) {\n this.PushToOutputStreamIndividual(textObj);\n }\n this.OutputStreamDirty();\n return;\n }\n }\n\n this.PushToOutputStreamIndividual(obj);\n this.OutputStreamDirty();\n }\n\n public PopFromOutputStream(count: number) {\n this.outputStream.splice(this.outputStream.length - count, count);\n this.OutputStreamDirty();\n }\n\n public TrySplittingHeadTailWhitespace(single: StringValue) {\n let str = single.value;\n if (str === null) {\n return throwNullException(\"single.value\");\n }\n\n let headFirstNewlineIdx = -1;\n let headLastNewlineIdx = -1;\n for (let i = 0; i < str.length; i++) {\n let c = str[i];\n if (c == \"\\n\") {\n if (headFirstNewlineIdx == -1) headFirstNewlineIdx = i;\n headLastNewlineIdx = i;\n } else if (c == \" \" || c == \"\\t\") continue;\n else break;\n }\n\n let tailLastNewlineIdx = -1;\n let tailFirstNewlineIdx = -1;\n for (let i = str.length - 1; i >= 0; i--) {\n let c = str[i];\n if (c == \"\\n\") {\n if (tailLastNewlineIdx == -1) tailLastNewlineIdx = i;\n tailFirstNewlineIdx = i;\n } else if (c == \" \" || c == \"\\t\") continue;\n else break;\n }\n\n // No splitting to be done?\n if (headFirstNewlineIdx == -1 && tailLastNewlineIdx == -1) return null;\n\n let listTexts: StringValue[] = [];\n let innerStrStart = 0;\n let innerStrEnd = str.length;\n\n if (headFirstNewlineIdx != -1) {\n if (headFirstNewlineIdx > 0) {\n let leadingSpaces = new StringValue(\n str.substring(0, headFirstNewlineIdx)\n );\n listTexts.push(leadingSpaces);\n }\n listTexts.push(new StringValue(\"\\n\"));\n innerStrStart = headLastNewlineIdx + 1;\n }\n\n if (tailLastNewlineIdx != -1) {\n innerStrEnd = tailFirstNewlineIdx;\n }\n\n if (innerStrEnd > innerStrStart) {\n let innerStrText = str.substring(innerStrStart, innerStrEnd);\n listTexts.push(new StringValue(innerStrText));\n }\n\n if (tailLastNewlineIdx != -1 && tailFirstNewlineIdx > headLastNewlineIdx) {\n listTexts.push(new StringValue(\"\\n\"));\n if (tailLastNewlineIdx < str.length - 1) {\n let numSpaces = str.length - tailLastNewlineIdx - 1;\n let trailingSpaces = new StringValue(\n str.substring(\n tailLastNewlineIdx + 1,\n tailLastNewlineIdx + 1 + numSpaces\n )\n );\n listTexts.push(trailingSpaces);\n }\n }\n\n return listTexts;\n }\n\n public PushToOutputStreamIndividual(obj: InkObject | null) {\n let glue = asOrNull(obj, Glue);\n let text = asOrNull(obj, StringValue);\n\n let includeInOutput = true;\n\n if (glue) {\n this.TrimNewlinesFromOutputStream();\n includeInOutput = true;\n } else if (text) {\n let functionTrimIndex = -1;\n let currEl = this.callStack.currentElement;\n if (currEl.type == PushPopType.Function) {\n functionTrimIndex = currEl.functionStartInOutputStream;\n }\n\n let glueTrimIndex = -1;\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let o = this.outputStream[i];\n let c = o instanceof ControlCommand ? o : null;\n let g = o instanceof Glue ? o : null;\n\n if (g != null) {\n glueTrimIndex = i;\n break;\n } else if (\n c != null &&\n c.commandType == ControlCommand.CommandType.BeginString\n ) {\n if (i >= functionTrimIndex) {\n functionTrimIndex = -1;\n }\n break;\n }\n }\n\n let trimIndex = -1;\n if (glueTrimIndex != -1 && functionTrimIndex != -1)\n trimIndex = Math.min(functionTrimIndex, glueTrimIndex);\n else if (glueTrimIndex != -1) trimIndex = glueTrimIndex;\n else trimIndex = functionTrimIndex;\n\n if (trimIndex != -1) {\n if (text.isNewline) {\n includeInOutput = false;\n } else if (text.isNonWhitespace) {\n if (glueTrimIndex > -1) this.RemoveExistingGlue();\n\n if (functionTrimIndex > -1) {\n let callStackElements = this.callStack.elements;\n for (let i = callStackElements.length - 1; i >= 0; i--) {\n let el = callStackElements[i];\n if (el.type == PushPopType.Function) {\n el.functionStartInOutputStream = -1;\n } else {\n break;\n }\n }\n }\n }\n } else if (text.isNewline) {\n if (this.outputStreamEndsInNewline || !this.outputStreamContainsContent)\n includeInOutput = false;\n }\n }\n\n if (includeInOutput) {\n if (obj === null) {\n return throwNullException(\"obj\");\n }\n this.outputStream.push(obj);\n this.OutputStreamDirty();\n }\n }\n\n public TrimNewlinesFromOutputStream() {\n let removeWhitespaceFrom = -1;\n\n let i = this.outputStream.length - 1;\n while (i >= 0) {\n let obj = this.outputStream[i];\n let cmd = asOrNull(obj, ControlCommand);\n let txt = asOrNull(obj, StringValue);\n\n if (cmd != null || (txt != null && txt.isNonWhitespace)) {\n break;\n } else if (txt != null && txt.isNewline) {\n removeWhitespaceFrom = i;\n }\n i--;\n }\n\n // Remove the whitespace\n if (removeWhitespaceFrom >= 0) {\n i = removeWhitespaceFrom;\n while (i < this.outputStream.length) {\n let text = asOrNull(this.outputStream[i], StringValue);\n if (text) {\n this.outputStream.splice(i, 1);\n } else {\n i++;\n }\n }\n }\n\n this.OutputStreamDirty();\n }\n\n public RemoveExistingGlue() {\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let c = this.outputStream[i];\n if (c instanceof Glue) {\n this.outputStream.splice(i, 1);\n } else if (c instanceof ControlCommand) {\n break;\n }\n }\n\n this.OutputStreamDirty();\n }\n\n get outputStreamEndsInNewline() {\n if (this.outputStream.length > 0) {\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let obj = this.outputStream[i];\n if (obj instanceof ControlCommand) break;\n let text = this.outputStream[i];\n if (text instanceof StringValue) {\n if (text.isNewline) return true;\n else if (text.isNonWhitespace) break;\n }\n }\n }\n\n return false;\n }\n\n get outputStreamContainsContent() {\n for (let content of this.outputStream) {\n if (content instanceof StringValue) return true;\n }\n return false;\n }\n\n get inStringEvaluation() {\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let cmd = asOrNull(this.outputStream[i], ControlCommand);\n if (\n cmd instanceof ControlCommand &&\n cmd.commandType == ControlCommand.CommandType.BeginString\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n public PushEvaluationStack(obj: InkObject | null) {\n // var listValue = obj as ListValue;\n let listValue = asOrNull(obj, ListValue);\n if (listValue) {\n // Update origin when list is has something to indicate the list origin\n let rawList = listValue.value;\n if (rawList === null) {\n return throwNullException(\"rawList\");\n }\n\n if (rawList.originNames != null) {\n if (!rawList.origins) rawList.origins = [];\n rawList.origins.length = 0;\n\n for (let n of rawList.originNames) {\n if (this.story.listDefinitions === null)\n return throwNullException(\"StoryState.story.listDefinitions\");\n let def = this.story.listDefinitions.TryListGetDefinition(n, null);\n if (def.result === null)\n return throwNullException(\"StoryState def.result\");\n if (rawList.origins.indexOf(def.result) < 0)\n rawList.origins.push(def.result);\n }\n }\n }\n\n if (obj === null) {\n return throwNullException(\"obj\");\n }\n this.evaluationStack.push(obj);\n }\n\n public PopEvaluationStack(): InkObject;\n public PopEvaluationStack(numberOfObjects: number): InkObject[];\n public PopEvaluationStack(numberOfObjects?: number) {\n if (typeof numberOfObjects === \"undefined\") {\n let obj = this.evaluationStack.pop();\n return nullIfUndefined(obj);\n } else {\n if (numberOfObjects > this.evaluationStack.length) {\n throw new Error(\"trying to pop too many objects\");\n }\n\n let popped = this.evaluationStack.splice(\n this.evaluationStack.length - numberOfObjects,\n numberOfObjects\n );\n return nullIfUndefined(popped);\n }\n }\n\n public PeekEvaluationStack() {\n return this.evaluationStack[this.evaluationStack.length - 1];\n }\n\n public ForceEnd() {\n this.callStack.Reset();\n\n this._currentFlow.currentChoices.length = 0;\n\n this.currentPointer = Pointer.Null;\n this.previousPointer = Pointer.Null;\n\n this.didSafeExit = true;\n }\n\n public TrimWhitespaceFromFunctionEnd() {\n Debug.Assert(this.callStack.currentElement.type == PushPopType.Function);\n let functionStartPoint =\n this.callStack.currentElement.functionStartInOutputStream;\n\n if (functionStartPoint == -1) {\n functionStartPoint = 0;\n }\n\n for (let i = this.outputStream.length - 1; i >= functionStartPoint; i--) {\n let obj = this.outputStream[i];\n let txt = asOrNull(obj, StringValue);\n let cmd = asOrNull(obj, ControlCommand);\n\n if (txt == null) continue;\n if (cmd) break;\n\n if (txt.isNewline || txt.isInlineWhitespace) {\n this.outputStream.splice(i, 1);\n this.OutputStreamDirty();\n } else {\n break;\n }\n }\n }\n\n public PopCallStack(popType: PushPopType | null = null) {\n if (this.callStack.currentElement.type == PushPopType.Function)\n this.TrimWhitespaceFromFunctionEnd();\n\n this.callStack.Pop(popType);\n }\n\n public SetChosenPath(path: Path, incrementingTurnIndex: boolean) {\n // Changing direction, assume we need to clear current set of choices\n this._currentFlow.currentChoices.length = 0;\n\n let newPointer = this.story.PointerAtPath(path);\n if (!newPointer.isNull && newPointer.index == -1) newPointer.index = 0;\n\n this.currentPointer = newPointer;\n\n if (incrementingTurnIndex) {\n this.currentTurnIndex++;\n }\n }\n\n public StartFunctionEvaluationFromGame(\n funcContainer: Container,\n args: any[]\n ) {\n this.callStack.Push(\n PushPopType.FunctionEvaluationFromGame,\n this.evaluationStack.length\n );\n this.callStack.currentElement.currentPointer =\n Pointer.StartOf(funcContainer);\n\n this.PassArgumentsToEvaluationStack(args);\n }\n\n public PassArgumentsToEvaluationStack(args: any[] | null) {\n if (args !== null) {\n for (let i = 0; i < args.length; i++) {\n if (\n !(\n typeof args[i] === \"number\" ||\n typeof args[i] === \"string\" ||\n typeof args[i] === \"boolean\" ||\n args[i] instanceof InkList\n )\n ) {\n throw new Error(\n \"ink arguments when calling EvaluateFunction / ChoosePathStringWithParameters must be\" +\n \"number, string, bool or InkList. Argument was \" +\n (nullIfUndefined(arguments[i]) === null)\n ? \"null\"\n : arguments[i].constructor.name\n );\n }\n\n this.PushEvaluationStack(Value.Create(args[i]));\n }\n }\n }\n\n public TryExitFunctionEvaluationFromGame() {\n if (\n this.callStack.currentElement.type ==\n PushPopType.FunctionEvaluationFromGame\n ) {\n this.currentPointer = Pointer.Null;\n this.didSafeExit = true;\n return true;\n }\n\n return false;\n }\n\n public CompleteFunctionEvaluationFromGame() {\n if (\n this.callStack.currentElement.type !=\n PushPopType.FunctionEvaluationFromGame\n ) {\n throw new Error(\n \"Expected external function evaluation to be complete. Stack trace: \" +\n this.callStack.callStackTrace\n );\n }\n\n let originalEvaluationStackHeight =\n this.callStack.currentElement.evaluationStackHeightWhenPushed;\n\n let returnedObj: InkObject | null = null;\n while (this.evaluationStack.length > originalEvaluationStackHeight) {\n let poppedObj = this.PopEvaluationStack();\n if (returnedObj === null) returnedObj = poppedObj;\n }\n\n this.PopCallStack(PushPopType.FunctionEvaluationFromGame);\n\n if (returnedObj) {\n if (returnedObj instanceof Void) return null;\n\n // Some kind of value, if not void\n // var returnVal = returnedObj as Runtime.Value;\n let returnVal = asOrThrows(returnedObj, Value);\n\n // DivertTargets get returned as the string of components\n // (rather than a Path, which isn't public)\n if (returnVal.valueType == ValueType.DivertTarget) {\n return returnVal.valueObject.toString();\n }\n\n // Other types can just have their exact object type:\n // int, float, string. VariablePointers get returned as strings.\n return returnVal.valueObject;\n }\n\n return null;\n }\n\n public AddError(message: string, isWarning: boolean) {\n if (!isWarning) {\n if (this._currentErrors == null) this._currentErrors = [];\n this._currentErrors.push(message);\n } else {\n if (this._currentWarnings == null) this._currentWarnings = [];\n this._currentWarnings.push(message);\n }\n }\n\n public OutputStreamDirty() {\n this._outputStreamTextDirty = true;\n this._outputStreamTagsDirty = true;\n }\n\n private _visitCounts: Map;\n private _turnIndices: Map;\n\n private _outputStreamTextDirty = true;\n private _outputStreamTagsDirty = true;\n\n private _patch: StatePatch | null = null;\n\n private _currentFlow: Flow;\n private _aliveFlowNames: string[] | null = null;\n private _namedFlows: Map | null = null;\n private readonly kDefaultFlowName = \"DEFAULT_FLOW\";\n private _aliveFlowNamesDirty: boolean = true;\n}\n","// This is simple replacement of the Stopwatch class from the .NET Framework.\n// The original class can count time with much more accuracy than the Javascript version.\n// It might be worth considering using `window.performance` in the browser\n// or `process.hrtime()` in node.\nexport class Stopwatch {\n private startTime: number | undefined;\n\n constructor() {\n this.startTime = undefined;\n }\n\n get ElapsedMilliseconds(): number {\n if (typeof this.startTime === \"undefined\") {\n return 0;\n }\n return new Date().getTime() - this.startTime;\n }\n\n public Start() {\n this.startTime = new Date().getTime();\n }\n public Stop() {\n this.startTime = undefined;\n }\n}\n","import { Container } from \"./Container\";\nimport { InkObject } from \"./Object\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { StoryState } from \"./StoryState\";\nimport { ControlCommand } from \"./ControlCommand\";\nimport { PushPopType } from \"./PushPop\";\nimport { ChoicePoint } from \"./ChoicePoint\";\nimport { Choice } from \"./Choice\";\nimport { Divert } from \"./Divert\";\nimport {\n Value,\n StringValue,\n IntValue,\n DivertTargetValue,\n VariablePointerValue,\n ListValue,\n} from \"./Value\";\nimport { Path } from \"./Path\";\nimport { Void } from \"./Void\";\nimport { Tag } from \"./Tag\";\nimport { VariableAssignment } from \"./VariableAssignment\";\nimport { VariableReference } from \"./VariableReference\";\nimport { NativeFunctionCall } from \"./NativeFunctionCall\";\nimport { StoryException } from \"./StoryException\";\nimport { PRNG } from \"./PRNG\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { ListDefinitionsOrigin } from \"./ListDefinitionsOrigin\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { Stopwatch } from \"./StopWatch\";\nimport { Pointer } from \"./Pointer\";\nimport { InkList, InkListItem, KeyValuePair } from \"./InkList\";\nimport { asOrNull, asOrThrows } from \"./TypeAssertion\";\nimport { DebugMetadata } from \"./DebugMetadata\";\nimport { throwNullException } from \"./NullException\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { ErrorHandler, ErrorType } from \"./Error\";\n\nexport { InkList } from \"./InkList\";\n\nif (!Number.isInteger) {\n Number.isInteger = function isInteger(nVal: any) {\n return (\n typeof nVal === \"number\" &&\n isFinite(nVal) &&\n nVal > -9007199254740992 &&\n nVal < 9007199254740992 &&\n Math.floor(nVal) === nVal\n );\n };\n}\n\nexport class Story extends InkObject {\n public static inkVersionCurrent = 21;\n\n public inkVersionMinimumCompatible = 18;\n\n get currentChoices() {\n let choices: Choice[] = [];\n\n if (this._state === null) {\n return throwNullException(\"this._state\");\n }\n for (let c of this._state.currentChoices) {\n if (!c.isInvisibleDefault) {\n c.index = choices.length;\n choices.push(c);\n }\n }\n\n return choices;\n }\n\n get currentText() {\n this.IfAsyncWeCant(\"call currentText since it's a work in progress\");\n return this.state.currentText;\n }\n\n get currentTags() {\n this.IfAsyncWeCant(\"call currentTags since it's a work in progress\");\n return this.state.currentTags;\n }\n\n get currentErrors() {\n return this.state.currentErrors;\n }\n\n get currentWarnings() {\n return this.state.currentWarnings;\n }\n\n get currentFlowName() {\n return this.state.currentFlowName;\n }\n\n get currentFlowIsDefaultFlow() {\n return this.state.currentFlowIsDefaultFlow;\n }\n\n get aliveFlowNames() {\n return this.state.aliveFlowNames;\n }\n\n get hasError() {\n return this.state.hasError;\n }\n\n get hasWarning() {\n return this.state.hasWarning;\n }\n\n get variablesState() {\n return this.state.variablesState;\n }\n\n get listDefinitions() {\n return this._listDefinitions;\n }\n\n get state() {\n return this._state;\n }\n\n public onError: ErrorHandler | null = null;\n\n public onDidContinue: (() => void) | null = null;\n\n public onMakeChoice: ((arg1: Choice) => void) | null = null;\n\n public onEvaluateFunction: ((arg1: string, arg2: any[]) => void) | null =\n null;\n\n public onCompleteEvaluateFunction:\n | ((arg1: string, arg2: any[], arg3: string, arg4: any) => void)\n | null = null;\n\n public onChoosePathString: ((arg1: string, arg2: any[]) => void) | null =\n null;\n\n // TODO: Implement Profiler\n public StartProfiling() {\n /* */\n }\n public EndProfiling() {\n /* */\n }\n\n constructor(contentContainer: Container, lists: ListDefinition[] | null);\n constructor(jsonString: string);\n constructor(json: Record);\n constructor() {\n super();\n\n // Discrimination between constructors\n let contentContainer: Container;\n let lists: ListDefinition[] | null = null;\n let json: Record | null = null;\n\n if (arguments[0] instanceof Container) {\n contentContainer = arguments[0] as Container;\n\n if (typeof arguments[1] !== \"undefined\") {\n lists = arguments[1] as ListDefinition[];\n }\n\n // ------ Story (Container contentContainer, List lists = null)\n this._mainContentContainer = contentContainer;\n // ------\n } else {\n if (typeof arguments[0] === \"string\") {\n let jsonString = arguments[0] as string;\n json = SimpleJson.TextToDictionary(jsonString);\n } else {\n json = arguments[0] as Record;\n }\n }\n\n // ------ Story (Container contentContainer, List lists = null)\n if (lists != null) this._listDefinitions = new ListDefinitionsOrigin(lists);\n\n this._externals = new Map();\n // ------\n\n // ------ Story(string jsonString) : this((Container)null)\n if (json !== null) {\n let rootObject: Record = json;\n\n let versionObj = rootObject[\"inkVersion\"];\n if (versionObj == null)\n throw new Error(\n \"ink version number not found. Are you sure it's a valid .ink.json file?\"\n );\n\n let formatFromFile = parseInt(versionObj);\n if (formatFromFile > Story.inkVersionCurrent) {\n throw new Error(\n \"Version of ink used to build story was newer than the current version of the engine\"\n );\n } else if (formatFromFile < this.inkVersionMinimumCompatible) {\n throw new Error(\n \"Version of ink used to build story is too old to be loaded by this version of the engine\"\n );\n } else if (formatFromFile != Story.inkVersionCurrent) {\n console.warn(\n \"WARNING: Version of ink used to build story doesn't match current version of engine. Non-critical, but recommend synchronising.\"\n );\n }\n\n let rootToken = rootObject[\"root\"];\n if (rootToken == null)\n throw new Error(\n \"Root node for ink not found. Are you sure it's a valid .ink.json file?\"\n );\n\n let listDefsObj;\n if ((listDefsObj = rootObject[\"listDefs\"])) {\n this._listDefinitions =\n JsonSerialisation.JTokenToListDefinitions(listDefsObj);\n }\n\n this._mainContentContainer = asOrThrows(\n JsonSerialisation.JTokenToRuntimeObject(rootToken),\n Container\n );\n\n this.ResetState();\n }\n // ------\n }\n\n // Merge together `public string ToJson()` and `void ToJson(SimpleJson.Writer writer)`.\n // Will only return a value if writer was not provided.\n public ToJson(writer?: SimpleJson.Writer): string | void {\n let shouldReturn = false;\n\n if (!writer) {\n shouldReturn = true;\n writer = new SimpleJson.Writer();\n }\n\n writer.WriteObjectStart();\n\n writer.WriteIntProperty(\"inkVersion\", Story.inkVersionCurrent);\n\n writer.WriteProperty(\"root\", (w) =>\n JsonSerialisation.WriteRuntimeContainer(w, this._mainContentContainer)\n );\n\n if (this._listDefinitions != null) {\n writer.WritePropertyStart(\"listDefs\");\n writer.WriteObjectStart();\n\n for (let def of this._listDefinitions.lists) {\n writer.WritePropertyStart(def.name);\n writer.WriteObjectStart();\n\n for (let [key, value] of def.items) {\n let item = InkListItem.fromSerializedKey(key);\n let val = value;\n writer.WriteIntProperty(item.itemName, val);\n }\n\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n\n if (shouldReturn) return writer.toString();\n }\n\n public ResetState() {\n this.IfAsyncWeCant(\"ResetState\");\n\n this._state = new StoryState(this);\n this._state.variablesState.ObserveVariableChange(\n this.VariableStateDidChangeEvent.bind(this)\n );\n\n this.ResetGlobals();\n }\n\n public ResetErrors() {\n if (this._state === null) {\n return throwNullException(\"this._state\");\n }\n this._state.ResetErrors();\n }\n\n public ResetCallstack() {\n this.IfAsyncWeCant(\"ResetCallstack\");\n if (this._state === null) {\n return throwNullException(\"this._state\");\n }\n this._state.ForceEnd();\n }\n\n public ResetGlobals() {\n if (this._mainContentContainer.namedContent.get(\"global decl\")) {\n let originalPointer = this.state.currentPointer.copy();\n\n this.ChoosePath(new Path(\"global decl\"), false);\n\n this.ContinueInternal();\n\n this.state.currentPointer = originalPointer;\n }\n\n this.state.variablesState.SnapshotDefaultGlobals();\n }\n\n public SwitchFlow(flowName: string) {\n this.IfAsyncWeCant(\"switch flow\");\n if (this._asyncSaving) {\n throw new Error(\n \"Story is already in background saving mode, can't switch flow to \" +\n flowName\n );\n }\n\n this.state.SwitchFlow_Internal(flowName);\n }\n\n public RemoveFlow(flowName: string) {\n this.state.RemoveFlow_Internal(flowName);\n }\n\n public SwitchToDefaultFlow() {\n this.state.SwitchToDefaultFlow_Internal();\n }\n\n public Continue() {\n this.ContinueAsync(0);\n return this.currentText;\n }\n\n get canContinue() {\n return this.state.canContinue;\n }\n\n get asyncContinueComplete() {\n return !this._asyncContinueActive;\n }\n\n public ContinueAsync(millisecsLimitAsync: number) {\n if (!this._hasValidatedExternals) this.ValidateExternalBindings();\n\n this.ContinueInternal(millisecsLimitAsync);\n }\n\n public ContinueInternal(millisecsLimitAsync = 0) {\n if (this._profiler != null) this._profiler.PreContinue();\n\n let isAsyncTimeLimited = millisecsLimitAsync > 0;\n this._recursiveContinueCount++;\n\n if (!this._asyncContinueActive) {\n this._asyncContinueActive = isAsyncTimeLimited;\n\n if (!this.canContinue) {\n throw new Error(\n \"Can't continue - should check canContinue before calling Continue\"\n );\n }\n\n this._state.didSafeExit = false;\n this._state.ResetOutput();\n\n if (this._recursiveContinueCount == 1)\n this._state.variablesState.batchObservingVariableChanges = true;\n }\n\n let durationStopwatch = new Stopwatch();\n durationStopwatch.Start();\n\n let outputStreamEndsInNewline = false;\n this._sawLookaheadUnsafeFunctionAfterNewline = false;\n do {\n try {\n outputStreamEndsInNewline = this.ContinueSingleStep();\n } catch (e) {\n if (!(e instanceof StoryException)) throw e;\n\n this.AddError(e.message, undefined, e.useEndLineNumber);\n break;\n }\n\n if (outputStreamEndsInNewline) break;\n\n if (\n this._asyncContinueActive &&\n durationStopwatch.ElapsedMilliseconds > millisecsLimitAsync\n ) {\n break;\n }\n } while (this.canContinue);\n\n durationStopwatch.Stop();\n\n if (outputStreamEndsInNewline || !this.canContinue) {\n if (this._stateSnapshotAtLastNewline !== null) {\n this.RestoreStateSnapshot();\n }\n\n if (!this.canContinue) {\n if (this.state.callStack.canPopThread)\n this.AddError(\n \"Thread available to pop, threads should always be flat by the end of evaluation?\"\n );\n\n if (\n this.state.generatedChoices.length == 0 &&\n !this.state.didSafeExit &&\n this._temporaryEvaluationContainer == null\n ) {\n if (this.state.callStack.CanPop(PushPopType.Tunnel))\n this.AddError(\n \"unexpectedly reached end of content. Do you need a '->->' to return from a tunnel?\"\n );\n else if (this.state.callStack.CanPop(PushPopType.Function))\n this.AddError(\n \"unexpectedly reached end of content. Do you need a '~ return'?\"\n );\n else if (!this.state.callStack.canPop)\n this.AddError(\n \"ran out of content. Do you need a '-> DONE' or '-> END'?\"\n );\n else\n this.AddError(\n \"unexpectedly reached end of content for unknown reason. Please debug compiler!\"\n );\n }\n }\n\n this.state.didSafeExit = false;\n this._sawLookaheadUnsafeFunctionAfterNewline = false;\n\n if (this._recursiveContinueCount == 1)\n this._state.variablesState.batchObservingVariableChanges = false;\n\n this._asyncContinueActive = false;\n if (this.onDidContinue !== null) this.onDidContinue();\n }\n\n this._recursiveContinueCount--;\n\n if (this._profiler != null) this._profiler.PostContinue();\n\n // In the following code, we're masking a lot of non-null assertion,\n // because testing for against `hasError` or `hasWarning` makes sure\n // the arrays are present and contain at least one element.\n if (this.state.hasError || this.state.hasWarning) {\n if (this.onError !== null) {\n if (this.state.hasError) {\n for (let err of this.state.currentErrors!) {\n this.onError(err, ErrorType.Error);\n }\n }\n if (this.state.hasWarning) {\n for (let err of this.state.currentWarnings!) {\n this.onError(err, ErrorType.Warning);\n }\n }\n this.ResetErrors();\n } else {\n let sb = new StringBuilder();\n sb.Append(\"Ink had \");\n if (this.state.hasError) {\n sb.Append(`${this.state.currentErrors!.length}`);\n sb.Append(\n this.state.currentErrors!.length == 1 ? \" error\" : \"errors\"\n );\n if (this.state.hasWarning) sb.Append(\" and \");\n }\n if (this.state.hasWarning) {\n sb.Append(`${this.state.currentWarnings!.length}`);\n sb.Append(\n this.state.currentWarnings!.length == 1 ? \" warning\" : \"warnings\"\n );\n if (this.state.hasWarning) sb.Append(\" and \");\n }\n sb.Append(\n \". It is strongly suggested that you assign an error handler to story.onError. The first issue was: \"\n );\n sb.Append(\n this.state.hasError\n ? this.state.currentErrors![0]\n : this.state.currentWarnings![0]\n );\n\n throw new StoryException(sb.toString());\n }\n }\n }\n\n public ContinueSingleStep() {\n if (this._profiler != null) this._profiler.PreStep();\n\n this.Step();\n\n if (this._profiler != null) this._profiler.PostStep();\n\n if (!this.canContinue && !this.state.callStack.elementIsEvaluateFromGame) {\n this.TryFollowDefaultInvisibleChoice();\n }\n\n if (this._profiler != null) this._profiler.PreSnapshot();\n\n if (!this.state.inStringEvaluation) {\n if (this._stateSnapshotAtLastNewline !== null) {\n if (this._stateSnapshotAtLastNewline.currentTags === null) {\n return throwNullException(\"this._stateAtLastNewline.currentTags\");\n }\n if (this.state.currentTags === null) {\n return throwNullException(\"this.state.currentTags\");\n }\n\n let change = this.CalculateNewlineOutputStateChange(\n this._stateSnapshotAtLastNewline.currentText,\n this.state.currentText,\n this._stateSnapshotAtLastNewline.currentTags.length,\n this.state.currentTags.length\n );\n\n if (\n change == Story.OutputStateChange.ExtendedBeyondNewline ||\n this._sawLookaheadUnsafeFunctionAfterNewline\n ) {\n this.RestoreStateSnapshot();\n\n return true;\n } else if (change == Story.OutputStateChange.NewlineRemoved) {\n this.DiscardSnapshot();\n }\n }\n\n if (this.state.outputStreamEndsInNewline) {\n if (this.canContinue) {\n if (this._stateSnapshotAtLastNewline == null) this.StateSnapshot();\n } else {\n this.DiscardSnapshot();\n }\n }\n }\n\n if (this._profiler != null) this._profiler.PostSnapshot();\n\n return false;\n }\n\n public CalculateNewlineOutputStateChange(\n prevText: string | null,\n currText: string | null,\n prevTagCount: number,\n currTagCount: number\n ) {\n if (prevText === null) {\n return throwNullException(\"prevText\");\n }\n if (currText === null) {\n return throwNullException(\"currText\");\n }\n\n let newlineStillExists =\n currText.length >= prevText.length &&\n prevText.length > 0 &&\n currText.charAt(prevText.length - 1) == \"\\n\";\n if (\n prevTagCount == currTagCount &&\n prevText.length == currText.length &&\n newlineStillExists\n )\n return Story.OutputStateChange.NoChange;\n\n if (!newlineStillExists) {\n return Story.OutputStateChange.NewlineRemoved;\n }\n\n if (currTagCount > prevTagCount)\n return Story.OutputStateChange.ExtendedBeyondNewline;\n\n for (let i = prevText.length; i < currText.length; i++) {\n let c = currText.charAt(i);\n if (c != \" \" && c != \"\\t\") {\n return Story.OutputStateChange.ExtendedBeyondNewline;\n }\n }\n\n return Story.OutputStateChange.NoChange;\n }\n\n public ContinueMaximally() {\n this.IfAsyncWeCant(\"ContinueMaximally\");\n\n let sb = new StringBuilder();\n\n while (this.canContinue) {\n sb.Append(this.Continue());\n }\n\n return sb.toString();\n }\n\n public ContentAtPath(path: Path) {\n return this.mainContentContainer.ContentAtPath(path);\n }\n\n public KnotContainerWithName(name: string) {\n let namedContainer = this.mainContentContainer.namedContent.get(name);\n if (namedContainer instanceof Container) return namedContainer;\n else return null;\n }\n\n public PointerAtPath(path: Path) {\n if (path.length == 0) return Pointer.Null;\n\n let p = new Pointer();\n\n let pathLengthToUse = path.length;\n\n let result = null;\n if (path.lastComponent === null) {\n return throwNullException(\"path.lastComponent\");\n }\n\n if (path.lastComponent.isIndex) {\n pathLengthToUse = path.length - 1;\n result = this.mainContentContainer.ContentAtPath(\n path,\n undefined,\n pathLengthToUse\n );\n p.container = result.container;\n p.index = path.lastComponent.index;\n } else {\n result = this.mainContentContainer.ContentAtPath(path);\n p.container = result.container;\n p.index = -1;\n }\n\n if (\n result.obj == null ||\n (result.obj == this.mainContentContainer && pathLengthToUse > 0)\n ) {\n this.Error(\n \"Failed to find content at path '\" +\n path +\n \"', and no approximation of it was possible.\"\n );\n } else if (result.approximate)\n this.Warning(\n \"Failed to find content at path '\" +\n path +\n \"', so it was approximated to: '\" +\n result.obj.path +\n \"'.\"\n );\n\n return p;\n }\n\n public StateSnapshot() {\n this._stateSnapshotAtLastNewline = this._state;\n this._state = this._state.CopyAndStartPatching();\n }\n\n public RestoreStateSnapshot() {\n if (this._stateSnapshotAtLastNewline === null) {\n throwNullException(\"_stateSnapshotAtLastNewline\");\n }\n this._stateSnapshotAtLastNewline.RestoreAfterPatch();\n\n this._state = this._stateSnapshotAtLastNewline;\n this._stateSnapshotAtLastNewline = null;\n\n if (!this._asyncSaving) {\n this._state.ApplyAnyPatch();\n }\n }\n\n public DiscardSnapshot() {\n if (!this._asyncSaving) this._state.ApplyAnyPatch();\n\n this._stateSnapshotAtLastNewline = null;\n }\n\n public CopyStateForBackgroundThreadSave() {\n this.IfAsyncWeCant(\"start saving on a background thread\");\n\n if (this._asyncSaving)\n throw new Error(\n \"Story is already in background saving mode, can't call CopyStateForBackgroundThreadSave again!\"\n );\n\n let stateToSave = this._state;\n this._state = this._state.CopyAndStartPatching();\n this._asyncSaving = true;\n return stateToSave;\n }\n\n public BackgroundSaveComplete() {\n if (this._stateSnapshotAtLastNewline === null) {\n this._state.ApplyAnyPatch();\n }\n\n this._asyncSaving = false;\n }\n\n public Step() {\n let shouldAddToStream = true;\n\n let pointer = this.state.currentPointer.copy();\n if (pointer.isNull) {\n return;\n }\n\n // Container containerToEnter = pointer.Resolve () as Container;\n let containerToEnter = asOrNull(pointer.Resolve(), Container);\n\n while (containerToEnter) {\n this.VisitContainer(containerToEnter, true);\n\n // No content? the most we can do is step past it\n if (containerToEnter.content.length == 0) {\n break;\n }\n\n pointer = Pointer.StartOf(containerToEnter);\n // containerToEnter = pointer.Resolve() as Container;\n containerToEnter = asOrNull(pointer.Resolve(), Container);\n }\n\n this.state.currentPointer = pointer.copy();\n\n if (this._profiler != null) this._profiler.Step(this.state.callStack);\n\n // Is the current content object:\n // - Normal content\n // - Or a logic/flow statement - if so, do it\n // Stop flow if we hit a stack pop when we're unable to pop (e.g. return/done statement in knot\n // that was diverted to rather than called as a function)\n let currentContentObj = pointer.Resolve();\n let isLogicOrFlowControl =\n this.PerformLogicAndFlowControl(currentContentObj);\n\n // Has flow been forced to end by flow control above?\n if (this.state.currentPointer.isNull) {\n return;\n }\n\n if (isLogicOrFlowControl) {\n shouldAddToStream = false;\n }\n\n // Choice with condition?\n // var choicePoint = currentContentObj as ChoicePoint;\n let choicePoint = asOrNull(currentContentObj, ChoicePoint);\n if (choicePoint) {\n let choice = this.ProcessChoice(choicePoint);\n if (choice) {\n this.state.generatedChoices.push(choice);\n }\n\n currentContentObj = null;\n shouldAddToStream = false;\n }\n\n // If the container has no content, then it will be\n // the \"content\" itself, but we skip over it.\n if (currentContentObj instanceof Container) {\n shouldAddToStream = false;\n }\n\n // Content to add to evaluation stack or the output stream\n if (shouldAddToStream) {\n // If we're pushing a variable pointer onto the evaluation stack, ensure that it's specific\n // to our current (possibly temporary) context index. And make a copy of the pointer\n // so that we're not editing the original runtime object.\n // var varPointer = currentContentObj as VariablePointerValue;\n let varPointer = asOrNull(currentContentObj, VariablePointerValue);\n if (varPointer && varPointer.contextIndex == -1) {\n // Create new object so we're not overwriting the story's own data\n let contextIdx = this.state.callStack.ContextForVariableNamed(\n varPointer.variableName\n );\n currentContentObj = new VariablePointerValue(\n varPointer.variableName,\n contextIdx\n );\n }\n\n // Expression evaluation content\n if (this.state.inExpressionEvaluation) {\n this.state.PushEvaluationStack(currentContentObj);\n }\n // Output stream content (i.e. not expression evaluation)\n else {\n this.state.PushToOutputStream(currentContentObj);\n }\n }\n\n // Increment the content pointer, following diverts if necessary\n this.NextContent();\n\n // Starting a thread should be done after the increment to the content pointer,\n // so that when returning from the thread, it returns to the content after this instruction.\n // var controlCmd = currentContentObj as ;\n let controlCmd = asOrNull(currentContentObj, ControlCommand);\n if (\n controlCmd &&\n controlCmd.commandType == ControlCommand.CommandType.StartThread\n ) {\n this.state.callStack.PushThread();\n }\n }\n\n public VisitContainer(container: Container, atStart: boolean) {\n if (!container.countingAtStartOnly || atStart) {\n if (container.visitsShouldBeCounted)\n this.state.IncrementVisitCountForContainer(container);\n\n if (container.turnIndexShouldBeCounted)\n this.state.RecordTurnIndexVisitToContainer(container);\n }\n }\n\n private _prevContainers: Container[] = [];\n public VisitChangedContainersDueToDivert() {\n let previousPointer = this.state.previousPointer.copy();\n let pointer = this.state.currentPointer.copy();\n\n if (pointer.isNull || pointer.index == -1) return;\n\n this._prevContainers.length = 0;\n if (!previousPointer.isNull) {\n // Container prevAncestor = previousPointer.Resolve() as Container ?? previousPointer.container as Container;\n let resolvedPreviousAncestor = previousPointer.Resolve();\n let prevAncestor =\n asOrNull(resolvedPreviousAncestor, Container) ||\n asOrNull(previousPointer.container, Container);\n while (prevAncestor) {\n this._prevContainers.push(prevAncestor);\n // prevAncestor = prevAncestor.parent as Container;\n prevAncestor = asOrNull(prevAncestor.parent, Container);\n }\n }\n\n let currentChildOfContainer = pointer.Resolve();\n\n if (currentChildOfContainer == null) return;\n\n // Container currentContainerAncestor = currentChildOfContainer.parent as Container;\n let currentContainerAncestor = asOrNull(\n currentChildOfContainer.parent,\n Container\n );\n let allChildrenEnteredAtStart = true;\n while (\n currentContainerAncestor &&\n (this._prevContainers.indexOf(currentContainerAncestor) < 0 ||\n currentContainerAncestor.countingAtStartOnly)\n ) {\n // Check whether this ancestor container is being entered at the start,\n // by checking whether the child object is the first.\n let enteringAtStart =\n currentContainerAncestor.content.length > 0 &&\n currentChildOfContainer == currentContainerAncestor.content[0] &&\n allChildrenEnteredAtStart;\n\n if (!enteringAtStart) allChildrenEnteredAtStart = false;\n\n // Mark a visit to this container\n this.VisitContainer(currentContainerAncestor, enteringAtStart);\n\n currentChildOfContainer = currentContainerAncestor;\n // currentContainerAncestor = currentContainerAncestor.parent as Container;\n currentContainerAncestor = asOrNull(\n currentContainerAncestor.parent,\n Container\n );\n }\n }\n\n public PopChoiceStringAndTags(tags: string[]) {\n let choiceOnlyStrVal = asOrThrows(\n this.state.PopEvaluationStack(),\n StringValue\n );\n\n while (\n this.state.evaluationStack.length > 0 &&\n asOrNull(this.state.PeekEvaluationStack(), Tag) != null\n ) {\n let tag = asOrNull(this.state.PopEvaluationStack(), Tag);\n if (tag) tags.push(tag.text);\n }\n return choiceOnlyStrVal.value;\n }\n\n public ProcessChoice(choicePoint: ChoicePoint) {\n let showChoice = true;\n\n // Don't create choice if choice point doesn't pass conditional\n if (choicePoint.hasCondition) {\n let conditionValue = this.state.PopEvaluationStack();\n if (!this.IsTruthy(conditionValue)) {\n showChoice = false;\n }\n }\n\n let startText = \"\";\n let choiceOnlyText = \"\";\n let tags: string[] = [];\n\n if (choicePoint.hasChoiceOnlyContent) {\n choiceOnlyText = this.PopChoiceStringAndTags(tags) || \"\";\n }\n\n if (choicePoint.hasStartContent) {\n startText = this.PopChoiceStringAndTags(tags) || \"\";\n }\n\n // Don't create choice if player has already read this content\n if (choicePoint.onceOnly) {\n let visitCount = this.state.VisitCountForContainer(\n choicePoint.choiceTarget\n );\n if (visitCount > 0) {\n showChoice = false;\n }\n }\n\n // We go through the full process of creating the choice above so\n // that we consume the content for it, since otherwise it'll\n // be shown on the output stream.\n if (!showChoice) {\n return null;\n }\n\n let choice = new Choice();\n choice.targetPath = choicePoint.pathOnChoice;\n choice.sourcePath = choicePoint.path.toString();\n choice.isInvisibleDefault = choicePoint.isInvisibleDefault;\n choice.threadAtGeneration = this.state.callStack.ForkThread();\n choice.tags = tags.reverse(); //C# is a stack\n choice.text = (startText + choiceOnlyText).replace(/^[ \\t]+|[ \\t]+$/g, \"\");\n\n return choice;\n }\n\n public IsTruthy(obj: InkObject) {\n let truthy = false;\n if (obj instanceof Value) {\n let val = obj;\n\n if (val instanceof DivertTargetValue) {\n let divTarget = val;\n this.Error(\n \"Shouldn't use a divert target (to \" +\n divTarget.targetPath +\n \") as a conditional value. Did you intend a function call 'likeThis()' or a read count check 'likeThis'? (no arrows)\"\n );\n return false;\n }\n\n return val.isTruthy;\n }\n return truthy;\n }\n\n public PerformLogicAndFlowControl(contentObj: InkObject | null) {\n if (contentObj == null) {\n return false;\n }\n\n // Divert\n if (contentObj instanceof Divert) {\n let currentDivert = contentObj;\n\n if (currentDivert.isConditional) {\n let conditionValue = this.state.PopEvaluationStack();\n\n // False conditional? Cancel divert\n if (!this.IsTruthy(conditionValue)) return true;\n }\n\n if (currentDivert.hasVariableTarget) {\n let varName = currentDivert.variableDivertName;\n\n let varContents =\n this.state.variablesState.GetVariableWithName(varName);\n\n if (varContents == null) {\n this.Error(\n \"Tried to divert using a target from a variable that could not be found (\" +\n varName +\n \")\"\n );\n } else if (!(varContents instanceof DivertTargetValue)) {\n // var intContent = varContents as IntValue;\n let intContent = asOrNull(varContents, IntValue);\n\n let errorMessage =\n \"Tried to divert to a target from a variable, but the variable (\" +\n varName +\n \") didn't contain a divert target, it \";\n if (intContent instanceof IntValue && intContent.value == 0) {\n errorMessage += \"was empty/null (the value 0).\";\n } else {\n errorMessage += \"contained '\" + varContents + \"'.\";\n }\n\n this.Error(errorMessage);\n }\n\n let target = asOrThrows(varContents, DivertTargetValue);\n this.state.divertedPointer = this.PointerAtPath(target.targetPath);\n } else if (currentDivert.isExternal) {\n this.CallExternalFunction(\n currentDivert.targetPathString,\n currentDivert.externalArgs\n );\n return true;\n } else {\n this.state.divertedPointer = currentDivert.targetPointer.copy();\n }\n\n if (currentDivert.pushesToStack) {\n this.state.callStack.Push(\n currentDivert.stackPushType,\n undefined,\n this.state.outputStream.length\n );\n }\n\n if (this.state.divertedPointer.isNull && !currentDivert.isExternal) {\n if (\n currentDivert &&\n currentDivert.debugMetadata &&\n currentDivert.debugMetadata.sourceName != null\n ) {\n this.Error(\n \"Divert target doesn't exist: \" +\n currentDivert.debugMetadata.sourceName\n );\n } else {\n this.Error(\"Divert resolution failed: \" + currentDivert);\n }\n }\n\n return true;\n }\n\n // Start/end an expression evaluation? Or print out the result?\n else if (contentObj instanceof ControlCommand) {\n let evalCommand = contentObj;\n\n switch (evalCommand.commandType) {\n case ControlCommand.CommandType.EvalStart:\n this.Assert(\n this.state.inExpressionEvaluation === false,\n \"Already in expression evaluation?\"\n );\n this.state.inExpressionEvaluation = true;\n break;\n\n case ControlCommand.CommandType.EvalEnd:\n this.Assert(\n this.state.inExpressionEvaluation === true,\n \"Not in expression evaluation mode\"\n );\n this.state.inExpressionEvaluation = false;\n break;\n\n case ControlCommand.CommandType.EvalOutput:\n // If the expression turned out to be empty, there may not be anything on the stack\n if (this.state.evaluationStack.length > 0) {\n let output = this.state.PopEvaluationStack();\n\n // Functions may evaluate to Void, in which case we skip output\n if (!(output instanceof Void)) {\n // TODO: Should we really always blanket convert to string?\n // It would be okay to have numbers in the output stream the\n // only problem is when exporting text for viewing, it skips over numbers etc.\n let text = new StringValue(output.toString());\n\n this.state.PushToOutputStream(text);\n }\n }\n break;\n\n case ControlCommand.CommandType.NoOp:\n break;\n\n case ControlCommand.CommandType.Duplicate:\n this.state.PushEvaluationStack(this.state.PeekEvaluationStack());\n break;\n\n case ControlCommand.CommandType.PopEvaluatedValue:\n this.state.PopEvaluationStack();\n break;\n\n case ControlCommand.CommandType.PopFunction:\n case ControlCommand.CommandType.PopTunnel:\n let popType =\n evalCommand.commandType == ControlCommand.CommandType.PopFunction\n ? PushPopType.Function\n : PushPopType.Tunnel;\n\n let overrideTunnelReturnTarget: DivertTargetValue | null = null;\n if (popType == PushPopType.Tunnel) {\n let popped = this.state.PopEvaluationStack();\n // overrideTunnelReturnTarget = popped as DivertTargetValue;\n overrideTunnelReturnTarget = asOrNull(popped, DivertTargetValue);\n if (overrideTunnelReturnTarget === null) {\n this.Assert(\n popped instanceof Void,\n \"Expected void if ->-> doesn't override target\"\n );\n }\n }\n\n if (this.state.TryExitFunctionEvaluationFromGame()) {\n break;\n } else if (\n this.state.callStack.currentElement.type != popType ||\n !this.state.callStack.canPop\n ) {\n let names: Map = new Map();\n names.set(\n PushPopType.Function,\n \"function return statement (~ return)\"\n );\n names.set(PushPopType.Tunnel, \"tunnel onwards statement (->->)\");\n\n let expected = names.get(this.state.callStack.currentElement.type);\n if (!this.state.callStack.canPop) {\n expected = \"end of flow (-> END or choice)\";\n }\n\n let errorMsg =\n \"Found \" + names.get(popType) + \", when expected \" + expected;\n\n this.Error(errorMsg);\n } else {\n this.state.PopCallStack();\n\n if (overrideTunnelReturnTarget)\n this.state.divertedPointer = this.PointerAtPath(\n overrideTunnelReturnTarget.targetPath\n );\n }\n break;\n\n case ControlCommand.CommandType.BeginString:\n this.state.PushToOutputStream(evalCommand);\n\n this.Assert(\n this.state.inExpressionEvaluation === true,\n \"Expected to be in an expression when evaluating a string\"\n );\n this.state.inExpressionEvaluation = false;\n break;\n\n // Leave it to story.currentText and story.currentTags to sort out the text from the tags\n // This is mostly because we can't always rely on the existence of EndTag, and we don't want\n // to try and flatten dynamic tags to strings every time \\n is pushed to output\n case ControlCommand.CommandType.BeginTag:\n this.state.PushToOutputStream(evalCommand);\n break;\n\n // EndTag has 2 modes:\n // - When in string evaluation (for choices)\n // - Normal\n //\n // The only way you could have an EndTag in the middle of\n // string evaluation is if we're currently generating text for a\n // choice, such as:\n //\n // + choice # tag\n //\n // In the above case, the ink will be run twice:\n // - First, to generate the choice text. String evaluation\n // will be on, and the final string will be pushed to the\n // evaluation stack, ready to be popped to make a Choice\n // object.\n // - Second, when ink generates text after choosing the choice.\n // On this ocassion, it's not in string evaluation mode.\n //\n // On the writing side, we disallow manually putting tags within\n // strings like this:\n //\n // {\"hello # world\"}\n //\n // So we know that the tag must be being generated as part of\n // choice content. Therefore, when the tag has been generated,\n // we push it onto the evaluation stack in the exact same way\n // as the string for the choice content.\n case ControlCommand.CommandType.EndTag: {\n if (this.state.inStringEvaluation) {\n let contentStackForTag: InkObject[] = [];\n let outputCountConsumed = 0;\n for (let i = this.state.outputStream.length - 1; i >= 0; --i) {\n let obj = this.state.outputStream[i];\n outputCountConsumed++;\n\n // var command = obj as ControlCommand;\n let command = asOrNull(obj, ControlCommand);\n if (command != null) {\n if (\n command.commandType == ControlCommand.CommandType.BeginTag\n ) {\n break;\n } else {\n this.Error(\n \"Unexpected ControlCommand while extracting tag from choice\"\n );\n break;\n }\n }\n if (obj instanceof StringValue) {\n contentStackForTag.push(obj);\n }\n }\n\n // Consume the content that was produced for this string\n this.state.PopFromOutputStream(outputCountConsumed);\n // Build string out of the content we collected\n let sb = new StringBuilder();\n for (let strVal of contentStackForTag) {\n sb.Append(strVal.toString());\n }\n let choiceTag = new Tag(\n this.state.CleanOutputWhitespace(sb.toString())\n );\n // Pushing to the evaluation stack means it gets picked up\n // when a Choice is generated from the next Choice Point.\n this.state.PushEvaluationStack(choiceTag);\n } else {\n // Otherwise! Simply push EndTag, so that in the output stream we\n // have a structure of: [BeginTag, \"the tag content\", EndTag]\n this.state.PushToOutputStream(evalCommand);\n }\n break;\n }\n\n case ControlCommand.CommandType.EndString: {\n let contentStackForString: InkObject[] = [];\n let contentToRetain: InkObject[] = [];\n\n let outputCountConsumed = 0;\n for (let i = this.state.outputStream.length - 1; i >= 0; --i) {\n let obj = this.state.outputStream[i];\n\n outputCountConsumed++;\n\n // var command = obj as ControlCommand;\n let command = asOrNull(obj, ControlCommand);\n if (\n command &&\n command.commandType == ControlCommand.CommandType.BeginString\n ) {\n break;\n }\n if (obj instanceof Tag) {\n contentToRetain.push(obj);\n }\n if (obj instanceof StringValue) {\n contentStackForString.push(obj);\n }\n }\n\n // Consume the content that was produced for this string\n this.state.PopFromOutputStream(outputCountConsumed);\n\n // Rescue the tags that we want actually to keep on the output stack\n // rather than consume as part of the string we're building.\n // At the time of writing, this only applies to Tag objects generated\n // by choices, which are pushed to the stack during string generation.\n for (let rescuedTag of contentToRetain)\n this.state.PushToOutputStream(rescuedTag);\n\n // The C# version uses a Stack for contentStackForString, but we're\n // using a simple array, so we need to reverse it before using it\n contentStackForString = contentStackForString.reverse();\n\n // Build string out of the content we collected\n let sb = new StringBuilder();\n for (let c of contentStackForString) {\n sb.Append(c.toString());\n }\n\n // Return to expression evaluation (from content mode)\n this.state.inExpressionEvaluation = true;\n this.state.PushEvaluationStack(new StringValue(sb.toString()));\n break;\n }\n\n case ControlCommand.CommandType.ChoiceCount:\n let choiceCount = this.state.generatedChoices.length;\n this.state.PushEvaluationStack(new IntValue(choiceCount));\n break;\n\n case ControlCommand.CommandType.Turns:\n this.state.PushEvaluationStack(\n new IntValue(this.state.currentTurnIndex + 1)\n );\n break;\n\n case ControlCommand.CommandType.TurnsSince:\n case ControlCommand.CommandType.ReadCount:\n let target = this.state.PopEvaluationStack();\n if (!(target instanceof DivertTargetValue)) {\n let extraNote = \"\";\n if (target instanceof IntValue)\n extraNote =\n \". Did you accidentally pass a read count ('knot_name') instead of a target ('-> knot_name')?\";\n this.Error(\n \"TURNS_SINCE / READ_COUNT expected a divert target (knot, stitch, label name), but saw \" +\n target +\n extraNote\n );\n break;\n }\n\n // var divertTarget = target as DivertTargetValue;\n let divertTarget = asOrThrows(target, DivertTargetValue);\n // var container = ContentAtPath (divertTarget.targetPath).correctObj as Container;\n let container = asOrNull(\n this.ContentAtPath(divertTarget.targetPath).correctObj,\n Container\n );\n\n let eitherCount;\n if (container != null) {\n if (\n evalCommand.commandType == ControlCommand.CommandType.TurnsSince\n )\n eitherCount = this.state.TurnsSinceForContainer(container);\n else eitherCount = this.state.VisitCountForContainer(container);\n } else {\n if (\n evalCommand.commandType == ControlCommand.CommandType.TurnsSince\n )\n eitherCount = -1;\n else eitherCount = 0;\n\n this.Warning(\n \"Failed to find container for \" +\n evalCommand.toString() +\n \" lookup at \" +\n divertTarget.targetPath.toString()\n );\n }\n\n this.state.PushEvaluationStack(new IntValue(eitherCount));\n break;\n\n case ControlCommand.CommandType.Random: {\n let maxInt = asOrNull(this.state.PopEvaluationStack(), IntValue);\n let minInt = asOrNull(this.state.PopEvaluationStack(), IntValue);\n\n if (minInt == null || minInt instanceof IntValue === false)\n return this.Error(\n \"Invalid value for minimum parameter of RANDOM(min, max)\"\n );\n\n if (maxInt == null || minInt instanceof IntValue === false)\n return this.Error(\n \"Invalid value for maximum parameter of RANDOM(min, max)\"\n );\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (maxInt.value === null) {\n return throwNullException(\"maxInt.value\");\n }\n if (minInt.value === null) {\n return throwNullException(\"minInt.value\");\n }\n\n // This code is differs a bit from the reference implementation, since\n // JavaScript has no true integers. Hence integer arithmetics and\n // interger overflows don't apply here. A loss of precision can\n // happen with big numbers however.\n //\n // The case where 'randomRange' is lower than zero is handled below,\n // so there's no need to test against Number.MIN_SAFE_INTEGER.\n let randomRange = maxInt.value - minInt.value + 1;\n if (!isFinite(randomRange) || randomRange > Number.MAX_SAFE_INTEGER) {\n randomRange = Number.MAX_SAFE_INTEGER;\n this.Error(\n \"RANDOM was called with a range that exceeds the size that ink numbers can use.\"\n );\n }\n if (randomRange <= 0)\n this.Error(\n \"RANDOM was called with minimum as \" +\n minInt.value +\n \" and maximum as \" +\n maxInt.value +\n \". The maximum must be larger\"\n );\n\n let resultSeed = this.state.storySeed + this.state.previousRandom;\n let random = new PRNG(resultSeed);\n\n let nextRandom = random.next();\n let chosenValue = (nextRandom % randomRange) + minInt.value;\n this.state.PushEvaluationStack(new IntValue(chosenValue));\n\n // Next random number (rather than keeping the Random object around)\n this.state.previousRandom = nextRandom;\n break;\n }\n\n case ControlCommand.CommandType.SeedRandom:\n let seed = asOrNull(this.state.PopEvaluationStack(), IntValue);\n if (seed == null || seed instanceof IntValue === false)\n return this.Error(\"Invalid value passed to SEED_RANDOM\");\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (seed.value === null) {\n return throwNullException(\"minInt.value\");\n }\n\n this.state.storySeed = seed.value;\n this.state.previousRandom = 0;\n\n this.state.PushEvaluationStack(new Void());\n break;\n\n case ControlCommand.CommandType.VisitIndex:\n let count =\n this.state.VisitCountForContainer(\n this.state.currentPointer.container\n ) - 1; // index not count\n this.state.PushEvaluationStack(new IntValue(count));\n break;\n\n case ControlCommand.CommandType.SequenceShuffleIndex:\n let shuffleIndex = this.NextSequenceShuffleIndex();\n this.state.PushEvaluationStack(new IntValue(shuffleIndex));\n break;\n\n case ControlCommand.CommandType.StartThread:\n // Handled in main step function\n break;\n\n case ControlCommand.CommandType.Done:\n // We may exist in the context of the initial\n // act of creating the thread, or in the context of\n // evaluating the content.\n if (this.state.callStack.canPopThread) {\n this.state.callStack.PopThread();\n }\n\n // In normal flow - allow safe exit without warning\n else {\n this.state.didSafeExit = true;\n\n // Stop flow in current thread\n this.state.currentPointer = Pointer.Null;\n }\n\n break;\n\n // Force flow to end completely\n case ControlCommand.CommandType.End:\n this.state.ForceEnd();\n break;\n\n case ControlCommand.CommandType.ListFromInt:\n // var intVal = state.PopEvaluationStack () as IntValue;\n let intVal = asOrNull(this.state.PopEvaluationStack(), IntValue);\n // var listNameVal = state.PopEvaluationStack () as StringValue;\n let listNameVal = asOrThrows(\n this.state.PopEvaluationStack(),\n StringValue\n );\n\n if (intVal === null) {\n throw new StoryException(\n \"Passed non-integer when creating a list element from a numerical value.\"\n );\n }\n\n let generatedListValue = null;\n\n if (this.listDefinitions === null) {\n return throwNullException(\"this.listDefinitions\");\n }\n let foundListDef = this.listDefinitions.TryListGetDefinition(\n listNameVal.value,\n null\n );\n if (foundListDef.exists) {\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (intVal.value === null) {\n return throwNullException(\"minInt.value\");\n }\n\n let foundItem = foundListDef.result!.TryGetItemWithValue(\n intVal.value,\n InkListItem.Null\n );\n if (foundItem.exists) {\n generatedListValue = new ListValue(\n foundItem.result!,\n intVal.value\n );\n }\n } else {\n throw new StoryException(\n \"Failed to find LIST called \" + listNameVal.value\n );\n }\n\n if (generatedListValue == null) generatedListValue = new ListValue();\n\n this.state.PushEvaluationStack(generatedListValue);\n break;\n\n case ControlCommand.CommandType.ListRange:\n let max = asOrNull(this.state.PopEvaluationStack(), Value);\n let min = asOrNull(this.state.PopEvaluationStack(), Value);\n\n // var targetList = state.PopEvaluationStack () as ListValue;\n let targetList = asOrNull(this.state.PopEvaluationStack(), ListValue);\n\n if (targetList === null || min === null || max === null)\n throw new StoryException(\n \"Expected list, minimum and maximum for LIST_RANGE\"\n );\n\n if (targetList.value === null) {\n return throwNullException(\"targetList.value\");\n }\n let result = targetList.value.ListWithSubRange(\n min.valueObject,\n max.valueObject\n );\n\n this.state.PushEvaluationStack(new ListValue(result));\n break;\n\n case ControlCommand.CommandType.ListRandom: {\n let listVal = this.state.PopEvaluationStack() as ListValue;\n if (listVal === null)\n throw new StoryException(\"Expected list for LIST_RANDOM\");\n\n let list = listVal.value;\n\n let newList: InkList | null = null;\n\n if (list === null) {\n throw throwNullException(\"list\");\n }\n if (list.Count == 0) {\n newList = new InkList();\n } else {\n // Generate a random index for the element to take\n let resultSeed = this.state.storySeed + this.state.previousRandom;\n let random = new PRNG(resultSeed);\n\n let nextRandom = random.next();\n let listItemIndex = nextRandom % list.Count;\n\n // This bit is a little different from the original\n // C# code, since iterators do not work in the same way.\n // First, we iterate listItemIndex - 1 times, calling next().\n // The listItemIndex-th time is made outside of the loop,\n // in order to retrieve the value.\n let listEnumerator = list.entries();\n for (let i = 0; i <= listItemIndex - 1; i++) {\n listEnumerator.next();\n }\n let value = listEnumerator.next().value;\n let randomItem: KeyValuePair = {\n Key: InkListItem.fromSerializedKey(value[0]),\n Value: value[1],\n };\n\n // Origin list is simply the origin of the one element\n if (randomItem.Key.originName === null) {\n return throwNullException(\"randomItem.Key.originName\");\n }\n newList = new InkList(randomItem.Key.originName, this);\n newList.Add(randomItem.Key, randomItem.Value);\n\n this.state.previousRandom = nextRandom;\n }\n\n this.state.PushEvaluationStack(new ListValue(newList));\n break;\n }\n\n default:\n this.Error(\"unhandled ControlCommand: \" + evalCommand);\n break;\n }\n\n return true;\n }\n\n // Variable assignment\n else if (contentObj instanceof VariableAssignment) {\n let varAss = contentObj;\n let assignedVal = this.state.PopEvaluationStack();\n\n this.state.variablesState.Assign(varAss, assignedVal);\n\n return true;\n }\n\n // Variable reference\n else if (contentObj instanceof VariableReference) {\n let varRef = contentObj;\n let foundValue = null;\n\n // Explicit read count value\n if (varRef.pathForCount != null) {\n let container = varRef.containerForCount;\n let count = this.state.VisitCountForContainer(container);\n foundValue = new IntValue(count);\n }\n\n // Normal variable reference\n else {\n foundValue = this.state.variablesState.GetVariableWithName(varRef.name);\n\n if (foundValue == null) {\n this.Warning(\n \"Variable not found: '\" +\n varRef.name +\n \"'. Using default value of 0 (false). This can happen with temporary variables if the declaration hasn't yet been hit. Globals are always given a default value on load if a value doesn't exist in the save state.\"\n );\n foundValue = new IntValue(0);\n }\n }\n\n this.state.PushEvaluationStack(foundValue);\n\n return true;\n }\n\n // Native function call\n else if (contentObj instanceof NativeFunctionCall) {\n let func = contentObj;\n let funcParams = this.state.PopEvaluationStack(func.numberOfParameters);\n let result = func.Call(funcParams);\n this.state.PushEvaluationStack(result);\n return true;\n }\n\n // No control content, must be ordinary content\n return false;\n }\n\n public ChoosePathString(\n path: string,\n resetCallstack = true,\n args: any[] = []\n ) {\n this.IfAsyncWeCant(\"call ChoosePathString right now\");\n if (this.onChoosePathString !== null) this.onChoosePathString(path, args);\n\n if (resetCallstack) {\n this.ResetCallstack();\n } else {\n if (this.state.callStack.currentElement.type == PushPopType.Function) {\n let funcDetail = \"\";\n let container =\n this.state.callStack.currentElement.currentPointer.container;\n if (container != null) {\n funcDetail = \"(\" + container.path.toString() + \") \";\n }\n throw new Error(\n \"Story was running a function \" +\n funcDetail +\n \"when you called ChoosePathString(\" +\n path +\n \") - this is almost certainly not not what you want! Full stack trace: \\n\" +\n this.state.callStack.callStackTrace\n );\n }\n }\n\n this.state.PassArgumentsToEvaluationStack(args);\n this.ChoosePath(new Path(path));\n }\n\n public IfAsyncWeCant(activityStr: string) {\n if (this._asyncContinueActive)\n throw new Error(\n \"Can't \" +\n activityStr +\n \". Story is in the middle of a ContinueAsync(). Make more ContinueAsync() calls or a single Continue() call beforehand.\"\n );\n }\n\n public ChoosePath(p: Path, incrementingTurnIndex: boolean = true) {\n this.state.SetChosenPath(p, incrementingTurnIndex);\n\n // Take a note of newly visited containers for read counts etc\n this.VisitChangedContainersDueToDivert();\n }\n\n public ChooseChoiceIndex(choiceIdx: number) {\n choiceIdx = choiceIdx;\n let choices = this.currentChoices;\n this.Assert(\n choiceIdx >= 0 && choiceIdx < choices.length,\n \"choice out of range\"\n );\n\n let choiceToChoose = choices[choiceIdx];\n if (this.onMakeChoice !== null) this.onMakeChoice(choiceToChoose);\n\n if (choiceToChoose.threadAtGeneration === null) {\n return throwNullException(\"choiceToChoose.threadAtGeneration\");\n }\n if (choiceToChoose.targetPath === null) {\n return throwNullException(\"choiceToChoose.targetPath\");\n }\n\n this.state.callStack.currentThread = choiceToChoose.threadAtGeneration;\n\n this.ChoosePath(choiceToChoose.targetPath);\n }\n\n public HasFunction(functionName: string) {\n try {\n return this.KnotContainerWithName(functionName) != null;\n } catch (e) {\n return false;\n }\n }\n\n public EvaluateFunction(\n functionName: string,\n args: any[] = [],\n returnTextOutput: boolean = false\n ): Story.EvaluateFunctionTextOutput | any {\n // EvaluateFunction behaves slightly differently than the C# version.\n // In C#, you can pass a (second) parameter `out textOutput` to get the\n // text outputted by the function. This is not possible in js. Instead,\n // we maintain the regular signature (functionName, args), plus an\n // optional third parameter returnTextOutput. If set to true, we will\n // return both the textOutput and the returned value, as an object.\n\n if (this.onEvaluateFunction !== null)\n this.onEvaluateFunction(functionName, args);\n\n this.IfAsyncWeCant(\"evaluate a function\");\n\n if (functionName == null) {\n throw new Error(\"Function is null\");\n } else if (functionName == \"\" || functionName.trim() == \"\") {\n throw new Error(\"Function is empty or white space.\");\n }\n\n let funcContainer = this.KnotContainerWithName(functionName);\n if (funcContainer == null) {\n throw new Error(\"Function doesn't exist: '\" + functionName + \"'\");\n }\n\n let outputStreamBefore: InkObject[] = [];\n outputStreamBefore.push(...this.state.outputStream);\n this._state.ResetOutput();\n\n this.state.StartFunctionEvaluationFromGame(funcContainer, args);\n\n // Evaluate the function, and collect the string output\n let stringOutput = new StringBuilder();\n while (this.canContinue) {\n stringOutput.Append(this.Continue());\n }\n let textOutput = stringOutput.toString();\n\n this._state.ResetOutput(outputStreamBefore);\n\n let result = this.state.CompleteFunctionEvaluationFromGame();\n if (this.onCompleteEvaluateFunction != null)\n this.onCompleteEvaluateFunction(functionName, args, textOutput, result);\n\n return returnTextOutput ? { returned: result, output: textOutput } : result;\n }\n\n public EvaluateExpression(exprContainer: Container) {\n let startCallStackHeight = this.state.callStack.elements.length;\n\n this.state.callStack.Push(PushPopType.Tunnel);\n\n this._temporaryEvaluationContainer = exprContainer;\n\n this.state.GoToStart();\n\n let evalStackHeight = this.state.evaluationStack.length;\n\n this.Continue();\n\n this._temporaryEvaluationContainer = null;\n\n // Should have fallen off the end of the Container, which should\n // have auto-popped, but just in case we didn't for some reason,\n // manually pop to restore the state (including currentPath).\n if (this.state.callStack.elements.length > startCallStackHeight) {\n this.state.PopCallStack();\n }\n\n let endStackHeight = this.state.evaluationStack.length;\n if (endStackHeight > evalStackHeight) {\n return this.state.PopEvaluationStack();\n } else {\n return null;\n }\n }\n\n public allowExternalFunctionFallbacks: boolean = false;\n\n public CallExternalFunction(\n funcName: string | null,\n numberOfArguments: number\n ) {\n if (funcName === null) {\n return throwNullException(\"funcName\");\n }\n let funcDef = this._externals.get(funcName);\n let fallbackFunctionContainer = null;\n\n let foundExternal = typeof funcDef !== \"undefined\";\n\n if (\n foundExternal &&\n !funcDef!.lookAheadSafe &&\n this._stateSnapshotAtLastNewline !== null\n ) {\n this._sawLookaheadUnsafeFunctionAfterNewline = true;\n return;\n }\n\n if (!foundExternal) {\n if (this.allowExternalFunctionFallbacks) {\n fallbackFunctionContainer = this.KnotContainerWithName(funcName);\n this.Assert(\n fallbackFunctionContainer !== null,\n \"Trying to call EXTERNAL function '\" +\n funcName +\n \"' which has not been bound, and fallback ink function could not be found.\"\n );\n\n // Divert direct into fallback function and we're done\n this.state.callStack.Push(\n PushPopType.Function,\n undefined,\n this.state.outputStream.length\n );\n this.state.divertedPointer = Pointer.StartOf(fallbackFunctionContainer);\n return;\n } else {\n this.Assert(\n false,\n \"Trying to call EXTERNAL function '\" +\n funcName +\n \"' which has not been bound (and ink fallbacks disabled).\"\n );\n }\n }\n\n // Pop arguments\n let args: any[] = [];\n for (let i = 0; i < numberOfArguments; ++i) {\n // var poppedObj = state.PopEvaluationStack () as Value;\n let poppedObj = asOrThrows(this.state.PopEvaluationStack(), Value);\n let valueObj = poppedObj.valueObject;\n args.push(valueObj);\n }\n\n // Reverse arguments from the order they were popped,\n // so they're the right way round again.\n args.reverse();\n\n // Run the function!\n let funcResult = funcDef!.function(args);\n\n // Convert return value (if any) to the a type that the ink engine can use\n let returnObj = null;\n if (funcResult != null) {\n returnObj = Value.Create(funcResult);\n this.Assert(\n returnObj !== null,\n \"Could not create ink value from returned object of type \" +\n typeof funcResult\n );\n } else {\n returnObj = new Void();\n }\n\n this.state.PushEvaluationStack(returnObj);\n }\n\n public BindExternalFunctionGeneral(\n funcName: string,\n func: Story.ExternalFunction,\n lookaheadSafe: boolean = true\n ) {\n this.IfAsyncWeCant(\"bind an external function\");\n this.Assert(\n !this._externals.has(funcName),\n \"Function '\" + funcName + \"' has already been bound.\"\n );\n this._externals.set(funcName, {\n function: func,\n lookAheadSafe: lookaheadSafe,\n });\n }\n\n public TryCoerce(value: any) {\n // We're skipping type coercition in this implementation. First of, js\n // is loosely typed, so it's not that important. Secondly, there is no\n // clean way (AFAIK) for the user to describe what type of parameters\n // they expect.\n return value;\n }\n\n public BindExternalFunction(\n funcName: string,\n func: Story.ExternalFunction,\n lookaheadSafe: boolean = false\n ) {\n this.Assert(func != null, \"Can't bind a null function\");\n\n this.BindExternalFunctionGeneral(\n funcName,\n (args: any) => {\n this.Assert(\n args.length >= func.length,\n \"External function expected \" + func.length + \" arguments\"\n );\n\n let coercedArgs = [];\n for (let i = 0, l = args.length; i < l; i++) {\n coercedArgs[i] = this.TryCoerce(args[i]);\n }\n return func.apply(null, coercedArgs);\n },\n lookaheadSafe\n );\n }\n\n public UnbindExternalFunction(funcName: string) {\n this.IfAsyncWeCant(\"unbind an external a function\");\n this.Assert(\n this._externals.has(funcName),\n \"Function '\" + funcName + \"' has not been bound.\"\n );\n this._externals.delete(funcName);\n }\n\n public ValidateExternalBindings(): void;\n public ValidateExternalBindings(\n c: Container | null,\n missingExternals: Set\n ): void;\n public ValidateExternalBindings(\n o: InkObject | null,\n missingExternals: Set\n ): void;\n public ValidateExternalBindings() {\n let c: Container | null = null;\n let o: InkObject | null = null;\n let missingExternals: Set = arguments[1] || new Set();\n\n if (arguments[0] instanceof Container) {\n c = arguments[0];\n }\n\n if (arguments[0] instanceof InkObject) {\n o = arguments[0];\n }\n\n if (c === null && o === null) {\n this.ValidateExternalBindings(\n this._mainContentContainer,\n missingExternals\n );\n this._hasValidatedExternals = true;\n\n // No problem! Validation complete\n if (missingExternals.size == 0) {\n this._hasValidatedExternals = true;\n } else {\n let message = \"Error: Missing function binding for external\";\n message += missingExternals.size > 1 ? \"s\" : \"\";\n message += \": '\";\n message += Array.from(missingExternals).join(\"', '\");\n message += \"' \";\n message += this.allowExternalFunctionFallbacks\n ? \", and no fallback ink function found.\"\n : \" (ink fallbacks disabled)\";\n\n this.Error(message);\n }\n } else if (c != null) {\n for (let innerContent of c.content) {\n let container = innerContent as Container;\n if (container == null || !container.hasValidName)\n this.ValidateExternalBindings(innerContent, missingExternals);\n }\n for (let [, value] of c.namedContent) {\n this.ValidateExternalBindings(\n asOrNull(value, InkObject),\n missingExternals\n );\n }\n } else if (o != null) {\n let divert = asOrNull(o, Divert);\n if (divert && divert.isExternal) {\n let name = divert.targetPathString;\n if (name === null) {\n return throwNullException(\"name\");\n }\n if (!this._externals.has(name)) {\n if (this.allowExternalFunctionFallbacks) {\n let fallbackFound =\n this.mainContentContainer.namedContent.has(name);\n if (!fallbackFound) {\n missingExternals.add(name);\n }\n } else {\n missingExternals.add(name);\n }\n }\n }\n }\n }\n\n public ObserveVariable(\n variableName: string,\n observer: Story.VariableObserver\n ) {\n this.IfAsyncWeCant(\"observe a new variable\");\n\n if (this._variableObservers === null) this._variableObservers = new Map();\n\n if (!this.state.variablesState.GlobalVariableExistsWithName(variableName))\n throw new Error(\n \"Cannot observe variable '\" +\n variableName +\n \"' because it wasn't declared in the ink story.\"\n );\n\n if (this._variableObservers.has(variableName)) {\n this._variableObservers.get(variableName)!.push(observer);\n } else {\n this._variableObservers.set(variableName, [observer]);\n }\n }\n\n public ObserveVariables(\n variableNames: string[],\n observers: Story.VariableObserver[]\n ) {\n for (let i = 0, l = variableNames.length; i < l; i++) {\n this.ObserveVariable(variableNames[i], observers[i]);\n }\n }\n\n public RemoveVariableObserver(\n observer?: Story.VariableObserver,\n specificVariableName?: string\n ) {\n // A couple of things to know about this method:\n //\n // 1. Since `RemoveVariableObserver` is exposed to the JavaScript world,\n // optionality is marked as `undefined` rather than `null`.\n // To keep things simple, null-checks are performed using regular\n // equality operators, where undefined == null.\n //\n // 2. Since C# delegates are translated to arrays of functions,\n // -= becomes a call to splice and null-checks are replaced by\n // emptiness-checks.\n //\n this.IfAsyncWeCant(\"remove a variable observer\");\n\n if (this._variableObservers === null) return;\n\n if (specificVariableName != null) {\n if (this._variableObservers.has(specificVariableName)) {\n if (observer != null) {\n let variableObservers =\n this._variableObservers.get(specificVariableName);\n if (variableObservers != null) {\n variableObservers.splice(variableObservers.indexOf(observer), 1);\n if (variableObservers.length === 0) {\n this._variableObservers.delete(specificVariableName);\n }\n }\n } else {\n this._variableObservers.delete(specificVariableName);\n }\n }\n } else if (observer != null) {\n let keys = this._variableObservers.keys();\n for (let varName of keys) {\n let variableObservers = this._variableObservers.get(varName);\n if (variableObservers != null) {\n variableObservers.splice(variableObservers.indexOf(observer), 1);\n if (variableObservers.length === 0) {\n this._variableObservers.delete(varName);\n }\n }\n }\n }\n }\n\n public VariableStateDidChangeEvent(\n variableName: string,\n newValueObj: InkObject\n ) {\n if (this._variableObservers === null) return;\n\n let observers = this._variableObservers.get(variableName);\n if (typeof observers !== \"undefined\") {\n if (!(newValueObj instanceof Value)) {\n throw new Error(\n \"Tried to get the value of a variable that isn't a standard type\"\n );\n }\n // var val = newValueObj as Value;\n let val = asOrThrows(newValueObj, Value);\n\n for (let observer of observers) {\n observer(variableName, val.valueObject);\n }\n }\n }\n\n get globalTags() {\n return this.TagsAtStartOfFlowContainerWithPathString(\"\");\n }\n\n public TagsForContentAtPath(path: string) {\n return this.TagsAtStartOfFlowContainerWithPathString(path);\n }\n\n public TagsAtStartOfFlowContainerWithPathString(pathString: string) {\n let path = new Path(pathString);\n\n let flowContainer = this.ContentAtPath(path).container;\n if (flowContainer === null) {\n return throwNullException(\"flowContainer\");\n }\n while (true) {\n let firstContent: InkObject = flowContainer.content[0];\n if (firstContent instanceof Container) flowContainer = firstContent;\n else break;\n }\n\n let inTag = false;\n let tags: string[] | null = null;\n\n for (let c of flowContainer.content) {\n // var tag = c as Runtime.Tag;\n let command = asOrNull(c, ControlCommand);\n\n if (command != null) {\n if (command.commandType == ControlCommand.CommandType.BeginTag) {\n inTag = true;\n } else if (command.commandType == ControlCommand.CommandType.EndTag) {\n inTag = false;\n }\n } else if (inTag) {\n let str = asOrNull(c, StringValue);\n if (str !== null) {\n if (tags === null) tags = [];\n if (str.value !== null) tags.push(str.value);\n } else {\n this.Error(\n \"Tag contained non-text content. Only plain text is allowed when using globalTags or TagsAtContentPath. If you want to evaluate dynamic content, you need to use story.Continue().\"\n );\n }\n } else {\n break;\n }\n }\n\n return tags;\n }\n\n public BuildStringOfHierarchy() {\n let sb = new StringBuilder();\n\n this.mainContentContainer.BuildStringOfHierarchy(\n sb,\n 0,\n this.state.currentPointer.Resolve()\n );\n\n return sb.toString();\n }\n\n public BuildStringOfContainer(container: Container) {\n let sb = new StringBuilder();\n container.BuildStringOfHierarchy(\n sb,\n 0,\n this.state.currentPointer.Resolve()\n );\n return sb.toString();\n }\n\n public NextContent() {\n this.state.previousPointer = this.state.currentPointer.copy();\n\n if (!this.state.divertedPointer.isNull) {\n this.state.currentPointer = this.state.divertedPointer.copy();\n this.state.divertedPointer = Pointer.Null;\n\n this.VisitChangedContainersDueToDivert();\n\n if (!this.state.currentPointer.isNull) {\n return;\n }\n }\n\n let successfulPointerIncrement = this.IncrementContentPointer();\n\n if (!successfulPointerIncrement) {\n let didPop = false;\n\n if (this.state.callStack.CanPop(PushPopType.Function)) {\n this.state.PopCallStack(PushPopType.Function);\n\n if (this.state.inExpressionEvaluation) {\n this.state.PushEvaluationStack(new Void());\n }\n\n didPop = true;\n } else if (this.state.callStack.canPopThread) {\n this.state.callStack.PopThread();\n\n didPop = true;\n } else {\n this.state.TryExitFunctionEvaluationFromGame();\n }\n\n if (didPop && !this.state.currentPointer.isNull) {\n this.NextContent();\n }\n }\n }\n\n public IncrementContentPointer() {\n let successfulIncrement = true;\n\n let pointer = this.state.callStack.currentElement.currentPointer.copy();\n pointer.index++;\n\n if (pointer.container === null) {\n return throwNullException(\"pointer.container\");\n }\n while (pointer.index >= pointer.container.content.length) {\n successfulIncrement = false;\n\n // Container nextAncestor = pointer.container.parent as Container;\n let nextAncestor = asOrNull(pointer.container.parent, Container);\n if (nextAncestor instanceof Container === false) {\n break;\n }\n\n let indexInAncestor = nextAncestor!.content.indexOf(pointer.container);\n if (indexInAncestor == -1) {\n break;\n }\n\n pointer = new Pointer(nextAncestor, indexInAncestor);\n\n pointer.index++;\n\n successfulIncrement = true;\n if (pointer.container === null) {\n return throwNullException(\"pointer.container\");\n }\n }\n\n if (!successfulIncrement) pointer = Pointer.Null;\n\n this.state.callStack.currentElement.currentPointer = pointer.copy();\n\n return successfulIncrement;\n }\n\n public TryFollowDefaultInvisibleChoice() {\n let allChoices = this._state.currentChoices;\n\n let invisibleChoices = allChoices.filter((c) => c.isInvisibleDefault);\n\n if (\n invisibleChoices.length == 0 ||\n allChoices.length > invisibleChoices.length\n )\n return false;\n\n let choice = invisibleChoices[0];\n\n if (choice.targetPath === null) {\n return throwNullException(\"choice.targetPath\");\n }\n\n if (choice.threadAtGeneration === null) {\n return throwNullException(\"choice.threadAtGeneration\");\n }\n\n this.state.callStack.currentThread = choice.threadAtGeneration;\n\n if (this._stateSnapshotAtLastNewline !== null) {\n this.state.callStack.currentThread = this.state.callStack.ForkThread();\n }\n\n this.ChoosePath(choice.targetPath, false);\n\n return true;\n }\n\n public NextSequenceShuffleIndex() {\n // var numElementsIntVal = state.PopEvaluationStack () as IntValue;\n let numElementsIntVal = asOrNull(this.state.PopEvaluationStack(), IntValue);\n if (!(numElementsIntVal instanceof IntValue)) {\n this.Error(\"expected number of elements in sequence for shuffle index\");\n return 0;\n }\n\n let seqContainer = this.state.currentPointer.container;\n if (seqContainer === null) {\n return throwNullException(\"seqContainer\");\n }\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (numElementsIntVal.value === null) {\n return throwNullException(\"numElementsIntVal.value\");\n }\n let numElements = numElementsIntVal.value;\n\n // var seqCountVal = state.PopEvaluationStack () as IntValue;\n let seqCountVal = asOrThrows(this.state.PopEvaluationStack(), IntValue);\n let seqCount = seqCountVal.value;\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (seqCount === null) {\n return throwNullException(\"seqCount\");\n }\n\n let loopIndex = seqCount / numElements;\n let iterationIndex = seqCount % numElements;\n\n let seqPathStr = seqContainer.path.toString();\n let sequenceHash = 0;\n for (let i = 0, l = seqPathStr.length; i < l; i++) {\n sequenceHash += seqPathStr.charCodeAt(i) || 0;\n }\n let randomSeed = sequenceHash + loopIndex + this.state.storySeed;\n let random = new PRNG(Math.floor(randomSeed));\n\n let unpickedIndices = [];\n for (let i = 0; i < numElements; ++i) {\n unpickedIndices.push(i);\n }\n\n for (let i = 0; i <= iterationIndex; ++i) {\n let chosen = random.next() % unpickedIndices.length;\n let chosenIndex = unpickedIndices[chosen];\n unpickedIndices.splice(chosen, 1);\n\n if (i == iterationIndex) {\n return chosenIndex;\n }\n }\n\n throw new Error(\"Should never reach here\");\n }\n\n public Error(message: string, useEndLineNumber = false): never {\n let e = new StoryException(message);\n e.useEndLineNumber = useEndLineNumber;\n throw e;\n }\n\n public Warning(message: string) {\n this.AddError(message, true);\n }\n\n public AddError(\n message: string,\n isWarning = false,\n useEndLineNumber = false\n ) {\n let dm = this.currentDebugMetadata;\n\n let errorTypeStr = isWarning ? \"WARNING\" : \"ERROR\";\n\n if (dm != null) {\n let lineNum = useEndLineNumber ? dm.endLineNumber : dm.startLineNumber;\n message =\n \"RUNTIME \" +\n errorTypeStr +\n \": '\" +\n dm.fileName +\n \"' line \" +\n lineNum +\n \": \" +\n message;\n } else if (!this.state.currentPointer.isNull) {\n message =\n \"RUNTIME \" +\n errorTypeStr +\n \": (\" +\n this.state.currentPointer +\n \"): \" +\n message;\n } else {\n message = \"RUNTIME \" + errorTypeStr + \": \" + message;\n }\n\n this.state.AddError(message, isWarning);\n\n // In a broken state don't need to know about any other errors.\n if (!isWarning) this.state.ForceEnd();\n }\n\n public Assert(condition: boolean, message: string | null = null) {\n if (condition == false) {\n if (message == null) {\n message = \"Story assert\";\n }\n\n throw new Error(message + \" \" + this.currentDebugMetadata);\n }\n }\n\n get currentDebugMetadata(): DebugMetadata | null {\n let dm: DebugMetadata | null;\n\n let pointer = this.state.currentPointer;\n if (!pointer.isNull && pointer.Resolve() !== null) {\n dm = pointer.Resolve()!.debugMetadata;\n if (dm !== null) {\n return dm;\n }\n }\n\n for (let i = this.state.callStack.elements.length - 1; i >= 0; --i) {\n pointer = this.state.callStack.elements[i].currentPointer;\n if (!pointer.isNull && pointer.Resolve() !== null) {\n dm = pointer.Resolve()!.debugMetadata;\n if (dm !== null) {\n return dm;\n }\n }\n }\n\n for (let i = this.state.outputStream.length - 1; i >= 0; --i) {\n let outputObj = this.state.outputStream[i];\n dm = outputObj.debugMetadata;\n if (dm !== null) {\n return dm;\n }\n }\n\n return null;\n }\n\n get mainContentContainer() {\n if (this._temporaryEvaluationContainer) {\n return this._temporaryEvaluationContainer;\n } else {\n return this._mainContentContainer;\n }\n }\n\n /**\n * `_mainContentContainer` is almost guaranteed to be set in the\n * constructor, unless the json is malformed.\n */\n private _mainContentContainer!: Container;\n private _listDefinitions: ListDefinitionsOrigin | null = null;\n\n private _externals: Map;\n private _variableObservers: Map | null =\n null;\n private _hasValidatedExternals: boolean = false;\n\n private _temporaryEvaluationContainer: Container | null = null;\n\n /**\n * `state` is almost guaranteed to be set in the constructor, unless\n * using the compiler-specific constructor which will likely not be used in\n * the real world.\n */\n private _state!: StoryState;\n\n private _asyncContinueActive: boolean = false;\n private _stateSnapshotAtLastNewline: StoryState | null = null;\n private _sawLookaheadUnsafeFunctionAfterNewline: boolean = false;\n\n private _recursiveContinueCount: number = 0;\n\n private _asyncSaving: boolean = false;\n\n private _profiler: any | null = null; // TODO: Profiler\n}\n\nexport namespace Story {\n export enum OutputStateChange {\n NoChange = 0,\n ExtendedBeyondNewline = 1,\n NewlineRemoved = 2,\n }\n\n export interface EvaluateFunctionTextOutput {\n returned: any;\n output: string;\n }\n\n export interface ExternalFunctionDef {\n function: ExternalFunction;\n lookAheadSafe: boolean;\n }\n\n export type VariableObserver = (variableName: string, newValue: any) => void;\n export type ExternalFunction = (...args: any) => any;\n}\n","import { AuthorWarning } from \"./AuthorWarning\";\nimport { ConstantDeclaration } from \"./Declaration/ConstantDeclaration\";\nimport { Container as RuntimeContainer } from \"../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../engine/ControlCommand\";\nimport { ErrorHandler } from \"../../../engine/Error\";\nimport { ErrorType } from \"../ErrorType\";\nimport { Expression } from \"./Expression/Expression\";\nimport { ExternalDeclaration } from \"./Declaration/ExternalDeclaration\";\nimport { FlowBase } from \"./Flow/FlowBase\";\nimport { FlowLevel } from \"./Flow/FlowLevel\";\nimport { IncludedFile } from \"./IncludedFile\";\nimport { ListDefinition } from \"./List/ListDefinition\";\nimport { ListElementDefinition } from \"./List/ListElementDefinition\";\nimport { ParsedObject } from \"./Object\";\nimport { Story as RuntimeStory } from \"../../../engine/Story\";\nimport { SymbolType } from \"./SymbolType\";\nimport { Text } from \"./Text\";\nimport { VariableAssignment as RuntimeVariableAssignment } from \"../../../engine/VariableAssignment\";\nimport { Identifier } from \"./Identifier\";\nimport { asOrNull } from \"../../../engine/TypeAssertion\";\nimport { ClosestFlowBase } from \"./Flow/ClosestFlowBase\";\nimport { FunctionCall } from \"./FunctionCall\";\nimport { Path } from \"./Path\";\nimport { VariableAssignment } from \"./Variable/VariableAssignment\";\n\nexport class Story extends FlowBase {\n public static readonly IsReservedKeyword = (name?: string): boolean => {\n switch (name) {\n case \"true\":\n case \"false\":\n case \"not\":\n case \"return\":\n case \"else\":\n case \"VAR\":\n case \"CONST\":\n case \"temp\":\n case \"LIST\":\n case \"function\":\n return true;\n }\n\n return false;\n };\n\n private _errorHandler: ErrorHandler | null = null;\n private _hadError: boolean = false;\n private _hadWarning: boolean = false;\n private _dontFlattenContainers: Set = new Set();\n private _listDefs: Map = new Map();\n\n get flowLevel(): FlowLevel {\n return FlowLevel.Story;\n }\n\n get hadError(): boolean {\n return this._hadError;\n }\n\n get hadWarning(): boolean {\n return this._hadWarning;\n }\n\n public constants: Map = new Map();\n public externals: Map = new Map();\n\n // Build setting for exporting:\n // When true, the visit count for *all* knots, stitches, choices,\n // and gathers is counted. When false, only those that are direclty\n // referenced by the ink are recorded. Use this flag to allow game-side\n // querying of arbitrary knots/stitches etc.\n // Storing all counts is more robust and future proof (updates to the story file\n // that reference previously uncounted visits are possible, but generates a much\n // larger safe file, with a lot of potentially redundant counts.\n public countAllVisits: boolean = false;\n\n constructor(toplevelObjects: ParsedObject[], isInclude: boolean = false) {\n // Don't do anything much on construction, leave it lightweight until\n // the ExportRuntime method is called.\n super(null, toplevelObjects, null, false, isInclude);\n }\n\n get typeName(): string {\n return \"Story\";\n }\n\n // Before this function is called, we have IncludedFile objects interspersed\n // in our content wherever an include statement was.\n // So that the include statement can be added in a sensible place (e.g. the\n // top of the file) without side-effects of jumping into a knot that was\n // defined in that include, we separate knots and stitches from anything\n // else defined at the top scope of the included file.\n //\n // Algorithm: For each IncludedFile we find, split its contents into\n // knots/stiches and any other content. Insert the normal content wherever\n // the include statement was, and append the knots/stitches to the very\n // end of the main story.\n public PreProcessTopLevelObjects(topLevelContent: ParsedObject[]): void {\n super.PreProcessTopLevelObjects(topLevelContent);\n\n const flowsFromOtherFiles = [];\n\n // Inject included files\n for (let obj of topLevelContent) {\n if (obj instanceof IncludedFile) {\n const file: IncludedFile = obj;\n\n // Remove the IncludedFile itself\n const posOfObj = topLevelContent.indexOf(obj);\n topLevelContent.splice(posOfObj, 1);\n\n // When an included story fails to load, the include\n // line itself is still valid, so we have to handle it here\n if (file.includedStory) {\n const nonFlowContent: ParsedObject[] = [];\n const subStory = file.includedStory;\n // Allow empty file\n if (subStory.content != null) {\n for (const subStoryObj of subStory.content) {\n if (subStoryObj instanceof FlowBase) {\n flowsFromOtherFiles.push(subStoryObj);\n } else {\n nonFlowContent.push(subStoryObj);\n }\n }\n\n // Add newline on the end of the include\n nonFlowContent.push(new Text(\"\\n\"));\n\n // Add contents of the file in its place\n topLevelContent.splice(posOfObj, 0, ...nonFlowContent);\n\n // Skip past the content of this sub story\n // (since it will already have recursively included\n // any lines from other files)\n }\n }\n\n // Include object has been removed, with possible content inserted,\n // and position of 'i' will have been determined already.\n continue;\n }\n }\n\n // Add the flows we collected from the included files to the\n // end of our list of our content\n topLevelContent.splice(0, 0, ...flowsFromOtherFiles);\n }\n\n public readonly ExportRuntime = (\n errorHandler: ErrorHandler | null = null\n ): RuntimeStory | null => {\n this._errorHandler = errorHandler;\n\n // Find all constants before main export begins, so that VariableReferences know\n // whether to generate a runtime variable reference or the literal value\n this.constants = new Map();\n for (const constDecl of this.FindAll(ConstantDeclaration)()) {\n // Check for duplicate definitions\n const existingDefinition: Expression = this.constants.get(\n constDecl.constantName!\n ) as any;\n\n if (existingDefinition) {\n if (!existingDefinition.Equals(constDecl.expression)) {\n const errorMsg = `CONST '${constDecl.constantName}' has been redefined with a different value. Multiple definitions of the same CONST are valid so long as they contain the same value. Initial definition was on ${existingDefinition.debugMetadata}.`;\n this.Error(errorMsg, constDecl, false);\n }\n }\n\n this.constants.set(constDecl.constantName!, constDecl.expression);\n }\n\n // List definitions are treated like constants too - they should be usable\n // from other variable declarations.\n this._listDefs = new Map();\n for (const listDef of this.FindAll(ListDefinition)()) {\n if (listDef.identifier?.name) {\n this._listDefs.set(listDef.identifier?.name, listDef);\n }\n }\n\n this.externals = new Map();\n\n // Resolution of weave point names has to come first, before any runtime code generation\n // since names have to be ready before diverts start getting created.\n // (It used to be done in the constructor for a weave, but didn't allow us to generate\n // errors when name resolution failed.)\n this.ResolveWeavePointNaming();\n\n // Get default implementation of runtimeObject, which calls ContainerBase's generation method\n const rootContainer = this.runtimeObject as RuntimeContainer;\n\n // Export initialisation of global variables\n // TODO: We *could* add this as a declarative block to the story itself...\n const variableInitialisation = new RuntimeContainer();\n variableInitialisation.AddContent(RuntimeControlCommand.EvalStart());\n\n // Global variables are those that are local to the story and marked as global\n const runtimeLists = [];\n for (const [key, value] of this.variableDeclarations) {\n if (value.isGlobalDeclaration) {\n if (value.listDefinition) {\n this._listDefs.set(key, value.listDefinition);\n variableInitialisation.AddContent(\n value.listDefinition.runtimeObject!\n );\n\n runtimeLists.push(value.listDefinition.runtimeListDefinition);\n } else {\n if (!value.expression) {\n throw new Error();\n }\n value.expression.GenerateIntoContainer(variableInitialisation);\n }\n\n const runtimeVarAss = new RuntimeVariableAssignment(key, true);\n runtimeVarAss.isGlobal = true;\n variableInitialisation.AddContent(runtimeVarAss);\n }\n }\n\n variableInitialisation.AddContent(RuntimeControlCommand.EvalEnd());\n variableInitialisation.AddContent(RuntimeControlCommand.End());\n\n if (this.variableDeclarations.size > 0) {\n variableInitialisation.name = \"global decl\";\n rootContainer.AddToNamedContentOnly(variableInitialisation);\n }\n\n // Signal that it's safe to exit without error, even if there are no choices generated\n // (this only happens at the end of top level content that isn't in any particular knot)\n rootContainer.AddContent(RuntimeControlCommand.Done());\n\n // Replace runtimeObject with Story object instead of the Runtime.Container generated by Parsed.ContainerBase\n const runtimeStory = new RuntimeStory(rootContainer, runtimeLists);\n\n this.runtimeObject = runtimeStory;\n\n if (this.hadError) {\n return null;\n }\n\n // Optimisation step - inline containers that can be\n this.FlattenContainersIn(rootContainer);\n\n // Now that the story has been fulled parsed into a hierarchy,\n // and the derived runtime hierarchy has been built, we can\n // resolve referenced symbols such as variables and paths.\n // e.g. for paths \" -> knotName --> stitchName\" into an INKPath (knotName.stitchName)\n // We don't make any assumptions that the INKPath follows the same\n // conventions as the script format, so we resolve to actual objects before\n // translating into an INKPath. (This also allows us to choose whether\n // we want the paths to be absolute)\n this.ResolveReferences(this);\n\n if (this.hadError) {\n return null;\n }\n\n runtimeStory.ResetState();\n\n return runtimeStory;\n };\n\n public readonly ResolveList = (listName: string): ListDefinition | null => {\n let list: ListDefinition | null | undefined = this._listDefs.get(listName);\n if (!list) {\n return null;\n }\n\n return list;\n };\n\n public readonly ResolveListItem = (\n listName: string | null,\n itemName: string,\n source: ParsedObject | null = null\n ): ListElementDefinition | null => {\n let listDef: ListDefinition | null | undefined = null;\n\n // Search a specific list if we know its name (i.e. the form listName.itemName)\n if (listName) {\n if (!(listDef = this._listDefs.get(listName))) {\n return null;\n }\n\n return listDef.ItemNamed(itemName);\n } else {\n // Otherwise, try to search all lists\n\n let foundItem: ListElementDefinition | null = null;\n let originalFoundList: ListDefinition | null = null;\n\n for (const [, value] of this._listDefs.entries()) {\n const itemInThisList = value.ItemNamed(itemName);\n if (itemInThisList) {\n if (foundItem) {\n this.Error(\n `Ambiguous item name '${itemName}' found in multiple sets, including ${\n originalFoundList!.identifier\n } and ${value!.identifier}`,\n source,\n false\n );\n } else {\n foundItem = itemInThisList;\n originalFoundList = value!;\n }\n }\n }\n\n return foundItem;\n }\n };\n\n public readonly FlattenContainersIn = (container: RuntimeContainer): void => {\n // Need to create a collection to hold the inner containers\n // because otherwise we'd end up modifying during iteration\n const innerContainers = new Set();\n if (container.content) {\n for (const c of container.content) {\n const innerContainer = asOrNull(c, RuntimeContainer);\n if (innerContainer) {\n innerContainers.add(innerContainer);\n }\n }\n }\n\n // Can't flatten the named inner containers, but we can at least\n // iterate through their children\n if (container.namedContent) {\n for (const [, value] of container.namedContent) {\n const namedInnerContainer = asOrNull(value, RuntimeContainer);\n if (namedInnerContainer) {\n innerContainers.add(namedInnerContainer);\n }\n }\n }\n\n for (const innerContainer of innerContainers) {\n this.TryFlattenContainer(innerContainer);\n this.FlattenContainersIn(innerContainer);\n }\n };\n\n public readonly TryFlattenContainer = (container: RuntimeContainer): void => {\n if (\n (container.namedContent && container.namedContent.size > 0) ||\n container.hasValidName ||\n this._dontFlattenContainers.has(container)\n ) {\n return;\n }\n\n // Inline all the content in container into the parent\n const parentContainer = asOrNull(container.parent, RuntimeContainer);\n if (parentContainer) {\n let contentIdx = parentContainer.content.indexOf(container);\n parentContainer.content.splice(contentIdx, 1);\n\n const dm = container.ownDebugMetadata;\n\n if (container.content) {\n for (const innerContent of container.content) {\n innerContent.parent = null;\n if (dm !== null && innerContent.ownDebugMetadata === null) {\n innerContent.debugMetadata = dm;\n }\n\n parentContainer.InsertContent(innerContent, contentIdx);\n contentIdx += 1;\n }\n }\n }\n };\n\n public readonly Error = (\n message: string,\n source: ParsedObject | null | undefined,\n isWarning: boolean | null | undefined\n ) => {\n let errorType: ErrorType = isWarning ? ErrorType.Warning : ErrorType.Error;\n\n let sb = \"\";\n if (source instanceof AuthorWarning) {\n sb += \"TODO: \";\n errorType = ErrorType.Author;\n } else if (isWarning) {\n sb += \"WARNING: \";\n } else {\n sb += \"ERROR: \";\n }\n\n if (\n source &&\n source.debugMetadata !== null &&\n source.debugMetadata.startLineNumber >= 1\n ) {\n if (source.debugMetadata.fileName != null) {\n sb += `'${source.debugMetadata.fileName}' `;\n }\n\n sb += `line ${source.debugMetadata.startLineNumber}: `;\n }\n\n sb += message;\n\n message = sb;\n\n if (this._errorHandler !== null) {\n this._errorHandler(message, errorType);\n } else {\n throw new Error(message);\n }\n\n this._hadError = errorType === ErrorType.Error;\n this._hadWarning = errorType === ErrorType.Warning;\n };\n\n public readonly ResetError = (): void => {\n this._hadError = false;\n this._hadWarning = false;\n };\n\n public readonly IsExternal = (namedFuncTarget: string): boolean =>\n this.externals.has(namedFuncTarget);\n\n public readonly AddExternal = (decl: ExternalDeclaration): void => {\n if (this.externals.has(decl.name!)) {\n this.Error(\n `Duplicate EXTERNAL definition of '${decl.name}'`,\n decl,\n false\n );\n } else if (decl.name) {\n this.externals.set(decl.name, decl);\n }\n };\n\n public readonly DontFlattenContainer = (\n container: RuntimeContainer\n ): void => {\n this._dontFlattenContainers.add(container);\n };\n\n public readonly NameConflictError = (\n obj: ParsedObject,\n name: string,\n existingObj: ParsedObject,\n typeNameToPrint: string\n ): void => {\n obj.Error(\n `${typeNameToPrint} '${name}': name has already been used for a ${existingObj.typeName.toLowerCase()} on ${\n existingObj.debugMetadata\n }`\n );\n };\n\n // Check given symbol type against everything that's of a higher priority in the ordered SymbolType enum (above).\n // When the given symbol type level is reached, we early-out / return.\n public readonly CheckForNamingCollisions = (\n obj: ParsedObject,\n identifier: Identifier,\n symbolType: SymbolType,\n typeNameOverride: string = \"\"\n ): void => {\n const typeNameToPrint: string = typeNameOverride || obj.typeName;\n if (Story.IsReservedKeyword(identifier?.name)) {\n obj.Error(\n `'${identifier}' cannot be used for the name of a ${typeNameToPrint.toLowerCase()} because it's a reserved keyword`\n );\n return;\n } else if (FunctionCall.IsBuiltIn(identifier?.name || \"\")) {\n obj.Error(\n `'${identifier}' cannot be used for the name of a ${typeNameToPrint.toLowerCase()} because it's a built in function`\n );\n\n return;\n }\n\n // Top level knots\n const maybeKnotOrFunction = this.ContentWithNameAtLevel(\n identifier?.name || \"\",\n FlowLevel.Knot\n );\n\n const knotOrFunction = asOrNull(maybeKnotOrFunction, FlowBase);\n\n if (\n knotOrFunction &&\n (knotOrFunction !== obj || symbolType === SymbolType.Arg)\n ) {\n this.NameConflictError(\n obj,\n identifier?.name || \"\",\n knotOrFunction,\n typeNameToPrint\n );\n return;\n }\n\n if (symbolType < SymbolType.List) {\n return;\n }\n\n // Lists\n for (const [key, value] of this._listDefs) {\n if (\n identifier?.name === key &&\n obj !== value &&\n value.variableAssignment !== obj\n ) {\n this.NameConflictError(obj, identifier?.name, value, typeNameToPrint);\n }\n\n // We don't check for conflicts between individual elements in\n // different lists because they are namespaced.\n if (!(obj instanceof ListElementDefinition)) {\n for (const item of value.itemDefinitions) {\n if (identifier?.name === item.name) {\n this.NameConflictError(\n obj,\n identifier?.name || \"\",\n item,\n typeNameToPrint\n );\n }\n }\n }\n }\n\n // Don't check for VAR->VAR conflicts because that's handled separately\n // (necessary since checking looks up in a dictionary)\n if (symbolType <= SymbolType.Var) {\n return;\n }\n\n // Global variable collision\n const varDecl: VariableAssignment | null =\n (identifier?.name && this.variableDeclarations.get(identifier?.name)) ||\n null;\n if (\n varDecl &&\n varDecl !== obj &&\n varDecl.isGlobalDeclaration &&\n varDecl.listDefinition == null\n ) {\n this.NameConflictError(\n obj,\n identifier?.name || \"\",\n varDecl,\n typeNameToPrint\n );\n }\n\n if (symbolType < SymbolType.SubFlowAndWeave) {\n return;\n }\n\n // Stitches, Choices and Gathers\n const path = new Path(identifier);\n const targetContent = path.ResolveFromContext(obj);\n if (targetContent && targetContent !== obj) {\n this.NameConflictError(\n obj,\n identifier?.name || \"\",\n targetContent,\n typeNameToPrint\n );\n return;\n }\n\n if (symbolType < SymbolType.Arg) {\n return;\n }\n\n // Arguments to the current flow\n if (symbolType !== SymbolType.Arg) {\n let flow: FlowBase | null = asOrNull(obj, FlowBase);\n if (!flow) {\n flow = ClosestFlowBase(obj);\n }\n\n if (flow && flow.hasParameters && flow.args) {\n for (const arg of flow.args) {\n if (arg.identifier?.name === identifier?.name) {\n obj.Error(\n `${typeNameToPrint} '${identifier}': name has already been used for a argument to ${flow.identifier} on ${flow.debugMetadata}`\n );\n\n return;\n }\n }\n }\n }\n };\n}\n","import { Container as RuntimeContainer } from \"../../../../engine/Container\";\nimport { ControlCommand as RuntimeControlCommand } from \"../../../../engine/ControlCommand\";\nimport { Expression } from \"./Expression\";\nimport { ParsedObject } from \"../Object\";\nimport { Text } from \"../Text\";\nimport { asOrNull } from \"../../../../engine/TypeAssertion\";\n\nexport class StringExpression extends Expression {\n get isSingleString() {\n if (this.content.length !== 1) {\n return false;\n }\n\n const c = this.content[0];\n if (!(c instanceof Text)) {\n return false;\n }\n\n return true;\n }\n\n constructor(content: ParsedObject[]) {\n super();\n\n this.AddContent(content);\n }\n\n get typeName(): string {\n return \"String\";\n }\n\n public readonly GenerateIntoContainer = (\n container: RuntimeContainer\n ): void => {\n container.AddContent(RuntimeControlCommand.BeginString());\n\n for (const c of this.content) {\n container.AddContent(c.runtimeObject);\n }\n\n container.AddContent(RuntimeControlCommand.EndString());\n };\n\n public readonly toString = (): string => {\n let sb = \"\";\n for (const c of this.content) {\n sb += c;\n }\n\n return sb;\n };\n\n // Equals override necessary in order to check for CONST multiple definition equality\n public Equals(obj: ParsedObject): boolean {\n const otherStr = asOrNull(obj, StringExpression);\n if (otherStr === null) {\n return false;\n }\n\n // Can only compare direct equality on single strings rather than\n // complex string expressions that contain dynamic logic\n if (!this.isSingleString || !otherStr.isSingleString) {\n return false;\n }\n\n const thisTxt = this.toString();\n const otherTxt = otherStr.toString();\n return thisTxt === otherTxt;\n }\n}\n","import { ParsedObject } from \"./Object\";\nimport { ControlCommand } from \"../../../engine/ControlCommand\";\nimport { InkObject as RuntimeObject } from \"../../../engine/Object\";\n\nexport class Tag extends ParsedObject {\n public isStart: boolean;\n public inChoice: boolean;\n\n constructor(isStart: boolean, inChoice: boolean = false) {\n super();\n this.isStart = isStart;\n this.inChoice = inChoice;\n }\n get typeName(): string {\n return \"Tag\";\n }\n public readonly GenerateRuntimeObject = (): RuntimeObject => {\n if (this.isStart) {\n return ControlCommand.BeginTag();\n } else {\n return ControlCommand.EndTag();\n }\n };\n\n public readonly toString = () => {\n if (this.isStart) {\n return \"#StartTag\";\n } else {\n return \"#EndTag\";\n }\n };\n}\n\nimport { Tag as RuntimeTag } from \"../../../engine/Tag\";\nimport { Wrap } from \"./Wrap\";\nexport class LegacyTag extends Wrap {\n constructor(tag: RuntimeTag) {\n super(tag);\n }\n get typeName(): string {\n return \"Tag\";\n }\n}\n","import { IFileHandler } from \"../IFileHandler\";\n\n// This class replaces upstream's DefaultFileHandler. It doesn't perform any\n// resolution and warns the user about providing a proper file handler when\n// INCLUDE statements are parsed. Since the JavaScript parser can be executed in\n// different environments, we let the user decide which FileHandler is best for\n// their use-case. See PosixFileHandler and JsonFileHandler.\nexport class DefaultFileHandler implements IFileHandler {\n constructor(public readonly rootPath?: string) {}\n\n readonly ResolveInkFilename = (): string => {\n throw Error(\n \"Can't resolve filename because no FileHandler was provided when instantiating the parser / compiler.\"\n );\n };\n\n readonly LoadInkFileContents = (): string => {\n throw Error(\n \"Can't load ink content because no FileHandler was provided when instantiating the parser / compiler.\"\n );\n };\n}\n","import { Argument } from \"./ParsedHierarchy/Argument\";\nimport { AuthorWarning } from \"./ParsedHierarchy/AuthorWarning\";\nimport { BinaryExpression } from \"./ParsedHierarchy/Expression/BinaryExpression\";\nimport { CharacterRange } from \"./CharacterRange\";\nimport { CharacterSet } from \"./CharacterSet\";\nimport { Choice } from \"./ParsedHierarchy/Choice\";\nimport { CommentEliminator } from \"./CommentEliminator\";\nimport { Conditional } from \"./ParsedHierarchy/Conditional/Conditional\";\nimport { ConditionalSingleBranch } from \"./ParsedHierarchy/Conditional/ConditionalSingleBranch\";\nimport { ContentList } from \"./ParsedHierarchy/ContentList\";\nimport { ConstantDeclaration } from \"./ParsedHierarchy/Declaration/ConstantDeclaration\";\nimport { CustomFlags } from \"./CustomFlags\";\nimport { DebugMetadata } from \"../../engine/DebugMetadata\";\nimport { Divert } from \"./ParsedHierarchy/Divert/Divert\";\nimport { DivertTarget } from \"./ParsedHierarchy/Divert/DivertTarget\";\nimport { Expression } from \"./ParsedHierarchy/Expression/Expression\";\nimport { ErrorHandler } from \"../../engine/Error\";\nimport { ExternalDeclaration } from \"./ParsedHierarchy/Declaration/ExternalDeclaration\";\nimport { FlowDecl } from \"./FlowDecl\";\nimport { FunctionCall } from \"./ParsedHierarchy/FunctionCall\";\nimport { Gather } from \"./ParsedHierarchy/Gather/Gather\";\nimport { Glue } from \"./ParsedHierarchy/Glue\";\nimport { Glue as RuntimeGlue } from \"../../engine/Glue\";\nimport { IFileHandler } from \"../IFileHandler\";\nimport { IncDecExpression } from \"./ParsedHierarchy/Expression/IncDecExpression\";\nimport { IncludedFile } from \"./ParsedHierarchy/IncludedFile\";\nimport { InfixOperator } from \"./InfixOperator\";\nimport { Knot } from \"./ParsedHierarchy/Knot\";\nimport { List } from \"./ParsedHierarchy/List/List\";\nimport { ListDefinition } from \"./ParsedHierarchy/List/ListDefinition\";\nimport { ListElementDefinition } from \"./ParsedHierarchy/List/ListElementDefinition\";\nimport { MultipleConditionExpression } from \"./ParsedHierarchy/Expression/MultipleConditionExpression\";\nimport { ParsedObject } from \"./ParsedHierarchy/Object\";\nimport { Path } from \"./ParsedHierarchy/Path\";\nimport { ReturnType } from \"./ParsedHierarchy/ReturnType\";\nimport { Sequence } from \"./ParsedHierarchy/Sequence/Sequence\";\nimport { SequenceType } from \"./ParsedHierarchy/Sequence/SequenceType\";\nimport { StatementLevel } from \"./StatementLevel\";\nimport { Stitch } from \"./ParsedHierarchy/Stitch\";\nimport { Story } from \"./ParsedHierarchy/Story\";\nimport { StringExpression } from \"./ParsedHierarchy/Expression/StringExpression\";\nimport {\n StringParser,\n SpecificParseRule,\n ParseRule,\n ParseRuleReturn,\n ParseSuccess,\n} from \"./StringParser/StringParser\";\nimport { StringParserElement } from \"./StringParser/StringParserElement\";\nimport { Tag } from \"./ParsedHierarchy/Tag\";\nimport { Text } from \"./ParsedHierarchy/Text\";\nimport { TunnelOnwards } from \"./ParsedHierarchy/TunnelOnwards\";\nimport { VariableAssignment } from \"./ParsedHierarchy/Variable/VariableAssignment\";\nimport { VariableReference } from \"./ParsedHierarchy/Variable/VariableReference\";\nimport { UnaryExpression } from \"./ParsedHierarchy/Expression/UnaryExpression\";\nimport { asOrNull, filterUndef } from \"../../engine/TypeAssertion\";\nimport { Identifier } from \"./ParsedHierarchy/Identifier\";\nimport { NumberExpression } from \"./ParsedHierarchy/Expression/NumberExpression\";\nimport { ErrorType } from \"./ErrorType\";\nimport { DefaultFileHandler } from \"../FileHandler/DefaultFileHandler\";\n\nexport class InkParser extends StringParser {\n /**\n * Begin base InkParser section.\n */\n\n get fileHandler(): IFileHandler {\n if (!this._fileHandler) {\n throw new Error(\"No FileHandler defined\");\n }\n return this._fileHandler;\n }\n\n set fileHandler(value: IFileHandler) {\n this._fileHandler = value;\n }\n\n constructor(\n str: string,\n filename: string | null = null,\n externalErrorHandler: ErrorHandler | null = null,\n rootParser: InkParser | null = null,\n fileHandler: IFileHandler | null = null\n ) {\n super(str);\n\n this._filename = filename;\n this.RegisterExpressionOperators();\n this.GenerateStatementLevelRules();\n\n this.errorHandler = this.OnStringParserError;\n\n this._externalErrorHandler = externalErrorHandler;\n\n if (fileHandler === null) {\n this._fileHandler = new DefaultFileHandler();\n } else {\n this._fileHandler = fileHandler;\n }\n\n if (rootParser === null) {\n this._rootParser = this;\n this._openFilenames = [];\n\n if (this._filename !== null) {\n const fullRootInkPath = this.fileHandler.ResolveInkFilename(\n this._filename\n );\n this._openFilenames.push(fullRootInkPath);\n }\n } else {\n this._rootParser = rootParser;\n }\n }\n\n // Main entry point\n // NOTE: This method is named Parse() in upstream.\n public readonly ParseStory = (): Story => {\n const topLevelContent: ParsedObject[] = this.StatementsAtLevel(\n StatementLevel.Top\n );\n\n // Note we used to return null if there were any errors, but this would mean\n // that include files would return completely empty rather than attempting to\n // continue with errors. Returning an empty include files meant that anything\n // that *did* compile successfully would otherwise be ignored, generating way\n // more errors than necessary.\n return new Story(topLevelContent, this._rootParser !== this);\n };\n\n public readonly SeparatedList = (\n mainRule: SpecificParseRule,\n separatorRule: ParseRule\n ): ParseRuleReturn[] | null => {\n const firstElement: ParseRuleReturn = this.Parse(mainRule);\n if (firstElement === null) {\n return null;\n }\n\n const allElements = [];\n allElements.push(firstElement);\n\n do {\n const nextElementRuleId: number = this.BeginRule();\n let sep = separatorRule();\n if (sep === null) {\n this.FailRule(nextElementRuleId);\n break;\n }\n\n const nextElement = this.Parse(mainRule);\n if (nextElement === null) {\n this.FailRule(nextElementRuleId);\n break;\n }\n\n this.SucceedRule(nextElementRuleId);\n allElements.push(nextElement);\n } while (true);\n\n return allElements;\n };\n\n public PreProcessInputString(str: string): string {\n const commentEliminator = new CommentEliminator(str);\n return commentEliminator.Process();\n }\n\n public readonly CreateDebugMetadata = (\n stateAtStart: StringParserElement | null,\n stateAtEnd: StringParserElement\n ): DebugMetadata => {\n const md = new DebugMetadata();\n md.startLineNumber = (stateAtStart?.lineIndex || 0) + 1;\n md.endLineNumber = stateAtEnd.lineIndex + 1;\n md.startCharacterNumber = (stateAtStart?.characterInLineIndex || 0) + 1;\n md.endCharacterNumber = stateAtEnd.characterInLineIndex + 1;\n md.fileName = this._filename;\n\n return md;\n };\n\n public readonly RuleDidSucceed = (\n result: ParseRuleReturn,\n stateAtStart: StringParserElement | null,\n stateAtEnd: StringParserElement\n ): void => {\n // Apply DebugMetadata based on the state at the start of the rule\n // (i.e. use line number as it was at the start of the rule)\n const parsedObj = asOrNull(result, ParsedObject);\n if (parsedObj) {\n parsedObj.debugMetadata = this.CreateDebugMetadata(\n stateAtStart,\n stateAtEnd\n );\n }\n\n // A list of objects that doesn't already have metadata?\n const parsedListObjs: ParsedObject[] | null = Array.isArray(result)\n ? (result as ParsedObject[])\n : null;\n if (parsedListObjs !== null) {\n for (const parsedListObj of parsedListObjs) {\n const singleObj = asOrNull(parsedListObj, ParsedObject);\n if (!singleObj) continue;\n if (!parsedListObj.hasOwnDebugMetadata) {\n parsedListObj.debugMetadata = this.CreateDebugMetadata(\n stateAtStart,\n stateAtEnd\n );\n }\n }\n }\n\n const id = asOrNull(result, Identifier);\n if (id != null) {\n id.debugMetadata = this.CreateDebugMetadata(stateAtStart, stateAtEnd);\n }\n };\n\n get parsingStringExpression(): boolean {\n return this.GetFlag(Number(CustomFlags.ParsingString));\n }\n\n set parsingStringExpression(value: boolean) {\n this.SetFlag(Number(CustomFlags.ParsingString), value);\n }\n\n get tagActive(): boolean {\n return this.GetFlag(Number(CustomFlags.TagActive));\n }\n\n set tagActive(value: boolean) {\n this.SetFlag(Number(CustomFlags.TagActive), value);\n }\n\n public readonly OnStringParserError = (\n message: string,\n index: number,\n lineIndex: number = 0,\n isWarning: boolean = false\n ): void => {\n const warningType: string = isWarning ? \"WARNING:\" : \"ERROR:\";\n let fullMessage: string = warningType;\n\n if (this._filename !== null) {\n fullMessage += ` '${this._filename}'`;\n }\n\n fullMessage += ` line ${lineIndex + 1}: ${message}`;\n\n if (this._externalErrorHandler !== null) {\n this._externalErrorHandler(\n fullMessage,\n isWarning ? ErrorType.Warning : ErrorType.Error\n );\n } else {\n throw new Error(fullMessage);\n }\n };\n\n public readonly AuthorWarning = (): AuthorWarning | null => {\n this.Whitespace();\n\n const identifier = this.Parse(\n this.IdentifierWithMetadata\n ) as unknown as Identifier | null;\n if (identifier === null || identifier.name !== \"TODO\") {\n return null;\n }\n\n this.Whitespace();\n this.ParseString(\":\");\n this.Whitespace();\n\n const message = this.ParseUntilCharactersFromString(\"\\n\\r\");\n\n if (message) {\n return new AuthorWarning(message);\n }\n\n return null;\n };\n\n /**\n * End base InkParser section.\n */\n\n /**\n * Begin CharacterRanges section.\n */\n\n public static readonly LatinBasic: CharacterRange = CharacterRange.Define(\n \"\\u0041\",\n \"\\u007A\",\n new CharacterSet().AddRange(\"\\u005B\", \"\\u0060\")\n );\n\n public static readonly LatinExtendedA: CharacterRange = CharacterRange.Define(\n \"\\u0100\",\n \"\\u017F\"\n // no excludes here\n );\n\n public static readonly LatinExtendedB: CharacterRange = CharacterRange.Define(\n \"\\u0180\",\n \"\\u024F\"\n // no excludes here\n );\n\n public static readonly Greek: CharacterRange = CharacterRange.Define(\n \"\\u0370\",\n \"\\u03FF\",\n new CharacterSet()\n .AddRange(\"\\u0378\", \"\\u0385\")\n .AddCharacters(\"\\u0374\\u0375\\u0378\\u0387\\u038B\\u038D\\u03A2\")\n );\n\n public static readonly Cyrillic: CharacterRange = CharacterRange.Define(\n \"\\u0400\",\n \"\\u04FF\",\n new CharacterSet().AddRange(\"\\u0482\", \"\\u0489\")\n );\n\n public static readonly Armenian: CharacterRange = CharacterRange.Define(\n \"\\u0530\",\n \"\\u058F\",\n new CharacterSet()\n .AddCharacters(\"\\u0530\")\n .AddRange(\"\\u0557\", \"\\u0560\")\n .AddRange(\"\\u0588\", \"\\u058E\")\n );\n\n public static readonly Hebrew: CharacterRange = CharacterRange.Define(\n \"\\u0590\",\n \"\\u05FF\",\n new CharacterSet()\n );\n\n public static readonly Arabic: CharacterRange = CharacterRange.Define(\n \"\\u0600\",\n \"\\u06FF\",\n new CharacterSet()\n );\n\n public static readonly Korean: CharacterRange = CharacterRange.Define(\n \"\\uAC00\",\n \"\\uD7AF\",\n new CharacterSet()\n );\n\n private readonly ExtendIdentifierCharacterRanges = (\n identifierCharSet: CharacterSet\n ): void => {\n const characterRanges = InkParser.ListAllCharacterRanges();\n for (const charRange of characterRanges) {\n identifierCharSet.AddCharacters(charRange.ToCharacterSet());\n }\n };\n\n /// \n /// Gets an array of representing all of the currently supported\n /// non-ASCII character ranges that can be used in identifier names.\n /// \n /// \n /// An array of representing all of the currently supported\n /// non-ASCII character ranges that can be used in identifier names.\n /// \n public static readonly ListAllCharacterRanges = (): CharacterRange[] => [\n InkParser.LatinBasic,\n InkParser.LatinExtendedA,\n InkParser.LatinExtendedB,\n InkParser.Arabic,\n InkParser.Armenian,\n InkParser.Cyrillic,\n InkParser.Greek,\n InkParser.Hebrew,\n InkParser.Korean,\n ];\n\n /**\n * End CharacterRanges section.\n */\n\n /**\n * Begin Choices section.\n */\n\n public _parsingChoice: boolean = false;\n\n public readonly Choice = (): Choice | null => {\n let onceOnlyChoice: boolean = true;\n let bullets = this.Interleave(\n this.OptionalExclude(this.Whitespace),\n this.String(\"*\")\n );\n\n if (!bullets) {\n bullets = this.Interleave(\n this.OptionalExclude(this.Whitespace),\n this.String(\"+\")\n );\n\n if (bullets === null) {\n return null;\n }\n\n onceOnlyChoice = false;\n }\n\n // Optional name for the choice\n const optionalName: Identifier = this.Parse(\n this.BracketedName\n ) as Identifier;\n\n this.Whitespace();\n\n // Optional condition for whether the choice should be shown to the player\n const conditionExpr: Expression = this.Parse(\n this.ChoiceCondition\n ) as Expression;\n\n this.Whitespace();\n\n // Ordinarily we avoid parser state variables like these, since\n // nesting would require us to store them in a stack. But since you should\n // never be able to nest choices within choice content, it's fine here.\n if (this._parsingChoice) {\n throw new Error(\n \"Already parsing a choice - shouldn't have nested choices\"\n );\n }\n\n this._parsingChoice = true;\n\n let startContent: ContentList | null = null;\n const startTextAndLogic = this.Parse(\n this.MixedTextAndLogic\n ) as ParsedObject[];\n if (startTextAndLogic) {\n startContent = new ContentList(startTextAndLogic);\n }\n\n let optionOnlyContent: ContentList | null = null;\n let innerContent: ContentList | null = null;\n\n // Check for a the weave style format:\n // * \"Hello[.\"],\" he said.\n const hasWeaveStyleInlineBrackets: boolean = this.ParseString(\"[\") !== null;\n if (hasWeaveStyleInlineBrackets) {\n this.EndTagIfNecessary(startContent);\n\n const optionOnlyTextAndLogic = this.Parse(\n this.MixedTextAndLogic\n ) as ParsedObject[];\n\n if (optionOnlyTextAndLogic !== null) {\n optionOnlyContent = new ContentList(optionOnlyTextAndLogic);\n }\n\n this.Expect(this.String(\"]\"), \"closing ']' for weave-style option\");\n\n this.EndTagIfNecessary(optionOnlyContent);\n\n let innerTextAndLogic = this.Parse(\n this.MixedTextAndLogic\n ) as ParsedObject[];\n if (innerTextAndLogic !== null) {\n innerContent = new ContentList(innerTextAndLogic);\n }\n }\n\n this.Whitespace();\n\n this.EndTagIfNecessary(innerContent ?? startContent);\n\n // Finally, now we know we're at the end of the main choice body, parse\n // any diverts separately.\n const diverts: ParsedObject[] = this.Parse(\n this.MultiDivert\n ) as ParsedObject[];\n\n this._parsingChoice = false;\n\n this.Whitespace();\n\n // Completely empty choice without even an empty divert?\n const emptyContent: boolean =\n !startContent && !innerContent && !optionOnlyContent;\n\n if (emptyContent && diverts === null) {\n this.Warning(\n \"Choice is completely empty. Interpretting as a default fallback choice. Add a divert arrow to remove this warning: * ->\"\n );\n }\n\n if (!startContent && hasWeaveStyleInlineBrackets && !optionOnlyContent) {\n // * [] some text\n this.Warning(\n \"Blank choice - if you intended a default fallback choice, use the `* ->` syntax\"\n );\n }\n\n if (!innerContent) {\n innerContent = new ContentList();\n }\n\n this.EndTagIfNecessary(innerContent);\n\n // Normal diverts on the end of a choice - simply add to the normal content\n if (diverts !== null) {\n for (const divObj of diverts) {\n // may be TunnelOnwards\n const div = asOrNull(divObj, Divert);\n\n // Empty divert serves no purpose other than to say\n // \"this choice is intentionally left blank\"\n // (as an invisible default choice)\n if (div && div.isEmpty) {\n continue;\n }\n\n innerContent.AddContent(divObj);\n }\n }\n\n // Terminate main content with a newline since this is the end of the line\n // Note that this will be redundant if the diverts above definitely take\n // the flow away permanently.\n innerContent.AddContent(new Text(\"\\n\"));\n\n const choice = new Choice(startContent!, optionOnlyContent!, innerContent);\n if (optionalName) choice.identifier = optionalName;\n choice.indentationDepth = bullets.length;\n choice.hasWeaveStyleInlineBrackets = hasWeaveStyleInlineBrackets;\n choice.condition = conditionExpr;\n choice.onceOnly = onceOnlyChoice;\n choice.isInvisibleDefault = emptyContent;\n return choice;\n };\n\n public readonly ChoiceCondition = (): Expression | null => {\n const conditions = this.Interleave(\n this.ChoiceSingleCondition,\n this.ChoiceConditionsSpace\n );\n\n if (conditions === null) {\n return null;\n } else if (conditions.length === 1) {\n return conditions[0];\n }\n\n return new MultipleConditionExpression(conditions);\n };\n\n public readonly ChoiceConditionsSpace = (): typeof ParseSuccess => {\n // Both optional\n // Newline includes initial end of line whitespace\n this.Newline();\n this.Whitespace();\n\n return ParseSuccess;\n };\n\n public readonly ChoiceSingleCondition = (): Expression | null => {\n if (this.ParseString(\"{\") === null) {\n return null;\n }\n\n const condExpr = this.Expect(\n this.Expression,\n \"choice condition inside { }\"\n ) as Expression;\n\n this.DisallowIncrement(condExpr);\n this.Expect(this.String(\"}\"), \"closing '}' for choice condition\");\n\n return condExpr;\n };\n\n public readonly Gather = (): Gather | null => {\n const gatherDashCountObj: number = this.Parse(this.GatherDashes) as number;\n if (gatherDashCountObj === null) {\n return null;\n }\n\n const gatherDashCount: number = Number(gatherDashCountObj);\n\n // Optional name for the gather\n const optionalName: Identifier = this.Parse(\n this.BracketedName\n ) as Identifier;\n\n const gather = new Gather(optionalName, gatherDashCount);\n\n // Optional newline before gather's content begins\n this.Newline();\n\n return gather;\n };\n\n public readonly GatherDashes = (): number | null => {\n this.Whitespace();\n\n let gatherDashCount: number = 0;\n while (this.ParseDashNotArrow() !== null) {\n gatherDashCount += 1;\n this.Whitespace();\n }\n\n if (gatherDashCount === 0) {\n return null;\n }\n\n return gatherDashCount as number;\n };\n\n public readonly ParseDashNotArrow = () => {\n const ruleId = this.BeginRule();\n\n if (\n this.ParseString(\"->\") === null &&\n this.ParseSingleCharacter() === \"-\"\n ) {\n return this.SucceedRule(ruleId);\n }\n\n return this.FailRule(ruleId);\n };\n\n public readonly BracketedName = (): Identifier | null => {\n if (this.ParseString(\"(\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n const name = this.Parse(this.IdentifierWithMetadata) as Identifier | null;\n if (name === null) {\n return null;\n }\n\n this.Whitespace();\n\n this.Expect(this.String(\")\"), \"closing ')' for bracketed name\");\n\n return name;\n };\n\n /**\n * End Choices section.\n */\n\n /**\n * Begin Conditional section.\n */\n\n public readonly InnerConditionalContent = (\n initialQueryExpression: Expression\n ): Conditional | null => {\n if (initialQueryExpression === undefined) {\n const initialQueryExpression = this.Parse(this.ConditionExpression);\n const conditional = this.Parse(() =>\n this.InnerConditionalContent(initialQueryExpression as Expression)\n ) as Conditional;\n\n if (conditional === null) {\n return null;\n }\n\n return conditional;\n }\n\n let alternatives: ConditionalSingleBranch[] | null;\n const canBeInline: boolean = initialQueryExpression !== null;\n const isInline: boolean = this.Parse(this.Newline) === null;\n\n if (isInline && !canBeInline) {\n return null;\n }\n\n if (isInline) {\n // Inline innards\n alternatives = this.InlineConditionalBranches();\n } else {\n // Multiline innards\n alternatives = this.MultilineConditionalBranches();\n\n if (alternatives === null) {\n // Allow single piece of content within multi-line expression, e.g.:\n // { true:\n // Some content that isn't preceded by '-'\n // }\n if (initialQueryExpression) {\n let soleContent: ParsedObject[] = this.StatementsAtLevel(\n StatementLevel.InnerBlock\n );\n if (soleContent !== null) {\n const soleBranch = new ConditionalSingleBranch(soleContent);\n alternatives = [soleBranch];\n\n // Also allow a final \"- else:\" clause\n const elseBranch = this.Parse(\n this.SingleMultilineCondition\n ) as ConditionalSingleBranch;\n if (elseBranch) {\n if (!elseBranch.isElse) {\n this.ErrorWithParsedObject(\n \"Expected an '- else:' clause here rather than an extra condition\",\n elseBranch\n );\n\n elseBranch.isElse = true;\n }\n\n alternatives.push(elseBranch);\n }\n }\n }\n\n // Still null?\n if (alternatives === null) {\n return null;\n }\n } else if (\n alternatives.length === 1 &&\n alternatives[0].isElse &&\n initialQueryExpression\n ) {\n // Empty true branch - didn't get parsed, but should insert one for semantic correctness,\n // and to make sure that any evaluation stack values get tidied up correctly.\n const emptyTrueBranch = new ConditionalSingleBranch(null);\n emptyTrueBranch.isTrueBranch = true;\n alternatives.unshift(emptyTrueBranch);\n }\n\n // Like a switch statement\n // { initialQueryExpression:\n // ... match the expression\n // }\n if (initialQueryExpression) {\n let earlierBranchesHaveOwnExpression: boolean = false;\n for (let ii = 0; ii < alternatives.length; ++ii) {\n const branch = alternatives[ii];\n const isLast: boolean = ii === alternatives.length - 1;\n\n // Matching equality with initial query expression\n // We set this flag even for the \"else\" clause so that\n // it knows to tidy up the evaluation stack at the end\n\n // Match query\n if (branch.ownExpression) {\n branch.matchingEquality = true;\n earlierBranchesHaveOwnExpression = true;\n } else if (earlierBranchesHaveOwnExpression && isLast) {\n // Else (final branch)\n branch.matchingEquality = true;\n branch.isElse = true;\n } else {\n // Binary condition:\n // { trueOrFalse:\n // - when true\n // - when false\n // }\n if (!isLast && alternatives.length > 2) {\n this.ErrorWithParsedObject(\n \"Only final branch can be an 'else'. Did you miss a ':'?\",\n branch\n );\n } else {\n if (ii === 0) {\n branch.isTrueBranch = true;\n } else {\n branch.isElse = true;\n }\n }\n }\n }\n } else {\n // No initial query, so just a multi-line conditional. e.g.:\n // {\n // - x > 3: greater than three\n // - x == 3: equal to three\n // - x < 3: less than three\n // }\n\n for (let ii = 0; ii < alternatives.length; ++ii) {\n const alt = alternatives[ii];\n const isLast: boolean = ii === alternatives.length - 1;\n\n if (alt.ownExpression === null) {\n if (isLast) {\n alt.isElse = true;\n } else {\n if (alt.isElse) {\n // Do we ALSO have a valid \"else\" at the end? Let's report the error there.\n const finalClause = alternatives[alternatives.length - 1];\n if (finalClause.isElse) {\n this.ErrorWithParsedObject(\n \"Multiple 'else' cases. Can have a maximum of one, at the end.\",\n finalClause\n );\n } else {\n this.ErrorWithParsedObject(\n \"'else' case in conditional should always be the final one\",\n alt\n );\n }\n } else {\n this.ErrorWithParsedObject(\n \"Branch doesn't have condition. Are you missing a ':'? \",\n alt\n );\n }\n }\n }\n }\n\n if (\n alternatives.length === 1 &&\n alternatives[0].ownExpression === null\n ) {\n this.ErrorWithParsedObject(\n \"Condition block with no conditions\",\n alternatives[0]\n );\n }\n }\n }\n\n // TODO: Come up with water-tight error conditions... it's quite a flexible system!\n // e.g.\n // - inline conditionals must have exactly 1 or 2 alternatives\n // - multiline expression shouldn't have mixed existence of branch-conditions?\n if (alternatives === null) {\n return null;\n }\n\n for (const branch of alternatives) {\n branch.isInline = isInline;\n }\n\n const cond = new Conditional(initialQueryExpression, alternatives);\n\n return cond;\n };\n\n public readonly InlineConditionalBranches = ():\n | ConditionalSingleBranch[]\n | null => {\n const listOfLists = this.Interleave(\n this.MixedTextAndLogic,\n this.Exclude(this.String(\"|\")),\n null,\n false\n );\n\n if (listOfLists === null || listOfLists.length === 0) {\n return null;\n }\n\n const result: ConditionalSingleBranch[] = [];\n\n if (listOfLists.length > 2) {\n this.Error(\n \"Expected one or two alternatives separated by '|' in inline conditional\"\n );\n } else {\n const trueBranch = new ConditionalSingleBranch(listOfLists[0]);\n trueBranch.isTrueBranch = true;\n result.push(trueBranch);\n\n if (listOfLists.length > 1) {\n const elseBranch = new ConditionalSingleBranch(listOfLists[1]);\n elseBranch.isElse = true;\n result.push(elseBranch);\n }\n }\n\n return result;\n };\n\n public readonly MultilineConditionalBranches = ():\n | ConditionalSingleBranch[]\n | null => {\n this.MultilineWhitespace();\n\n const multipleConditions = this.OneOrMore(this.SingleMultilineCondition);\n if (multipleConditions === null) {\n return null;\n }\n\n this.MultilineWhitespace();\n\n return multipleConditions as ConditionalSingleBranch[];\n };\n\n public readonly SingleMultilineCondition =\n (): ConditionalSingleBranch | null => {\n this.Whitespace();\n\n if (\n // Make sure we're not accidentally parsing a divert\n this.ParseString(\"->\") !== null ||\n this.ParseString(\"-\") === null\n ) {\n return null;\n }\n\n this.Whitespace();\n\n let expr: Expression | null = null;\n const isElse: boolean = this.Parse(this.ElseExpression) !== null;\n\n if (!isElse) {\n expr = this.Parse(this.ConditionExpression) as Expression;\n }\n\n let content: ParsedObject[] = this.StatementsAtLevel(\n StatementLevel.InnerBlock\n );\n if (expr === null && content === null) {\n this.Error(\"expected content for the conditional branch following '-'\");\n\n // Recover\n content = [new Text(\"\")];\n }\n\n // Allow additional multiline whitespace, if the statements were empty (valid)\n // then their surrounding multiline whitespacce needs to be handled manually.\n // e.g.\n // { x:\n // - 1: // intentionally left blank, but newline needs to be parsed\n // - 2: etc\n // }\n this.MultilineWhitespace();\n\n const branch = new ConditionalSingleBranch(content);\n branch.ownExpression = expr;\n branch.isElse = isElse;\n\n return branch;\n };\n\n public readonly ConditionExpression = (): ParsedObject | null => {\n const expr = this.Parse(this.Expression) as ParsedObject;\n if (expr === null) {\n return null;\n }\n\n this.DisallowIncrement(expr);\n\n this.Whitespace();\n\n if (this.ParseString(\":\") === null) {\n return null;\n }\n\n return expr;\n };\n\n public readonly ElseExpression = (): typeof ParseSuccess | null => {\n if (this.ParseString(\"else\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n if (this.ParseString(\":\") === null) {\n return null;\n }\n\n return ParseSuccess;\n };\n\n /**\n * End Conditional section.\n */\n\n /**\n * Begin Content section.\n */\n\n public _nonTextPauseCharacters: CharacterSet | null = null;\n public _nonTextEndCharacters: CharacterSet | null = null;\n public _notTextEndCharactersChoice: CharacterSet | null = null;\n public _notTextEndCharactersString: CharacterSet | null = null;\n\n public readonly TrimEndWhitespace = (\n mixedTextAndLogicResults: ParsedObject[],\n terminateWithSpace: boolean\n ): void => {\n // Trim whitespace from end\n if (mixedTextAndLogicResults.length > 0) {\n const lastObjIdx = mixedTextAndLogicResults.length - 1;\n const lastObj = mixedTextAndLogicResults[lastObjIdx];\n if (lastObj instanceof Text) {\n const textObj: Text = lastObj;\n textObj.text = textObj.text.replace(new RegExp(/[ \\t]+$/g), \"\");\n\n if (terminateWithSpace) {\n textObj.text += \" \";\n } else if (textObj.text.length === 0) {\n // No content left at all? trim the whole object\n mixedTextAndLogicResults.splice(lastObjIdx, 1);\n\n // Recurse in case there's more whitespace\n this.TrimEndWhitespace(mixedTextAndLogicResults, false);\n }\n }\n }\n };\n\n public readonly LineOfMixedTextAndLogic = (): ParsedObject[] | null => {\n // Consume any whitespace at the start of the line\n // (Except for escaped whitespace)\n this.Parse(this.Whitespace);\n\n let result: ParsedObject[] = this.Parse(\n this.MixedTextAndLogic\n ) as ParsedObject[];\n\n if (!result || !result.length) {\n return null;\n }\n\n // Warn about accidentally writing \"return\" without \"~\"\n const firstText = result[0] as Text;\n if (firstText && firstText.text && firstText.text.startsWith(\"return\")) {\n this.Warning(\n \"Do you need a '~' before 'return'? If not, perhaps use a glue: <> (since it's lowercase) or rewrite somehow?\"\n );\n }\n\n if (result.length === 0) {\n return null;\n }\n\n const lastObj = result[result.length - 1];\n if (!(lastObj instanceof Divert)) {\n this.TrimEndWhitespace(result, false);\n }\n\n this.EndTagIfNecessary(result);\n\n // If the line doens't actually contain any normal text content\n // but is in fact entirely a tag, then let's not append\n // a newline, since we want the tag (or tags) to be associated\n // with the line below rather than being completely independent.\n let lineIsPureTag =\n result.length > 0 && result[0] instanceof Tag && result[0].isStart;\n\n if (!lineIsPureTag) {\n result.push(new Text(\"\\n\"));\n }\n\n this.Expect(this.EndOfLine, \"end of line\", this.SkipToNextLine);\n return result;\n };\n\n public readonly MixedTextAndLogic = (): ParsedObject[] | null => {\n // Check for disallowed \"~\" within this context\n const disallowedTilde = this.ParseObject(this.Spaced(this.String(\"~\")));\n if (disallowedTilde !== null) {\n this.Error(\n \"You shouldn't use a '~' here - tildas are for logic that's on its own line. To do inline logic, use { curly braces } instead\"\n );\n }\n\n // Either, or both interleaved\n let results: ParsedObject[] = this.Interleave(\n this.Optional(this.ContentText),\n this.Optional(this.InlineLogicOrGlueOrStartTag)\n );\n\n // Terminating divert?\n // (When parsing content for the text of a choice, diverts aren't allowed.\n // The divert on the end of the body of a choice is handled specially.)\n if (!this._parsingChoice) {\n const diverts: ParsedObject[] = this.Parse(\n this.MultiDivert\n ) as ParsedObject[];\n if (diverts !== null) {\n // May not have had any results at all if there's *only* a divert!\n if (results === null) {\n results = [];\n }\n\n // End previously active tag if necessary\n this.EndTagIfNecessary(results);\n\n this.TrimEndWhitespace(results, true);\n\n results.push(...diverts);\n }\n }\n\n if (!results) {\n return null;\n }\n\n return results;\n };\n\n public readonly ContentText = () => {\n return this.ContentTextAllowingEscapeChar();\n };\n\n public readonly ContentTextAllowingEscapeChar = (): Text | null => {\n let sb: string | null = null;\n\n do {\n let str = this.Parse(this.ContentTextNoEscape);\n const gotEscapeChar: boolean = this.ParseString(\"\\\\\") !== null;\n\n if (gotEscapeChar || str !== null) {\n if (sb === null) {\n sb = \"\";\n }\n\n if (str !== null) {\n sb += String(str);\n }\n\n if (gotEscapeChar) {\n const c: string = this.ParseSingleCharacter();\n sb += c;\n }\n } else {\n break;\n }\n } while (true);\n\n if (sb !== null) {\n return new Text(sb);\n }\n\n return null;\n };\n\n // Content text is an unusual parse rule compared with most since it's\n // less about saying \"this is is the small selection of stuff that we parse\"\n // and more \"we parse ANYTHING except this small selection of stuff\".\n public readonly ContentTextNoEscape = (): string | null => {\n // Eat through text, pausing at the following characters, and\n // attempt to parse the nonTextRule.\n // \"-\": possible start of divert or start of gather\n // \"<\": possible start of glue\n if (this._nonTextPauseCharacters === null) {\n this._nonTextPauseCharacters = new CharacterSet(\"-<\");\n }\n\n // If we hit any of these characters, we stop *immediately* without bothering to even check the nonTextRule\n // \"{\" for start of logic\n // \"|\" for mid logic branch\n if (this._nonTextEndCharacters === null) {\n this._nonTextEndCharacters = new CharacterSet(\"{}|\\n\\r\\\\#\");\n this._notTextEndCharactersChoice = new CharacterSet(\n this._nonTextEndCharacters\n );\n this._notTextEndCharactersChoice.AddCharacters(\"[]\");\n this._notTextEndCharactersString = new CharacterSet(\n this._nonTextEndCharacters\n );\n this._notTextEndCharactersString.AddCharacters('\"');\n }\n\n // When the ParseUntil pauses, check these rules in case they evaluate successfully\n const nonTextRule: ParseRule = () =>\n this.OneOf([\n this.ParseDivertArrow,\n this.ParseThreadArrow,\n this.EndOfLine,\n this.Glue,\n ]);\n\n let endChars: CharacterSet | null = null;\n if (this.parsingStringExpression) {\n endChars = this._notTextEndCharactersString;\n } else if (this._parsingChoice) {\n endChars = this._notTextEndCharactersChoice;\n } else {\n endChars = this._nonTextEndCharacters;\n }\n\n const pureTextContent: string = this.ParseUntil(\n nonTextRule,\n this._nonTextPauseCharacters,\n endChars\n );\n\n if (pureTextContent !== null) {\n return pureTextContent;\n }\n\n return null;\n };\n\n /**\n * End Content section.\n */\n\n /**\n * Begin Divert section.\n */\n\n public readonly MultiDivert = (): ParsedObject[] | null => {\n this.Whitespace();\n\n let diverts: ParsedObject[] = [];\n\n // Try single thread first\n const threadDivert = this.Parse(this.StartThread) as ParsedObject;\n if (threadDivert) {\n diverts = [threadDivert];\n\n return diverts;\n }\n\n // Normal diverts and tunnels\n const arrowsAndDiverts = this.Interleave(\n this.ParseDivertArrowOrTunnelOnwards,\n this.DivertIdentifierWithArguments\n );\n\n if (!arrowsAndDiverts) {\n return null;\n }\n\n diverts = [];\n\n this.EndTagIfNecessary(diverts);\n\n // Possible patterns:\n // -> -- explicit gather\n // ->-> -- tunnel onwards\n // -> div -- normal divert\n // ->-> div -- tunnel onwards, followed by override divert\n // -> div -> -- normal tunnel\n // -> div ->-> -- tunnel then tunnel continue\n // -> div -> div -- tunnel then divert\n // -> div -> div -> -- tunnel then tunnel\n // -> div -> div ->->\n // -> div -> div ->-> div (etc)\n\n // Look at the arrows and diverts\n for (let ii = 0; ii < arrowsAndDiverts.length; ++ii) {\n const isArrow: boolean = ii % 2 === 0;\n\n // Arrow string\n if (isArrow) {\n // Tunnel onwards\n if ((arrowsAndDiverts[ii] as any) === \"->->\") {\n const tunnelOnwardsPlacementValid: boolean =\n ii === 0 ||\n ii === arrowsAndDiverts.length - 1 ||\n ii === arrowsAndDiverts.length - 2;\n\n if (!tunnelOnwardsPlacementValid) {\n this.Error(\n \"Tunnel onwards '->->' must only come at the begining or the start of a divert\"\n );\n }\n\n const tunnelOnwards = new TunnelOnwards();\n if (ii < arrowsAndDiverts.length - 1) {\n const tunnelOnwardDivert = asOrNull(\n arrowsAndDiverts[ii + 1],\n Divert\n );\n tunnelOnwards.divertAfter = tunnelOnwardDivert;\n }\n\n diverts.push(tunnelOnwards);\n\n // Not allowed to do anything after a tunnel onwards.\n // If we had anything left it would be caused in the above Error for\n // the positioning of a ->->\n break;\n }\n } else {\n // Divert\n const divert = arrowsAndDiverts[ii] as Divert;\n // More to come? (further arrows) Must be tunnelling.\n if (ii < arrowsAndDiverts.length - 1) {\n divert.isTunnel = true;\n }\n\n diverts.push(divert);\n }\n }\n\n // Single -> (used for default choices)\n if (diverts.length === 0 && arrowsAndDiverts.length === 1) {\n const gatherDivert = new Divert(null);\n gatherDivert.isEmpty = true;\n diverts.push(gatherDivert);\n\n if (!this._parsingChoice) {\n this.Error(\"Empty diverts (->) are only valid on choices\");\n }\n }\n\n return diverts;\n };\n\n public readonly StartThread = (): Divert | null => {\n this.Whitespace();\n\n if (this.ParseThreadArrow() === null) {\n return null;\n }\n\n this.Whitespace();\n\n const divert = this.Expect(\n this.DivertIdentifierWithArguments,\n \"target for new thread\",\n () => new Divert(null)\n ) as Divert;\n\n divert.isThread = true;\n\n return divert;\n };\n\n public readonly DivertIdentifierWithArguments = (): Divert | null => {\n this.Whitespace();\n\n const targetComponents: Identifier[] = this.Parse(\n this.DotSeparatedDivertPathComponents\n ) as Identifier[];\n\n if (!targetComponents) {\n return null;\n }\n\n this.Whitespace();\n\n const optionalArguments = this.Parse(\n this.ExpressionFunctionCallArguments\n ) as Expression[];\n\n this.Whitespace();\n\n const targetPath = new Path(targetComponents);\n\n return new Divert(targetPath, optionalArguments);\n };\n\n public readonly SingleDivert = (): Divert | null => {\n const diverts = this.Parse(this.MultiDivert) as ParsedObject[];\n if (!diverts) {\n return null;\n }\n\n // Ideally we'd report errors if we get the\n // wrong kind of divert, but unfortunately we\n // have to hack around the fact that sequences use\n // a very similar syntax.\n // i.e. if you have a multi-divert at the start\n // of a sequence, it initially tries to parse it\n // as a divert target (part of an expression of\n // a conditional) and gives errors. So instead\n // we just have to blindly reject it as a single\n // divert, and give a slightly less nice error\n // when you DO use a multi divert as a divert taret.\n\n if (diverts.length !== 1) {\n return null;\n }\n\n const singleDivert = diverts[0];\n if (singleDivert instanceof TunnelOnwards) {\n return null;\n }\n\n const divert = diverts[0] as Divert;\n if (divert.isTunnel) {\n return null;\n }\n\n return divert;\n };\n\n public readonly DotSeparatedDivertPathComponents = (): Identifier[] =>\n this.Interleave(\n this.Spaced(this.IdentifierWithMetadata),\n this.Exclude(this.String(\".\"))\n );\n\n public readonly ParseDivertArrowOrTunnelOnwards = (): string | null => {\n let numArrows: number = 0;\n while (this.ParseString(\"->\") !== null) {\n numArrows += 1;\n }\n\n if (numArrows === 0) {\n return null;\n } else if (numArrows === 1) {\n return \"->\";\n } else if (numArrows === 2) {\n return \"->->\";\n }\n\n this.Error(\n \"Unexpected number of arrows in divert. Should only have '->' or '->->'\"\n );\n\n return \"->->\";\n };\n\n public readonly ParseDivertArrow = () => this.ParseString(\"->\");\n\n public readonly ParseThreadArrow = () => this.ParseString(\"<-\");\n\n /**\n * End Divert section.\n */\n\n /**\n * Begin Expressions section.\n */\n\n public _binaryOperators: InfixOperator[] = [];\n public _maxBinaryOpLength: number = 0;\n\n public readonly TempDeclarationOrAssignment = (): ParsedObject | null => {\n this.Whitespace();\n\n const isNewDeclaration: boolean = this.ParseTempKeyword();\n\n this.Whitespace();\n\n let varIdentifier: Identifier | null = null;\n if (isNewDeclaration) {\n varIdentifier = this.Expect(\n this.IdentifierWithMetadata,\n \"variable name\"\n ) as Identifier;\n } else {\n varIdentifier = this.Parse(this.IdentifierWithMetadata) as Identifier;\n }\n\n if (varIdentifier === null) {\n return null;\n }\n\n this.Whitespace();\n\n // += -=\n const isIncrement: boolean = this.ParseString(\"+\") !== null;\n const isDecrement: boolean = this.ParseString(\"-\") !== null;\n\n if (isIncrement && isDecrement) {\n this.Error(\"Unexpected sequence '+-'\");\n }\n\n if (this.ParseString(\"=\") === null) {\n // Definitely in an assignment expression?\n if (isNewDeclaration) {\n this.Error(\"Expected '='\");\n }\n\n return null;\n }\n\n const assignedExpression: Expression = this.Expect(\n this.Expression,\n \"value expression to be assigned\"\n ) as Expression;\n\n if (isIncrement || isDecrement) {\n const result = new IncDecExpression(\n varIdentifier,\n assignedExpression,\n isIncrement\n );\n return result;\n }\n\n const result = new VariableAssignment({\n variableIdentifier: varIdentifier,\n assignedExpression,\n isTemporaryNewDeclaration: isNewDeclaration,\n });\n\n return result;\n };\n\n public readonly DisallowIncrement = (expr: ParsedObject): void => {\n if (expr instanceof IncDecExpression) {\n this.Error(\n \"Can't use increment/decrement here. It can only be used on a ~ line\"\n );\n }\n };\n\n public readonly ParseTempKeyword = () => {\n const ruleId = this.BeginRule();\n\n if (this.Parse(this.Identifier) === \"temp\") {\n this.SucceedRule(ruleId);\n return true;\n }\n\n this.FailRule(ruleId);\n return false;\n };\n\n public readonly ReturnStatement = (): ReturnType | null => {\n this.Whitespace();\n\n const returnOrDone = this.Parse(this.Identifier);\n if (returnOrDone !== \"return\") {\n return null;\n }\n\n this.Whitespace();\n\n const expr = this.Parse(this.Expression) as Expression;\n\n const returnObj = new ReturnType(expr);\n\n return returnObj;\n };\n\n // Pratt Parser\n // aka \"Top down operator precedence parser\"\n // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/\n // Algorithm overview:\n // The two types of precedence are handled in two different ways:\n // ((((a . b) . c) . d) . e)\t\t\t#1\n // (a . (b . (c . (d . e))))\t\t\t#2\n // Where #1 is automatically handled by successive loops within the main 'while' in this function,\n // so long as continuing operators have lower (or equal) precedence (e.g. imagine some series of \"*\"s then \"+\" above.\n // ...and #2 is handled by recursion of the right hand term in the binary expression parser.\n // (see link for advice on how to extend for postfix and mixfix operators)\n public readonly Expression = (\n minimumPrecedence: number = 0\n ): Expression | null => {\n this.Whitespace();\n\n // First parse a unary expression e.g. \"-a\" or parethensised \"(1 + 2)\"\n let expr = this.ExpressionUnary();\n if (expr === null) {\n return null;\n }\n\n this.Whitespace();\n\n // Attempt to parse (possibly multiple) continuing infix expressions (e.g. 1 + 2 + 3)\n while (true) {\n const ruleId = this.BeginRule();\n\n // Operator\n const infixOp = this.ParseInfixOperator();\n if (infixOp !== null && infixOp.precedence > minimumPrecedence) {\n // Expect right hand side of operator\n const expectationMessage = `right side of '${infixOp.type}' expression`;\n const multiaryExpr = this.Expect(\n () => this.ExpressionInfixRight(expr, infixOp),\n expectationMessage\n );\n\n if (multiaryExpr === null) {\n // Fail for operator and right-hand side of multiary expression\n this.FailRule(ruleId);\n\n return null;\n }\n\n expr = this.SucceedRule(ruleId, multiaryExpr) as Expression;\n\n continue;\n }\n\n this.FailRule(ruleId);\n break;\n }\n\n this.Whitespace();\n\n return expr;\n };\n\n public readonly ExpressionUnary = (): Expression | null => {\n // Divert target is a special case - it can't have any other operators\n // applied to it, and we also want to check for it first so that we don't\n // confuse \"->\" for subtraction.\n const divertTarget = this.Parse(this.ExpressionDivertTarget) as Expression;\n if (divertTarget !== null) {\n return divertTarget;\n }\n\n let prefixOp: Expression = this.OneOf([\n this.String(\"-\"),\n this.String(\"!\"),\n ]) as Expression;\n\n // Don't parse like the string rules above, in case its actually\n // a variable that simply starts with \"not\", e.g. \"notable\".\n // This rule uses the Identifier rule, which will scan as much text\n // as possible before returning.\n if (prefixOp === null) {\n prefixOp = this.Parse(this.ExpressionNot) as Expression;\n }\n\n this.Whitespace();\n\n // - Since we allow numbers at the start of variable names, variable names are checked before literals\n // - Function calls before variable names in case we see parentheses\n let expr = this.OneOf([\n this.ExpressionList,\n this.ExpressionParen,\n this.ExpressionFunctionCall,\n this.ExpressionVariableName,\n this.ExpressionLiteral,\n ]) as Expression | null;\n\n // Only recurse immediately if we have one of the (usually optional) unary ops\n if (expr === null && prefixOp !== null) {\n expr = this.ExpressionUnary();\n }\n\n if (expr === null) {\n return null;\n } else if (prefixOp !== null) {\n expr = UnaryExpression.WithInner(expr, prefixOp as any) as Expression;\n }\n\n this.Whitespace();\n\n const postfixOp = this.OneOf([this.String(\"++\"), this.String(\"--\")]);\n\n if (postfixOp !== null) {\n const isInc: boolean = postfixOp === \"++\";\n\n if (!(expr instanceof VariableReference)) {\n this.Error(\n `can only increment and decrement variables, but saw '${expr}'.`\n );\n\n // Drop down and succeed without the increment after reporting error\n } else {\n const varRef = expr as VariableReference;\n expr = new IncDecExpression(varRef.identifier, isInc);\n }\n }\n\n return expr;\n };\n\n public readonly ExpressionNot = (): string | null => {\n const id = this.Identifier();\n if (id === \"not\") {\n return id;\n }\n\n return null;\n };\n\n public readonly ExpressionLiteral = (): Expression =>\n this.OneOf([\n this.ExpressionFloat,\n this.ExpressionInt,\n this.ExpressionBool,\n this.ExpressionString,\n ]) as Expression;\n\n public readonly ExpressionDivertTarget = (): Expression | null => {\n this.Whitespace();\n\n const divert = this.Parse(this.SingleDivert) as Divert;\n if (!divert || (divert && divert.isThread)) {\n return null;\n }\n\n this.Whitespace();\n\n return new DivertTarget(divert);\n };\n\n public readonly ExpressionInt = (): NumberExpression | null => {\n const intOrNull: number = this.ParseInt() as number;\n if (intOrNull === null) {\n return null;\n }\n\n return new NumberExpression(intOrNull, \"int\");\n };\n\n public readonly ExpressionFloat = (): NumberExpression | null => {\n const floatOrNull: number = this.ParseFloat() as number;\n if (floatOrNull === null) {\n return null;\n }\n\n return new NumberExpression(floatOrNull, \"float\");\n };\n\n public readonly ExpressionString = (): StringExpression | null => {\n const openQuote = this.ParseString('\"');\n if (openQuote === null) {\n return null;\n }\n\n // Set custom parser state flag so that within the text parser,\n // it knows to treat the quote character (\") as an end character\n this.parsingStringExpression = true;\n\n let textAndLogic: ParsedObject[] = this.Parse(\n this.MixedTextAndLogic\n ) as ParsedObject[];\n\n this.Expect(this.String('\"'), \"close quote for string expression\");\n\n this.parsingStringExpression = false;\n\n if (textAndLogic === null) {\n textAndLogic = [new Text(\"\")];\n } else if (textAndLogic.find((c) => c instanceof Divert)) {\n this.Error(\"String expressions cannot contain diverts (->)\");\n }\n\n return new StringExpression(textAndLogic);\n };\n\n public readonly ExpressionBool = (): NumberExpression | null => {\n const id = this.Parse(this.Identifier);\n if (id === \"true\") {\n return new NumberExpression(true, \"bool\");\n } else if (id === \"false\") {\n return new NumberExpression(false, \"bool\");\n }\n\n return null;\n };\n\n public readonly ExpressionFunctionCall = (): Expression | null => {\n const iden = this.Parse(this.IdentifierWithMetadata);\n if (iden === null) {\n return null;\n }\n\n this.Whitespace();\n\n const args = this.Parse(this.ExpressionFunctionCallArguments);\n if (args === null) {\n return null;\n }\n\n return new FunctionCall(iden as Identifier, args as any);\n };\n\n public readonly ExpressionFunctionCallArguments = (): Expression[] | null => {\n if (this.ParseString(\"(\") === null) {\n return null;\n }\n\n // \"Exclude\" requires the rule to succeed, but causes actual comma string to be excluded from the list of results\n const commas: ParseRule = this.Exclude(this.String(\",\"));\n let args = this.Interleave(this.Expression, commas);\n if (args === null) {\n args = [];\n }\n\n this.Whitespace();\n\n this.Expect(this.String(\")\"), \"closing ')' for function call\");\n\n return args;\n };\n\n public readonly ExpressionVariableName = (): Expression | null => {\n const path = this.Interleave(\n this.IdentifierWithMetadata,\n this.Exclude(this.Spaced(this.String(\".\")))\n );\n\n if (path === null || Story.IsReservedKeyword(path[0].name)) {\n return null;\n }\n\n return new VariableReference(path);\n };\n\n public readonly ExpressionParen = (): Expression | null => {\n if (this.ParseString(\"(\") === null) {\n return null;\n }\n\n const innerExpr = this.Parse(this.Expression) as Expression;\n if (innerExpr === null) {\n return null;\n }\n\n this.Whitespace();\n\n this.Expect(this.String(\")\"), \"closing parenthesis ')' for expression\");\n\n return innerExpr;\n };\n\n public readonly ExpressionInfixRight = (\n left: Expression | null,\n op: InfixOperator\n ) => {\n if (!left) {\n return null;\n }\n\n this.Whitespace();\n\n const right = this.Parse(() =>\n this.Expression(op.precedence)\n ) as Expression;\n if (right) {\n // We assume that the character we use for the operator's type is the same\n // as that used internally by e.g. Runtime.Expression.Add, Runtime.Expression.Multiply etc\n const expr = new BinaryExpression(left, right, op.type);\n return expr;\n }\n\n return null;\n };\n\n private readonly ParseInfixOperator = (): InfixOperator | null => {\n for (const op of this._binaryOperators) {\n const ruleId: number = this.BeginRule();\n\n if (this.ParseString(op.type) !== null) {\n if (op.requireWhitespace) {\n if (this.Whitespace() === null) {\n this.FailRule(ruleId);\n\n continue;\n }\n }\n\n return this.SucceedRule(ruleId, op) as InfixOperator;\n }\n\n this.FailRule(ruleId);\n }\n\n return null;\n };\n\n public readonly ExpressionList = (): List | null => {\n this.Whitespace();\n\n if (this.ParseString(\"(\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n // When list has:\n // - 0 elements (null list) - this is okay, it's an empty list: \"()\"\n // - 1 element - it could be confused for a single non-list related\n // identifier expression in brackets, but this is a useless thing\n // to do, so we reserve that syntax for a list with one item.\n // - 2 or more elements - normal!\n const memberNames: Identifier[] = this.SeparatedList(\n this.ListMember,\n this.Spaced(this.String(\",\"))\n ) as Identifier[];\n\n this.Whitespace();\n\n // May have failed to parse the inner list - the parentheses may\n // be for a normal expression\n if (this.ParseString(\")\") === null) {\n return null;\n }\n return new List(memberNames);\n };\n\n public readonly ListMember = (): Identifier | null => {\n this.Whitespace();\n\n let identifier: Identifier = this.Parse(\n this.IdentifierWithMetadata\n ) as Identifier;\n if (identifier === null) {\n return null;\n }\n\n const dot = this.ParseString(\".\");\n if (dot !== null) {\n const identifier2: Identifier = this.Expect(\n this.IdentifierWithMetadata,\n `element name within the set ${identifier}`\n ) as Identifier;\n\n identifier.name += `.${identifier2?.name}`;\n }\n\n this.Whitespace();\n\n return identifier;\n };\n\n public readonly RegisterExpressionOperators = () => {\n // These will be tried in order, so we need \"<=\" before \"<\"\n // for correctness\n\n this.RegisterBinaryOperator(\"&&\", 1);\n this.RegisterBinaryOperator(\"||\", 1);\n this.RegisterBinaryOperator(\"and\", 1, true);\n this.RegisterBinaryOperator(\"or\", 1, true);\n this.RegisterBinaryOperator(\"==\", 2);\n this.RegisterBinaryOperator(\">=\", 2);\n this.RegisterBinaryOperator(\"<=\", 2);\n this.RegisterBinaryOperator(\"<\", 2);\n this.RegisterBinaryOperator(\">\", 2);\n this.RegisterBinaryOperator(\"!=\", 2);\n\n // (apples, oranges) + cabbages has (oranges, cabbages) === true\n this.RegisterBinaryOperator(\"?\", 3);\n this.RegisterBinaryOperator(\"has\", 3, true);\n this.RegisterBinaryOperator(\"!?\", 3);\n this.RegisterBinaryOperator(\"hasnt\", 3, true);\n this.RegisterBinaryOperator(\"^\", 3);\n\n this.RegisterBinaryOperator(\"+\", 4);\n this.RegisterBinaryOperator(\"-\", 5);\n this.RegisterBinaryOperator(\"*\", 6);\n this.RegisterBinaryOperator(\"/\", 7);\n\n this.RegisterBinaryOperator(\"%\", 8);\n this.RegisterBinaryOperator(\"mod\", 8, true);\n };\n\n public readonly RegisterBinaryOperator = (\n op: string,\n precedence: number,\n requireWhitespace: boolean = false\n ): void => {\n const infix = new InfixOperator(op, precedence, requireWhitespace);\n this._binaryOperators.push(infix);\n this._maxBinaryOpLength = Math.max(this._maxBinaryOpLength, op.length);\n };\n\n /**\n * End Expressions section.\n */\n\n /**\n * Begin Include section.\n */\n\n private _rootParser: InkParser;\n private _openFilenames: string[] = [];\n\n public readonly IncludeStatement = () => {\n this.Whitespace();\n\n if (this.ParseString(\"INCLUDE\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n let filename: string = this.Expect(\n () => this.ParseUntilCharactersFromString(\"\\n\\r\"),\n \"filename for include statement\"\n ) as string;\n\n filename = filename.replace(new RegExp(/[ \\t]+$/g), \"\");\n\n // Working directory should already have been set up relative to the root ink file.\n const fullFilename = this.fileHandler.ResolveInkFilename(filename);\n\n if (this.FilenameIsAlreadyOpen(fullFilename)) {\n this.Error(\n `Recursive INCLUDE detected: '${fullFilename}' is already open.`\n );\n this.ParseUntilCharactersFromString(\"\\r\\n\");\n return new IncludedFile(null);\n } else {\n this.AddOpenFilename(fullFilename);\n }\n\n let includedStory: Story | null = null;\n let includedString: string = \"\";\n try {\n includedString =\n this._rootParser.fileHandler.LoadInkFileContents(fullFilename);\n } catch (err) {\n this.Error(`Failed to load: '${filename}'.\\nError:${err}`);\n }\n\n if (includedString) {\n const parser: InkParser = new InkParser(\n includedString,\n filename,\n this._externalErrorHandler,\n this._rootParser,\n this.fileHandler\n );\n\n includedStory = parser.ParseStory();\n }\n\n this.RemoveOpenFilename(fullFilename);\n\n // Return valid IncludedFile object even if there were errors when parsing.\n // We don't want to attempt to re-parse the include line as something else,\n // and we want to include the bits that *are* valid, so we don't generate\n // more errors than necessary.\n return new IncludedFile(includedStory);\n };\n\n public readonly FilenameIsAlreadyOpen = (fullFilename: string): boolean =>\n this._rootParser._openFilenames.includes(fullFilename);\n\n public readonly AddOpenFilename = (fullFilename: string): void => {\n this._rootParser._openFilenames.push(fullFilename);\n };\n\n public readonly RemoveOpenFilename = (fullFilename: string) => {\n this._rootParser._openFilenames.splice(\n this._rootParser._openFilenames.indexOf(fullFilename),\n 1\n );\n };\n\n /**\n * End Include section.\n */\n\n /**\n * Begin Knot section.\n */\n\n public readonly KnotDefinition = (): Knot | null => {\n const knotDecl: FlowDecl = this.Parse(this.KnotDeclaration) as FlowDecl;\n if (knotDecl === null) {\n return null;\n }\n\n this.Expect(\n this.EndOfLine,\n \"end of line after knot name definition\",\n this.SkipToNextLine\n );\n\n const innerKnotStatements: ParseRule = (): ParsedObject[] =>\n this.StatementsAtLevel(StatementLevel.Knot);\n\n const content = this.Expect(\n innerKnotStatements,\n \"at least one line within the knot\",\n this.KnotStitchNoContentRecoveryRule\n ) as ParsedObject[];\n\n return new Knot(knotDecl.name, content, knotDecl.args, knotDecl.isFunction);\n };\n\n public readonly KnotDeclaration = (): FlowDecl | null => {\n this.Whitespace();\n\n if (this.KnotTitleEquals() === null) {\n return null;\n }\n\n this.Whitespace();\n\n const identifier: Identifier = this.Parse(\n this.IdentifierWithMetadata\n ) as Identifier;\n let knotName: Identifier;\n\n const isFunc: boolean = identifier?.name === \"function\";\n if (isFunc) {\n this.Expect(this.Whitespace, \"whitespace after the 'function' keyword\");\n\n knotName = this.Parse(this.IdentifierWithMetadata) as Identifier;\n } else {\n knotName = identifier;\n }\n\n if (knotName === null) {\n this.Error(`Expected the name of the ${isFunc ? \"function\" : \"knot\"}`);\n knotName = new Identifier(\"\"); // prevent later null ref\n }\n\n this.Whitespace();\n\n const parameterNames: Argument[] = this.Parse(\n this.BracketedKnotDeclArguments\n ) as Argument[];\n\n this.Whitespace();\n\n // Optional equals after name\n this.Parse(this.KnotTitleEquals);\n\n return new FlowDecl(knotName, parameterNames, isFunc);\n };\n\n public readonly KnotTitleEquals = (): string | null => {\n // 2+ \"=\" starts a knot\n const multiEquals = this.ParseCharactersFromString(\"=\");\n if (multiEquals === null || multiEquals.length <= 1) {\n return null;\n }\n\n return multiEquals;\n };\n\n public readonly StitchDefinition = (): ParseRuleReturn => {\n const decl = this.Parse(this.StitchDeclaration) as FlowDecl;\n if (decl === null) {\n return null;\n }\n\n this.Expect(\n this.EndOfLine,\n \"end of line after stitch name\",\n this.SkipToNextLine\n );\n\n const innerStitchStatements: ParseRule = () =>\n this.StatementsAtLevel(StatementLevel.Stitch);\n\n const content = this.Expect(\n innerStitchStatements,\n \"at least one line within the stitch\",\n this.KnotStitchNoContentRecoveryRule\n ) as ParsedObject[];\n\n return new Stitch(decl.name, content, decl.args, decl.isFunction);\n };\n\n public readonly StitchDeclaration = (): FlowDecl | null => {\n this.Whitespace();\n\n // Single \"=\" to define a stitch\n if (this.ParseString(\"=\") === null) {\n return null;\n }\n\n // If there's more than one \"=\", that's actually a knot definition (or divert), so this rule should fail\n if (this.ParseString(\"=\") !== null) {\n return null;\n }\n\n this.Whitespace();\n\n // Stitches aren't allowed to be functions, but we parse it anyway and report the error later\n const isFunc: boolean = this.ParseString(\"function\") !== null;\n if (isFunc) {\n this.Whitespace();\n }\n\n const stitchName: Identifier = this.Parse(\n this.IdentifierWithMetadata\n ) as Identifier;\n if (stitchName === null) {\n return null;\n }\n\n this.Whitespace();\n\n const flowArgs: Argument[] = this.Parse(\n this.BracketedKnotDeclArguments\n ) as Argument[];\n\n this.Whitespace();\n\n return new FlowDecl(stitchName, flowArgs, isFunc);\n };\n\n public readonly KnotStitchNoContentRecoveryRule = (): ParseRuleReturn => {\n // Jump ahead to the next knot or the end of the file\n this.ParseUntil(this.KnotDeclaration, new CharacterSet(\"=\"), null);\n\n const recoveredFlowContent: ParsedObject[] = [new Text(\"\")];\n\n return recoveredFlowContent;\n };\n\n public readonly BracketedKnotDeclArguments = (): Argument[] | null => {\n if (this.ParseString(\"(\") === null) {\n return null;\n }\n\n let flowArguments = this.Interleave(\n this.Spaced(this.FlowDeclArgument),\n this.Exclude(this.String(\",\"))\n );\n\n this.Expect(this.String(\")\"), \"closing ')' for parameter list\");\n\n // If no parameters, create an empty list so that this method is type safe and\n // doesn't attempt to return the ParseSuccess object\n if (flowArguments === null) {\n flowArguments = [];\n }\n\n return flowArguments;\n };\n\n public readonly FlowDeclArgument = (): Argument | null => {\n // Possible forms:\n // name\n // -> name (variable divert target argument\n // ref name\n // ref -> name (variable divert target by reference)\n const firstIden = this.Parse(this.IdentifierWithMetadata) as Identifier;\n this.Whitespace();\n\n const divertArrow = this.ParseDivertArrow();\n\n this.Whitespace();\n\n const secondIden = this.Parse(this.IdentifierWithMetadata) as Identifier;\n\n if (firstIden == null && secondIden === null) {\n return null;\n }\n\n const flowArg = new Argument();\n if (divertArrow !== null) {\n flowArg.isDivertTarget = true;\n }\n\n // Passing by reference\n if (firstIden !== null && firstIden.name === \"ref\") {\n if (secondIden === null) {\n this.Error(\"Expected an parameter name after 'ref'\");\n }\n\n flowArg.identifier = secondIden;\n flowArg.isByReference = true;\n } else {\n // Simple argument name\n if (flowArg.isDivertTarget) {\n flowArg.identifier = secondIden;\n } else {\n flowArg.identifier = firstIden;\n }\n\n if (flowArg.identifier === null) {\n this.Error(\"Expected an parameter name\");\n }\n\n flowArg.isByReference = false;\n }\n\n return flowArg;\n };\n\n public readonly ExternalDeclaration = (): ExternalDeclaration | null => {\n this.Whitespace();\n\n const external = this.Parse(\n this.IdentifierWithMetadata\n ) as Identifier | null;\n if (external === null || external.name != \"EXTERNAL\") {\n return null;\n }\n\n this.Whitespace();\n\n const funcIdentifier: Identifier =\n (this.Expect(\n this.IdentifierWithMetadata,\n \"name of external function\"\n ) as Identifier | null) || new Identifier(\"\");\n\n this.Whitespace();\n\n let parameterNames = this.Expect(\n this.BracketedKnotDeclArguments,\n `declaration of arguments for EXTERNAL, even if empty, i.e. 'EXTERNAL ${funcIdentifier}()'`\n ) as Argument[];\n\n if (parameterNames === null) {\n parameterNames = [];\n }\n\n const argNames = parameterNames\n .map((arg) => arg.identifier?.name)\n .filter(filterUndef);\n\n return new ExternalDeclaration(funcIdentifier, argNames);\n };\n\n /**\n * End Knot section.\n */\n\n /**\n * Start Logic section.\n */\n\n private _identifierCharSet: CharacterSet | null = null;\n\n get identifierCharSet(): CharacterSet {\n if (this._identifierCharSet === null) {\n (this._identifierCharSet = new CharacterSet())\n .AddRange(\"A\", \"Z\")\n .AddRange(\"a\", \"z\")\n .AddRange(\"0\", \"9\")\n .Add(\"_\");\n\n // Enable non-ASCII characters for story identifiers.\n this.ExtendIdentifierCharacterRanges(this._identifierCharSet);\n }\n\n return this._identifierCharSet;\n }\n\n public readonly LogicLine = (): ParsedObject | null => {\n this.Whitespace();\n\n if (this.ParseString(\"~\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n // Some example lines we need to be able to distinguish between:\n // ~ temp x = 5 -- var decl + assign\n // ~ temp x -- var decl\n // ~ x = 5 -- var assign\n // ~ x -- expr (not var decl or assign)\n // ~ f() -- expr\n // We don't treat variable decl/assign as an expression since we don't want an assignment\n // to have a return value, or to be used in compound expressions.\n const afterTilde: ParseRule = () =>\n this.OneOf([\n this.ReturnStatement,\n this.TempDeclarationOrAssignment,\n this.Expression,\n ]);\n\n let result = this.Expect(\n afterTilde,\n \"expression after '~'\",\n this.SkipToNextLine\n ) as ParsedObject;\n\n // Prevent further errors, already reported expected expression and have skipped to next line.\n if (result === null) {\n return new ContentList();\n }\n\n // Parse all expressions, but tell the writer off if they did something useless like:\n // ~ 5 + 4\n // And even:\n // ~ false && myFunction()\n // ...since it's bad practice, and won't do what they expect if\n // they're expecting C's lazy evaluation.\n if (\n result instanceof Expression &&\n !(result instanceof FunctionCall || result instanceof IncDecExpression)\n ) {\n this.Error(\n \"Logic following a '~' can't be that type of expression. It can only be something like:\\n\\t~ return\\n\\t~ var x = blah\\n\\t~ x++\\n\\t~ myFunction()\"\n );\n }\n\n // Line is pure function call? e.g.\n // ~ f()\n // Add extra pop to make sure we tidy up after ourselves.\n // We no longer need anything on the evaluation stack.\n const funCall = asOrNull(result, FunctionCall);\n if (funCall) {\n funCall.shouldPopReturnedValue = true;\n }\n\n // If the expression contains a function call, then it could produce a text side effect,\n // in which case it needs a newline on the end. e.g.\n // ~ printMyName()\n // ~ x = 1 + returnAValueAndAlsoPrintStuff()\n // If no text gets printed, then the extra newline will have to be culled later.\n // Multiple newlines on the output will be removed, so there will be no \"leak\" for\n // long running calculations. It's disappointingly messy though :-/\n if (result.Find(FunctionCall)() !== null) {\n result = new ContentList(result as any, new Text(\"\\n\"));\n }\n\n this.Expect(this.EndOfLine, \"end of line\", this.SkipToNextLine);\n\n return result as ParsedObject;\n };\n\n public readonly VariableDeclaration = (): ParsedObject | null => {\n this.Whitespace();\n\n const id = this.Parse(this.Identifier);\n if (id !== \"VAR\") {\n return null;\n }\n\n this.Whitespace();\n\n const varName = this.Expect(\n this.IdentifierWithMetadata,\n \"variable name\"\n ) as Identifier;\n\n this.Whitespace();\n\n this.Expect(\n this.String(\"=\"),\n \"the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)\"\n );\n\n this.Whitespace();\n\n const definition = this.Expect(this.Expression, \"initial value for \");\n\n const expr = definition as Expression;\n\n if (expr) {\n const check =\n expr instanceof NumberExpression ||\n expr instanceof StringExpression ||\n expr instanceof DivertTarget ||\n expr instanceof VariableReference ||\n expr instanceof List;\n\n if (!check) {\n this.Error(\n \"initial value for a variable must be a number, constant, list or divert target\"\n );\n }\n\n if (this.Parse(this.ListElementDefinitionSeparator) !== null) {\n this.Error(\n \"Unexpected ','. If you're trying to declare a new list, use the LIST keyword, not VAR\"\n );\n } else if (expr instanceof StringExpression) {\n // Ensure string expressions are simple\n const strExpr = expr as StringExpression;\n if (!strExpr.isSingleString) {\n this.Error(\"Constant strings cannot contain any logic.\");\n }\n }\n\n const result = new VariableAssignment({\n assignedExpression: expr,\n isGlobalDeclaration: true,\n variableIdentifier: varName,\n });\n\n return result;\n }\n\n return null;\n };\n\n public readonly ListDeclaration = (): VariableAssignment | null => {\n this.Whitespace();\n\n const id = this.Parse(this.Identifier);\n if (id != \"LIST\") {\n return null;\n }\n\n this.Whitespace();\n\n const varName = this.Expect(\n this.IdentifierWithMetadata,\n \"list name\"\n ) as Identifier;\n\n this.Whitespace();\n\n this.Expect(\n this.String(\"=\"),\n \"the '=' for an assignment of the list definition\"\n );\n\n this.Whitespace();\n\n const definition = this.Expect(\n this.ListDefinition,\n \"list item names\"\n ) as ListDefinition;\n\n if (definition) {\n definition.identifier = new Identifier(varName.name);\n return new VariableAssignment({\n variableIdentifier: varName,\n listDef: definition,\n });\n }\n\n return null;\n };\n\n public readonly ListDefinition = (): ListDefinition | null => {\n this.AnyWhitespace();\n\n const allElements = this.SeparatedList(\n this.ListElementDefinition,\n this.ListElementDefinitionSeparator\n ) as ListElementDefinition[];\n\n if (allElements === null) {\n return null;\n }\n\n return new ListDefinition(allElements);\n };\n\n public readonly ListElementDefinitionSeparator = (): string | null => {\n this.AnyWhitespace();\n\n if (this.ParseString(\",\") === null) {\n return null;\n }\n\n this.AnyWhitespace();\n\n return \",\";\n };\n\n public readonly ListElementDefinition = () => {\n const inInitialList = this.ParseString(\"(\") !== null;\n let needsToCloseParen = inInitialList;\n\n this.Whitespace();\n\n const name = this.Parse(this.IdentifierWithMetadata) as Identifier | null;\n if (name === null) {\n return null;\n }\n\n this.Whitespace();\n\n if (inInitialList) {\n if (this.ParseString(\")\") != null) {\n needsToCloseParen = false;\n this.Whitespace();\n }\n }\n\n let elementValue: number | null = null;\n if (this.ParseString(\"=\") !== null) {\n this.Whitespace();\n\n const elementValueNum = this.Expect(\n this.ExpressionInt,\n \"value to be assigned to list item\"\n ) as NumberExpression;\n\n if (elementValueNum !== null) {\n elementValue = elementValueNum.value as number;\n }\n\n if (needsToCloseParen) {\n this.Whitespace();\n\n if (this.ParseString(\")\") !== null) {\n needsToCloseParen = false;\n }\n }\n }\n\n if (needsToCloseParen) {\n this.Error(\"Expected closing ')'\");\n }\n\n return new ListElementDefinition(name, inInitialList, elementValue);\n };\n\n public readonly ConstDeclaration = (): ParsedObject | null => {\n this.Whitespace();\n\n const id = this.Parse(this.Identifier);\n if (id !== \"CONST\") {\n return null;\n }\n\n this.Whitespace();\n\n const varName = this.Expect(\n this.IdentifierWithMetadata,\n \"constant name\"\n ) as Identifier;\n\n this.Whitespace();\n\n this.Expect(\n this.String(\"=\"),\n \"the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)\"\n );\n\n this.Whitespace();\n\n const expr = this.Expect(\n this.Expression,\n \"initial value for \"\n ) as Expression;\n\n const check =\n expr instanceof NumberExpression ||\n expr instanceof DivertTarget ||\n expr instanceof StringExpression;\n\n if (!check) {\n this.Error(\n \"initial value for a constant must be a number or divert target\"\n );\n } else if (expr instanceof StringExpression) {\n // Ensure string expressions are simple\n const strExpr = expr as StringExpression;\n if (!strExpr.isSingleString) {\n this.Error(\"Constant strings cannot contain any logic.\");\n }\n }\n\n const result = new ConstantDeclaration(varName, expr);\n\n return result;\n };\n\n public readonly InlineLogicOrGlueOrStartTag = (): ParsedObject =>\n this.OneOf([this.InlineLogic, this.Glue, this.StartTag]) as ParsedObject;\n\n public readonly Glue = (): Glue | null => {\n // Don't want to parse whitespace, since it might be important\n // surrounding the glue.\n const glueStr = this.ParseString(\"<>\");\n if (glueStr !== null) {\n return new Glue(new RuntimeGlue());\n }\n\n return null;\n };\n\n public readonly InlineLogic = () => {\n if (this.ParseString(\"{\") === null) {\n return null;\n }\n\n let wasParsingString = this.parsingStringExpression;\n let wasTagActive = this.tagActive;\n\n this.Whitespace();\n\n const logic = this.Expect(\n this.InnerLogic,\n \"some kind of logic, conditional or sequence within braces: { ... }\"\n ) as ParsedObject;\n\n if (logic === null) {\n this.parsingStringExpression = wasParsingString;\n return null;\n }\n\n this.DisallowIncrement(logic);\n\n let contentList = asOrNull(logic, ContentList);\n if (!contentList) {\n contentList = new ContentList(logic as any);\n }\n\n this.Whitespace();\n\n this.Expect(this.String(\"}\"), \"closing brace '}' for inline logic\");\n\n // Allow nested strings and logic\n this.parsingStringExpression = wasParsingString;\n\n // Difference between:\n //\n // 1) A thing # {image}.jpg\n // 2) A {red #red|blue #blue} sequence.\n //\n // When logic ends in (1) we still want tag to continue.\n // When logic ends in (2) we want to auto-end the tag.\n // Side note: we simply disallow tags within strings.\n if (!wasTagActive) this.EndTagIfNecessary(contentList);\n\n return contentList;\n };\n\n public readonly InnerLogic = (): ParsedObject | null => {\n this.Whitespace();\n\n // Explicitly try the combinations of inner logic\n // that could potentially have conflicts first.\n\n // Explicit sequence annotation?\n const explicitSeqType: SequenceType = this.ParseObject(\n this.SequenceTypeAnnotation\n ) as SequenceType;\n\n if (explicitSeqType !== null) {\n const contentLists = this.Expect(\n this.InnerSequenceObjects,\n \"sequence elements (for cycle/stoping etc)\"\n ) as ContentList[];\n\n if (contentLists === null) {\n return null;\n }\n\n return new Sequence(contentLists, explicitSeqType);\n }\n\n // Conditional with expression?\n const initialQueryExpression = this.Parse(\n this.ConditionExpression\n ) as Expression;\n if (initialQueryExpression) {\n const conditional = this.Expect(\n () => this.InnerConditionalContent(initialQueryExpression),\n \"conditional content following query\"\n ) as Conditional;\n\n return conditional;\n }\n\n // Now try to evaluate each of the \"full\" rules in turn\n const rules: ParseRule[] = [\n // Conditional still necessary, since you can have a multi-line conditional\n // without an initial query expression:\n // {\n // - true: this is true\n // - false: this is false\n // }\n this.InnerConditionalContent as ParseRule,\n this.InnerSequence,\n this.InnerExpression,\n ];\n\n let wasTagActiveAtStartOfScope = this.tagActive;\n\n // Adapted from \"OneOf\" structuring rule except that in\n // order for the rule to succeed, it has to maximally\n // cover the entire string within the { }. Used to\n // differentiate between:\n // {myVar} -- Expression (try first)\n // {my content is jolly} -- sequence with single element\n for (const rule of rules) {\n const ruleId: number = this.BeginRule();\n\n const result: ParsedObject = this.ParseObject(rule) as ParsedObject;\n if (result) {\n // Not yet at end?\n if (this.Peek(this.Spaced(this.String(\"}\"))) === null) {\n this.FailRule(ruleId);\n } else {\n // Full parse of content within braces\n return this.SucceedRule(ruleId, result) as ParsedObject;\n }\n } else {\n this.FailRule(ruleId);\n }\n }\n\n return null;\n };\n\n public readonly InnerExpression = (): ParsedObject => {\n const expr = this.Parse(this.Expression) as Expression;\n if (expr) {\n expr.outputWhenComplete = true;\n }\n\n return expr;\n };\n\n public readonly IdentifierWithMetadata = (): Identifier | null => {\n const id = this.Identifier();\n if (id === null) {\n return null;\n }\n return new Identifier(id);\n };\n\n // Note: we allow identifiers that start with a number,\n // but not if they *only* comprise numbers\n public readonly Identifier = (): string | null => {\n // Parse remaining characters (if any)\n const name = this.ParseCharactersFromCharSet(this.identifierCharSet);\n if (name === null) {\n return null;\n }\n\n // Reject if it's just a number\n let isNumberCharsOnly: boolean = true;\n for (let c of name) {\n if (!(c >= \"0\" && c <= \"9\")) {\n isNumberCharsOnly = false;\n break;\n }\n }\n\n if (isNumberCharsOnly) {\n return null;\n }\n\n return name;\n };\n\n /**\n * End Logic section.\n */\n\n /**\n * Begin Sequences section.\n */\n\n public _sequenceTypeSymbols: CharacterSet = new CharacterSet(\"!&~$\");\n\n public readonly InnerSequence = (): Sequence | null => {\n this.Whitespace();\n\n // Default sequence type\n let seqType: SequenceType = SequenceType.Stopping;\n\n // Optional explicit sequence type\n const parsedSeqType: SequenceType = this.Parse(\n this.SequenceTypeAnnotation\n ) as SequenceType;\n\n if (parsedSeqType !== null) {\n seqType = parsedSeqType;\n }\n\n const contentLists = this.Parse(this.InnerSequenceObjects) as ContentList[];\n if (contentLists === null || contentLists.length <= 1) {\n return null;\n }\n\n return new Sequence(contentLists, seqType);\n };\n\n public readonly SequenceTypeAnnotation = (): ParseRuleReturn => {\n let annotation = this.Parse(\n this.SequenceTypeSymbolAnnotation\n ) as SequenceType;\n\n if (annotation === null) {\n annotation = this.Parse(this.SequenceTypeWordAnnotation) as SequenceType;\n }\n\n if (annotation === null) {\n return null;\n }\n\n switch (annotation) {\n case SequenceType.Once:\n case SequenceType.Cycle:\n case SequenceType.Stopping:\n case SequenceType.Shuffle:\n case SequenceType.Shuffle | SequenceType.Stopping:\n case SequenceType.Shuffle | SequenceType.Once:\n break;\n default:\n this.Error(`Sequence type combination not supported: ${annotation}`);\n return SequenceType.Stopping;\n }\n\n return annotation;\n };\n\n public readonly SequenceTypeSymbolAnnotation = (): ParseRuleReturn => {\n if (this._sequenceTypeSymbols === null) {\n this._sequenceTypeSymbols = new CharacterSet(\"!&~$ \");\n }\n\n let sequenceType = 0 as SequenceType;\n const sequenceAnnotations = this.ParseCharactersFromCharSet(\n this._sequenceTypeSymbols\n );\n\n if (sequenceAnnotations === null) {\n return null;\n }\n\n for (const symbolChar of sequenceAnnotations) {\n switch (symbolChar) {\n case \"!\":\n sequenceType |= SequenceType.Once;\n break;\n case \"&\":\n sequenceType |= SequenceType.Cycle;\n break;\n case \"~\":\n sequenceType |= SequenceType.Shuffle;\n break;\n case \"$\":\n sequenceType |= SequenceType.Stopping;\n break;\n }\n }\n\n if (sequenceType === (0 as SequenceType)) {\n return null;\n }\n\n return sequenceType;\n };\n\n public readonly SequenceTypeWordAnnotation = (): ParseRuleReturn => {\n const sequenceTypes = this.Interleave(\n this.SequenceTypeSingleWord,\n this.Exclude(this.Whitespace)\n );\n\n if (sequenceTypes === null || sequenceTypes.length === 0) {\n return null;\n }\n\n if (this.ParseString(\":\") === null) {\n return null;\n }\n\n let combinedSequenceType = 0 as SequenceType;\n for (const seqType of sequenceTypes) {\n combinedSequenceType |= seqType!;\n }\n\n return combinedSequenceType;\n };\n\n public readonly SequenceTypeSingleWord = () => {\n let seqType: SequenceType | null = null;\n\n const word = this.Parse(this.IdentifierWithMetadata) as Identifier | null;\n\n if (word !== null) {\n switch (word.name) {\n case \"once\":\n seqType = SequenceType.Once;\n break;\n case \"cycle\":\n seqType = SequenceType.Cycle;\n break;\n case \"shuffle\":\n seqType = SequenceType.Shuffle;\n break;\n case \"stopping\":\n seqType = SequenceType.Stopping;\n break;\n }\n }\n\n if (seqType === null) {\n return null;\n }\n\n return seqType;\n };\n\n public readonly InnerSequenceObjects = (): ContentList[] => {\n const multiline = this.Parse(this.Newline) !== null;\n\n let result: ContentList[] | null = null;\n if (multiline) {\n result = this.Parse(this.InnerMultilineSequenceObjects) as ContentList[];\n } else {\n result = this.Parse(this.InnerInlineSequenceObjects) as ContentList[];\n }\n\n return result;\n };\n\n public readonly InnerInlineSequenceObjects = (): ContentList[] | null => {\n const interleavedContentAndPipes = this.Interleave(\n this.Optional(this.MixedTextAndLogic),\n this.String(\"|\"),\n null,\n false\n );\n\n if (interleavedContentAndPipes === null) {\n return null;\n }\n\n const result = [];\n\n // The content and pipes won't necessarily be perfectly interleaved in the sense that\n // the content can be missing, but in that case it's intended that there's blank content.\n let justHadContent: boolean = false;\n for (const contentOrPipe of interleavedContentAndPipes) {\n // Pipe/separator\n if ((contentOrPipe as any) === \"|\") {\n // Expected content, saw pipe - need blank content now\n if (!justHadContent) {\n // Add blank content\n result.push(new ContentList());\n }\n\n justHadContent = false;\n } else {\n // Real content\n const content = contentOrPipe as any;\n if (content === null) {\n this.Error(\n `Expected content, but got ${contentOrPipe} (this is an ink compiler bug!)`\n );\n } else {\n result.push(new ContentList(content));\n }\n\n justHadContent = true;\n }\n }\n\n // Ended in a pipe? Need to insert final blank content\n if (!justHadContent) {\n result.push(new ContentList());\n }\n\n return result;\n };\n\n public readonly InnerMultilineSequenceObjects = (): ContentList[] | null => {\n this.MultilineWhitespace();\n\n const contentLists = this.OneOrMore(\n this.SingleMultilineSequenceElement\n ) as ContentList[];\n if (contentLists === null) {\n return null;\n }\n\n return contentLists;\n };\n\n public readonly SingleMultilineSequenceElement = () => {\n this.Whitespace();\n\n // Make sure we're not accidentally parsing a divert\n if (this.ParseString(\"->\") !== null) {\n return null;\n }\n\n if (this.ParseString(\"-\") === null) {\n return null;\n }\n\n this.Whitespace();\n\n const content: ParsedObject[] = this.StatementsAtLevel(\n StatementLevel.InnerBlock\n );\n\n if (content === null) {\n this.MultilineWhitespace();\n } else {\n // Add newline at the start of each branch\n content.unshift(new Text(\"\\n\"));\n }\n\n return new ContentList(content);\n };\n\n /**\n * End Sequences section.\n */\n\n /**\n * Begin Statements section.\n */\n\n private _statementRulesAtLevel: ParseRule[][] = [];\n private _statementBreakRulesAtLevel: ParseRule[][] = [];\n\n public readonly StatementsAtLevel = (\n level: StatementLevel\n ): ParsedObject[] => {\n // Check for error: Should not be allowed gather dashes within an inner block\n if (level === StatementLevel.InnerBlock) {\n const badGatherDashCount = this.Parse(this.GatherDashes) as ParsedObject;\n if (badGatherDashCount !== null) {\n this.Error(\n \"You can't use a gather (the dashes) within the { curly braces } context. For multi-line sequences and conditions, you should only use one dash.\"\n );\n }\n }\n\n return this.Interleave(\n this.Optional(this.MultilineWhitespace),\n () => this.StatementAtLevel(level),\n () => this.StatementsBreakForLevel(level)\n );\n };\n\n public readonly StatementAtLevel = (level: StatementLevel): ParsedObject => {\n const rulesAtLevel: ParseRule[] =\n this._statementRulesAtLevel[level as number];\n const statement = this.OneOf(rulesAtLevel) as ReturnType;\n\n // For some statements, allow them to parse, but create errors, since\n // writers may think they can use the statement, so it's useful to have\n // the error message.\n if (level === StatementLevel.Top) {\n if (statement instanceof ReturnType) {\n this.Error(\"should not have return statement outside of a knot\");\n }\n }\n\n return statement;\n };\n\n public readonly StatementsBreakForLevel = (\n level: StatementLevel\n ): ParseRuleReturn => {\n this.Whitespace();\n\n const breakRules: ParseRule[] =\n this._statementBreakRulesAtLevel[level as number];\n const breakRuleResult = this.OneOf(breakRules);\n if (breakRuleResult === null) {\n return null;\n }\n\n return breakRuleResult;\n };\n\n public readonly GenerateStatementLevelRules = () => {\n const levels = Object.values(StatementLevel);\n\n this._statementRulesAtLevel = \"f\"\n .repeat(levels.length)\n .split(\"f\")\n .map(() => []);\n\n this._statementBreakRulesAtLevel = \"f\"\n .repeat(levels.length)\n .split(\"f\")\n .map(() => []);\n\n for (const level of levels) {\n const rulesAtLevel: ParseRule[] = [];\n const breakingRules: ParseRule[] = [];\n\n // Diverts can go anywhere\n rulesAtLevel.push(this.Line(this.MultiDivert));\n\n // Knots can only be parsed at Top/Global scope\n if (level >= StatementLevel.Top) {\n rulesAtLevel.push(this.KnotDefinition);\n }\n\n rulesAtLevel.push(this.Line(this.Choice));\n\n rulesAtLevel.push(this.Line(this.AuthorWarning));\n\n // Gather lines would be confused with multi-line block separators, like\n // within a multi-line if statement\n if (level > StatementLevel.InnerBlock) {\n rulesAtLevel.push(this.Gather);\n }\n\n // Stitches (and gathers) can (currently) only go in Knots and top level\n if (level >= StatementLevel.Knot) {\n rulesAtLevel.push(this.StitchDefinition);\n }\n\n // Global variable declarations can go anywhere\n rulesAtLevel.push(this.Line(this.ListDeclaration));\n rulesAtLevel.push(this.Line(this.VariableDeclaration));\n rulesAtLevel.push(this.Line(this.ConstDeclaration));\n rulesAtLevel.push(this.Line(this.ExternalDeclaration));\n\n // Global include can go anywhere\n rulesAtLevel.push(this.Line(this.IncludeStatement));\n\n // Normal logic / text can go anywhere\n rulesAtLevel.push(this.LogicLine);\n rulesAtLevel.push(this.LineOfMixedTextAndLogic);\n\n // --------\n // Breaking rules\n\n // Break current knot with a new knot\n if (level <= StatementLevel.Knot) {\n breakingRules.push(this.KnotDeclaration);\n }\n\n // Break current stitch with a new stitch\n if (level <= StatementLevel.Stitch) {\n breakingRules.push(this.StitchDeclaration);\n }\n\n // Breaking an inner block (like a multi-line condition statement)\n if (level <= StatementLevel.InnerBlock) {\n breakingRules.push(this.ParseDashNotArrow);\n breakingRules.push(this.String(\"}\"));\n }\n\n this._statementRulesAtLevel[level as number] = rulesAtLevel;\n this._statementBreakRulesAtLevel[level as number] = breakingRules;\n }\n };\n\n public readonly SkipToNextLine = (): typeof ParseSuccess => {\n this.ParseUntilCharactersFromString(\"\\n\\r\");\n this.ParseNewline();\n\n return ParseSuccess;\n };\n\n // Modifier to turn a rule into one that expects a newline on the end.\n // e.g. anywhere you can use \"MixedTextAndLogic\" as a rule, you can use\n // \"Line(MixedTextAndLogic)\" to specify that it expects a newline afterwards.\n public readonly Line =\n (inlineRule: ParseRule): ParseRule =>\n () => {\n const result = this.ParseObject(inlineRule);\n if (result === null) {\n return null;\n }\n\n this.Expect(this.EndOfLine, \"end of line\", this.SkipToNextLine);\n\n return result;\n };\n\n /**\n * End Statements section.\n */\n\n /**\n * Begin Tags section.\n */\n\n public readonly StartTag = (): ParsedObject | null => {\n this.Whitespace();\n\n if (this.ParseString(\"#\") === null) {\n return null;\n }\n\n if (this.parsingStringExpression) {\n this.Error(\n \"Tags aren't allowed inside of strings. Please use \\\\# if you want a hash symbol.\"\n );\n }\n\n let result: ParsedObject | null = null;\n if (this.tagActive) {\n let contentList = new ContentList();\n contentList.AddContent(new Tag(/*isStart:*/ false));\n contentList.AddContent(new Tag(/*isStart:*/ true));\n result = contentList;\n } else {\n result = new Tag(/*isStart:*/ true);\n }\n this.tagActive = true;\n\n this.Whitespace();\n\n return result;\n };\n\n public EndTagIfNecessary(outputContentList: ParsedObject[] | null): void;\n public EndTagIfNecessary(outputContentList: ContentList | null): void;\n public EndTagIfNecessary(\n outputContentList: ParsedObject[] | ContentList | null\n ): void {\n if (this.tagActive) {\n if (outputContentList != null) {\n if (outputContentList instanceof ContentList) {\n outputContentList.AddContent(new Tag(/*isStart:*/ false));\n } else {\n outputContentList.push(new Tag(/*isStart:*/ false));\n }\n }\n this.tagActive = false;\n }\n }\n\n /**\n * End Tags section.\n */\n\n /**\n * Begin Whitespace section.\n */\n\n private _inlineWhitespaceChars: CharacterSet = new CharacterSet(\" \\t\");\n\n // Handles both newline and endOfFile\n public readonly EndOfLine = () => this.OneOf([this.Newline, this.EndOfFile]);\n\n // Allow whitespace before the actual newline\n public readonly Newline = (): typeof ParseSuccess | null => {\n this.Whitespace();\n\n const gotNewline: boolean = this.ParseNewline() !== null;\n\n // Optional \\r, definite \\n to support Windows (\\r\\n) and Mac/Unix (\\n)\n\n if (!gotNewline) {\n return null;\n }\n\n return ParseSuccess;\n };\n\n public readonly EndOfFile = (): typeof ParseSuccess | null => {\n this.Whitespace();\n\n if (!this.endOfInput) return null;\n\n return ParseSuccess;\n };\n\n // General purpose space, returns N-count newlines (fails if no newlines)\n public readonly MultilineWhitespace = (): typeof ParseSuccess | null => {\n let newlines: ParseRuleReturn[] | null = this.OneOrMore(this.Newline);\n if (newlines === null) {\n return null;\n }\n\n // Use content field of Token to say how many newlines there were\n // (in most circumstances it's unimportant)\n const numNewlines: number = newlines.length;\n if (numNewlines >= 1) {\n return ParseSuccess;\n }\n\n return null;\n };\n\n public readonly Whitespace = (): typeof ParseSuccess | null => {\n const doneParsed = this.ParseCharactersFromCharSet(\n this._inlineWhitespaceChars\n );\n\n if (doneParsed !== null) {\n return ParseSuccess;\n }\n\n return null;\n };\n\n public readonly Spaced =\n (rule: ParseRule): ParseRule =>\n () => {\n this.Whitespace();\n\n const result = this.ParseObject(rule);\n if (result === null) {\n return null;\n }\n\n this.Whitespace();\n\n return result;\n };\n\n public readonly AnyWhitespace = (): typeof ParseSuccess | null => {\n let anyWhitespace: boolean = false;\n\n while (this.OneOf([this.Whitespace, this.MultilineWhitespace]) !== null) {\n anyWhitespace = true;\n }\n\n return anyWhitespace ? ParseSuccess : null;\n };\n\n public readonly MultiSpaced =\n (rule: ParseRule): ParseRuleReturn =>\n () => {\n this.AnyWhitespace();\n\n const result = this.ParseObject(rule);\n if (result === null) {\n return null;\n }\n\n this.AnyWhitespace();\n\n return result;\n };\n\n private _filename: string | null = null;\n private _externalErrorHandler: ErrorHandler | null = null;\n private _fileHandler: IFileHandler | null = null;\n\n /**\n * End Whitespace section.\n */\n}\n","import { IFileHandler } from \"../IFileHandler\";\n\nexport class JsonFileHandler implements IFileHandler {\n constructor(public readonly fileHierarchy: Record) {}\n\n readonly ResolveInkFilename = (filename: string): string => {\n if (Object.keys(this.fileHierarchy).includes(filename)) return filename;\n throw new Error(\n `Cannot locate ${filename}. Are you trying a relative import ? This is not yet implemented.`\n );\n };\n\n readonly LoadInkFileContents = (filename: string): string => {\n if (Object.keys(this.fileHierarchy).includes(filename)) {\n return this.fileHierarchy[filename];\n } else {\n throw new Error(`Cannot open ${filename}.`);\n }\n };\n}\n","import { CompilerOptions } from \"./CompilerOptions\";\nimport { DebugSourceRange } from \"./DebugSourceRange\";\nimport { ErrorType } from \"./Parser/ErrorType\";\nimport { InkParser } from \"./Parser/InkParser\";\nimport { Story } from \"../engine/Story\";\nimport { Story as ParsedStory } from \"./Parser/ParsedHierarchy/Story\";\nimport { DebugMetadata } from \"../engine/DebugMetadata\";\nimport { StringValue } from \"../engine/Value\";\nimport { asOrNull } from \"../engine/TypeAssertion\";\n\nexport { CompilerOptions } from \"./CompilerOptions\";\nexport { JsonFileHandler } from \"./FileHandler/JsonFileHandler\";\nexport { InkList, Story } from \"../engine/Story\";\n\nexport class Compiler {\n private _errors: string[] = [];\n get errors(): string[] {\n return this._errors;\n }\n\n private _warnings: string[] = [];\n get warnings(): string[] {\n return this._warnings;\n }\n\n private _authorMessages: string[] = [];\n get authorMessages(): string[] {\n return this._authorMessages;\n }\n\n private _inputString: string;\n get inputString(): string {\n return this._inputString;\n }\n\n private _options: CompilerOptions;\n get options(): CompilerOptions {\n return this._options;\n }\n\n private _parsedStory: ParsedStory | null = null;\n get parsedStory(): ParsedStory {\n if (!this._parsedStory) {\n throw new Error();\n }\n\n return this._parsedStory;\n }\n\n private _runtimeStory: Story | null = null;\n get runtimeStory(): Story {\n if (!this._runtimeStory) {\n throw new Error(\"Compilation failed.\");\n }\n\n return this._runtimeStory;\n }\n\n private _parser: InkParser | null = null;\n get parser(): InkParser {\n if (!this._parser) {\n throw new Error();\n }\n\n return this._parser;\n }\n\n private _debugSourceRanges: DebugSourceRange[] = [];\n get debugSourceRanges(): DebugSourceRange[] {\n return this._debugSourceRanges;\n }\n\n constructor(inkSource: string, options: CompilerOptions | null = null) {\n this._inputString = inkSource;\n this._options = options || new CompilerOptions();\n }\n\n public readonly Compile = (): Story => {\n this._parser = new InkParser(\n this.inputString,\n this.options.sourceFilename || null,\n this.OnError,\n null,\n this.options.fileHandler\n );\n\n this._parsedStory = this.parser.ParseStory();\n\n if (this.errors.length === 0) {\n this.parsedStory.countAllVisits = this.options.countAllVisits;\n this._runtimeStory = this.parsedStory.ExportRuntime(this.OnError);\n } else {\n this._runtimeStory = null;\n }\n\n return this.runtimeStory;\n };\n\n public readonly RetrieveDebugSourceForLatestContent = (): void => {\n for (const outputObj of this.runtimeStory.state.outputStream) {\n const textContent = asOrNull(outputObj, StringValue);\n if (textContent !== null) {\n const range = new DebugSourceRange(\n textContent.value?.length || 0,\n textContent.debugMetadata,\n textContent.value || \"unknown\"\n );\n\n this.debugSourceRanges.push(range);\n }\n }\n };\n\n public readonly DebugMetadataForContentAtOffset = (\n offset: number\n ): DebugMetadata | null => {\n let currOffset = 0;\n\n let lastValidMetadata: DebugMetadata | null = null;\n for (const range of this.debugSourceRanges) {\n if (range.debugMetadata !== null) {\n lastValidMetadata = range.debugMetadata;\n }\n\n if (offset >= currOffset && offset < currOffset + range.length) {\n return lastValidMetadata;\n }\n\n currOffset += range.length;\n }\n\n return null;\n };\n\n public readonly OnError = (message: string, errorType: ErrorType) => {\n switch (errorType) {\n case ErrorType.Author:\n this._authorMessages.push(message);\n break;\n\n case ErrorType.Warning:\n this._warnings.push(message);\n break;\n\n case ErrorType.Error:\n this._errors.push(message);\n break;\n }\n\n if (this.options.errorHandler !== null) {\n this.options.errorHandler(message, errorType);\n }\n };\n}\n"],"names":["CompilerOptions","ErrorType","sourceFilename","pluginNames","countAllVisits","errorHandler","fileHandler","_classCallCheck","this","DebugSourceRange","length","debugMetadata","text","Argument","identifier","isByReference","isDivertTarget","asOrNull","obj","type","unsafeTypeAssertion","asOrThrows","Error","concat","asINamedContentOrNull","hasValidName","name","nullIfUndefined","isEquatable","_typeof","Equals","filterUndef","element","undefined","Debug","ParsedObject","_this","_alreadyHadError","_alreadyHadWarning","_debugMetadata","_runtimeObject","content","parent","GetType","typeName","AddContent","subContent","_step","_iterator","_createForOfIteratorHelper","Array","isArray","s","n","done","ss","value","hasOwnProperty","push","err","e","f","InsertContent","index","splice","Find","queryFunc","tObj","_step2","_iterator2","nestedResult","FindAll","foundSoFar","found","_step3","_iterator3","Warning","message","source","_createClass","key","get","set","Boolean","ancestor","GenerateRuntimeObject","runtimeObject","path","result","reverse","context","_step4","_iterator4","ResolveReferences","_Error","_x","apply","arguments","toString","isWarning","AuthorWarning","_ParsedObject","_inherits","_super","_createSuper","warningMessage","call","Path","_components","_componentsString","_isRelative","componentsString","Component","head","tail","relative","slice","self","lastComponentIdx","i","l","isIndex","pathToAppend","p","upwardMoves","isParent","join","isRelative","substring","split","str","test","parseInt","otherPath","c","_p$_components","_toConsumableArray","parentId","indexOrName","otherComp","Assert","condition","console","warn","trace","AssertType","variable","NullException","_wrapNativeSuper","throwNullException","InkObject","_path","root","rootContentContainer","targetContent","ContentAtPath","dm","startLineNumber","comps","child","container","Container","namedChild","unshift","indexOf","nearestContainer","GetComponent","contentContainer","globalPath","ownPath","minPathLength","Math","min","lastSharedPathCompIndex","ownComp","numUpwardsMoves","componentCount","newPathComps","up","ToParent","down","globalPathStr","relativePathStr","PathByAppendingPath","ConvertPathToRelative","prop","StringBuilder","string","Append","format","_len","args","_key","replace","match","num","InkListItem","originName","itemName","fullName","nameParts","otherItem","JSON","stringify","parse","isLikeInkListItem","Null","inkListItem","item","InkList","_Map","_arguments","origins","_originNames","otherList","otherOriginNames","originNames","singleOriginListName","originStory","SetInitialOriginName","listDefinitions","def","TryListGetDefinition","exists","singleElement","Add","Key","Value","itemOrItemName","AddItem","origin","intVal","TryGetValueForItem","foundListDef","ContainsItemWithName","itemVal","ValueForItem","_slicedToArray","fromSerializedKey","has","serialized","serializedKey","delete","size","maxOriginName","maxItem","every","Count","initialOriginName","initialOriginNames","_step5","max","_iterator5","_step5$value","isNull","_step6","_iterator6","_step6$value","list","_step7","_iterator7","_step8","items","_iterator8","_step8$value","ContainsKey","_step9","_iterator9","_step10","_iterator10","_step10$value","_step11","union","_iterator11","_step11$value","_step12","intersection","_iterator12","_step12$value","_step13","_iterator13","listToRemove","_step14","_iterator14","what","ContainsItemNamed","_step15","_iterator15","minItem","minBound","maxBound","ordered","orderedItems","minValue","maxValue","Number","MAX_SAFE_INTEGER","isInteger","subList","SetInitialOriginNames","_step16","_iterator16","otherInkList","_step17","_iterator17","_step18","_iterator18","_step18$value","sort","x","y","localeCompare","sb","NaN","myListItem","listValue","_a","FindSingleItemListWithName","Map","StoryException","useEndLineNumber","tryGetValueFromMap","map","val","ValueType","_AbstractValue","_super2","_InkObject","AbstractValue","Create","valueObject","targetType","valueType","preferredNumberType","Int","IntValue","Float","isNaN","FloatValue","BoolValue","StringValue","String","DivertTargetValue","ListValue","_Value","_super3","Bool","newType","BadCastException","_Value2","_super4","_Value3","_super5","_Value4","_super6","_this2","_isNewline","_isInlineWhitespace","isNewline","isInlineWhitespace","parsedInt","defaultValue","tryParseInt","parsedFloat","parseFloat","tryParseFloat","_Value5","_super7","targetPath","DivertTarget","VariablePointerValue","_Value6","_super8","variableName","_this3","contextIndex","_contextIndex","VariablePointer","_Value7","_super9","listOrSingleItem","singleValue","_this4","List","oldValue","newValue","oldList","newList","SearchResult","approximate","searchResult","_content","namedContent","visitsShouldBeCounted","turnIndexShouldBeCounted","countingAtStartOnly","_pathToFirstLeafContent","namedOnlyContentDict","_step$value","inkObject","named","existingNamedOnly","namedOnlyContent","AddToNamedContentOnly","flags","CountFlags","Visits","Turns","CountStartOnly","flag","internalPathToFirstLeafContent","components","contentObjOrList","contentObj","TryAddNamedContent","namedContentObj","partialPathStart","partialPathLength","currentContainer","currentObj","comp","foundObj","ContentWithPathComponent","otherContainer","_this$content","component","foundContent","BuildStringOfHierarchy","indentation","pointedObj","appendIndentation","AppendFormat","AppendLine","onlyNamed","_step7$value","ControlCommand","commandType","CommandType","NotSet","_commandType","EvalStart","EvalOutput","EvalEnd","Duplicate","PopEvaluatedValue","PopFunction","PopTunnel","BeginString","EndString","NoOp","ChoiceCount","TurnsSince","ReadCount","Random","SeedRandom","VisitIndex","SequenceShuffleIndex","StartThread","Done","End","ListFromInt","ListRange","ListRandom","BeginTag","EndTag","Expression","_prototypeRuntimeConstantExpression","outputWhenComplete","RuntimeContainer","RuntimeControlCommand","GenerateIntoContainer","GenerateConstantIntoContainer","copy","Copy","Void","NativeFunctionCall","_name","_numberOfParameters","_prototype","_isPrototype","_operationFuncs","GenerateNativeFunctionsIfNecessary","numberOfParameters","_nativeFunctions","parameters","Call","hasList","CallBinaryListOperation","coercedParams","CoerceValuesToSingleType","coercedType","CallType","parametersOfSingleType","param1","valType","val1","paramCount","opForTypeObj","val2","opForType","resultVal","CallListIncrementOperation","v1","v2","op","asBooleanOrThrows","isTruthy","listIntParams","listVal","resultInkList","_step2$value","listItemKey","listItemValue","listItem","intOp","targetInt","itemOrigin","incrementedItem","TryGetItemWithValue","parametersIn","specialCaseList","parametersOut","originOfMaxItem","castedValue","Cast","functionName","t","AddIntBinaryOp","Subtract","Multiply","Divide","floor","Mod","AddIntUnaryOp","Negate","Equal","Greater","Less","GreaterThanOrEquals","LessThanOrEquals","NotEquals","Not","And","Or","Max","Min","Pow","pow","Floor","Identity","Ceiling","AddFloatBinaryOp","AddFloatUnaryOp","ceil","AddStringBinaryOp","Has","includes","Hasnt","AddListBinaryOp","Union","Without","Contains","Intersect","GreaterThan","LessThan","AddListUnaryOp","Invert","inverse","All","all","ListMin","MinAsList","ListMax","MaxAsList","ValueOfList","AddOpToNativeFunc","d1","d2","nativeFunc","AddOpFuncForType","NumberExpression","_Expression","subtype","isInt","isFloat","isBool","numberExpression","UnaryExpression","inner","innerExpression","CallWithName","nativeNameForOp","WithInner","innerNumber","BinaryExpression","left","right","opName","leftExpression","rightExpression","NativeNameForOp","_get","leftUnary","CharacterSet","arg","Set","add","AddRange","start","end","charCodeAt","fromCharCode","AddCharacters","chars","FromRange","CharacterRange","_start","_end","excludes","_correspondingCharSet","_excludes","ToCharacterSet","ii","Define","PushPopType","ChoicePoint","onceOnly","_pathOnChoice","hasCondition","hasStartContent","hasChoiceOnlyContent","isInvisibleDefault","choiceTargetObj","choiceTarget","ResolvePath","pathOnChoice","CompactPathString","SymbolType","Pointer","PathByAppendingComponent","Divert","stackPushType","_targetPath","_targetPointer","variableDivertName","pushesToStack","isExternal","externalArgs","isConditional","targetObj","targetPointer","Resolve","lastComponent","StartOf","otherDivert","hasVariableTarget","targetStr","Function","targetPathString","VariableAssignment","isNewDeclaration","isGlobal","Choice","startContent","choiceOnlyContent","innerContent","_condition","_innerContentContainer","_outerContainer","_runtimeChoice","_returnToR1","_returnToR2","_r1Label","_r2Label","_divertToStartContentOuter","_divertToStartContentInner","_startContentRuntimeContainer","hasWeaveStyleInlineBrackets","varAssign","RuntimeVariableAssignment","RuntimeDivert","varDivert","choiceOnlyRuntimeContent","AddContentsOfContainer","innerChoiceOnlyContent","story","indentationDepth","innerContentContainer","runtimeChoice","_getPrototypeOf","prototype","CheckForNamingCollisions","SubFlowAndWeave","StringParserElement","characterIndex","characterInLineIndex","lineIndex","reportedErrorInScope","uniqueId","customFlags","CopyFrom","fromElement","_uniqueIdCounter","SquashFrom","StringParserState","_stack","_numElements","Push","prevElement","newElement","Pop","expectedRuleId","currentElement","Peek","PeekPenultimate","Squash","penultimateEl","lastEl","NoteErrorReported","ParseSuccess","Symbol","StringParser","ParseRule","hadError","BeginRule","state","FailRule","CancelRule","SucceedRule","stateAtSucceedRule","stateAtBeginRule","RuleDidSucceed","finalResult","Expect","rule","recoveryRule","ParseObject","butSaw","lineRemainder","LineRemainder","ErrorOnLine","ErrorWithParsedObject","lineNumber","errorReportedAlreadyInScope","errorType","ParseUntilCharactersFromString","SetFlag","trueOrFalse","GetFlag","ruleId","stackHeightBefore","stackHeight","Parse","OneOf","array","OneOrMore","results","Optional","Exclude","OptionalExclude","ParseString","TryAddResultToList","flatten","resultCollection","Interleave","ruleA","ruleB","untilTerminator","firstA","lastMainResult","outerResult","remainingLength","cli","li","success","tempIdx","_chars","ParseSingleCharacter","maxCount","ParseCharactersFromString","ParseUntilCharactersFromCharSet","charSet","ParseCharactersFromCharSet","maxCountOrShouldIncludeStrChars","shouldIncludeChars","startIndex","count","lastCharIndex","ParseInt","oldIndex","oldCharacterInLineIndex","negative","parsedString","numbersCharacterSet","MIN_SAFE_INTEGER","ParseFloat","leadingInt","afterDecimalPointStr","ParseNewline","strPreProc","PreProcessInputString","inputString","stopRule","pauseCharacters","endCharacters","pauseAndEnd","values","partialParsedString","endOfInput","pauseCharacter","currentCharacter","FlowLevel","CommentEliminator","_StringParser","_commentOrNewlineStartCharacter","_commentBlockEndCharacter","_newlineCharacters","Process","stringList","CommentsAndNewlines","MainInk","ParseUntil","newLines","ParseSingleComment","EndOfLineComment","BlockComment","startLineIndex","commentResult","repeat","Conditional","initialCondition","branches","_reJoinTarget","branchContainer","ownExpression","isElse","pathToReJoin","branch","returnDivert","Text","ConstantDeclaration","assignedExpression","_expression","constantIdentifier","Var","Gather","_b","argOne","argTwo","_dotSeparatedComponents","baseTargetLevel","WeavePoint","dotSeparatedComponents","ResolveFromContext","baseTargetObject","ResolveBaseTarget","ResolveTailComponents","originalContext","firstComp","firstComponent","ancestorContext","deepSearch","foundBase","GetChildFromContext","rootTarget","foundComponent","compName","minimumExpectedLevel","foundFlow","FlowBase","flowLevel","childName","minimumLevel","forceDeepSearch","ambiguousChildLevel","weaveContext","Weave","WeavePointNamed","flowContext","shouldDeepSearch","Knot","ContentWithNameAtLevel","Object","_baseTargetLevel","baseLevelIsAmbiguous","Story","filter","ReturnType","returnedExpression","ClosestFlowBase","iamFlowbase","Identifier","topLevelObjects","isFunction","isIncludedStory","_rootWeave","_subFlowsByName","_startingSubFlowDivert","_startingSubFlowRuntime","_firstChildFlow","variableDeclarations","SplitWeaveAndSubFlowContent","contentObjs","isRootStory","weaveObjs","subFlowObjs","subFlow","finalContent","ResolveVariableWithName","varName","fromNode","ownerFlow","isArgument","isTemporary","AddNewVariableDeclaration","varDecl","varab","prevDeclError","ResolveWeavePointNaming","foundReturn","CheckForDisallowedFunctionFlowControl","Stitch","GenerateArgumentVariableAssignments","contentIdx","childFlow","childFlowRuntime","hasParameters","existingChild","errorMsg","ValidateTermination","WarningInTermination","paramName","assign","level","_assertThisInitialized","weavePointResult","DeepSearchForAnyLevelContent","weaveResultSelf","deepResult","divert","isFunctionCall","choice","terminatingObject","terminatingDivert","isTunnel","target","PreProcessTopLevelObjects","_","Arg","jj","symbolType","ContentList","objects","dontFlatten","TrimTrailingWhitespace","RegExp","contentObjRuntime","DontFlattenContainer","moreObjects","VariableReference","pathForCount","pathStringForCount","pathIdentifiers","_runtimeVarRef","isConstantReference","isListItemReference","constantValue","constants","RuntimeVariableReference","listItemName","listName","ResolveListItem","id","parsedPath","targetForCount","containerForCounting","runtimePath","targetFlow","FunctionCall","_divertTargetToCount","_variableReferenceToCount","shouldPopReturnedValue","foundList","ResolveList","usingProxyDivert","isChoiceCount","isTurns","isTurnsSince","isReadCount","divertTarget","variableDivertTarget","isRandom","isSeedRandom","isListRange","isListRandom","CallExistsWithName","nativeCall","msg","RuntimeInkList","_proxyDivert","strArgs","runtimeDivert","attemptingTurnCountOfVariableTarget","targetObject","runtimeVarRef","IsBuiltIn","SequenceType","MultipleConditionExpression","conditionExpressions","isFirst","subExpressions","_runtimeDivert","_runtimeDivertTargetValue","runtimeDivertTargetValue","otherDivTarget","isDone","isEnd","usageContext","badUsage","foundUsage","usageParent","binaryExprParent","funcCall","ConditionalSingleBranch","parentFunc","isEmpty","isThread","ResolveTargetContent","CheckArgumentValidity","requiresArgCodeGen","targetArguments","argToPass","argExpected","varRef","varPointer","Tunnel","PathAsVariableName","variableTargetName","flowBaseScope","resolveResult","argument","find","a","numArgs","butClause","flowArg","divArgExpr","knotCountPath","CheckExternalArgumentValidity","externalName","external","externals","externalArgCount","argumentNames","ownArgCount","returnString","targetWasFound","isBuiltIn","numberOfComponents","IsExternal","RuntimePath","GatherPointToResolve","targetRuntimeObj","SequenceDivertToResolve","CustomFlags","Sequence","elementContentLists","sequenceType","_sequenceDivertsToResolve","once","Once","cycle","Cycle","stopping","Stopping","shuffle","Shuffle","seqBranchCount","sequenceElements","postShuffleNoOp","lastIdx","skipShuffleDivert","AddDivertToResolve","elementCountToShuffle","postSequenceNoOp","elIndex","sequenceDivert","contentContainerForSequenceBranch","seqBranchCompleteDivert","elementContentList","seqElObject","toResolve","TunnelOnwards","_overrideDivertTarget","_divertAfter","divertAfter","returnRuntimeObj","returnRuntimeContainer","evalStart","evalEnd","cmd","returnDivertObj","ListDefinition","_items","_itemNameToValues","itemDefinitions","variableAssignment","_elementsByName","ItemNamed","el","initialValues","itemDef","inInitialList","RuntimeInkListItem","seriesValue","currentValue","explicitValue","allItems","RuntimeListDefinition","_ref","isGlobalDeclaration","isTemporaryNewDeclaration","listDef","variableIdentifier","_runtimeAssignment","expression","listDefinition","newDeclScope","isNewTemporaryDeclaration","isDeclaration","Temp","variableReference","resolvedVarAssignment","cont","indentIndex","previousWeavePoint","addContentToPreviousWeavePoint","hasSeenChoiceInSection","_unnamedGatherCount","_choiceCount","_rootContainer","_namedWeavePoints","looseEnds","gatherPointsToResolve","namedWeavePoints","w","weavePoint","existingWeavePoint","existingObj","_c","ConstructWeaveHierarchyFromIndentation","weaveIndentIdx","baseIndentIndex","innerWeaveStartIdx","innerWeaveObj","weaveContentCount","weaveContent","weave","DetermineBaseIndentationFromContent","contentList","AddRuntimeForWeavePoint","_this$gatherPointsToR","AddRuntimeForNestedWeave","AddGeneralRuntimeContent","PassLooseEndsToAncestors","AddRuntimeForGather","gather","autoEnter","gatherContainer","runtimeContainer","rootContainer","looseEnd","looseWeavePoint","WeavePointHasLooseEnd","closestInnerWeaveAncestor","closestOuterWeaveAncestor","nested","weaveAncestor","received","ReceiveLooseEnd","receivingWeave","childWeaveLooseEnd","IsGlobalDeclaration","varAss","ContentThatFollowsWeavePoint","returned","parentWeave","laterObj","badTerminationHandler","lastParsedSignificantObject","looseEndFlow","ValidateFlowOfObjectsTerminates","BadNestedTerminationHandler","terminatingObj","conditional","toLowerCase","objFlow","defaultObj","terminated","flowObj","d","innerDivert","CheckForWeavePointNamingCollisions","ancestorFlows","ancestry","flow","weavePointName","otherContentWithName","lastObject","lastText","lastWeave","isNestedWeave","gatherPoint","_contentContainer","_conditionalDivert","_ownExpression","_innerWeave","isTrueBranch","matchingEquality","isInline","startsWith","duplicatesStackValue","needsEval","GenerateRuntimeForContent","StatementLevel","DebugMetadata","endLineNumber","startCharacterNumber","endCharacterNumber","fileName","sourceName","newDebugMetadata","ExternalDeclaration","AddExternal","FlowDecl","Glue","_Wrap","glue","Wrap","_objToWrap","IncDecExpression","varIdentifier","isIncOrExpression","isInc","varResolveResult","incrementDecrementWord","IncludedFile","includedStory","InfixOperator","precedence","requireWhitespace","_FlowBase","parentStory","stitchName","subFlowsByName","knotWithStitchName","stitch","itemIdentifierList","runtimeRawList","itemIdentifier","ListElementDefinition","indentifier","_thisSuper","parentList","ListItem","Tag","tagText","threadAtGeneration","sourcePath","tags","originalThreadIndex","ListDefinitionsOrigin","lists","_lists","_allUnambiguousListValueCache","listOfLists","definition","JsonSerialisation","jArray","skipLast","jTok","runtimeObj","JTokenToRuntimeObject","writer","dictionary","WriteObjectStart","WritePropertyStart","WriteRuntimeObject","WritePropertyEnd","WriteObjectEnd","WriteArrayStart","WriteArrayEnd","dict","_step3$value","WriteIntProperty","WriteRuntimeContainer","divTypeKey","WriteProperty","choicePoint","pathStringOnChoice","boolVal","WriteBool","WriteInt","floatVal","WriteFloat","strVal","Write","WriteStringStart","WriteStringInner","WriteStringEnd","WriteInkList","divTargetVal","varPtrVal","controlCmd","_controlCommandNames","readCountPath","tag","WriteChoice","jObject","token","firstChar","propValue","varPtr","isDivert","divPushType","readCountVarRef","isVarAss","isGlobalVar","isNewDecl","listContent","rawList","namesAsObjs","nameToVal","JObjectToChoice","JArrayToContainer","toJson","me","removes","space","k","v","some","r","withoutName","countFlags","hasNameProperty","hasTerminator","namedContainer","WriteNull","JArrayToRuntimeObjList","namedContentItem","namedSubContainer","jObj","WritePropertyNameStart","WritePropertyNameInner","WritePropertyNameEnd","listDefJson","_step9$value","defsObj","allDefs","nameValueKey","nameValue","TOTAL_VALUES","CallStack","_threadCounter","_startOfRoot","storyContext","Reset","toCopy","_threads","otherThread","callStack","elements","cs","callstack","Thread","Element","jThreadObj","thread","WriteObject","WriteJson","newThread","currentThread","threadIndex","forkedThread","canPopThread","elementIsEvaluateFromGame","FunctionEvaluationFromGame","externalEvaluationStackHeight","outputStreamLengthWithPushed","currentPointer","evaluationStackHeightWhenPushed","functionStartInOutputStream","canPop","CanPop","pop","currentElementIndex","contextElement","varValue","temporaryVariables","declareNew","RetainListOriginsForAssignment","filtered","isCurrent","pointer","inExpressionEvaluation","previousPointer","jThreadCallstack","jElTok","jElementObj","pushPopType","currentContainerPathStr","currentContainerPathStrToken","threadPointerResult","temps","JObjectToDictionaryRuntimeObjs","clear","prevContentObjPath","prevPath","PointerAtPath","WriteDictionaryRuntimeObjs","resolvedPointer","VariablesState","_VariablesStateAccess","listDefsOrigin","variableChangedEventCallbacks","patch","_batchObservingVariableChanges","_defaultGlobalVariables","_changedVariablesForBatchObs","_globalVariables","_callStack","_listDefsOrigin","_possibleConstructorReturn","Proxy","$","callback","variableChangedEvent","varContents","TryGetGlobal","SetGlobal","globals","namedVarKey","namedVarValue","changedVariables","jToken","varValKey","varValValue","loadedToken","tokenInkObject","keyValKey","keyValValue","dontSaveDefaultValues","defaultVal","RuntimeObjectsEqual","obj1","obj2","constructor","GetRawVariableWithName","ValueAtVariablePointer","variableValue","GetTemporaryVariableWithName","GetVariableWithName","setGlobal","GlobalVariableExistsWithName","ResolveVariablePointer","existingPointer","SetTemporaryVariable","batchObservingVariableChanges","AddChangedVariable","GetContextIndexOfVariableNamed","doubleRedirectionPointer","_class","PRNG","seed","next","StatePatch","_changedVariables","_visitCounts","_turnIndices","_globals","SimpleJson","Reader","ToDictionary","ToArray","_rootObject","Writer","_currentPropertyName","_currentString","_stateStack","_collectionStack","_propertyNameStack","_jsonObject","StartNewObject","newObject","State","Property","currentCollection","currentPropertyName","propertyName","None","StateElement","innerOrContent","IncrementChildCount","childCount","PropertyName","_addToCurrentObject","error","POSITIVE_INFINITY","NEGATIVE_INFINITY","currEl","Flow","SetJsonToken","outputStream","currentChoices","jChoiceThreadsObj","LoadFlowChoiceThreads","WriteListRuntimeObjs","hasChoiceThreads","ThreadWithIndex","jChoiceThreads","foundActiveThread","jSavedChoiceThread","StoryState","kInkSaveStateVersion","kMinCompatibleLoadVersion","onDidLoadState","_currentErrors","_currentWarnings","divertedPointer","_currentTurnIndex","storySeed","previousRandom","didSafeExit","_currentText","_currentTags","_outputStreamTextDirty","_outputStreamTagsDirty","_patch","_aliveFlowNames","_namedFlows","kDefaultFlowName","_aliveFlowNamesDirty","_currentFlow","OutputStreamDirty","_evaluationStack","_variablesState","currentTurnIndex","timeSeed","Date","getTime","GoToStart","indented","ToJson","json","TextToDictionary","LoadJsonObj","pathString","visitCountOut","TryGetVisitCount","containerPathStr","count2","currCount","VisitCountForContainer","SetVisitCount","SetTurnIndex","TryGetTurnIndex","index2","depth","canContinue","hasError","currentErrors","currentWarnings","inTag","outputObj","textContent","controlCommand","CleanOutputWhitespace","currentWhitespaceStart","startOfLine","charAt","Length","txt","Clear","keys","flowName","mainContentContainer","variablesState","SwitchFlow_Internal","SwitchToDefaultFlow_Internal","_copy$_currentFlow$cu","_copy$_currentFlow$ou","_copy$evaluationStack","_copy$_currentErrors","_copy$_currentWarning","_step4$value","namedFlowKey","namedFlowValue","hasWarning","evaluationStack","ApplyPatch","visitCounts","ApplyCountChanges","turnIndices","newCount","isVisit","_loop","WriteIntDictionary","inkVersionCurrent","jSaveVersion","flowsObj","flowsObjDict","_i","_flowsObjDictEntries","entries","_flowsObjDictEntries$","currFlowName","currentDivertTargetPath","divertPath","JObjectToIntDictionary","_this$outputStream","objs","listText","TrySplittingHeadTailWhitespace","textObj","PushToOutputStreamIndividual","single","headFirstNewlineIdx","headLastNewlineIdx","tailLastNewlineIdx","tailFirstNewlineIdx","listTexts","innerStrStart","innerStrEnd","leadingSpaces","innerStrText","numSpaces","trailingSpaces","includeInOutput","TrimNewlinesFromOutputStream","functionTrimIndex","glueTrimIndex","o","isNonWhitespace","RemoveExistingGlue","callStackElements","outputStreamEndsInNewline","outputStreamContainsContent","removeWhitespaceFrom","numberOfObjects","functionStartPoint","popType","TrimWhitespaceFromFunctionEnd","incrementingTurnIndex","newPointer","funcContainer","PassArgumentsToEvaluationStack","PushEvaluationStack","callStackTrace","originalEvaluationStackHeight","returnedObj","poppedObj","PopEvaluationStack","PopCallStack","returnVal","Stopwatch","startTime","nVal","isFinite","exports","inkVersionMinimumCompatible","onError","onDidContinue","onMakeChoice","onEvaluateFunction","onCompleteEvaluateFunction","onChoosePathString","_prevContainers","allowExternalFunctionFallbacks","_listDefinitions","_variableObservers","_hasValidatedExternals","_temporaryEvaluationContainer","_asyncContinueActive","_stateSnapshotAtLastNewline","_sawLookaheadUnsafeFunctionAfterNewline","_recursiveContinueCount","_asyncSaving","_profiler","_mainContentContainer","jsonString","_externals","rootObject","versionObj","formatFromFile","listDefsObj","rootToken","JTokenToListDefinitions","ResetState","choices","_state","IfAsyncWeCant","currentText","currentTags","currentFlowName","currentFlowIsDefaultFlow","aliveFlowNames","shouldReturn","ObserveVariableChange","VariableStateDidChangeEvent","bind","ResetGlobals","ResetErrors","ForceEnd","originalPointer","ChoosePath","ContinueInternal","SnapshotDefaultGlobals","RemoveFlow_Internal","ContinueAsync","millisecsLimitAsync","ValidateExternalBindings","PreContinue","isAsyncTimeLimited","ResetOutput","durationStopwatch","Start","ContinueSingleStep","AddError","ElapsedMilliseconds","Stop","RestoreStateSnapshot","generatedChoices","PostContinue","PreStep","Step","PostStep","TryFollowDefaultInvisibleChoice","PreSnapshot","inStringEvaluation","change","CalculateNewlineOutputStateChange","OutputStateChange","ExtendedBeyondNewline","NewlineRemoved","DiscardSnapshot","StateSnapshot","PostSnapshot","prevText","currText","prevTagCount","currTagCount","newlineStillExists","NoChange","Continue","pathLengthToUse","CopyAndStartPatching","RestoreAfterPatch","ApplyAnyPatch","stateToSave","shouldAddToStream","containerToEnter","VisitContainer","currentContentObj","isLogicOrFlowControl","PerformLogicAndFlowControl","ProcessChoice","contextIdx","ContextForVariableNamed","PushToOutputStream","NextContent","PushThread","atStart","IncrementVisitCountForContainer","RecordTurnIndexVisitToContainer","prevAncestor","currentChildOfContainer","currentContainerAncestor","allChildrenEnteredAtStart","enteringAtStart","choiceOnlyStrVal","PeekEvaluationStack","showChoice","conditionValue","IsTruthy","startText","choiceOnlyText","PopChoiceStringAndTags","ForkThread","divTarget","currentDivert","intContent","errorMessage","CallExternalFunction","evalCommand","output","overrideTunnelReturnTarget","popped","TryExitFunctionEvaluationFromGame","names","expected","contentStackForTag","outputCountConsumed","command","PopFromOutputStream","_contentStackForTag","choiceTag","contentStackForString","contentToRetain","_i3","_contentToRetain","rescuedTag","choiceCount","extraNote","eitherCount","correctObj","TurnsSinceForContainer","maxInt","minInt","randomRange","resultSeed","nextRandom","chosenValue","shuffleIndex","NextSequenceShuffleIndex","PopThread","listNameVal","generatedListValue","foundItem","targetList","ListWithSubRange","listItemIndex","listEnumerator","randomItem","assignedVal","Assign","foundValue","containerForCount","func","funcParams","resetCallstack","ResetCallstack","funcDetail","activityStr","SetChosenPath","VisitChangedContainersDueToDivert","choiceIdx","choiceToChoose","KnotContainerWithName","returnTextOutput","trim","outputStreamBefore","StartFunctionEvaluationFromGame","stringOutput","textOutput","CompleteFunctionEvaluationFromGame","exprContainer","startCallStackHeight","evalStackHeight","funcName","numberOfArguments","funcDef","fallbackFunctionContainer","foundExternal","lookAheadSafe","valueObj","funcResult","function","returnObj","lookaheadSafe","BindExternalFunctionGeneral","coercedArgs","TryCoerce","missingExternals","from","fallbackFound","observer","variableNames","observers","ObserveVariable","specificVariableName","variableObservers","newValueObj","TagsAtStartOfFlowContainerWithPathString","flowContainer","firstContent","IncrementContentPointer","didPop","successfulIncrement","nextAncestor","indexInAncestor","allChoices","invisibleChoices","numElementsIntVal","seqContainer","numElements","seqCount","loopIndex","iterationIndex","seqPathStr","sequenceHash","randomSeed","random","unpickedIndices","chosen","chosenIndex","currentDebugMetadata","errorTypeStr","lineNum","toplevelObjects","isInclude","_errorHandler","_hadError","_hadWarning","_dontFlattenContainers","_listDefs","ExportRuntime","constDecl","existingDefinition","constantName","variableInitialisation","runtimeLists","runtimeListDefinition","runtimeVarAss","runtimeStory","RuntimeStory","FlattenContainersIn","originalFoundList","itemInThisList","innerContainers","innerContainer","namedInnerContainer","TryFlattenContainer","parentContainer","ownDebugMetadata","Author","ResetError","namedFuncTarget","decl","NameConflictError","typeNameToPrint","typeNameOverride","IsReservedKeyword","maybeKnotOrFunction","knotOrFunction","topLevelContent","flowsFromOtherFiles","file","posOfObj","nonFlowContent","subStory","subStoryObj","StringExpression","otherStr","isSingleString","isStart","inChoice","DefaultFileHandler","rootPath","ResolveInkFilename","LoadInkFileContents","InkParser","filename","externalErrorHandler","rootParser","ParseStory","StatementsAtLevel","Top","_rootParser","SeparatedList","mainRule","separatorRule","firstElement","allElements","nextElementRuleId","nextElement","CreateDebugMetadata","stateAtStart","stateAtEnd","md","_filename","parsedObj","parsedListObjs","parsedListObj","hasOwnDebugMetadata","OnStringParserError","warningType","fullMessage","_externalErrorHandler","Whitespace","IdentifierWithMetadata","ExtendIdentifierCharacterRanges","identifierCharSet","ListAllCharacterRanges","charRange","_parsingChoice","onceOnlyChoice","bullets","optionalName","BracketedName","conditionExpr","ChoiceCondition","startTextAndLogic","MixedTextAndLogic","optionOnlyContent","EndTagIfNecessary","optionOnlyTextAndLogic","innerTextAndLogic","diverts","MultiDivert","emptyContent","divObj","div","conditions","ChoiceSingleCondition","ChoiceConditionsSpace","Newline","condExpr","DisallowIncrement","gatherDashCountObj","GatherDashes","gatherDashCount","ParseDashNotArrow","InnerConditionalContent","initialQueryExpression","ConditionExpression","alternatives","canBeInline","InlineConditionalBranches","MultilineConditionalBranches","soleContent","InnerBlock","elseBranch","SingleMultilineCondition","emptyTrueBranch","earlierBranchesHaveOwnExpression","isLast","alt","finalClause","trueBranch","MultilineWhitespace","multipleConditions","expr","ElseExpression","_nonTextPauseCharacters","_nonTextEndCharacters","_notTextEndCharactersChoice","_notTextEndCharactersString","TrimEndWhitespace","mixedTextAndLogicResults","terminateWithSpace","lastObjIdx","lastObj","LineOfMixedTextAndLogic","firstText","EndOfLine","SkipToNextLine","Spaced","ContentText","InlineLogicOrGlueOrStartTag","_results","ContentTextAllowingEscapeChar","ContentTextNoEscape","gotEscapeChar","endChars","parsingStringExpression","pureTextContent","ParseDivertArrow","ParseThreadArrow","threadDivert","arrowsAndDiverts","ParseDivertArrowOrTunnelOnwards","DivertIdentifierWithArguments","tunnelOnwards","tunnelOnwardDivert","gatherDivert","targetComponents","DotSeparatedDivertPathComponents","optionalArguments","ExpressionFunctionCallArguments","SingleDivert","numArrows","_binaryOperators","_maxBinaryOpLength","TempDeclarationOrAssignment","ParseTempKeyword","isIncrement","isDecrement","ReturnStatement","minimumPrecedence","ExpressionUnary","infixOp","ParseInfixOperator","expectationMessage","multiaryExpr","ExpressionInfixRight","_ret","ExpressionDivertTarget","prefixOp","ExpressionNot","ExpressionList","ExpressionParen","ExpressionFunctionCall","ExpressionVariableName","ExpressionLiteral","postfixOp","ExpressionFloat","ExpressionInt","ExpressionBool","ExpressionString","intOrNull","floatOrNull","textAndLogic","iden","commas","innerExpr","memberNames","ListMember","identifier2","RegisterExpressionOperators","RegisterBinaryOperator","infix","_openFilenames","IncludeStatement","fullFilename","FilenameIsAlreadyOpen","AddOpenFilename","includedString","RemoveOpenFilename","KnotDefinition","knotDecl","KnotDeclaration","KnotStitchNoContentRecoveryRule","KnotTitleEquals","knotName","isFunc","parameterNames","BracketedKnotDeclArguments","multiEquals","StitchDefinition","StitchDeclaration","flowArgs","flowArguments","FlowDeclArgument","firstIden","divertArrow","secondIden","funcIdentifier","argNames","_identifierCharSet","LogicLine","funCall","VariableDeclaration","ListElementDefinitionSeparator","ListDeclaration","AnyWhitespace","needsToCloseParen","elementValue","elementValueNum","ConstDeclaration","InlineLogic","StartTag","RuntimeGlue","wasParsingString","wasTagActive","tagActive","logic","InnerLogic","explicitSeqType","SequenceTypeAnnotation","contentLists","InnerSequenceObjects","rules","InnerSequence","InnerExpression","_rules","isNumberCharsOnly","_sequenceTypeSymbols","seqType","parsedSeqType","annotation","SequenceTypeSymbolAnnotation","SequenceTypeWordAnnotation","sequenceAnnotations","sequenceTypes","SequenceTypeSingleWord","combinedSequenceType","word","InnerMultilineSequenceObjects","InnerInlineSequenceObjects","interleavedContentAndPipes","justHadContent","contentOrPipe","SingleMultilineSequenceElement","_statementRulesAtLevel","_statementBreakRulesAtLevel","StatementAtLevel","StatementsBreakForLevel","rulesAtLevel","statement","breakRules","breakRuleResult","GenerateStatementLevelRules","levels","_i2","_levels","breakingRules","Line","inlineRule","_inlineWhitespaceChars","EndOfFile","newlines","anyWhitespace","MultiSpaced","_fileHandler","fullRootInkPath","ParsingString","TagActive","outputContentList","LatinBasic","LatinExtendedA","LatinExtendedB","Greek","Cyrillic","Armenian","Hebrew","Arabic","Korean","JsonFileHandler","fileHierarchy","Compiler","inkSource","options","_errors","_warnings","_authorMessages","_parsedStory","_runtimeStory","_parser","_debugSourceRanges","Compile","OnError","parser","errors","parsedStory","RetrieveDebugSourceForLatestContent","range","debugSourceRanges","DebugMetadataForContentAtOffset","offset","currOffset","lastValidMetadata","_inputString","_options"],"mappings":"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"} \ No newline at end of file diff --git a/prototype/ink-full.js.old b/prototype/ink-full.js.old new file mode 100644 index 0000000..e065eef --- /dev/null +++ b/prototype/ink-full.js.old @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).inkjs={})}(this,(function(t){"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function r(t,e){for(var n=0;nt.length)&&(e=t.length);for(var n=0,r=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,o=!0,s=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return o=t.done,t},e:function(t){s=!0,a=t},f:function(){try{o||null==n.return||n.return()}finally{if(s)throw a}}}}var b,w=i((function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;n(this,t),this.sourceFilename=e,this.pluginNames=r,this.countAllVisits=i,this.errorHandler=a,this.fileHandler=o})),k=i((function t(e,r,i){n(this,t),this.length=e,this.debugMetadata=r,this.text=i}));!function(t){t[t.Author=0]="Author",t[t.Warning=1]="Warning",t[t.Error=2]="Error"}(b||(b={}));var E=i((function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;n(this,t),this.identifier=e,this.isByReference=r,this.isDivertTarget=i}));function _(t,e){return t instanceof e?x(t):null}function T(t,e){if(t instanceof e)return x(t);throw new Error("".concat(t," is not of type ").concat(e))}function A(t){return t.hasValidName&&t.name?t:null}function P(t){return void 0===t?null:t}function N(t){return"object"===e(t)&&"function"==typeof t.Equals}function x(t,e){return t}function O(t){return null!=t}var I,F=function(){function t(){var e=this;n(this,t),this._alreadyHadError=!1,this._alreadyHadWarning=!1,this._debugMetadata=null,this._runtimeObject=null,this.content=[],this.parent=null,this.GetType=function(){return e.typeName},this.AddContent=function(t){null===e.content&&(e.content=[]);var n,r=S(Array.isArray(t)?t:[t]);try{for(r.s();!(n=r.n()).done;){var i=n.value;i.hasOwnProperty("parent")&&(i.parent=e),e.content.push(i)}}catch(t){r.e(t)}finally{r.f()}return Array.isArray(t)?void 0:t},this.InsertContent=function(t,n){return null===e.content&&(e.content=[]),n.parent=e,e.content.splice(t,0,n),n},this.Find=function(t){return function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,r=_(e,t);if(null!==r&&(null===n||!0===n(r)))return r;if(null===e.content)return null;var i,a=S(e.content);try{for(a.s();!(i=a.n()).done;){var o=i.value,s=o.Find&&o.Find(t)(n);if(s)return s}}catch(t){a.e(t)}finally{a.f()}return null}},this.FindAll=function(t){return function(n,r){var i=Array.isArray(r)?r:[],a=_(e,t);if(null===a||n&&!0!==n(a)||i.push(a),null===e.content)return[];var o,s=S(e.content);try{for(s.s();!(o=s.n()).done;){var l=o.value;l.FindAll&&l.FindAll(t)(n,i)}}catch(t){s.e(t)}finally{s.f()}return i}},this.Warning=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;e.Error(t,n,!0)}}return i(t,[{key:"debugMetadata",get:function(){return null===this._debugMetadata&&this.parent?this.parent.debugMetadata:this._debugMetadata},set:function(t){this._debugMetadata=t}},{key:"hasOwnDebugMetadata",get:function(){return Boolean(this.debugMetadata)}},{key:"typeName",get:function(){return"ParsedObject"}},{key:"story",get:function(){for(var t=this;t.parent;)t=t.parent;return t}},{key:"runtimeObject",get:function(){return this._runtimeObject||(this._runtimeObject=this.GenerateRuntimeObject(),this._runtimeObject&&(this._runtimeObject.debugMetadata=this.debugMetadata)),this._runtimeObject},set:function(t){this._runtimeObject=t}},{key:"runtimePath",get:function(){if(!this.runtimeObject.path)throw new Error;return this.runtimeObject.path}},{key:"containerForCounting",get:function(){return this.runtimeObject}},{key:"ancestry",get:function(){for(var t=[],e=this.parent;e;)t.push(e),e=e.parent;return t=t.reverse()}},{key:"ResolveReferences",value:function(t){if(null!==this.content){var e,n=S(this.content);try{for(n.s();!(e=n.n()).done;){e.value.ResolveReferences(t)}}catch(t){n.e(t)}finally{n.f()}}}},{key:"Error",value:function(t){function e(e){return t.apply(this,arguments)}return e.toString=function(){return t.toString()},e}((function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(null===e&&(e=this),!(e._alreadyHadError&&!n||e._alreadyHadWarning&&n)){if(!this.parent)throw new Error("No parent object to send error to: ".concat(t));this.parent.Error(t,e,n),n?e._alreadyHadWarning=!0:e._alreadyHadError=!0}}))}]),t}(),W=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this)).warningMessage=t,i.GenerateRuntimeObject=function(){return i.Warning(i.warningMessage),null},i}return i(r,[{key:"typeName",get:function(){return"AuthorWarning"}}]),r}(F),R=function(){function t(){if(n(this,t),this._components=[],this._componentsString=null,this._isRelative=!1,"string"==typeof arguments[0]){var e=arguments[0];this.componentsString=e}else if(arguments[0]instanceof t.Component&&arguments[1]instanceof t){var r=arguments[0],i=arguments[1];this._components.push(r),this._components=this._components.concat(i._components)}else if(arguments[0]instanceof Array){var a=arguments[0],o=!!arguments[1];this._components=this._components.concat(a),this._isRelative=o}}return i(t,[{key:"isRelative",get:function(){return this._isRelative}},{key:"componentCount",get:function(){return this._components.length}},{key:"head",get:function(){return this._components.length>0?this._components[0]:null}},{key:"tail",get:function(){return this._components.length>=2?new t(this._components.slice(1,this._components.length)):t.self}},{key:"length",get:function(){return this._components.length}},{key:"lastComponent",get:function(){var t=this._components.length-1;return t>=0?this._components[t]:null}},{key:"containsNamedComponent",get:function(){for(var t=0,e=this._components.length;t=0}},{key:"isParent",get:function(){return this.name==t.parentId}},{key:"toString",value:function(){return this.isIndex?this.index.toString():this.name}},{key:"Equals",value:function(t){return null!=t&&t.isIndex==this.isIndex&&(this.isIndex?this.index==t.index:this.name==t.name)}}],[{key:"ToParent",value:function(){return new e(t.parentId)}}]),e}();t.Component=e}(R||(R={})),function(t){function e(t,e){if(!t)throw void 0!==e&&console.warn(e),console.trace&&console.trace(),new Error("")}t.AssertType=function(t,n,r){e(t instanceof n,r)},t.Assert=e}(I||(I={}));var D=function(t){a(r,t);var e=d(r);function r(){return n(this,r),e.apply(this,arguments)}return i(r)}(c(Error));function L(t){throw new D("".concat(t," is null or undefined"))}var V=function(){function t(){n(this,t),this.parent=null,this._debugMetadata=null,this._path=null}return i(t,[{key:"debugMetadata",get:function(){return null===this._debugMetadata&&this.parent?this.parent.debugMetadata:this._debugMetadata},set:function(t){this._debugMetadata=t}},{key:"ownDebugMetadata",get:function(){return this._debugMetadata}},{key:"DebugLineNumberOfPath",value:function(t){if(null===t)return null;var e=this.rootContentContainer;if(e){var n=e.ContentAtPath(t).obj;if(n){var r=n.debugMetadata;if(null!==r)return r.startLineNumber}}return null}},{key:"path",get:function(){if(null==this._path)if(null==this.parent)this._path=new R;else{for(var t=[],e=this,n=_(e.parent,tt);null!==n;){var r=A(e);if(null!=r&&r.hasValidName){if(null===r.name)return L("namedChild.name");t.unshift(new R.Component(r.name))}else t.unshift(new R.Component(n.content.indexOf(e)));e=n,n=_(n.parent,tt)}this._path=new R(t)}return this._path}},{key:"ResolvePath",value:function(t){if(null===t)return L("path");if(t.isRelative){var e=_(this,tt);return null===e&&(I.Assert(null!==this.parent,"Can't resolve relative path because we don't have a parent"),e=_(this.parent,tt),I.Assert(null!==e,"Expected parent to be a container"),I.Assert(t.GetComponent(0).isParent),t=t.tail),null===e?L("nearestContainer"):e.ContentAtPath(t)}var n=this.rootContentContainer;return null===n?L("contentContainer"):n.ContentAtPath(t)}},{key:"ConvertPathToRelative",value:function(t){for(var e=this.path,n=Math.min(t.length,e.length),r=-1,i=0;i1?e-1:0),r=1;r0){null==this._originNames&&this.Count>0?this._originNames=[]:(this._originNames||(this._originNames=[]),this._originNames.length=0);var t,e=S(this);try{for(e.s();!(t=e.n()).done;){var n=m(t.value,1)[0],r=B.fromSerializedKey(n);if(null===r.originName)return L("item.originName");this._originNames.push(r.originName)}}catch(t){e.e(t)}finally{e.f()}}return this._originNames}},{key:"SetInitialOriginName",value:function(t){this._originNames=[t]}},{key:"SetInitialOriginNames",value:function(t){this._originNames=null==t?null:t.slice()}},{key:"maxItem",get:function(){var t,e={Key:B.Null,Value:0},n=S(this);try{for(n.s();!(t=n.n()).done;){var r=m(t.value,2),i=r[0],a=r[1],o=B.fromSerializedKey(i);(e.Key.isNull||a>e.Value)&&(e={Key:o,Value:a})}}catch(t){n.e(t)}finally{n.f()}return e}},{key:"minItem",get:function(){var t,e={Key:B.Null,Value:0},n=S(this);try{for(n.s();!(t=n.n()).done;){var r=m(t.value,2),i=r[0],a=r[1],o=B.fromSerializedKey(i);(e.Key.isNull||at.maxItem.Value)}},{key:"GreaterThanOrEquals",value:function(t){return 0!=this.Count&&(0==t.Count||this.minItem.Value>=t.minItem.Value&&this.maxItem.Value>=t.maxItem.Value)}},{key:"LessThan",value:function(t){return 0!=t.Count&&(0==this.Count||this.maxItem.Value0?new o(this.maxItem):new o}},{key:"MinAsList",value:function(){return this.Count>0?new o(this.minItem):new o}},{key:"ListWithSubRange",value:function(t,e){if(0==this.Count)return new o;var n=this.orderedItems,r=0,i=Number.MAX_SAFE_INTEGER;Number.isInteger(t)?r=t:t instanceof o&&t.Count>0&&(r=t.minItem.Value),Number.isInteger(e)?i=e:t instanceof o&&t.Count>0&&(i=e.maxItem.Value);var a=new o;a.SetInitialOriginNames(this.originNames);var s,l=S(n);try{for(l.s();!(s=l.n()).done;){var u=s.value;u.Value>=r&&u.Value<=i&&a.Add(u.Key,u.Value)}}catch(t){l.e(t)}finally{l.f()}return a}},{key:"Equals",value:function(t){if(t instanceof o==!1)return!1;if(t.Count!=this.Count)return!1;var e,n=S(this);try{for(n.s();!(e=n.n()).done;){var r=m(e.value,1)[0];if(!t.has(r))return!1}}catch(t){n.e(t)}finally{n.f()}return!0}},{key:"orderedItems",get:function(){var t,e=new Array,n=S(this);try{for(n.s();!(t=n.n()).done;){var r=m(t.value,2),i=r[0],a=r[1],o=B.fromSerializedKey(i);e.push({Key:o,Value:a})}}catch(t){n.e(t)}finally{n.f()}return e.sort((function(t,e){return null===t.Key.originName?L("x.Key.originName"):null===e.Key.originName?L("y.Key.originName"):t.Value==e.Value?t.Key.originName.localeCompare(e.Key.originName):t.Valuee.Value?1:0})),e}},{key:"toString",value:function(){for(var t=this.orderedItems,e=new j,n=0;n0&&e.Append(", ");var r=t[n].Key;if(null===r.itemName)return L("item.itemName");e.Append(r.itemName)}return e.toString()}},{key:"valueOf",value:function(){return NaN}}],[{key:"FromString",value:function(t,e){var n,r=null===(n=e.listDefinitions)||void 0===n?void 0:n.FindSingleItemListWithName(t);if(r)return null===r.value?L("listValue.value"):new o(r.value);throw new Error("Could not find the InkListItem from the string '"+t+"' to create an InkList because it doesn't exist in the original list definition in ink.")}}]),o}(c(Map)),G=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this,t)).useEndLineNumber=!1,i.message=t,i.name="StoryException",i}return i(r)}(c(Error));function q(t,e,n){if(null===t)return{result:n,exists:!1};var r=t.get(e);return void 0===r?{result:n,exists:!1}:{result:r,exists:!0}}var U,K=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this)).value=t,i}return i(r,[{key:"valueObject",get:function(){return this.value}},{key:"toString",value:function(){return null===this.value?L("Value.value"):this.value.toString()}}]),r}(function(t){a(r,t);var e=d(r);function r(){return n(this,r),e.apply(this,arguments)}return i(r,[{key:"Copy",value:function(){return T(r.Create(this.valueObject),V)}},{key:"BadCastException",value:function(t){return new G("Can't cast "+this.valueObject+" from "+this.valueType+" to "+t)}}],[{key:"Create",value:function(t,e){if(e){if(e===U.Int&&Number.isInteger(Number(t)))return new J(Number(t));if(e===U.Float&&!isNaN(t))return new z(Number(t))}return"boolean"==typeof t?new H(Boolean(t)):"string"==typeof t?new $(String(t)):Number.isInteger(Number(t))?new J(Number(t)):isNaN(t)?t instanceof R?new X(T(t,R)):t instanceof M?new Z(T(t,M)):null:new z(Number(t))}}]),r}(V)),H=function(t){a(r,t);var e=d(r);function r(t){return n(this,r),e.call(this,t||!1)}return i(r,[{key:"isTruthy",get:function(){return Boolean(this.value)}},{key:"valueType",get:function(){return U.Bool}},{key:"Cast",value:function(t){if(null===this.value)return L("Value.value");if(t==this.valueType)return this;if(t==U.Int)return new J(this.value?1:0);if(t==U.Float)return new z(this.value?1:0);if(t==U.String)return new $(this.value?"true":"false");throw this.BadCastException(t)}},{key:"toString",value:function(){return this.value?"true":"false"}}]),r}(K),J=function(t){a(r,t);var e=d(r);function r(t){return n(this,r),e.call(this,t||0)}return i(r,[{key:"isTruthy",get:function(){return 0!=this.value}},{key:"valueType",get:function(){return U.Int}},{key:"Cast",value:function(t){if(null===this.value)return L("Value.value");if(t==this.valueType)return this;if(t==U.Bool)return new H(0!==this.value);if(t==U.Float)return new z(this.value);if(t==U.String)return new $(""+this.value);throw this.BadCastException(t)}}]),r}(K),z=function(t){a(r,t);var e=d(r);function r(t){return n(this,r),e.call(this,t||0)}return i(r,[{key:"isTruthy",get:function(){return 0!=this.value}},{key:"valueType",get:function(){return U.Float}},{key:"Cast",value:function(t){if(null===this.value)return L("Value.value");if(t==this.valueType)return this;if(t==U.Bool)return new H(0!==this.value);if(t==U.Int)return new J(this.value);if(t==U.String)return new $(""+this.value);throw this.BadCastException(t)}}]),r}(K),$=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this,t||""))._isNewline="\n"==i.value,i._isInlineWhitespace=!0,null===i.value?f(i,L("Value.value")):(i.value.length>0&&i.value.split("").every((function(t){return" "==t||"\t"==t||(i._isInlineWhitespace=!1,!1)})),i)}return i(r,[{key:"valueType",get:function(){return U.String}},{key:"isTruthy",get:function(){return null===this.value?L("Value.value"):this.value.length>0}},{key:"isNewline",get:function(){return this._isNewline}},{key:"isInlineWhitespace",get:function(){return this._isInlineWhitespace}},{key:"isNonWhitespace",get:function(){return!this.isNewline&&!this.isInlineWhitespace}},{key:"Cast",value:function(t){if(t==this.valueType)return this;if(t==U.Int){var e=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=parseInt(t);return Number.isNaN(n)?{result:e,exists:!1}:{result:n,exists:!0}}(this.value);if(e.exists)return new J(e.result);throw this.BadCastException(t)}if(t==U.Float){var n=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=parseFloat(t);return Number.isNaN(n)?{result:e,exists:!1}:{result:n,exists:!0}}(this.value);if(n.exists)return new z(n.result);throw this.BadCastException(t)}throw this.BadCastException(t)}}]),r}(K),X=function(t){a(r,t);var e=d(r);function r(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;return n(this,r),e.call(this,t)}return i(r,[{key:"valueType",get:function(){return U.DivertTarget}},{key:"targetPath",get:function(){return null===this.value?L("Value.value"):this.value},set:function(t){this.value=t}},{key:"isTruthy",get:function(){throw new Error("Shouldn't be checking the truthiness of a divert target")}},{key:"Cast",value:function(t){if(t==this.valueType)return this;throw this.BadCastException(t)}},{key:"toString",value:function(){return"DivertTargetValue("+this.targetPath+")"}}]),r}(K),Y=function(t){a(r,t);var e=d(r);function r(t){var i,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;return n(this,r),(i=e.call(this,t))._contextIndex=a,i}return i(r,[{key:"contextIndex",get:function(){return this._contextIndex},set:function(t){this._contextIndex=t}},{key:"variableName",get:function(){return null===this.value?L("Value.value"):this.value},set:function(t){this.value=t}},{key:"valueType",get:function(){return U.VariablePointer}},{key:"isTruthy",get:function(){throw new Error("Shouldn't be checking the truthiness of a variable pointer")}},{key:"Cast",value:function(t){if(t==this.valueType)return this;throw this.BadCastException(t)}},{key:"toString",value:function(){return"VariablePointerValue("+this.variableName+")"}},{key:"Copy",value:function(){return new r(this.variableName,this.contextIndex)}}]),r}(K),Z=function(t){a(r,t);var e=d(r);function r(t,i){var a;return n(this,r),a=e.call(this,null),t||i?t instanceof M?a.value=new M(t):t instanceof B&&"number"==typeof i&&(a.value=new M({Key:t,Value:i})):a.value=new M,a}return i(r,[{key:"isTruthy",get:function(){return null===this.value?L("this.value"):this.value.Count>0}},{key:"valueType",get:function(){return U.List}},{key:"Cast",value:function(t){if(null===this.value)return L("Value.value");if(t==U.Int){var e=this.value.maxItem;return e.Key.isNull?new J(0):new J(e.Value)}if(t==U.Float){var n=this.value.maxItem;return n.Key.isNull?new z(0):new z(n.Value)}if(t==U.String){var r=this.value.maxItem;return r.Key.isNull?new $(""):new $(r.Key.toString())}if(t==this.valueType)return this;throw this.BadCastException(t)}}],[{key:"RetainListOriginsForAssignment",value:function(t,e){var n=_(t,r),i=_(e,r);return i&&null===i.value?L("newList.value"):n&&null===n.value?L("oldList.value"):void(n&&i&&0==i.value.Count&&i.value.SetInitialOriginNames(n.value.originNames))}}]),r}(K);!function(t){t[t.Bool=-1]="Bool",t[t.Int=0]="Int",t[t.Float=1]="Float",t[t.List=2]="List",t[t.String=3]="String",t[t.DivertTarget=4]="DivertTarget",t[t.VariablePointer=5]="VariablePointer"}(U||(U={}));var Q=function(){function t(){n(this,t),this.obj=null,this.approximate=!1}return i(t,[{key:"correctObj",get:function(){return this.approximate?null:this.obj}},{key:"container",get:function(){return this.obj instanceof tt?this.obj:null}},{key:"copy",value:function(){var e=new t;return e.obj=this.obj,e.approximate=this.approximate,e}}]),t}(),tt=function(t){a(r,t);var e=d(r);function r(){var t;return n(this,r),(t=e.apply(this,arguments)).name=null,t._content=[],t.namedContent=new Map,t.visitsShouldBeCounted=!1,t.turnIndexShouldBeCounted=!1,t.countingAtStartOnly=!1,t._pathToFirstLeafContent=null,t}return i(r,[{key:"hasValidName",get:function(){return null!=this.name&&this.name.length>0}},{key:"content",get:function(){return this._content},set:function(t){this.AddContent(t)}},{key:"namedOnlyContent",get:function(){var t,e=new Map,n=S(this.namedContent);try{for(n.s();!(t=n.n()).done;){var r=m(t.value,2),i=r[0],a=T(r[1],V);e.set(i,a)}}catch(t){n.e(t)}finally{n.f()}var o,s=S(this.content);try{for(s.s();!(o=s.n()).done;){var l=A(o.value);null!=l&&l.hasValidName&&e.delete(l.name)}}catch(t){s.e(t)}finally{s.f()}return 0==e.size&&(e=null),e},set:function(t){var e=this.namedOnlyContent;if(null!=e){var n,r=S(e);try{for(r.s();!(n=r.n()).done;){var i=m(n.value,1)[0];this.namedContent.delete(i)}}catch(t){r.e(t)}finally{r.f()}}if(null!=t){var a,o=S(t);try{for(o.s();!(a=o.n()).done;){var s=A(m(a.value,2)[1]);null!=s&&this.AddToNamedContentOnly(s)}}catch(t){o.e(t)}finally{o.f()}}}},{key:"countFlags",get:function(){var t=0;return this.visitsShouldBeCounted&&(t|=r.CountFlags.Visits),this.turnIndexShouldBeCounted&&(t|=r.CountFlags.Turns),this.countingAtStartOnly&&(t|=r.CountFlags.CountStartOnly),t==r.CountFlags.CountStartOnly&&(t=0),t},set:function(t){var e=t;(e&r.CountFlags.Visits)>0&&(this.visitsShouldBeCounted=!0),(e&r.CountFlags.Turns)>0&&(this.turnIndexShouldBeCounted=!0),(e&r.CountFlags.CountStartOnly)>0&&(this.countingAtStartOnly=!0)}},{key:"pathToFirstLeafContent",get:function(){return null==this._pathToFirstLeafContent&&(this._pathToFirstLeafContent=this.path.PathByAppendingPath(this.internalPathToFirstLeafContent)),this._pathToFirstLeafContent}},{key:"internalPathToFirstLeafContent",get:function(){for(var t=[],e=this;e instanceof r;)e.content.length>0&&(t.push(new R.Component(0)),e=e.content[0]);return new R(t)}},{key:"AddContent",value:function(t){if(t instanceof Array){var e,n=S(t);try{for(n.s();!(e=n.n()).done;){var r=e.value;this.AddContent(r)}}catch(t){n.e(t)}finally{n.f()}}else{var i=t;if(this._content.push(i),i.parent)throw new Error("content is already in "+i.parent);i.parent=this,this.TryAddNamedContent(i)}}},{key:"TryAddNamedContent",value:function(t){var e=A(t);null!=e&&e.hasValidName&&this.AddToNamedContentOnly(e)}},{key:"AddToNamedContentOnly",value:function(t){if(I.AssertType(t,V,"Can only add Runtime.Objects to a Runtime.Container"),T(t,V).parent=this,null===t.name)return L("namedContentObj.name");this.namedContent.set(t.name,t)}},{key:"ContentAtPath",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-1;-1==n&&(n=t.length);var i=new Q;i.approximate=!1;for(var a=this,o=this,s=e;s=0&&t.index=0||u.set(f,d)}}catch(t){c.e(t)}finally{c.f()}if(u.size>0){i(),t.AppendLine("-- named: --");var v,p=S(u);try{for(p.s();!(v=p.n()).done;){var g=m(v.value,2),y=g[1];I.AssertType(y,r,"Can only print out named Containers");var C=y;C.BuildStringOfHierarchy(t,e,n),t.AppendLine()}}catch(t){p.e(t)}finally{p.f()}}e--,i(),t.Append("]")}}]),r}(V);!function(t){var e;(e=t.CountFlags||(t.CountFlags={}))[e.Visits=1]="Visits",e[e.Turns=2]="Turns",e[e.CountStartOnly=4]="CountStartOnly"}(tt||(tt={}));var et=function(t){a(r,t);var e=d(r);function r(){var t,i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:r.CommandType.NotSet;return n(this,r),(t=e.call(this))._commandType=i,t}return i(r,[{key:"commandType",get:function(){return this._commandType}},{key:"Copy",value:function(){return new r(this.commandType)}},{key:"toString",value:function(){return this.commandType.toString()}}],[{key:"EvalStart",value:function(){return new r(r.CommandType.EvalStart)}},{key:"EvalOutput",value:function(){return new r(r.CommandType.EvalOutput)}},{key:"EvalEnd",value:function(){return new r(r.CommandType.EvalEnd)}},{key:"Duplicate",value:function(){return new r(r.CommandType.Duplicate)}},{key:"PopEvaluatedValue",value:function(){return new r(r.CommandType.PopEvaluatedValue)}},{key:"PopFunction",value:function(){return new r(r.CommandType.PopFunction)}},{key:"PopTunnel",value:function(){return new r(r.CommandType.PopTunnel)}},{key:"BeginString",value:function(){return new r(r.CommandType.BeginString)}},{key:"EndString",value:function(){return new r(r.CommandType.EndString)}},{key:"NoOp",value:function(){return new r(r.CommandType.NoOp)}},{key:"ChoiceCount",value:function(){return new r(r.CommandType.ChoiceCount)}},{key:"Turns",value:function(){return new r(r.CommandType.Turns)}},{key:"TurnsSince",value:function(){return new r(r.CommandType.TurnsSince)}},{key:"ReadCount",value:function(){return new r(r.CommandType.ReadCount)}},{key:"Random",value:function(){return new r(r.CommandType.Random)}},{key:"SeedRandom",value:function(){return new r(r.CommandType.SeedRandom)}},{key:"VisitIndex",value:function(){return new r(r.CommandType.VisitIndex)}},{key:"SequenceShuffleIndex",value:function(){return new r(r.CommandType.SequenceShuffleIndex)}},{key:"StartThread",value:function(){return new r(r.CommandType.StartThread)}},{key:"Done",value:function(){return new r(r.CommandType.Done)}},{key:"End",value:function(){return new r(r.CommandType.End)}},{key:"ListFromInt",value:function(){return new r(r.CommandType.ListFromInt)}},{key:"ListRange",value:function(){return new r(r.CommandType.ListRange)}},{key:"ListRandom",value:function(){return new r(r.CommandType.ListRandom)}},{key:"BeginTag",value:function(){return new r(r.CommandType.BeginTag)}},{key:"EndTag",value:function(){return new r(r.CommandType.EndTag)}}]),r}(V);!function(t){var e;(e=t.CommandType||(t.CommandType={}))[e.NotSet=-1]="NotSet",e[e.EvalStart=0]="EvalStart",e[e.EvalOutput=1]="EvalOutput",e[e.EvalEnd=2]="EvalEnd",e[e.Duplicate=3]="Duplicate",e[e.PopEvaluatedValue=4]="PopEvaluatedValue",e[e.PopFunction=5]="PopFunction",e[e.PopTunnel=6]="PopTunnel",e[e.BeginString=7]="BeginString",e[e.EndString=8]="EndString",e[e.NoOp=9]="NoOp",e[e.ChoiceCount=10]="ChoiceCount",e[e.Turns=11]="Turns",e[e.TurnsSince=12]="TurnsSince",e[e.ReadCount=13]="ReadCount",e[e.Random=14]="Random",e[e.SeedRandom=15]="SeedRandom",e[e.VisitIndex=16]="VisitIndex",e[e.SequenceShuffleIndex=17]="SequenceShuffleIndex",e[e.StartThread=18]="StartThread",e[e.Done=19]="Done",e[e.End=20]="End",e[e.ListFromInt=21]="ListFromInt",e[e.ListRange=22]="ListRange",e[e.ListRandom=23]="ListRandom",e[e.BeginTag=24]="BeginTag",e[e.EndTag=25]="EndTag",e[e.TOTAL_VALUES=26]="TOTAL_VALUES"}(et||(et={}));var nt=function(t){a(r,t);var e=d(r);function r(){var t;return n(this,r),(t=e.apply(this,arguments))._prototypeRuntimeConstantExpression=null,t.outputWhenComplete=!1,t.GenerateRuntimeObject=function(){var e=new tt;return e.AddContent(et.EvalStart()),t.GenerateIntoContainer(e),t.outputWhenComplete&&e.AddContent(et.EvalOutput()),e.AddContent(et.EvalEnd()),e},t.GenerateConstantIntoContainer=function(e){null===t._prototypeRuntimeConstantExpression&&(t._prototypeRuntimeConstantExpression=new tt,t.GenerateIntoContainer(t._prototypeRuntimeConstantExpression));var n,r=S(t._prototypeRuntimeConstantExpression.content);try{for(r.s();!(n=r.n()).done;){var i=n.value.Copy();i&&e.AddContent(i)}}catch(t){r.e(t)}finally{r.f()}},t.toString=function(){return"No string value in JavaScript."},t}return i(r,[{key:"typeName",get:function(){return"Expression"}},{key:"Equals",value:function(t){return!1}}]),r}(F),rt=function(t){a(r,t);var e=d(r);function r(){return n(this,r),e.apply(this,arguments)}return i(r)}(V),it=function(t){a(r,t);var e=d(r);function r(){var t;if(n(this,r),(t=e.call(this))._name=null,t._numberOfParameters=0,t._prototype=null,t._isPrototype=!1,t._operationFuncs=null,0===arguments.length)r.GenerateNativeFunctionsIfNecessary();else if(1===arguments.length){var i=arguments[0];r.GenerateNativeFunctionsIfNecessary(),t.name=i}else if(2===arguments.length){var a=arguments[0],o=arguments[1];t._isPrototype=!0,t.name=a,t.numberOfParameters=o}return t}return i(r,[{key:"name",get:function(){return null===this._name?L("NativeFunctionCall._name"):this._name},set:function(t){this._name=t,this._isPrototype||(null===r._nativeFunctions?L("NativeFunctionCall._nativeFunctions"):this._prototype=r._nativeFunctions.get(this._name)||null)}},{key:"numberOfParameters",get:function(){return this._prototype?this._prototype.numberOfParameters:this._numberOfParameters},set:function(t){this._numberOfParameters=t}},{key:"Call",value:function(t){if(this._prototype)return this._prototype.Call(t);if(this.numberOfParameters!=t.length)throw new Error("Unexpected number of parameters");var e,n=!1,r=S(t);try{for(r.s();!(e=r.n()).done;){var i=e.value;if(i instanceof rt)throw new G('Attempting to perform operation on a void value. Did you forget to "return" a value from a function you called here?');i instanceof Z&&(n=!0)}}catch(t){r.e(t)}finally{r.f()}if(2==t.length&&n)return this.CallBinaryListOperation(t);var a=this.CoerceValuesToSingleType(t),o=a[0].valueType;return o==U.Int||o==U.Float||o==U.String||o==U.DivertTarget||o==U.List?this.CallType(a):null}},{key:"CallType",value:function(t){var e=T(t[0],K),n=e.valueType,i=e,a=t.length;if(2==a||1==a){if(null===this._operationFuncs)return L("NativeFunctionCall._operationFuncs");var o=this._operationFuncs.get(n);if(!o){var s=U[n];throw new G("Cannot perform operation "+this.name+" on "+s)}if(2==a){var l=T(t[1],K),u=o;if(null===i.value||null===l.value)return L("NativeFunctionCall.Call BinaryOp values");var c=u(i.value,l.value);return K.Create(c)}var h=o;if(null===i.value)return L("NativeFunctionCall.Call UnaryOp value");var f=h(i.value);return this.name===r.Int?K.Create(f,U.Int):this.name===r.Float?K.Create(f,U.Float):K.Create(f,e.valueType)}throw new Error("Unexpected number of parameters to NativeFunctionCall: "+t.length)}},{key:"CallBinaryListOperation",value:function(t){if(("+"==this.name||"-"==this.name)&&t[0]instanceof Z&&t[1]instanceof J)return this.CallListIncrementOperation(t);var e=T(t[0],K),n=T(t[1],K);if(!("&&"!=this.name&&"||"!=this.name||e.valueType==U.List&&n.valueType==U.List)){if(null===this._operationFuncs)return L("NativeFunctionCall._operationFuncs");var r=this._operationFuncs.get(U.Int);if(null===r)return L("NativeFunctionCall.CallBinaryListOperation op");var i=function(t){if("boolean"==typeof t)return t;throw new Error("".concat(t," is not a boolean"))}(r(e.isTruthy?1:0,n.isTruthy?1:0));return new H(i)}if(e.valueType==U.List&&n.valueType==U.List)return this.CallType([e,n]);throw new G("Can not call use "+this.name+" operation on "+U[e.valueType]+" and "+U[n.valueType])}},{key:"CallListIncrementOperation",value:function(t){var e=T(t[0],Z),n=T(t[1],J),r=new M;if(null===e.value)return L("NativeFunctionCall.CallListIncrementOperation listVal.value");var i,a=S(e.value);try{for(a.s();!(i=a.n()).done;){var o=m(i.value,2),s=o[0],l=o[1],u=B.fromSerializedKey(s);if(null===this._operationFuncs)return L("NativeFunctionCall._operationFuncs");var c=this._operationFuncs.get(U.Int);if(null===n.value)return L("NativeFunctionCall.CallListIncrementOperation intVal.value");var h=c(l,n.value),f=null;if(null===e.value.origins)return L("NativeFunctionCall.CallListIncrementOperation listVal.value.origins");var d,v=S(e.value.origins);try{for(v.s();!(d=v.n()).done;){var p=d.value;if(p.name==u.originName){f=p;break}}}catch(t){v.e(t)}finally{v.f()}if(null!=f){var g=f.TryGetItemWithValue(h,B.Null);g.exists&&r.Add(g.result,h)}}}catch(t){a.e(t)}finally{a.f()}return new Z(r)}},{key:"CoerceValuesToSingleType",value:function(t){var e,n=U.Int,r=null,i=S(t);try{for(i.s();!(e=i.n()).done;){var a=T(e.value,K);a.valueType>n&&(n=a.valueType),a.valueType==U.List&&(r=_(a,Z))}}catch(t){i.e(t)}finally{i.f()}var o=[];if(U[n]==U[U.List]){var s,l=S(t);try{for(l.s();!(s=l.n()).done;){var u=T(s.value,K);if(u.valueType==U.List)o.push(u);else{if(u.valueType!=U.Int){var c=U[u.valueType];throw new G("Cannot mix Lists and "+c+" values in this operation")}var h=parseInt(u.valueObject);if(null===(r=T(r,Z)).value)return L("NativeFunctionCall.CoerceValuesToSingleType specialCaseList.value");var f=r.value.originOfMaxItem;if(null===f)return L("NativeFunctionCall.CoerceValuesToSingleType list");var d=f.TryGetItemWithValue(h,B.Null);if(!d.exists)throw new G("Could not find List item with the value "+h+" in "+f.name);var v=new Z(d.result,h);o.push(v)}}}catch(t){l.e(t)}finally{l.f()}}else{var p,m=S(t);try{for(m.s();!(p=m.n()).done;){var g=T(p.value,K).Cast(n);o.push(g)}}catch(t){m.e(t)}finally{m.f()}}return o}},{key:"AddOpFuncForType",value:function(t,e){null==this._operationFuncs&&(this._operationFuncs=new Map),this._operationFuncs.set(t,e)}},{key:"toString",value:function(){return'Native "'+this.name+'"'}}],[{key:"CallWithName",value:function(t){return new r(t)}},{key:"CallExistsWithName",value:function(t){return this.GenerateNativeFunctionsIfNecessary(),this._nativeFunctions.get(t)}},{key:"Identity",value:function(t){return t}},{key:"GenerateNativeFunctionsIfNecessary",value:function(){if(null==this._nativeFunctions){this._nativeFunctions=new Map,this.AddIntBinaryOp(this.Add,(function(t,e){return t+e})),this.AddIntBinaryOp(this.Subtract,(function(t,e){return t-e})),this.AddIntBinaryOp(this.Multiply,(function(t,e){return t*e})),this.AddIntBinaryOp(this.Divide,(function(t,e){return Math.floor(t/e)})),this.AddIntBinaryOp(this.Mod,(function(t,e){return t%e})),this.AddIntUnaryOp(this.Negate,(function(t){return-t})),this.AddIntBinaryOp(this.Equal,(function(t,e){return t==e})),this.AddIntBinaryOp(this.Greater,(function(t,e){return t>e})),this.AddIntBinaryOp(this.Less,(function(t,e){return t=e})),this.AddIntBinaryOp(this.LessThanOrEquals,(function(t,e){return t<=e})),this.AddIntBinaryOp(this.NotEquals,(function(t,e){return t!=e})),this.AddIntUnaryOp(this.Not,(function(t){return 0==t})),this.AddIntBinaryOp(this.And,(function(t,e){return 0!=t&&0!=e})),this.AddIntBinaryOp(this.Or,(function(t,e){return 0!=t||0!=e})),this.AddIntBinaryOp(this.Max,(function(t,e){return Math.max(t,e)})),this.AddIntBinaryOp(this.Min,(function(t,e){return Math.min(t,e)})),this.AddIntBinaryOp(this.Pow,(function(t,e){return Math.pow(t,e)})),this.AddIntUnaryOp(this.Floor,r.Identity),this.AddIntUnaryOp(this.Ceiling,r.Identity),this.AddIntUnaryOp(this.Int,r.Identity),this.AddIntUnaryOp(this.Float,(function(t){return t})),this.AddFloatBinaryOp(this.Add,(function(t,e){return t+e})),this.AddFloatBinaryOp(this.Subtract,(function(t,e){return t-e})),this.AddFloatBinaryOp(this.Multiply,(function(t,e){return t*e})),this.AddFloatBinaryOp(this.Divide,(function(t,e){return t/e})),this.AddFloatBinaryOp(this.Mod,(function(t,e){return t%e})),this.AddFloatUnaryOp(this.Negate,(function(t){return-t})),this.AddFloatBinaryOp(this.Equal,(function(t,e){return t==e})),this.AddFloatBinaryOp(this.Greater,(function(t,e){return t>e})),this.AddFloatBinaryOp(this.Less,(function(t,e){return t=e})),this.AddFloatBinaryOp(this.LessThanOrEquals,(function(t,e){return t<=e})),this.AddFloatBinaryOp(this.NotEquals,(function(t,e){return t!=e})),this.AddFloatUnaryOp(this.Not,(function(t){return 0==t})),this.AddFloatBinaryOp(this.And,(function(t,e){return 0!=t&&0!=e})),this.AddFloatBinaryOp(this.Or,(function(t,e){return 0!=t||0!=e})),this.AddFloatBinaryOp(this.Max,(function(t,e){return Math.max(t,e)})),this.AddFloatBinaryOp(this.Min,(function(t,e){return Math.min(t,e)})),this.AddFloatBinaryOp(this.Pow,(function(t,e){return Math.pow(t,e)})),this.AddFloatUnaryOp(this.Floor,(function(t){return Math.floor(t)})),this.AddFloatUnaryOp(this.Ceiling,(function(t){return Math.ceil(t)})),this.AddFloatUnaryOp(this.Int,(function(t){return Math.floor(t)})),this.AddFloatUnaryOp(this.Float,r.Identity),this.AddStringBinaryOp(this.Add,(function(t,e){return t+e})),this.AddStringBinaryOp(this.Equal,(function(t,e){return t===e})),this.AddStringBinaryOp(this.NotEquals,(function(t,e){return!(t===e)})),this.AddStringBinaryOp(this.Has,(function(t,e){return t.includes(e)})),this.AddStringBinaryOp(this.Hasnt,(function(t,e){return!t.includes(e)})),this.AddListBinaryOp(this.Add,(function(t,e){return t.Union(e)})),this.AddListBinaryOp(this.Subtract,(function(t,e){return t.Without(e)})),this.AddListBinaryOp(this.Has,(function(t,e){return t.Contains(e)})),this.AddListBinaryOp(this.Hasnt,(function(t,e){return!t.Contains(e)})),this.AddListBinaryOp(this.Intersect,(function(t,e){return t.Intersect(e)})),this.AddListBinaryOp(this.Equal,(function(t,e){return t.Equals(e)})),this.AddListBinaryOp(this.Greater,(function(t,e){return t.GreaterThan(e)})),this.AddListBinaryOp(this.Less,(function(t,e){return t.LessThan(e)})),this.AddListBinaryOp(this.GreaterThanOrEquals,(function(t,e){return t.GreaterThanOrEquals(e)})),this.AddListBinaryOp(this.LessThanOrEquals,(function(t,e){return t.LessThanOrEquals(e)})),this.AddListBinaryOp(this.NotEquals,(function(t,e){return!t.Equals(e)})),this.AddListBinaryOp(this.And,(function(t,e){return t.Count>0&&e.Count>0})),this.AddListBinaryOp(this.Or,(function(t,e){return t.Count>0||e.Count>0})),this.AddListUnaryOp(this.Not,(function(t){return 0==t.Count?1:0})),this.AddListUnaryOp(this.Invert,(function(t){return t.inverse})),this.AddListUnaryOp(this.All,(function(t){return t.all})),this.AddListUnaryOp(this.ListMin,(function(t){return t.MinAsList()})),this.AddListUnaryOp(this.ListMax,(function(t){return t.MaxAsList()})),this.AddListUnaryOp(this.Count,(function(t){return t.Count})),this.AddListUnaryOp(this.ValueOfList,(function(t){return t.maxItem.Value}));this.AddOpToNativeFunc(this.Equal,2,U.DivertTarget,(function(t,e){return t.Equals(e)})),this.AddOpToNativeFunc(this.NotEquals,2,U.DivertTarget,(function(t,e){return!t.Equals(e)}))}}},{key:"AddOpToNativeFunc",value:function(t,e,n,i){if(null===this._nativeFunctions)return L("NativeFunctionCall._nativeFunctions");var a=this._nativeFunctions.get(t);a||(a=new r(t,e),this._nativeFunctions.set(t,a)),a.AddOpFuncForType(n,i)}},{key:"AddIntBinaryOp",value:function(t,e){this.AddOpToNativeFunc(t,2,U.Int,e)}},{key:"AddIntUnaryOp",value:function(t,e){this.AddOpToNativeFunc(t,1,U.Int,e)}},{key:"AddFloatBinaryOp",value:function(t,e){this.AddOpToNativeFunc(t,2,U.Float,e)}},{key:"AddFloatUnaryOp",value:function(t,e){this.AddOpToNativeFunc(t,1,U.Float,e)}},{key:"AddStringBinaryOp",value:function(t,e){this.AddOpToNativeFunc(t,2,U.String,e)}},{key:"AddListBinaryOp",value:function(t,e){this.AddOpToNativeFunc(t,2,U.List,e)}},{key:"AddListUnaryOp",value:function(t,e){this.AddOpToNativeFunc(t,1,U.List,e)}}]),r}(V);it.Add="+",it.Subtract="-",it.Divide="/",it.Multiply="*",it.Mod="%",it.Negate="_",it.Equal="==",it.Greater=">",it.Less="<",it.GreaterThanOrEquals=">=",it.LessThanOrEquals="<=",it.NotEquals="!=",it.Not="!",it.And="&&",it.Or="||",it.Min="MIN",it.Max="MAX",it.Pow="POW",it.Floor="FLOOR",it.Ceiling="CEILING",it.Int="INT",it.Float="FLOAT",it.Has="?",it.Hasnt="!?",it.Intersect="^",it.ListMin="LIST_MIN",it.ListMax="LIST_MAX",it.All="LIST_ALL",it.Count="LIST_COUNT",it.ValueOfList="LIST_VALUE",it.Invert="LIST_INVERT",it._nativeFunctions=null;var at=function(t){a(r,t);var e=d(r);function r(t,i){var a;if(n(this,r),(a=e.call(this)).isInt=function(){return"int"==a.subtype},a.isFloat=function(){return"float"==a.subtype},a.isBool=function(){return"bool"==a.subtype},a.GenerateIntoContainer=function(t){a.isInt()?t.AddContent(new J(a.value)):a.isFloat()?t.AddContent(new z(a.value)):a.isBool()&&t.AddContent(new H(a.value))},a.toString=function(){return String(a.value)},("number"!=typeof t||Number.isNaN(t))&&"boolean"!=typeof t)throw new Error("Unexpected object type in NumberExpression.");return a.value=t,a.subtype=i,a}return i(r,[{key:"typeName",get:function(){return"Number"}},{key:"Equals",value:function(t){var e=_(t,r);return!!e&&(e.subtype==this.subtype&&e.value==this.value)}}]),r}(nt),ot=function(t){a(r,t);var e=d(r);function r(t,i){var a;return n(this,r),(a=e.call(this)).op=i,a.GenerateIntoContainer=function(t){a.innerExpression.GenerateIntoContainer(t),t.AddContent(it.CallWithName(a.nativeNameForOp))},a.toString=function(){return a.nativeNameForOp+a.innerExpression},a.innerExpression=a.AddContent(t),a}return i(r,[{key:"nativeNameForOp",get:function(){return"-"===this.op?"_":"not"===this.op?"!":this.op}},{key:"typeName",get:function(){return"UnaryExpression"}}]),r}(nt);ot.WithInner=function(t,e){var n=_(t,at);if(n){if("-"===e){if(n.isInt())return new at(-n.value,"int");if(n.isFloat())return new at(-n.value,"float")}else if("!"==e||"not"==e){if(n.isInt())return new at(0==n.value,"bool");if(n.isFloat())return new at(0==n.value,"bool");if(n.isBool())return new at(!n.value,"bool")}throw new Error("Unexpected operation or number type")}return new ot(t,e)};var st=function(t){a(r,t);var e=d(r);function r(t,i,a){var o;return n(this,r),(o=e.call(this)).opName=a,o.GenerateIntoContainer=function(t){o.leftExpression.GenerateIntoContainer(t),o.rightExpression.GenerateIntoContainer(t),o.opName=o.NativeNameForOp(o.opName),t.AddContent(it.CallWithName(o.opName))},o.NativeNameForOp=function(t){return"and"===t?"&&":"or"===t?"||":"mod"===t?"%":"has"===t?"?":"hasnt"===t?"!?":t},o.toString=function(){return"(".concat(o.leftExpression," ").concat(o.opName," ").concat(o.rightExpression,")")},o.leftExpression=o.AddContent(t),o.rightExpression=o.AddContent(i),o.opName=a,o}return i(r,[{key:"typeName",get:function(){return"BinaryExpression"}},{key:"ResolveReferences",value:function(t){if(p(o(r.prototype),"ResolveReferences",this).call(this,t),"?"===this.NativeNameForOp(this.opName)){var e=_(this.leftExpression,ot);null===e||"not"!==e.op&&"!"!==e.op||this.Error("Using 'not' or '!' here negates '".concat(e.innerExpression,"' rather than the result of the '?' or 'has' operator. You need to add parentheses around the (A ? B) expression."))}}}]),r}(nt),lt=i((function t(e){var r=this;n(this,t),this.set=new Set,this.Add=function(t){return r.set.add(t)},this.AddRange=function(t,e){for(var n=t.charCodeAt(0);n<=e.charCodeAt(0);++n)r.Add(String.fromCharCode(n));return r},this.AddCharacters=function(t){if("string"==typeof t||Array.isArray(t)){var e,n=S(t);try{for(n.s();!(e=n.n()).done;){var i=e.value;r.Add(i)}}catch(t){n.e(t)}finally{n.f()}}else{var a,o=S(t.set);try{for(o.s();!(a=o.n()).done;){var s=a.value;r.Add(s)}}catch(t){o.e(t)}finally{o.f()}}return r},e&&this.AddCharacters(e)}));lt.FromRange=function(t,e){return(new lt).AddRange(t,e)};var ut=function(){function t(e,r){var i=this,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];if(n(this,t),this._start=e,this._end=r,this._correspondingCharSet=new lt,this._excludes=new Set,this.ToCharacterSet=function(){if(0===i._correspondingCharSet.set.size)for(var t=i.start.charCodeAt(0),e=String.fromCharCode(t);t<=i.end.charCodeAt(0);t+=1)i._excludes.has(e)||i._correspondingCharSet.AddCharacters(e);return i._correspondingCharSet},a instanceof lt)this._excludes=a.set;else{var o,s=S(a);try{for(s.s();!(o=s.n()).done;){var l=o.value;this._excludes.add(l)}}catch(t){s.e(t)}finally{s.f()}}}return i(t,[{key:"start",get:function(){return this._start}},{key:"end",get:function(){return this._end}}]),t}();ut.Define=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return new ut(t,e,n)};var ct,ht=function(t){a(r,t);var e=d(r);function r(){var t,i=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return n(this,r),(t=e.call(this))._pathOnChoice=null,t.hasCondition=!1,t.hasStartContent=!1,t.hasChoiceOnlyContent=!1,t.isInvisibleDefault=!1,t.onceOnly=!0,t.onceOnly=i,t}return i(r,[{key:"pathOnChoice",get:function(){if(null!=this._pathOnChoice&&this._pathOnChoice.isRelative){var t=this.choiceTarget;t&&(this._pathOnChoice=t.path)}return this._pathOnChoice},set:function(t){this._pathOnChoice=t}},{key:"choiceTarget",get:function(){return null===this._pathOnChoice?L("ChoicePoint._pathOnChoice"):this.ResolvePath(this._pathOnChoice).container}},{key:"pathStringOnChoice",get:function(){return null===this.pathOnChoice?L("ChoicePoint.pathOnChoice"):this.CompactPathString(this.pathOnChoice)},set:function(t){this.pathOnChoice=new R(t)}},{key:"flags",get:function(){var t=0;return this.hasCondition&&(t|=1),this.hasStartContent&&(t|=2),this.hasChoiceOnlyContent&&(t|=4),this.isInvisibleDefault&&(t|=8),this.onceOnly&&(t|=16),t},set:function(t){this.hasCondition=(1&t)>0,this.hasStartContent=(2&t)>0,this.hasChoiceOnlyContent=(4&t)>0,this.isInvisibleDefault=(8&t)>0,this.onceOnly=(16&t)>0}},{key:"toString",value:function(){return null===this.pathOnChoice?L("ChoicePoint.pathOnChoice"):"Choice: -> "+this.pathOnChoice.toString()}}]),r}(V);!function(t){t[t.Tunnel=0]="Tunnel",t[t.Function=1]="Function",t[t.FunctionEvaluationFromGame=2]="FunctionEvaluationFromGame"}(ct||(ct={}));var ft,dt=function(){function t(){n(this,t),this.container=null,this.index=-1,2===arguments.length&&(this.container=arguments[0],this.index=arguments[1])}return i(t,[{key:"Resolve",value:function(){return this.index<0?this.container:null==this.container?null:0==this.container.content.length?this.container:this.index>=this.container.content.length?null:this.container.content[this.index]}},{key:"isNull",get:function(){return null==this.container}},{key:"path",get:function(){return this.isNull?null:this.index>=0?this.container.path.PathByAppendingComponent(new R.Component(this.index)):this.container.path}},{key:"toString",value:function(){return this.container?"Ink Pointer -> "+this.container.path.toString()+" -- index "+this.index:"Ink Pointer (null)"}},{key:"copy",value:function(){return new t(this.container,this.index)}}],[{key:"StartOf",value:function(e){return new t(e,0)}},{key:"Null",get:function(){return new t(null,-1)}}]),t}(),vt=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this))._targetPath=null,i._targetPointer=dt.Null,i.variableDivertName=null,i.pushesToStack=!1,i.stackPushType=0,i.isExternal=!1,i.externalArgs=0,i.isConditional=!1,i.pushesToStack=!1,void 0!==t&&(i.pushesToStack=!0,i.stackPushType=t),i}return i(r,[{key:"targetPath",get:function(){if(null!=this._targetPath&&this._targetPath.isRelative){var t=this.targetPointer.Resolve();t&&(this._targetPath=t.path)}return this._targetPath},set:function(t){this._targetPath=t,this._targetPointer=dt.Null}},{key:"targetPointer",get:function(){if(this._targetPointer.isNull){var t=this.ResolvePath(this._targetPath).obj;if(null===this._targetPath)return L("this._targetPath");if(null===this._targetPath.lastComponent)return L("this._targetPath.lastComponent");if(this._targetPath.lastComponent.isIndex){if(null===t)return L("targetObj");this._targetPointer.container=t.parent instanceof tt?t.parent:null,this._targetPointer.index=this._targetPath.lastComponent.index}else this._targetPointer=dt.StartOf(t instanceof tt?t:null)}return this._targetPointer.copy()}},{key:"targetPathString",get:function(){return null==this.targetPath?null:this.CompactPathString(this.targetPath)},set:function(t){this.targetPath=null==t?null:new R(t)}},{key:"hasVariableTarget",get:function(){return null!=this.variableDivertName}},{key:"Equals",value:function(t){var e=t;return e instanceof r&&this.hasVariableTarget==e.hasVariableTarget&&(this.hasVariableTarget?this.variableDivertName==e.variableDivertName:null===this.targetPath?L("this.targetPath"):this.targetPath.Equals(e.targetPath))}},{key:"toString",value:function(){if(this.hasVariableTarget)return"Divert(variable: "+this.variableDivertName+")";if(null==this.targetPath)return"Divert(null)";var t=new j,e=this.targetPath.toString();return t.Append("Divert"),this.isConditional&&t.Append("?"),this.pushesToStack&&(this.stackPushType==ct.Function?t.Append(" function"):t.Append(" tunnel")),t.Append(" -> "),t.Append(this.targetPathString),t.Append(" ("),t.Append(e),t.Append(")"),t.toString()}}]),r}(V);!function(t){t[t.Knot=0]="Knot",t[t.List=1]="List",t[t.ListItem=2]="ListItem",t[t.Var=3]="Var",t[t.SubFlowAndWeave=4]="SubFlowAndWeave",t[t.Arg=5]="Arg",t[t.Temp=6]="Temp"}(ft||(ft={}));var pt=function(t){a(r,t);var e=d(r);function r(t,i){var a;return n(this,r),(a=e.call(this)).variableName=t||null,a.isNewDeclaration=!!i,a.isGlobal=!1,a}return i(r,[{key:"toString",value:function(){return"VarAssign to "+this.variableName}}]),r}(V),mt=function(t){a(r,t);var e=d(r);function r(t,i,a){var o;return n(this,r),(o=e.call(this))._condition=null,o._innerContentContainer=null,o._outerContainer=null,o._runtimeChoice=null,o._returnToR1=null,o._returnToR2=null,o._r1Label=null,o._r2Label=null,o._divertToStartContentOuter=null,o._divertToStartContentInner=null,o._startContentRuntimeContainer=null,o.isInvisibleDefault=!1,o.hasWeaveStyleInlineBrackets=!1,o.GenerateRuntimeObject=function(){if(o._outerContainer=new tt,o._runtimeChoice=new ht(o.onceOnly),o._runtimeChoice.isInvisibleDefault=o.isInvisibleDefault,(o.startContent||o.choiceOnlyContent||o.condition)&&o._outerContainer.AddContent(et.EvalStart()),o.startContent){o._returnToR1=new X,o._outerContainer.AddContent(o._returnToR1);var t=new pt("$r",!0);o._outerContainer.AddContent(t),o._outerContainer.AddContent(et.BeginString()),o._divertToStartContentOuter=new vt,o._outerContainer.AddContent(o._divertToStartContentOuter),o._startContentRuntimeContainer=o.startContent.GenerateRuntimeObject(),o._startContentRuntimeContainer.name="s";var e=new vt;e.variableDivertName="$r",o._startContentRuntimeContainer.AddContent(e),o._outerContainer.AddToNamedContentOnly(o._startContentRuntimeContainer),o._r1Label=new tt,o._r1Label.name="$r1",o._outerContainer.AddContent(o._r1Label),o._outerContainer.AddContent(et.EndString()),o._runtimeChoice.hasStartContent=!0}if(o.choiceOnlyContent){o._outerContainer.AddContent(et.BeginString());var n=o.choiceOnlyContent.GenerateRuntimeObject();o._outerContainer.AddContentsOfContainer(n),o._outerContainer.AddContent(et.EndString()),o._runtimeChoice.hasChoiceOnlyContent=!0}if(o.condition&&(o.condition.GenerateIntoContainer(o._outerContainer),o._runtimeChoice.hasCondition=!0),(o.startContent||o.choiceOnlyContent||o.condition)&&o._outerContainer.AddContent(et.EvalEnd()),o._outerContainer.AddContent(o._runtimeChoice),o._innerContentContainer=new tt,o.startContent){o._returnToR2=new X,o._innerContentContainer.AddContent(et.EvalStart()),o._innerContentContainer.AddContent(o._returnToR2),o._innerContentContainer.AddContent(et.EvalEnd());var r=new pt("$r",!0);o._innerContentContainer.AddContent(r),o._divertToStartContentInner=new vt,o._innerContentContainer.AddContent(o._divertToStartContentInner),o._r2Label=new tt,o._r2Label.name="$r2",o._innerContentContainer.AddContent(o._r2Label)}if(o.innerContent){var i=o.innerContent.GenerateRuntimeObject();o._innerContentContainer.AddContentsOfContainer(i)}return o.story.countAllVisits&&(o._innerContentContainer.visitsShouldBeCounted=!0),o._innerContentContainer.countingAtStartOnly=!0,o._outerContainer},o.toString=function(){return null!==o.choiceOnlyContent?"* ".concat(o.startContent,"[").concat(o.choiceOnlyContent,"]..."):"* ".concat(o.startContent,"...")},o.startContent=t,o.choiceOnlyContent=i,o.innerContent=a,o.indentationDepth=1,t&&o.AddContent(o.startContent),i&&o.AddContent(o.choiceOnlyContent),a&&o.AddContent(o.innerContent),o.onceOnly=!0,o}return i(r,[{key:"runtimeChoice",get:function(){if(!this._runtimeChoice)throw new Error;return this._runtimeChoice}},{key:"name",get:function(){var t;return(null===(t=this.identifier)||void 0===t?void 0:t.name)||null}},{key:"condition",get:function(){return this._condition},set:function(t){this._condition=t,t&&this.AddContent(t)}},{key:"runtimeContainer",get:function(){return this._innerContentContainer}},{key:"innerContentContainer",get:function(){return this._innerContentContainer}},{key:"containerForCounting",get:function(){return this._innerContentContainer}},{key:"runtimePath",get:function(){if(!this.innerContentContainer||!this.innerContentContainer.path)throw new Error;return this.innerContentContainer.path}},{key:"typeName",get:function(){return"Choice"}},{key:"ResolveReferences",value:function(t){var e;if(this._innerContentContainer&&(this.runtimeChoice.pathOnChoice=this._innerContentContainer.path,this.onceOnly&&(this._innerContentContainer.visitsShouldBeCounted=!0)),this._returnToR1){if(!this._r1Label)throw new Error;this._returnToR1.targetPath=this._r1Label.path}if(this._returnToR2){if(!this._r2Label)throw new Error;this._returnToR2.targetPath=this._r2Label.path}if(this._divertToStartContentOuter){if(!this._startContentRuntimeContainer)throw new Error;this._divertToStartContentOuter.targetPath=this._startContentRuntimeContainer.path}if(this._divertToStartContentInner){if(!this._startContentRuntimeContainer)throw new Error;this._divertToStartContentInner.targetPath=this._startContentRuntimeContainer.path}p(o(r.prototype),"ResolveReferences",this).call(this,t),this.identifier&&((null===(e=this.identifier)||void 0===e?void 0:e.name)||"").length>0&&t.CheckForNamingCollisions(this,this.identifier,ft.SubFlowAndWeave)}}]),r}(F),gt=i((function t(){var e=this;n(this,t),this.characterIndex=0,this.characterInLineIndex=0,this.lineIndex=0,this.reportedErrorInScope=!1,this.uniqueId=0,this.customFlags=0,this.CopyFrom=function(n){t._uniqueIdCounter++,e.uniqueId=t._uniqueIdCounter,e.characterIndex=n.characterIndex,e.characterInLineIndex=n.characterInLineIndex,e.lineIndex=n.lineIndex,e.customFlags=n.customFlags,e.reportedErrorInScope=!1},this.SquashFrom=function(t){e.characterIndex=t.characterIndex,e.characterInLineIndex=t.characterInLineIndex,e.lineIndex=t.lineIndex,e.reportedErrorInScope=t.reportedErrorInScope,e.customFlags=t.customFlags}}));gt._uniqueIdCounter=1e3;var yt=function(){function t(){var e=this;n(this,t),this._stack=[],this._numElements=0,this.StringParserState=function(){e._stack=new Array(200);for(var t=0;t<200;++t)e._stack[t]=new gt;e._numElements=1},this.Push=function(){if(e._numElements>=e._stack.length&&e._numElements>0)throw new Error("Stack overflow in parser state.");var t=e._stack[e._numElements-1],n=e._stack[e._numElements];return e._numElements++,n.CopyFrom(t),n.uniqueId},this.Pop=function(t){if(1==e._numElements)throw new Error("Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?");if(e.currentElement.uniqueId!=t)throw new Error("Mismatched rule IDs while Poping - do you have mismatched Begin/Succeed/Fail?");e._numElements-=1},this.Peek=function(t){if(e.currentElement.uniqueId!=t)throw new Error("Mismatched rule IDs while Peeking - do you have mismatched Begin/Succeed/Fail?");return e._stack[e._numElements-1]},this.PeekPenultimate=function(){return e._numElements>=2?e._stack[e._numElements-2]:null},this.Squash=function(){if(e._numElements<2)throw new Error("Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?");var t=e._stack[e._numElements-2],n=e._stack[e._numElements-1];t.SquashFrom(n),e._numElements-=1},this.NoteErrorReported=function(){var t,n=S(e._stack);try{for(n.s();!(t=n.n()).done;){t.value.reportedErrorInScope=!0}}catch(t){n.e(t)}finally{n.f()}};for(var r=0;r<200;r++)this._stack[r]=new gt;this._numElements=1}return i(t,[{key:"currentElement",get:function(){return this._stack[this._numElements-1]}},{key:"lineIndex",get:function(){return this.currentElement.lineIndex},set:function(t){this.currentElement.lineIndex=t}},{key:"characterIndex",get:function(){return this.currentElement.characterIndex},set:function(t){this.currentElement.characterIndex=t}},{key:"characterInLineIndex",get:function(){return this.currentElement.characterInLineIndex},set:function(t){this.currentElement.characterInLineIndex=t}},{key:"customFlags",get:function(){return this.currentElement.customFlags},set:function(t){this.currentElement.customFlags=t}},{key:"errorReportedAlreadyInScope",get:function(){return this.currentElement.reportedErrorInScope}},{key:"stackHeight",get:function(){return this._numElements}}]),t}(),Ct=Symbol("ParseSuccessStruct"),St=function(){function t(e){var r=this;n(this,t),this.ParseRule=null,this.errorHandler=null,this.hadError=!1,this.BeginRule=function(){return r.state.Push()},this.FailRule=function(t){return r.state.Pop(t),null},this.CancelRule=function(t){r.state.Pop(t)},this.SucceedRule=function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=r.state.Peek(e),a=r.state.PeekPenultimate();r.RuleDidSucceed&&r.RuleDidSucceed(n,a,i),r.state.Squash();var o=n;return null===o&&(o=t.ParseSuccess),o},this.Expect=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,i=r.ParseObject(t);if(null===i){var a;null===e&&(e=t.name);var o=r.LineRemainder();a=null===o||0===o.length?"end of line":"'".concat(o,"'"),r.Error("Expected ".concat(e," but saw ").concat(a)),null!==n&&(i=n())}return i},this.Error=function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];r.ErrorOnLine(t,r.lineIndex+1,e)},this.ErrorWithParsedObject=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];r.ErrorOnLine(t,e.debugMetadata?e.debugMetadata.startLineNumber:-1,n)},this.ErrorOnLine=function(t,e,n){if(!r.state.errorReportedAlreadyInScope){var i=n?"Warning":"Error";if(!r.errorHandler)throw new Error("".concat(i," on line ").concat(e,": ").concat(t));r.errorHandler(t,r.index,e-1,n),r.state.NoteErrorReported()}n||(r.hadError=!0)},this.Warning=function(t){return r.Error(t,!0)},this.LineRemainder=function(){return r.Peek((function(){return r.ParseUntilCharactersFromString("\n\r")}))},this.SetFlag=function(t,e){e?r.state.customFlags|=t:r.state.customFlags&=~t},this.GetFlag=function(t){return Boolean(r.state.customFlags&t)},this.ParseObject=function(t){var e=r.BeginRule(),n=r.state.stackHeight,i=t();if(n!==r.state.stackHeight)throw new Error("Mismatched Begin/Fail/Succeed rules");return null===i?r.FailRule(e):(r.SucceedRule(e,i),i)},this.Parse=function(t){var e=r.BeginRule(),n=t();return null===n?(r.FailRule(e),null):(r.SucceedRule(e,n),n)},this.OneOf=function(t){var e,n=S(t);try{for(n.s();!(e=n.n()).done;){var i=e.value,a=r.ParseObject(i);if(null!==a)return a}}catch(t){n.e(t)}finally{n.f()}return null},this.OneOrMore=function(t){var e=[],n=null;do{null!==(n=r.ParseObject(t))&&e.push(n)}while(null!==n);return e.length>0?e:null},this.Optional=function(e){return function(){var n=r.ParseObject(e);return null===n?t.ParseSuccess:n}},this.Exclude=function(e){return function(){return r.ParseObject(e)&&t.ParseSuccess}},this.OptionalExclude=function(e){return function(){return r.ParseObject(e),t.ParseSuccess}},this.String=function(t){return function(){return r.ParseString(t)}},this.TryAddResultToList=function(e,n){var r=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(e!==t.ParseSuccess){if(r&&Array.isArray(e)){var i=e;if(null!==i){var a,o=S(i);try{for(o.s();!(a=o.n()).done;){var s=a.value;n.push(s)}}catch(t){o.e(t)}finally{o.f()}return}}n.push(e)}},this.Interleave=function(e,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],o=r.BeginRule(),s=[],l=r.ParseObject(e);if(null===l)return r.FailRule(o);r.TryAddResultToList(l,s,a);var u=null,c=null;do{if(null!==i&&null!==r.Peek(i))break;if(null===(u=r.ParseObject(n)))break;if(r.TryAddResultToList(u,s,a),c=null,null!==u){if(null===(c=r.ParseObject(e)))break;r.TryAddResultToList(c,s,a)}}while((null!==u||null!==c)&&(u!==t.ParseSuccess||c!=t.ParseSuccess)&&r.remainingLength>0);return 0===s.length?r.FailRule(o):r.SucceedRule(o,s)},this.ParseString=function(t){if(t.length>r.remainingLength)return null;for(var e=r.BeginRule(),n=r.index,i=r.characterInLineIndex,a=r.lineIndex,o=!0,s=0;s0){var t=r._chars[r.index];return"\n"===t&&(r.lineIndex+=1,r.characterInLineIndex=-1),r.index+=1,r.characterInLineIndex+=1,t}return"0"},this.ParseUntilCharactersFromString=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;return r.ParseCharactersFromString(t,!1,e)},this.ParseUntilCharactersFromCharSet=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;return r.ParseCharactersFromCharSet(t,!1,e)},this.ParseCharactersFromString=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-1,i=new lt(t);return"number"==typeof e?r.ParseCharactersFromCharSet(i,!0,e):r.ParseCharactersFromCharSet(i,e,n)},this.ParseCharactersFromCharSet=function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-1;-1===n&&(n=Number.MAX_SAFE_INTEGER);for(var i=r.index,a=r.index,o=r.characterInLineIndex,s=r.lineIndex,l=0;ai?r._chars.slice(i,r.index).join(""):null},this.Peek=function(t){var e=r.BeginRule(),n=t();return r.CancelRule(e),n},this.ParseInt=function(){var e=r.index,n=r.characterInLineIndex,i=null!==r.ParseString("-");r.ParseCharactersFromString(" \t");var a,o=r.ParseCharactersFromCharSet(t.numbersCharacterSet);return null===o?(r.index=e,r.characterInLineIndex=n,null):Number.isNaN(Number(o))?(r.Error("Failed to read integer value: "+o+". Perhaps it's out of the range of acceptable numbers ink supports? ("+Number.MIN_SAFE_INTEGER+" to "+Number.MAX_SAFE_INTEGER+")"),null):(a=Number(o),i?-a:a)},this.ParseFloat=function(){var e=r.index,n=r.characterInLineIndex,i=r.ParseInt();if(null!==i&&null!==r.ParseString(".")){var a=r.ParseCharactersFromCharSet(t.numbersCharacterSet);return Number("".concat(i,".").concat(a))}return r.index=e,r.characterInLineIndex=n,null},this.ParseNewline=function(){var t=r.BeginRule();return r.ParseString("\r"),null===r.ParseString("\n")?r.FailRule(t):r.SucceedRule(t,"\n")};var i=this.PreProcessInputString(e);this.state=new yt,this._chars=e?i.split(""):[],this.inputString=i}return i(t,[{key:"currentCharacter",get:function(){return this.index>=0&&this.remainingLength>0?this._chars[this.index]:"0"}},{key:"PreProcessInputString",value:function(t){return t}},{key:"endOfInput",get:function(){return this.index>=this._chars.length}},{key:"remainingString",get:function(){return this._chars.slice(this.index,this.index+this.remainingLength).join("")}},{key:"remainingLength",get:function(){return this._chars.length-this.index}},{key:"lineIndex",get:function(){return this.state.lineIndex},set:function(t){this.state.lineIndex=t}},{key:"characterInLineIndex",get:function(){return this.state.characterInLineIndex},set:function(t){this.state.characterInLineIndex=t}},{key:"index",get:function(){return this.state.characterIndex},set:function(t){this.state.characterIndex=t}},{key:"ParseUntil",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=this.BeginRule(),i=new lt;null!==e&&(i.set=new Set([].concat(g(i.set.values()),g(e.set.values())))),null!==n&&(i.set=new Set([].concat(g(i.set.values()),g(n.set.values()))));for(var a="";;){var o=this.ParseUntilCharactersFromCharSet(i);if(o&&(a+=o),null!==this.Peek(t))break;if(this.endOfInput)break;var s=this.currentCharacter;if(null===e||!e.set.has(s))break;a+=s,"\n"===s&&(this.lineIndex+=1,this.characterInLineIndex=-1),this.index+=1,this.characterInLineIndex+=1}return a.length>0?this.SucceedRule(r,String(a)):this.FailRule(r)}}]),t}();St.ParseSuccess=Ct,St.numbersCharacterSet=new lt("0123456789");var bt,wt=function(t){a(r,t);var e=d(r);function r(){var t;return n(this,r),(t=e.apply(this,arguments))._commentOrNewlineStartCharacter=new lt("/\r\n"),t._commentBlockEndCharacter=new lt("*"),t._newlineCharacters=new lt("\n\r"),t.Process=function(){var e=t.Interleave(t.Optional(t.CommentsAndNewlines),t.Optional(t.MainInk));return null!==e?e.join(""):""},t.MainInk=function(){return t.ParseUntil(t.CommentsAndNewlines,t._commentOrNewlineStartCharacter,null)},t.CommentsAndNewlines=function(){var e=t.Interleave(t.Optional(t.ParseNewline),t.Optional(t.ParseSingleComment));return null!==e?e.join(""):null},t.ParseSingleComment=function(){return t.OneOf([t.EndOfLineComment,t.BlockComment])},t.EndOfLineComment=function(){return null===t.ParseString("//")?null:(t.ParseUntilCharactersFromCharSet(t._newlineCharacters),"")},t.BlockComment=function(){if(null===t.ParseString("/*"))return null;var e=t.lineIndex,n=t.ParseUntil(t.String("*/"),t._commentBlockEndCharacter,null);return t.endOfInput||t.ParseString("*/"),null!=n?"\n".repeat(t.lineIndex-e):null},t}return i(r,[{key:"PreProcessInputString",value:function(t){return t}}]),r}(St),kt=function(t){a(r,t);var e=d(r);function r(t,i){var a;return n(this,r),(a=e.call(this)).initialCondition=t,a.branches=i,a._reJoinTarget=null,a.GenerateRuntimeObject=function(){var t=new tt;a.initialCondition&&t.AddContent(a.initialCondition.runtimeObject);var e,n=S(a.branches);try{for(n.s();!(e=n.n()).done;){var r=e.value.runtimeObject;t.AddContent(r)}}catch(t){n.e(t)}finally{n.f()}return null===a.initialCondition||null===a.branches[0].ownExpression||a.branches[a.branches.length-1].isElse||t.AddContent(et.PopEvaluatedValue()),a._reJoinTarget=et.NoOp(),t.AddContent(a._reJoinTarget),t},a.initialCondition&&a.AddContent(a.initialCondition),null!==a.branches&&a.AddContent(a.branches),a}return i(r,[{key:"typeName",get:function(){return"Conditional"}},{key:"ResolveReferences",value:function(t){var e,n=this._reJoinTarget.path,i=S(this.branches);try{for(i.s();!(e=i.n()).done;){var a=e.value;if(!a.returnDivert)throw new Error;a.returnDivert.targetPath=n}}catch(t){i.e(t)}finally{i.f()}p(o(r.prototype),"ResolveReferences",this).call(this,t)}}]),r}(F),Et=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this)).text=t,i.GenerateRuntimeObject=function(){return new $(i.text)},i.toString=function(){return i.text},i}return i(r,[{key:"typeName",get:function(){return"Text"}}]),r}(F),_t=function(t){a(r,t);var e=d(r);function r(t,i){var a;return n(this,r),(a=e.call(this))._expression=null,a.GenerateRuntimeObject=function(){return null},a.constantIdentifier=t,i&&(a._expression=a.AddContent(i)),a}return i(r,[{key:"constantName",get:function(){var t;return null===(t=this.constantIdentifier)||void 0===t?void 0:t.name}},{key:"expression",get:function(){if(!this._expression)throw new Error;return this._expression}},{key:"typeName",get:function(){return"CONST"}},{key:"ResolveReferences",value:function(t){p(o(r.prototype),"ResolveReferences",this).call(this,t),t.CheckForNamingCollisions(this,this.constantIdentifier,ft.Var)}}]),r}(F);!function(t){t[t.Story=0]="Story",t[t.Knot=1]="Knot",t[t.Stitch=2]="Stitch",t[t.WeavePoint=3]="WeavePoint"}(bt||(bt={}));var Tt=function(t){a(r,t);var e=d(r);function r(t,i){var a;return n(this,r),(a=e.call(this)).indentationDepth=i,a.GenerateRuntimeObject=function(){var t=new tt;if(t.name=a.name,a.story.countAllVisits&&(t.visitsShouldBeCounted=!0),t.countingAtStartOnly=!0,a.content){var e,n=S(a.content);try{for(n.s();!(e=n.n()).done;){var r=e.value;t.AddContent(r.runtimeObject)}}catch(t){n.e(t)}finally{n.f()}}return t},a.toString=function(){var t,e;return"- ".concat((null===(t=a.identifier)||void 0===t?void 0:t.name)?"("+(null===(e=a.identifier)||void 0===e?void 0:e.name)+")":"gather")},t&&(a.identifier=t),a}return i(r,[{key:"name",get:function(){var t;return(null===(t=this.identifier)||void 0===t?void 0:t.name)||null}},{key:"runtimeContainer",get:function(){return this.runtimeObject}},{key:"typeName",get:function(){return"Gather"}},{key:"ResolveReferences",value:function(t){p(o(r.prototype),"ResolveReferences",this).call(this,t),this.identifier&&(this.identifier.name||"").length>0&&t.CheckForNamingCollisions(this,this.identifier,ft.SubFlowAndWeave)}}]),r}(F),At=function(){function t(e,r){var i=this;n(this,t),this._dotSeparatedComponents=null,this.toString=function(){return null===i.components||0===i.components.length?i.baseTargetLevel===bt.WeavePoint?"-> ":"":"-> ".concat(i.dotSeparatedComponents)},this.ResolveFromContext=function(t){if(null==i.components||0==i.components.length)return null;var e=i.ResolveBaseTarget(t);return null===e?null:i.components.length>1?i.ResolveTailComponents(e):e},this.ResolveBaseTarget=function(t){for(var e=i.firstComponent,n=t;n;){var r=n===t,a=i.GetChildFromContext(n,e,null,r);if(a)return a;n=n.parent}return null},this.ResolveTailComponents=function(t){var e=t;if(!i.components)return null;for(var n=1;n3&&void 0!==arguments[3]&&arguments[3],i=null===n,a=_(t,zt);if(e&&null!==a&&(i||n===bt.WeavePoint))return a.WeavePointNamed(e);var o=_(t,Ot);if(e&&null!==o){var s=r||o.flowLevel===bt.Knot;return o.ContentWithNameAtLevel(e,n,s)}return null},Object.values(bt).includes(e)?(this._baseTargetLevel=e,this.components=r||[]):Array.isArray(e)?(this._baseTargetLevel=null,this.components=e||[]):(this._baseTargetLevel=null,this.components=[e])}return i(t,[{key:"baseTargetLevel",get:function(){return this.baseLevelIsAmbiguous?bt.Story:this._baseTargetLevel}},{key:"baseLevelIsAmbiguous",get:function(){return!this._baseTargetLevel}},{key:"firstComponent",get:function(){return null!=this.components&&this.components.length?this.components[0].name:null}},{key:"numberOfComponents",get:function(){return this.components?this.components.length:0}},{key:"dotSeparatedComponents",get:function(){return null==this._dotSeparatedComponents&&(this._dotSeparatedComponents=(this.components?this.components:[]).map((function(t){return t.name})).filter(O).join(".")),this._dotSeparatedComponents}},{key:"typeName",get:function(){return"Path"}}]),t}(),Pt=function(t){a(r,t);var e=d(r);function r(){var t,i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;return n(this,r),(t=e.call(this)).returnedExpression=null,t.GenerateRuntimeObject=function(){var e=new tt;return t.returnedExpression?e.AddContent(t.returnedExpression.runtimeObject):(e.AddContent(et.EvalStart()),e.AddContent(new rt),e.AddContent(et.EvalEnd())),e.AddContent(et.PopFunction()),e},i&&(t.returnedExpression=t.AddContent(i)),t}return i(r,[{key:"typeName",get:function(){return"ReturnType"}}]),r}(F);function Nt(t){for(var e=t.parent;e;){if(e.hasOwnProperty("iamFlowbase")&&e.iamFlowbase())return e;e=e.parent}return null}var xt=function(){function t(e){var r=this;n(this,t),this.debugMetadata=null,this.toString=function(){return r.name||"undefined identifer"},this.name=e}return i(t,[{key:"typeName",get:function(){return"Identifier"}}],[{key:"Done",value:function(){return new t("DONE")}}]),t}(),Ot=function(t){a(r,t);var e=d(r);function r(t){var i,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,s=arguments.length>3&&void 0!==arguments[3]&&arguments[3],l=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return n(this,r),(i=e.call(this)).isFunction=s,i._rootWeave=null,i._subFlowsByName=new Map,i._startingSubFlowDivert=null,i._startingSubFlowRuntime=null,i._firstChildFlow=null,i.variableDeclarations=new Map,i.identifier=null,i.args=null,i.iamFlowbase=function(){return!0},i.SplitWeaveAndSubFlowContent=function(t,e){var n,a,o=[],s=[];i._subFlowsByName=new Map;var l,u=S(t);try{for(u.s();!(l=u.n()).done;){var c=l.value,h=_(c,r);h?(null===i._firstChildFlow&&(i._firstChildFlow=h),s.push(c),(null===(n=h.identifier)||void 0===n?void 0:n.name)&&i._subFlowsByName.set(null===(a=h.identifier)||void 0===a?void 0:a.name,h)):o.push(c)}}catch(t){u.e(t)}finally{u.f()}e&&o.push(new Tt(null,1),new jt(new At(xt.Done())));var f=[];return o.length>0&&(i._rootWeave=new zt(o,0),f.push(i._rootWeave)),s.length>0&&f.push.apply(f,s),f},i.ResolveVariableWithName=function(t,e){var n,r={},a=null===e?h(i):Nt(e);if(a){if(null!==a.args){var o,s=S(a.args);try{for(s.s();!(o=s.n()).done;){if((null===(n=o.value.identifier)||void 0===n?void 0:n.name)===t)return r.found=!0,r.isArgument=!0,r.ownerFlow=a,r}}catch(t){s.e(t)}finally{s.f()}}if(a!==i.story&&a.variableDeclarations.has(t))return r.found=!0,r.ownerFlow=a,r.isTemporary=!0,r}return i.story.variableDeclarations.has(t)?(r.found=!0,r.ownerFlow=i.story,r.isGlobal=!0,r):(r.found=!1,r)},i.AddNewVariableDeclaration=function(t){var e=t.variableName;if(i.variableDeclarations.has(e)){var n=i.variableDeclarations.get(e),r="";return n.debugMetadata&&(r=" (".concat(n.debugMetadata,")")),void i.Error("found declaration variable '".concat(e,"' that was already declared").concat(r),t,!1)}i.variableDeclarations.set(t.variableName,t)},i.ResolveWeavePointNaming=function(){i._rootWeave&&i._rootWeave.ResolveWeavePointNaming();var t,e=S(i._subFlowsByName);try{for(e.s();!(t=e.n()).done;){var n=m(t.value,2)[1];n.hasOwnProperty("ResolveWeavePointNaming")&&n.ResolveWeavePointNaming()}}catch(t){e.e(t)}finally{e.f()}},i.GenerateRuntimeObject=function(){var t,e=null;i.isFunction?i.CheckForDisallowedFunctionFlowControl():i.flowLevel!==bt.Knot&&i.flowLevel!==bt.Stitch||null!==(e=i.Find(Pt)())&&i.Error("Return statements can only be used in knots that are declared as functions: == function ".concat(i.identifier," =="),e);var n=new tt;n.name=null===(t=i.identifier)||void 0===t?void 0:t.name,i.story.countAllVisits&&(n.visitsShouldBeCounted=!0),i.GenerateArgumentVariableAssignments(n);for(var a=0;null!==i.content&&a=0;--n){var r=(null===(e=i.args[n].identifier)||void 0===e?void 0:e.name)||null,a=new pt(r,!0);t.AddContent(a)}},i.ContentWithNameAtLevel=function(t){var e,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if((n===i.flowLevel||null===n)&&t===(null===(e=i.identifier)||void 0===e?void 0:e.name))return h(i);if(n===bt.WeavePoint||null===n){var a=null;if(i._rootWeave&&(a=i._rootWeave.WeavePointNamed(t)))return a;if(n===bt.WeavePoint)return r?i.DeepSearchForAnyLevelContent(t):null}if(null!==n&&n' returns it won't have anywhere to go.")),i.Warning(e,t)},i.toString=function(){return"".concat(i.typeName," '").concat(i.identifier,"'")},i.identifier=t,i.args=o,null===a&&(a=[]),i.PreProcessTopLevelObjects(a),a=i.SplitWeaveAndSubFlowContent(a,"Story"==i.GetType()&&!l),i.AddContent(a),i}return i(r,[{key:"hasParameters",get:function(){return null!==this.args&&this.args.length>0}},{key:"subFlowsByName",get:function(){return this._subFlowsByName}},{key:"typeName",get:function(){return this.isFunction?"Function":String(this.flowLevel)}},{key:"name",get:function(){var t;return(null===(t=this.identifier)||void 0===t?void 0:t.name)||null}},{key:"PreProcessTopLevelObjects",value:function(t){}},{key:"ResolveReferences",value:function(t){var e,n;if(this._startingSubFlowDivert){if(!this._startingSubFlowRuntime)throw new Error;this._startingSubFlowDivert.targetPath=this._startingSubFlowRuntime.path}if(p(o(r.prototype),"ResolveReferences",this).call(this,t),null!==this.args){var i,a=S(this.args);try{for(a.s();!(i=a.n()).done;){var s=i.value;t.CheckForNamingCollisions(this,s.identifier,ft.Arg,"argument")}}catch(t){a.e(t)}finally{a.f()}for(var l=0;l=0;--t){var e=_(i.content[t],Et);if(null===e)break;if(e.text=e.text.replace(new RegExp(/[ \t]/g),""),0!==e.text.length)break;i.content.splice(t,1)}},i.GenerateRuntimeObject=function(){var t=new tt;if(null!==i.content){var e,n=S(i.content);try{for(n.s();!(e=n.n()).done;){var r=e.value.runtimeObject;r&&t.AddContent(r)}}catch(t){n.e(t)}finally{n.f()}}return i.dontFlatten&&i.story.DontFlattenContainer(t),t},i.toString=function(){return"ContentList(".concat(i.content.join(", "),")")},t&&i.AddContent(t);for(var a=arguments.length,o=new Array(a>1?a-1:0),s=1;s0&&void 0!==arguments[0]?arguments[0]:null;return n(this,r),(t=e.call(this)).pathForCount=null,t.name=i,t}return i(r,[{key:"containerForCount",get:function(){return null===this.pathForCount?null:this.ResolvePath(this.pathForCount).container}},{key:"pathStringForCount",get:function(){return null===this.pathForCount?null:this.CompactPathString(this.pathForCount)},set:function(t){this.pathForCount=null===t?null:new R(t)}},{key:"toString",value:function(){return null!=this.name?"var("+this.name+")":"read_count("+this.pathStringForCount+")"}}]),r}(V),Wt=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this)).pathIdentifiers=t,i._runtimeVarRef=null,i.isConstantReference=!1,i.isListItemReference=!1,i.GenerateIntoContainer=function(t){var e=i.story.constants.get(i.name);if(e)return e.GenerateConstantIntoContainer(t),void(i.isConstantReference=!0);if(i._runtimeVarRef=new Ft(i.name),1===i.path.length||2===i.path.length){var n="",r="";1===i.path.length?n=i.path[0]:(r=i.path[0],n=i.path[1]),i.story.ResolveListItem(r,n,h(i))&&(i.isListItemReference=!0)}t.AddContent(i._runtimeVarRef)},i.toString=function(){return"{".concat(i.path.join("."),"}")},i}return i(r,[{key:"name",get:function(){return this.path.join(".")}},{key:"path",get:function(){return this.pathIdentifiers.map((function(t){return t.name})).filter(O)}},{key:"identifier",get:function(){if(!this.pathIdentifiers||0==this.pathIdentifiers.length)return null;var t=this.path.join(".");return new xt(t)}},{key:"runtimeVarRef",get:function(){return this._runtimeVarRef}},{key:"typeName",get:function(){return"ref"}},{key:"ResolveReferences",value:function(t){if(p(o(r.prototype),"ResolveReferences",this).call(this,t),!this.isConstantReference&&!this.isListItemReference){var e=new At(this.pathIdentifiers),n=e.ResolveFromContext(this);if(n){if(!n.containerForCounting)throw new Error;if(n.containerForCounting.visitsShouldBeCounted=!0,null===this._runtimeVarRef)return;this._runtimeVarRef.pathForCount=n.runtimePath,this._runtimeVarRef.name=null;var i=_(n,Ot);i&&i.isFunction&&(this.parent instanceof zt||this.parent instanceof It||this.parent instanceof Ot)&&this.Warning("'".concat(i.identifier,"' being used as read count rather than being called as function. Perhaps you intended to write ").concat(i.identifier,"()"))}else{if(this.path.length>1){var a="Could not find target for read count: ".concat(e);return this.path.length<=2&&(a+=", or couldn't find list item with the name ".concat(this.path.join(","))),void this.Error(a)}t.ResolveVariableWithName(this.name,this).found||this.Error("Unresolved variable: ".concat(this.name),this)}}}}]),r}(nt),Rt=function(t){a(r,t);var e=d(r);function r(t,i){var a;return n(this,r),(a=e.call(this))._divertTargetToCount=null,a._variableReferenceToCount=null,a.shouldPopReturnedValue=!1,a.GenerateIntoContainer=function(t){var e=a.story.ResolveList(a.name),n=!1;if(a.isChoiceCount)a.args.length>0&&a.Error("The CHOICE_COUNT() function shouldn't take any arguments"),t.AddContent(et.ChoiceCount());else if(a.isTurns)a.args.length>0&&a.Error("The TURNS() function shouldn't take any arguments"),t.AddContent(et.Turns());else if(a.isTurnsSince||a.isReadCount){var r=_(a.args[0],Vt),i=_(a.args[0],Wt);if(1!==a.args.length||null===r&&null===i)return void a.Error("The ".concat(a.name,"() function should take one argument: a divert target to the target knot, stitch, gather or choice you want to check. e.g. TURNS_SINCE(-> myKnot)"));r?(a._divertTargetToCount=r,a.AddContent(a._divertTargetToCount),a._divertTargetToCount.GenerateIntoContainer(t)):i&&(a._variableReferenceToCount=i,a.AddContent(a._variableReferenceToCount),a._variableReferenceToCount.GenerateIntoContainer(t)),a.isTurnsSince?t.AddContent(et.TurnsSince()):t.AddContent(et.ReadCount())}else if(a.isRandom){2!==a.args.length&&a.Error("RANDOM should take 2 parameters: a minimum and a maximum integer");for(var o=0;o1&&(f+="s"),a.Error(f)}for(var d=0;d1&&a.Error("Can currently only construct a list from one integer (or an empty list from a given list definition)"),1===a.args.length)t.AddContent(new $(a.name)),a.args[0].GenerateIntoContainer(t),t.AddContent(et.ListFromInt());else{var v=new M;v.SetInitialOriginName(a.name),t.AddContent(new Z(v))}else t.AddContent(a._proxyDivert.runtimeObject),n=!0;n||a.content.splice(a.content.indexOf(a._proxyDivert),1),a.shouldPopReturnedValue&&t.AddContent(et.PopEvaluatedValue())},a.toString=function(){var t=a.args.join(", ");return"".concat(a.name,"(").concat(t,")")},a._proxyDivert=new jt(new At(t),i),a._proxyDivert.isFunctionCall=!0,a.AddContent(a._proxyDivert),a}return i(r,[{key:"proxyDivert",get:function(){return this._proxyDivert}},{key:"name",get:function(){return this._proxyDivert.target.firstComponent||""}},{key:"args",get:function(){return this._proxyDivert.args}},{key:"runtimeDivert",get:function(){return this._proxyDivert.runtimeDivert}},{key:"isChoiceCount",get:function(){return"CHOICE_COUNT"===this.name}},{key:"isTurns",get:function(){return"TURNS"===this.name}},{key:"isTurnsSince",get:function(){return"TURNS_SINCE"===this.name}},{key:"isRandom",get:function(){return"RANDOM"===this.name}},{key:"isSeedRandom",get:function(){return"SEED_RANDOM"===this.name}},{key:"isListRange",get:function(){return"LIST_RANGE"===this.name}},{key:"isListRandom",get:function(){return"LIST_RANDOM"===this.name}},{key:"isReadCount",get:function(){return"READ_COUNT"===this.name}},{key:"typeName",get:function(){return"FunctionCall"}},{key:"ResolveReferences",value:function(t){if(p(o(r.prototype),"ResolveReferences",this).call(this,t),!this.content.includes(this._proxyDivert)&&null!==this.args){var e,n=S(this.args);try{for(n.s();!(e=n.n()).done;){e.value.ResolveReferences(t)}}catch(t){n.e(t)}finally{n.f()}}if(this._divertTargetToCount){var i=this._divertTargetToCount.divert,a=null!=i.runtimeDivert.variableDivertName;if(a)return void this.Error("When getting the TURNS_SINCE() of a variable target, remove the '->' - i.e. it should just be TURNS_SINCE(".concat(i.runtimeDivert.variableDivertName,")"));var s=i.targetContent;if(null===s)a||this.Error("Failed to find target for TURNS_SINCE: '".concat(i.target,"'"));else{if(!s.containerForCounting)throw new Error;s.containerForCounting.turnIndexShouldBeCounted=!0}}else if(this._variableReferenceToCount){var l=this._variableReferenceToCount.runtimeVarRef;if(!l)throw new Error;null!==l.pathForCount&&this.Error("Should be '".concat(name,"'(-> '").concat(this._variableReferenceToCount.name,"). Usage without the '->' only makes sense for variable targets."))}}}]),r}(nt);Rt.IsBuiltIn=function(t){return!!it.CallExistsWithName(t)||("CHOICE_COUNT"===t||"TURNS_SINCE"===t||"TURNS"===t||"RANDOM"===t||"SEED_RANDOM"===t||"LIST_VALUE"===t||"LIST_RANDOM"===t||"READ_COUNT"===t)};var Dt,Lt=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this)).GenerateIntoContainer=function(t){var e,n=!0,r=S(i.subExpressions);try{for(r.s();!(e=r.n()).done;){e.value.GenerateIntoContainer(t),n||t.AddContent(it.CallWithName("&&")),n=!1}}catch(t){r.e(t)}finally{r.f()}},i.AddContent(t),i}return i(r,[{key:"subExpressions",get:function(){return this.content}},{key:"typeName",get:function(){return"MultipleConditionExpression"}}]),r}(nt),Vt=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this))._runtimeDivert=null,i._runtimeDivertTargetValue=null,i.GenerateIntoContainer=function(t){i.divert.GenerateRuntimeObject(),i._runtimeDivert=i.divert.runtimeDivert,i._runtimeDivertTargetValue=new X,t.AddContent(i.runtimeDivertTargetValue)},i.Equals=function(t){var e=_(t,r);return!!(e&&i.divert.target&&e.divert.target)&&i.divert.target.dotSeparatedComponents===e.divert.target.dotSeparatedComponents},i.divert=i.AddContent(t),i}return i(r,[{key:"runtimeDivert",get:function(){if(!this._runtimeDivert)throw new Error;return this._runtimeDivert}},{key:"runtimeDivertTargetValue",get:function(){if(!this._runtimeDivertTargetValue)throw new Error;return this._runtimeDivertTargetValue}},{key:"typeName",get:function(){return"DivertTarget"}},{key:"ResolveReferences",value:function(t){if(p(o(r.prototype),"ResolveReferences",this).call(this,t),this.divert.isDone||this.divert.isEnd)this.Error("Can't use -> DONE or -> END as variable divert targets",this);else{for(var e=this;e&&e instanceof nt;){var n=!1,i=!1,a=e.parent;if(a instanceof st){var s=a;"=="!==s.opName&&"!="!==s.opName?n=!0:(s.leftExpression instanceof r||s.leftExpression instanceof Wt)&&(s.rightExpression instanceof r||s.rightExpression instanceof Wt)||(n=!0),i=!0}else if(a instanceof Rt){var l=a;l.isTurnsSince||l.isReadCount||(n=!0),i=!0}else(a instanceof nt||a instanceof Lt||a instanceof mt&&a.condition===e||a instanceof kt||a instanceof $t)&&(n=!0,i=!0);if(n&&this.Error("Can't use a divert target like that. Did you intend to call '".concat(this.divert.target,"' as a function: likeThis(), or check the read count: likeThis, with no arrows?"),this),i)break;e=a}if(this.runtimeDivert.hasVariableTarget){if(!this.divert.target)throw new Error;this.Error("Since '".concat(this.divert.target.dotSeparatedComponents,"' is a variable, it shouldn't be preceded by '->' here."))}this.runtimeDivert.targetPath&&(this.runtimeDivertTargetValue.targetPath=this.runtimeDivert.targetPath);var u=this.divert.targetContent;if(null!==u){var c=u.containerForCounting;if(null!==c){var h=_(this.parent,Rt);h&&h.isTurnsSince||(c.visitsShouldBeCounted=!0),c.turnIndexShouldBeCounted=!0}var f=_(u,Ot);if(null!=f&&null!==f.args){var d,v=S(f.args);try{for(v.s();!(d=v.n()).done;){var m=d.value;m.isByReference&&this.Error("Can't store a divert target to a knot or function that has by-reference arguments ('".concat(f.identifier,"' has 'ref ").concat(m.identifier,"')."))}}catch(t){v.e(t)}finally{v.f()}}}}}}]),r}(nt),jt=function(t){a(r,t);var e=d(r);function r(t,i){var a;return n(this,r),(a=e.call(this)).args=[],a.target=null,a.targetContent=null,a._runtimeDivert=null,a.isFunctionCall=!1,a.isEmpty=!1,a.isTunnel=!1,a.isThread=!1,a.GenerateRuntimeObject=function(){if(a.isEnd)return et.End();if(a.isDone)return et.Done();a.runtimeDivert=new vt,a.ResolveTargetContent(),a.CheckArgumentValidity();var t=null!==a.args&&a.args.length>0;if(t||a.isFunctionCall||a.isTunnel||a.isThread){var e=new tt;if(t){a.isFunctionCall||e.AddContent(et.EvalStart());var n=null;a.targetContent&&(n=a.targetContent.args);for(var r=0;r ").concat(r.identifier),n.ownerFlow)}return void(a.runtimeDivert.variableDivertName=t)}}}if(!a.target)throw new Error;a.targetContent=a.target.ResolveFromContext(h(a))}},a.CheckArgumentValidity=function(){if(!a.isEmpty){var t=0;if(null!==a.args&&a.args.length>0&&(t=a.args.length),null!==a.targetContent){var e=_(a.targetContent,Ot);if(0!==t||null!==e&&e.hasParameters)if(null===e&&t>0)a.Error("target needs to be a knot or stitch in order to pass arguments");else if(null!==e&&(null===e.args||!e.args&&t>0))a.Error("target (".concat(e.name,") doesn't take parameters"));else if(a.parent instanceof Vt)t>0&&a.Error("can't store arguments in a divert target variable");else{var n,r=e.args.length;if(r!==t)return n=0===t?"but there weren't any passed to it":t ").concat(o.identifier," but saw ").concat(s),s)}}null!==e||a.Error("Can't call as a function or with arguments unless it's a knot or stitch")}}}},a.CheckExternalArgumentValidity=function(t){var e=a.target?a.target.firstComponent:null,n=t.externals.get(e);if(!n)throw new Error("external not found");var r=n.argumentNames.length,i=0;a.args&&(i=a.args.length),i!==r&&a.Error("incorrect number of arguments sent to external function '".concat(e,"'. Expected ").concat(r," but got ").concat(i))},a.toString=function(){var t="";return null===a.target?"-> ":(t+=a.target.toString(),a.isTunnel&&(t+=" ->"),a.isFunctionCall&&(t+=" ()"),t)},t&&(a.target=t),i&&(a.args=i,a.AddContent(i)),a}return i(r,[{key:"runtimeDivert",get:function(){if(!this._runtimeDivert)throw new Error;return this._runtimeDivert},set:function(t){this._runtimeDivert=t}},{key:"isEnd",get:function(){return Boolean(this.target&&"END"===this.target.dotSeparatedComponents)}},{key:"isDone",get:function(){return Boolean(this.target&&"DONE"===this.target.dotSeparatedComponents)}},{key:"typeName",get:function(){return"Divert"}},{key:"ResolveReferences",value:function(t){if(!(this.isEmpty||this.isEnd||this.isDone)){if(!this.runtimeDivert)throw new Error;this.targetContent&&(this.runtimeDivert.targetPath=this.targetContent.runtimePath),p(o(r.prototype),"ResolveReferences",this).call(this,t);var e=_(this.targetContent,Ot);e&&(!e.isFunction&&this.isFunctionCall?p(o(r.prototype),"Error",this).call(this,"".concat(e.identifier," hasn't been marked as a function, but it's being called as one. Do you need to delcare the knot as '== function ").concat(e.identifier," =='?")):!e.isFunction||this.isFunctionCall||this.parent instanceof Vt||p(o(r.prototype),"Error",this).call(this,e.identifier+" can't be diverted to. It can only be called as a function since it's been marked as such: '"+e.identifier+"(...)'"));var n=null!==this.targetContent,i=!1,a=!1;if(!this.target)throw new Error;if(1===this.target.numberOfComponents){if(!this.target.firstComponent)throw new Error;if(i=Rt.IsBuiltIn(this.target.firstComponent),a=t.IsExternal(this.target.firstComponent),i||a)return this.isFunctionCall||p(o(r.prototype),"Error",this).call(this,"".concat(this.target.firstComponent," must be called as a function: ~ ").concat(this.target.firstComponent,"()")),void(a&&(this.runtimeDivert.isExternal=!0,null!==this.args&&(this.runtimeDivert.externalArgs=this.args.length),this.runtimeDivert.pushesToStack=!1,this.runtimeDivert.targetPath=new R(this.target.firstComponent),this.CheckExternalArgumentValidity(t)))}null==this.runtimeDivert.variableDivertName&&(n||i||a||this.Error("target not found: '".concat(this.target,"'")))}}},{key:"Error",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];e!==this&&e?p(o(r.prototype),"Error",this).call(this,t,e):this.isFunctionCall?p(o(r.prototype),"Error",this).call(this,"Function call ".concat(t),e,n):p(o(r.prototype),"Error",this).call(this,"Divert ".concat(t),e,n)}}]),r}(F),Bt=i((function t(e,r){n(this,t),this.divert=e,this.targetRuntimeObj=r})),Mt=i((function t(e,r){n(this,t),this.divert=e,this.targetContent=r}));!function(t){t[t.Stopping=1]="Stopping",t[t.Cycle=2]="Cycle",t[t.Shuffle=4]="Shuffle",t[t.Once=8]="Once"}(Dt||(Dt={}));var Gt,qt=function(t){a(r,t);var e=d(r);function r(t,i){var a;n(this,r),(a=e.call(this)).sequenceType=i,a._sequenceDivertsToResolve=[],a.GenerateRuntimeObject=function(){var t=new tt;t.visitsShouldBeCounted=!0,t.countingAtStartOnly=!0,a._sequenceDivertsToResolve=[],t.AddContent(et.EvalStart()),t.AddContent(et.VisitIndex());var e=(a.sequenceType&Dt.Once)>0,n=(a.sequenceType&Dt.Cycle)>0,r=(a.sequenceType&Dt.Stopping)>0,i=(a.sequenceType&Dt.Shuffle)>0,o=a.sequenceElements.length;if(e&&(o+=1),r||e?(t.AddContent(new J(o-1)),t.AddContent(it.CallWithName("MIN"))):n&&(t.AddContent(new J(a.sequenceElements.length)),t.AddContent(it.CallWithName("%"))),i){var s=et.NoOp();if(e||r){var l=r?a.sequenceElements.length-1:a.sequenceElements.length;t.AddContent(et.Duplicate()),t.AddContent(new J(l)),t.AddContent(it.CallWithName("=="));var u=new vt;u.isConditional=!0,t.AddContent(u),a.AddDivertToResolve(u,s)}var c=a.sequenceElements.length;r&&(c-=1),t.AddContent(new J(c)),t.AddContent(et.SequenceShuffleIndex()),(e||r)&&t.AddContent(s)}t.AddContent(et.EvalEnd());for(var h=et.NoOp(),f=0;f0){for(var a=-1,o=-1,s=0;s ".concat(t._divertAfter)},t}return i(r,[{key:"divertAfter",get:function(){return this._divertAfter},set:function(t){this._divertAfter=t,this._divertAfter&&this.AddContent(this._divertAfter)}},{key:"typeName",get:function(){return"TunnelOnwards"}},{key:"ResolveReferences",value:function(t){p(o(r.prototype),"ResolveReferences",this).call(this,t),this.divertAfter&&this.divertAfter.targetContent&&(this._overrideDivertTarget.targetPath=this.divertAfter.targetContent.runtimePath)}}]),r}(F),Kt=function(){function t(e,r){n(this,t),this._name=e||"",this._items=null,this._itemNameToValues=r||new Map}return i(t,[{key:"name",get:function(){return this._name}},{key:"items",get:function(){if(null==this._items){this._items=new Map;var t,e=S(this._itemNameToValues);try{for(e.s();!(t=e.n()).done;){var n=m(t.value,2),r=n[0],i=n[1],a=new B(this.name,r);this._items.set(a.serialized(),i)}}catch(t){e.e(t)}finally{e.f()}}return this._items}},{key:"ValueForItem",value:function(t){if(!t.itemName)return 0;var e=this._itemNameToValues.get(t.itemName);return void 0!==e?e:0}},{key:"ContainsItem",value:function(t){return!!t.itemName&&(t.originName==this.name&&this._itemNameToValues.has(t.itemName))}},{key:"ContainsItemWithName",value:function(t){return this._itemNameToValues.has(t)}},{key:"TryGetItemWithValue",value:function(t,e){var n,r=S(this._itemNameToValues);try{for(r.s();!(n=r.n()).done;){var i=m(n.value,2),a=i[0];if(i[1]==t)return{result:new B(this.name,a),exists:!0}}}catch(t){r.e(t)}finally{r.f()}return{result:B.Null,exists:!1}}},{key:"TryGetValueForItem",value:function(t,e){if(!t.itemName)return{result:0,exists:!1};var n=this._itemNameToValues.get(t.itemName);return n?{result:n,exists:!0}:{result:0,exists:!1}}}]),t}(),Ht=function(t){a(r,t);var e=d(r);function r(t){var i;n(this,r),(i=e.call(this)).itemDefinitions=t,i.identifier=null,i.variableAssignment=null,i._elementsByName=null,i.ItemNamed=function(t){if(null===i._elementsByName){i._elementsByName=new Map;var e,n=S(i.itemDefinitions);try{for(n.s();!(e=n.n()).done;){var r=e.value;i._elementsByName.set(r.name,r)}}catch(t){n.e(t)}finally{n.f()}}return i._elementsByName.get(t)||null},i.GenerateRuntimeObject=function(){var t,e,n,r=new M,a=S(i.itemDefinitions);try{for(a.s();!(n=a.n()).done;){var o=n.value;if(o.inInitialList){var s=new B((null===(t=i.identifier)||void 0===t?void 0:t.name)||null,o.name||null);r.Add(s,o.seriesValue)}}}catch(t){a.e(t)}finally{a.f()}return r.SetInitialOriginName((null===(e=i.identifier)||void 0===e?void 0:e.name)||""),new Z(r)};var a,o=1,s=S(i.itemDefinitions);try{for(s.s();!(a=s.n()).done;){var l=a.value;null!==l.explicitValue&&(o=l.explicitValue),l.seriesValue=o,o+=1}}catch(t){s.e(t)}finally{s.f()}return i.AddContent(t),i}return i(r,[{key:"typeName",get:function(){return"ListDefinition"}},{key:"runtimeListDefinition",get:function(){var t,e,n=new Map,r=S(this.itemDefinitions);try{for(r.s();!(e=r.n()).done;){var i=e.value;n.has(i.name)?this.Error("List '".concat(this.identifier,"' contains duplicate items called '").concat(i.name,"'")):n.set(i.name,i.seriesValue)}}catch(t){r.e(t)}finally{r.f()}return new Kt((null===(t=this.identifier)||void 0===t?void 0:t.name)||"",n)}},{key:"ResolveReferences",value:function(t){p(o(r.prototype),"ResolveReferences",this).call(this,t),t.CheckForNamingCollisions(this,this.identifier,ft.List)}}]),r}(F),Jt=function(t){a(r,t);var e=d(r);function r(t){var i,a=t.assignedExpression,o=t.isGlobalDeclaration,s=t.isTemporaryNewDeclaration,l=t.listDef,u=t.variableIdentifier;return n(this,r),(i=e.call(this))._runtimeAssignment=null,i.expression=null,i.listDefinition=null,i.GenerateRuntimeObject=function(){var t=null;if(i.isGlobalDeclaration?t=i.story:i.isNewTemporaryDeclaration&&(t=Nt(h(i))),t&&t.AddNewVariableDeclaration(h(i)),i.isGlobalDeclaration)return null;var e=new tt;return i.expression?e.AddContent(i.expression.runtimeObject):i.listDefinition&&e.AddContent(i.listDefinition.runtimeObject),i._runtimeAssignment=new pt(i.variableName,i.isNewTemporaryDeclaration),e.AddContent(i._runtimeAssignment),e},i.toString=function(){return"".concat(i.isGlobalDeclaration?"VAR":i.isNewTemporaryDeclaration?"~ temp":""," ").concat(i.variableName)},i.variableIdentifier=u,i.isGlobalDeclaration=Boolean(o),i.isNewTemporaryDeclaration=Boolean(s),l instanceof Ht?(i.listDefinition=i.AddContent(l),i.listDefinition.variableAssignment=h(i),i.isGlobalDeclaration=!0):a&&(i.expression=i.AddContent(a)),i}return i(r,[{key:"variableName",get:function(){return this.variableIdentifier.name}},{key:"typeName",get:function(){return this.isNewTemporaryDeclaration?"temp":this.isGlobalDeclaration?null!==this.listDefinition?"LIST":"VAR":"variable assignment"}},{key:"isDeclaration",get:function(){return this.isGlobalDeclaration||this.isNewTemporaryDeclaration}},{key:"ResolveReferences",value:function(t){if(p(o(r.prototype),"ResolveReferences",this).call(this,t),this.isDeclaration&&null===this.listDefinition&&t.CheckForNamingCollisions(this,this.variableIdentifier,this.isGlobalDeclaration?ft.Var:ft.Temp),this.isGlobalDeclaration){var e=_(this.expression,Wt);!e||e.isConstantReference||e.isListItemReference||this.Error("global variable assignments cannot refer to other variables, only literal values, constants and list items")}if(!this.isNewTemporaryDeclaration){var n=t.ResolveVariableWithName(this.variableName,this);n.found||(this.variableName in this.story.constants?this.Error("Can't re-assign to a constant (do you need to use VAR when declaring '".concat(this.variableName,"'?)"),this):this.Error("Variable could not be found to assign to: '".concat(this.variableName,"'"),this)),this._runtimeAssignment&&(this._runtimeAssignment.isGlobal=n.isGlobal)}}}]),r}(F),zt=function(t){a(r,t);var e=d(r);function r(t){var i,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;return n(this,r),(i=e.call(this)).previousWeavePoint=null,i.addContentToPreviousWeavePoint=!1,i.hasSeenChoiceInSection=!1,i.currentContainer=null,i._unnamedGatherCount=0,i._choiceCount=0,i._rootContainer=null,i._namedWeavePoints=new Map,i.looseEnds=[],i.gatherPointsToResolve=[],i.ResolveWeavePointNaming=function(){var t,e,n,r=[].concat(g(i.FindAll(Tt)((function(t){return!(null===t.name||void 0===t.name)}))),g(i.FindAll(mt)((function(t){return!(null===t.name||void 0===t.name)}))));i._namedWeavePoints=new Map;var a,o=S(r);try{for(o.s();!(a=o.n()).done;){var s=a.value,l=i.namedWeavePoints.get((null===(t=s.identifier)||void 0===t?void 0:t.name)||"");if(l){var u=l instanceof Tt?"gather":"choice",c=l;i.Error("A ".concat(u," with the same label name '").concat(s.name,"' already exists in this context on line ").concat(c.debugMetadata?c.debugMetadata.startLineNumber:"NO DEBUG METADATA AVAILABLE"),s)}(null===(e=s.identifier)||void 0===e?void 0:e.name)&&i.namedWeavePoints.set(null===(n=s.identifier)||void 0===n?void 0:n.name,s)}}catch(t){o.e(t)}finally{o.f()}},i.ConstructWeaveHierarchyFromIndentation=function(){for(var t=0;ti.baseIndentIndex){for(var a=t;t=0;s-=1){var l=i.looseEnds[s],u=!1;if(n){if(l instanceof mt&&null!==t)t.ReceiveLooseEnd(l),u=!0;else if(!(l instanceof mt)){var c=t||e;null!==c&&(c.ReceiveLooseEnd(l),u=!0)}}else(null==t?void 0:t.hasOwnProperty("ReceiveLooseEnd"))&&t.ReceiveLooseEnd(l),u=!0;u&&i.looseEnds.splice(s,1)}}},i.ReceiveLooseEnd=function(t){i.looseEnds.push(t)},i.WeavePointNamed=function(t){if(!i.namedWeavePoints)return null;var e=i.namedWeavePoints.get(t);return e||null},i.IsGlobalDeclaration=function(t){var e=_(t,Jt);return!!(e&&e.isGlobalDeclaration&&e.isDeclaration)||!!_(t,_t)},i.ContentThatFollowsWeavePoint=function(t){var e=[],n=t;if(null!==n.content){var a,o=S(n.content);try{for(o.s();!(a=o.n()).done;){var s=a.value;i.IsGlobalDeclaration(s)||e.push(s)}}catch(t){o.e(t)}finally{o.f()}}var l=_(n.parent,r);if(null===l)throw new Error("Expected weave point parent to be weave?");for(var u=l.content.indexOf(n)+1;u0){var e,n=S(i.looseEnds);try{for(n.s();!(e=n.n()).done;){var r=e.value,a=i.ContentThatFollowsWeavePoint(r);i.ValidateFlowOfObjectsTerminates(a,r,t)}}catch(t){n.e(t)}finally{n.f()}}else{var o,s=S(i.content);try{for(s.s();!(o=s.n()).done;){var l=o.value;if(l instanceof mt||l instanceof jt)return}}catch(t){s.e(t)}finally{s.f()}i.ValidateFlowOfObjectsTerminates(i.content,h(i),t)}},i.BadNestedTerminationHandler=function(t){for(var e=null,n=t.parent;null!==n;n=n.parent)if(n instanceof qt||n instanceof kt){e=_(n,kt);break}var r="Choices nested in conditionals or sequences need to explicitly divert afterwards.";null!==e&&(1===e.FindAll(mt)().length&&(r="Choices with conditions should be written: '* {condition} choice'. Otherwise, ".concat(r.toLowerCase())));i.Error(r,t)},i.ValidateFlowOfObjectsTerminates=function(t,e,n){var r,i=!1,a=e,o=S(t);try{for(o.s();!(r=o.n()).done;){var s=r.value;if(null!==s.Find(jt)((function(t){return!(t.isThread||t.isTunnel||t.isFunctionCall||t.parent instanceof Vt)}))&&(i=!0),null!=s.Find(Ut)()){i=!0;break}a=s}}catch(t){o.e(t)}finally{o.f()}if(!i){if(a instanceof W)return;n(a)}},i.WeavePointHasLooseEnd=function(t){if(null===t.content)return!0;for(var e=t.content.length-1;e>=0;--e){var n=_(t.content[e],jt);if(n)if(!(n.isThread||n.isTunnel||n.isFunctionCall))return!1}return!0},i.CheckForWeavePointNamingCollisions=function(){if(i.namedWeavePoints){var t,e=[],n=S(i.ancestry);try{for(n.s();!(t=n.n()).done;){var r=_(t.value,Ot);if(!r)break;e.push(r)}}catch(t){n.e(t)}finally{n.f()}var a,o=S(i.namedWeavePoints);try{for(o.s();!(a=o.n()).done;){var s,l=m(a.value,2),u=l[0],c=l[1],h=S(e);try{for(h.s();!(s=h.n()).done;){var f=s.value.ContentWithNameAtLevel(u);if(f&&f!==c){var d="".concat(c.GetType()," '").concat(u,"' has the same label name as a ").concat(f.GetType()," (on ").concat(f.debugMetadata,")");i.Error(d,c)}}}catch(t){h.e(t)}finally{h.f()}}}catch(t){o.e(t)}finally{o.f()}}},i.baseIndentIndex=-1==a?i.DetermineBaseIndentationFromContent(t):a,i.AddContent(t),i.ConstructWeaveHierarchyFromIndentation(),i}return i(r,[{key:"rootContainer",get:function(){return this._rootContainer||(this._rootContainer=this.GenerateRuntimeObject()),this._rootContainer}},{key:"namedWeavePoints",get:function(){return this._namedWeavePoints}},{key:"lastParsedSignificantObject",get:function(){if(0===this.content.length)return null;for(var t=null,e=this.content.length-1;e>=0;--e){var n=_(t=this.content[e],Et);if((!n||"\n"!==n.text)&&!this.IsGlobalDeclaration(t))break}var i=_(t,r);return i&&(t=i.lastParsedSignificantObject),t}},{key:"typeName",get:function(){return"Weave"}},{key:"ResolveReferences",value:function(t){if(p(o(r.prototype),"ResolveReferences",this).call(this,t),null!==this.looseEnds&&this.looseEnds.length>0){for(var e=!1,n=this.parent;null!==n;n=n.parent)if(n instanceof qt||n instanceof kt){e=!0;break}e&&this.ValidateTermination(this.BadNestedTerminationHandler)}var i,a=S(this.gatherPointsToResolve);try{for(a.s();!(i=a.n()).done;){var s=i.value;s.divert.targetPath=s.targetRuntimeObj.path}}catch(t){a.e(t)}finally{a.f()}this.CheckForWeavePointNamingCollisions()}}]),r}(F),$t=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this))._contentContainer=null,i._conditionalDivert=null,i._ownExpression=null,i._innerWeave=null,i.isTrueBranch=!1,i.matchingEquality=!1,i.isElse=!1,i.isInline=!1,i.returnDivert=null,i.GenerateRuntimeObject=function(){if(i._innerWeave){var t,e=S(i._innerWeave.content);try{for(e.s();!(t=e.n()).done;){var n=_(t.value,Et);n&&n.text.startsWith("else:")&&i.Warning("Saw the text 'else:' which is being treated as content. Did you mean '- else:'?",n)}}catch(t){e.e(t)}finally{e.f()}}var r=new tt,a=i.matchingEquality&&!i.isElse;if(a&&r.AddContent(et.Duplicate()),i._conditionalDivert=new vt,i._conditionalDivert.isConditional=!i.isElse,!i.isTrueBranch&&!i.isElse){var o=null!==i.ownExpression;o&&r.AddContent(et.EvalStart()),i.ownExpression&&i.ownExpression.GenerateIntoContainer(r),i.matchingEquality&&r.AddContent(it.CallWithName("==")),o&&r.AddContent(et.EvalEnd())}return r.AddContent(i._conditionalDivert),i._contentContainer=i.GenerateRuntimeForContent(),i._contentContainer.name="b",i.isInline||i._contentContainer.InsertContent(new $("\n"),0),(a||i.isElse&&i.matchingEquality)&&i._contentContainer.InsertContent(et.PopEvaluatedValue(),0),r.AddToNamedContentOnly(i._contentContainer),i.returnDivert=new vt,i._contentContainer.AddContent(i.returnDivert),r},i.GenerateRuntimeForContent=function(){return null===i._innerWeave?new tt:i._innerWeave.rootContainer},t&&(i._innerWeave=new zt(t),i.AddContent(i._innerWeave)),i}return i(r,[{key:"ownExpression",get:function(){return this._ownExpression},set:function(t){this._ownExpression=t,this._ownExpression&&this.AddContent(this._ownExpression)}},{key:"typeName",get:function(){return"ConditionalSingleBranch"}},{key:"ResolveReferences",value:function(t){if(!this._conditionalDivert||!this._contentContainer)throw new Error;this._conditionalDivert.targetPath=this._contentContainer.path,p(o(r.prototype),"ResolveReferences",this).call(this,t)}}]),r}(F);!function(t){t[t.ParsingString=1]="ParsingString",t[t.TagActive=2]="TagActive"}(Gt||(Gt={}));var Xt,Yt=function(){function t(){n(this,t),this.startLineNumber=0,this.endLineNumber=0,this.startCharacterNumber=0,this.endCharacterNumber=0,this.fileName=null,this.sourceName=null}return i(t,[{key:"Merge",value:function(e){var n=new t;return n.fileName=this.fileName,n.sourceName=this.sourceName,this.startLineNumbere.startLineNumber?(n.startLineNumber=e.startLineNumber,n.startCharacterNumber=e.startCharacterNumber):(n.startLineNumber=this.startLineNumber,n.startCharacterNumber=Math.min(this.startCharacterNumber,e.startCharacterNumber)),this.endLineNumber>e.endLineNumber?(n.endLineNumber=this.endLineNumber,n.endCharacterNumber=this.endCharacterNumber):this.endLineNumber1?(u=l[0],c=l[1]):c=l[0];var f=i.story.ResolveListItem(u,c,h(i));if(null===f)null===u?i.Error("Could not find list definition that contains item '".concat(s,"'")):i.Error("Could not find list item ".concat(s));else{if(null==f.parent)return void i.Error("Could not find list definition for item ".concat(s));u||(u=(null===(n=f.parent.identifier)||void 0===n?void 0:n.name)||null);var d=new B(u,f.name||null);r.has(d.serialized())?i.Warning("Duplicate of item '".concat(s,"' in list.")):r.Add(d,f.seriesValue)}}}catch(t){o.e(t)}finally{o.f()}}t.AddContent(new Z(r))},i}return i(r,[{key:"typeName",get:function(){return"List"}}]),r}(nt),se=function(t){a(r,t);var e=d(r);function r(t,i){var a,s,l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return n(this,r),(s=e.call(this)).indentifier=t,s.inInitialList=i,s.explicitValue=l,s.seriesValue=0,s.parent=null,s.GenerateRuntimeObject=function(){throw new Error("Not implemented.")},s.toString=function(){return s.fullName},s.parent=p((a=h(s),o(r.prototype)),"parent",a),s}return i(r,[{key:"fullName",get:function(){var t,e=this.parent;if(null===e)throw new Error("Can't get full name without a parent list.");return"".concat(null===(t=e.identifier)||void 0===t?void 0:t.name,".").concat(this.name)}},{key:"typeName",get:function(){return"ListElement"}},{key:"name",get:function(){var t;return(null===(t=this.indentifier)||void 0===t?void 0:t.name)||null}},{key:"ResolveReferences",value:function(t){p(o(r.prototype),"ResolveReferences",this).call(this,t),t.CheckForNamingCollisions(this,this.indentifier,ft.ListItem)}}]),r}(F);!function(t){t[t.InnerBlock=0]="InnerBlock",t[t.Stitch=1]="Stitch",t[t.Knot=2]="Knot",t[t.Top=3]="Top"}(Xt||(Xt={}));var le=function(t){a(r,t);var e=d(r);function r(t,i,a,s){var l,u;return n(this,r),(u=e.call(this,t,i,a,s)).toString=function(){return"".concat(null!==u.parent?u.parent+" > ":"").concat(p((l=h(u),o(r.prototype)),"toString",l).call(l))},u}return i(r,[{key:"flowLevel",get:function(){return bt.Stitch}},{key:"typeName",get:function(){return"Stitch"}}]),r}(Ot),ue=function(t){a(r,t);var e=d(r);function r(t){var i;return n(this,r),(i=e.call(this)).text=t.toString()||"",i}return i(r,[{key:"toString",value:function(){return"# "+this.text}}]),r}(V),ce=function(t){a(r,t);var e=d(r);function r(){var t;return n(this,r),(t=e.apply(this,arguments)).text="",t.index=0,t.threadAtGeneration=null,t.sourcePath="",t.targetPath=null,t.isInvisibleDefault=!1,t.tags=null,t.originalThreadIndex=0,t}return i(r,[{key:"pathStringOnChoice",get:function(){return null===this.targetPath?L("Choice.targetPath"):this.targetPath.toString()},set:function(t){this.targetPath=new R(t)}}]),r}(V),he=function(){function t(e){n(this,t),this._lists=new Map,this._allUnambiguousListValueCache=new Map;var r,i=S(e);try{for(i.s();!(r=i.n()).done;){var a=r.value;this._lists.set(a.name,a);var o,s=S(a.items);try{for(s.s();!(o=s.n()).done;){var l=m(o.value,2),u=l[0],c=l[1],h=B.fromSerializedKey(u),f=new Z(h,c);if(!h.itemName)throw new Error("item.itemName is null or undefined.");this._allUnambiguousListValueCache.set(h.itemName,f),this._allUnambiguousListValueCache.set(h.fullName,f)}}catch(t){s.e(t)}finally{s.f()}}}catch(t){i.e(t)}finally{i.f()}}return i(t,[{key:"lists",get:function(){var t,e=[],n=S(this._lists);try{for(n.s();!(t=n.n()).done;){var r=m(t.value,2)[1];e.push(r)}}catch(t){n.e(t)}finally{n.f()}return e}},{key:"TryListGetDefinition",value:function(t,e){if(null===t)return{result:e,exists:!1};var n=this._lists.get(t);return n?{result:n,exists:!0}:{result:e,exists:!1}}},{key:"FindSingleItemListWithName",value:function(t){if(null===t)return L("name");var e=this._allUnambiguousListValueCache.get(t);return void 0!==e?e:null}}]),t}(),fe=function(){function t(){n(this,t)}return i(t,null,[{key:"JArrayToRuntimeObjList",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.length;e&&n--;for(var r=[],i=0;it->")),a=i.hasVariableTarget?i.variableDivertName:i.targetPathString,e.WriteObjectStart(),e.WriteProperty(o,a),i.hasVariableTarget&&e.WriteProperty("var",!0),i.isConditional&&e.WriteProperty("c",!0),i.externalArgs>0&&e.WriteIntProperty("exArgs",i.externalArgs),void e.WriteObjectEnd()}var s=_(n,ht);if(s)return e.WriteObjectStart(),e.WriteProperty("*",s.pathStringOnChoice),e.WriteIntProperty("flg",s.flags),void e.WriteObjectEnd();var l=_(n,H);if(l)e.WriteBool(l.value);else{var u=_(n,J);if(u)e.WriteInt(u.value);else{var c=_(n,z);if(c)e.WriteFloat(c.value);else{var h=_(n,$);if(h)h.isNewline?e.Write("\n",!1):(e.WriteStringStart(),e.WriteStringInner("^"),e.WriteStringInner(h.value),e.WriteStringEnd());else{var f=_(n,Z);if(f)this.WriteInkList(e,f);else{var d=_(n,X);if(d)return e.WriteObjectStart(),null===d.value?L("divTargetVal.value"):(e.WriteProperty("^->",d.value.componentsString),void e.WriteObjectEnd());var v=_(n,Y);if(v)return e.WriteObjectStart(),e.WriteProperty("^var",v.value),e.WriteIntProperty("ci",v.contextIndex),void e.WriteObjectEnd();if(_(n,ee))e.Write("<>");else{var p=_(n,et);if(p)e.Write(t._controlCommandNames[p.commandType]);else{var m=_(n,it);if(m){var g=m.name;return"^"==g&&(g="L^"),void e.Write(g)}var y=_(n,Ft);if(y){e.WriteObjectStart();var C=y.pathStringForCount;return null!=C?e.WriteProperty("CNT?",C):e.WriteProperty("VAR?",y.name),void e.WriteObjectEnd()}var S=_(n,pt);if(S){e.WriteObjectStart();var b=S.isGlobal?"VAR=":"temp=";return e.WriteProperty(b,S.variableName),S.isNewDeclaration||e.WriteProperty("re",!0),void e.WriteObjectEnd()}if(_(n,rt))e.Write("void");else{var w=_(n,ue);if(w)return e.WriteObjectStart(),e.WriteProperty("#",w.text),void e.WriteObjectEnd();var k=_(n,ce);if(!k)throw new Error("Failed to convert runtime object to Json token: "+n);this.WriteChoice(e,k)}}}}}}}}}}},{key:"JObjectToDictionaryRuntimeObjs",value:function(t){var e=new Map;for(var n in t)if(t.hasOwnProperty(n)){var r=this.JTokenToRuntimeObject(t[n]);if(null===r)return L("inkObject");e.set(n,r)}return e}},{key:"JObjectToIntDictionary",value:function(t){var e=new Map;for(var n in t)t.hasOwnProperty(n)&&e.set(n,parseInt(t[n]));return e}},{key:"JTokenToRuntimeObject",value:function(n){if("number"==typeof n&&!isNaN(n)||"boolean"==typeof n)return K.Create(n);if("string"==typeof n){var r=n.toString(),i=r[0];if("^"==i)return new $(r.substring(1));if("\n"==i&&1==r.length)return new $("\n");if("<>"==r)return new ee;for(var a=0;a->"==r)return et.PopTunnel();if("~ret"==r)return et.PopFunction();if("void"==r)return new rt}if("object"===e(n)&&!Array.isArray(n)){var o,s=n;if(s["^->"])return o=s["^->"],new X(new R(o.toString()));if(s["^var"]){o=s["^var"];var l=new Y(o.toString());return"ci"in s&&(o=s.ci,l.contextIndex=parseInt(o)),l}var u=!1,c=!1,h=ct.Function,f=!1;if((o=s["->"])?u=!0:(o=s["f()"])?(u=!0,c=!0,h=ct.Function):(o=s["->t->"])?(u=!0,c=!0,h=ct.Tunnel):(o=s["x()"])&&(u=!0,f=!0,c=!1,h=ct.Function),u){var d=new vt;d.pushesToStack=c,d.stackPushType=h,d.isExternal=f;var v=o.toString();return(o=s.var)?d.variableDivertName=v:d.targetPathString=v,d.isConditional=!!s.c,f&&(o=s.exArgs)&&(d.externalArgs=parseInt(o)),d}if(o=s["*"]){var p=new ht;return p.pathStringOnChoice=o.toString(),(o=s.flg)&&(p.flags=parseInt(o)),p}if(o=s["VAR?"])return new Ft(o.toString());if(o=s["CNT?"]){var m=new Ft;return m.pathStringForCount=o.toString(),m}var g=!1,y=!1;if((o=s["VAR="])?(g=!0,y=!0):(o=s["temp="])&&(g=!0,y=!1),g){var C=o.toString(),S=!s.re,b=new pt(C,S);return b.isGlobal=y,b}if(void 0!==s["#"])return o=s["#"],new ue(o.toString());if(o=s.list){var w=o,k=new M;if(o=s.origins){var E=o;k.SetInitialOriginNames(E)}for(var _ in w)if(w.hasOwnProperty(_)){var T=w[_],A=new B(_),P=parseInt(T);k.Add(A,P)}return new Z(k)}if(null!=s.originalChoicePath)return this.JObjectToChoice(s)}if(Array.isArray(n))return this.JArrayToContainer(n);if(null==n)return null;throw new Error("Failed to convert token to runtime object: "+this.toJson(n,["parent"]))}},{key:"toJson",value:function(t,e,n){return JSON.stringify(t,(function(t,n){return(null==e?void 0:e.some((function(e){return e===t})))?void 0:n}),n)}},{key:"WriteRuntimeContainer",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(t.WriteArrayStart(),null===e)return L("container");var r,i=S(e.content);try{for(i.s();!(r=i.n()).done;){var a=r.value;this.WriteRuntimeObject(t,a)}}catch(t){i.e(t)}finally{i.f()}var o=e.namedOnlyContent,s=e.countFlags,l=null!=e.name&&!n,u=null!=o||s>0||l;if(u&&t.WriteObjectStart(),null!=o){var c,h=S(o);try{for(h.s();!(c=h.n()).done;){var f=m(c.value,2),d=f[0],v=f[1],p=d,g=_(v,tt);t.WritePropertyStart(p),this.WriteRuntimeContainer(t,g,!0),t.WritePropertyEnd()}}catch(t){h.e(t)}finally{h.f()}}s>0&&t.WriteIntProperty("#f",s),l&&t.WriteProperty("#n",e.name),u?t.WriteObjectEnd():t.WriteNull(),t.WriteArrayEnd()}},{key:"JArrayToContainer",value:function(t){var e=new tt;e.content=this.JArrayToRuntimeObjList(t,!0);var n=t[t.length-1];if(null!=n){var r=new Map;for(var i in n)if("#f"==i)e.countFlags=parseInt(n[i]);else if("#n"==i)e.name=n[i].toString();else{var a=this.JTokenToRuntimeObject(n[i]),o=_(a,tt);o&&(o.name=i),r.set(i,a)}e.namedOnlyContent=r}return e}},{key:"JObjectToChoice",value:function(t){var e=new ce;return e.text=t.text.toString(),e.index=parseInt(t.index),e.sourcePath=t.originalChoicePath.toString(),e.originalThreadIndex=parseInt(t.originalThreadIndex),e.pathStringOnChoice=t.targetPath.toString(),e}},{key:"WriteChoice",value:function(t,e){t.WriteObjectStart(),t.WriteProperty("text",e.text),t.WriteIntProperty("index",e.index),t.WriteProperty("originalChoicePath",e.sourcePath),t.WriteIntProperty("originalThreadIndex",e.originalThreadIndex),t.WriteProperty("targetPath",e.pathStringOnChoice),t.WriteObjectEnd()}},{key:"WriteInkList",value:function(t,e){var n=e.value;if(null===n)return L("rawList");t.WriteObjectStart(),t.WritePropertyStart("list"),t.WriteObjectStart();var r,i=S(n);try{for(i.s();!(r=i.n()).done;){var a=m(r.value,2),o=a[0],s=a[1],l=B.fromSerializedKey(o),u=s;if(null===l.itemName)return L("item.itemName");t.WritePropertyNameStart(),t.WritePropertyNameInner(l.originName?l.originName:"?"),t.WritePropertyNameInner("."),t.WritePropertyNameInner(l.itemName),t.WritePropertyNameEnd(),t.Write(u),t.WritePropertyEnd()}}catch(t){i.e(t)}finally{i.f()}if(t.WriteObjectEnd(),t.WritePropertyEnd(),0==n.Count&&null!=n.originNames&&n.originNames.length>0){t.WritePropertyStart("origins"),t.WriteArrayStart();var c,h=S(n.originNames);try{for(h.s();!(c=h.n()).done;){var f=c.value;t.Write(f)}}catch(t){h.e(t)}finally{h.f()}t.WriteArrayEnd(),t.WritePropertyEnd()}t.WriteObjectEnd()}},{key:"ListDefinitionsToJToken",value:function(t){var e,n={},r=S(t.lists);try{for(r.s();!(e=r.n()).done;){var i,a=e.value,o={},s=S(a.items);try{for(s.s();!(i=s.n()).done;){var l=m(i.value,2),u=l[0],c=l[1],h=B.fromSerializedKey(u);if(null===h.itemName)return L("item.itemName");o[h.itemName]=c}}catch(t){s.e(t)}finally{s.f()}n[a.name]=o}}catch(t){r.e(t)}finally{r.f()}return n}},{key:"JTokenToListDefinitions",value:function(t){var e=t,n=[];for(var r in e)if(e.hasOwnProperty(r)){var i=r.toString(),a=e[r],o=new Map;for(var s in a)if(e.hasOwnProperty(r)){var l=a[s];o.set(s,parseInt(l))}var u=new Kt(i,o);n.push(u)}return new he(n)}}]),t}();fe._controlCommandNames=function(){var t=[];t[et.CommandType.EvalStart]="ev",t[et.CommandType.EvalOutput]="out",t[et.CommandType.EvalEnd]="/ev",t[et.CommandType.Duplicate]="du",t[et.CommandType.PopEvaluatedValue]="pop",t[et.CommandType.PopFunction]="~ret",t[et.CommandType.PopTunnel]="->->",t[et.CommandType.BeginString]="str",t[et.CommandType.EndString]="/str",t[et.CommandType.NoOp]="nop",t[et.CommandType.ChoiceCount]="choiceCnt",t[et.CommandType.Turns]="turn",t[et.CommandType.TurnsSince]="turns",t[et.CommandType.ReadCount]="readc",t[et.CommandType.Random]="rnd",t[et.CommandType.SeedRandom]="srnd",t[et.CommandType.VisitIndex]="visit",t[et.CommandType.SequenceShuffleIndex]="seq",t[et.CommandType.StartThread]="thread",t[et.CommandType.Done]="done",t[et.CommandType.End]="end",t[et.CommandType.ListFromInt]="listInt",t[et.CommandType.ListRange]="range",t[et.CommandType.ListRandom]="lrnd",t[et.CommandType.BeginTag]="#",t[et.CommandType.EndTag]="/#";for(var e=0;e1}},{key:"Reset",value:function(){this._threads=[],this._threads.push(new e.Thread),this._threads[0].callstack.push(new e.Element(ct.Tunnel,this._startOfRoot))}},{key:"SetJsonToken",value:function(t,n){this._threads.length=0;var r,i=S(t.threads);try{for(i.s();!(r=i.n()).done;){var a=r.value,o=new e.Thread(a,n);this._threads.push(o)}}catch(t){i.e(t)}finally{i.f()}this._threadCounter=parseInt(t.threadCounter),this._startOfRoot=dt.StartOf(n.rootContentContainer)}},{key:"WriteJson",value:function(t){var e=this;t.WriteObject((function(t){t.WritePropertyStart("threads"),t.WriteArrayStart();var n,r=S(e._threads);try{for(r.s();!(n=r.n()).done;){n.value.WriteJson(t)}}catch(t){r.e(t)}finally{r.f()}t.WriteArrayEnd(),t.WritePropertyEnd(),t.WritePropertyStart("threadCounter"),t.WriteInt(e._threadCounter),t.WritePropertyEnd()}))}},{key:"PushThread",value:function(){var t=this.currentThread.Copy();this._threadCounter++,t.threadIndex=this._threadCounter,this._threads.push(t)}},{key:"ForkThread",value:function(){var t=this.currentThread.Copy();return this._threadCounter++,t.threadIndex=this._threadCounter,t}},{key:"PopThread",value:function(){if(!this.canPopThread)throw new Error("Can't pop thread");this._threads.splice(this._threads.indexOf(this.currentThread),1)}},{key:"canPopThread",get:function(){return this._threads.length>1&&!this.elementIsEvaluateFromGame}},{key:"elementIsEvaluateFromGame",get:function(){return this.currentElement.type==ct.FunctionEvaluationFromGame}},{key:"Push",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,i=new e.Element(t,this.currentElement.currentPointer,!1);i.evaluationStackHeightWhenPushed=n,i.functionStartInOutputStream=r,this.callStack.push(i)}},{key:"CanPop",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;return!!this.canPop&&(null==t||this.currentElement.type==t)}},{key:"Pop",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;if(!this.CanPop(t))throw new Error("Mismatched push/pop in Callstack");this.callStack.pop()}},{key:"GetTemporaryVariableWithName",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;-1==e&&(e=this.currentElementIndex+1);var n=this.callStack[e-1],r=q(n.temporaryVariables,t,null);return r.exists?r.result:null}},{key:"SetTemporaryVariable",value:function(t,e,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:-1;-1==r&&(r=this.currentElementIndex+1);var i=this.callStack[r-1];if(!n&&!i.temporaryVariables.get(t))throw new Error("Could not find temporary variable to set: "+t);var a=q(i.temporaryVariables,t,null);a.exists&&Z.RetainListOriginsForAssignment(a.result,e),i.temporaryVariables.set(t,e)}},{key:"ContextForVariableNamed",value:function(t){return this.currentElement.temporaryVariables.get(t)?this.currentElementIndex+1:0}},{key:"ThreadWithIndex",value:function(t){var e=this._threads.filter((function(e){if(e.threadIndex==t)return e}));return e.length>0?e[0]:null}},{key:"callStack",get:function(){return this.currentThread.callstack}},{key:"callStackTrace",get:function(){for(var t=new j,e=0;e")}}}return t.toString()}}]),e}();!function(t){var e=function(){function t(e,r){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];n(this,t),this.evaluationStackHeightWhenPushed=0,this.functionStartInOutputStream=0,this.currentPointer=r.copy(),this.inExpressionEvaluation=i,this.temporaryVariables=new Map,this.type=e}return i(t,[{key:"Copy",value:function(){var e=new t(this.type,this.currentPointer,this.inExpressionEvaluation);return e.temporaryVariables=new Map(this.temporaryVariables),e.evaluationStackHeightWhenPushed=this.evaluationStackHeightWhenPushed,e.functionStartInOutputStream=this.functionStartInOutputStream,e}}]),t}();t.Element=e;var r=function(){function t(){if(n(this,t),this.threadIndex=0,this.previousPointer=dt.Null,this.callstack=[],arguments[0]&&arguments[1]){var r=arguments[0],i=arguments[1];this.threadIndex=parseInt(r.threadIndex);var a,o=r.callstack,s=S(o);try{for(s.s();!(a=s.n()).done;){var l=a.value,u=l,c=parseInt(u.type),h=dt.Null,f=void 0,d=u.cPath;if(void 0!==d){f=d.toString();var v=i.ContentAtPath(new R(f));if(h.container=v.container,h.index=parseInt(u.idx),null==v.obj)throw new Error("When loading state, internal story location couldn't be found: "+f+". Has the story changed since this save data was created?");if(v.approximate){if(null===h.container)return L("pointer.container");i.Warning("When loading state, exact internal story location couldn't be found: '"+f+"', so it was approximated to '"+h.container.path.toString()+"' to recover. Has the story changed since this save data was created?")}}var p=!!u.exp,m=new e(c,h,p),g=u.temp;void 0!==g?m.temporaryVariables=fe.JObjectToDictionaryRuntimeObjs(g):m.temporaryVariables.clear(),this.callstack.push(m)}}catch(t){s.e(t)}finally{s.f()}var y=r.previousContentObject;if(void 0!==y){var C=new R(y.toString());this.previousPointer=i.PointerAtPath(C)}}}return i(t,[{key:"Copy",value:function(){var e=new t;e.threadIndex=this.threadIndex;var n,r=S(this.callstack);try{for(r.s();!(n=r.n()).done;){var i=n.value;e.callstack.push(i.Copy())}}catch(t){r.e(t)}finally{r.f()}return e.previousPointer=this.previousPointer.copy(),e}},{key:"WriteJson",value:function(t){t.WriteObjectStart(),t.WritePropertyStart("callstack"),t.WriteArrayStart();var e,n=S(this.callstack);try{for(n.s();!(e=n.n()).done;){var r=e.value;if(t.WriteObjectStart(),!r.currentPointer.isNull){if(null===r.currentPointer.container)return L("el.currentPointer.container");t.WriteProperty("cPath",r.currentPointer.container.path.componentsString),t.WriteIntProperty("idx",r.currentPointer.index)}t.WriteProperty("exp",r.inExpressionEvaluation),t.WriteIntProperty("type",r.type),r.temporaryVariables.size>0&&(t.WritePropertyStart("temp"),fe.WriteDictionaryRuntimeObjs(t,r.temporaryVariables),t.WritePropertyEnd()),t.WriteObjectEnd()}}catch(t){n.e(t)}finally{n.f()}if(t.WriteArrayEnd(),t.WritePropertyEnd(),t.WriteIntProperty("threadIndex",this.threadIndex),!this.previousPointer.isNull){var i=this.previousPointer.Resolve();if(null===i)return L("this.previousPointer.Resolve()");t.WriteProperty("previousContentObject",i.path.toString())}t.WriteObjectEnd()}}]),t}();t.Thread=r}(de||(de={}));var ve=function(t){a(r,t);var e=d(r);function r(t,i){var a;n(this,r),(a=e.call(this)).variableChangedEventCallbacks=[],a.patch=null,a._batchObservingVariableChanges=!1,a._defaultGlobalVariables=new Map,a._changedVariablesForBatchObs=new Set,a._globalVariables=new Map,a._callStack=t,a._listDefsOrigin=i;try{return f(a,new Proxy(h(a),{get:function(t,e){return e in t?t[e]:t.$(e)},set:function(t,e,n){return e in t?t[e]=n:t.$(e,n),!0}}))}catch(t){}return a}return i(r,[{key:"variableChangedEvent",value:function(t,e){var n,r=S(this.variableChangedEventCallbacks);try{for(r.s();!(n=r.n()).done;){(0,n.value)(t,e)}}catch(t){r.e(t)}finally{r.f()}}},{key:"batchObservingVariableChanges",get:function(){return this._batchObservingVariableChanges},set:function(t){if(this._batchObservingVariableChanges=t,t)this._changedVariablesForBatchObs=new Set;else if(null!=this._changedVariablesForBatchObs){var e,n=S(this._changedVariablesForBatchObs);try{for(n.s();!(e=n.n()).done;){var r=e.value,i=this._globalVariables.get(r);i?this.variableChangedEvent(r,i):L("currentValue")}}catch(t){n.e(t)}finally{n.f()}this._changedVariablesForBatchObs=null}}},{key:"callStack",get:function(){return this._callStack},set:function(t){this._callStack=t}},{key:"$",value:function(t,e){if(void 0===e){var n=null;return null!==this.patch&&(n=this.patch.TryGetGlobal(t,null)).exists?n.result.valueObject:(void 0===(n=this._globalVariables.get(t))&&(n=this._defaultGlobalVariables.get(t)),void 0!==n?n.valueObject:null)}if(void 0===this._defaultGlobalVariables.get(t))throw new G("Cannot assign to a variable ("+t+") that hasn't been declared in the story");var r=K.Create(e);if(null==r)throw null==e?new Error("Cannot pass null to VariableState"):new Error("Invalid value passed to VariableState: "+e.toString());this.SetGlobal(t,r)}},{key:"ApplyPatch",value:function(){if(null===this.patch)return L("this.patch");var t,e=S(this.patch.globals);try{for(e.s();!(t=e.n()).done;){var n=m(t.value,2),r=n[0],i=n[1];this._globalVariables.set(r,i)}}catch(t){e.e(t)}finally{e.f()}if(null!==this._changedVariablesForBatchObs){var a,o=S(this.patch.changedVariables);try{for(o.s();!(a=o.n()).done;){var s=a.value;this._changedVariablesForBatchObs.add(s)}}catch(t){o.e(t)}finally{o.f()}}this.patch=null}},{key:"SetJsonToken",value:function(t){this._globalVariables.clear();var e,n=S(this._defaultGlobalVariables);try{for(n.s();!(e=n.n()).done;){var r=m(e.value,2),i=r[0],a=r[1],o=t[i];if(void 0!==o){var s=fe.JTokenToRuntimeObject(o);if(null===s)return L("tokenInkObject");this._globalVariables.set(i,s)}else this._globalVariables.set(i,a)}}catch(t){n.e(t)}finally{n.f()}}},{key:"WriteJson",value:function(t){t.WriteObjectStart();var e,n=S(this._globalVariables);try{for(n.s();!(e=n.n()).done;){var i=m(e.value,2),a=i[0],o=i[1],s=a,l=o;if(r.dontSaveDefaultValues&&this._defaultGlobalVariables.has(s)){var u=this._defaultGlobalVariables.get(s);if(this.RuntimeObjectsEqual(l,u))continue}t.WritePropertyStart(s),fe.WriteRuntimeObject(t,l),t.WritePropertyEnd()}}catch(t){n.e(t)}finally{n.f()}t.WriteObjectEnd()}},{key:"RuntimeObjectsEqual",value:function(t,e){if(null===t)return L("obj1");if(null===e)return L("obj2");if(t.constructor!==e.constructor)return!1;var n=_(t,H);if(null!==n)return n.value===T(e,H).value;var r=_(t,J);if(null!==r)return r.value===T(e,J).value;var i=_(t,z);if(null!==i)return i.value===T(e,z).value;var a=_(t,K),o=_(e,K);if(null!==a&&null!==o)return N(a.valueObject)&&N(o.valueObject)?a.valueObject.Equals(o.valueObject):a.valueObject===o.valueObject;throw new Error("FastRoughDefinitelyEquals: Unsupported runtime object type: "+t.constructor.name)}},{key:"GetVariableWithName",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1,n=this.GetRawVariableWithName(t,e),r=_(n,Y);return null!==r&&(n=this.ValueAtVariablePointer(r)),n}},{key:"TryGetDefaultVariableValue",value:function(t){var e=q(this._defaultGlobalVariables,t,null);return e.exists?e.result:null}},{key:"GlobalVariableExistsWithName",value:function(t){return this._globalVariables.has(t)||null!==this._defaultGlobalVariables&&this._defaultGlobalVariables.has(t)}},{key:"GetRawVariableWithName",value:function(t,e){if(0==e||-1==e){var n=null;if(null!==this.patch&&(n=this.patch.TryGetGlobal(t,null)).exists)return n.result;if((n=q(this._globalVariables,t,null)).exists)return n.result;if(null!==this._defaultGlobalVariables&&(n=q(this._defaultGlobalVariables,t,null)).exists)return n.result;if(null===this._listDefsOrigin)return L("VariablesState._listDefsOrigin");var r=this._listDefsOrigin.FindSingleItemListWithName(t);if(r)return r}return this._callStack.GetTemporaryVariableWithName(t,e)}},{key:"ValueAtVariablePointer",value:function(t){return this.GetVariableWithName(t.variableName,t.contextIndex)}},{key:"Assign",value:function(t,e){var n=t.variableName;if(null===n)return L("name");var r=-1,i=!1;if(i=t.isNewDeclaration?t.isGlobal:this.GlobalVariableExistsWithName(n),t.isNewDeclaration){var a=_(e,Y);if(null!==a)e=this.ResolveVariablePointer(a)}else{var o=null;do{null!=(o=_(this.GetRawVariableWithName(n,r),Y))&&(n=o.variableName,i=0==(r=o.contextIndex))}while(null!=o)}i?this.SetGlobal(n,e):this._callStack.SetTemporaryVariable(n,e,t.isNewDeclaration,r)}},{key:"SnapshotDefaultGlobals",value:function(){this._defaultGlobalVariables=new Map(this._globalVariables)}},{key:"RetainListOriginsForAssignment",value:function(t,e){var n=T(t,Z),r=T(e,Z);n.value&&r.value&&0==r.value.Count&&r.value.SetInitialOriginNames(n.value.originNames)}},{key:"SetGlobal",value:function(t,e){var n=null;if(null===this.patch&&(n=q(this._globalVariables,t,null)),null!==this.patch&&((n=this.patch.TryGetGlobal(t,null)).exists||(n=q(this._globalVariables,t,null))),Z.RetainListOriginsForAssignment(n.result,e),null===t)return L("variableName");if(null!==this.patch?this.patch.SetGlobal(t,e):this._globalVariables.set(t,e),null!==this.variableChangedEvent&&null!==n&&e!==n.result)if(this.batchObservingVariableChanges){if(null===this._changedVariablesForBatchObs)return L("this._changedVariablesForBatchObs");null!==this.patch?this.patch.AddChangedVariable(t):null!==this._changedVariablesForBatchObs&&this._changedVariablesForBatchObs.add(t)}else this.variableChangedEvent(t,e)}},{key:"ResolveVariablePointer",value:function(t){var e=t.contextIndex;-1==e&&(e=this.GetContextIndexOfVariableNamed(t.variableName));var n=_(this.GetRawVariableWithName(t.variableName,e),Y);return null!=n?n:new Y(t.variableName,e)}},{key:"GetContextIndexOfVariableNamed",value:function(t){return this.GlobalVariableExistsWithName(t)?0:this._callStack.currentElementIndex}},{key:"ObserveVariableChange",value:function(t){this.variableChangedEventCallbacks.push(t)}}]),r}(function(){return i((function t(){n(this,t)}))}());ve.dontSaveDefaultValues=!0;var pe=function(){function t(e){n(this,t),this.seed=e%2147483647,this.seed<=0&&(this.seed+=2147483646)}return i(t,[{key:"next",value:function(){return this.seed=48271*this.seed%2147483647}},{key:"nextFloat",value:function(){return(this.next()-1)/2147483646}}]),t}(),me=function(){function t(){if(n(this,t),this._changedVariables=new Set,this._visitCounts=new Map,this._turnIndices=new Map,1===arguments.length&&null!==arguments[0]){var e=arguments[0];this._globals=new Map(e._globals),this._changedVariables=new Set(e._changedVariables),this._visitCounts=new Map(e._visitCounts),this._turnIndices=new Map(e._turnIndices)}else this._globals=new Map,this._changedVariables=new Set,this._visitCounts=new Map,this._turnIndices=new Map}return i(t,[{key:"globals",get:function(){return this._globals}},{key:"changedVariables",get:function(){return this._changedVariables}},{key:"visitCounts",get:function(){return this._visitCounts}},{key:"turnIndices",get:function(){return this._turnIndices}},{key:"TryGetGlobal",value:function(t,e){return null!==t&&this._globals.has(t)?{result:this._globals.get(t),exists:!0}:{result:e,exists:!1}}},{key:"SetGlobal",value:function(t,e){this._globals.set(t,e)}},{key:"AddChangedVariable",value:function(t){return this._changedVariables.add(t)}},{key:"TryGetVisitCount",value:function(t,e){return this._visitCounts.has(t)?{result:this._visitCounts.get(t),exists:!0}:{result:e,exists:!1}}},{key:"SetVisitCount",value:function(t,e){this._visitCounts.set(t,e)}},{key:"SetTurnIndex",value:function(t,e){this._turnIndices.set(t,e)}},{key:"TryGetTurnIndex",value:function(t,e){return this._turnIndices.has(t)?{result:this._turnIndices.get(t),exists:!0}:{result:e,exists:!1}}}]),t}(),ge=function(){function t(){n(this,t)}return i(t,null,[{key:"TextToDictionary",value:function(e){return new t.Reader(e).ToDictionary()}},{key:"TextToArray",value:function(e){return new t.Reader(e).ToArray()}}]),t}();!function(t){var e=function(){function t(e){n(this,t),this._rootObject=JSON.parse(e)}return i(t,[{key:"ToDictionary",value:function(){return this._rootObject}},{key:"ToArray",value:function(){return this._rootObject}}]),t}();t.Reader=e;var r=function(){function e(){n(this,e),this._currentPropertyName=null,this._currentString=null,this._stateStack=[],this._collectionStack=[],this._propertyNameStack=[],this._jsonObject=null}return i(e,[{key:"WriteObject",value:function(t){this.WriteObjectStart(),t(this),this.WriteObjectEnd()}},{key:"WriteObjectStart",value:function(){this.StartNewObject(!0);var e={};if(this.state===t.Writer.State.Property){this.Assert(null!==this.currentCollection),this.Assert(null!==this.currentPropertyName);var n=this._propertyNameStack.pop();this.currentCollection[n]=e,this._collectionStack.push(e)}else this.state===t.Writer.State.Array?(this.Assert(null!==this.currentCollection),this.currentCollection.push(e),this._collectionStack.push(e)):(this.Assert(this.state===t.Writer.State.None),this._jsonObject=e,this._collectionStack.push(e));this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Object))}},{key:"WriteObjectEnd",value:function(){this.Assert(this.state===t.Writer.State.Object),this._collectionStack.pop(),this._stateStack.pop()}},{key:"WriteProperty",value:function(t,e){if(this.WritePropertyStart(t),arguments[1]instanceof Function){var n=arguments[1];n(this)}else{var r=arguments[1];this.Write(r)}this.WritePropertyEnd()}},{key:"WriteIntProperty",value:function(t,e){this.WritePropertyStart(t),this.WriteInt(e),this.WritePropertyEnd()}},{key:"WriteFloatProperty",value:function(t,e){this.WritePropertyStart(t),this.WriteFloat(e),this.WritePropertyEnd()}},{key:"WritePropertyStart",value:function(e){this.Assert(this.state===t.Writer.State.Object),this._propertyNameStack.push(e),this.IncrementChildCount(),this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Property))}},{key:"WritePropertyEnd",value:function(){this.Assert(this.state===t.Writer.State.Property),this.Assert(1===this.childCount),this._stateStack.pop()}},{key:"WritePropertyNameStart",value:function(){this.Assert(this.state===t.Writer.State.Object),this.IncrementChildCount(),this._currentPropertyName="",this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Property)),this._stateStack.push(new t.Writer.StateElement(t.Writer.State.PropertyName))}},{key:"WritePropertyNameEnd",value:function(){this.Assert(this.state===t.Writer.State.PropertyName),this.Assert(null!==this._currentPropertyName),this._propertyNameStack.push(this._currentPropertyName),this._currentPropertyName=null,this._stateStack.pop()}},{key:"WritePropertyNameInner",value:function(e){this.Assert(this.state===t.Writer.State.PropertyName),this.Assert(null!==this._currentPropertyName),this._currentPropertyName+=e}},{key:"WriteArrayStart",value:function(){this.StartNewObject(!0);var e=[];if(this.state===t.Writer.State.Property){this.Assert(null!==this.currentCollection),this.Assert(null!==this.currentPropertyName);var n=this._propertyNameStack.pop();this.currentCollection[n]=e,this._collectionStack.push(e)}else this.state===t.Writer.State.Array?(this.Assert(null!==this.currentCollection),this.currentCollection.push(e),this._collectionStack.push(e)):(this.Assert(this.state===t.Writer.State.None),this._jsonObject=e,this._collectionStack.push(e));this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Array))}},{key:"WriteArrayEnd",value:function(){this.Assert(this.state===t.Writer.State.Array),this._collectionStack.pop(),this._stateStack.pop()}},{key:"Write",value:function(t){null!==t?(this.StartNewObject(!1),this._addToCurrentObject(t)):console.error("Warning: trying to write a null value")}},{key:"WriteBool",value:function(t){null!==t&&(this.StartNewObject(!1),this._addToCurrentObject(t))}},{key:"WriteInt",value:function(t){null!==t&&(this.StartNewObject(!1),this._addToCurrentObject(Math.floor(t)))}},{key:"WriteFloat",value:function(t){null!==t&&(this.StartNewObject(!1),t==Number.POSITIVE_INFINITY?this._addToCurrentObject(34e37):t==Number.NEGATIVE_INFINITY?this._addToCurrentObject(-34e37):isNaN(t)?this._addToCurrentObject(0):this._addToCurrentObject(t))}},{key:"WriteNull",value:function(){this.StartNewObject(!1),this._addToCurrentObject(null)}},{key:"WriteStringStart",value:function(){this.StartNewObject(!1),this._currentString="",this._stateStack.push(new t.Writer.StateElement(t.Writer.State.String))}},{key:"WriteStringEnd",value:function(){this.Assert(this.state==t.Writer.State.String),this._stateStack.pop(),this._addToCurrentObject(this._currentString),this._currentString=null}},{key:"WriteStringInner",value:function(e){this.Assert(this.state===t.Writer.State.String),null!==e?this._currentString+=e:console.error("Warning: trying to write a null string")}},{key:"toString",value:function(){return null===this._jsonObject?"":JSON.stringify(this._jsonObject)}},{key:"StartNewObject",value:function(e){e?this.Assert(this.state===t.Writer.State.None||this.state===t.Writer.State.Property||this.state===t.Writer.State.Array):this.Assert(this.state===t.Writer.State.Property||this.state===t.Writer.State.Array),this.state===t.Writer.State.Property&&this.Assert(0===this.childCount),this.state!==t.Writer.State.Array&&this.state!==t.Writer.State.Property||this.IncrementChildCount()}},{key:"state",get:function(){return this._stateStack.length>0?this._stateStack[this._stateStack.length-1].type:t.Writer.State.None}},{key:"childCount",get:function(){return this._stateStack.length>0?this._stateStack[this._stateStack.length-1].childCount:0}},{key:"currentCollection",get:function(){return this._collectionStack.length>0?this._collectionStack[this._collectionStack.length-1]:null}},{key:"currentPropertyName",get:function(){return this._propertyNameStack.length>0?this._propertyNameStack[this._propertyNameStack.length-1]:null}},{key:"IncrementChildCount",value:function(){this.Assert(this._stateStack.length>0);var t=this._stateStack.pop();t.childCount++,this._stateStack.push(t)}},{key:"Assert",value:function(t){if(!t)throw Error("Assert failed while writing JSON")}},{key:"_addToCurrentObject",value:function(e){this.Assert(null!==this.currentCollection),this.state===t.Writer.State.Array?(this.Assert(Array.isArray(this.currentCollection)),this.currentCollection.push(e)):this.state===t.Writer.State.Property&&(this.Assert(!Array.isArray(this.currentCollection)),this.Assert(null!==this.currentPropertyName),this.currentCollection[this.currentPropertyName]=e,this._propertyNameStack.pop())}}]),e}();t.Writer=r,function(e){var r;(r=e.State||(e.State={}))[r.None=0]="None",r[r.Object=1]="Object",r[r.Array=2]="Array",r[r.Property=3]="Property",r[r.PropertyName=4]="PropertyName",r[r.String=5]="String";var a=i((function e(r){n(this,e),this.type=t.Writer.State.None,this.childCount=0,this.type=r}));e.StateElement=a}(r=t.Writer||(t.Writer={}))}(ge||(ge={}));var ye,Ce=function(){function t(){n(this,t);var e=arguments[0],r=arguments[1];if(this.name=e,this.callStack=new de(r),arguments[2]){var i=arguments[2];this.callStack.SetJsonToken(i.callstack,r),this.outputStream=fe.JArrayToRuntimeObjList(i.outputStream),this.currentChoices=fe.JArrayToRuntimeObjList(i.currentChoices);var a=i.choiceThreads;void 0!==a&&this.LoadFlowChoiceThreads(a,r)}else this.outputStream=[],this.currentChoices=[]}return i(t,[{key:"WriteJson",value:function(t){var e=this;t.WriteObjectStart(),t.WriteProperty("callstack",(function(t){return e.callStack.WriteJson(t)})),t.WriteProperty("outputStream",(function(t){return fe.WriteListRuntimeObjs(t,e.outputStream)}));var n,r=!1,i=S(this.currentChoices);try{for(i.s();!(n=i.n()).done;){var a=n.value;if(null===a.threadAtGeneration)return L("c.threadAtGeneration");a.originalThreadIndex=a.threadAtGeneration.threadIndex,null===this.callStack.ThreadWithIndex(a.originalThreadIndex)&&(r||(r=!0,t.WritePropertyStart("choiceThreads"),t.WriteObjectStart()),t.WritePropertyStart(a.originalThreadIndex),a.threadAtGeneration.WriteJson(t),t.WritePropertyEnd())}}catch(t){i.e(t)}finally{i.f()}r&&(t.WriteObjectEnd(),t.WritePropertyEnd()),t.WriteProperty("currentChoices",(function(t){t.WriteArrayStart();var n,r=S(e.currentChoices);try{for(r.s();!(n=r.n()).done;){var i=n.value;fe.WriteChoice(t,i)}}catch(t){r.e(t)}finally{r.f()}t.WriteArrayEnd()})),t.WriteObjectEnd()}},{key:"LoadFlowChoiceThreads",value:function(t,e){var n,r=S(this.currentChoices);try{for(r.s();!(n=r.n()).done;){var i=n.value,a=this.callStack.ThreadWithIndex(i.originalThreadIndex);if(null!==a)i.threadAtGeneration=a.Copy();else{var o=t["".concat(i.originalThreadIndex)];i.threadAtGeneration=new de.Thread(o,e)}}}catch(t){r.e(t)}finally{r.f()}}}]),t}(),Se=function(){function e(t){n(this,e),this.kInkSaveStateVersion=10,this.kMinCompatibleLoadVersion=8,this.onDidLoadState=null,this._currentErrors=null,this._currentWarnings=null,this.divertedPointer=dt.Null,this._currentTurnIndex=0,this.storySeed=0,this.previousRandom=0,this.didSafeExit=!1,this._currentText=null,this._currentTags=null,this._outputStreamTextDirty=!0,this._outputStreamTagsDirty=!0,this._patch=null,this._aliveFlowNames=null,this._namedFlows=null,this.kDefaultFlowName="DEFAULT_FLOW",this._aliveFlowNamesDirty=!0,this.story=t,this._currentFlow=new Ce(this.kDefaultFlowName,t),this.OutputStreamDirty(),this._aliveFlowNamesDirty=!0,this._evaluationStack=[],this._variablesState=new ve(this.callStack,t.listDefinitions),this._visitCounts=new Map,this._turnIndices=new Map,this.currentTurnIndex=-1;var r=(new Date).getTime();this.storySeed=new pe(r).next()%100,this.previousRandom=0,this.GoToStart()}return i(e,[{key:"ToJson",value:function(){var t=new ge.Writer;return this.WriteJson(t),t.toString()}},{key:"toJson",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return this.ToJson(t)}},{key:"LoadJson",value:function(t){var e=ge.TextToDictionary(t);this.LoadJsonObj(e),null!==this.onDidLoadState&&this.onDidLoadState()}},{key:"VisitCountAtPathString",value:function(t){var e;if(null!==this._patch){var n=this.story.ContentAtPath(new R(t)).container;if(null===n)throw new Error("Content at path not found: "+t);if((e=this._patch.TryGetVisitCount(n,0)).exists)return e.result}return(e=q(this._visitCounts,t,null)).exists?e.result:0}},{key:"VisitCountForContainer",value:function(t){if(null===t)return L("container");if(!t.visitsShouldBeCounted)return this.story.Error("Read count for target ("+t.name+" - on "+t.debugMetadata+") unknown. The story may need to be compiled with countAllVisits flag (-c)."),0;if(null!==this._patch){var e=this._patch.TryGetVisitCount(t,0);if(e.exists)return e.result}var n=t.path.toString(),r=q(this._visitCounts,n,null);return r.exists?r.result:0}},{key:"IncrementVisitCountForContainer",value:function(t){if(null!==this._patch){var e=this.VisitCountForContainer(t);return e++,void this._patch.SetVisitCount(t,e)}var n=t.path.toString(),r=q(this._visitCounts,n,null);r.exists?this._visitCounts.set(n,r.result+1):this._visitCounts.set(n,1)}},{key:"RecordTurnIndexVisitToContainer",value:function(t){if(null===this._patch){var e=t.path.toString();this._turnIndices.set(e,this.currentTurnIndex)}else this._patch.SetTurnIndex(t,this.currentTurnIndex)}},{key:"TurnsSinceForContainer",value:function(t){if(t.turnIndexShouldBeCounted||this.story.Error("TURNS_SINCE() for target ("+t.name+" - on "+t.debugMetadata+") unknown. The story may need to be compiled with countAllVisits flag (-c)."),null!==this._patch){var e=this._patch.TryGetTurnIndex(t,0);if(e.exists)return this.currentTurnIndex-e.result}var n=t.path.toString(),r=q(this._turnIndices,n,0);return r.exists?this.currentTurnIndex-r.result:-1}},{key:"callstackDepth",get:function(){return this.callStack.depth}},{key:"outputStream",get:function(){return this._currentFlow.outputStream}},{key:"currentChoices",get:function(){return this.canContinue?[]:this._currentFlow.currentChoices}},{key:"generatedChoices",get:function(){return this._currentFlow.currentChoices}},{key:"currentErrors",get:function(){return this._currentErrors}},{key:"currentWarnings",get:function(){return this._currentWarnings}},{key:"variablesState",get:function(){return this._variablesState},set:function(t){this._variablesState=t}},{key:"callStack",get:function(){return this._currentFlow.callStack}},{key:"evaluationStack",get:function(){return this._evaluationStack}},{key:"currentTurnIndex",get:function(){return this._currentTurnIndex},set:function(t){this._currentTurnIndex=t}},{key:"currentPathString",get:function(){var t=this.currentPointer;return t.isNull?null:null===t.path?L("pointer.path"):t.path.toString()}},{key:"currentPointer",get:function(){return this.callStack.currentElement.currentPointer.copy()},set:function(t){this.callStack.currentElement.currentPointer=t.copy()}},{key:"previousPointer",get:function(){return this.callStack.currentThread.previousPointer.copy()},set:function(t){this.callStack.currentThread.previousPointer=t.copy()}},{key:"canContinue",get:function(){return!this.currentPointer.isNull&&!this.hasError}},{key:"hasError",get:function(){return null!=this.currentErrors&&this.currentErrors.length>0}},{key:"hasWarning",get:function(){return null!=this.currentWarnings&&this.currentWarnings.length>0}},{key:"currentText",get:function(){if(this._outputStreamTextDirty){var t,e=new j,n=!1,r=S(this.outputStream);try{for(r.s();!(t=r.n()).done;){var i=t.value,a=_(i,$);if(n||null===a){var o=_(i,et);null!==o&&(o.commandType==et.CommandType.BeginTag?n=!0:o.commandType==et.CommandType.EndTag&&(n=!1))}else e.Append(a.value)}}catch(t){r.e(t)}finally{r.f()}this._currentText=this.CleanOutputWhitespace(e.toString()),this._outputStreamTextDirty=!1}return this._currentText}},{key:"CleanOutputWhitespace",value:function(t){for(var e=new j,n=-1,r=0,i=0;i0&&n!=r&&e.Append(" "),n=-1),"\n"==a&&(r=i+1),o||e.Append(a)}return e.toString()}},{key:"currentTags",get:function(){if(this._outputStreamTagsDirty){this._currentTags=[];var t,e=!1,n=new j,r=S(this.outputStream);try{for(r.s();!(t=r.n()).done;){var i=t.value,a=_(i,et);if(null!=a){if(a.commandType==et.CommandType.BeginTag){if(e&&n.Length>0){var o=this.CleanOutputWhitespace(n.toString());this._currentTags.push(o),n.Clear()}e=!0}else if(a.commandType==et.CommandType.EndTag){if(n.Length>0){var s=this.CleanOutputWhitespace(n.toString());this._currentTags.push(s),n.Clear()}e=!1}}else if(e){var l=_(i,$);null!==l&&n.Append(l.value)}else{var u=_(i,ue);null!=u&&null!=u.text&&u.text.length>0&&this._currentTags.push(u.text)}}}catch(t){r.e(t)}finally{r.f()}if(n.Length>0){var c=this.CleanOutputWhitespace(n.toString());this._currentTags.push(c),n.Clear()}this._outputStreamTagsDirty=!1}return this._currentTags}},{key:"currentFlowName",get:function(){return this._currentFlow.name}},{key:"currentFlowIsDefaultFlow",get:function(){return this._currentFlow.name==this.kDefaultFlowName}},{key:"aliveFlowNames",get:function(){if(this._aliveFlowNamesDirty){if(this._aliveFlowNames=[],null!=this._namedFlows){var t,e=S(this._namedFlows.keys());try{for(e.s();!(t=e.n()).done;){var n=t.value;n!=this.kDefaultFlowName&&this._aliveFlowNames.push(n)}}catch(t){e.e(t)}finally{e.f()}}this._aliveFlowNamesDirty=!1}return this._aliveFlowNames}},{key:"inExpressionEvaluation",get:function(){return this.callStack.currentElement.inExpressionEvaluation},set:function(t){this.callStack.currentElement.inExpressionEvaluation=t}},{key:"GoToStart",value:function(){this.callStack.currentElement.currentPointer=dt.StartOf(this.story.mainContentContainer)}},{key:"SwitchFlow_Internal",value:function(t){if(null===t)throw new Error("Must pass a non-null string to Story.SwitchFlow");if(null===this._namedFlows&&(this._namedFlows=new Map,this._namedFlows.set(this.kDefaultFlowName,this._currentFlow)),t!==this._currentFlow.name){var e,n=q(this._namedFlows,t,null);n.exists?e=n.result:(e=new Ce(t,this.story),this._namedFlows.set(t,e),this._aliveFlowNamesDirty=!0),this._currentFlow=e,this.variablesState.callStack=this._currentFlow.callStack,this.OutputStreamDirty()}}},{key:"SwitchToDefaultFlow_Internal",value:function(){null!==this._namedFlows&&this.SwitchFlow_Internal(this.kDefaultFlowName)}},{key:"RemoveFlow_Internal",value:function(t){if(null===t)throw new Error("Must pass a non-null string to Story.DestroyFlow");if(t===this.kDefaultFlowName)throw new Error("Cannot destroy default flow");if(this._currentFlow.name===t&&this.SwitchToDefaultFlow_Internal(),null===this._namedFlows)return L("this._namedFlows");this._namedFlows.delete(t),this._aliveFlowNamesDirty=!0}},{key:"CopyAndStartPatching",value:function(){var t,n,r,i,a,o=new e(this.story);if(o._patch=new me(this._patch),o._currentFlow.name=this._currentFlow.name,o._currentFlow.callStack=new de(this._currentFlow.callStack),(t=o._currentFlow.currentChoices).push.apply(t,g(this._currentFlow.currentChoices)),(n=o._currentFlow.outputStream).push.apply(n,g(this._currentFlow.outputStream)),o.OutputStreamDirty(),null!==this._namedFlows){o._namedFlows=new Map;var s,l=S(this._namedFlows);try{for(l.s();!(s=l.n()).done;){var u=m(s.value,2),c=u[0],h=u[1];o._namedFlows.set(c,h),o._aliveFlowNamesDirty=!0}}catch(t){l.e(t)}finally{l.f()}o._namedFlows.set(this._currentFlow.name,o._currentFlow)}this.hasError&&(o._currentErrors=[],(i=o._currentErrors).push.apply(i,g(this.currentErrors||[])));this.hasWarning&&(o._currentWarnings=[],(a=o._currentWarnings).push.apply(a,g(this.currentWarnings||[])));return o.variablesState=this.variablesState,o.variablesState.callStack=o.callStack,o.variablesState.patch=o._patch,(r=o.evaluationStack).push.apply(r,g(this.evaluationStack)),this.divertedPointer.isNull||(o.divertedPointer=this.divertedPointer.copy()),o.previousPointer=this.previousPointer.copy(),o._visitCounts=this._visitCounts,o._turnIndices=this._turnIndices,o.currentTurnIndex=this.currentTurnIndex,o.storySeed=this.storySeed,o.previousRandom=this.previousRandom,o.didSafeExit=this.didSafeExit,o}},{key:"RestoreAfterPatch",value:function(){this.variablesState.callStack=this.callStack,this.variablesState.patch=this._patch}},{key:"ApplyAnyPatch",value:function(){if(null!==this._patch){this.variablesState.ApplyPatch();var t,e=S(this._patch.visitCounts);try{for(e.s();!(t=e.n()).done;){var n=m(t.value,2),r=n[0],i=n[1];this.ApplyCountChanges(r,i,!0)}}catch(t){e.e(t)}finally{e.f()}var a,o=S(this._patch.turnIndices);try{for(o.s();!(a=o.n()).done;){var s=m(a.value,2),l=s[0],u=s[1];this.ApplyCountChanges(l,u,!1)}}catch(t){o.e(t)}finally{o.f()}this._patch=null}}},{key:"ApplyCountChanges",value:function(t,e,n){(n?this._visitCounts:this._turnIndices).set(t.path.toString(),e)}},{key:"WriteJson",value:function(e){var n=this;if(e.WriteObjectStart(),e.WritePropertyStart("flows"),e.WriteObjectStart(),null!==this._namedFlows){var r,i=S(this._namedFlows);try{var a=function(){var t=m(r.value,2),n=t[0],i=t[1];e.WriteProperty(n,(function(t){return i.WriteJson(t)}))};for(i.s();!(r=i.n()).done;)a()}catch(t){i.e(t)}finally{i.f()}}else e.WriteProperty(this._currentFlow.name,(function(t){return n._currentFlow.WriteJson(t)}));if(e.WriteObjectEnd(),e.WritePropertyEnd(),e.WriteProperty("currentFlowName",this._currentFlow.name),e.WriteProperty("variablesState",(function(t){return n.variablesState.WriteJson(t)})),e.WriteProperty("evalStack",(function(t){return fe.WriteListRuntimeObjs(t,n.evaluationStack)})),!this.divertedPointer.isNull){if(null===this.divertedPointer.path)return L("divertedPointer");e.WriteProperty("currentDivertTarget",this.divertedPointer.path.componentsString)}e.WriteProperty("visitCounts",(function(t){return fe.WriteIntDictionary(t,n._visitCounts)})),e.WriteProperty("turnIndices",(function(t){return fe.WriteIntDictionary(t,n._turnIndices)})),e.WriteIntProperty("turnIdx",this.currentTurnIndex),e.WriteIntProperty("storySeed",this.storySeed),e.WriteIntProperty("previousRandom",this.previousRandom),e.WriteIntProperty("inkSaveVersion",this.kInkSaveStateVersion),e.WriteIntProperty("inkFormatVersion",t.Story.inkVersionCurrent),e.WriteObjectEnd()}},{key:"LoadJsonObj",value:function(t){var e=t,n=e.inkSaveVersion;if(null==n)throw new Error("ink save format incorrect, can't load.");if(parseInt(n)1){var h=e.currentFlowName;this._currentFlow=this._namedFlows.get(h)}}else{this._namedFlows=null,this._currentFlow.name=this.kDefaultFlowName,this._currentFlow.callStack.SetJsonToken(e.callstackThreads,this.story),this._currentFlow.outputStream=fe.JArrayToRuntimeObjList(e.outputStream),this._currentFlow.currentChoices=fe.JArrayToRuntimeObjList(e.currentChoices);var f=e.choiceThreads;this._currentFlow.LoadFlowChoiceThreads(f,this.story)}this.OutputStreamDirty(),this._aliveFlowNamesDirty=!0,this.variablesState.SetJsonToken(e.variablesState),this.variablesState.callStack=this._currentFlow.callStack,this._evaluationStack=fe.JArrayToRuntimeObjList(e.evalStack);var d=e.currentDivertTarget;if(null!=d){var v=new R(d.toString());this.divertedPointer=this.story.PointerAtPath(v)}this._visitCounts=fe.JObjectToIntDictionary(e.visitCounts),this._turnIndices=fe.JObjectToIntDictionary(e.turnIndices),this.currentTurnIndex=parseInt(e.turnIdx),this.storySeed=parseInt(e.storySeed),this.previousRandom=parseInt(e.previousRandom)}},{key:"ResetErrors",value:function(){this._currentErrors=null,this._currentWarnings=null}},{key:"ResetOutput",value:function(){var t,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;this.outputStream.length=0,null!==e&&(t=this.outputStream).push.apply(t,g(e)),this.OutputStreamDirty()}},{key:"PushToOutputStream",value:function(t){var e=_(t,$);if(null!==e){var n=this.TrySplittingHeadTailWhitespace(e);if(null!==n){var r,i=S(n);try{for(i.s();!(r=i.n()).done;){var a=r.value;this.PushToOutputStreamIndividual(a)}}catch(t){i.e(t)}finally{i.f()}return void this.OutputStreamDirty()}}this.PushToOutputStreamIndividual(t),this.OutputStreamDirty()}},{key:"PopFromOutputStream",value:function(t){this.outputStream.splice(this.outputStream.length-t,t),this.OutputStreamDirty()}},{key:"TrySplittingHeadTailWhitespace",value:function(t){var e=t.value;if(null===e)return L("single.value");for(var n=-1,r=-1,i=0;i=0;l--){var u=e[l];if("\n"!=u){if(" "==u||"\t"==u)continue;break}-1==o&&(o=l),s=l}if(-1==n&&-1==o)return null;var c=[],h=0,f=e.length;if(-1!=n){if(n>0){var d=new $(e.substring(0,n));c.push(d)}c.push(new $("\n")),h=r+1}if(-1!=o&&(f=s),f>h){var v=e.substring(h,f);c.push(new $(v))}if(-1!=o&&s>r&&(c.push(new $("\n")),o=0;s--){var l=this.outputStream[s],u=l instanceof et?l:null;if(null!=(l instanceof ee?l:null)){o=s;break}if(null!=u&&u.commandType==et.CommandType.BeginString){s>=i&&(i=-1);break}}if(-1!=(-1!=o&&-1!=i?Math.min(i,o):-1!=o?o:i)){if(n.isNewline)r=!1;else if(n.isNonWhitespace&&(o>-1&&this.RemoveExistingGlue(),i>-1))for(var c=this.callStack.elements,h=c.length-1;h>=0;h--){var f=c[h];if(f.type!=ct.Function)break;f.functionStartInOutputStream=-1}}else n.isNewline&&(!this.outputStreamEndsInNewline&&this.outputStreamContainsContent||(r=!1))}if(r){if(null===t)return L("obj");this.outputStream.push(t),this.OutputStreamDirty()}}},{key:"TrimNewlinesFromOutputStream",value:function(){for(var t=-1,e=this.outputStream.length-1;e>=0;){var n=this.outputStream[e],r=_(n,et),i=_(n,$);if(null!=r||null!=i&&i.isNonWhitespace)break;null!=i&&i.isNewline&&(t=e),e--}if(t>=0)for(e=t;e=0;t--){var e=this.outputStream[t];if(e instanceof ee)this.outputStream.splice(t,1);else if(e instanceof et)break}this.OutputStreamDirty()}},{key:"outputStreamEndsInNewline",get:function(){if(this.outputStream.length>0)for(var t=this.outputStream.length-1;t>=0;t--){if(this.outputStream[t]instanceof et)break;var e=this.outputStream[t];if(e instanceof $){if(e.isNewline)return!0;if(e.isNonWhitespace)break}}return!1}},{key:"outputStreamContainsContent",get:function(){var t,e=S(this.outputStream);try{for(e.s();!(t=e.n()).done;){if(t.value instanceof $)return!0}}catch(t){e.e(t)}finally{e.f()}return!1}},{key:"inStringEvaluation",get:function(){for(var t=this.outputStream.length-1;t>=0;t--){var e=_(this.outputStream[t],et);if(e instanceof et&&e.commandType==et.CommandType.BeginString)return!0}return!1}},{key:"PushEvaluationStack",value:function(t){var e=_(t,Z);if(e){var n=e.value;if(null===n)return L("rawList");if(null!=n.originNames){n.origins||(n.origins=[]),n.origins.length=0;var r,i=S(n.originNames);try{for(i.s();!(r=i.n()).done;){var a=r.value;if(null===this.story.listDefinitions)return L("StoryState.story.listDefinitions");var o=this.story.listDefinitions.TryListGetDefinition(a,null);if(null===o.result)return L("StoryState def.result");n.origins.indexOf(o.result)<0&&n.origins.push(o.result)}}catch(t){i.e(t)}finally{i.f()}}}if(null===t)return L("obj");this.evaluationStack.push(t)}},{key:"PopEvaluationStack",value:function(t){if(void 0===t)return P(this.evaluationStack.pop());if(t>this.evaluationStack.length)throw new Error("trying to pop too many objects");return P(this.evaluationStack.splice(this.evaluationStack.length-t,t))}},{key:"PeekEvaluationStack",value:function(){return this.evaluationStack[this.evaluationStack.length-1]}},{key:"ForceEnd",value:function(){this.callStack.Reset(),this._currentFlow.currentChoices.length=0,this.currentPointer=dt.Null,this.previousPointer=dt.Null,this.didSafeExit=!0}},{key:"TrimWhitespaceFromFunctionEnd",value:function(){I.Assert(this.callStack.currentElement.type==ct.Function);var t=this.callStack.currentElement.functionStartInOutputStream;-1==t&&(t=0);for(var e=this.outputStream.length-1;e>=t;e--){var n=this.outputStream[e],r=_(n,$),i=_(n,et);if(null!=r){if(i)break;if(!r.isNewline&&!r.isInlineWhitespace)break;this.outputStream.splice(e,1),this.OutputStreamDirty()}}}},{key:"PopCallStack",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;this.callStack.currentElement.type==ct.Function&&this.TrimWhitespaceFromFunctionEnd(),this.callStack.Pop(t)}},{key:"SetChosenPath",value:function(t,e){this._currentFlow.currentChoices.length=0;var n=this.story.PointerAtPath(t);n.isNull||-1!=n.index||(n.index=0),this.currentPointer=n,e&&this.currentTurnIndex++}},{key:"StartFunctionEvaluationFromGame",value:function(t,e){this.callStack.Push(ct.FunctionEvaluationFromGame,this.evaluationStack.length),this.callStack.currentElement.currentPointer=dt.StartOf(t),this.PassArgumentsToEvaluationStack(e)}},{key:"PassArgumentsToEvaluationStack",value:function(t){if(null!==t)for(var e=0;et;){var n=this.PopEvaluationStack();null===e&&(e=n)}if(this.PopCallStack(ct.FunctionEvaluationFromGame),e){if(e instanceof rt)return null;var r=T(e,K);return r.valueType==U.DivertTarget?r.valueObject.toString():r.valueObject}return null}},{key:"AddError",value:function(t,e){e?(null==this._currentWarnings&&(this._currentWarnings=[]),this._currentWarnings.push(t)):(null==this._currentErrors&&(this._currentErrors=[]),this._currentErrors.push(t))}},{key:"OutputStreamDirty",value:function(){this._outputStreamTextDirty=!0,this._outputStreamTagsDirty=!0}}]),e}(),be=function(){function t(){n(this,t),this.startTime=void 0}return i(t,[{key:"ElapsedMilliseconds",get:function(){return void 0===this.startTime?0:(new Date).getTime()-this.startTime}},{key:"Start",value:function(){this.startTime=(new Date).getTime()}},{key:"Stop",value:function(){this.startTime=void 0}}]),t}();!function(t){t[t.Author=0]="Author",t[t.Warning=1]="Warning",t[t.Error=2]="Error"}(ye||(ye={})),Number.isInteger||(Number.isInteger=function(t){return"number"==typeof t&&isFinite(t)&&t>-9007199254740992&&t<9007199254740992&&Math.floor(t)===t}),t.Story=function(t){a(o,t);var r=d(o);function o(){var t,e;n(this,o),(t=r.call(this)).inkVersionMinimumCompatible=18,t.onError=null,t.onDidContinue=null,t.onMakeChoice=null,t.onEvaluateFunction=null,t.onCompleteEvaluateFunction=null,t.onChoosePathString=null,t._prevContainers=[],t.allowExternalFunctionFallbacks=!1,t._listDefinitions=null,t._variableObservers=null,t._hasValidatedExternals=!1,t._temporaryEvaluationContainer=null,t._asyncContinueActive=!1,t._stateSnapshotAtLastNewline=null,t._sawLookaheadUnsafeFunctionAfterNewline=!1,t._recursiveContinueCount=0,t._asyncSaving=!1,t._profiler=null;var i=null,a=null;if(arguments[0]instanceof tt)e=arguments[0],void 0!==arguments[1]&&(i=arguments[1]),t._mainContentContainer=e;else if("string"==typeof arguments[0]){var s=arguments[0];a=ge.TextToDictionary(s)}else a=arguments[0];if(null!=i&&(t._listDefinitions=new he(i)),t._externals=new Map,null!==a){var l=a,u=l.inkVersion;if(null==u)throw new Error("ink version number not found. Are you sure it's a valid .ink.json file?");var c=parseInt(u);if(c>o.inkVersionCurrent)throw new Error("Version of ink used to build story was newer than the current version of the engine");if(c0&&void 0!==arguments[0]?arguments[0]:0;null!=this._profiler&&this._profiler.PreContinue();var e=t>0;if(this._recursiveContinueCount++,!this._asyncContinueActive){if(this._asyncContinueActive=e,!this.canContinue)throw new Error("Can't continue - should check canContinue before calling Continue");this._state.didSafeExit=!1,this._state.ResetOutput(),1==this._recursiveContinueCount&&(this._state.variablesState.batchObservingVariableChanges=!0)}var n=new be;n.Start();var r=!1;this._sawLookaheadUnsafeFunctionAfterNewline=!1;do{try{r=this.ContinueSingleStep()}catch(t){if(!(t instanceof G))throw t;this.AddError(t.message,void 0,t.useEndLineNumber);break}if(r)break;if(this._asyncContinueActive&&n.ElapsedMilliseconds>t)break}while(this.canContinue);if(n.Stop(),!r&&this.canContinue||(null!==this._stateSnapshotAtLastNewline&&this.RestoreStateSnapshot(),this.canContinue||(this.state.callStack.canPopThread&&this.AddError("Thread available to pop, threads should always be flat by the end of evaluation?"),0!=this.state.generatedChoices.length||this.state.didSafeExit||null!=this._temporaryEvaluationContainer||(this.state.callStack.CanPop(ct.Tunnel)?this.AddError("unexpectedly reached end of content. Do you need a '->->' to return from a tunnel?"):this.state.callStack.CanPop(ct.Function)?this.AddError("unexpectedly reached end of content. Do you need a '~ return'?"):this.state.callStack.canPop?this.AddError("unexpectedly reached end of content for unknown reason. Please debug compiler!"):this.AddError("ran out of content. Do you need a '-> DONE' or '-> END'?"))),this.state.didSafeExit=!1,this._sawLookaheadUnsafeFunctionAfterNewline=!1,1==this._recursiveContinueCount&&(this._state.variablesState.batchObservingVariableChanges=!1),this._asyncContinueActive=!1,null!==this.onDidContinue&&this.onDidContinue()),this._recursiveContinueCount--,null!=this._profiler&&this._profiler.PostContinue(),this.state.hasError||this.state.hasWarning){if(null===this.onError){var i=new j;throw i.Append("Ink had "),this.state.hasError&&(i.Append("".concat(this.state.currentErrors.length)),i.Append(1==this.state.currentErrors.length?" error":"errors"),this.state.hasWarning&&i.Append(" and ")),this.state.hasWarning&&(i.Append("".concat(this.state.currentWarnings.length)),i.Append(1==this.state.currentWarnings.length?" warning":"warnings"),this.state.hasWarning&&i.Append(" and ")),i.Append(". It is strongly suggested that you assign an error handler to story.onError. The first issue was: "),i.Append(this.state.hasError?this.state.currentErrors[0]:this.state.currentWarnings[0]),new G(i.toString())}if(this.state.hasError){var a,o=S(this.state.currentErrors);try{for(o.s();!(a=o.n()).done;){var s=a.value;this.onError(s,ye.Error)}}catch(s){o.e(s)}finally{o.f()}}if(this.state.hasWarning){var l,u=S(this.state.currentWarnings);try{for(u.s();!(l=u.n()).done;){var c=l.value;this.onError(c,ye.Warning)}}catch(s){u.e(s)}finally{u.f()}}this.ResetErrors()}}},{key:"ContinueSingleStep",value:function(){if(null!=this._profiler&&this._profiler.PreStep(),this.Step(),null!=this._profiler&&this._profiler.PostStep(),this.canContinue||this.state.callStack.elementIsEvaluateFromGame||this.TryFollowDefaultInvisibleChoice(),null!=this._profiler&&this._profiler.PreSnapshot(),!this.state.inStringEvaluation){if(null!==this._stateSnapshotAtLastNewline){if(null===this._stateSnapshotAtLastNewline.currentTags)return L("this._stateAtLastNewline.currentTags");if(null===this.state.currentTags)return L("this.state.currentTags");var t=this.CalculateNewlineOutputStateChange(this._stateSnapshotAtLastNewline.currentText,this.state.currentText,this._stateSnapshotAtLastNewline.currentTags.length,this.state.currentTags.length);if(t==o.OutputStateChange.ExtendedBeyondNewline||this._sawLookaheadUnsafeFunctionAfterNewline)return this.RestoreStateSnapshot(),!0;t==o.OutputStateChange.NewlineRemoved&&this.DiscardSnapshot()}this.state.outputStreamEndsInNewline&&(this.canContinue?null==this._stateSnapshotAtLastNewline&&this.StateSnapshot():this.DiscardSnapshot())}return null!=this._profiler&&this._profiler.PostSnapshot(),!1}},{key:"CalculateNewlineOutputStateChange",value:function(t,e,n,r){if(null===t)return L("prevText");if(null===e)return L("currText");var i=e.length>=t.length&&t.length>0&&"\n"==e.charAt(t.length-1);if(n==r&&t.length==e.length&&i)return o.OutputStateChange.NoChange;if(!i)return o.OutputStateChange.NewlineRemoved;if(r>n)return o.OutputStateChange.ExtendedBeyondNewline;for(var a=t.length;a0?this.Error("Failed to find content at path '"+t+"', and no approximation of it was possible."):r.approximate&&this.Warning("Failed to find content at path '"+t+"', so it was approximated to: '"+r.obj.path+"'."),e)}},{key:"StateSnapshot",value:function(){this._stateSnapshotAtLastNewline=this._state,this._state=this._state.CopyAndStartPatching()}},{key:"RestoreStateSnapshot",value:function(){null===this._stateSnapshotAtLastNewline&&L("_stateSnapshotAtLastNewline"),this._stateSnapshotAtLastNewline.RestoreAfterPatch(),this._state=this._stateSnapshotAtLastNewline,this._stateSnapshotAtLastNewline=null,this._asyncSaving||this._state.ApplyAnyPatch()}},{key:"DiscardSnapshot",value:function(){this._asyncSaving||this._state.ApplyAnyPatch(),this._stateSnapshotAtLastNewline=null}},{key:"CopyStateForBackgroundThreadSave",value:function(){if(this.IfAsyncWeCant("start saving on a background thread"),this._asyncSaving)throw new Error("Story is already in background saving mode, can't call CopyStateForBackgroundThreadSave again!");var t=this._state;return this._state=this._state.CopyAndStartPatching(),this._asyncSaving=!0,t}},{key:"BackgroundSaveComplete",value:function(){null===this._stateSnapshotAtLastNewline&&this._state.ApplyAnyPatch(),this._asyncSaving=!1}},{key:"Step",value:function(){var t=!0,e=this.state.currentPointer.copy();if(!e.isNull){for(var n=_(e.Resolve(),tt);n&&(this.VisitContainer(n,!0),0!=n.content.length);)n=_((e=dt.StartOf(n)).Resolve(),tt);this.state.currentPointer=e.copy(),null!=this._profiler&&this._profiler.Step(this.state.callStack);var r=e.Resolve(),i=this.PerformLogicAndFlowControl(r);if(!this.state.currentPointer.isNull){i&&(t=!1);var a=_(r,ht);if(a){var o=this.ProcessChoice(a);o&&this.state.generatedChoices.push(o),r=null,t=!1}if(r instanceof tt&&(t=!1),t){var s=_(r,Y);if(s&&-1==s.contextIndex){var l=this.state.callStack.ContextForVariableNamed(s.variableName);r=new Y(s.variableName,l)}this.state.inExpressionEvaluation?this.state.PushEvaluationStack(r):this.state.PushToOutputStream(r)}this.NextContent();var u=_(r,et);u&&u.commandType==et.CommandType.StartThread&&this.state.callStack.PushThread()}}}},{key:"VisitContainer",value:function(t,e){t.countingAtStartOnly&&!e||(t.visitsShouldBeCounted&&this.state.IncrementVisitCountForContainer(t),t.turnIndexShouldBeCounted&&this.state.RecordTurnIndexVisitToContainer(t))}},{key:"VisitChangedContainersDueToDivert",value:function(){var t=this.state.previousPointer.copy(),e=this.state.currentPointer.copy();if(!e.isNull&&-1!=e.index){if(this._prevContainers.length=0,!t.isNull)for(var n=_(t.Resolve(),tt)||_(t.container,tt);n;)this._prevContainers.push(n),n=_(n.parent,tt);var r=e.Resolve();if(null!=r)for(var i=_(r.parent,tt),a=!0;i&&(this._prevContainers.indexOf(i)<0||i.countingAtStartOnly);){var o=i.content.length>0&&r==i.content[0]&&a;o||(a=!1),this.VisitContainer(i,o),r=i,i=_(i.parent,tt)}}}},{key:"PopChoiceStringAndTags",value:function(t){for(var e=T(this.state.PopEvaluationStack(),$);this.state.evaluationStack.length>0&&null!=_(this.state.PeekEvaluationStack(),ue);){var n=_(this.state.PopEvaluationStack(),ue);n&&t.push(n.text)}return e.value}},{key:"ProcessChoice",value:function(t){var e=!0;if(t.hasCondition){var n=this.state.PopEvaluationStack();this.IsTruthy(n)||(e=!1)}var r="",i="",a=[];(t.hasChoiceOnlyContent&&(i=this.PopChoiceStringAndTags(a)||""),t.hasStartContent&&(r=this.PopChoiceStringAndTags(a)||""),t.onceOnly)&&(this.state.VisitCountForContainer(t.choiceTarget)>0&&(e=!1));if(!e)return null;var o=new ce;return o.targetPath=t.pathOnChoice,o.sourcePath=t.path.toString(),o.isInvisibleDefault=t.isInvisibleDefault,o.threadAtGeneration=this.state.callStack.ForkThread(),o.tags=a.reverse(),o.text=(r+i).replace(/^[ \t]+|[ \t]+$/g,""),o}},{key:"IsTruthy",value:function(t){if(t instanceof K){var e=t;if(e instanceof X){var n=e;return this.Error("Shouldn't use a divert target (to "+n.targetPath+") as a conditional value. Did you intend a function call 'likeThis()' or a read count check 'likeThis'? (no arrows)"),!1}return e.isTruthy}return!1}},{key:"PerformLogicAndFlowControl",value:function(t){if(null==t)return!1;if(t instanceof vt){var e=t;if(e.isConditional){var n=this.state.PopEvaluationStack();if(!this.IsTruthy(n))return!0}if(e.hasVariableTarget){var r=e.variableDivertName,i=this.state.variablesState.GetVariableWithName(r);if(null==i)this.Error("Tried to divert using a target from a variable that could not be found ("+r+")");else if(!(i instanceof X)){var a=_(i,J),o="Tried to divert to a target from a variable, but the variable ("+r+") didn't contain a divert target, it ";a instanceof J&&0==a.value?o+="was empty/null (the value 0).":o+="contained '"+i+"'.",this.Error(o)}var s=T(i,X);this.state.divertedPointer=this.PointerAtPath(s.targetPath)}else{if(e.isExternal)return this.CallExternalFunction(e.targetPathString,e.externalArgs),!0;this.state.divertedPointer=e.targetPointer.copy()}return e.pushesToStack&&this.state.callStack.Push(e.stackPushType,void 0,this.state.outputStream.length),this.state.divertedPointer.isNull&&!e.isExternal&&(e&&e.debugMetadata&&null!=e.debugMetadata.sourceName?this.Error("Divert target doesn't exist: "+e.debugMetadata.sourceName):this.Error("Divert resolution failed: "+e)),!0}if(t instanceof et){var l=t;switch(l.commandType){case et.CommandType.EvalStart:this.Assert(!1===this.state.inExpressionEvaluation,"Already in expression evaluation?"),this.state.inExpressionEvaluation=!0;break;case et.CommandType.EvalEnd:this.Assert(!0===this.state.inExpressionEvaluation,"Not in expression evaluation mode"),this.state.inExpressionEvaluation=!1;break;case et.CommandType.EvalOutput:if(this.state.evaluationStack.length>0){var u=this.state.PopEvaluationStack();if(!(u instanceof rt)){var c=new $(u.toString());this.state.PushToOutputStream(c)}}break;case et.CommandType.NoOp:break;case et.CommandType.Duplicate:this.state.PushEvaluationStack(this.state.PeekEvaluationStack());break;case et.CommandType.PopEvaluatedValue:this.state.PopEvaluationStack();break;case et.CommandType.PopFunction:case et.CommandType.PopTunnel:var h=l.commandType==et.CommandType.PopFunction?ct.Function:ct.Tunnel,f=null;if(h==ct.Tunnel){var d=this.state.PopEvaluationStack();null===(f=_(d,X))&&this.Assert(d instanceof rt,"Expected void if ->-> doesn't override target")}if(this.state.TryExitFunctionEvaluationFromGame())break;if(this.state.callStack.currentElement.type==h&&this.state.callStack.canPop)this.state.PopCallStack(),f&&(this.state.divertedPointer=this.PointerAtPath(f.targetPath));else{var v=new Map;v.set(ct.Function,"function return statement (~ return)"),v.set(ct.Tunnel,"tunnel onwards statement (->->)");var p=v.get(this.state.callStack.currentElement.type);this.state.callStack.canPop||(p="end of flow (-> END or choice)");var m="Found "+v.get(h)+", when expected "+p;this.Error(m)}break;case et.CommandType.BeginString:this.state.PushToOutputStream(l),this.Assert(!0===this.state.inExpressionEvaluation,"Expected to be in an expression when evaluating a string"),this.state.inExpressionEvaluation=!1;break;case et.CommandType.BeginTag:this.state.PushToOutputStream(l);break;case et.CommandType.EndTag:if(this.state.inStringEvaluation){for(var g=[],y=0,C=this.state.outputStream.length-1;C>=0;--C){var b=this.state.outputStream[C];y++;var w=_(b,et);if(null!=w){if(w.commandType==et.CommandType.BeginTag)break;this.Error("Unexpected ControlCommand while extracting tag from choice");break}b instanceof $&&g.push(b)}this.state.PopFromOutputStream(y);for(var k=new j,E=0,A=g;E=0;--F){var W=this.state.outputStream[F];I++;var R=_(W,et);if(R&&R.commandType==et.CommandType.BeginString)break;W instanceof ue&&O.push(W),W instanceof $&&x.push(W)}this.state.PopFromOutputStream(I);for(var D=0,V=O;DNumber.MAX_SAFE_INTEGER)&&(ft=Number.MAX_SAFE_INTEGER,this.Error("RANDOM was called with a range that exceeds the size that ink numbers can use.")),ft<=0&&this.Error("RANDOM was called with minimum as "+ht.value+" and maximum as "+ut.value+". The maximum must be larger");var mt=this.state.storySeed+this.state.previousRandom,gt=new pe(mt).next(),yt=gt%ft+ht.value;this.state.PushEvaluationStack(new J(yt)),this.state.previousRandom=gt;break;case et.CommandType.SeedRandom:var Ct=_(this.state.PopEvaluationStack(),J);if(null==Ct||Ct instanceof J==!1)return this.Error("Invalid value passed to SEED_RANDOM");if(null===Ct.value)return L("minInt.value");this.state.storySeed=Ct.value,this.state.previousRandom=0,this.state.PushEvaluationStack(new rt);break;case et.CommandType.VisitIndex:var St=this.state.VisitCountForContainer(this.state.currentPointer.container)-1;this.state.PushEvaluationStack(new J(St));break;case et.CommandType.SequenceShuffleIndex:var bt=this.NextSequenceShuffleIndex();this.state.PushEvaluationStack(new J(bt));break;case et.CommandType.StartThread:break;case et.CommandType.Done:this.state.callStack.canPopThread?this.state.callStack.PopThread():(this.state.didSafeExit=!0,this.state.currentPointer=dt.Null);break;case et.CommandType.End:this.state.ForceEnd();break;case et.CommandType.ListFromInt:var wt=_(this.state.PopEvaluationStack(),J),kt=T(this.state.PopEvaluationStack(),$);if(null===wt)throw new G("Passed non-integer when creating a list element from a numerical value.");var Et=null;if(null===this.listDefinitions)return L("this.listDefinitions");var _t=this.listDefinitions.TryListGetDefinition(kt.value,null);if(!_t.exists)throw new G("Failed to find LIST called "+kt.value);if(null===wt.value)return L("minInt.value");var Tt=_t.result.TryGetItemWithValue(wt.value,B.Null);Tt.exists&&(Et=new Z(Tt.result,wt.value)),null==Et&&(Et=new Z),this.state.PushEvaluationStack(Et);break;case et.CommandType.ListRange:var At=_(this.state.PopEvaluationStack(),K),Pt=_(this.state.PopEvaluationStack(),K),Nt=_(this.state.PopEvaluationStack(),Z);if(null===Nt||null===Pt||null===At)throw new G("Expected list, minimum and maximum for LIST_RANGE");if(null===Nt.value)return L("targetList.value");var xt=Nt.value.ListWithSubRange(Pt.valueObject,At.valueObject);this.state.PushEvaluationStack(new Z(xt));break;case et.CommandType.ListRandom:var Ot=this.state.PopEvaluationStack();if(null===Ot)throw new G("Expected list for LIST_RANDOM");var It=Ot.value,Wt=null;if(null===It)throw L("list");if(0==It.Count)Wt=new M;else{for(var Rt=this.state.storySeed+this.state.previousRandom,Dt=new pe(Rt).next(),Lt=Dt%It.Count,Vt=It.entries(),jt=0;jt<=Lt-1;jt++)Vt.next();var Bt=Vt.next().value,Mt={Key:B.fromSerializedKey(Bt[0]),Value:Bt[1]};if(null===Mt.Key.originName)return L("randomItem.Key.originName");(Wt=new M(Mt.Key.originName,this)).Add(Mt.Key,Mt.Value),this.state.previousRandom=Dt}this.state.PushEvaluationStack(new Z(Wt));break;default:this.Error("unhandled ControlCommand: "+l)}return!0}if(t instanceof pt){var Gt=t,qt=this.state.PopEvaluationStack();return this.state.variablesState.Assign(Gt,qt),!0}if(t instanceof Ft){var Ut=t,Kt=null;if(null!=Ut.pathForCount){var Ht=Ut.containerForCount,Jt=this.state.VisitCountForContainer(Ht);Kt=new J(Jt)}else null==(Kt=this.state.variablesState.GetVariableWithName(Ut.name))&&(this.Warning("Variable not found: '"+Ut.name+"'. Using default value of 0 (false). This can happen with temporary variables if the declaration hasn't yet been hit. Globals are always given a default value on load if a value doesn't exist in the save state."),Kt=new J(0));return this.state.PushEvaluationStack(Kt),!0}if(t instanceof it){var zt=t,$t=this.state.PopEvaluationStack(zt.numberOfParameters),Xt=zt.Call($t);return this.state.PushEvaluationStack(Xt),!0}return!1}},{key:"ChoosePathString",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];if(this.IfAsyncWeCant("call ChoosePathString right now"),null!==this.onChoosePathString&&this.onChoosePathString(t,n),e)this.ResetCallstack();else if(this.state.callStack.currentElement.type==ct.Function){var r="",i=this.state.callStack.currentElement.currentPointer.container;throw null!=i&&(r="("+i.path.toString()+") "),new Error("Story was running a function "+r+"when you called ChoosePathString("+t+") - this is almost certainly not not what you want! Full stack trace: \n"+this.state.callStack.callStackTrace)}this.state.PassArgumentsToEvaluationStack(n),this.ChoosePath(new R(t))}},{key:"IfAsyncWeCant",value:function(t){if(this._asyncContinueActive)throw new Error("Can't "+t+". Story is in the middle of a ContinueAsync(). Make more ContinueAsync() calls or a single Continue() call beforehand.")}},{key:"ChoosePath",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.state.SetChosenPath(t,e),this.VisitChangedContainersDueToDivert()}},{key:"ChooseChoiceIndex",value:function(t){t=t;var e=this.currentChoices;this.Assert(t>=0&&t1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(null!==this.onEvaluateFunction&&this.onEvaluateFunction(t,e),this.IfAsyncWeCant("evaluate a function"),null==t)throw new Error("Function is null");if(""==t||""==t.trim())throw new Error("Function is empty or white space.");var r=this.KnotContainerWithName(t);if(null==r)throw new Error("Function doesn't exist: '"+t+"'");var i=[];i.push.apply(i,g(this.state.outputStream)),this._state.ResetOutput(),this.state.StartFunctionEvaluationFromGame(r,e);for(var a=new j;this.canContinue;)a.Append(this.Continue());var o=a.toString();this._state.ResetOutput(i);var s=this.state.CompleteFunctionEvaluationFromGame();return null!=this.onCompleteEvaluateFunction&&this.onCompleteEvaluateFunction(t,e,o,s),n?{returned:s,output:o}:s}},{key:"EvaluateExpression",value:function(t){var e=this.state.callStack.elements.length;this.state.callStack.Push(ct.Tunnel),this._temporaryEvaluationContainer=t,this.state.GoToStart();var n=this.state.evaluationStack.length;return this.Continue(),this._temporaryEvaluationContainer=null,this.state.callStack.elements.length>e&&this.state.PopCallStack(),this.state.evaluationStack.length>n?this.state.PopEvaluationStack():null}},{key:"CallExternalFunction",value:function(t,n){if(null===t)return L("funcName");var r=this._externals.get(t),i=null,a=void 0!==r;if(!a||r.lookAheadSafe||null===this._stateSnapshotAtLastNewline){if(!a){if(this.allowExternalFunctionFallbacks)return i=this.KnotContainerWithName(t),this.Assert(null!==i,"Trying to call EXTERNAL function '"+t+"' which has not been bound, and fallback ink function could not be found."),this.state.callStack.Push(ct.Function,void 0,this.state.outputStream.length),void(this.state.divertedPointer=dt.StartOf(i));this.Assert(!1,"Trying to call EXTERNAL function '"+t+"' which has not been bound (and ink fallbacks disabled).")}for(var o=[],s=0;s2&&void 0!==arguments[2])||arguments[2];this.IfAsyncWeCant("bind an external function"),this.Assert(!this._externals.has(t),"Function '"+t+"' has already been bound."),this._externals.set(t,{function:e,lookAheadSafe:n})}},{key:"TryCoerce",value:function(t){return t}},{key:"BindExternalFunction",value:function(t,e){var n=this,r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];this.Assert(null!=e,"Can't bind a null function"),this.BindExternalFunctionGeneral(t,(function(t){n.Assert(t.length>=e.length,"External function expected "+e.length+" arguments");for(var r=[],i=0,a=t.length;i1?"s":"",r+=": '",r+=Array.from(n).join("', '"),r+="' ",r+=this.allowExternalFunctionFallbacks?", and no fallback ink function found.":" (ink fallbacks disabled)",this.Error(r)}else if(null!=t){var i,a=S(t.content);try{for(a.s();!(i=a.n()).done;){var o=i.value,s=o;null!=s&&s.hasValidName||this.ValidateExternalBindings(o,n)}}catch(t){a.e(t)}finally{a.f()}var l,u=S(t.namedContent);try{for(u.s();!(l=u.n()).done;){var c=m(l.value,2),h=c[1];this.ValidateExternalBindings(_(h,V),n)}}catch(t){u.e(t)}finally{u.f()}}else if(null!=e){var f=_(e,vt);if(f&&f.isExternal){var d=f.targetPathString;if(null===d)return L("name");if(!this._externals.has(d))if(this.allowExternalFunctionFallbacks){var v=this.mainContentContainer.namedContent.has(d);v||n.add(d)}else n.add(d)}}}},{key:"ObserveVariable",value:function(t,e){if(this.IfAsyncWeCant("observe a new variable"),null===this._variableObservers&&(this._variableObservers=new Map),!this.state.variablesState.GlobalVariableExistsWithName(t))throw new Error("Cannot observe variable '"+t+"' because it wasn't declared in the ink story.");this._variableObservers.has(t)?this._variableObservers.get(t).push(e):this._variableObservers.set(t,[e])}},{key:"ObserveVariables",value:function(t,e){for(var n=0,r=t.length;n=e.container.content.length;){t=!1;var n=_(e.container.parent,tt);if(n instanceof tt==!1)break;var r=n.content.indexOf(e.container);if(-1==r)break;if((e=new dt(n,r)).index++,t=!0,null===e.container)return L("pointer.container")}return t||(e=dt.Null),this.state.callStack.currentElement.currentPointer=e.copy(),t}},{key:"TryFollowDefaultInvisibleChoice",value:function(){var t=this._state.currentChoices,e=t.filter((function(t){return t.isInvisibleDefault}));if(0==e.length||t.length>e.length)return!1;var n=e[0];return null===n.targetPath?L("choice.targetPath"):null===n.threadAtGeneration?L("choice.threadAtGeneration"):(this.state.callStack.currentThread=n.threadAtGeneration,null!==this._stateSnapshotAtLastNewline&&(this.state.callStack.currentThread=this.state.callStack.ForkThread()),this.ChoosePath(n.targetPath,!1),!0)}},{key:"NextSequenceShuffleIndex",value:function(){var t=_(this.state.PopEvaluationStack(),J);if(!(t instanceof J))return this.Error("expected number of elements in sequence for shuffle index"),0;var e=this.state.currentPointer.container;if(null===e)return L("seqContainer");if(null===t.value)return L("numElementsIntVal.value");var n=t.value,r=T(this.state.PopEvaluationStack(),J).value;if(null===r)return L("seqCount");for(var i=r/n,a=r%n,o=e.path.toString(),s=0,l=0,u=o.length;l1&&void 0!==arguments[1]&&arguments[1],n=new G(t);throw n.useEndLineNumber=e,n}},{key:"Warning",value:function(t){this.AddError(t,!0)}},{key:"AddError",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=this.currentDebugMetadata,i=e?"WARNING":"ERROR";if(null!=r){var a=n?r.endLineNumber:r.startLineNumber;t="RUNTIME "+i+": '"+r.fileName+"' line "+a+": "+t}else t=this.state.currentPointer.isNull?"RUNTIME "+i+": "+t:"RUNTIME "+i+": ("+this.state.currentPointer+"): "+t;this.state.AddError(t,e),e||this.state.ForceEnd()}},{key:"Assert",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(0==t)throw null==e&&(e="Story assert"),new Error(e+" "+this.currentDebugMetadata)}},{key:"currentDebugMetadata",get:function(){var t,e=this.state.currentPointer;if(!e.isNull&&null!==e.Resolve()&&null!==(t=e.Resolve().debugMetadata))return t;for(var n=this.state.callStack.elements.length-1;n>=0;--n)if(!(e=this.state.callStack.elements[n].currentPointer).isNull&&null!==e.Resolve()&&null!==(t=e.Resolve().debugMetadata))return t;for(var r=this.state.outputStream.length-1;r>=0;--r){if(null!==(t=this.state.outputStream[r].debugMetadata))return t}return null}},{key:"mainContentContainer",get:function(){return this._temporaryEvaluationContainer?this._temporaryEvaluationContainer:this._mainContentContainer}}]),o}(V),t.Story.inkVersionCurrent=21,function(t){var e;(e=t.OutputStateChange||(t.OutputStateChange={}))[e.NoChange=0]="NoChange",e[e.ExtendedBeyondNewline=1]="ExtendedBeyondNewline",e[e.NewlineRemoved=2]="NewlineRemoved"}(t.Story||(t.Story={}));var we=function(e){a(s,e);var r=d(s);function s(e){var i,a=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return n(this,s),(i=r.call(this,null,e,null,!1,a))._errorHandler=null,i._hadError=!1,i._hadWarning=!1,i._dontFlattenContainers=new Set,i._listDefs=new Map,i.constants=new Map,i.externals=new Map,i.countAllVisits=!1,i.ExportRuntime=function(){var e,n,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;i._errorHandler=r,i.constants=new Map;var a,o=S(i.FindAll(_t)());try{for(o.s();!(a=o.n()).done;){var s=a.value,l=i.constants.get(s.constantName);if(l&&!l.Equals(s.expression)){var u="CONST '".concat(s.constantName,"' has been redefined with a different value. Multiple definitions of the same CONST are valid so long as they contain the same value. Initial definition was on ").concat(l.debugMetadata,".");i.Error(u,s,!1)}i.constants.set(s.constantName,s.expression)}}catch(t){o.e(t)}finally{o.f()}i._listDefs=new Map;var c,f=S(i.FindAll(Ht)());try{for(f.s();!(c=f.n()).done;){var d=c.value;(null===(e=d.identifier)||void 0===e?void 0:e.name)&&i._listDefs.set(null===(n=d.identifier)||void 0===n?void 0:n.name,d)}}catch(t){f.e(t)}finally{f.f()}i.externals=new Map,i.ResolveWeavePointNaming();var v=i.runtimeObject,p=new tt;p.AddContent(et.EvalStart());var g,y=[],C=S(i.variableDeclarations);try{for(C.s();!(g=C.n()).done;){var b=m(g.value,2),w=b[0],k=b[1];if(k.isGlobalDeclaration){if(k.listDefinition)i._listDefs.set(w,k.listDefinition),p.AddContent(k.listDefinition.runtimeObject),y.push(k.listDefinition.runtimeListDefinition);else{if(!k.expression)throw new Error;k.expression.GenerateIntoContainer(p)}var E=new pt(w,!0);E.isGlobal=!0,p.AddContent(E)}}}catch(t){C.e(t)}finally{C.f()}p.AddContent(et.EvalEnd()),p.AddContent(et.End()),i.variableDeclarations.size>0&&(p.name="global decl",v.AddToNamedContentOnly(p)),v.AddContent(et.Done());var _=new t.Story(v,y);return i.runtimeObject=_,i.hadError?null:(i.FlattenContainersIn(v),i.ResolveReferences(h(i)),i.hadError?null:(_.ResetState(),_))},i.ResolveList=function(t){var e=i._listDefs.get(t);return e||null},i.ResolveListItem=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=null;if(t)return(r=i._listDefs.get(t))?r.ItemNamed(e):null;var a,o=null,s=null,l=S(i._listDefs.entries());try{for(l.s();!(a=l.n()).done;){var u=m(a.value,2),c=u[1],h=c.ItemNamed(e);h&&(o?i.Error("Ambiguous item name '".concat(e,"' found in multiple sets, including ").concat(s.identifier," and ").concat(c.identifier),n,!1):(o=h,s=c))}}catch(t){l.e(t)}finally{l.f()}return o},i.FlattenContainersIn=function(t){var e=new Set;if(t.content){var n,r=S(t.content);try{for(r.s();!(n=r.n()).done;){var a=_(n.value,tt);a&&e.add(a)}}catch(t){r.e(t)}finally{r.f()}}if(t.namedContent){var o,s=S(t.namedContent);try{for(s.s();!(o=s.n()).done;){var l=_(m(o.value,2)[1],tt);l&&e.add(l)}}catch(t){s.e(t)}finally{s.f()}}var u,c=S(e);try{for(c.s();!(u=c.n()).done;){var h=u.value;i.TryFlattenContainer(h),i.FlattenContainersIn(h)}}catch(t){c.e(t)}finally{c.f()}},i.TryFlattenContainer=function(t){if(!(t.namedContent&&t.namedContent.size>0||t.hasValidName||i._dontFlattenContainers.has(t))){var e=_(t.parent,tt);if(e){var n=e.content.indexOf(t);e.content.splice(n,1);var r=t.ownDebugMetadata;if(t.content){var a,o=S(t.content);try{for(o.s();!(a=o.n()).done;){var s=a.value;s.parent=null,null!==r&&null===s.ownDebugMetadata&&(s.debugMetadata=r),e.InsertContent(s,n),n+=1}}catch(t){o.e(t)}finally{o.f()}}}}},i.Error=function(t,e,n){var r=n?b.Warning:b.Error,a="";if(e instanceof W?(a+="TODO: ",r=b.Author):a+=n?"WARNING: ":"ERROR: ",e&&null!==e.debugMetadata&&e.debugMetadata.startLineNumber>=1&&(null!=e.debugMetadata.fileName&&(a+="'".concat(e.debugMetadata.fileName,"' ")),a+="line ".concat(e.debugMetadata.startLineNumber,": ")),t=a+=t,null===i._errorHandler)throw new Error(t);i._errorHandler(t,r),i._hadError=r===b.Error,i._hadWarning=r===b.Warning},i.ResetError=function(){i._hadError=!1,i._hadWarning=!1},i.IsExternal=function(t){return i.externals.has(t)},i.AddExternal=function(t){i.externals.has(t.name)?i.Error("Duplicate EXTERNAL definition of '".concat(t.name,"'"),t,!1):t.name&&i.externals.set(t.name,t)},i.DontFlattenContainer=function(t){i._dontFlattenContainers.add(t)},i.NameConflictError=function(t,e,n,r){t.Error("".concat(r," '").concat(e,"': name has already been used for a ").concat(n.typeName.toLowerCase()," on ").concat(n.debugMetadata))},i.CheckForNamingCollisions=function(t,e,n){var r,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"",o=a||t.typeName;if(s.IsReservedKeyword(null==e?void 0:e.name))t.Error("'".concat(e,"' cannot be used for the name of a ").concat(o.toLowerCase()," because it's a reserved keyword"));else if(Rt.IsBuiltIn((null==e?void 0:e.name)||""))t.Error("'".concat(e,"' cannot be used for the name of a ").concat(o.toLowerCase()," because it's a built in function"));else{var l=i.ContentWithNameAtLevel((null==e?void 0:e.name)||"",bt.Knot),u=_(l,Ot);if(!u||u===t&&n!==ft.Arg){if(!(n1&&void 0!==arguments[1]&&arguments[1];return n(this,r),(i=e.call(this)).GenerateRuntimeObject=function(){return i.isStart?et.BeginTag():et.EndTag()},i.toString=function(){return i.isStart?"#StartTag":"#EndTag"},i.isStart=t,i.inChoice=a,i}return i(r,[{key:"typeName",get:function(){return"Tag"}}]),r}(F),_e=i((function t(e){n(this,t),this.rootPath=e,this.ResolveInkFilename=function(){throw Error("Can't resolve filename because no FileHandler was provided when instantiating the parser / compiler.")},this.LoadInkFileContents=function(){throw Error("Can't load ink content because no FileHandler was provided when instantiating the parser / compiler.")}})),Te=function(t){a(o,t);var r=d(o);function o(t){var i,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,u=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;if(n(this,o),(i=r.call(this,t)).ParseStory=function(){var t=i.StatementsAtLevel(Xt.Top);return new we(t,i._rootParser!==h(i))},i.SeparatedList=function(t,e){var n=i.Parse(t);if(null===n)return null;var r=[];for(r.push(n);;){var a=i.BeginRule();if(null===e()){i.FailRule(a);break}var o=i.Parse(t);if(null===o){i.FailRule(a);break}i.SucceedRule(a),r.push(o)}return r},i.CreateDebugMetadata=function(t,e){var n=new Yt;return n.startLineNumber=((null==t?void 0:t.lineIndex)||0)+1,n.endLineNumber=e.lineIndex+1,n.startCharacterNumber=((null==t?void 0:t.characterInLineIndex)||0)+1,n.endCharacterNumber=e.characterInLineIndex+1,n.fileName=i._filename,n},i.RuleDidSucceed=function(t,e,n){var r=_(t,F);r&&(r.debugMetadata=i.CreateDebugMetadata(e,n));var a=Array.isArray(t)?t:null;if(null!==a){var o,s=S(a);try{for(s.s();!(o=s.n()).done;){var l=o.value;_(l,F)&&(l.hasOwnDebugMetadata||(l.debugMetadata=i.CreateDebugMetadata(e,n)))}}catch(t){s.e(t)}finally{s.f()}}var u=_(t,xt);null!=u&&(u.debugMetadata=i.CreateDebugMetadata(e,n))},i.OnStringParserError=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],a=r?"WARNING:":"ERROR:",o=a;if(null!==i._filename&&(o+=" '".concat(i._filename,"'")),o+=" line ".concat(n+1,": ").concat(t),null===i._externalErrorHandler)throw new Error(o);i._externalErrorHandler(o,r?b.Warning:b.Error)},i.AuthorWarning=function(){i.Whitespace();var t=i.Parse(i.IdentifierWithMetadata);if(null===t||"TODO"!==t.name)return null;i.Whitespace(),i.ParseString(":"),i.Whitespace();var e=i.ParseUntilCharactersFromString("\n\r");return e?new W(e):null},i.ExtendIdentifierCharacterRanges=function(t){var e,n=S(o.ListAllCharacterRanges());try{for(n.s();!(e=n.n()).done;){var r=e.value;t.AddCharacters(r.ToCharacterSet())}}catch(t){n.e(t)}finally{n.f()}},i._parsingChoice=!1,i.Choice=function(){var t=!0,e=i.Interleave(i.OptionalExclude(i.Whitespace),i.String("*"));if(!e){if(null===(e=i.Interleave(i.OptionalExclude(i.Whitespace),i.String("+"))))return null;t=!1}var n=i.Parse(i.BracketedName);i.Whitespace();var r=i.Parse(i.ChoiceCondition);if(i.Whitespace(),i._parsingChoice)throw new Error("Already parsing a choice - shouldn't have nested choices");i._parsingChoice=!0;var a=null,o=i.Parse(i.MixedTextAndLogic);o&&(a=new It(o));var s=null,l=null,u=null!==i.ParseString("[");if(u){i.EndTagIfNecessary(a);var c=i.Parse(i.MixedTextAndLogic);null!==c&&(s=new It(c)),i.Expect(i.String("]"),"closing ']' for weave-style option"),i.EndTagIfNecessary(s);var h=i.Parse(i.MixedTextAndLogic);null!==h&&(l=new It(h))}i.Whitespace(),i.EndTagIfNecessary(null!=l?l:a);var f=i.Parse(i.MultiDivert);i._parsingChoice=!1,i.Whitespace();var d=!a&&!l&&!s;if(d&&null===f&&i.Warning("Choice is completely empty. Interpretting as a default fallback choice. Add a divert arrow to remove this warning: * ->"),a||!u||s||i.Warning("Blank choice - if you intended a default fallback choice, use the `* ->` syntax"),l||(l=new It),i.EndTagIfNecessary(l),null!==f){var v,p=S(f);try{for(p.s();!(v=p.n()).done;){var m=v.value,g=_(m,jt);g&&g.isEmpty||l.AddContent(m)}}catch(t){p.e(t)}finally{p.f()}}l.AddContent(new Et("\n"));var y=new mt(a,s,l);return n&&(y.identifier=n),y.indentationDepth=e.length,y.hasWeaveStyleInlineBrackets=u,y.condition=r,y.onceOnly=t,y.isInvisibleDefault=d,y},i.ChoiceCondition=function(){var t=i.Interleave(i.ChoiceSingleCondition,i.ChoiceConditionsSpace);return null===t?null:1===t.length?t[0]:new Lt(t)},i.ChoiceConditionsSpace=function(){return i.Newline(),i.Whitespace(),Ct},i.ChoiceSingleCondition=function(){if(null===i.ParseString("{"))return null;var t=i.Expect(i.Expression,"choice condition inside { }");return i.DisallowIncrement(t),i.Expect(i.String("}"),"closing '}' for choice condition"),t},i.Gather=function(){var t=i.Parse(i.GatherDashes);if(null===t)return null;var e=Number(t),n=i.Parse(i.BracketedName),r=new Tt(n,e);return i.Newline(),r},i.GatherDashes=function(){i.Whitespace();for(var t=0;null!==i.ParseDashNotArrow();)t+=1,i.Whitespace();return 0===t?null:t},i.ParseDashNotArrow=function(){var t=i.BeginRule();return null===i.ParseString("->")&&"-"===i.ParseSingleCharacter()?i.SucceedRule(t):i.FailRule(t)},i.BracketedName=function(){if(null===i.ParseString("("))return null;i.Whitespace();var t=i.Parse(i.IdentifierWithMetadata);return null===t?null:(i.Whitespace(),i.Expect(i.String(")"),"closing ')' for bracketed name"),t)},i.InnerConditionalContent=function(t){if(void 0===t){var e=i.Parse(i.ConditionExpression),n=i.Parse((function(){return i.InnerConditionalContent(e)}));return null===n?null:n}var r,a=null!==t,o=null===i.Parse(i.Newline);if(o&&!a)return null;if(o)r=i.InlineConditionalBranches();else{if(null===(r=i.MultilineConditionalBranches())){if(t){var s=i.StatementsAtLevel(Xt.InnerBlock);if(null!==s){r=[new $t(s)];var l=i.Parse(i.SingleMultilineCondition);l&&(l.isElse||(i.ErrorWithParsedObject("Expected an '- else:' clause here rather than an extra condition",l),l.isElse=!0),r.push(l))}}if(null===r)return null}else if(1===r.length&&r[0].isElse&&t){var u=new $t(null);u.isTrueBranch=!0,r.unshift(u)}if(t)for(var c=!1,h=0;h2?i.ErrorWithParsedObject("Only final branch can be an 'else'. Did you miss a ':'?",f):0===h?f.isTrueBranch=!0:f.isElse=!0}else{for(var v=0;v2)i.Error("Expected one or two alternatives separated by '|' in inline conditional");else{var n=new $t(t[0]);if(n.isTrueBranch=!0,e.push(n),t.length>1){var r=new $t(t[1]);r.isElse=!0,e.push(r)}}return e},i.MultilineConditionalBranches=function(){i.MultilineWhitespace();var t=i.OneOrMore(i.SingleMultilineCondition);return null===t?null:(i.MultilineWhitespace(),t)},i.SingleMultilineCondition=function(){if(i.Whitespace(),null!==i.ParseString("->")||null===i.ParseString("-"))return null;i.Whitespace();var t=null,e=null!==i.Parse(i.ElseExpression);e||(t=i.Parse(i.ConditionExpression));var n=i.StatementsAtLevel(Xt.InnerBlock);null===t&&null===n&&(i.Error("expected content for the conditional branch following '-'"),n=[new Et("")]),i.MultilineWhitespace();var r=new $t(n);return r.ownExpression=t,r.isElse=e,r},i.ConditionExpression=function(){var t=i.Parse(i.Expression);return null===t?null:(i.DisallowIncrement(t),i.Whitespace(),null===i.ParseString(":")?null:t)},i.ElseExpression=function(){return null===i.ParseString("else")?null:(i.Whitespace(),null===i.ParseString(":")?null:Ct)},i._nonTextPauseCharacters=null,i._nonTextEndCharacters=null,i._notTextEndCharactersChoice=null,i._notTextEndCharactersString=null,i.TrimEndWhitespace=function(t,e){if(t.length>0){var n=t.length-1,r=t[n];if(r instanceof Et){var a=r;a.text=a.text.replace(new RegExp(/[ \t]+$/g),""),e?a.text+=" ":0===a.text.length&&(t.splice(n,1),i.TrimEndWhitespace(t,!1))}}},i.LineOfMixedTextAndLogic=function(){i.Parse(i.Whitespace);var t=i.Parse(i.MixedTextAndLogic);if(!t||!t.length)return null;var e=t[0];return e&&e.text&&e.text.startsWith("return")&&i.Warning("Do you need a '~' before 'return'? If not, perhaps use a glue: <> (since it's lowercase) or rewrite somehow?"),0===t.length?null:(t[t.length-1]instanceof jt||i.TrimEndWhitespace(t,!1),i.EndTagIfNecessary(t),t.length>0&&t[0]instanceof Ee&&t[0].isStart||t.push(new Et("\n")),i.Expect(i.EndOfLine,"end of line",i.SkipToNextLine),t)},i.MixedTextAndLogic=function(){null!==i.ParseObject(i.Spaced(i.String("~")))&&i.Error("You shouldn't use a '~' here - tildas are for logic that's on its own line. To do inline logic, use { curly braces } instead");var t=i.Interleave(i.Optional(i.ContentText),i.Optional(i.InlineLogicOrGlueOrStartTag));if(!i._parsingChoice){var e,n=i.Parse(i.MultiDivert);if(null!==n)null===t&&(t=[]),i.EndTagIfNecessary(t),i.TrimEndWhitespace(t,!0),(e=t).push.apply(e,g(n))}return t||null},i.ContentText=function(){return i.ContentTextAllowingEscapeChar()},i.ContentTextAllowingEscapeChar=function(){for(var t=null;;){var e=i.Parse(i.ContentTextNoEscape),n=null!==i.ParseString("\\");if(!n&&null===e)break;null===t&&(t=""),null!==e&&(t+=String(e)),n&&(t+=i.ParseSingleCharacter())}return null!==t?new Et(t):null},i.ContentTextNoEscape=function(){null===i._nonTextPauseCharacters&&(i._nonTextPauseCharacters=new lt("-<")),null===i._nonTextEndCharacters&&(i._nonTextEndCharacters=new lt("{}|\n\r\\#"),i._notTextEndCharactersChoice=new lt(i._nonTextEndCharacters),i._notTextEndCharactersChoice.AddCharacters("[]"),i._notTextEndCharactersString=new lt(i._nonTextEndCharacters),i._notTextEndCharactersString.AddCharacters('"'));var t=null;t=i.parsingStringExpression?i._notTextEndCharactersString:i._parsingChoice?i._notTextEndCharactersChoice:i._nonTextEndCharacters;var e=i.ParseUntil((function(){return i.OneOf([i.ParseDivertArrow,i.ParseThreadArrow,i.EndOfLine,i.Glue])}),i._nonTextPauseCharacters,t);return null!==e?e:null},i.MultiDivert=function(){i.Whitespace();var t=[],e=i.Parse(i.StartThread);if(e)return t=[e];var n=i.Interleave(i.ParseDivertArrowOrTunnelOnwards,i.DivertIdentifierWithArguments);if(!n)return null;t=[],i.EndTagIfNecessary(t);for(var r=0;r->"===n[r]){0===r||r===n.length-1||r===n.length-2||i.Error("Tunnel onwards '->->' must only come at the begining or the start of a divert");var a=new Ut;if(r) are only valid on choices")}return t},i.StartThread=function(){if(i.Whitespace(),null===i.ParseThreadArrow())return null;i.Whitespace();var t=i.Expect(i.DivertIdentifierWithArguments,"target for new thread",(function(){return new jt(null)}));return t.isThread=!0,t},i.DivertIdentifierWithArguments=function(){i.Whitespace();var t=i.Parse(i.DotSeparatedDivertPathComponents);if(!t)return null;i.Whitespace();var e=i.Parse(i.ExpressionFunctionCallArguments);i.Whitespace();var n=new At(t);return new jt(n,e)},i.SingleDivert=function(){var t=i.Parse(i.MultiDivert);if(!t)return null;if(1!==t.length)return null;if(t[0]instanceof Ut)return null;var e=t[0];return e.isTunnel?null:e},i.DotSeparatedDivertPathComponents=function(){return i.Interleave(i.Spaced(i.IdentifierWithMetadata),i.Exclude(i.String(".")))},i.ParseDivertArrowOrTunnelOnwards=function(){for(var t=0;null!==i.ParseString("->");)t+=1;return 0===t?null:1===t?"->":(2===t||i.Error("Unexpected number of arrows in divert. Should only have '->' or '->->'"),"->->")},i.ParseDivertArrow=function(){return i.ParseString("->")},i.ParseThreadArrow=function(){return i.ParseString("<-")},i._binaryOperators=[],i._maxBinaryOpLength=0,i.TempDeclarationOrAssignment=function(){i.Whitespace();var t=i.ParseTempKeyword();i.Whitespace();var e=null;if(null===(e=t?i.Expect(i.IdentifierWithMetadata,"variable name"):i.Parse(i.IdentifierWithMetadata)))return null;i.Whitespace();var n=null!==i.ParseString("+"),r=null!==i.ParseString("-");if(n&&r&&i.Error("Unexpected sequence '+-'"),null===i.ParseString("="))return t&&i.Error("Expected '='"),null;var a=i.Expect(i.Expression,"value expression to be assigned");return n||r?new ne(e,a,n):new Jt({variableIdentifier:e,assignedExpression:a,isTemporaryNewDeclaration:t})},i.DisallowIncrement=function(t){t instanceof ne&&i.Error("Can't use increment/decrement here. It can only be used on a ~ line")},i.ParseTempKeyword=function(){var t=i.BeginRule();return"temp"===i.Parse(i.Identifier)?(i.SucceedRule(t),!0):(i.FailRule(t),!1)},i.ReturnStatement=function(){if(i.Whitespace(),"return"!==i.Parse(i.Identifier))return null;i.Whitespace();var t=i.Parse(i.Expression);return new Pt(t)},i.Expression=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;i.Whitespace();var n=i.ExpressionUnary();if(null===n)return null;i.Whitespace();for(var r=function(){var e=i.BeginRule(),r=i.ParseInfixOperator();if(null!==r&&r.precedence>t){var a="right side of '".concat(r.type,"' expression"),o=i.Expect((function(){return i.ExpressionInfixRight(n,r)}),a);return null===o?(i.FailRule(e),{v:null}):(n=i.SucceedRule(e,o),"continue")}return i.FailRule(e),"break"};;){var a=r();if("continue"!==a){if("break"===a)break;if("object"===e(a))return a.v}}return i.Whitespace(),n},i.ExpressionUnary=function(){var t=i.Parse(i.ExpressionDivertTarget);if(null!==t)return t;var e=i.OneOf([i.String("-"),i.String("!")]);null===e&&(e=i.Parse(i.ExpressionNot)),i.Whitespace();var n=i.OneOf([i.ExpressionList,i.ExpressionParen,i.ExpressionFunctionCall,i.ExpressionVariableName,i.ExpressionLiteral]);if(null===n&&null!==e&&(n=i.ExpressionUnary()),null===n)return null;null!==e&&(n=ot.WithInner(n,e)),i.Whitespace();var r=i.OneOf([i.String("++"),i.String("--")]);if(null!==r){var a="++"===r;if(n instanceof Wt)n=new ne(n.identifier,a);else i.Error("can only increment and decrement variables, but saw '".concat(n,"'."))}return n},i.ExpressionNot=function(){var t=i.Identifier();return"not"===t?t:null},i.ExpressionLiteral=function(){return i.OneOf([i.ExpressionFloat,i.ExpressionInt,i.ExpressionBool,i.ExpressionString])},i.ExpressionDivertTarget=function(){i.Whitespace();var t=i.Parse(i.SingleDivert);return!t||t&&t.isThread?null:(i.Whitespace(),new Vt(t))},i.ExpressionInt=function(){var t=i.ParseInt();return null===t?null:new at(t,"int")},i.ExpressionFloat=function(){var t=i.ParseFloat();return null===t?null:new at(t,"float")},i.ExpressionString=function(){if(null===i.ParseString('"'))return null;i.parsingStringExpression=!0;var t=i.Parse(i.MixedTextAndLogic);return i.Expect(i.String('"'),"close quote for string expression"),i.parsingStringExpression=!1,null===t?t=[new Et("")]:t.find((function(t){return t instanceof jt}))&&i.Error("String expressions cannot contain diverts (->)"),new ke(t)},i.ExpressionBool=function(){var t=i.Parse(i.Identifier);return"true"===t?new at(!0,"bool"):"false"===t?new at(!1,"bool"):null},i.ExpressionFunctionCall=function(){var t=i.Parse(i.IdentifierWithMetadata);if(null===t)return null;i.Whitespace();var e=i.Parse(i.ExpressionFunctionCallArguments);return null===e?null:new Rt(t,e)},i.ExpressionFunctionCallArguments=function(){if(null===i.ParseString("("))return null;var t=i.Exclude(i.String(",")),e=i.Interleave(i.Expression,t);return null===e&&(e=[]),i.Whitespace(),i.Expect(i.String(")"),"closing ')' for function call"),e},i.ExpressionVariableName=function(){var t=i.Interleave(i.IdentifierWithMetadata,i.Exclude(i.Spaced(i.String("."))));return null===t||we.IsReservedKeyword(t[0].name)?null:new Wt(t)},i.ExpressionParen=function(){if(null===i.ParseString("("))return null;var t=i.Parse(i.Expression);return null===t?null:(i.Whitespace(),i.Expect(i.String(")"),"closing parenthesis ')' for expression"),t)},i.ExpressionInfixRight=function(t,e){if(!t)return null;i.Whitespace();var n=i.Parse((function(){return i.Expression(e.precedence)}));return n?new st(t,n,e.type):null},i.ParseInfixOperator=function(){var t,e=S(i._binaryOperators);try{for(e.s();!(t=e.n()).done;){var n=t.value,r=i.BeginRule();if(null!==i.ParseString(n.type)){if(n.requireWhitespace&&null===i.Whitespace()){i.FailRule(r);continue}return i.SucceedRule(r,n)}i.FailRule(r)}}catch(t){e.e(t)}finally{e.f()}return null},i.ExpressionList=function(){if(i.Whitespace(),null===i.ParseString("("))return null;i.Whitespace();var t=i.SeparatedList(i.ListMember,i.Spaced(i.String(",")));return i.Whitespace(),null===i.ParseString(")")?null:new oe(t)},i.ListMember=function(){i.Whitespace();var t=i.Parse(i.IdentifierWithMetadata);if(null===t)return null;if(null!==i.ParseString(".")){var e=i.Expect(i.IdentifierWithMetadata,"element name within the set ".concat(t));t.name+=".".concat(null==e?void 0:e.name)}return i.Whitespace(),t},i.RegisterExpressionOperators=function(){i.RegisterBinaryOperator("&&",1),i.RegisterBinaryOperator("||",1),i.RegisterBinaryOperator("and",1,!0),i.RegisterBinaryOperator("or",1,!0),i.RegisterBinaryOperator("==",2),i.RegisterBinaryOperator(">=",2),i.RegisterBinaryOperator("<=",2),i.RegisterBinaryOperator("<",2),i.RegisterBinaryOperator(">",2),i.RegisterBinaryOperator("!=",2),i.RegisterBinaryOperator("?",3),i.RegisterBinaryOperator("has",3,!0),i.RegisterBinaryOperator("!?",3),i.RegisterBinaryOperator("hasnt",3,!0),i.RegisterBinaryOperator("^",3),i.RegisterBinaryOperator("+",4),i.RegisterBinaryOperator("-",5),i.RegisterBinaryOperator("*",6),i.RegisterBinaryOperator("/",7),i.RegisterBinaryOperator("%",8),i.RegisterBinaryOperator("mod",8,!0)},i.RegisterBinaryOperator=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=new ie(t,e,n);i._binaryOperators.push(r),i._maxBinaryOpLength=Math.max(i._maxBinaryOpLength,t.length)},i._openFilenames=[],i.IncludeStatement=function(){if(i.Whitespace(),null===i.ParseString("INCLUDE"))return null;i.Whitespace();var t=i.Expect((function(){return i.ParseUntilCharactersFromString("\n\r")}),"filename for include statement");t=t.replace(new RegExp(/[ \t]+$/g),"");var e=i.fileHandler.ResolveInkFilename(t);if(i.FilenameIsAlreadyOpen(e))return i.Error("Recursive INCLUDE detected: '".concat(e,"' is already open.")),i.ParseUntilCharactersFromString("\r\n"),new re(null);i.AddOpenFilename(e);var n=null,r="";try{r=i._rootParser.fileHandler.LoadInkFileContents(e)}catch(e){i.Error("Failed to load: '".concat(t,"'.\nError:").concat(e))}r&&(n=new o(r,t,i._externalErrorHandler,i._rootParser,i.fileHandler).ParseStory());return i.RemoveOpenFilename(e),new re(n)},i.FilenameIsAlreadyOpen=function(t){return i._rootParser._openFilenames.includes(t)},i.AddOpenFilename=function(t){i._rootParser._openFilenames.push(t)},i.RemoveOpenFilename=function(t){i._rootParser._openFilenames.splice(i._rootParser._openFilenames.indexOf(t),1)},i.KnotDefinition=function(){var t=i.Parse(i.KnotDeclaration);if(null===t)return null;i.Expect(i.EndOfLine,"end of line after knot name definition",i.SkipToNextLine);var e=i.Expect((function(){return i.StatementsAtLevel(Xt.Knot)}),"at least one line within the knot",i.KnotStitchNoContentRecoveryRule);return new ae(t.name,e,t.args,t.isFunction)},i.KnotDeclaration=function(){if(i.Whitespace(),null===i.KnotTitleEquals())return null;i.Whitespace();var t,e=i.Parse(i.IdentifierWithMetadata),n="function"===(null==e?void 0:e.name);n?(i.Expect(i.Whitespace,"whitespace after the 'function' keyword"),t=i.Parse(i.IdentifierWithMetadata)):t=e,null===t&&(i.Error("Expected the name of the ".concat(n?"function":"knot")),t=new xt("")),i.Whitespace();var r=i.Parse(i.BracketedKnotDeclArguments);return i.Whitespace(),i.Parse(i.KnotTitleEquals),new Qt(t,r,n)},i.KnotTitleEquals=function(){var t=i.ParseCharactersFromString("=");return null===t||t.length<=1?null:t},i.StitchDefinition=function(){var t=i.Parse(i.StitchDeclaration);if(null===t)return null;i.Expect(i.EndOfLine,"end of line after stitch name",i.SkipToNextLine);var e=i.Expect((function(){return i.StatementsAtLevel(Xt.Stitch)}),"at least one line within the stitch",i.KnotStitchNoContentRecoveryRule);return new le(t.name,e,t.args,t.isFunction)},i.StitchDeclaration=function(){if(i.Whitespace(),null===i.ParseString("="))return null;if(null!==i.ParseString("="))return null;i.Whitespace();var t=null!==i.ParseString("function");t&&i.Whitespace();var e=i.Parse(i.IdentifierWithMetadata);if(null===e)return null;i.Whitespace();var n=i.Parse(i.BracketedKnotDeclArguments);return i.Whitespace(),new Qt(e,n,t)},i.KnotStitchNoContentRecoveryRule=function(){return i.ParseUntil(i.KnotDeclaration,new lt("="),null),[new Et("")]},i.BracketedKnotDeclArguments=function(){if(null===i.ParseString("("))return null;var t=i.Interleave(i.Spaced(i.FlowDeclArgument),i.Exclude(i.String(",")));return i.Expect(i.String(")"),"closing ')' for parameter list"),null===t&&(t=[]),t},i.FlowDeclArgument=function(){var t=i.Parse(i.IdentifierWithMetadata);i.Whitespace();var e=i.ParseDivertArrow();i.Whitespace();var n=i.Parse(i.IdentifierWithMetadata);if(null==t&&null===n)return null;var r=new E;return null!==e&&(r.isDivertTarget=!0),null!==t&&"ref"===t.name?(null===n&&i.Error("Expected an parameter name after 'ref'"),r.identifier=n,r.isByReference=!0):(r.isDivertTarget?r.identifier=n:r.identifier=t,null===r.identifier&&i.Error("Expected an parameter name"),r.isByReference=!1),r},i.ExternalDeclaration=function(){i.Whitespace();var t=i.Parse(i.IdentifierWithMetadata);if(null===t||"EXTERNAL"!=t.name)return null;i.Whitespace();var e=i.Expect(i.IdentifierWithMetadata,"name of external function")||new xt("");i.Whitespace();var n=i.Expect(i.BracketedKnotDeclArguments,"declaration of arguments for EXTERNAL, even if empty, i.e. 'EXTERNAL ".concat(e,"()'"));null===n&&(n=[]);var r=n.map((function(t){var e;return null===(e=t.identifier)||void 0===e?void 0:e.name})).filter(O);return new Zt(e,r)},i._identifierCharSet=null,i.LogicLine=function(){if(i.Whitespace(),null===i.ParseString("~"))return null;i.Whitespace();var t=i.Expect((function(){return i.OneOf([i.ReturnStatement,i.TempDeclarationOrAssignment,i.Expression])}),"expression after '~'",i.SkipToNextLine);if(null===t)return new It;t instanceof nt&&!(t instanceof Rt||t instanceof ne)&&i.Error("Logic following a '~' can't be that type of expression. It can only be something like:\n\t~ return\n\t~ var x = blah\n\t~ x++\n\t~ myFunction()");var e=_(t,Rt);return e&&(e.shouldPopReturnedValue=!0),null!==t.Find(Rt)()&&(t=new It(t,new Et("\n"))),i.Expect(i.EndOfLine,"end of line",i.SkipToNextLine),t},i.VariableDeclaration=function(){if(i.Whitespace(),"VAR"!==i.Parse(i.Identifier))return null;i.Whitespace();var t=i.Expect(i.IdentifierWithMetadata,"variable name");i.Whitespace(),i.Expect(i.String("="),"the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)"),i.Whitespace();var e=i.Expect(i.Expression,"initial value for ");if(e){if(e instanceof at||e instanceof ke||e instanceof Vt||e instanceof Wt||e instanceof oe||i.Error("initial value for a variable must be a number, constant, list or divert target"),null!==i.Parse(i.ListElementDefinitionSeparator))i.Error("Unexpected ','. If you're trying to declare a new list, use the LIST keyword, not VAR");else if(e instanceof ke){e.isSingleString||i.Error("Constant strings cannot contain any logic.")}return new Jt({assignedExpression:e,isGlobalDeclaration:!0,variableIdentifier:t})}return null},i.ListDeclaration=function(){if(i.Whitespace(),"LIST"!=i.Parse(i.Identifier))return null;i.Whitespace();var t=i.Expect(i.IdentifierWithMetadata,"list name");i.Whitespace(),i.Expect(i.String("="),"the '=' for an assignment of the list definition"),i.Whitespace();var e=i.Expect(i.ListDefinition,"list item names");return e?(e.identifier=new xt(t.name),new Jt({variableIdentifier:t,listDef:e})):null},i.ListDefinition=function(){i.AnyWhitespace();var t=i.SeparatedList(i.ListElementDefinition,i.ListElementDefinitionSeparator);return null===t?null:new Ht(t)},i.ListElementDefinitionSeparator=function(){return i.AnyWhitespace(),null===i.ParseString(",")?null:(i.AnyWhitespace(),",")},i.ListElementDefinition=function(){var t=null!==i.ParseString("("),e=t;i.Whitespace();var n=i.Parse(i.IdentifierWithMetadata);if(null===n)return null;i.Whitespace(),t&&null!=i.ParseString(")")&&(e=!1,i.Whitespace());var r=null;if(null!==i.ParseString("=")){i.Whitespace();var a=i.Expect(i.ExpressionInt,"value to be assigned to list item");null!==a&&(r=a.value),e&&(i.Whitespace(),null!==i.ParseString(")")&&(e=!1))}return e&&i.Error("Expected closing ')'"),new se(n,t,r)},i.ConstDeclaration=function(){if(i.Whitespace(),"CONST"!==i.Parse(i.Identifier))return null;i.Whitespace();var t=i.Expect(i.IdentifierWithMetadata,"constant name");i.Whitespace(),i.Expect(i.String("="),"the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)"),i.Whitespace();var e=i.Expect(i.Expression,"initial value for ");if(e instanceof at||e instanceof Vt||e instanceof ke){if(e instanceof ke){e.isSingleString||i.Error("Constant strings cannot contain any logic.")}}else i.Error("initial value for a constant must be a number or divert target");return new _t(t,e)},i.InlineLogicOrGlueOrStartTag=function(){return i.OneOf([i.InlineLogic,i.Glue,i.StartTag])},i.Glue=function(){return null!==i.ParseString("<>")?new te(new ee):null},i.InlineLogic=function(){if(null===i.ParseString("{"))return null;var t=i.parsingStringExpression,e=i.tagActive;i.Whitespace();var n=i.Expect(i.InnerLogic,"some kind of logic, conditional or sequence within braces: { ... }");if(null===n)return i.parsingStringExpression=t,null;i.DisallowIncrement(n);var r=_(n,It);return r||(r=new It(n)),i.Whitespace(),i.Expect(i.String("}"),"closing brace '}' for inline logic"),i.parsingStringExpression=t,e||i.EndTagIfNecessary(r),r},i.InnerLogic=function(){i.Whitespace();var t=i.ParseObject(i.SequenceTypeAnnotation);if(null!==t){var e=i.Expect(i.InnerSequenceObjects,"sequence elements (for cycle/stoping etc)");return null===e?null:new qt(e,t)}var n=i.Parse(i.ConditionExpression);if(n)return i.Expect((function(){return i.InnerConditionalContent(n)}),"conditional content following query");var r=[i.InnerConditionalContent,i.InnerSequence,i.InnerExpression];i.tagActive;for(var a=0,o=r;a="0"&&a<="9")){n=!1;break}}}catch(t){r.e(t)}finally{r.f()}return n?null:t},i._sequenceTypeSymbols=new lt("!&~$"),i.InnerSequence=function(){i.Whitespace();var t=Dt.Stopping,e=i.Parse(i.SequenceTypeAnnotation);null!==e&&(t=e);var n=i.Parse(i.InnerSequenceObjects);return null===n||n.length<=1?null:new qt(n,t)},i.SequenceTypeAnnotation=function(){var t=i.Parse(i.SequenceTypeSymbolAnnotation);if(null===t&&(t=i.Parse(i.SequenceTypeWordAnnotation)),null===t)return null;switch(t){case Dt.Once:case Dt.Cycle:case Dt.Stopping:case Dt.Shuffle:case Dt.Shuffle|Dt.Stopping:case Dt.Shuffle|Dt.Once:break;default:return i.Error("Sequence type combination not supported: ".concat(t)),Dt.Stopping}return t},i.SequenceTypeSymbolAnnotation=function(){null===i._sequenceTypeSymbols&&(i._sequenceTypeSymbols=new lt("!&~$ "));var t=0,e=i.ParseCharactersFromCharSet(i._sequenceTypeSymbols);if(null===e)return null;var n,r=S(e);try{for(r.s();!(n=r.n()).done;){switch(n.value){case"!":t|=Dt.Once;break;case"&":t|=Dt.Cycle;break;case"~":t|=Dt.Shuffle;break;case"$":t|=Dt.Stopping}}}catch(t){r.e(t)}finally{r.f()}return 0===t?null:t},i.SequenceTypeWordAnnotation=function(){var t=i.Interleave(i.SequenceTypeSingleWord,i.Exclude(i.Whitespace));if(null===t||0===t.length)return null;if(null===i.ParseString(":"))return null;var e,n=0,r=S(t);try{for(r.s();!(e=r.n()).done;){n|=e.value}}catch(t){r.e(t)}finally{r.f()}return n},i.SequenceTypeSingleWord=function(){var t=null,e=i.Parse(i.IdentifierWithMetadata);if(null!==e)switch(e.name){case"once":t=Dt.Once;break;case"cycle":t=Dt.Cycle;break;case"shuffle":t=Dt.Shuffle;break;case"stopping":t=Dt.Stopping}return null===t?null:t},i.InnerSequenceObjects=function(){return null!==i.Parse(i.Newline)?i.Parse(i.InnerMultilineSequenceObjects):i.Parse(i.InnerInlineSequenceObjects)},i.InnerInlineSequenceObjects=function(){var t=i.Interleave(i.Optional(i.MixedTextAndLogic),i.String("|"),null,!1);if(null===t)return null;var e,n=[],r=!1,a=S(t);try{for(a.s();!(e=a.n()).done;){var o=e.value;if("|"===o)r||n.push(new It),r=!1;else{var s=o;null===s?i.Error("Expected content, but got ".concat(o," (this is an ink compiler bug!)")):n.push(new It(s)),r=!0}}}catch(t){a.e(t)}finally{a.f()}return r||n.push(new It),n},i.InnerMultilineSequenceObjects=function(){i.MultilineWhitespace();var t=i.OneOrMore(i.SingleMultilineSequenceElement);return null===t?null:t},i.SingleMultilineSequenceElement=function(){if(i.Whitespace(),null!==i.ParseString("->"))return null;if(null===i.ParseString("-"))return null;i.Whitespace();var t=i.StatementsAtLevel(Xt.InnerBlock);return null===t?i.MultilineWhitespace():t.unshift(new Et("\n")),new It(t)},i._statementRulesAtLevel=[],i._statementBreakRulesAtLevel=[],i.StatementsAtLevel=function(t){t===Xt.InnerBlock&&(null!==i.Parse(i.GatherDashes)&&i.Error("You can't use a gather (the dashes) within the { curly braces } context. For multi-line sequences and conditions, you should only use one dash."));return i.Interleave(i.Optional(i.MultilineWhitespace),(function(){return i.StatementAtLevel(t)}),(function(){return i.StatementsBreakForLevel(t)}))},i.StatementAtLevel=function(t){var e=i._statementRulesAtLevel[t],n=i.OneOf(e);return t===Xt.Top&&n instanceof Pt&&i.Error("should not have return statement outside of a knot"),n},i.StatementsBreakForLevel=function(t){i.Whitespace();var e=i._statementBreakRulesAtLevel[t],n=i.OneOf(e);return null===n?null:n},i.GenerateStatementLevelRules=function(){var t=Object.values(Xt);i._statementRulesAtLevel="f".repeat(t.length).split("f").map((function(){return[]})),i._statementBreakRulesAtLevel="f".repeat(t.length).split("f").map((function(){return[]}));for(var e=0,n=t;e=Xt.Top&&a.push(i.KnotDefinition),a.push(i.Line(i.Choice)),a.push(i.Line(i.AuthorWarning)),r>Xt.InnerBlock&&a.push(i.Gather),r>=Xt.Knot&&a.push(i.StitchDefinition),a.push(i.Line(i.ListDeclaration)),a.push(i.Line(i.VariableDeclaration)),a.push(i.Line(i.ConstDeclaration)),a.push(i.Line(i.ExternalDeclaration)),a.push(i.Line(i.IncludeStatement)),a.push(i.LogicLine),a.push(i.LineOfMixedTextAndLogic),r<=Xt.Knot&&o.push(i.KnotDeclaration),r<=Xt.Stitch&&o.push(i.StitchDeclaration),r<=Xt.InnerBlock&&(o.push(i.ParseDashNotArrow),o.push(i.String("}"))),i._statementRulesAtLevel[r]=a,i._statementBreakRulesAtLevel[r]=o}},i.SkipToNextLine=function(){return i.ParseUntilCharactersFromString("\n\r"),i.ParseNewline(),Ct},i.Line=function(t){return function(){var e=i.ParseObject(t);return null===e?null:(i.Expect(i.EndOfLine,"end of line",i.SkipToNextLine),e)}},i.StartTag=function(){if(i.Whitespace(),null===i.ParseString("#"))return null;i.parsingStringExpression&&i.Error("Tags aren't allowed inside of strings. Please use \\# if you want a hash symbol.");var t=null;if(i.tagActive){var e=new It;e.AddContent(new Ee(!1)),e.AddContent(new Ee(!0)),t=e}else t=new Ee(!0);return i.tagActive=!0,i.Whitespace(),t},i._inlineWhitespaceChars=new lt(" \t"),i.EndOfLine=function(){return i.OneOf([i.Newline,i.EndOfFile])},i.Newline=function(){return i.Whitespace(),null!==i.ParseNewline()?Ct:null},i.EndOfFile=function(){return i.Whitespace(),i.endOfInput?Ct:null},i.MultilineWhitespace=function(){var t=i.OneOrMore(i.Newline);return null===t?null:t.length>=1?Ct:null},i.Whitespace=function(){return null!==i.ParseCharactersFromCharSet(i._inlineWhitespaceChars)?Ct:null},i.Spaced=function(t){return function(){i.Whitespace();var e=i.ParseObject(t);return null===e?null:(i.Whitespace(),e)}},i.AnyWhitespace=function(){for(var t=!1;null!==i.OneOf([i.Whitespace,i.MultilineWhitespace]);)t=!0;return t?Ct:null},i.MultiSpaced=function(t){return function(){i.AnyWhitespace();var e=i.ParseObject(t);return null===e?null:(i.AnyWhitespace(),e)}},i._filename=null,i._externalErrorHandler=null,i._fileHandler=null,i._filename=a,i.RegisterExpressionOperators(),i.GenerateStatementLevelRules(),i.errorHandler=i.OnStringParserError,i._externalErrorHandler=s,i._fileHandler=null===u?new _e:u,null===l){if(i._rootParser=h(i),i._openFilenames=[],null!==i._filename){var c=i.fileHandler.ResolveInkFilename(i._filename);i._openFilenames.push(c)}}else i._rootParser=l;return i}return i(o,[{key:"fileHandler",get:function(){if(!this._fileHandler)throw new Error("No FileHandler defined");return this._fileHandler},set:function(t){this._fileHandler=t}},{key:"PreProcessInputString",value:function(t){return new wt(t).Process()}},{key:"parsingStringExpression",get:function(){return this.GetFlag(Number(Gt.ParsingString))},set:function(t){this.SetFlag(Number(Gt.ParsingString),t)}},{key:"tagActive",get:function(){return this.GetFlag(Number(Gt.TagActive))},set:function(t){this.SetFlag(Number(Gt.TagActive),t)}},{key:"identifierCharSet",get:function(){return null===this._identifierCharSet&&((this._identifierCharSet=new lt).AddRange("A","Z").AddRange("a","z").AddRange("0","9").Add("_"),this.ExtendIdentifierCharacterRanges(this._identifierCharSet)),this._identifierCharSet}},{key:"EndTagIfNecessary",value:function(t){this.tagActive&&(null!=t&&(t instanceof It?t.AddContent(new Ee(!1)):t.push(new Ee(!1))),this.tagActive=!1)}}]),o}(St);Te.LatinBasic=ut.Define("A","z",(new lt).AddRange("[","`")),Te.LatinExtendedA=ut.Define("Ā","ſ"),Te.LatinExtendedB=ut.Define("ƀ","ɏ"),Te.Greek=ut.Define("Ͱ","Ͽ",(new lt).AddRange("͸","΅").AddCharacters("ʹ͵͸·΋΍΢")),Te.Cyrillic=ut.Define("Ѐ","ӿ",(new lt).AddRange("҂","҉")),Te.Armenian=ut.Define("԰","֏",(new lt).AddCharacters("԰").AddRange("՗","ՠ").AddRange("ֈ","֎")),Te.Hebrew=ut.Define("֐","׿",new lt),Te.Arabic=ut.Define("؀","ۿ",new lt),Te.Korean=ut.Define("가","힯",new lt),Te.ListAllCharacterRanges=function(){return[Te.LatinBasic,Te.LatinExtendedA,Te.LatinExtendedB,Te.Arabic,Te.Armenian,Te.Cyrillic,Te.Greek,Te.Hebrew,Te.Korean]};var Ae=i((function t(e){var r=this;n(this,t),this.fileHierarchy=e,this.ResolveInkFilename=function(t){if(Object.keys(r.fileHierarchy).includes(t))return t;throw new Error("Cannot locate ".concat(t,". Are you trying a relative import ? This is not yet implemented."))},this.LoadInkFileContents=function(t){if(Object.keys(r.fileHierarchy).includes(t))return r.fileHierarchy[t];throw new Error("Cannot open ".concat(t,"."))}})),Pe=function(){function t(e){var r=this,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;n(this,t),this._errors=[],this._warnings=[],this._authorMessages=[],this._parsedStory=null,this._runtimeStory=null,this._parser=null,this._debugSourceRanges=[],this.Compile=function(){return r._parser=new Te(r.inputString,r.options.sourceFilename||null,r.OnError,null,r.options.fileHandler),r._parsedStory=r.parser.ParseStory(),0===r.errors.length?(r.parsedStory.countAllVisits=r.options.countAllVisits,r._runtimeStory=r.parsedStory.ExportRuntime(r.OnError)):r._runtimeStory=null,r.runtimeStory},this.RetrieveDebugSourceForLatestContent=function(){var t,e,n=S(r.runtimeStory.state.outputStream);try{for(n.s();!(e=n.n()).done;){var i=_(e.value,$);if(null!==i){var a=new k((null===(t=i.value)||void 0===t?void 0:t.length)||0,i.debugMetadata,i.value||"unknown");r.debugSourceRanges.push(a)}}}catch(t){n.e(t)}finally{n.f()}},this.DebugMetadataForContentAtOffset=function(t){var e,n=0,i=null,a=S(r.debugSourceRanges);try{for(a.s();!(e=a.n()).done;){var o=e.value;if(null!==o.debugMetadata&&(i=o.debugMetadata),t>=n&&tt.length)&&(e=t.length);for(var n=0,i=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[i++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,s=!0,o=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return s=t.done,t},e:function(t){o=!0,a=t},f:function(){try{s||null==n.return||n.return()}finally{if(o)throw a}}}}var g,S=function(){function t(){if(n(this,t),this._components=[],this._componentsString=null,this._isRelative=!1,"string"==typeof arguments[0]){var e=arguments[0];this.componentsString=e}else if(arguments[0]instanceof t.Component&&arguments[1]instanceof t){var i=arguments[0],r=arguments[1];this._components.push(i),this._components=this._components.concat(r._components)}else if(arguments[0]instanceof Array){var a=arguments[0],s=!!arguments[1];this._components=this._components.concat(a),this._isRelative=s}}return r(t,[{key:"isRelative",get:function(){return this._isRelative}},{key:"componentCount",get:function(){return this._components.length}},{key:"head",get:function(){return this._components.length>0?this._components[0]:null}},{key:"tail",get:function(){return this._components.length>=2?new t(this._components.slice(1,this._components.length)):t.self}},{key:"length",get:function(){return this._components.length}},{key:"lastComponent",get:function(){var t=this._components.length-1;return t>=0?this._components[t]:null}},{key:"containsNamedComponent",get:function(){for(var t=0,e=this._components.length;t=0}},{key:"isParent",get:function(){return this.name==t.parentId}},{key:"toString",value:function(){return this.isIndex?this.index.toString():this.name}},{key:"Equals",value:function(t){return null!=t&&t.isIndex==this.isIndex&&(this.isIndex?this.index==t.index:this.name==t.name)}}],[{key:"ToParent",value:function(){return new e(t.parentId)}}]),e}();t.Component=e}(S||(S={})),function(t){function e(t,e){if(!t)throw void 0!==e&&console.warn(e),console.trace&&console.trace(),new Error("")}t.AssertType=function(t,n,i){e(t instanceof n,i)},t.Assert=e}(g||(g={}));var E=function(t){a(i,t);var e=f(i);function i(){return n(this,i),e.apply(this,arguments)}return r(i)}(h(Error));function O(t){throw new E("".concat(t," is null or undefined"))}var P=function(){function t(){n(this,t),this.parent=null,this._debugMetadata=null,this._path=null}return r(t,[{key:"debugMetadata",get:function(){return null===this._debugMetadata&&this.parent?this.parent.debugMetadata:this._debugMetadata},set:function(t){this._debugMetadata=t}},{key:"ownDebugMetadata",get:function(){return this._debugMetadata}},{key:"DebugLineNumberOfPath",value:function(t){if(null===t)return null;var e=this.rootContentContainer;if(e){var n=e.ContentAtPath(t).obj;if(n){var i=n.debugMetadata;if(null!==i)return i.startLineNumber}}return null}},{key:"path",get:function(){if(null==this._path)if(null==this.parent)this._path=new S;else{for(var t=[],e=this,n=k(e.parent,U);null!==n;){var i=b(e);if(null!=i&&i.hasValidName){if(null===i.name)return O("namedChild.name");t.unshift(new S.Component(i.name))}else t.unshift(new S.Component(n.content.indexOf(e)));e=n,n=k(n.parent,U)}this._path=new S(t)}return this._path}},{key:"ResolvePath",value:function(t){if(null===t)return O("path");if(t.isRelative){var e=k(this,U);return null===e&&(g.Assert(null!==this.parent,"Can't resolve relative path because we don't have a parent"),e=k(this.parent,U),g.Assert(null!==e,"Expected parent to be a container"),g.Assert(t.GetComponent(0).isParent),t=t.tail),null===e?O("nearestContainer"):e.ContentAtPath(t)}var n=this.rootContentContainer;return null===n?O("contentContainer"):n.ContentAtPath(t)}},{key:"ConvertPathToRelative",value:function(t){for(var e=this.path,n=Math.min(t.length,e.length),i=-1,r=0;r1?e-1:0),i=1;i0){null==this._originNames&&this.Count>0?this._originNames=[]:(this._originNames||(this._originNames=[]),this._originNames.length=0);var t,e=m(this);try{for(e.s();!(t=e.n()).done;){var n=v(t.value,1)[0],i=A.fromSerializedKey(n);if(null===i.originName)return O("item.originName");this._originNames.push(i.originName)}}catch(t){e.e(t)}finally{e.f()}}return this._originNames}},{key:"SetInitialOriginName",value:function(t){this._originNames=[t]}},{key:"SetInitialOriginNames",value:function(t){this._originNames=null==t?null:t.slice()}},{key:"maxItem",get:function(){var t,e={Key:A.Null,Value:0},n=m(this);try{for(n.s();!(t=n.n()).done;){var i=v(t.value,2),r=i[0],a=i[1],s=A.fromSerializedKey(r);(e.Key.isNull||a>e.Value)&&(e={Key:s,Value:a})}}catch(t){n.e(t)}finally{n.f()}return e}},{key:"minItem",get:function(){var t,e={Key:A.Null,Value:0},n=m(this);try{for(n.s();!(t=n.n()).done;){var i=v(t.value,2),r=i[0],a=i[1],s=A.fromSerializedKey(r);(e.Key.isNull||at.maxItem.Value)}},{key:"GreaterThanOrEquals",value:function(t){return 0!=this.Count&&(0==t.Count||this.minItem.Value>=t.minItem.Value&&this.maxItem.Value>=t.maxItem.Value)}},{key:"LessThan",value:function(t){return 0!=t.Count&&(0==this.Count||this.maxItem.Value0?new s(this.maxItem):new s}},{key:"MinAsList",value:function(){return this.Count>0?new s(this.minItem):new s}},{key:"ListWithSubRange",value:function(t,e){if(0==this.Count)return new s;var n=this.orderedItems,i=0,r=Number.MAX_SAFE_INTEGER;Number.isInteger(t)?i=t:t instanceof s&&t.Count>0&&(i=t.minItem.Value),Number.isInteger(e)?r=e:t instanceof s&&t.Count>0&&(r=e.maxItem.Value);var a=new s;a.SetInitialOriginNames(this.originNames);var o,u=m(n);try{for(u.s();!(o=u.n()).done;){var l=o.value;l.Value>=i&&l.Value<=r&&a.Add(l.Key,l.Value)}}catch(t){u.e(t)}finally{u.f()}return a}},{key:"Equals",value:function(t){if(t instanceof s==!1)return!1;if(t.Count!=this.Count)return!1;var e,n=m(this);try{for(n.s();!(e=n.n()).done;){var i=v(e.value,1)[0];if(!t.has(i))return!1}}catch(t){n.e(t)}finally{n.f()}return!0}},{key:"orderedItems",get:function(){var t,e=new Array,n=m(this);try{for(n.s();!(t=n.n()).done;){var i=v(t.value,2),r=i[0],a=i[1],s=A.fromSerializedKey(r);e.push({Key:s,Value:a})}}catch(t){n.e(t)}finally{n.f()}return e.sort((function(t,e){return null===t.Key.originName?O("x.Key.originName"):null===e.Key.originName?O("y.Key.originName"):t.Value==e.Value?t.Key.originName.localeCompare(e.Key.originName):t.Valuee.Value?1:0})),e}},{key:"toString",value:function(){for(var t=this.orderedItems,e=new N,n=0;n0&&e.Append(", ");var i=t[n].Key;if(null===i.itemName)return O("item.itemName");e.Append(i.itemName)}return e.toString()}},{key:"valueOf",value:function(){return NaN}}],[{key:"FromString",value:function(t,e){var n,i=null===(n=e.listDefinitions)||void 0===n?void 0:n.FindSingleItemListWithName(t);if(i)return null===i.value?O("listValue.value"):new s(i.value);throw new Error("Could not find the InkListItem from the string '"+t+"' to create an InkList because it doesn't exist in the original list definition in ink.")}}]),s}(h(Map)),x=function(t){a(i,t);var e=f(i);function i(t){var r;return n(this,i),(r=e.call(this,t)).useEndLineNumber=!1,r.message=t,r.name="StoryException",r}return r(i)}(h(Error));function F(t,e,n){if(null===t)return{result:n,exists:!1};var i=t.get(e);return void 0===i?{result:n,exists:!1}:{result:i,exists:!0}}var W,V=function(t){a(i,t);var e=f(i);function i(){return n(this,i),e.apply(this,arguments)}return r(i,[{key:"Copy",value:function(){return C(i.Create(this.valueObject),P)}},{key:"BadCastException",value:function(t){return new x("Can't cast "+this.valueObject+" from "+this.valueType+" to "+t)}}],[{key:"Create",value:function(t,e){if(e){if(e===W.Int&&Number.isInteger(Number(t)))return new j(Number(t));if(e===W.Float&&!isNaN(t))return new D(Number(t))}return"boolean"==typeof t?new R(Boolean(t)):"string"==typeof t?new B(String(t)):Number.isInteger(Number(t))?new j(Number(t)):isNaN(t)?t instanceof S?new G(C(t,S)):t instanceof I?new J(C(t,I)):null:new D(Number(t))}}]),i}(P),L=function(t){a(i,t);var e=f(i);function i(t){var r;return n(this,i),(r=e.call(this)).value=t,r}return r(i,[{key:"valueObject",get:function(){return this.value}},{key:"toString",value:function(){return null===this.value?O("Value.value"):this.value.toString()}}]),i}(V),R=function(t){a(i,t);var e=f(i);function i(t){return n(this,i),e.call(this,t||!1)}return r(i,[{key:"isTruthy",get:function(){return Boolean(this.value)}},{key:"valueType",get:function(){return W.Bool}},{key:"Cast",value:function(t){if(null===this.value)return O("Value.value");if(t==this.valueType)return this;if(t==W.Int)return new j(this.value?1:0);if(t==W.Float)return new D(this.value?1:0);if(t==W.String)return new B(this.value?"true":"false");throw this.BadCastException(t)}},{key:"toString",value:function(){return this.value?"true":"false"}}]),i}(L),j=function(t){a(i,t);var e=f(i);function i(t){return n(this,i),e.call(this,t||0)}return r(i,[{key:"isTruthy",get:function(){return 0!=this.value}},{key:"valueType",get:function(){return W.Int}},{key:"Cast",value:function(t){if(null===this.value)return O("Value.value");if(t==this.valueType)return this;if(t==W.Bool)return new R(0!==this.value);if(t==W.Float)return new D(this.value);if(t==W.String)return new B(""+this.value);throw this.BadCastException(t)}}]),i}(L),D=function(t){a(i,t);var e=f(i);function i(t){return n(this,i),e.call(this,t||0)}return r(i,[{key:"isTruthy",get:function(){return 0!=this.value}},{key:"valueType",get:function(){return W.Float}},{key:"Cast",value:function(t){if(null===this.value)return O("Value.value");if(t==this.valueType)return this;if(t==W.Bool)return new R(0!==this.value);if(t==W.Int)return new j(this.value);if(t==W.String)return new B(""+this.value);throw this.BadCastException(t)}}]),i}(L),B=function(t){a(i,t);var e=f(i);function i(t){var r;return n(this,i),(r=e.call(this,t||""))._isNewline="\n"==r.value,r._isInlineWhitespace=!0,null===r.value?c(r,O("Value.value")):(r.value.length>0&&r.value.split("").every((function(t){return" "==t||"\t"==t||(r._isInlineWhitespace=!1,!1)})),r)}return r(i,[{key:"valueType",get:function(){return W.String}},{key:"isTruthy",get:function(){return null===this.value?O("Value.value"):this.value.length>0}},{key:"isNewline",get:function(){return this._isNewline}},{key:"isInlineWhitespace",get:function(){return this._isInlineWhitespace}},{key:"isNonWhitespace",get:function(){return!this.isNewline&&!this.isInlineWhitespace}},{key:"Cast",value:function(t){if(t==this.valueType)return this;if(t==W.Int){var e=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=parseInt(t);return Number.isNaN(n)?{result:e,exists:!1}:{result:n,exists:!0}}(this.value);if(e.exists)return new j(e.result);throw this.BadCastException(t)}if(t==W.Float){var n=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=parseFloat(t);return Number.isNaN(n)?{result:e,exists:!1}:{result:n,exists:!0}}(this.value);if(n.exists)return new D(n.result);throw this.BadCastException(t)}throw this.BadCastException(t)}}]),i}(L),G=function(t){a(i,t);var e=f(i);function i(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;return n(this,i),e.call(this,t)}return r(i,[{key:"valueType",get:function(){return W.DivertTarget}},{key:"targetPath",get:function(){return null===this.value?O("Value.value"):this.value},set:function(t){this.value=t}},{key:"isTruthy",get:function(){throw new Error("Shouldn't be checking the truthiness of a divert target")}},{key:"Cast",value:function(t){if(t==this.valueType)return this;throw this.BadCastException(t)}},{key:"toString",value:function(){return"DivertTargetValue("+this.targetPath+")"}}]),i}(L),M=function(t){a(i,t);var e=f(i);function i(t){var r,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;return n(this,i),(r=e.call(this,t))._contextIndex=a,r}return r(i,[{key:"contextIndex",get:function(){return this._contextIndex},set:function(t){this._contextIndex=t}},{key:"variableName",get:function(){return null===this.value?O("Value.value"):this.value},set:function(t){this.value=t}},{key:"valueType",get:function(){return W.VariablePointer}},{key:"isTruthy",get:function(){throw new Error("Shouldn't be checking the truthiness of a variable pointer")}},{key:"Cast",value:function(t){if(t==this.valueType)return this;throw this.BadCastException(t)}},{key:"toString",value:function(){return"VariablePointerValue("+this.variableName+")"}},{key:"Copy",value:function(){return new i(this.variableName,this.contextIndex)}}]),i}(L),J=function(t){a(i,t);var e=f(i);function i(t,r){var a;return n(this,i),a=e.call(this,null),t||r?t instanceof I?a.value=new I(t):t instanceof A&&"number"==typeof r&&(a.value=new I({Key:t,Value:r})):a.value=new I,a}return r(i,[{key:"isTruthy",get:function(){return null===this.value?O("this.value"):this.value.Count>0}},{key:"valueType",get:function(){return W.List}},{key:"Cast",value:function(t){if(null===this.value)return O("Value.value");if(t==W.Int){var e=this.value.maxItem;return e.Key.isNull?new j(0):new j(e.Value)}if(t==W.Float){var n=this.value.maxItem;return n.Key.isNull?new D(0):new D(n.Value)}if(t==W.String){var i=this.value.maxItem;return i.Key.isNull?new B(""):new B(i.Key.toString())}if(t==this.valueType)return this;throw this.BadCastException(t)}}],[{key:"RetainListOriginsForAssignment",value:function(t,e){var n=k(t,i),r=k(e,i);return r&&null===r.value?O("newList.value"):n&&null===n.value?O("oldList.value"):void(n&&r&&0==r.value.Count&&r.value.SetInitialOriginNames(n.value.originNames))}}]),i}(L);!function(t){t[t.Bool=-1]="Bool",t[t.Int=0]="Int",t[t.Float=1]="Float",t[t.List=2]="List",t[t.String=3]="String",t[t.DivertTarget=4]="DivertTarget",t[t.VariablePointer=5]="VariablePointer"}(W||(W={}));var q=function(){function t(){n(this,t),this.obj=null,this.approximate=!1}return r(t,[{key:"correctObj",get:function(){return this.approximate?null:this.obj}},{key:"container",get:function(){return this.obj instanceof U?this.obj:null}},{key:"copy",value:function(){var e=new t;return e.obj=this.obj,e.approximate=this.approximate,e}}]),t}(),U=function(t){a(i,t);var e=f(i);function i(){var t;return n(this,i),(t=e.apply(this,arguments)).name=null,t._content=[],t.namedContent=new Map,t.visitsShouldBeCounted=!1,t.turnIndexShouldBeCounted=!1,t.countingAtStartOnly=!1,t._pathToFirstLeafContent=null,t}return r(i,[{key:"hasValidName",get:function(){return null!=this.name&&this.name.length>0}},{key:"content",get:function(){return this._content},set:function(t){this.AddContent(t)}},{key:"namedOnlyContent",get:function(){var t,e=new Map,n=m(this.namedContent);try{for(n.s();!(t=n.n()).done;){var i=v(t.value,2),r=i[0],a=C(i[1],P);e.set(r,a)}}catch(t){n.e(t)}finally{n.f()}var s,o=m(this.content);try{for(o.s();!(s=o.n()).done;){var u=b(s.value);null!=u&&u.hasValidName&&e.delete(u.name)}}catch(t){o.e(t)}finally{o.f()}return 0==e.size&&(e=null),e},set:function(t){var e=this.namedOnlyContent;if(null!=e){var n,i=m(e);try{for(i.s();!(n=i.n()).done;){var r=v(n.value,1)[0];this.namedContent.delete(r)}}catch(t){i.e(t)}finally{i.f()}}if(null!=t){var a,s=m(t);try{for(s.s();!(a=s.n()).done;){var o=b(v(a.value,2)[1]);null!=o&&this.AddToNamedContentOnly(o)}}catch(t){s.e(t)}finally{s.f()}}}},{key:"countFlags",get:function(){var t=0;return this.visitsShouldBeCounted&&(t|=i.CountFlags.Visits),this.turnIndexShouldBeCounted&&(t|=i.CountFlags.Turns),this.countingAtStartOnly&&(t|=i.CountFlags.CountStartOnly),t==i.CountFlags.CountStartOnly&&(t=0),t},set:function(t){var e=t;(e&i.CountFlags.Visits)>0&&(this.visitsShouldBeCounted=!0),(e&i.CountFlags.Turns)>0&&(this.turnIndexShouldBeCounted=!0),(e&i.CountFlags.CountStartOnly)>0&&(this.countingAtStartOnly=!0)}},{key:"pathToFirstLeafContent",get:function(){return null==this._pathToFirstLeafContent&&(this._pathToFirstLeafContent=this.path.PathByAppendingPath(this.internalPathToFirstLeafContent)),this._pathToFirstLeafContent}},{key:"internalPathToFirstLeafContent",get:function(){for(var t=[],e=this;e instanceof i;)e.content.length>0&&(t.push(new S.Component(0)),e=e.content[0]);return new S(t)}},{key:"AddContent",value:function(t){if(t instanceof Array){var e,n=m(t);try{for(n.s();!(e=n.n()).done;){var i=e.value;this.AddContent(i)}}catch(t){n.e(t)}finally{n.f()}}else{var r=t;if(this._content.push(r),r.parent)throw new Error("content is already in "+r.parent);r.parent=this,this.TryAddNamedContent(r)}}},{key:"TryAddNamedContent",value:function(t){var e=b(t);null!=e&&e.hasValidName&&this.AddToNamedContentOnly(e)}},{key:"AddToNamedContentOnly",value:function(t){if(g.AssertType(t,P,"Can only add Runtime.Objects to a Runtime.Container"),C(t,P).parent=this,null===t.name)return O("namedContentObj.name");this.namedContent.set(t.name,t)}},{key:"ContentAtPath",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-1;-1==n&&(n=t.length);var r=new q;r.approximate=!1;for(var a=this,s=this,o=e;o=0&&t.index=0||l.set(f,d)}}catch(t){h.e(t)}finally{h.f()}if(l.size>0){r(),t.AppendLine("-- named: --");var p,y=m(l);try{for(y.s();!(p=y.n()).done;){var S=v(p.value,2),k=S[1];g.AssertType(k,i,"Can only print out named Containers");var b=k;b.BuildStringOfHierarchy(t,e,n),t.AppendLine()}}catch(t){y.e(t)}finally{y.f()}}e--,r(),t.Append("]")}}]),i}(P);!function(t){var e;(e=t.CountFlags||(t.CountFlags={}))[e.Visits=1]="Visits",e[e.Turns=2]="Turns",e[e.CountStartOnly=4]="CountStartOnly"}(U||(U={}));var K,z=function(t){a(i,t);var e=f(i);function i(){return n(this,i),e.apply(this,arguments)}return r(i,[{key:"toString",value:function(){return"Glue"}}]),i}(P),H=function(t){a(i,t);var e=f(i);function i(){var t,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:i.CommandType.NotSet;return n(this,i),(t=e.call(this))._commandType=r,t}return r(i,[{key:"commandType",get:function(){return this._commandType}},{key:"Copy",value:function(){return new i(this.commandType)}},{key:"toString",value:function(){return this.commandType.toString()}}],[{key:"EvalStart",value:function(){return new i(i.CommandType.EvalStart)}},{key:"EvalOutput",value:function(){return new i(i.CommandType.EvalOutput)}},{key:"EvalEnd",value:function(){return new i(i.CommandType.EvalEnd)}},{key:"Duplicate",value:function(){return new i(i.CommandType.Duplicate)}},{key:"PopEvaluatedValue",value:function(){return new i(i.CommandType.PopEvaluatedValue)}},{key:"PopFunction",value:function(){return new i(i.CommandType.PopFunction)}},{key:"PopTunnel",value:function(){return new i(i.CommandType.PopTunnel)}},{key:"BeginString",value:function(){return new i(i.CommandType.BeginString)}},{key:"EndString",value:function(){return new i(i.CommandType.EndString)}},{key:"NoOp",value:function(){return new i(i.CommandType.NoOp)}},{key:"ChoiceCount",value:function(){return new i(i.CommandType.ChoiceCount)}},{key:"Turns",value:function(){return new i(i.CommandType.Turns)}},{key:"TurnsSince",value:function(){return new i(i.CommandType.TurnsSince)}},{key:"ReadCount",value:function(){return new i(i.CommandType.ReadCount)}},{key:"Random",value:function(){return new i(i.CommandType.Random)}},{key:"SeedRandom",value:function(){return new i(i.CommandType.SeedRandom)}},{key:"VisitIndex",value:function(){return new i(i.CommandType.VisitIndex)}},{key:"SequenceShuffleIndex",value:function(){return new i(i.CommandType.SequenceShuffleIndex)}},{key:"StartThread",value:function(){return new i(i.CommandType.StartThread)}},{key:"Done",value:function(){return new i(i.CommandType.Done)}},{key:"End",value:function(){return new i(i.CommandType.End)}},{key:"ListFromInt",value:function(){return new i(i.CommandType.ListFromInt)}},{key:"ListRange",value:function(){return new i(i.CommandType.ListRange)}},{key:"ListRandom",value:function(){return new i(i.CommandType.ListRandom)}}]),i}(P);!function(t){var e;(e=t.CommandType||(t.CommandType={}))[e.NotSet=-1]="NotSet",e[e.EvalStart=0]="EvalStart",e[e.EvalOutput=1]="EvalOutput",e[e.EvalEnd=2]="EvalEnd",e[e.Duplicate=3]="Duplicate",e[e.PopEvaluatedValue=4]="PopEvaluatedValue",e[e.PopFunction=5]="PopFunction",e[e.PopTunnel=6]="PopTunnel",e[e.BeginString=7]="BeginString",e[e.EndString=8]="EndString",e[e.NoOp=9]="NoOp",e[e.ChoiceCount=10]="ChoiceCount",e[e.Turns=11]="Turns",e[e.TurnsSince=12]="TurnsSince",e[e.Random=13]="Random",e[e.SeedRandom=14]="SeedRandom",e[e.VisitIndex=15]="VisitIndex",e[e.SequenceShuffleIndex=16]="SequenceShuffleIndex",e[e.StartThread=17]="StartThread",e[e.Done=18]="Done",e[e.End=19]="End",e[e.ListFromInt=20]="ListFromInt",e[e.ListRange=21]="ListRange",e[e.ListRandom=22]="ListRandom",e[e.ReadCount=23]="ReadCount",e[e.TOTAL_VALUES=24]="TOTAL_VALUES"}(H||(H={})),function(t){t[t.Tunnel=0]="Tunnel",t[t.Function=1]="Function",t[t.FunctionEvaluationFromGame=2]="FunctionEvaluationFromGame"}(K||(K={}));var X=function(){function t(){n(this,t),this.container=null,this.index=-1,2===arguments.length&&(this.container=arguments[0],this.index=arguments[1])}return r(t,[{key:"Resolve",value:function(){return this.index<0?this.container:null==this.container?null:0==this.container.content.length?this.container:this.index>=this.container.content.length?null:this.container.content[this.index]}},{key:"isNull",get:function(){return null==this.container}},{key:"path",get:function(){return this.isNull?null:this.index>=0?this.container.path.PathByAppendingComponent(new S.Component(this.index)):this.container.path}},{key:"toString",value:function(){return this.container?"Ink Pointer -> "+this.container.path.toString()+" -- index "+this.index:"Ink Pointer (null)"}},{key:"copy",value:function(){return new t(this.container,this.index)}}],[{key:"StartOf",value:function(e){return new t(e,0)}},{key:"Null",get:function(){return new t(null,-1)}}]),t}(),$=function(t){a(i,t);var e=f(i);function i(t){var r;return n(this,i),(r=e.call(this))._targetPath=null,r._targetPointer=X.Null,r.variableDivertName=null,r.pushesToStack=!1,r.stackPushType=0,r.isExternal=!1,r.externalArgs=0,r.isConditional=!1,r.pushesToStack=!1,void 0!==t&&(r.pushesToStack=!0,r.stackPushType=t),r}return r(i,[{key:"targetPath",get:function(){if(null!=this._targetPath&&this._targetPath.isRelative){var t=this.targetPointer.Resolve();t&&(this._targetPath=t.path)}return this._targetPath},set:function(t){this._targetPath=t,this._targetPointer=X.Null}},{key:"targetPointer",get:function(){if(this._targetPointer.isNull){var t=this.ResolvePath(this._targetPath).obj;if(null===this._targetPath)return O("this._targetPath");if(null===this._targetPath.lastComponent)return O("this._targetPath.lastComponent");if(this._targetPath.lastComponent.isIndex){if(null===t)return O("targetObj");this._targetPointer.container=t.parent instanceof U?t.parent:null,this._targetPointer.index=this._targetPath.lastComponent.index}else this._targetPointer=X.StartOf(t instanceof U?t:null)}return this._targetPointer.copy()}},{key:"targetPathString",get:function(){return null==this.targetPath?null:this.CompactPathString(this.targetPath)},set:function(t){this.targetPath=null==t?null:new S(t)}},{key:"hasVariableTarget",get:function(){return null!=this.variableDivertName}},{key:"Equals",value:function(t){var e=t;return e instanceof i&&this.hasVariableTarget==e.hasVariableTarget&&(this.hasVariableTarget?this.variableDivertName==e.variableDivertName:null===this.targetPath?O("this.targetPath"):this.targetPath.Equals(e.targetPath))}},{key:"toString",value:function(){if(this.hasVariableTarget)return"Divert(variable: "+this.variableDivertName+")";if(null==this.targetPath)return"Divert(null)";var t=new N,e=this.targetPath.toString();return t.Append("Divert"),this.isConditional&&t.Append("?"),this.pushesToStack&&(this.stackPushType==K.Function?t.Append(" function"):t.Append(" tunnel")),t.Append(" -> "),t.Append(this.targetPathString),t.Append(" ("),t.Append(e),t.Append(")"),t.toString()}}]),i}(P),Y=function(t){a(i,t);var e=f(i);function i(){var t,r=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return n(this,i),(t=e.call(this))._pathOnChoice=null,t.hasCondition=!1,t.hasStartContent=!1,t.hasChoiceOnlyContent=!1,t.isInvisibleDefault=!1,t.onceOnly=!0,t.onceOnly=r,t}return r(i,[{key:"pathOnChoice",get:function(){if(null!=this._pathOnChoice&&this._pathOnChoice.isRelative){var t=this.choiceTarget;t&&(this._pathOnChoice=t.path)}return this._pathOnChoice},set:function(t){this._pathOnChoice=t}},{key:"choiceTarget",get:function(){return null===this._pathOnChoice?O("ChoicePoint._pathOnChoice"):this.ResolvePath(this._pathOnChoice).container}},{key:"pathStringOnChoice",get:function(){return null===this.pathOnChoice?O("ChoicePoint.pathOnChoice"):this.CompactPathString(this.pathOnChoice)},set:function(t){this.pathOnChoice=new S(t)}},{key:"flags",get:function(){var t=0;return this.hasCondition&&(t|=1),this.hasStartContent&&(t|=2),this.hasChoiceOnlyContent&&(t|=4),this.isInvisibleDefault&&(t|=8),this.onceOnly&&(t|=16),t},set:function(t){this.hasCondition=(1&t)>0,this.hasStartContent=(2&t)>0,this.hasChoiceOnlyContent=(4&t)>0,this.isInvisibleDefault=(8&t)>0,this.onceOnly=(16&t)>0}},{key:"toString",value:function(){return null===this.pathOnChoice?O("ChoicePoint.pathOnChoice"):"Choice: -> "+this.pathOnChoice.toString()}}]),i}(P),Q=function(t){a(i,t);var e=f(i);function i(){var t,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;return n(this,i),(t=e.call(this)).pathForCount=null,t.name=r,t}return r(i,[{key:"containerForCount",get:function(){return null===this.pathForCount?null:this.ResolvePath(this.pathForCount).container}},{key:"pathStringForCount",get:function(){return null===this.pathForCount?null:this.CompactPathString(this.pathForCount)},set:function(t){this.pathForCount=null===t?null:new S(t)}},{key:"toString",value:function(){return null!=this.name?"var("+this.name+")":"read_count("+this.pathStringForCount+")"}}]),i}(P),Z=function(t){a(i,t);var e=f(i);function i(t,r){var a;return n(this,i),(a=e.call(this)).variableName=t||null,a.isNewDeclaration=!!r,a.isGlobal=!1,a}return r(i,[{key:"toString",value:function(){return"VarAssign to "+this.variableName}}]),i}(P),tt=function(t){a(i,t);var e=f(i);function i(){return n(this,i),e.apply(this,arguments)}return r(i)}(P),et=function(t){a(i,t);var e=f(i);function i(){var t;if(n(this,i),(t=e.call(this))._name=null,t._numberOfParameters=0,t._prototype=null,t._isPrototype=!1,t._operationFuncs=null,0===arguments.length)i.GenerateNativeFunctionsIfNecessary();else if(1===arguments.length){var r=arguments[0];i.GenerateNativeFunctionsIfNecessary(),t.name=r}else if(2===arguments.length){var a=arguments[0],s=arguments[1];t._isPrototype=!0,t.name=a,t.numberOfParameters=s}return t}return r(i,[{key:"name",get:function(){return null===this._name?O("NativeFunctionCall._name"):this._name},set:function(t){this._name=t,this._isPrototype||(null===i._nativeFunctions?O("NativeFunctionCall._nativeFunctions"):this._prototype=i._nativeFunctions.get(this._name)||null)}},{key:"numberOfParameters",get:function(){return this._prototype?this._prototype.numberOfParameters:this._numberOfParameters},set:function(t){this._numberOfParameters=t}},{key:"Call",value:function(t){if(this._prototype)return this._prototype.Call(t);if(this.numberOfParameters!=t.length)throw new Error("Unexpected number of parameters");var e,n=!1,i=m(t);try{for(i.s();!(e=i.n()).done;){var r=e.value;if(r instanceof tt)throw new x('Attempting to perform operation on a void value. Did you forget to "return" a value from a function you called here?');r instanceof J&&(n=!0)}}catch(t){i.e(t)}finally{i.f()}if(2==t.length&&n)return this.CallBinaryListOperation(t);var a=this.CoerceValuesToSingleType(t),s=a[0].valueType;return s==W.Int||s==W.Float||s==W.String||s==W.DivertTarget||s==W.List?this.CallType(a):null}},{key:"CallType",value:function(t){var e=C(t[0],L),n=e.valueType,r=e,a=t.length;if(2==a||1==a){if(null===this._operationFuncs)return O("NativeFunctionCall._operationFuncs");var s=this._operationFuncs.get(n);if(!s){var o=W[n];throw new x("Cannot perform operation "+this.name+" on "+o)}if(2==a){var u=C(t[1],L),l=s;if(null===r.value||null===u.value)return O("NativeFunctionCall.Call BinaryOp values");var h=l(r.value,u.value);return L.Create(h)}var c=s;if(null===r.value)return O("NativeFunctionCall.Call UnaryOp value");var f=c(r.value);return this.name===i.Int?L.Create(f,W.Int):this.name===i.Float?L.Create(f,W.Float):L.Create(f,e.valueType)}throw new Error("Unexpected number of parameters to NativeFunctionCall: "+t.length)}},{key:"CallBinaryListOperation",value:function(t){if(("+"==this.name||"-"==this.name)&&t[0]instanceof J&&t[1]instanceof j)return this.CallListIncrementOperation(t);var e=C(t[0],L),n=C(t[1],L);if(!("&&"!=this.name&&"||"!=this.name||e.valueType==W.List&&n.valueType==W.List)){if(null===this._operationFuncs)return O("NativeFunctionCall._operationFuncs");var i=this._operationFuncs.get(W.Int);if(null===i)return O("NativeFunctionCall.CallBinaryListOperation op");var r=function(t){if("boolean"==typeof t)return t;throw new Error("".concat(t," is not a boolean"))}(i(e.isTruthy?1:0,n.isTruthy?1:0));return new R(r)}if(e.valueType==W.List&&n.valueType==W.List)return this.CallType([e,n]);throw new x("Can not call use "+this.name+" operation on "+W[e.valueType]+" and "+W[n.valueType])}},{key:"CallListIncrementOperation",value:function(t){var e=C(t[0],J),n=C(t[1],j),i=new I;if(null===e.value)return O("NativeFunctionCall.CallListIncrementOperation listVal.value");var r,a=m(e.value);try{for(a.s();!(r=a.n()).done;){var s=v(r.value,2),o=s[0],u=s[1],l=A.fromSerializedKey(o);if(null===this._operationFuncs)return O("NativeFunctionCall._operationFuncs");var h=this._operationFuncs.get(W.Int);if(null===n.value)return O("NativeFunctionCall.CallListIncrementOperation intVal.value");var c=h(u,n.value),f=null;if(null===e.value.origins)return O("NativeFunctionCall.CallListIncrementOperation listVal.value.origins");var d,p=m(e.value.origins);try{for(p.s();!(d=p.n()).done;){var y=d.value;if(y.name==l.originName){f=y;break}}}catch(t){p.e(t)}finally{p.f()}if(null!=f){var g=f.TryGetItemWithValue(c,A.Null);g.exists&&i.Add(g.result,c)}}}catch(t){a.e(t)}finally{a.f()}return new J(i)}},{key:"CoerceValuesToSingleType",value:function(t){var e,n=W.Int,i=null,r=m(t);try{for(r.s();!(e=r.n()).done;){var a=C(e.value,L);a.valueType>n&&(n=a.valueType),a.valueType==W.List&&(i=k(a,J))}}catch(t){r.e(t)}finally{r.f()}var s=[];if(W[n]==W[W.List]){var o,u=m(t);try{for(u.s();!(o=u.n()).done;){var l=C(o.value,L);if(l.valueType==W.List)s.push(l);else{if(l.valueType!=W.Int){var h=W[l.valueType];throw new x("Cannot mix Lists and "+h+" values in this operation")}var c=parseInt(l.valueObject);if(null===(i=C(i,J)).value)return O("NativeFunctionCall.CoerceValuesToSingleType specialCaseList.value");var f=i.value.originOfMaxItem;if(null===f)return O("NativeFunctionCall.CoerceValuesToSingleType list");var v=f.TryGetItemWithValue(c,A.Null);if(!v.exists)throw new x("Could not find List item with the value "+c+" in "+f.name);var d=new J(v.result,c);s.push(d)}}}catch(t){u.e(t)}finally{u.f()}}else{var p,y=m(t);try{for(y.s();!(p=y.n()).done;){var g=C(p.value,L).Cast(n);s.push(g)}}catch(t){y.e(t)}finally{y.f()}}return s}},{key:"AddOpFuncForType",value:function(t,e){null==this._operationFuncs&&(this._operationFuncs=new Map),this._operationFuncs.set(t,e)}},{key:"toString",value:function(){return'Native "'+this.name+'"'}}],[{key:"CallWithName",value:function(t){return new i(t)}},{key:"CallExistsWithName",value:function(t){return this.GenerateNativeFunctionsIfNecessary(),this._nativeFunctions.get(t)}},{key:"Identity",value:function(t){return t}},{key:"GenerateNativeFunctionsIfNecessary",value:function(){if(null==this._nativeFunctions){this._nativeFunctions=new Map,this.AddIntBinaryOp(this.Add,(function(t,e){return t+e})),this.AddIntBinaryOp(this.Subtract,(function(t,e){return t-e})),this.AddIntBinaryOp(this.Multiply,(function(t,e){return t*e})),this.AddIntBinaryOp(this.Divide,(function(t,e){return Math.floor(t/e)})),this.AddIntBinaryOp(this.Mod,(function(t,e){return t%e})),this.AddIntUnaryOp(this.Negate,(function(t){return-t})),this.AddIntBinaryOp(this.Equal,(function(t,e){return t==e})),this.AddIntBinaryOp(this.Greater,(function(t,e){return t>e})),this.AddIntBinaryOp(this.Less,(function(t,e){return t=e})),this.AddIntBinaryOp(this.LessThanOrEquals,(function(t,e){return t<=e})),this.AddIntBinaryOp(this.NotEquals,(function(t,e){return t!=e})),this.AddIntUnaryOp(this.Not,(function(t){return 0==t})),this.AddIntBinaryOp(this.And,(function(t,e){return 0!=t&&0!=e})),this.AddIntBinaryOp(this.Or,(function(t,e){return 0!=t||0!=e})),this.AddIntBinaryOp(this.Max,(function(t,e){return Math.max(t,e)})),this.AddIntBinaryOp(this.Min,(function(t,e){return Math.min(t,e)})),this.AddIntBinaryOp(this.Pow,(function(t,e){return Math.pow(t,e)})),this.AddIntUnaryOp(this.Floor,i.Identity),this.AddIntUnaryOp(this.Ceiling,i.Identity),this.AddIntUnaryOp(this.Int,i.Identity),this.AddIntUnaryOp(this.Float,(function(t){return t})),this.AddFloatBinaryOp(this.Add,(function(t,e){return t+e})),this.AddFloatBinaryOp(this.Subtract,(function(t,e){return t-e})),this.AddFloatBinaryOp(this.Multiply,(function(t,e){return t*e})),this.AddFloatBinaryOp(this.Divide,(function(t,e){return t/e})),this.AddFloatBinaryOp(this.Mod,(function(t,e){return t%e})),this.AddFloatUnaryOp(this.Negate,(function(t){return-t})),this.AddFloatBinaryOp(this.Equal,(function(t,e){return t==e})),this.AddFloatBinaryOp(this.Greater,(function(t,e){return t>e})),this.AddFloatBinaryOp(this.Less,(function(t,e){return t=e})),this.AddFloatBinaryOp(this.LessThanOrEquals,(function(t,e){return t<=e})),this.AddFloatBinaryOp(this.NotEquals,(function(t,e){return t!=e})),this.AddFloatUnaryOp(this.Not,(function(t){return 0==t})),this.AddFloatBinaryOp(this.And,(function(t,e){return 0!=t&&0!=e})),this.AddFloatBinaryOp(this.Or,(function(t,e){return 0!=t||0!=e})),this.AddFloatBinaryOp(this.Max,(function(t,e){return Math.max(t,e)})),this.AddFloatBinaryOp(this.Min,(function(t,e){return Math.min(t,e)})),this.AddFloatBinaryOp(this.Pow,(function(t,e){return Math.pow(t,e)})),this.AddFloatUnaryOp(this.Floor,(function(t){return Math.floor(t)})),this.AddFloatUnaryOp(this.Ceiling,(function(t){return Math.ceil(t)})),this.AddFloatUnaryOp(this.Int,(function(t){return Math.floor(t)})),this.AddFloatUnaryOp(this.Float,i.Identity),this.AddStringBinaryOp(this.Add,(function(t,e){return t+e})),this.AddStringBinaryOp(this.Equal,(function(t,e){return t===e})),this.AddStringBinaryOp(this.NotEquals,(function(t,e){return!(t===e)})),this.AddStringBinaryOp(this.Has,(function(t,e){return t.includes(e)})),this.AddStringBinaryOp(this.Hasnt,(function(t,e){return!t.includes(e)})),this.AddListBinaryOp(this.Add,(function(t,e){return t.Union(e)})),this.AddListBinaryOp(this.Subtract,(function(t,e){return t.Without(e)})),this.AddListBinaryOp(this.Has,(function(t,e){return t.Contains(e)})),this.AddListBinaryOp(this.Hasnt,(function(t,e){return!t.Contains(e)})),this.AddListBinaryOp(this.Intersect,(function(t,e){return t.Intersect(e)})),this.AddListBinaryOp(this.Equal,(function(t,e){return t.Equals(e)})),this.AddListBinaryOp(this.Greater,(function(t,e){return t.GreaterThan(e)})),this.AddListBinaryOp(this.Less,(function(t,e){return t.LessThan(e)})),this.AddListBinaryOp(this.GreaterThanOrEquals,(function(t,e){return t.GreaterThanOrEquals(e)})),this.AddListBinaryOp(this.LessThanOrEquals,(function(t,e){return t.LessThanOrEquals(e)})),this.AddListBinaryOp(this.NotEquals,(function(t,e){return!t.Equals(e)})),this.AddListBinaryOp(this.And,(function(t,e){return t.Count>0&&e.Count>0})),this.AddListBinaryOp(this.Or,(function(t,e){return t.Count>0||e.Count>0})),this.AddListUnaryOp(this.Not,(function(t){return 0==t.Count?1:0})),this.AddListUnaryOp(this.Invert,(function(t){return t.inverse})),this.AddListUnaryOp(this.All,(function(t){return t.all})),this.AddListUnaryOp(this.ListMin,(function(t){return t.MinAsList()})),this.AddListUnaryOp(this.ListMax,(function(t){return t.MaxAsList()})),this.AddListUnaryOp(this.Count,(function(t){return t.Count})),this.AddListUnaryOp(this.ValueOfList,(function(t){return t.maxItem.Value}));this.AddOpToNativeFunc(this.Equal,2,W.DivertTarget,(function(t,e){return t.Equals(e)})),this.AddOpToNativeFunc(this.NotEquals,2,W.DivertTarget,(function(t,e){return!t.Equals(e)}))}}},{key:"AddOpToNativeFunc",value:function(t,e,n,r){if(null===this._nativeFunctions)return O("NativeFunctionCall._nativeFunctions");var a=this._nativeFunctions.get(t);a||(a=new i(t,e),this._nativeFunctions.set(t,a)),a.AddOpFuncForType(n,r)}},{key:"AddIntBinaryOp",value:function(t,e){this.AddOpToNativeFunc(t,2,W.Int,e)}},{key:"AddIntUnaryOp",value:function(t,e){this.AddOpToNativeFunc(t,1,W.Int,e)}},{key:"AddFloatBinaryOp",value:function(t,e){this.AddOpToNativeFunc(t,2,W.Float,e)}},{key:"AddFloatUnaryOp",value:function(t,e){this.AddOpToNativeFunc(t,1,W.Float,e)}},{key:"AddStringBinaryOp",value:function(t,e){this.AddOpToNativeFunc(t,2,W.String,e)}},{key:"AddListBinaryOp",value:function(t,e){this.AddOpToNativeFunc(t,2,W.List,e)}},{key:"AddListUnaryOp",value:function(t,e){this.AddOpToNativeFunc(t,1,W.List,e)}}]),i}(P);et.Add="+",et.Subtract="-",et.Divide="/",et.Multiply="*",et.Mod="%",et.Negate="_",et.Equal="==",et.Greater=">",et.Less="<",et.GreaterThanOrEquals=">=",et.LessThanOrEquals="<=",et.NotEquals="!=",et.Not="!",et.And="&&",et.Or="||",et.Min="MIN",et.Max="MAX",et.Pow="POW",et.Floor="FLOOR",et.Ceiling="CEILING",et.Int="INT",et.Float="FLOAT",et.Has="?",et.Hasnt="!?",et.Intersect="^",et.ListMin="LIST_MIN",et.ListMax="LIST_MAX",et.All="LIST_ALL",et.Count="LIST_COUNT",et.ValueOfList="LIST_VALUE",et.Invert="LIST_INVERT",et._nativeFunctions=null;var nt=function(t){a(i,t);var e=f(i);function i(t){var r;return n(this,i),(r=e.call(this)).text=t.toString()||"",r}return r(i,[{key:"toString",value:function(){return"# "+this.text}}]),i}(P),it=function(t){a(i,t);var e=f(i);function i(){var t;return n(this,i),(t=e.apply(this,arguments)).text="",t.index=0,t.threadAtGeneration=null,t.sourcePath="",t.targetPath=null,t.isInvisibleDefault=!1,t.originalThreadIndex=0,t}return r(i,[{key:"pathStringOnChoice",get:function(){return null===this.targetPath?O("Choice.targetPath"):this.targetPath.toString()},set:function(t){this.targetPath=new S(t)}}]),i}(P),rt=function(){function t(e,i){n(this,t),this._name=e||"",this._items=null,this._itemNameToValues=i||new Map}return r(t,[{key:"name",get:function(){return this._name}},{key:"items",get:function(){if(null==this._items){this._items=new Map;var t,e=m(this._itemNameToValues);try{for(e.s();!(t=e.n()).done;){var n=v(t.value,2),i=n[0],r=n[1],a=new A(this.name,i);this._items.set(a.serialized(),r)}}catch(t){e.e(t)}finally{e.f()}}return this._items}},{key:"ValueForItem",value:function(t){if(!t.itemName)return 0;var e=this._itemNameToValues.get(t.itemName);return void 0!==e?e:0}},{key:"ContainsItem",value:function(t){return!!t.itemName&&(t.originName==this.name&&this._itemNameToValues.has(t.itemName))}},{key:"ContainsItemWithName",value:function(t){return this._itemNameToValues.has(t)}},{key:"TryGetItemWithValue",value:function(t,e){var n,i=m(this._itemNameToValues);try{for(i.s();!(n=i.n()).done;){var r=v(n.value,2),a=r[0];if(r[1]==t)return{result:new A(this.name,a),exists:!0}}}catch(t){i.e(t)}finally{i.f()}return{result:A.Null,exists:!1}}},{key:"TryGetValueForItem",value:function(t,e){if(!t.itemName)return{result:0,exists:!1};var n=this._itemNameToValues.get(t.itemName);return n?{result:n,exists:!0}:{result:0,exists:!1}}}]),t}(),at=function(){function t(e){n(this,t),this._lists=new Map,this._allUnambiguousListValueCache=new Map;var i,r=m(e);try{for(r.s();!(i=r.n()).done;){var a=i.value;this._lists.set(a.name,a);var s,o=m(a.items);try{for(o.s();!(s=o.n()).done;){var u=v(s.value,2),l=u[0],h=u[1],c=A.fromSerializedKey(l),f=new J(c,h);if(!c.itemName)throw new Error("item.itemName is null or undefined.");this._allUnambiguousListValueCache.set(c.itemName,f),this._allUnambiguousListValueCache.set(c.fullName,f)}}catch(t){o.e(t)}finally{o.f()}}}catch(t){r.e(t)}finally{r.f()}}return r(t,[{key:"lists",get:function(){var t,e=[],n=m(this._lists);try{for(n.s();!(t=n.n()).done;){var i=v(t.value,2)[1];e.push(i)}}catch(t){n.e(t)}finally{n.f()}return e}},{key:"TryListGetDefinition",value:function(t,e){if(null===t)return{result:e,exists:!1};var n=this._lists.get(t);return n?{result:n,exists:!0}:{result:e,exists:!1}}},{key:"FindSingleItemListWithName",value:function(t){if(null===t)return O("name");var e=this._allUnambiguousListValueCache.get(t);return void 0!==e?e:null}}]),t}(),st=function(){function t(){n(this,t)}return r(t,null,[{key:"JArrayToRuntimeObjList",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.length;e&&n--;for(var i=[],r=0;rt->")),a=r.hasVariableTarget?r.variableDivertName:r.targetPathString,e.WriteObjectStart(),e.WriteProperty(s,a),r.hasVariableTarget&&e.WriteProperty("var",!0),r.isConditional&&e.WriteProperty("c",!0),r.externalArgs>0&&e.WriteIntProperty("exArgs",r.externalArgs),void e.WriteObjectEnd()}var o=k(n,Y);if(o)return e.WriteObjectStart(),e.WriteProperty("*",o.pathStringOnChoice),e.WriteIntProperty("flg",o.flags),void e.WriteObjectEnd();var u=k(n,R);if(u)e.WriteBool(u.value);else{var l=k(n,j);if(l)e.WriteInt(l.value);else{var h=k(n,D);if(h)e.WriteFloat(h.value);else{var c=k(n,B);if(c)c.isNewline?e.Write("\n",!1):(e.WriteStringStart(),e.WriteStringInner("^"),e.WriteStringInner(c.value),e.WriteStringEnd());else{var f=k(n,J);if(f)this.WriteInkList(e,f);else{var v=k(n,G);if(v)return e.WriteObjectStart(),null===v.value?O("divTargetVal.value"):(e.WriteProperty("^->",v.value.componentsString),void e.WriteObjectEnd());var d=k(n,M);if(d)return e.WriteObjectStart(),e.WriteProperty("^var",d.value),e.WriteIntProperty("ci",d.contextIndex),void e.WriteObjectEnd();if(k(n,z))e.Write("<>");else{var p=k(n,H);if(p)e.Write(t._controlCommandNames[p.commandType]);else{var y=k(n,et);if(y){var m=y.name;return"^"==m&&(m="L^"),void e.Write(m)}var g=k(n,Q);if(g){e.WriteObjectStart();var S=g.pathStringForCount;return null!=S?e.WriteProperty("CNT?",S):e.WriteProperty("VAR?",g.name),void e.WriteObjectEnd()}var C=k(n,Z);if(C){e.WriteObjectStart();var b=C.isGlobal?"VAR=":"temp=";return e.WriteProperty(b,C.variableName),C.isNewDeclaration||e.WriteProperty("re",!0),void e.WriteObjectEnd()}if(k(n,tt))e.Write("void");else{var _=k(n,nt);if(_)return e.WriteObjectStart(),e.WriteProperty("#",_.text),void e.WriteObjectEnd();var w=k(n,it);if(!w)throw new Error("Failed to convert runtime object to Json token: "+n);this.WriteChoice(e,w)}}}}}}}}}}},{key:"JObjectToDictionaryRuntimeObjs",value:function(t){var e=new Map;for(var n in t)if(t.hasOwnProperty(n)){var i=this.JTokenToRuntimeObject(t[n]);if(null===i)return O("inkObject");e.set(n,i)}return e}},{key:"JObjectToIntDictionary",value:function(t){var e=new Map;for(var n in t)t.hasOwnProperty(n)&&e.set(n,parseInt(t[n]));return e}},{key:"JTokenToRuntimeObject",value:function(n){if("number"==typeof n&&!isNaN(n)||"boolean"==typeof n)return L.Create(n);if("string"==typeof n){var i=n.toString(),r=i[0];if("^"==r)return new B(i.substring(1));if("\n"==r&&1==i.length)return new B("\n");if("<>"==i)return new z;for(var a=0;a->"==i)return H.PopTunnel();if("~ret"==i)return H.PopFunction();if("void"==i)return new tt}if("object"===e(n)&&!Array.isArray(n)){var s,o=n;if(o["^->"])return s=o["^->"],new G(new S(s.toString()));if(o["^var"]){s=o["^var"];var u=new M(s.toString());return"ci"in o&&(s=o.ci,u.contextIndex=parseInt(s)),u}var l=!1,h=!1,c=K.Function,f=!1;if((s=o["->"])?l=!0:(s=o["f()"])?(l=!0,h=!0,c=K.Function):(s=o["->t->"])?(l=!0,h=!0,c=K.Tunnel):(s=o["x()"])&&(l=!0,f=!0,h=!1,c=K.Function),l){var v=new $;v.pushesToStack=h,v.stackPushType=c,v.isExternal=f;var d=s.toString();return(s=o.var)?v.variableDivertName=d:v.targetPathString=d,v.isConditional=!!o.c,f&&(s=o.exArgs)&&(v.externalArgs=parseInt(s)),v}if(s=o["*"]){var p=new Y;return p.pathStringOnChoice=s.toString(),(s=o.flg)&&(p.flags=parseInt(s)),p}if(s=o["VAR?"])return new Q(s.toString());if(s=o["CNT?"]){var y=new Q;return y.pathStringForCount=s.toString(),y}var m=!1,g=!1;if((s=o["VAR="])?(m=!0,g=!0):(s=o["temp="])&&(m=!0,g=!1),m){var k=s.toString(),C=!o.re,b=new Z(k,C);return b.isGlobal=g,b}if(void 0!==o["#"])return s=o["#"],new nt(s.toString());if(s=o.list){var _=s,w=new I;if(s=o.origins){var T=s;w.SetInitialOriginNames(T)}for(var E in _)if(_.hasOwnProperty(E)){var O=_[E],P=new A(E),N=parseInt(O);w.Add(P,N)}return new J(w)}if(null!=o.originalChoicePath)return this.JObjectToChoice(o)}if(Array.isArray(n))return this.JArrayToContainer(n);if(null==n)return null;throw new Error("Failed to convert token to runtime object: "+this.toJson(n,["parent"]))}},{key:"toJson",value:function(t,e,n){return JSON.stringify(t,(function(t,n){return(null==e?void 0:e.some((function(e){return e===t})))?void 0:n}),n)}},{key:"WriteRuntimeContainer",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(t.WriteArrayStart(),null===e)return O("container");var i,r=m(e.content);try{for(r.s();!(i=r.n()).done;){var a=i.value;this.WriteRuntimeObject(t,a)}}catch(t){r.e(t)}finally{r.f()}var s=e.namedOnlyContent,o=e.countFlags,u=null!=e.name&&!n,l=null!=s||o>0||u;if(l&&t.WriteObjectStart(),null!=s){var h,c=m(s);try{for(c.s();!(h=c.n()).done;){var f=v(h.value,2),d=f[0],p=f[1],y=d,g=k(p,U);t.WritePropertyStart(y),this.WriteRuntimeContainer(t,g,!0),t.WritePropertyEnd()}}catch(t){c.e(t)}finally{c.f()}}o>0&&t.WriteIntProperty("#f",o),u&&t.WriteProperty("#n",e.name),l?t.WriteObjectEnd():t.WriteNull(),t.WriteArrayEnd()}},{key:"JArrayToContainer",value:function(t){var e=new U;e.content=this.JArrayToRuntimeObjList(t,!0);var n=t[t.length-1];if(null!=n){var i=new Map;for(var r in n)if("#f"==r)e.countFlags=parseInt(n[r]);else if("#n"==r)e.name=n[r].toString();else{var a=this.JTokenToRuntimeObject(n[r]),s=k(a,U);s&&(s.name=r),i.set(r,a)}e.namedOnlyContent=i}return e}},{key:"JObjectToChoice",value:function(t){var e=new it;return e.text=t.text.toString(),e.index=parseInt(t.index),e.sourcePath=t.originalChoicePath.toString(),e.originalThreadIndex=parseInt(t.originalThreadIndex),e.pathStringOnChoice=t.targetPath.toString(),e}},{key:"WriteChoice",value:function(t,e){t.WriteObjectStart(),t.WriteProperty("text",e.text),t.WriteIntProperty("index",e.index),t.WriteProperty("originalChoicePath",e.sourcePath),t.WriteIntProperty("originalThreadIndex",e.originalThreadIndex),t.WriteProperty("targetPath",e.pathStringOnChoice),t.WriteObjectEnd()}},{key:"WriteInkList",value:function(t,e){var n=e.value;if(null===n)return O("rawList");t.WriteObjectStart(),t.WritePropertyStart("list"),t.WriteObjectStart();var i,r=m(n);try{for(r.s();!(i=r.n()).done;){var a=v(i.value,2),s=a[0],o=a[1],u=A.fromSerializedKey(s),l=o;if(null===u.itemName)return O("item.itemName");t.WritePropertyNameStart(),t.WritePropertyNameInner(u.originName?u.originName:"?"),t.WritePropertyNameInner("."),t.WritePropertyNameInner(u.itemName),t.WritePropertyNameEnd(),t.Write(l),t.WritePropertyEnd()}}catch(t){r.e(t)}finally{r.f()}if(t.WriteObjectEnd(),t.WritePropertyEnd(),0==n.Count&&null!=n.originNames&&n.originNames.length>0){t.WritePropertyStart("origins"),t.WriteArrayStart();var h,c=m(n.originNames);try{for(c.s();!(h=c.n()).done;){var f=h.value;t.Write(f)}}catch(t){c.e(t)}finally{c.f()}t.WriteArrayEnd(),t.WritePropertyEnd()}t.WriteObjectEnd()}},{key:"ListDefinitionsToJToken",value:function(t){var e,n={},i=m(t.lists);try{for(i.s();!(e=i.n()).done;){var r,a=e.value,s={},o=m(a.items);try{for(o.s();!(r=o.n()).done;){var u=v(r.value,2),l=u[0],h=u[1],c=A.fromSerializedKey(l);if(null===c.itemName)return O("item.itemName");s[c.itemName]=h}}catch(t){o.e(t)}finally{o.f()}n[a.name]=s}}catch(t){i.e(t)}finally{i.f()}return n}},{key:"JTokenToListDefinitions",value:function(t){var e=t,n=[];for(var i in e)if(e.hasOwnProperty(i)){var r=i.toString(),a=e[i],s=new Map;for(var o in a)if(e.hasOwnProperty(i)){var u=a[o];s.set(o,parseInt(u))}var l=new rt(r,s);n.push(l)}return new at(n)}}]),t}();st._controlCommandNames=function(){var t=[];t[H.CommandType.EvalStart]="ev",t[H.CommandType.EvalOutput]="out",t[H.CommandType.EvalEnd]="/ev",t[H.CommandType.Duplicate]="du",t[H.CommandType.PopEvaluatedValue]="pop",t[H.CommandType.PopFunction]="~ret",t[H.CommandType.PopTunnel]="->->",t[H.CommandType.BeginString]="str",t[H.CommandType.EndString]="/str",t[H.CommandType.NoOp]="nop",t[H.CommandType.ChoiceCount]="choiceCnt",t[H.CommandType.Turns]="turn",t[H.CommandType.TurnsSince]="turns",t[H.CommandType.ReadCount]="readc",t[H.CommandType.Random]="rnd",t[H.CommandType.SeedRandom]="srnd",t[H.CommandType.VisitIndex]="visit",t[H.CommandType.SequenceShuffleIndex]="seq",t[H.CommandType.StartThread]="thread",t[H.CommandType.Done]="done",t[H.CommandType.End]="end",t[H.CommandType.ListFromInt]="listInt",t[H.CommandType.ListRange]="range",t[H.CommandType.ListRandom]="lrnd";for(var e=0;e1}},{key:"Reset",value:function(){this._threads=[],this._threads.push(new e.Thread),this._threads[0].callstack.push(new e.Element(K.Tunnel,this._startOfRoot))}},{key:"SetJsonToken",value:function(t,n){this._threads.length=0;var i,r=m(t.threads);try{for(r.s();!(i=r.n()).done;){var a=i.value,s=new e.Thread(a,n);this._threads.push(s)}}catch(t){r.e(t)}finally{r.f()}this._threadCounter=parseInt(t.threadCounter),this._startOfRoot=X.StartOf(n.rootContentContainer)}},{key:"WriteJson",value:function(t){var e=this;t.WriteObject((function(t){t.WritePropertyStart("threads"),t.WriteArrayStart();var n,i=m(e._threads);try{for(i.s();!(n=i.n()).done;){n.value.WriteJson(t)}}catch(t){i.e(t)}finally{i.f()}t.WriteArrayEnd(),t.WritePropertyEnd(),t.WritePropertyStart("threadCounter"),t.WriteInt(e._threadCounter),t.WritePropertyEnd()}))}},{key:"PushThread",value:function(){var t=this.currentThread.Copy();this._threadCounter++,t.threadIndex=this._threadCounter,this._threads.push(t)}},{key:"ForkThread",value:function(){var t=this.currentThread.Copy();return this._threadCounter++,t.threadIndex=this._threadCounter,t}},{key:"PopThread",value:function(){if(!this.canPopThread)throw new Error("Can't pop thread");this._threads.splice(this._threads.indexOf(this.currentThread),1)}},{key:"canPopThread",get:function(){return this._threads.length>1&&!this.elementIsEvaluateFromGame}},{key:"elementIsEvaluateFromGame",get:function(){return this.currentElement.type==K.FunctionEvaluationFromGame}},{key:"Push",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,r=new e.Element(t,this.currentElement.currentPointer,!1);r.evaluationStackHeightWhenPushed=n,r.functionStartInOutputStream=i,this.callStack.push(r)}},{key:"CanPop",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;return!!this.canPop&&(null==t||this.currentElement.type==t)}},{key:"Pop",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;if(!this.CanPop(t))throw new Error("Mismatched push/pop in Callstack");this.callStack.pop()}},{key:"GetTemporaryVariableWithName",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;-1==e&&(e=this.currentElementIndex+1);var n=this.callStack[e-1],i=F(n.temporaryVariables,t,null);return i.exists?i.result:null}},{key:"SetTemporaryVariable",value:function(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:-1;-1==i&&(i=this.currentElementIndex+1);var r=this.callStack[i-1];if(!n&&!r.temporaryVariables.get(t))throw new Error("Could not find temporary variable to set: "+t);var a=F(r.temporaryVariables,t,null);a.exists&&J.RetainListOriginsForAssignment(a.result,e),r.temporaryVariables.set(t,e)}},{key:"ContextForVariableNamed",value:function(t){return this.currentElement.temporaryVariables.get(t)?this.currentElementIndex+1:0}},{key:"ThreadWithIndex",value:function(t){var e=this._threads.filter((function(e){if(e.threadIndex==t)return e}));return e.length>0?e[0]:null}},{key:"callStack",get:function(){return this.currentThread.callstack}},{key:"callStackTrace",get:function(){for(var t=new N,e=0;e")}}}return t.toString()}}]),e}();!function(t){var e=function(){function t(e,i){var r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];n(this,t),this.evaluationStackHeightWhenPushed=0,this.functionStartInOutputStream=0,this.currentPointer=i.copy(),this.inExpressionEvaluation=r,this.temporaryVariables=new Map,this.type=e}return r(t,[{key:"Copy",value:function(){var e=new t(this.type,this.currentPointer,this.inExpressionEvaluation);return e.temporaryVariables=new Map(this.temporaryVariables),e.evaluationStackHeightWhenPushed=this.evaluationStackHeightWhenPushed,e.functionStartInOutputStream=this.functionStartInOutputStream,e}}]),t}();t.Element=e;var i=function(){function t(){if(n(this,t),this.threadIndex=0,this.previousPointer=X.Null,this.callstack=[],arguments[0]&&arguments[1]){var i=arguments[0],r=arguments[1];this.threadIndex=parseInt(i.threadIndex);var a,s=i.callstack,o=m(s);try{for(o.s();!(a=o.n()).done;){var u=a.value,l=u,h=parseInt(l.type),c=X.Null,f=void 0,v=l.cPath;if(void 0!==v){f=v.toString();var d=r.ContentAtPath(new S(f));if(c.container=d.container,c.index=parseInt(l.idx),null==d.obj)throw new Error("When loading state, internal story location couldn't be found: "+f+". Has the story changed since this save data was created?");if(d.approximate){if(null===c.container)return O("pointer.container");r.Warning("When loading state, exact internal story location couldn't be found: '"+f+"', so it was approximated to '"+c.container.path.toString()+"' to recover. Has the story changed since this save data was created?")}}var p=!!l.exp,y=new e(h,c,p),g=l.temp;void 0!==g?y.temporaryVariables=st.JObjectToDictionaryRuntimeObjs(g):y.temporaryVariables.clear(),this.callstack.push(y)}}catch(t){o.e(t)}finally{o.f()}var k=i.previousContentObject;if(void 0!==k){var C=new S(k.toString());this.previousPointer=r.PointerAtPath(C)}}}return r(t,[{key:"Copy",value:function(){var e=new t;e.threadIndex=this.threadIndex;var n,i=m(this.callstack);try{for(i.s();!(n=i.n()).done;){var r=n.value;e.callstack.push(r.Copy())}}catch(t){i.e(t)}finally{i.f()}return e.previousPointer=this.previousPointer.copy(),e}},{key:"WriteJson",value:function(t){t.WriteObjectStart(),t.WritePropertyStart("callstack"),t.WriteArrayStart();var e,n=m(this.callstack);try{for(n.s();!(e=n.n()).done;){var i=e.value;if(t.WriteObjectStart(),!i.currentPointer.isNull){if(null===i.currentPointer.container)return O("el.currentPointer.container");t.WriteProperty("cPath",i.currentPointer.container.path.componentsString),t.WriteIntProperty("idx",i.currentPointer.index)}t.WriteProperty("exp",i.inExpressionEvaluation),t.WriteIntProperty("type",i.type),i.temporaryVariables.size>0&&(t.WritePropertyStart("temp"),st.WriteDictionaryRuntimeObjs(t,i.temporaryVariables),t.WritePropertyEnd()),t.WriteObjectEnd()}}catch(t){n.e(t)}finally{n.f()}if(t.WriteArrayEnd(),t.WritePropertyEnd(),t.WriteIntProperty("threadIndex",this.threadIndex),!this.previousPointer.isNull){var r=this.previousPointer.Resolve();if(null===r)return O("this.previousPointer.Resolve()");t.WriteProperty("previousContentObject",r.path.toString())}t.WriteObjectEnd()}}]),t}();t.Thread=i}(ot||(ot={}));var ut=function(){function t(e,i){n(this,t),this.variableChangedEventCallbacks=[],this.patch=null,this._batchObservingVariableChanges=!1,this._defaultGlobalVariables=new Map,this._changedVariablesForBatchObs=new Set,this._globalVariables=new Map,this._callStack=e,this._listDefsOrigin=i;try{return new Proxy(this,{get:function(t,e){return e in t?t[e]:t.$(e)},set:function(t,e,n){return e in t?t[e]=n:t.$(e,n),!0}})}catch(t){}}return r(t,[{key:"variableChangedEvent",value:function(t,e){var n,i=m(this.variableChangedEventCallbacks);try{for(i.s();!(n=i.n()).done;){(0,n.value)(t,e)}}catch(t){i.e(t)}finally{i.f()}}},{key:"batchObservingVariableChanges",get:function(){return this._batchObservingVariableChanges},set:function(t){if(this._batchObservingVariableChanges=t,t)this._changedVariablesForBatchObs=new Set;else if(null!=this._changedVariablesForBatchObs){var e,n=m(this._changedVariablesForBatchObs);try{for(n.s();!(e=n.n()).done;){var i=e.value,r=this._globalVariables.get(i);r?this.variableChangedEvent(i,r):O("currentValue")}}catch(t){n.e(t)}finally{n.f()}this._changedVariablesForBatchObs=null}}},{key:"callStack",get:function(){return this._callStack},set:function(t){this._callStack=t}},{key:"$",value:function(t,e){if(void 0===e){var n=null;return null!==this.patch&&(n=this.patch.TryGetGlobal(t,null)).exists?n.result.valueObject:(void 0===(n=this._globalVariables.get(t))&&(n=this._defaultGlobalVariables.get(t)),void 0!==n?n.valueObject:null)}if(void 0===this._defaultGlobalVariables.get(t))throw new x("Cannot assign to a variable ("+t+") that hasn't been declared in the story");var i=L.Create(e);if(null==i)throw null==e?new Error("Cannot pass null to VariableState"):new Error("Invalid value passed to VariableState: "+e.toString());this.SetGlobal(t,i)}},{key:"ApplyPatch",value:function(){if(null===this.patch)return O("this.patch");var t,e=m(this.patch.globals);try{for(e.s();!(t=e.n()).done;){var n=v(t.value,2),i=n[0],r=n[1];this._globalVariables.set(i,r)}}catch(t){e.e(t)}finally{e.f()}if(null!==this._changedVariablesForBatchObs){var a,s=m(this.patch.changedVariables);try{for(s.s();!(a=s.n()).done;){var o=a.value;this._changedVariablesForBatchObs.add(o)}}catch(t){s.e(t)}finally{s.f()}}this.patch=null}},{key:"SetJsonToken",value:function(t){this._globalVariables.clear();var e,n=m(this._defaultGlobalVariables);try{for(n.s();!(e=n.n()).done;){var i=v(e.value,2),r=i[0],a=i[1],s=t[r];if(void 0!==s){var o=st.JTokenToRuntimeObject(s);if(null===o)return O("tokenInkObject");this._globalVariables.set(r,o)}else this._globalVariables.set(r,a)}}catch(t){n.e(t)}finally{n.f()}}},{key:"WriteJson",value:function(e){e.WriteObjectStart();var n,i=m(this._globalVariables);try{for(i.s();!(n=i.n()).done;){var r=v(n.value,2),a=r[0],s=r[1],o=a,u=s;if(t.dontSaveDefaultValues&&this._defaultGlobalVariables.has(o)){var l=this._defaultGlobalVariables.get(o);if(this.RuntimeObjectsEqual(u,l))continue}e.WritePropertyStart(o),st.WriteRuntimeObject(e,u),e.WritePropertyEnd()}}catch(t){i.e(t)}finally{i.f()}e.WriteObjectEnd()}},{key:"RuntimeObjectsEqual",value:function(t,e){if(null===t)return O("obj1");if(null===e)return O("obj2");if(t.constructor!==e.constructor)return!1;var n=k(t,R);if(null!==n)return n.value===C(e,R).value;var i=k(t,j);if(null!==i)return i.value===C(e,j).value;var r=k(t,D);if(null!==r)return r.value===C(e,D).value;var a=k(t,L),s=k(e,L);if(null!==a&&null!==s)return w(a.valueObject)&&w(s.valueObject)?a.valueObject.Equals(s.valueObject):a.valueObject===s.valueObject;throw new Error("FastRoughDefinitelyEquals: Unsupported runtime object type: "+t.constructor.name)}},{key:"GetVariableWithName",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1,n=this.GetRawVariableWithName(t,e),i=k(n,M);return null!==i&&(n=this.ValueAtVariablePointer(i)),n}},{key:"TryGetDefaultVariableValue",value:function(t){var e=F(this._defaultGlobalVariables,t,null);return e.exists?e.result:null}},{key:"GlobalVariableExistsWithName",value:function(t){return this._globalVariables.has(t)||null!==this._defaultGlobalVariables&&this._defaultGlobalVariables.has(t)}},{key:"GetRawVariableWithName",value:function(t,e){if(0==e||-1==e){var n=null;if(null!==this.patch&&(n=this.patch.TryGetGlobal(t,null)).exists)return n.result;if((n=F(this._globalVariables,t,null)).exists)return n.result;if(null!==this._defaultGlobalVariables&&(n=F(this._defaultGlobalVariables,t,null)).exists)return n.result;if(null===this._listDefsOrigin)return O("VariablesState._listDefsOrigin");var i=this._listDefsOrigin.FindSingleItemListWithName(t);if(i)return i}return this._callStack.GetTemporaryVariableWithName(t,e)}},{key:"ValueAtVariablePointer",value:function(t){return this.GetVariableWithName(t.variableName,t.contextIndex)}},{key:"Assign",value:function(t,e){var n=t.variableName;if(null===n)return O("name");var i=-1,r=!1;if(r=t.isNewDeclaration?t.isGlobal:this.GlobalVariableExistsWithName(n),t.isNewDeclaration){var a=k(e,M);if(null!==a)e=this.ResolveVariablePointer(a)}else{var s=null;do{null!=(s=k(this.GetRawVariableWithName(n,i),M))&&(n=s.variableName,r=0==(i=s.contextIndex))}while(null!=s)}r?this.SetGlobal(n,e):this._callStack.SetTemporaryVariable(n,e,t.isNewDeclaration,i)}},{key:"SnapshotDefaultGlobals",value:function(){this._defaultGlobalVariables=new Map(this._globalVariables)}},{key:"RetainListOriginsForAssignment",value:function(t,e){var n=C(t,J),i=C(e,J);n.value&&i.value&&0==i.value.Count&&i.value.SetInitialOriginNames(n.value.originNames)}},{key:"SetGlobal",value:function(t,e){var n=null;if(null===this.patch&&(n=F(this._globalVariables,t,null)),null!==this.patch&&((n=this.patch.TryGetGlobal(t,null)).exists||(n=F(this._globalVariables,t,null))),J.RetainListOriginsForAssignment(n.result,e),null===t)return O("variableName");if(null!==this.patch?this.patch.SetGlobal(t,e):this._globalVariables.set(t,e),null!==this.variableChangedEvent&&null!==n&&e!==n.result)if(this.batchObservingVariableChanges){if(null===this._changedVariablesForBatchObs)return O("this._changedVariablesForBatchObs");null!==this.patch?this.patch.AddChangedVariable(t):null!==this._changedVariablesForBatchObs&&this._changedVariablesForBatchObs.add(t)}else this.variableChangedEvent(t,e)}},{key:"ResolveVariablePointer",value:function(t){var e=t.contextIndex;-1==e&&(e=this.GetContextIndexOfVariableNamed(t.variableName));var n=k(this.GetRawVariableWithName(t.variableName,e),M);return null!=n?n:new M(t.variableName,e)}},{key:"GetContextIndexOfVariableNamed",value:function(t){return this.GlobalVariableExistsWithName(t)?0:this._callStack.currentElementIndex}},{key:"ObserveVariableChange",value:function(t){this.variableChangedEventCallbacks.push(t)}}]),t}();ut.dontSaveDefaultValues=!0;var lt=function(){function t(e){n(this,t),this.seed=e%2147483647,this.seed<=0&&(this.seed+=2147483646)}return r(t,[{key:"next",value:function(){return this.seed=48271*this.seed%2147483647}},{key:"nextFloat",value:function(){return(this.next()-1)/2147483646}}]),t}(),ht=function(){function t(){if(n(this,t),this._changedVariables=new Set,this._visitCounts=new Map,this._turnIndices=new Map,1===arguments.length&&null!==arguments[0]){var e=arguments[0];this._globals=new Map(e._globals),this._changedVariables=new Set(e._changedVariables),this._visitCounts=new Map(e._visitCounts),this._turnIndices=new Map(e._turnIndices)}else this._globals=new Map,this._changedVariables=new Set,this._visitCounts=new Map,this._turnIndices=new Map}return r(t,[{key:"globals",get:function(){return this._globals}},{key:"changedVariables",get:function(){return this._changedVariables}},{key:"visitCounts",get:function(){return this._visitCounts}},{key:"turnIndices",get:function(){return this._turnIndices}},{key:"TryGetGlobal",value:function(t,e){return null!==t&&this._globals.has(t)?{result:this._globals.get(t),exists:!0}:{result:e,exists:!1}}},{key:"SetGlobal",value:function(t,e){this._globals.set(t,e)}},{key:"AddChangedVariable",value:function(t){return this._changedVariables.add(t)}},{key:"TryGetVisitCount",value:function(t,e){return this._visitCounts.has(t)?{result:this._visitCounts.get(t),exists:!0}:{result:e,exists:!1}}},{key:"SetVisitCount",value:function(t,e){this._visitCounts.set(t,e)}},{key:"SetTurnIndex",value:function(t,e){this._turnIndices.set(t,e)}},{key:"TryGetTurnIndex",value:function(t,e){return this._turnIndices.has(t)?{result:this._turnIndices.get(t),exists:!0}:{result:e,exists:!1}}}]),t}(),ct=function(){function t(){n(this,t)}return r(t,null,[{key:"TextToDictionary",value:function(e){return new t.Reader(e).ToDictionary()}},{key:"TextToArray",value:function(e){return new t.Reader(e).ToArray()}}]),t}();!function(t){var e=function(){function t(e){n(this,t),this._rootObject=JSON.parse(e)}return r(t,[{key:"ToDictionary",value:function(){return this._rootObject}},{key:"ToArray",value:function(){return this._rootObject}}]),t}();t.Reader=e;var i=function(){function e(){n(this,e),this._currentPropertyName=null,this._currentString=null,this._stateStack=[],this._collectionStack=[],this._propertyNameStack=[],this._jsonObject=null}return r(e,[{key:"WriteObject",value:function(t){this.WriteObjectStart(),t(this),this.WriteObjectEnd()}},{key:"WriteObjectStart",value:function(){this.StartNewObject(!0);var e={};if(this.state===t.Writer.State.Property){this.Assert(null!==this.currentCollection),this.Assert(null!==this.currentPropertyName);var n=this._propertyNameStack.pop();this.currentCollection[n]=e,this._collectionStack.push(e)}else this.state===t.Writer.State.Array?(this.Assert(null!==this.currentCollection),this.currentCollection.push(e),this._collectionStack.push(e)):(this.Assert(this.state===t.Writer.State.None),this._jsonObject=e,this._collectionStack.push(e));this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Object))}},{key:"WriteObjectEnd",value:function(){this.Assert(this.state===t.Writer.State.Object),this._collectionStack.pop(),this._stateStack.pop()}},{key:"WriteProperty",value:function(t,e){if(this.WritePropertyStart(t),arguments[1]instanceof Function){var n=arguments[1];n(this)}else{var i=arguments[1];this.Write(i)}this.WritePropertyEnd()}},{key:"WriteIntProperty",value:function(t,e){this.WritePropertyStart(t),this.WriteInt(e),this.WritePropertyEnd()}},{key:"WriteFloatProperty",value:function(t,e){this.WritePropertyStart(t),this.WriteFloat(e),this.WritePropertyEnd()}},{key:"WritePropertyStart",value:function(e){this.Assert(this.state===t.Writer.State.Object),this._propertyNameStack.push(e),this.IncrementChildCount(),this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Property))}},{key:"WritePropertyEnd",value:function(){this.Assert(this.state===t.Writer.State.Property),this.Assert(1===this.childCount),this._stateStack.pop()}},{key:"WritePropertyNameStart",value:function(){this.Assert(this.state===t.Writer.State.Object),this.IncrementChildCount(),this._currentPropertyName="",this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Property)),this._stateStack.push(new t.Writer.StateElement(t.Writer.State.PropertyName))}},{key:"WritePropertyNameEnd",value:function(){this.Assert(this.state===t.Writer.State.PropertyName),this.Assert(null!==this._currentPropertyName),this._propertyNameStack.push(this._currentPropertyName),this._currentPropertyName=null,this._stateStack.pop()}},{key:"WritePropertyNameInner",value:function(e){this.Assert(this.state===t.Writer.State.PropertyName),this.Assert(null!==this._currentPropertyName),this._currentPropertyName+=e}},{key:"WriteArrayStart",value:function(){this.StartNewObject(!0);var e=[];if(this.state===t.Writer.State.Property){this.Assert(null!==this.currentCollection),this.Assert(null!==this.currentPropertyName);var n=this._propertyNameStack.pop();this.currentCollection[n]=e,this._collectionStack.push(e)}else this.state===t.Writer.State.Array?(this.Assert(null!==this.currentCollection),this.currentCollection.push(e),this._collectionStack.push(e)):(this.Assert(this.state===t.Writer.State.None),this._jsonObject=e,this._collectionStack.push(e));this._stateStack.push(new t.Writer.StateElement(t.Writer.State.Array))}},{key:"WriteArrayEnd",value:function(){this.Assert(this.state===t.Writer.State.Array),this._collectionStack.pop(),this._stateStack.pop()}},{key:"Write",value:function(t){null!==t?(this.StartNewObject(!1),this._addToCurrentObject(t)):console.error("Warning: trying to write a null value")}},{key:"WriteBool",value:function(t){null!==t&&(this.StartNewObject(!1),this._addToCurrentObject(t))}},{key:"WriteInt",value:function(t){null!==t&&(this.StartNewObject(!1),this._addToCurrentObject(Math.floor(t)))}},{key:"WriteFloat",value:function(t){null!==t&&(this.StartNewObject(!1),t==Number.POSITIVE_INFINITY?this._addToCurrentObject(34e37):t==Number.NEGATIVE_INFINITY?this._addToCurrentObject(-34e37):isNaN(t)?this._addToCurrentObject(0):this._addToCurrentObject(t))}},{key:"WriteNull",value:function(){this.StartNewObject(!1),this._addToCurrentObject(null)}},{key:"WriteStringStart",value:function(){this.StartNewObject(!1),this._currentString="",this._stateStack.push(new t.Writer.StateElement(t.Writer.State.String))}},{key:"WriteStringEnd",value:function(){this.Assert(this.state==t.Writer.State.String),this._stateStack.pop(),this._addToCurrentObject(this._currentString),this._currentString=null}},{key:"WriteStringInner",value:function(e){this.Assert(this.state===t.Writer.State.String),null!==e?this._currentString+=e:console.error("Warning: trying to write a null string")}},{key:"toString",value:function(){return null===this._jsonObject?"":JSON.stringify(this._jsonObject)}},{key:"StartNewObject",value:function(e){e?this.Assert(this.state===t.Writer.State.None||this.state===t.Writer.State.Property||this.state===t.Writer.State.Array):this.Assert(this.state===t.Writer.State.Property||this.state===t.Writer.State.Array),this.state===t.Writer.State.Property&&this.Assert(0===this.childCount),this.state!==t.Writer.State.Array&&this.state!==t.Writer.State.Property||this.IncrementChildCount()}},{key:"state",get:function(){return this._stateStack.length>0?this._stateStack[this._stateStack.length-1].type:t.Writer.State.None}},{key:"childCount",get:function(){return this._stateStack.length>0?this._stateStack[this._stateStack.length-1].childCount:0}},{key:"currentCollection",get:function(){return this._collectionStack.length>0?this._collectionStack[this._collectionStack.length-1]:null}},{key:"currentPropertyName",get:function(){return this._propertyNameStack.length>0?this._propertyNameStack[this._propertyNameStack.length-1]:null}},{key:"IncrementChildCount",value:function(){this.Assert(this._stateStack.length>0);var t=this._stateStack.pop();t.childCount++,this._stateStack.push(t)}},{key:"Assert",value:function(t){if(!t)throw Error("Assert failed while writing JSON")}},{key:"_addToCurrentObject",value:function(e){this.Assert(null!==this.currentCollection),this.state===t.Writer.State.Array?(this.Assert(Array.isArray(this.currentCollection)),this.currentCollection.push(e)):this.state===t.Writer.State.Property&&(this.Assert(!Array.isArray(this.currentCollection)),this.Assert(null!==this.currentPropertyName),this.currentCollection[this.currentPropertyName]=e,this._propertyNameStack.pop())}}]),e}();t.Writer=i,function(e){var i;(i=e.State||(e.State={}))[i.None=0]="None",i[i.Object=1]="Object",i[i.Array=2]="Array",i[i.Property=3]="Property",i[i.PropertyName=4]="PropertyName",i[i.String=5]="String";var a=r((function e(i){n(this,e),this.type=t.Writer.State.None,this.childCount=0,this.type=i}));e.StateElement=a}(i=t.Writer||(t.Writer={}))}(ct||(ct={}));var ft,vt,dt,pt=function(){function t(){n(this,t);var e=arguments[0],i=arguments[1];if(this.name=e,this.callStack=new ot(i),arguments[2]){var r=arguments[2];this.callStack.SetJsonToken(r.callstack,i),this.outputStream=st.JArrayToRuntimeObjList(r.outputStream),this.currentChoices=st.JArrayToRuntimeObjList(r.currentChoices);var a=r.choiceThreads;void 0!==a&&this.LoadFlowChoiceThreads(a,i)}else this.outputStream=[],this.currentChoices=[]}return r(t,[{key:"WriteJson",value:function(t){var e=this;t.WriteObjectStart(),t.WriteProperty("callstack",(function(t){return e.callStack.WriteJson(t)})),t.WriteProperty("outputStream",(function(t){return st.WriteListRuntimeObjs(t,e.outputStream)}));var n,i=!1,r=m(this.currentChoices);try{for(r.s();!(n=r.n()).done;){var a=n.value;if(null===a.threadAtGeneration)return O("c.threadAtGeneration");a.originalThreadIndex=a.threadAtGeneration.threadIndex,null===this.callStack.ThreadWithIndex(a.originalThreadIndex)&&(i||(i=!0,t.WritePropertyStart("choiceThreads"),t.WriteObjectStart()),t.WritePropertyStart(a.originalThreadIndex),a.threadAtGeneration.WriteJson(t),t.WritePropertyEnd())}}catch(t){r.e(t)}finally{r.f()}i&&(t.WriteObjectEnd(),t.WritePropertyEnd()),t.WriteProperty("currentChoices",(function(t){t.WriteArrayStart();var n,i=m(e.currentChoices);try{for(i.s();!(n=i.n()).done;){var r=n.value;st.WriteChoice(t,r)}}catch(t){i.e(t)}finally{i.f()}t.WriteArrayEnd()})),t.WriteObjectEnd()}},{key:"LoadFlowChoiceThreads",value:function(t,e){var n,i=m(this.currentChoices);try{for(i.s();!(n=i.n()).done;){var r=n.value,a=this.callStack.ThreadWithIndex(r.originalThreadIndex);if(null!==a)r.threadAtGeneration=a.Copy();else{var s=t["".concat(r.originalThreadIndex)];r.threadAtGeneration=new ot.Thread(s,e)}}}catch(t){i.e(t)}finally{i.f()}}}]),t}(),yt=function(){function e(t){n(this,e),this.kInkSaveStateVersion=9,this.kMinCompatibleLoadVersion=8,this.onDidLoadState=null,this._currentErrors=null,this._currentWarnings=null,this.divertedPointer=X.Null,this._currentTurnIndex=0,this.storySeed=0,this.previousRandom=0,this.didSafeExit=!1,this._currentText=null,this._currentTags=null,this._outputStreamTextDirty=!0,this._outputStreamTagsDirty=!0,this._patch=null,this._namedFlows=null,this.kDefaultFlowName="DEFAULT_FLOW",this.story=t,this._currentFlow=new pt(this.kDefaultFlowName,t),this.OutputStreamDirty(),this._evaluationStack=[],this._variablesState=new ut(this.callStack,t.listDefinitions),this._visitCounts=new Map,this._turnIndices=new Map,this.currentTurnIndex=-1;var i=(new Date).getTime();this.storySeed=new lt(i).next()%100,this.previousRandom=0,this.GoToStart()}return r(e,[{key:"ToJson",value:function(){var t=new ct.Writer;return this.WriteJson(t),t.toString()}},{key:"toJson",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return this.ToJson(t)}},{key:"LoadJson",value:function(t){var e=ct.TextToDictionary(t);this.LoadJsonObj(e),null!==this.onDidLoadState&&this.onDidLoadState()}},{key:"VisitCountAtPathString",value:function(t){var e;if(null!==this._patch){var n=this.story.ContentAtPath(new S(t)).container;if(null===n)throw new Error("Content at path not found: "+t);if((e=this._patch.TryGetVisitCount(n,0)).exists)return e.result}return(e=F(this._visitCounts,t,null)).exists?e.result:0}},{key:"VisitCountForContainer",value:function(t){if(null===t)return O("container");if(!t.visitsShouldBeCounted)return this.story.Error("Read count for target ("+t.name+" - on "+t.debugMetadata+") unknown. The story may need to be compiled with countAllVisits flag (-c)."),0;if(null!==this._patch){var e=this._patch.TryGetVisitCount(t,0);if(e.exists)return e.result}var n=t.path.toString(),i=F(this._visitCounts,n,null);return i.exists?i.result:0}},{key:"IncrementVisitCountForContainer",value:function(t){if(null!==this._patch){var e=this.VisitCountForContainer(t);return e++,void this._patch.SetVisitCount(t,e)}var n=t.path.toString(),i=F(this._visitCounts,n,null);i.exists?this._visitCounts.set(n,i.result+1):this._visitCounts.set(n,1)}},{key:"RecordTurnIndexVisitToContainer",value:function(t){if(null===this._patch){var e=t.path.toString();this._turnIndices.set(e,this.currentTurnIndex)}else this._patch.SetTurnIndex(t,this.currentTurnIndex)}},{key:"TurnsSinceForContainer",value:function(t){if(t.turnIndexShouldBeCounted||this.story.Error("TURNS_SINCE() for target ("+t.name+" - on "+t.debugMetadata+") unknown. The story may need to be compiled with countAllVisits flag (-c)."),null!==this._patch){var e=this._patch.TryGetTurnIndex(t,0);if(e.exists)return this.currentTurnIndex-e.result}var n=t.path.toString(),i=F(this._turnIndices,n,0);return i.exists?this.currentTurnIndex-i.result:-1}},{key:"callstackDepth",get:function(){return this.callStack.depth}},{key:"outputStream",get:function(){return this._currentFlow.outputStream}},{key:"currentChoices",get:function(){return this.canContinue?[]:this._currentFlow.currentChoices}},{key:"generatedChoices",get:function(){return this._currentFlow.currentChoices}},{key:"currentErrors",get:function(){return this._currentErrors}},{key:"currentWarnings",get:function(){return this._currentWarnings}},{key:"variablesState",get:function(){return this._variablesState},set:function(t){this._variablesState=t}},{key:"callStack",get:function(){return this._currentFlow.callStack}},{key:"evaluationStack",get:function(){return this._evaluationStack}},{key:"currentTurnIndex",get:function(){return this._currentTurnIndex},set:function(t){this._currentTurnIndex=t}},{key:"currentPathString",get:function(){var t=this.currentPointer;return t.isNull?null:null===t.path?O("pointer.path"):t.path.toString()}},{key:"currentPointer",get:function(){return this.callStack.currentElement.currentPointer.copy()},set:function(t){this.callStack.currentElement.currentPointer=t.copy()}},{key:"previousPointer",get:function(){return this.callStack.currentThread.previousPointer.copy()},set:function(t){this.callStack.currentThread.previousPointer=t.copy()}},{key:"canContinue",get:function(){return!this.currentPointer.isNull&&!this.hasError}},{key:"hasError",get:function(){return null!=this.currentErrors&&this.currentErrors.length>0}},{key:"hasWarning",get:function(){return null!=this.currentWarnings&&this.currentWarnings.length>0}},{key:"currentText",get:function(){if(this._outputStreamTextDirty){var t,e=new N,n=m(this.outputStream);try{for(n.s();!(t=n.n()).done;){var i=k(t.value,B);null!==i&&e.Append(i.value)}}catch(t){n.e(t)}finally{n.f()}this._currentText=this.CleanOutputWhitespace(e.toString()),this._outputStreamTextDirty=!1}return this._currentText}},{key:"CleanOutputWhitespace",value:function(t){for(var e=new N,n=-1,i=0,r=0;r0&&n!=i&&e.Append(" "),n=-1),"\n"==a&&(i=r+1),s||e.Append(a)}return e.toString()}},{key:"currentTags",get:function(){if(this._outputStreamTagsDirty){this._currentTags=[];var t,e=m(this.outputStream);try{for(e.s();!(t=e.n()).done;){var n=k(t.value,nt);null!==n&&this._currentTags.push(n.text)}}catch(t){e.e(t)}finally{e.f()}this._outputStreamTagsDirty=!1}return this._currentTags}},{key:"currentFlowName",get:function(){return this._currentFlow.name}},{key:"inExpressionEvaluation",get:function(){return this.callStack.currentElement.inExpressionEvaluation},set:function(t){this.callStack.currentElement.inExpressionEvaluation=t}},{key:"GoToStart",value:function(){this.callStack.currentElement.currentPointer=X.StartOf(this.story.mainContentContainer)}},{key:"SwitchFlow_Internal",value:function(t){if(null===t)throw new Error("Must pass a non-null string to Story.SwitchFlow");if(null===this._namedFlows&&(this._namedFlows=new Map,this._namedFlows.set(this.kDefaultFlowName,this._currentFlow)),t!==this._currentFlow.name){var e,n=F(this._namedFlows,t,null);n.exists?e=n.result:(e=new pt(t,this.story),this._namedFlows.set(t,e)),this._currentFlow=e,this.variablesState.callStack=this._currentFlow.callStack,this.OutputStreamDirty()}}},{key:"SwitchToDefaultFlow_Internal",value:function(){null!==this._namedFlows&&this.SwitchFlow_Internal(this.kDefaultFlowName)}},{key:"RemoveFlow_Internal",value:function(t){if(null===t)throw new Error("Must pass a non-null string to Story.DestroyFlow");if(t===this.kDefaultFlowName)throw new Error("Cannot destroy default flow");if(this._currentFlow.name===t&&this.SwitchToDefaultFlow_Internal(),null===this._namedFlows)return O("this._namedFlows");this._namedFlows.delete(t)}},{key:"CopyAndStartPatching",value:function(){var t,n,i,r,a,s=new e(this.story);if(s._patch=new ht(this._patch),s._currentFlow.name=this._currentFlow.name,s._currentFlow.callStack=new ot(this._currentFlow.callStack),(t=s._currentFlow.currentChoices).push.apply(t,d(this._currentFlow.currentChoices)),(n=s._currentFlow.outputStream).push.apply(n,d(this._currentFlow.outputStream)),s.OutputStreamDirty(),null!==this._namedFlows){s._namedFlows=new Map;var o,u=m(this._namedFlows);try{for(u.s();!(o=u.n()).done;){var l=v(o.value,2),h=l[0],c=l[1];s._namedFlows.set(h,c)}}catch(t){u.e(t)}finally{u.f()}s._namedFlows.set(this._currentFlow.name,s._currentFlow)}this.hasError&&(s._currentErrors=[],(r=s._currentErrors).push.apply(r,d(this.currentErrors||[])));this.hasWarning&&(s._currentWarnings=[],(a=s._currentWarnings).push.apply(a,d(this.currentWarnings||[])));return s.variablesState=this.variablesState,s.variablesState.callStack=s.callStack,s.variablesState.patch=s._patch,(i=s.evaluationStack).push.apply(i,d(this.evaluationStack)),this.divertedPointer.isNull||(s.divertedPointer=this.divertedPointer.copy()),s.previousPointer=this.previousPointer.copy(),s._visitCounts=this._visitCounts,s._turnIndices=this._turnIndices,s.currentTurnIndex=this.currentTurnIndex,s.storySeed=this.storySeed,s.previousRandom=this.previousRandom,s.didSafeExit=this.didSafeExit,s}},{key:"RestoreAfterPatch",value:function(){this.variablesState.callStack=this.callStack,this.variablesState.patch=this._patch}},{key:"ApplyAnyPatch",value:function(){if(null!==this._patch){this.variablesState.ApplyPatch();var t,e=m(this._patch.visitCounts);try{for(e.s();!(t=e.n()).done;){var n=v(t.value,2),i=n[0],r=n[1];this.ApplyCountChanges(i,r,!0)}}catch(t){e.e(t)}finally{e.f()}var a,s=m(this._patch.turnIndices);try{for(s.s();!(a=s.n()).done;){var o=v(a.value,2),u=o[0],l=o[1];this.ApplyCountChanges(u,l,!1)}}catch(t){s.e(t)}finally{s.f()}this._patch=null}}},{key:"ApplyCountChanges",value:function(t,e,n){(n?this._visitCounts:this._turnIndices).set(t.path.toString(),e)}},{key:"WriteJson",value:function(e){var n=this;if(e.WriteObjectStart(),e.WritePropertyStart("flows"),e.WriteObjectStart(),null!==this._namedFlows){var i,r=m(this._namedFlows);try{var a=function(){var t=v(i.value,2),n=t[0],r=t[1];e.WriteProperty(n,(function(t){return r.WriteJson(t)}))};for(r.s();!(i=r.n()).done;)a()}catch(t){r.e(t)}finally{r.f()}}else e.WriteProperty(this._currentFlow.name,(function(t){return n._currentFlow.WriteJson(t)}));if(e.WriteObjectEnd(),e.WritePropertyEnd(),e.WriteProperty("currentFlowName",this._currentFlow.name),e.WriteProperty("variablesState",(function(t){return n.variablesState.WriteJson(t)})),e.WriteProperty("evalStack",(function(t){return st.WriteListRuntimeObjs(t,n.evaluationStack)})),!this.divertedPointer.isNull){if(null===this.divertedPointer.path)return O("divertedPointer");e.WriteProperty("currentDivertTarget",this.divertedPointer.path.componentsString)}e.WriteProperty("visitCounts",(function(t){return st.WriteIntDictionary(t,n._visitCounts)})),e.WriteProperty("turnIndices",(function(t){return st.WriteIntDictionary(t,n._turnIndices)})),e.WriteIntProperty("turnIdx",this.currentTurnIndex),e.WriteIntProperty("storySeed",this.storySeed),e.WriteIntProperty("previousRandom",this.previousRandom),e.WriteIntProperty("inkSaveVersion",this.kInkSaveStateVersion),e.WriteIntProperty("inkFormatVersion",t.Story.inkVersionCurrent),e.WriteObjectEnd()}},{key:"LoadJsonObj",value:function(t){var e=t,n=e.inkSaveVersion;if(null==n)throw new Error("ink save format incorrect, can't load.");if(parseInt(n)1){var c=e.currentFlowName;this._currentFlow=this._namedFlows.get(c)}}else{this._namedFlows=null,this._currentFlow.name=this.kDefaultFlowName,this._currentFlow.callStack.SetJsonToken(e.callstackThreads,this.story),this._currentFlow.outputStream=st.JArrayToRuntimeObjList(e.outputStream),this._currentFlow.currentChoices=st.JArrayToRuntimeObjList(e.currentChoices);var f=e.choiceThreads;this._currentFlow.LoadFlowChoiceThreads(f,this.story)}this.OutputStreamDirty(),this.variablesState.SetJsonToken(e.variablesState),this.variablesState.callStack=this._currentFlow.callStack,this._evaluationStack=st.JArrayToRuntimeObjList(e.evalStack);var d=e.currentDivertTarget;if(null!=d){var p=new S(d.toString());this.divertedPointer=this.story.PointerAtPath(p)}this._visitCounts=st.JObjectToIntDictionary(e.visitCounts),this._turnIndices=st.JObjectToIntDictionary(e.turnIndices),this.currentTurnIndex=parseInt(e.turnIdx),this.storySeed=parseInt(e.storySeed),this.previousRandom=parseInt(e.previousRandom)}},{key:"ResetErrors",value:function(){this._currentErrors=null,this._currentWarnings=null}},{key:"ResetOutput",value:function(){var t,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;this.outputStream.length=0,null!==e&&(t=this.outputStream).push.apply(t,d(e)),this.OutputStreamDirty()}},{key:"PushToOutputStream",value:function(t){var e=k(t,B);if(null!==e){var n=this.TrySplittingHeadTailWhitespace(e);if(null!==n){var i,r=m(n);try{for(r.s();!(i=r.n()).done;){var a=i.value;this.PushToOutputStreamIndividual(a)}}catch(t){r.e(t)}finally{r.f()}return void this.OutputStreamDirty()}}this.PushToOutputStreamIndividual(t),this.OutputStreamDirty()}},{key:"PopFromOutputStream",value:function(t){this.outputStream.splice(this.outputStream.length-t,t),this.OutputStreamDirty()}},{key:"TrySplittingHeadTailWhitespace",value:function(t){var e=t.value;if(null===e)return O("single.value");for(var n=-1,i=-1,r=0;r=0;u--){var l=e[u];if("\n"!=l){if(" "==l||"\t"==l)continue;break}-1==s&&(s=u),o=u}if(-1==n&&-1==s)return null;var h=[],c=0,f=e.length;if(-1!=n){if(n>0){var v=new B(e.substring(0,n));h.push(v)}h.push(new B("\n")),c=i+1}if(-1!=s&&(f=o),f>c){var d=e.substring(c,f-c);h.push(new B(d))}if(-1!=s&&o>i&&(h.push(new B("\n")),s=0;o--){var u=this.outputStream[o],l=u instanceof H?u:null;if(null!=(u instanceof z?u:null)){s=o;break}if(null!=l&&l.commandType==H.CommandType.BeginString){o>=r&&(r=-1);break}}if(-1!=(-1!=s&&-1!=r?Math.min(r,s):-1!=s?s:r)){if(n.isNewline)i=!1;else if(n.isNonWhitespace&&(s>-1&&this.RemoveExistingGlue(),r>-1))for(var h=this.callStack.elements,c=h.length-1;c>=0;c--){var f=h[c];if(f.type!=K.Function)break;f.functionStartInOutputStream=-1}}else n.isNewline&&(!this.outputStreamEndsInNewline&&this.outputStreamContainsContent||(i=!1))}if(i){if(null===t)return O("obj");this.outputStream.push(t),this.OutputStreamDirty()}}},{key:"TrimNewlinesFromOutputStream",value:function(){for(var t=-1,e=this.outputStream.length-1;e>=0;){var n=this.outputStream[e],i=k(n,H),r=k(n,B);if(null!=i||null!=r&&r.isNonWhitespace)break;null!=r&&r.isNewline&&(t=e),e--}if(t>=0)for(e=t;e=0;t--){var e=this.outputStream[t];if(e instanceof z)this.outputStream.splice(t,1);else if(e instanceof H)break}this.OutputStreamDirty()}},{key:"outputStreamEndsInNewline",get:function(){if(this.outputStream.length>0)for(var t=this.outputStream.length-1;t>=0;t--){if(this.outputStream[t]instanceof H)break;var e=this.outputStream[t];if(e instanceof B){if(e.isNewline)return!0;if(e.isNonWhitespace)break}}return!1}},{key:"outputStreamContainsContent",get:function(){var t,e=m(this.outputStream);try{for(e.s();!(t=e.n()).done;){if(t.value instanceof B)return!0}}catch(t){e.e(t)}finally{e.f()}return!1}},{key:"inStringEvaluation",get:function(){for(var t=this.outputStream.length-1;t>=0;t--){var e=k(this.outputStream[t],H);if(e instanceof H&&e.commandType==H.CommandType.BeginString)return!0}return!1}},{key:"PushEvaluationStack",value:function(t){var e=k(t,J);if(e){var n=e.value;if(null===n)return O("rawList");if(null!=n.originNames){n.origins||(n.origins=[]),n.origins.length=0;var i,r=m(n.originNames);try{for(r.s();!(i=r.n()).done;){var a=i.value;if(null===this.story.listDefinitions)return O("StoryState.story.listDefinitions");var s=this.story.listDefinitions.TryListGetDefinition(a,null);if(null===s.result)return O("StoryState def.result");n.origins.indexOf(s.result)<0&&n.origins.push(s.result)}}catch(t){r.e(t)}finally{r.f()}}}if(null===t)return O("obj");this.evaluationStack.push(t)}},{key:"PopEvaluationStack",value:function(t){if(void 0===t)return _(this.evaluationStack.pop());if(t>this.evaluationStack.length)throw new Error("trying to pop too many objects");return _(this.evaluationStack.splice(this.evaluationStack.length-t,t))}},{key:"PeekEvaluationStack",value:function(){return this.evaluationStack[this.evaluationStack.length-1]}},{key:"ForceEnd",value:function(){this.callStack.Reset(),this._currentFlow.currentChoices.length=0,this.currentPointer=X.Null,this.previousPointer=X.Null,this.didSafeExit=!0}},{key:"TrimWhitespaceFromFunctionEnd",value:function(){g.Assert(this.callStack.currentElement.type==K.Function);var t=this.callStack.currentElement.functionStartInOutputStream;-1==t&&(t=0);for(var e=this.outputStream.length-1;e>=t;e--){var n=this.outputStream[e],i=k(n,B),r=k(n,H);if(null!=i){if(r)break;if(!i.isNewline&&!i.isInlineWhitespace)break;this.outputStream.splice(e,1),this.OutputStreamDirty()}}}},{key:"PopCallStack",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;this.callStack.currentElement.type==K.Function&&this.TrimWhitespaceFromFunctionEnd(),this.callStack.Pop(t)}},{key:"SetChosenPath",value:function(t,e){this._currentFlow.currentChoices.length=0;var n=this.story.PointerAtPath(t);n.isNull||-1!=n.index||(n.index=0),this.currentPointer=n,e&&this.currentTurnIndex++}},{key:"StartFunctionEvaluationFromGame",value:function(t,e){this.callStack.Push(K.FunctionEvaluationFromGame,this.evaluationStack.length),this.callStack.currentElement.currentPointer=X.StartOf(t),this.PassArgumentsToEvaluationStack(e)}},{key:"PassArgumentsToEvaluationStack",value:function(t){if(null!==t)for(var e=0;et;){var n=this.PopEvaluationStack();null===e&&(e=n)}if(this.PopCallStack(K.FunctionEvaluationFromGame),e){if(e instanceof tt)return null;var i=C(e,L);return i.valueType==W.DivertTarget?i.valueObject.toString():i.valueObject}return null}},{key:"AddError",value:function(t,e){e?(null==this._currentWarnings&&(this._currentWarnings=[]),this._currentWarnings.push(t)):(null==this._currentErrors&&(this._currentErrors=[]),this._currentErrors.push(t))}},{key:"OutputStreamDirty",value:function(){this._outputStreamTextDirty=!0,this._outputStreamTagsDirty=!0}}]),e}(),mt=function(){function t(){n(this,t),this.startTime=void 0}return r(t,[{key:"ElapsedMilliseconds",get:function(){return void 0===this.startTime?0:(new Date).getTime()-this.startTime}},{key:"Start",value:function(){this.startTime=(new Date).getTime()}},{key:"Stop",value:function(){this.startTime=void 0}}]),t}();!function(t){t[t.Author=0]="Author",t[t.Warning=1]="Warning",t[t.Error=2]="Error"}(ft||(ft={})),Number.isInteger||(Number.isInteger=function(t){return"number"==typeof t&&isFinite(t)&&t>-9007199254740992&&t<9007199254740992&&Math.floor(t)===t}),t.Story=function(t){a(s,t);var i=f(s);function s(){var t,e;n(this,s),(t=i.call(this)).inkVersionMinimumCompatible=18,t.onError=null,t.onDidContinue=null,t.onMakeChoice=null,t.onEvaluateFunction=null,t.onCompleteEvaluateFunction=null,t.onChoosePathString=null,t._prevContainers=[],t.allowExternalFunctionFallbacks=!1,t._listDefinitions=null,t._variableObservers=null,t._hasValidatedExternals=!1,t._temporaryEvaluationContainer=null,t._asyncContinueActive=!1,t._stateSnapshotAtLastNewline=null,t._sawLookaheadUnsafeFunctionAfterNewline=!1,t._recursiveContinueCount=0,t._asyncSaving=!1,t._profiler=null;var r=null,a=null;if(arguments[0]instanceof U)e=arguments[0],void 0!==arguments[1]&&(r=arguments[1]),t._mainContentContainer=e;else if("string"==typeof arguments[0]){var o=arguments[0];a=ct.TextToDictionary(o)}else a=arguments[0];if(null!=r&&(t._listDefinitions=new at(r)),t._externals=new Map,null!==a){var u=a,l=u.inkVersion;if(null==l)throw new Error("ink version number not found. Are you sure it's a valid .ink.json file?");var h=parseInt(l);if(h>s.inkVersionCurrent)throw new Error("Version of ink used to build story was newer than the current version of the engine");if(h0&&void 0!==arguments[0]?arguments[0]:0;null!=this._profiler&&this._profiler.PreContinue();var e=t>0;if(this._recursiveContinueCount++,!this._asyncContinueActive){if(this._asyncContinueActive=e,!this.canContinue)throw new Error("Can't continue - should check canContinue before calling Continue");this._state.didSafeExit=!1,this._state.ResetOutput(),1==this._recursiveContinueCount&&(this._state.variablesState.batchObservingVariableChanges=!0)}var n=new mt;n.Start();var i=!1;this._sawLookaheadUnsafeFunctionAfterNewline=!1;do{try{i=this.ContinueSingleStep()}catch(t){if(!(t instanceof x))throw t;this.AddError(t.message,void 0,t.useEndLineNumber);break}if(i)break;if(this._asyncContinueActive&&n.ElapsedMilliseconds>t)break}while(this.canContinue);if(n.Stop(),!i&&this.canContinue||(null!==this._stateSnapshotAtLastNewline&&this.RestoreStateSnapshot(),this.canContinue||(this.state.callStack.canPopThread&&this.AddError("Thread available to pop, threads should always be flat by the end of evaluation?"),0!=this.state.generatedChoices.length||this.state.didSafeExit||null!=this._temporaryEvaluationContainer||(this.state.callStack.CanPop(K.Tunnel)?this.AddError("unexpectedly reached end of content. Do you need a '->->' to return from a tunnel?"):this.state.callStack.CanPop(K.Function)?this.AddError("unexpectedly reached end of content. Do you need a '~ return'?"):this.state.callStack.canPop?this.AddError("unexpectedly reached end of content for unknown reason. Please debug compiler!"):this.AddError("ran out of content. Do you need a '-> DONE' or '-> END'?"))),this.state.didSafeExit=!1,this._sawLookaheadUnsafeFunctionAfterNewline=!1,1==this._recursiveContinueCount&&(this._state.variablesState.batchObservingVariableChanges=!1),this._asyncContinueActive=!1,null!==this.onDidContinue&&this.onDidContinue()),this._recursiveContinueCount--,null!=this._profiler&&this._profiler.PostContinue(),this.state.hasError||this.state.hasWarning){if(null===this.onError){var r=new N;throw r.Append("Ink had "),this.state.hasError&&(r.Append("".concat(this.state.currentErrors.length)),r.Append(1==this.state.currentErrors.length?" error":"errors"),this.state.hasWarning&&r.Append(" and ")),this.state.hasWarning&&(r.Append("".concat(this.state.currentWarnings.length)),r.Append(1==this.state.currentWarnings.length?" warning":"warnings"),this.state.hasWarning&&r.Append(" and ")),r.Append(". It is strongly suggested that you assign an error handler to story.onError. The first issue was: "),r.Append(this.state.hasError?this.state.currentErrors[0]:this.state.currentWarnings[0]),new x(r.toString())}if(this.state.hasError){var a,s=m(this.state.currentErrors);try{for(s.s();!(a=s.n()).done;){var o=a.value;this.onError(o,ft.Error)}}catch(o){s.e(o)}finally{s.f()}}if(this.state.hasWarning){var u,l=m(this.state.currentWarnings);try{for(l.s();!(u=l.n()).done;){var h=u.value;this.onError(h,ft.Warning)}}catch(o){l.e(o)}finally{l.f()}}this.ResetErrors()}}},{key:"ContinueSingleStep",value:function(){if(null!=this._profiler&&this._profiler.PreStep(),this.Step(),null!=this._profiler&&this._profiler.PostStep(),this.canContinue||this.state.callStack.elementIsEvaluateFromGame||this.TryFollowDefaultInvisibleChoice(),null!=this._profiler&&this._profiler.PreSnapshot(),!this.state.inStringEvaluation){if(null!==this._stateSnapshotAtLastNewline){if(null===this._stateSnapshotAtLastNewline.currentTags)return O("this._stateAtLastNewline.currentTags");if(null===this.state.currentTags)return O("this.state.currentTags");var t=this.CalculateNewlineOutputStateChange(this._stateSnapshotAtLastNewline.currentText,this.state.currentText,this._stateSnapshotAtLastNewline.currentTags.length,this.state.currentTags.length);if(t==s.OutputStateChange.ExtendedBeyondNewline||this._sawLookaheadUnsafeFunctionAfterNewline)return this.RestoreStateSnapshot(),!0;t==s.OutputStateChange.NewlineRemoved&&this.DiscardSnapshot()}this.state.outputStreamEndsInNewline&&(this.canContinue?null==this._stateSnapshotAtLastNewline&&this.StateSnapshot():this.DiscardSnapshot())}return null!=this._profiler&&this._profiler.PostSnapshot(),!1}},{key:"CalculateNewlineOutputStateChange",value:function(t,e,n,i){if(null===t)return O("prevText");if(null===e)return O("currText");var r=e.length>=t.length&&"\n"==e.charAt(t.length-1);if(n==i&&t.length==e.length&&r)return s.OutputStateChange.NoChange;if(!r)return s.OutputStateChange.NewlineRemoved;if(i>n)return s.OutputStateChange.ExtendedBeyondNewline;for(var a=t.length;a0?this.Error("Failed to find content at path '"+t+"', and no approximation of it was possible."):i.approximate&&this.Warning("Failed to find content at path '"+t+"', so it was approximated to: '"+i.obj.path+"'."),e)}},{key:"StateSnapshot",value:function(){this._stateSnapshotAtLastNewline=this._state,this._state=this._state.CopyAndStartPatching()}},{key:"RestoreStateSnapshot",value:function(){null===this._stateSnapshotAtLastNewline&&O("_stateSnapshotAtLastNewline"),this._stateSnapshotAtLastNewline.RestoreAfterPatch(),this._state=this._stateSnapshotAtLastNewline,this._stateSnapshotAtLastNewline=null,this._asyncSaving||this._state.ApplyAnyPatch()}},{key:"DiscardSnapshot",value:function(){this._asyncSaving||this._state.ApplyAnyPatch(),this._stateSnapshotAtLastNewline=null}},{key:"CopyStateForBackgroundThreadSave",value:function(){if(this.IfAsyncWeCant("start saving on a background thread"),this._asyncSaving)throw new Error("Story is already in background saving mode, can't call CopyStateForBackgroundThreadSave again!");var t=this._state;return this._state=this._state.CopyAndStartPatching(),this._asyncSaving=!0,t}},{key:"BackgroundSaveComplete",value:function(){null===this._stateSnapshotAtLastNewline&&this._state.ApplyAnyPatch(),this._asyncSaving=!1}},{key:"Step",value:function(){var t=!0,e=this.state.currentPointer.copy();if(!e.isNull){for(var n=k(e.Resolve(),U);n&&(this.VisitContainer(n,!0),0!=n.content.length);)n=k((e=X.StartOf(n)).Resolve(),U);this.state.currentPointer=e.copy(),null!=this._profiler&&this._profiler.Step(this.state.callStack);var i=e.Resolve(),r=this.PerformLogicAndFlowControl(i);if(!this.state.currentPointer.isNull){r&&(t=!1);var a=k(i,Y);if(a){var s=this.ProcessChoice(a);s&&this.state.generatedChoices.push(s),i=null,t=!1}if(i instanceof U&&(t=!1),t){var o=k(i,M);if(o&&-1==o.contextIndex){var u=this.state.callStack.ContextForVariableNamed(o.variableName);i=new M(o.variableName,u)}this.state.inExpressionEvaluation?this.state.PushEvaluationStack(i):this.state.PushToOutputStream(i)}this.NextContent();var l=k(i,H);l&&l.commandType==H.CommandType.StartThread&&this.state.callStack.PushThread()}}}},{key:"VisitContainer",value:function(t,e){t.countingAtStartOnly&&!e||(t.visitsShouldBeCounted&&this.state.IncrementVisitCountForContainer(t),t.turnIndexShouldBeCounted&&this.state.RecordTurnIndexVisitToContainer(t))}},{key:"VisitChangedContainersDueToDivert",value:function(){var t=this.state.previousPointer.copy(),e=this.state.currentPointer.copy();if(!e.isNull&&-1!=e.index){if(this._prevContainers.length=0,!t.isNull)for(var n=k(t.Resolve(),U)||k(t.container,U);n;)this._prevContainers.push(n),n=k(n.parent,U);var i=e.Resolve();if(null!=i)for(var r=k(i.parent,U),a=!0;r&&(this._prevContainers.indexOf(r)<0||r.countingAtStartOnly);){var s=r.content.length>0&&i==r.content[0]&&a;s||(a=!1),this.VisitContainer(r,s),i=r,r=k(r.parent,U)}}}},{key:"ProcessChoice",value:function(t){var e=!0;if(t.hasCondition){var n=this.state.PopEvaluationStack();this.IsTruthy(n)||(e=!1)}var i="",r="";t.hasChoiceOnlyContent&&(r=C(this.state.PopEvaluationStack(),B).value||"");t.hasStartContent&&(i=C(this.state.PopEvaluationStack(),B).value||"");t.onceOnly&&(this.state.VisitCountForContainer(t.choiceTarget)>0&&(e=!1));if(!e)return null;var a=new it;return a.targetPath=t.pathOnChoice,a.sourcePath=t.path.toString(),a.isInvisibleDefault=t.isInvisibleDefault,a.threadAtGeneration=this.state.callStack.ForkThread(),a.text=(i+r).replace(/^[ \t]+|[ \t]+$/g,""),a}},{key:"IsTruthy",value:function(t){if(t instanceof L){var e=t;if(e instanceof G){var n=e;return this.Error("Shouldn't use a divert target (to "+n.targetPath+") as a conditional value. Did you intend a function call 'likeThis()' or a read count check 'likeThis'? (no arrows)"),!1}return e.isTruthy}return!1}},{key:"PerformLogicAndFlowControl",value:function(t){if(null==t)return!1;if(t instanceof $){var e=t;if(e.isConditional){var n=this.state.PopEvaluationStack();if(!this.IsTruthy(n))return!0}if(e.hasVariableTarget){var i=e.variableDivertName,r=this.state.variablesState.GetVariableWithName(i);if(null==r)this.Error("Tried to divert using a target from a variable that could not be found ("+i+")");else if(!(r instanceof G)){var a=k(r,j),s="Tried to divert to a target from a variable, but the variable ("+i+") didn't contain a divert target, it ";a instanceof j&&0==a.value?s+="was empty/null (the value 0).":s+="contained '"+r+"'.",this.Error(s)}var o=C(r,G);this.state.divertedPointer=this.PointerAtPath(o.targetPath)}else{if(e.isExternal)return this.CallExternalFunction(e.targetPathString,e.externalArgs),!0;this.state.divertedPointer=e.targetPointer.copy()}return e.pushesToStack&&this.state.callStack.Push(e.stackPushType,void 0,this.state.outputStream.length),this.state.divertedPointer.isNull&&!e.isExternal&&(e&&e.debugMetadata&&null!=e.debugMetadata.sourceName?this.Error("Divert target doesn't exist: "+e.debugMetadata.sourceName):this.Error("Divert resolution failed: "+e)),!0}if(t instanceof H){var u=t;switch(u.commandType){case H.CommandType.EvalStart:this.Assert(!1===this.state.inExpressionEvaluation,"Already in expression evaluation?"),this.state.inExpressionEvaluation=!0;break;case H.CommandType.EvalEnd:this.Assert(!0===this.state.inExpressionEvaluation,"Not in expression evaluation mode"),this.state.inExpressionEvaluation=!1;break;case H.CommandType.EvalOutput:if(this.state.evaluationStack.length>0){var l=this.state.PopEvaluationStack();if(!(l instanceof tt)){var h=new B(l.toString());this.state.PushToOutputStream(h)}}break;case H.CommandType.NoOp:break;case H.CommandType.Duplicate:this.state.PushEvaluationStack(this.state.PeekEvaluationStack());break;case H.CommandType.PopEvaluatedValue:this.state.PopEvaluationStack();break;case H.CommandType.PopFunction:case H.CommandType.PopTunnel:var c=u.commandType==H.CommandType.PopFunction?K.Function:K.Tunnel,f=null;if(c==K.Tunnel){var v=this.state.PopEvaluationStack();null===(f=k(v,G))&&this.Assert(v instanceof tt,"Expected void if ->-> doesn't override target")}if(this.state.TryExitFunctionEvaluationFromGame())break;if(this.state.callStack.currentElement.type==c&&this.state.callStack.canPop)this.state.PopCallStack(),f&&(this.state.divertedPointer=this.PointerAtPath(f.targetPath));else{var d=new Map;d.set(K.Function,"function return statement (~ return)"),d.set(K.Tunnel,"tunnel onwards statement (->->)");var p=d.get(this.state.callStack.currentElement.type);this.state.callStack.canPop||(p="end of flow (-> END or choice)");var y="Found "+d.get(c)+", when expected "+p;this.Error(y)}break;case H.CommandType.BeginString:this.state.PushToOutputStream(u),this.Assert(!0===this.state.inExpressionEvaluation,"Expected to be in an expression when evaluating a string"),this.state.inExpressionEvaluation=!1;break;case H.CommandType.EndString:for(var g=[],S=0,b=this.state.outputStream.length-1;b>=0;--b){var _=this.state.outputStream[b];S++;var w=k(_,H);if(w&&w.commandType==H.CommandType.BeginString)break;_ instanceof B&&g.push(_)}this.state.PopFromOutputStream(S),g=g.reverse();var T,E=new N,P=m(g);try{for(P.s();!(T=P.n()).done;){var F=T.value;E.Append(F.toString())}}catch(t){P.e(t)}finally{P.f()}this.state.inExpressionEvaluation=!0,this.state.PushEvaluationStack(new B(E.toString()));break;case H.CommandType.ChoiceCount:var W=this.state.generatedChoices.length;this.state.PushEvaluationStack(new j(W));break;case H.CommandType.Turns:this.state.PushEvaluationStack(new j(this.state.currentTurnIndex+1));break;case H.CommandType.TurnsSince:case H.CommandType.ReadCount:var V=this.state.PopEvaluationStack();if(!(V instanceof G)){var R="";V instanceof j&&(R=". Did you accidentally pass a read count ('knot_name') instead of a target ('-> knot_name')?"),this.Error("TURNS_SINCE / READ_COUNT expected a divert target (knot, stitch, label name), but saw "+V+R);break}var D,M=C(V,G),q=k(this.ContentAtPath(M.targetPath).correctObj,U);null!=q?D=u.commandType==H.CommandType.TurnsSince?this.state.TurnsSinceForContainer(q):this.state.VisitCountForContainer(q):(D=u.commandType==H.CommandType.TurnsSince?-1:0,this.Warning("Failed to find container for "+u.toString()+" lookup at "+M.targetPath.toString())),this.state.PushEvaluationStack(new j(D));break;case H.CommandType.Random:var z=k(this.state.PopEvaluationStack(),j),Y=k(this.state.PopEvaluationStack(),j);if(null==Y||Y instanceof j==!1)return this.Error("Invalid value for minimum parameter of RANDOM(min, max)");if(null==z||Y instanceof j==!1)return this.Error("Invalid value for maximum parameter of RANDOM(min, max)");if(null===z.value)return O("maxInt.value");if(null===Y.value)return O("minInt.value");var nt=z.value-Y.value+1;(!isFinite(nt)||nt>Number.MAX_SAFE_INTEGER)&&(nt=Number.MAX_SAFE_INTEGER,this.Error("RANDOM was called with a range that exceeds the size that ink numbers can use.")),nt<=0&&this.Error("RANDOM was called with minimum as "+Y.value+" and maximum as "+z.value+". The maximum must be larger");var it=this.state.storySeed+this.state.previousRandom,rt=new lt(it).next(),at=rt%nt+Y.value;this.state.PushEvaluationStack(new j(at)),this.state.previousRandom=rt;break;case H.CommandType.SeedRandom:var st=k(this.state.PopEvaluationStack(),j);if(null==st||st instanceof j==!1)return this.Error("Invalid value passed to SEED_RANDOM");if(null===st.value)return O("minInt.value");this.state.storySeed=st.value,this.state.previousRandom=0,this.state.PushEvaluationStack(new tt);break;case H.CommandType.VisitIndex:var ot=this.state.VisitCountForContainer(this.state.currentPointer.container)-1;this.state.PushEvaluationStack(new j(ot));break;case H.CommandType.SequenceShuffleIndex:var ut=this.NextSequenceShuffleIndex();this.state.PushEvaluationStack(new j(ut));break;case H.CommandType.StartThread:break;case H.CommandType.Done:this.state.callStack.canPopThread?this.state.callStack.PopThread():(this.state.didSafeExit=!0,this.state.currentPointer=X.Null);break;case H.CommandType.End:this.state.ForceEnd();break;case H.CommandType.ListFromInt:var ht=k(this.state.PopEvaluationStack(),j),ct=C(this.state.PopEvaluationStack(),B);if(null===ht)throw new x("Passed non-integer when creating a list element from a numerical value.");var ft=null;if(null===this.listDefinitions)return O("this.listDefinitions");var vt=this.listDefinitions.TryListGetDefinition(ct.value,null);if(!vt.exists)throw new x("Failed to find LIST called "+ct.value);if(null===ht.value)return O("minInt.value");var dt=vt.result.TryGetItemWithValue(ht.value,A.Null);dt.exists&&(ft=new J(dt.result,ht.value)),null==ft&&(ft=new J),this.state.PushEvaluationStack(ft);break;case H.CommandType.ListRange:var pt=k(this.state.PopEvaluationStack(),L),yt=k(this.state.PopEvaluationStack(),L),mt=k(this.state.PopEvaluationStack(),J);if(null===mt||null===yt||null===pt)throw new x("Expected list, minimum and maximum for LIST_RANGE");if(null===mt.value)return O("targetList.value");var gt=mt.value.ListWithSubRange(yt.valueObject,pt.valueObject);this.state.PushEvaluationStack(new J(gt));break;case H.CommandType.ListRandom:var St=this.state.PopEvaluationStack();if(null===St)throw new x("Expected list for LIST_RANDOM");var kt=St.value,Ct=null;if(null===kt)throw O("list");if(0==kt.Count)Ct=new I;else{for(var bt=this.state.storySeed+this.state.previousRandom,_t=new lt(bt).next(),wt=_t%kt.Count,Tt=kt.entries(),Et=0;Et<=wt-1;Et++)Tt.next();var Ot=Tt.next().value,Pt={Key:A.fromSerializedKey(Ot[0]),Value:Ot[1]};if(null===Pt.Key.originName)return O("randomItem.Key.originName");(Ct=new I(Pt.Key.originName,this)).Add(Pt.Key,Pt.Value),this.state.previousRandom=_t}this.state.PushEvaluationStack(new J(Ct));break;default:this.Error("unhandled ControlCommand: "+u)}return!0}if(t instanceof Z){var Nt=t,At=this.state.PopEvaluationStack();return this.state.variablesState.Assign(Nt,At),!0}if(t instanceof Q){var It=t,xt=null;if(null!=It.pathForCount){var Ft=It.containerForCount,Wt=this.state.VisitCountForContainer(Ft);xt=new j(Wt)}else null==(xt=this.state.variablesState.GetVariableWithName(It.name))&&(this.Warning("Variable not found: '"+It.name+"'. Using default value of 0 (false). This can happen with temporary variables if the declaration hasn't yet been hit. Globals are always given a default value on load if a value doesn't exist in the save state."),xt=new j(0));return this.state.PushEvaluationStack(xt),!0}if(t instanceof et){var Vt=t,Lt=this.state.PopEvaluationStack(Vt.numberOfParameters),Rt=Vt.Call(Lt);return this.state.PushEvaluationStack(Rt),!0}return!1}},{key:"ChoosePathString",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];if(this.IfAsyncWeCant("call ChoosePathString right now"),null!==this.onChoosePathString&&this.onChoosePathString(t,n),e)this.ResetCallstack();else if(this.state.callStack.currentElement.type==K.Function){var i="",r=this.state.callStack.currentElement.currentPointer.container;throw null!=r&&(i="("+r.path.toString()+") "),new Error("Story was running a function "+i+"when you called ChoosePathString("+t+") - this is almost certainly not not what you want! Full stack trace: \n"+this.state.callStack.callStackTrace)}this.state.PassArgumentsToEvaluationStack(n),this.ChoosePath(new S(t))}},{key:"IfAsyncWeCant",value:function(t){if(this._asyncContinueActive)throw new Error("Can't "+t+". Story is in the middle of a ContinueAsync(). Make more ContinueAsync() calls or a single Continue() call beforehand.")}},{key:"ChoosePath",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.state.SetChosenPath(t,e),this.VisitChangedContainersDueToDivert()}},{key:"ChooseChoiceIndex",value:function(t){t=t;var e=this.currentChoices;this.Assert(t>=0&&t1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(null!==this.onEvaluateFunction&&this.onEvaluateFunction(t,e),this.IfAsyncWeCant("evaluate a function"),null==t)throw new Error("Function is null");if(""==t||""==t.trim())throw new Error("Function is empty or white space.");var i=this.KnotContainerWithName(t);if(null==i)throw new Error("Function doesn't exist: '"+t+"'");var r=[];r.push.apply(r,d(this.state.outputStream)),this._state.ResetOutput(),this.state.StartFunctionEvaluationFromGame(i,e);for(var a=new N;this.canContinue;)a.Append(this.Continue());var s=a.toString();this._state.ResetOutput(r);var o=this.state.CompleteFunctionEvaluationFromGame();return null!=this.onCompleteEvaluateFunction&&this.onCompleteEvaluateFunction(t,e,s,o),n?{returned:o,output:s}:o}},{key:"EvaluateExpression",value:function(t){var e=this.state.callStack.elements.length;this.state.callStack.Push(K.Tunnel),this._temporaryEvaluationContainer=t,this.state.GoToStart();var n=this.state.evaluationStack.length;return this.Continue(),this._temporaryEvaluationContainer=null,this.state.callStack.elements.length>e&&this.state.PopCallStack(),this.state.evaluationStack.length>n?this.state.PopEvaluationStack():null}},{key:"CallExternalFunction",value:function(t,n){if(null===t)return O("funcName");var i=this._externals.get(t),r=null,a=void 0!==i;if(!a||i.lookAheadSafe||null===this._stateSnapshotAtLastNewline){if(!a){if(this.allowExternalFunctionFallbacks)return r=this.KnotContainerWithName(t),this.Assert(null!==r,"Trying to call EXTERNAL function '"+t+"' which has not been bound, and fallback ink function could not be found."),this.state.callStack.Push(K.Function,void 0,this.state.outputStream.length),void(this.state.divertedPointer=X.StartOf(r));this.Assert(!1,"Trying to call EXTERNAL function '"+t+"' which has not been bound (and ink fallbacks disabled).")}for(var s=[],o=0;o=e.length,"External function expected "+e.length+" arguments");for(var n=[],r=0,a=t.length;r1?"s":"",i+=": '",i+=Array.from(n).join("', '"),i+="' ",i+=this.allowExternalFunctionFallbacks?", and no fallback ink function found.":" (ink fallbacks disabled)",this.Error(i)}else if(null!=t){var r,a=m(t.content);try{for(a.s();!(r=a.n()).done;){var s=r.value,o=s;null!=o&&o.hasValidName||this.ValidateExternalBindings(s,n)}}catch(t){a.e(t)}finally{a.f()}var u,l=m(t.namedContent);try{for(l.s();!(u=l.n()).done;){var h=v(u.value,2),c=h[1];this.ValidateExternalBindings(k(c,P),n)}}catch(t){l.e(t)}finally{l.f()}}else if(null!=e){var f=k(e,$);if(f&&f.isExternal){var d=f.targetPathString;if(null===d)return O("name");if(!this._externals.has(d))if(this.allowExternalFunctionFallbacks){var p=this.mainContentContainer.namedContent.has(d);p||n.add(d)}else n.add(d)}}}},{key:"ObserveVariable",value:function(t,e){if(this.IfAsyncWeCant("observe a new variable"),null===this._variableObservers&&(this._variableObservers=new Map),!this.state.variablesState.GlobalVariableExistsWithName(t))throw new Error("Cannot observe variable '"+t+"' because it wasn't declared in the ink story.");this._variableObservers.has(t)?this._variableObservers.get(t).push(e):this._variableObservers.set(t,[e])}},{key:"ObserveVariables",value:function(t,e){for(var n=0,i=t.length;n=e.container.content.length;){t=!1;var n=k(e.container.parent,U);if(n instanceof U==!1)break;var i=n.content.indexOf(e.container);if(-1==i)break;if((e=new X(n,i)).index++,t=!0,null===e.container)return O("pointer.container")}return t||(e=X.Null),this.state.callStack.currentElement.currentPointer=e.copy(),t}},{key:"TryFollowDefaultInvisibleChoice",value:function(){var t=this._state.currentChoices,e=t.filter((function(t){return t.isInvisibleDefault}));if(0==e.length||t.length>e.length)return!1;var n=e[0];return null===n.targetPath?O("choice.targetPath"):null===n.threadAtGeneration?O("choice.threadAtGeneration"):(this.state.callStack.currentThread=n.threadAtGeneration,null!==this._stateSnapshotAtLastNewline&&(this.state.callStack.currentThread=this.state.callStack.ForkThread()),this.ChoosePath(n.targetPath,!1),!0)}},{key:"NextSequenceShuffleIndex",value:function(){var t=k(this.state.PopEvaluationStack(),j);if(!(t instanceof j))return this.Error("expected number of elements in sequence for shuffle index"),0;var e=this.state.currentPointer.container;if(null===e)return O("seqContainer");if(null===t.value)return O("numElementsIntVal.value");var n=t.value,i=C(this.state.PopEvaluationStack(),j).value;if(null===i)return O("seqCount");for(var r=i/n,a=i%n,s=e.path.toString(),o=0,u=0,l=s.length;u1&&void 0!==arguments[1]&&arguments[1],n=new x(t);throw n.useEndLineNumber=e,n}},{key:"Warning",value:function(t){this.AddError(t,!0)}},{key:"AddError",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=this.currentDebugMetadata,r=e?"WARNING":"ERROR";if(null!=i){var a=n?i.endLineNumber:i.startLineNumber;t="RUNTIME "+r+": '"+i.fileName+"' line "+a+": "+t}else t=this.state.currentPointer.isNull?"RUNTIME "+r+": "+t:"RUNTIME "+r+": ("+this.state.currentPointer+"): "+t;this.state.AddError(t,e),e||this.state.ForceEnd()}},{key:"Assert",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(0==t)throw null==e&&(e="Story assert"),new Error(e+" "+this.currentDebugMetadata)}},{key:"currentDebugMetadata",get:function(){var t,e=this.state.currentPointer;if(!e.isNull&&null!==e.Resolve()&&null!==(t=e.Resolve().debugMetadata))return t;for(var n=this.state.callStack.elements.length-1;n>=0;--n)if(!(e=this.state.callStack.elements[n].currentPointer).isNull&&null!==e.Resolve()&&null!==(t=e.Resolve().debugMetadata))return t;for(var i=this.state.outputStream.length-1;i>=0;--i){if(null!==(t=this.state.outputStream[i].debugMetadata))return t}return null}},{key:"mainContentContainer",get:function(){return this._temporaryEvaluationContainer?this._temporaryEvaluationContainer:this._mainContentContainer}}]),s}(P),t.Story.inkVersionCurrent=20,vt=t.Story||(t.Story={}),(dt=vt.OutputStateChange||(vt.OutputStateChange={}))[dt.NoChange=0]="NoChange",dt[dt.ExtendedBeyondNewline=1]="ExtendedBeyondNewline",dt[dt.NewlineRemoved=2]="NewlineRemoved",t.InkList=I,Object.defineProperty(t,"__esModule",{value:!0})})); +//# sourceMappingURL=ink.js.map diff --git a/prototype/ink.js.code-workspace b/prototype/ink.js.code-workspace new file mode 100644 index 0000000..8f559e5 --- /dev/null +++ b/prototype/ink.js.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "CodeGPT.apiKey": "Ollama" + } +} \ No newline at end of file diff --git a/prototype/ink.js.map b/prototype/ink.js.map new file mode 100644 index 0000000..0a50d2e --- /dev/null +++ b/prototype/ink.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ink.js","sources":["../src/engine/Debug.ts","../src/engine/Path.ts","../src/engine/TypeAssertion.ts","../src/engine/NullException.ts","../src/engine/Object.ts","../src/engine/StringBuilder.ts","../src/engine/InkList.ts","../src/engine/StoryException.ts","../src/engine/TryGetResult.ts","../src/engine/Value.ts","../src/engine/SearchResult.ts","../src/engine/Container.ts","../src/engine/PushPop.ts","../src/engine/Glue.ts","../src/engine/ControlCommand.ts","../src/engine/Pointer.ts","../src/engine/Divert.ts","../src/engine/ChoicePoint.ts","../src/engine/VariableReference.ts","../src/engine/VariableAssignment.ts","../src/engine/Void.ts","../src/engine/NativeFunctionCall.ts","../src/engine/Tag.ts","../src/engine/Choice.ts","../src/engine/ListDefinition.ts","../src/engine/ListDefinitionsOrigin.ts","../src/engine/JsonSerialisation.ts","../src/engine/CallStack.ts","../src/engine/VariablesState.ts","../src/engine/PRNG.ts","../src/engine/StatePatch.ts","../src/engine/SimpleJson.ts","../src/engine/Error.ts","../src/engine/Story.ts","../src/engine/Flow.ts","../src/engine/StoryState.ts","../src/engine/StopWatch.ts"],"sourcesContent":["export namespace Debug {\n export function AssertType(\n variable: any,\n type: new () => T,\n message: string\n ): void | never {\n Assert(variable instanceof type, message);\n }\n\n export function Assert(condition: boolean, message?: string): void | never {\n if (!condition) {\n if (typeof message !== \"undefined\") {\n console.warn(message);\n }\n\n if (console.trace) {\n console.trace();\n }\n\n throw new Error(\"\");\n }\n }\n}\n","export class Path {\n public static parentId = \"^\";\n\n public _isRelative: boolean;\n public _components: Path.Component[];\n public _componentsString: string | null;\n\n constructor();\n constructor(componentsString: string);\n constructor(head: Path.Component, tail: Path);\n constructor(head: Path.Component[], relative?: boolean);\n constructor() {\n this._components = [];\n this._componentsString = null;\n this._isRelative = false;\n\n if (typeof arguments[0] == \"string\") {\n let componentsString = arguments[0] as string;\n this.componentsString = componentsString;\n } else if (\n arguments[0] instanceof Path.Component &&\n arguments[1] instanceof Path\n ) {\n let head = arguments[0] as Path.Component;\n let tail = arguments[1] as Path;\n this._components.push(head);\n this._components = this._components.concat(tail._components);\n } else if (arguments[0] instanceof Array) {\n let head = arguments[0] as Path.Component[];\n let relative = !!arguments[1] as boolean;\n this._components = this._components.concat(head);\n this._isRelative = relative;\n }\n }\n get isRelative() {\n return this._isRelative;\n }\n get componentCount(): number {\n return this._components.length;\n }\n get head(): Path.Component | null {\n if (this._components.length > 0) {\n return this._components[0];\n } else {\n return null;\n }\n }\n get tail(): Path {\n if (this._components.length >= 2) {\n // careful, the original code uses length-1 here. This is because the second argument of\n // List.GetRange is a number of elements to extract, wherease Array.slice uses an index\n let tailComps = this._components.slice(1, this._components.length);\n return new Path(tailComps);\n } else {\n return Path.self;\n }\n }\n get length(): number {\n return this._components.length;\n }\n get lastComponent(): Path.Component | null {\n let lastComponentIdx = this._components.length - 1;\n if (lastComponentIdx >= 0) {\n return this._components[lastComponentIdx];\n } else {\n return null;\n }\n }\n get containsNamedComponent(): boolean {\n for (let i = 0, l = this._components.length; i < l; i++) {\n if (!this._components[i].isIndex) {\n return true;\n }\n }\n return false;\n }\n static get self(): Path {\n let path = new Path();\n path._isRelative = true;\n return path;\n }\n\n public GetComponent(index: number): Path.Component {\n return this._components[index];\n }\n public PathByAppendingPath(pathToAppend: Path): Path {\n let p = new Path();\n\n let upwardMoves = 0;\n for (let i = 0; i < pathToAppend._components.length; ++i) {\n if (pathToAppend._components[i].isParent) {\n upwardMoves++;\n } else {\n break;\n }\n }\n\n for (let i = 0; i < this._components.length - upwardMoves; ++i) {\n p._components.push(this._components[i]);\n }\n\n for (let i = upwardMoves; i < pathToAppend._components.length; ++i) {\n p._components.push(pathToAppend._components[i]);\n }\n\n return p;\n }\n get componentsString(): string {\n if (this._componentsString == null) {\n this._componentsString = this._components.join(\".\");\n if (this.isRelative)\n this._componentsString = \".\" + this._componentsString;\n }\n\n return this._componentsString;\n }\n set componentsString(value: string) {\n this._components.length = 0;\n\n this._componentsString = value;\n\n if (this._componentsString == null || this._componentsString == \"\") return;\n\n if (this._componentsString[0] == \".\") {\n this._isRelative = true;\n this._componentsString = this._componentsString.substring(1);\n }\n\n let componentStrings = this._componentsString.split(\".\");\n for (let str of componentStrings) {\n // we need to distinguish between named components that start with a number, eg \"42somewhere\", and indexed components\n // the normal parseInt won't do for the detection because it's too relaxed.\n // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt\n if (/^(\\-|\\+)?([0-9]+|Infinity)$/.test(str)) {\n this._components.push(new Path.Component(parseInt(str)));\n } else {\n this._components.push(new Path.Component(str));\n }\n }\n }\n public toString(): string {\n return this.componentsString;\n }\n public Equals(otherPath: Path | null): boolean {\n if (otherPath == null) return false;\n\n if (otherPath._components.length != this._components.length) return false;\n\n if (otherPath.isRelative != this.isRelative) return false;\n\n // the original code uses SequenceEqual here, so we need to iterate over the components manually.\n for (let i = 0, l = otherPath._components.length; i < l; i++) {\n // it's not quite clear whether this test should use Equals or a simple == operator,\n // see https://github.com/y-lohse/inkjs/issues/22\n if (!otherPath._components[i].Equals(this._components[i])) return false;\n }\n\n return true;\n }\n public PathByAppendingComponent(c: Path.Component): Path {\n let p = new Path();\n p._components.push(...this._components);\n p._components.push(c);\n return p;\n }\n}\n\nexport namespace Path {\n export class Component {\n public readonly index: number;\n public readonly name: string | null;\n\n constructor(indexOrName: string | number) {\n this.index = -1;\n this.name = null;\n if (typeof indexOrName == \"string\") {\n this.name = indexOrName;\n } else {\n this.index = indexOrName;\n }\n }\n get isIndex(): boolean {\n return this.index >= 0;\n }\n get isParent(): boolean {\n return this.name == Path.parentId;\n }\n\n public static ToParent(): Component {\n return new Component(Path.parentId);\n }\n public toString(): string | null {\n if (this.isIndex) {\n return this.index.toString();\n } else {\n return this.name;\n }\n }\n public Equals(otherComp: Component): boolean {\n if (otherComp != null && otherComp.isIndex == this.isIndex) {\n if (this.isIndex) {\n return this.index == otherComp.index;\n } else {\n return this.name == otherComp.name;\n }\n }\n\n return false;\n }\n }\n}\n","import { INamedContent } from \"./INamedContent\";\n\nexport function asOrNull(\n obj: any,\n type: (new (...arg: any[]) => T) | (Function & { prototype: T })\n): T | null {\n if (obj instanceof type) {\n return unsafeTypeAssertion(obj, type);\n } else {\n return null;\n }\n}\n\nexport function asOrThrows(\n obj: any,\n type: (new (...arg: any[]) => T) | (Function & { prototype: T })\n): T | never {\n if (obj instanceof type) {\n return unsafeTypeAssertion(obj, type);\n } else {\n throw new Error(`${obj} is not of type ${type}`);\n }\n}\n\nexport function asNumberOrThrows(obj: any) {\n if (typeof obj === \"number\") {\n return obj as number;\n } else {\n throw new Error(`${obj} is not a number`);\n }\n}\n\nexport function asBooleanOrThrows(obj: any) {\n if (typeof obj === \"boolean\") {\n return obj as boolean;\n } else {\n throw new Error(`${obj} is not a boolean`);\n }\n}\n\n// So here, in the reference implementation, contentObj is casted to an INamedContent\n// but here we use js-style duck typing: if it implements the same props as the interface,\n// we treat it as valid.\nexport function asINamedContentOrNull(obj: any): INamedContent | null {\n if (obj.hasValidName && obj.name) {\n return obj as INamedContent;\n }\n\n return null;\n}\n\nexport function nullIfUndefined(obj: T | undefined): T | null {\n if (typeof obj === \"undefined\") {\n return null;\n }\n\n return obj;\n}\n\nexport function isEquatable(type: any) {\n return typeof type === \"object\" && typeof type.Equals === \"function\";\n}\n\nfunction unsafeTypeAssertion(\n obj: any,\n type: (new () => T) | (Function & { prototype: T })\n) {\n return obj as T;\n}\n\nexport function filterUndef(element: T | undefined): element is T {\n return element != undefined;\n}\n","/**\n * In the original C# code, a SystemException would be thrown when passing\n * null to methods expected a valid instance. Javascript has no such\n * concept, but TypeScript will not allow `null` to be passed to methods\n * explicitely requiring a valid type.\n *\n * Whenever TypeScript complain about the possibility of a `null` value,\n * check the offending value and it it's null, throw this exception using\n * `throwNullException(name: string)`.\n */\nexport class NullException extends Error {}\n\n/**\n * Throw a NullException.\n *\n * @param name a short description of the offending value (often its name within the code).\n */\nexport function throwNullException(name: string): never {\n throw new NullException(`${name} is null or undefined`);\n}\n","import { Path } from \"./Path\";\nimport { Container } from \"./Container\";\nimport { Debug } from \"./Debug\";\nimport { asOrNull, asINamedContentOrNull } from \"./TypeAssertion\";\nimport { throwNullException } from \"./NullException\";\nimport { SearchResult } from \"./SearchResult\";\nimport { DebugMetadata } from \"./DebugMetadata\";\n\nexport class InkObject {\n public parent: InkObject | null = null;\n\n get debugMetadata(): DebugMetadata | null {\n if (this._debugMetadata === null) {\n if (this.parent) {\n return this.parent.debugMetadata;\n }\n }\n\n return this._debugMetadata;\n }\n\n set debugMetadata(value) {\n this._debugMetadata = value;\n }\n\n get ownDebugMetadata() {\n return this._debugMetadata;\n }\n\n private _debugMetadata: DebugMetadata | null = null;\n\n public DebugLineNumberOfPath(path: Path) {\n if (path === null) return null;\n\n // Try to get a line number from debug metadata\n let root = this.rootContentContainer;\n if (root) {\n let targetContent = root.ContentAtPath(path).obj;\n if (targetContent) {\n let dm = targetContent.debugMetadata;\n if (dm !== null) {\n return dm.startLineNumber;\n }\n }\n }\n\n return null;\n }\n\n get path() {\n if (this._path == null) {\n if (this.parent == null) {\n this._path = new Path();\n } else {\n let comps: Path.Component[] = [];\n\n let child: InkObject = this;\n let container = asOrNull(child.parent, Container);\n\n while (container !== null) {\n let namedChild = asINamedContentOrNull(child);\n if (namedChild != null && namedChild.hasValidName) {\n if (namedChild.name === null)\n return throwNullException(\"namedChild.name\");\n comps.unshift(new Path.Component(namedChild.name!));\n } else {\n comps.unshift(new Path.Component(container.content.indexOf(child)));\n }\n\n child = container;\n container = asOrNull(container.parent, Container);\n }\n\n this._path = new Path(comps);\n }\n }\n\n return this._path;\n }\n private _path: Path | null = null;\n\n public ResolvePath(path: Path | null): SearchResult {\n if (path === null) return throwNullException(\"path\");\n if (path.isRelative) {\n let nearestContainer = asOrNull(this, Container);\n\n if (nearestContainer === null) {\n Debug.Assert(\n this.parent !== null,\n \"Can't resolve relative path because we don't have a parent\"\n );\n nearestContainer = asOrNull(this.parent, Container);\n Debug.Assert(\n nearestContainer !== null,\n \"Expected parent to be a container\"\n );\n Debug.Assert(path.GetComponent(0).isParent);\n path = path.tail;\n }\n\n if (nearestContainer === null) {\n return throwNullException(\"nearestContainer\");\n }\n return nearestContainer.ContentAtPath(path);\n } else {\n let contentContainer = this.rootContentContainer;\n if (contentContainer === null) {\n return throwNullException(\"contentContainer\");\n }\n return contentContainer.ContentAtPath(path);\n }\n }\n\n public ConvertPathToRelative(globalPath: Path) {\n let ownPath = this.path;\n\n let minPathLength = Math.min(globalPath.length, ownPath.length);\n let lastSharedPathCompIndex = -1;\n\n for (let i = 0; i < minPathLength; ++i) {\n let ownComp = ownPath.GetComponent(i);\n let otherComp = globalPath.GetComponent(i);\n\n if (ownComp.Equals(otherComp)) {\n lastSharedPathCompIndex = i;\n } else {\n break;\n }\n }\n\n // No shared path components, so just use global path\n if (lastSharedPathCompIndex == -1) return globalPath;\n\n let numUpwardsMoves = ownPath.componentCount - 1 - lastSharedPathCompIndex;\n\n let newPathComps: Path.Component[] = [];\n\n for (let up = 0; up < numUpwardsMoves; ++up)\n newPathComps.push(Path.Component.ToParent());\n\n for (\n let down = lastSharedPathCompIndex + 1;\n down < globalPath.componentCount;\n ++down\n )\n newPathComps.push(globalPath.GetComponent(down));\n\n let relativePath = new Path(newPathComps, true);\n return relativePath;\n }\n\n public CompactPathString(otherPath: Path) {\n let globalPathStr = null;\n let relativePathStr = null;\n\n if (otherPath.isRelative) {\n relativePathStr = otherPath.componentsString;\n globalPathStr = this.path.PathByAppendingPath(otherPath).componentsString;\n } else {\n let relativePath = this.ConvertPathToRelative(otherPath);\n relativePathStr = relativePath.componentsString;\n globalPathStr = otherPath.componentsString;\n }\n\n if (relativePathStr.length < globalPathStr.length) return relativePathStr;\n else return globalPathStr;\n }\n\n get rootContentContainer() {\n let ancestor: InkObject = this;\n while (ancestor.parent) {\n ancestor = ancestor.parent;\n }\n return asOrNull(ancestor, Container);\n }\n\n public Copy(): InkObject {\n throw Error(\"Not Implemented: Doesn't support copying\");\n }\n // SetChild works slightly diferently in the js implementation.\n // Since we can't pass an objets property by reference, we instead pass\n // the object and the property string.\n // TODO: This method can probably be rewritten with type-safety in mind.\n public SetChild(obj: any, prop: any, value: any) {\n if (obj[prop]) obj[prop] = null;\n\n obj[prop] = value;\n\n if (obj[prop]) obj[prop].parent = this;\n }\n\n public Equals(obj: any) {\n return obj === this;\n }\n}\n","export class StringBuilder {\n private string: string;\n\n constructor(str?: string) {\n str = typeof str !== \"undefined\" ? str.toString() : \"\";\n this.string = str;\n }\n get Length(): number {\n return this.string.length;\n }\n public Append(str: string | null) {\n if (str !== null) {\n this.string += str;\n }\n }\n public AppendLine(str?: string) {\n if (typeof str !== \"undefined\") this.Append(str);\n this.string += \"\\n\";\n }\n public AppendFormat(format: string, ...args: any[]) {\n // taken from http://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format\n this.string += format.replace(/{(\\d+)}/g, (match: string, num: number) =>\n typeof args[num] != \"undefined\" ? args[num] : match\n );\n }\n public toString(): string {\n return this.string;\n }\n}\n","import { throwNullException } from \"./NullException\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { Story } from \"./Story\";\n\nexport class InkListItem implements IInkListItem {\n // InkListItem is a struct\n\n public readonly originName: string | null = null;\n public readonly itemName: string | null = null;\n\n constructor(originName: string | null, itemName: string | null);\n constructor(fullName: string | null);\n constructor() {\n if (typeof arguments[1] !== \"undefined\") {\n let originName = arguments[0] as string | null;\n let itemName = arguments[1] as string | null;\n\n this.originName = originName;\n this.itemName = itemName;\n } else if (arguments[0]) {\n let fullName = arguments[0] as string;\n\n let nameParts = fullName.toString().split(\".\");\n this.originName = nameParts[0];\n this.itemName = nameParts[1];\n }\n }\n public static get Null() {\n return new InkListItem(null, null);\n }\n public get isNull() {\n return this.originName == null && this.itemName == null;\n }\n get fullName() {\n return (\n (this.originName !== null ? this.originName : \"?\") + \".\" + this.itemName\n );\n }\n public toString(): string {\n return this.fullName;\n }\n public Equals(obj: InkListItem) {\n if (obj instanceof InkListItem) {\n let otherItem = obj;\n return (\n otherItem.itemName == this.itemName &&\n otherItem.originName == this.originName\n );\n }\n\n return false;\n }\n\n // These methods did not exist in the original C# code. Their purpose is to\n // make `InkListItem` mimics the value-type semantics of the original\n // struct. Please refer to the end of this file, for a more in-depth\n // explanation.\n\n /**\n * Returns a shallow clone of the current instance.\n */\n public copy() {\n return new InkListItem(this.originName, this.itemName);\n }\n /**\n * Returns a `SerializedInkListItem` representing the current\n * instance. The result is intended to be used as a key inside a Map.\n */\n public serialized(): SerializedInkListItem {\n // We are simply using a JSON representation as a value-typed key.\n return JSON.stringify({\n originName: this.originName,\n itemName: this.itemName,\n });\n }\n\n /**\n * Reconstructs a `InkListItem` from the given SerializedInkListItem.\n */\n public static fromSerializedKey(key: SerializedInkListItem): InkListItem {\n let obj = JSON.parse(key);\n if (!InkListItem.isLikeInkListItem(obj)) return InkListItem.Null;\n\n let inkListItem = obj as IInkListItem;\n\n return new InkListItem(inkListItem.originName, inkListItem.itemName);\n }\n\n /**\n * Determines whether the given item is sufficiently `InkListItem`-like\n * to be used as a template when reconstructing the InkListItem.\n */\n private static isLikeInkListItem(item: any) {\n if (typeof item !== \"object\") return false;\n if (!item.hasOwnProperty(\"originName\") || !item.hasOwnProperty(\"itemName\"))\n return false;\n if (typeof item.originName !== \"string\" && typeof item.originName !== null)\n return false;\n if (typeof item.itemName !== \"string\" && typeof item.itemName !== null)\n return false;\n\n return true;\n }\n}\n\nexport class InkList extends Map {\n public origins: ListDefinition[] | null = null;\n public _originNames: string[] | null = [];\n\n constructor();\n constructor(otherList: InkList);\n constructor(singleOriginListName: string, originStory: Story);\n constructor(singleElement: KeyValuePair);\n constructor() {\n // Trying to be smart here, this emulates the constructor inheritance found\n // in the original code, but only if otherList is an InkList. IIFE FTW.\n super(\n (() => {\n if (arguments[0] instanceof InkList) {\n return arguments[0];\n } else {\n return [];\n }\n })()\n );\n\n if (arguments[0] instanceof InkList) {\n let otherList = arguments[0] as InkList;\n\n this._originNames = otherList.originNames;\n if (otherList.origins !== null) {\n this.origins = otherList.origins.slice();\n }\n } else if (typeof arguments[0] === \"string\") {\n let singleOriginListName = arguments[0] as string;\n let originStory = arguments[1] as Story;\n this.SetInitialOriginName(singleOriginListName);\n\n if (originStory.listDefinitions === null) {\n return throwNullException(\"originStory.listDefinitions\");\n }\n let def = originStory.listDefinitions.TryListGetDefinition(\n singleOriginListName,\n null\n );\n if (def.exists) {\n // Throwing now, because if the value is `null` it will\n // eventually throw down the line.\n if (def.result === null) {\n return throwNullException(\"def.result\");\n }\n this.origins = [def.result];\n } else {\n throw new Error(\n \"InkList origin could not be found in story when constructing new list: \" +\n singleOriginListName\n );\n }\n } else if (\n typeof arguments[0] === \"object\" &&\n arguments[0].hasOwnProperty(\"Key\") &&\n arguments[0].hasOwnProperty(\"Value\")\n ) {\n let singleElement = arguments[0] as KeyValuePair;\n this.Add(singleElement.Key, singleElement.Value);\n }\n }\n\n public static FromString(myListItem: string, originStory: Story) {\n let listValue =\n originStory.listDefinitions?.FindSingleItemListWithName(myListItem);\n if (listValue) {\n if (listValue.value === null) {\n return throwNullException(\"listValue.value\");\n }\n return new InkList(listValue.value);\n } else {\n throw new Error(\n \"Could not find the InkListItem from the string '\" +\n myListItem +\n \"' to create an InkList because it doesn't exist in the original list definition in ink.\"\n );\n }\n }\n\n public AddItem(itemOrItemName: InkListItem | string | null) {\n if (itemOrItemName instanceof InkListItem) {\n let item = itemOrItemName;\n\n if (item.originName == null) {\n this.AddItem(item.itemName);\n return;\n }\n\n if (this.origins === null) return throwNullException(\"this.origins\");\n\n for (let origin of this.origins) {\n if (origin.name == item.originName) {\n let intVal = origin.TryGetValueForItem(item, 0);\n if (intVal.exists) {\n this.Add(item, intVal.result);\n return;\n } else {\n throw new Error(\n \"Could not add the item \" +\n item +\n \" to this list because it doesn't exist in the original list definition in ink.\"\n );\n }\n }\n }\n\n throw new Error(\n \"Failed to add item to list because the item was from a new list definition that wasn't previously known to this list. Only items from previously known lists can be used, so that the int value can be found.\"\n );\n } else {\n let itemName = itemOrItemName as string | null;\n\n let foundListDef: ListDefinition | null = null;\n\n if (this.origins === null) return throwNullException(\"this.origins\");\n\n for (let origin of this.origins) {\n if (itemName === null) return throwNullException(\"itemName\");\n\n if (origin.ContainsItemWithName(itemName)) {\n if (foundListDef != null) {\n throw new Error(\n \"Could not add the item \" +\n itemName +\n \" to this list because it could come from either \" +\n origin.name +\n \" or \" +\n foundListDef.name\n );\n } else {\n foundListDef = origin;\n }\n }\n }\n\n if (foundListDef == null)\n throw new Error(\n \"Could not add the item \" +\n itemName +\n \" to this list because it isn't known to any list definitions previously associated with this list.\"\n );\n\n let item = new InkListItem(foundListDef.name, itemName);\n let itemVal = foundListDef.ValueForItem(item);\n this.Add(item, itemVal);\n }\n }\n public ContainsItemNamed(itemName: string | null) {\n for (let [key] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (item.itemName == itemName) return true;\n }\n\n return false;\n }\n public ContainsKey(key: InkListItem) {\n return this.has(key.serialized());\n }\n public Add(key: InkListItem, value: number) {\n let serializedKey = key.serialized();\n if (this.has(serializedKey)) {\n // Throw an exception to match the C# behavior.\n throw new Error(`The Map already contains an entry for ${key}`);\n }\n this.set(serializedKey, value);\n }\n public Remove(key: InkListItem) {\n return this.delete(key.serialized());\n }\n get Count() {\n return this.size;\n }\n get originOfMaxItem(): ListDefinition | null {\n if (this.origins == null) return null;\n\n let maxOriginName = this.maxItem.Key.originName;\n let result = null;\n this.origins.every((origin) => {\n if (origin.name == maxOriginName) {\n result = origin;\n return false;\n } else return true;\n });\n\n return result;\n }\n get originNames(): string[] {\n if (this.Count > 0) {\n if (this._originNames == null && this.Count > 0) this._originNames = [];\n else {\n if (!this._originNames) this._originNames = [];\n this._originNames.length = 0;\n }\n\n for (let [key] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (item.originName === null)\n return throwNullException(\"item.originName\");\n this._originNames.push(item.originName);\n }\n }\n\n return this._originNames as string[];\n }\n public SetInitialOriginName(initialOriginName: string) {\n this._originNames = [initialOriginName];\n }\n public SetInitialOriginNames(initialOriginNames: string[]) {\n if (initialOriginNames == null) this._originNames = null;\n else this._originNames = initialOriginNames.slice(); // store a copy\n }\n get maxItem() {\n let max: KeyValuePair = {\n Key: InkListItem.Null,\n Value: 0,\n };\n for (let [key, value] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (max.Key.isNull || value > max.Value)\n max = { Key: item, Value: value };\n }\n\n return max;\n }\n get minItem() {\n let min: KeyValuePair = {\n Key: InkListItem.Null,\n Value: 0,\n };\n for (let [key, value] of this) {\n let item = InkListItem.fromSerializedKey(key);\n if (min.Key.isNull || value < min.Value) {\n min = { Key: item, Value: value };\n }\n }\n return min;\n }\n get inverse() {\n let list = new InkList();\n if (this.origins != null) {\n for (let origin of this.origins) {\n for (let [key, value] of origin.items) {\n let item = InkListItem.fromSerializedKey(key);\n if (!this.ContainsKey(item)) list.Add(item, value);\n }\n }\n }\n return list;\n }\n get all() {\n let list = new InkList();\n if (this.origins != null) {\n for (let origin of this.origins) {\n for (let [key, value] of origin.items) {\n let item = InkListItem.fromSerializedKey(key);\n list.set(item.serialized(), value);\n }\n }\n }\n return list;\n }\n public Union(otherList: InkList) {\n let union = new InkList(this);\n for (let [key, value] of otherList) {\n union.set(key, value);\n }\n return union;\n }\n public Intersect(otherList: InkList) {\n let intersection = new InkList();\n for (let [key, value] of this) {\n if (otherList.has(key)) intersection.set(key, value);\n }\n\n return intersection;\n }\n public Without(listToRemove: InkList) {\n let result = new InkList(this);\n for (let [key] of listToRemove) {\n result.delete(key);\n }\n\n return result;\n }\n public Contains(otherList: InkList) {\n for (let [key] of otherList) {\n if (!this.has(key)) return false;\n }\n\n return true;\n }\n public GreaterThan(otherList: InkList) {\n if (this.Count == 0) return false;\n if (otherList.Count == 0) return true;\n\n return this.minItem.Value > otherList.maxItem.Value;\n }\n public GreaterThanOrEquals(otherList: InkList) {\n if (this.Count == 0) return false;\n if (otherList.Count == 0) return true;\n\n return (\n this.minItem.Value >= otherList.minItem.Value &&\n this.maxItem.Value >= otherList.maxItem.Value\n );\n }\n public LessThan(otherList: InkList) {\n if (otherList.Count == 0) return false;\n if (this.Count == 0) return true;\n\n return this.maxItem.Value < otherList.minItem.Value;\n }\n public LessThanOrEquals(otherList: InkList) {\n if (otherList.Count == 0) return false;\n if (this.Count == 0) return true;\n\n return (\n this.maxItem.Value <= otherList.maxItem.Value &&\n this.minItem.Value <= otherList.minItem.Value\n );\n }\n public MaxAsList() {\n if (this.Count > 0) return new InkList(this.maxItem);\n else return new InkList();\n }\n public MinAsList() {\n if (this.Count > 0) return new InkList(this.minItem);\n else return new InkList();\n }\n public ListWithSubRange(minBound: any, maxBound: any) {\n if (this.Count == 0) return new InkList();\n\n let ordered = this.orderedItems;\n\n let minValue = 0;\n let maxValue = Number.MAX_SAFE_INTEGER;\n\n if (Number.isInteger(minBound)) {\n minValue = minBound;\n } else {\n if (minBound instanceof InkList && minBound.Count > 0)\n minValue = minBound.minItem.Value;\n }\n\n if (Number.isInteger(maxBound)) {\n maxValue = maxBound;\n } else {\n if (minBound instanceof InkList && minBound.Count > 0)\n maxValue = maxBound.maxItem.Value;\n }\n\n let subList = new InkList();\n subList.SetInitialOriginNames(this.originNames);\n for (let item of ordered) {\n if (item.Value >= minValue && item.Value <= maxValue) {\n subList.Add(item.Key, item.Value);\n }\n }\n\n return subList;\n }\n public Equals(otherInkList: InkList) {\n if (otherInkList instanceof InkList === false) return false;\n if (otherInkList.Count != this.Count) return false;\n\n for (let [key] of this) {\n if (!otherInkList.has(key)) return false;\n }\n\n return true;\n }\n // GetHashCode not implemented\n get orderedItems() {\n // List>\n let ordered = new Array>();\n\n for (let [key, value] of this) {\n let item = InkListItem.fromSerializedKey(key);\n ordered.push({ Key: item, Value: value });\n }\n\n ordered.sort((x, y) => {\n if (x.Key.originName === null) {\n return throwNullException(\"x.Key.originName\");\n }\n if (y.Key.originName === null) {\n return throwNullException(\"y.Key.originName\");\n }\n\n if (x.Value == y.Value) {\n return x.Key.originName.localeCompare(y.Key.originName);\n } else {\n // TODO: refactor this bit into a numberCompareTo method?\n if (x.Value < y.Value) return -1;\n return x.Value > y.Value ? 1 : 0;\n }\n });\n\n return ordered;\n }\n public toString() {\n let ordered = this.orderedItems;\n\n let sb = new StringBuilder();\n for (let i = 0; i < ordered.length; i++) {\n if (i > 0) sb.Append(\", \");\n\n let item = ordered[i].Key;\n if (item.itemName === null) return throwNullException(\"item.itemName\");\n sb.Append(item.itemName);\n }\n\n return sb.toString();\n }\n // casting a InkList to a Number, for somereason, actually gives a number.\n // This messes up the type detection when creating a Value from a InkList.\n // Returning NaN here prevents that.\n public valueOf() {\n return NaN;\n }\n}\n\n/**\n * In the original C# code, `InkListItem` was defined as value type, meaning\n * that two `InkListItem` would be considered equal as long as they held the\n * same values. This doesn't hold true in Javascript, as `InkListItem` is a\n * reference type (Javascript doesn't allow the creation of custom value types).\n *\n * The key equality of Map objects is based on the \"SameValueZero\" algorithm;\n * since `InkListItem` is a value type, two keys will only be considered\n * equal if they are, in fact, the same object. As we are trying to emulate\n * the original behavior as close as possible, this will lead to unforeseen\n * side effects.\n *\n * In order to have a key equality based on value semantics, we'll convert\n * `InkListItem` to a valid string representation and use this representation\n * as a key (strings are value types in Javascript). Rather than using the\n * type `string` directly, we'll alias it to `SerializedInkListItem` and use\n * this type as the key for our Map-based `InkList`.\n *\n * Reducing `InkListItem` to a JSON representation would not be bulletproof\n * in the general case, but for our needs it works well. The major downside of\n * this method is that we will have to to reconstruct the original `InkListItem`\n * every time we'll need to access its properties.\n */\nexport type SerializedInkListItem = string;\n\n/**\n * An interface inherited by `InkListItem`, defining exposed\n * properties. It's mainly used when deserializing a `InkListItem` from its\n * key (`SerializedInkListItem`)\n */\ninterface IInkListItem {\n readonly originName: string | null;\n readonly itemName: string | null;\n}\nexport interface KeyValuePair {\n Key: K;\n Value: V;\n}\n","export class StoryException extends Error {\n public useEndLineNumber: boolean;\n public message: string;\n public name: string;\n\n constructor(message: string) {\n super(message);\n this.useEndLineNumber = false;\n this.message = message;\n this.name = \"StoryException\";\n }\n}\n","/**\n * This interface normalize the `TryGet` behavior found in the original\n * C# project. Any `TryGet` method will return a object conforming to this\n * interface.\n *\n * The original function returns a boolean and has a second parameter called\n * item that is an `out`. Both are needed and we can't just return the item\n * because it'll always be truthy. Instead, we return an object containing\n * whether the result exists (`exists`) and the result itself (`result`).\n *\n * For instance a `TryGet` prototype would look like this:\n```\nTryGetItemWithValue(val: number, item: InkListItem): TryGetResult{\n```\n *\n * On the other hand, dealing with the result can be done in the following way:\n```\nvar item = item.TryGetItemWithValue(intVal, InkListItem.Null);\nif (item.exists) {\n\tconsole.log(item.result)\n}\n```\n *\n */\nexport interface TryGetResult {\n result: T;\n exists: boolean;\n}\n\nexport function tryGetValueFromMap(\n map: Map | null,\n key: K,\n /* out */ value: V\n): TryGetResult {\n if (map === null) {\n return { result: value, exists: false };\n }\n\n let val = map.get(key);\n\n if (typeof val === \"undefined\") {\n return { result: value, exists: false };\n } else {\n return { result: val, exists: true };\n }\n}\n\nexport function tryParseInt(\n value: any,\n /* out */ defaultValue: number = 0\n): TryGetResult {\n let val = parseInt(value);\n\n if (!Number.isNaN(val)) {\n return { result: val, exists: true };\n } else {\n return { result: defaultValue, exists: false };\n }\n}\n\nexport function tryParseFloat(\n value: any,\n /* out */ defaultValue: number = 0\n): TryGetResult {\n let val = parseFloat(value);\n\n if (!Number.isNaN(val)) {\n return { result: val, exists: true };\n } else {\n return { result: defaultValue, exists: false };\n }\n}\n","import { InkObject } from \"./Object\";\nimport { Path } from \"./Path\";\nimport { InkList, InkListItem } from \"./InkList\";\nimport { StoryException } from \"./StoryException\";\nimport { asOrNull, asOrThrows } from \"./TypeAssertion\";\nimport { tryParseInt, tryParseFloat } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\n\nexport abstract class AbstractValue extends InkObject {\n public abstract get valueType(): ValueType;\n public abstract get isTruthy(): boolean;\n public abstract get valueObject(): any;\n\n public abstract Cast(newType: ValueType): Value;\n\n public static Create(\n val: any,\n preferredNumberType?: ValueType\n ): Value | null {\n // This code doesn't exist in upstream and is simply here to enforce\n // the creation of the proper number value.\n // If `preferredNumberType` is not provided or if value doesn't match\n // `preferredNumberType`, this conditional does nothing.\n if (preferredNumberType) {\n if (\n preferredNumberType === (ValueType.Int as ValueType) &&\n Number.isInteger(Number(val))\n ) {\n return new IntValue(Number(val));\n } else if (\n preferredNumberType === (ValueType.Float as ValueType) &&\n !isNaN(val)\n ) {\n return new FloatValue(Number(val));\n }\n }\n\n if (typeof val === \"boolean\") {\n return new BoolValue(Boolean(val));\n }\n\n // https://github.com/y-lohse/inkjs/issues/425\n // Changed condition sequence, because Number('') is\n // parsed to 0, which made setting string to empty\n // impossible\n if (typeof val === \"string\") {\n return new StringValue(String(val));\n } else if (Number.isInteger(Number(val))) {\n return new IntValue(Number(val));\n } else if (!isNaN(val)) {\n return new FloatValue(Number(val));\n } else if (val instanceof Path) {\n return new DivertTargetValue(asOrThrows(val, Path));\n } else if (val instanceof InkList) {\n return new ListValue(asOrThrows(val, InkList));\n }\n\n return null;\n }\n public Copy() {\n return asOrThrows(AbstractValue.Create(this.valueObject), InkObject);\n }\n public BadCastException(targetType: ValueType) {\n return new StoryException(\n \"Can't cast \" +\n this.valueObject +\n \" from \" +\n this.valueType +\n \" to \" +\n targetType\n );\n }\n}\n\nexport abstract class Value<\n T extends { toString: () => string }\n> extends AbstractValue {\n public value: T | null;\n\n constructor(val: T | null) {\n super();\n this.value = val;\n }\n public get valueObject() {\n return this.value;\n }\n public toString() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value.toString();\n }\n}\n\nexport class BoolValue extends Value {\n constructor(val: boolean) {\n super(val || false);\n }\n public get isTruthy() {\n return Boolean(this.value);\n }\n public get valueType() {\n return ValueType.Bool;\n }\n\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Int) {\n return new IntValue(this.value ? 1 : 0);\n }\n\n if (newType == ValueType.Float) {\n return new FloatValue(this.value ? 1.0 : 0.0);\n }\n\n if (newType == ValueType.String) {\n return new StringValue(this.value ? \"true\" : \"false\");\n }\n\n throw this.BadCastException(newType);\n }\n\n public toString() {\n return this.value ? \"true\" : \"false\";\n }\n}\n\nexport class IntValue extends Value {\n constructor(val: number) {\n super(val || 0);\n }\n public get isTruthy() {\n return this.value != 0;\n }\n public get valueType() {\n return ValueType.Int;\n }\n\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Bool) {\n return new BoolValue(this.value === 0 ? false : true);\n }\n\n if (newType == ValueType.Float) {\n return new FloatValue(this.value);\n }\n\n if (newType == ValueType.String) {\n return new StringValue(\"\" + this.value);\n }\n\n throw this.BadCastException(newType);\n }\n}\n\nexport class FloatValue extends Value {\n constructor(val: number) {\n super(val || 0.0);\n }\n public get isTruthy() {\n return this.value != 0.0;\n }\n public get valueType() {\n return ValueType.Float;\n }\n\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Bool) {\n return new BoolValue(this.value === 0.0 ? false : true);\n }\n\n if (newType == ValueType.Int) {\n return new IntValue(this.value);\n }\n\n if (newType == ValueType.String) {\n return new StringValue(\"\" + this.value);\n }\n\n throw this.BadCastException(newType);\n }\n}\n\nexport class StringValue extends Value {\n public _isNewline: boolean;\n public _isInlineWhitespace: boolean;\n\n constructor(val: string) {\n super(val || \"\");\n\n this._isNewline = this.value == \"\\n\";\n this._isInlineWhitespace = true;\n\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (this.value.length > 0) {\n this.value.split(\"\").every((c) => {\n if (c != \" \" && c != \"\\t\") {\n this._isInlineWhitespace = false;\n return false;\n }\n\n return true;\n });\n }\n }\n public get valueType() {\n return ValueType.String;\n }\n public get isTruthy() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value.length > 0;\n }\n public get isNewline() {\n return this._isNewline;\n }\n public get isInlineWhitespace() {\n return this._isInlineWhitespace;\n }\n public get isNonWhitespace() {\n return !this.isNewline && !this.isInlineWhitespace;\n }\n\n public Cast(newType: ValueType): Value {\n if (newType == this.valueType) {\n return this;\n }\n\n if (newType == ValueType.Int) {\n let parsedInt = tryParseInt(this.value);\n if (parsedInt.exists) {\n return new IntValue(parsedInt.result);\n } else {\n throw this.BadCastException(newType);\n }\n }\n\n if (newType == ValueType.Float) {\n let parsedFloat = tryParseFloat(this.value);\n if (parsedFloat.exists) {\n return new FloatValue(parsedFloat.result);\n } else {\n throw this.BadCastException(newType);\n }\n }\n\n throw this.BadCastException(newType);\n }\n}\n\nexport class DivertTargetValue extends Value {\n constructor(targetPath: Path | null = null) {\n super(targetPath);\n }\n public get valueType() {\n return ValueType.DivertTarget;\n }\n public get targetPath() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value;\n }\n public set targetPath(value: Path) {\n this.value = value;\n }\n public get isTruthy(): never {\n throw new Error(\"Shouldn't be checking the truthiness of a divert target\");\n }\n\n public Cast(newType: ValueType): Value {\n if (newType == this.valueType) return this;\n\n throw this.BadCastException(newType);\n }\n public toString() {\n return \"DivertTargetValue(\" + this.targetPath + \")\";\n }\n}\n\nexport class VariablePointerValue extends Value {\n public _contextIndex: number;\n\n constructor(variableName: string, contextIndex: number = -1) {\n super(variableName);\n\n this._contextIndex = contextIndex;\n }\n\n public get contextIndex() {\n return this._contextIndex;\n }\n public set contextIndex(value: number) {\n this._contextIndex = value;\n }\n public get variableName() {\n if (this.value === null) return throwNullException(\"Value.value\");\n return this.value;\n }\n public set variableName(value: string) {\n this.value = value;\n }\n public get valueType() {\n return ValueType.VariablePointer;\n }\n\n public get isTruthy(): never {\n throw new Error(\n \"Shouldn't be checking the truthiness of a variable pointer\"\n );\n }\n\n public Cast(newType: ValueType): Value {\n if (newType == this.valueType) return this;\n\n throw this.BadCastException(newType);\n }\n public toString() {\n return \"VariablePointerValue(\" + this.variableName + \")\";\n }\n public Copy() {\n return new VariablePointerValue(this.variableName, this.contextIndex);\n }\n}\n\nexport class ListValue extends Value {\n public get isTruthy() {\n if (this.value === null) {\n return throwNullException(\"this.value\");\n }\n return this.value.Count > 0;\n }\n public get valueType() {\n return ValueType.List;\n }\n public Cast(newType: ValueType): Value {\n if (this.value === null) return throwNullException(\"Value.value\");\n\n if (newType == ValueType.Int) {\n let max = this.value.maxItem;\n if (max.Key.isNull) return new IntValue(0);\n else return new IntValue(max.Value);\n } else if (newType == ValueType.Float) {\n let max = this.value.maxItem;\n if (max.Key.isNull) return new FloatValue(0.0);\n else return new FloatValue(max.Value);\n } else if (newType == ValueType.String) {\n let max = this.value.maxItem;\n if (max.Key.isNull) return new StringValue(\"\");\n else {\n return new StringValue(max.Key.toString());\n }\n }\n\n if (newType == this.valueType) return this;\n\n throw this.BadCastException(newType);\n }\n constructor();\n constructor(list: InkList);\n constructor(listOrSingleItem: InkListItem, singleValue: number);\n constructor(listOrSingleItem?: InkListItem | InkList, singleValue?: number) {\n super(null);\n\n if (!listOrSingleItem && !singleValue) {\n this.value = new InkList();\n } else if (listOrSingleItem instanceof InkList) {\n this.value = new InkList(listOrSingleItem);\n } else if (\n listOrSingleItem instanceof InkListItem &&\n typeof singleValue === \"number\"\n ) {\n this.value = new InkList({\n Key: listOrSingleItem,\n Value: singleValue,\n });\n }\n }\n public static RetainListOriginsForAssignment(\n oldValue: InkObject | null,\n newValue: InkObject\n ) {\n let oldList = asOrNull(oldValue, ListValue);\n let newList = asOrNull(newValue, ListValue);\n\n if (newList && newList.value === null)\n return throwNullException(\"newList.value\");\n if (oldList && oldList.value === null)\n return throwNullException(\"oldList.value\");\n\n // When assigning the empty list, try to retain any initial origin names\n if (oldList && newList && newList.value!.Count == 0)\n newList.value!.SetInitialOriginNames(oldList.value!.originNames);\n }\n}\n\nexport enum ValueType {\n Bool = -1,\n Int = 0,\n Float = 1,\n List = 2,\n String = 3,\n DivertTarget = 4,\n VariablePointer = 5,\n}\n","import { InkObject } from \"./Object\";\nimport { Container } from \"./Container\";\n\nexport class SearchResult {\n public obj: InkObject | null = null;\n public approximate: boolean = false;\n\n get correctObj() {\n return this.approximate ? null : this.obj;\n }\n\n get container() {\n return this.obj instanceof Container ? this.obj : null;\n }\n\n public copy() {\n let searchResult = new SearchResult();\n searchResult.obj = this.obj;\n searchResult.approximate = this.approximate;\n\n return searchResult;\n }\n}\n","import { StringValue } from \"./Value\";\nimport { throwNullException } from \"./NullException\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { INamedContent } from \"./INamedContent\";\nimport { InkObject } from \"./Object\";\nimport { SearchResult } from \"./SearchResult\";\nimport { Path } from \"./Path\";\nimport { Debug } from \"./Debug\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { asINamedContentOrNull, asOrNull, asOrThrows } from \"./TypeAssertion\";\n\nexport class Container extends InkObject implements INamedContent {\n public name: string | null = null;\n\n public _content: InkObject[] = [];\n public namedContent: Map = new Map();\n\n public visitsShouldBeCounted: boolean = false;\n public turnIndexShouldBeCounted: boolean = false;\n public countingAtStartOnly: boolean = false;\n\n public _pathToFirstLeafContent: Path | null = null;\n\n get hasValidName() {\n return this.name != null && this.name.length > 0;\n }\n get content() {\n return this._content;\n }\n set content(value: InkObject[]) {\n this.AddContent(value);\n }\n get namedOnlyContent() {\n let namedOnlyContentDict: Map | null = new Map();\n\n for (let [key, value] of this.namedContent) {\n let inkObject = asOrThrows(value, InkObject);\n namedOnlyContentDict.set(key, inkObject);\n }\n\n for (let c of this.content) {\n let named = asINamedContentOrNull(c);\n if (named != null && named.hasValidName) {\n namedOnlyContentDict.delete(named.name!);\n }\n }\n\n if (namedOnlyContentDict.size == 0) namedOnlyContentDict = null;\n\n return namedOnlyContentDict;\n }\n set namedOnlyContent(value: Map | null) {\n let existingNamedOnly = this.namedOnlyContent;\n if (existingNamedOnly != null) {\n for (let [key] of existingNamedOnly) {\n this.namedContent.delete(key);\n }\n }\n\n if (value == null) return;\n\n for (let [, val] of value) {\n let named = asINamedContentOrNull(val);\n if (named != null) this.AddToNamedContentOnly(named);\n }\n }\n get countFlags(): number {\n let flags: Container.CountFlags = 0;\n if (this.visitsShouldBeCounted) flags |= Container.CountFlags.Visits;\n if (this.turnIndexShouldBeCounted) flags |= Container.CountFlags.Turns;\n if (this.countingAtStartOnly) flags |= Container.CountFlags.CountStartOnly;\n\n if (flags == Container.CountFlags.CountStartOnly) {\n flags = 0;\n }\n\n return flags;\n }\n set countFlags(value: number) {\n let flag: Container.CountFlags = value;\n if ((flag & Container.CountFlags.Visits) > 0)\n this.visitsShouldBeCounted = true;\n if ((flag & Container.CountFlags.Turns) > 0)\n this.turnIndexShouldBeCounted = true;\n if ((flag & Container.CountFlags.CountStartOnly) > 0)\n this.countingAtStartOnly = true;\n }\n get pathToFirstLeafContent() {\n if (this._pathToFirstLeafContent == null)\n this._pathToFirstLeafContent = this.path.PathByAppendingPath(\n this.internalPathToFirstLeafContent\n );\n\n return this._pathToFirstLeafContent;\n }\n get internalPathToFirstLeafContent() {\n let components: Path.Component[] = [];\n let container: Container = this;\n while (container instanceof Container) {\n if (container.content.length > 0) {\n components.push(new Path.Component(0));\n container = container.content[0] as Container;\n }\n }\n return new Path(components);\n }\n\n public AddContent(contentObjOrList: InkObject | InkObject[]) {\n if (contentObjOrList instanceof Array) {\n let contentList = contentObjOrList as InkObject[];\n\n for (let c of contentList) {\n this.AddContent(c);\n }\n } else {\n let contentObj = contentObjOrList as InkObject;\n\n this._content.push(contentObj);\n\n if (contentObj.parent) {\n throw new Error(\"content is already in \" + contentObj.parent);\n }\n\n contentObj.parent = this;\n\n this.TryAddNamedContent(contentObj);\n }\n }\n public TryAddNamedContent(contentObj: InkObject) {\n let namedContentObj = asINamedContentOrNull(contentObj);\n if (namedContentObj != null && namedContentObj.hasValidName) {\n this.AddToNamedContentOnly(namedContentObj);\n }\n }\n public AddToNamedContentOnly(namedContentObj: INamedContent) {\n Debug.AssertType(\n namedContentObj,\n InkObject,\n \"Can only add Runtime.Objects to a Runtime.Container\"\n );\n let runtimeObj = asOrThrows(namedContentObj, InkObject);\n runtimeObj.parent = this;\n\n if (namedContentObj.name === null)\n return throwNullException(\"namedContentObj.name\");\n this.namedContent.set(namedContentObj.name!, namedContentObj);\n }\n public ContentAtPath(\n path: Path,\n partialPathStart: number = 0,\n partialPathLength: number = -1\n ) {\n if (partialPathLength == -1) partialPathLength = path.length;\n\n let result = new SearchResult();\n result.approximate = false;\n\n let currentContainer: Container | null = this;\n let currentObj: InkObject = this;\n\n for (let i = partialPathStart; i < partialPathLength; ++i) {\n let comp = path.GetComponent(i);\n if (currentContainer == null) {\n result.approximate = true;\n break;\n }\n\n let foundObj: InkObject | null =\n currentContainer.ContentWithPathComponent(comp);\n\n if (foundObj == null) {\n result.approximate = true;\n break;\n }\n\n currentObj = foundObj;\n currentContainer = asOrNull(foundObj, Container);\n }\n\n result.obj = currentObj;\n\n return result;\n }\n public InsertContent(contentObj: InkObject, index: number) {\n this.content.splice(index, 0, contentObj);\n\n if (contentObj.parent) {\n throw new Error(\"content is already in \" + contentObj.parent);\n }\n\n contentObj.parent = this;\n\n this.TryAddNamedContent(contentObj);\n }\n public AddContentsOfContainer(otherContainer: Container) {\n this.content.push(...otherContainer.content);\n\n for (let obj of otherContainer.content) {\n obj.parent = this;\n this.TryAddNamedContent(obj);\n }\n }\n public ContentWithPathComponent(component: Path.Component): InkObject | null {\n if (component.isIndex) {\n if (component.index >= 0 && component.index < this.content.length) {\n return this.content[component.index];\n } else {\n return null;\n }\n } else if (component.isParent) {\n return this.parent;\n } else {\n if (component.name === null) {\n return throwNullException(\"component.name\");\n }\n let foundContent = tryGetValueFromMap(\n this.namedContent,\n component.name,\n null\n );\n if (foundContent.exists) {\n return asOrThrows(foundContent.result, InkObject);\n } else {\n return null;\n }\n }\n }\n public BuildStringOfHierarchy(): string;\n public BuildStringOfHierarchy(\n sb: StringBuilder,\n indentation: number,\n pointedObj: InkObject | null\n ): string;\n public BuildStringOfHierarchy() {\n let sb: StringBuilder;\n if (arguments.length == 0) {\n sb = new StringBuilder();\n this.BuildStringOfHierarchy(sb, 0, null);\n return sb.toString();\n }\n\n sb = arguments[0] as StringBuilder;\n let indentation = arguments[1] as number;\n let pointedObj = arguments[2] as InkObject | null;\n\n function appendIndentation() {\n const spacesPerIndent = 4; // Truly const in the original code\n for (let i = 0; i < spacesPerIndent * indentation; ++i) {\n sb.Append(\" \");\n }\n }\n\n appendIndentation();\n sb.Append(\"[\");\n\n if (this.hasValidName) {\n sb.AppendFormat(\" ({0})\", this.name);\n }\n\n if (this == pointedObj) {\n sb.Append(\" <---\");\n }\n\n sb.AppendLine();\n\n indentation++;\n\n for (let i = 0; i < this.content.length; ++i) {\n let obj = this.content[i];\n\n if (obj instanceof Container) {\n let container = obj as Container;\n\n container.BuildStringOfHierarchy(sb, indentation, pointedObj);\n } else {\n appendIndentation();\n if (obj instanceof StringValue) {\n sb.Append('\"');\n sb.Append(obj.toString().replace(\"\\n\", \"\\\\n\"));\n sb.Append('\"');\n } else {\n sb.Append(obj.toString());\n }\n }\n\n if (i != this.content.length - 1) {\n sb.Append(\",\");\n }\n\n if (!(obj instanceof Container) && obj == pointedObj) {\n sb.Append(\" <---\");\n }\n\n sb.AppendLine();\n }\n\n let onlyNamed: Map = new Map();\n\n for (let [key, value] of this.namedContent) {\n if (this.content.indexOf(asOrThrows(value, InkObject)) >= 0) {\n continue;\n } else {\n onlyNamed.set(key, value);\n }\n }\n\n if (onlyNamed.size > 0) {\n appendIndentation();\n sb.AppendLine(\"-- named: --\");\n\n for (let [, value] of onlyNamed) {\n Debug.AssertType(\n value,\n Container,\n \"Can only print out named Containers\"\n );\n let container = value as Container;\n container.BuildStringOfHierarchy(sb, indentation, pointedObj);\n sb.AppendLine();\n }\n }\n\n indentation--;\n\n appendIndentation();\n sb.Append(\"]\");\n }\n}\n\nexport namespace Container {\n export enum CountFlags {\n Visits = 1,\n Turns = 2,\n CountStartOnly = 4,\n }\n}\n","export enum PushPopType {\n Tunnel = 0,\n Function = 1,\n FunctionEvaluationFromGame = 2,\n}\n","import { InkObject } from \"./Object\";\n\nexport class Glue extends InkObject {\n public toString() {\n return \"Glue\";\n }\n}\n","import { InkObject } from \"./Object\";\n\nexport class ControlCommand extends InkObject {\n private _commandType: ControlCommand.CommandType;\n\n get commandType(): ControlCommand.CommandType {\n return this._commandType;\n }\n\n constructor(\n commandType: ControlCommand.CommandType = ControlCommand.CommandType.NotSet\n ) {\n super();\n this._commandType = commandType;\n }\n\n public Copy() {\n return new ControlCommand(this.commandType);\n }\n public static EvalStart() {\n return new ControlCommand(ControlCommand.CommandType.EvalStart);\n }\n public static EvalOutput() {\n return new ControlCommand(ControlCommand.CommandType.EvalOutput);\n }\n public static EvalEnd() {\n return new ControlCommand(ControlCommand.CommandType.EvalEnd);\n }\n public static Duplicate() {\n return new ControlCommand(ControlCommand.CommandType.Duplicate);\n }\n public static PopEvaluatedValue() {\n return new ControlCommand(ControlCommand.CommandType.PopEvaluatedValue);\n }\n public static PopFunction() {\n return new ControlCommand(ControlCommand.CommandType.PopFunction);\n }\n public static PopTunnel() {\n return new ControlCommand(ControlCommand.CommandType.PopTunnel);\n }\n public static BeginString() {\n return new ControlCommand(ControlCommand.CommandType.BeginString);\n }\n public static EndString() {\n return new ControlCommand(ControlCommand.CommandType.EndString);\n }\n public static NoOp() {\n return new ControlCommand(ControlCommand.CommandType.NoOp);\n }\n public static ChoiceCount() {\n return new ControlCommand(ControlCommand.CommandType.ChoiceCount);\n }\n public static Turns() {\n return new ControlCommand(ControlCommand.CommandType.Turns);\n }\n public static TurnsSince() {\n return new ControlCommand(ControlCommand.CommandType.TurnsSince);\n }\n public static ReadCount() {\n return new ControlCommand(ControlCommand.CommandType.ReadCount);\n }\n public static Random() {\n return new ControlCommand(ControlCommand.CommandType.Random);\n }\n public static SeedRandom() {\n return new ControlCommand(ControlCommand.CommandType.SeedRandom);\n }\n public static VisitIndex() {\n return new ControlCommand(ControlCommand.CommandType.VisitIndex);\n }\n public static SequenceShuffleIndex() {\n return new ControlCommand(ControlCommand.CommandType.SequenceShuffleIndex);\n }\n public static StartThread() {\n return new ControlCommand(ControlCommand.CommandType.StartThread);\n }\n public static Done() {\n return new ControlCommand(ControlCommand.CommandType.Done);\n }\n public static End() {\n return new ControlCommand(ControlCommand.CommandType.End);\n }\n public static ListFromInt() {\n return new ControlCommand(ControlCommand.CommandType.ListFromInt);\n }\n public static ListRange() {\n return new ControlCommand(ControlCommand.CommandType.ListRange);\n }\n public static ListRandom() {\n return new ControlCommand(ControlCommand.CommandType.ListRandom);\n }\n public toString() {\n return this.commandType.toString();\n }\n}\n\nexport namespace ControlCommand {\n export enum CommandType {\n NotSet = -1,\n EvalStart, // 0\n EvalOutput, // 1\n EvalEnd, // 2\n Duplicate, // 3\n PopEvaluatedValue, // 4\n PopFunction, // 5\n PopTunnel, // 6\n BeginString, // 7\n EndString, // 8\n NoOp, // 9\n ChoiceCount, // 10\n Turns, // 11\n TurnsSince, // 12\n Random, // 13\n SeedRandom, // 14\n VisitIndex, // 15\n SequenceShuffleIndex, // 16\n StartThread, // 17\n Done, // 18\n End, // 19\n ListFromInt, // 20\n ListRange, // 21\n ListRandom, // 22\n ReadCount, // 23\n\n TOTAL_VALUES,\n }\n}\n","import { Path } from \"./Path\";\nimport { Container } from \"./Container\";\nimport { InkObject } from \"./Object\";\n\nexport class Pointer {\n public container: Container | null = null;\n public index: number = -1;\n\n constructor();\n constructor(container: Container | null, index: number);\n constructor() {\n if (arguments.length === 2) {\n this.container = arguments[0];\n this.index = arguments[1];\n }\n }\n\n public Resolve(): InkObject | null {\n if (this.index < 0) return this.container;\n if (this.container == null) return null;\n if (this.container.content.length == 0) return this.container;\n if (this.index >= this.container.content.length) return null;\n\n return this.container.content[this.index];\n }\n\n get isNull(): boolean {\n return this.container == null;\n }\n\n get path(): Path | null {\n if (this.isNull) return null;\n\n if (this.index >= 0)\n return this.container!.path.PathByAppendingComponent(\n new Path.Component(this.index)\n );\n else return this.container!.path;\n }\n\n public toString(): string {\n if (!this.container) return \"Ink Pointer (null)\";\n\n return (\n \"Ink Pointer -> \" +\n this.container.path.toString() +\n \" -- index \" +\n this.index\n );\n }\n\n // This method does not exist in the original C# code, but is here to maintain the\n // value semantics of Pointer.\n public copy(): Pointer {\n return new Pointer(this.container, this.index);\n }\n\n public static StartOf(container: Container | null): Pointer {\n return new Pointer(container, 0);\n }\n\n public static get Null(): Pointer {\n return new Pointer(null, -1);\n }\n}\n","import { Path } from \"./Path\";\nimport { PushPopType } from \"./PushPop\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { InkObject } from \"./Object\";\nimport { Pointer } from \"./Pointer\";\nimport { Container } from \"./Container\";\nimport { throwNullException } from \"./NullException\";\n\nexport class Divert extends InkObject {\n get targetPath() {\n if (this._targetPath != null && this._targetPath.isRelative) {\n let targetObj = this.targetPointer.Resolve();\n if (targetObj) {\n this._targetPath = targetObj.path;\n }\n }\n\n return this._targetPath;\n }\n set targetPath(value: Path | null) {\n this._targetPath = value;\n this._targetPointer = Pointer.Null;\n }\n\n public _targetPath: Path | null = null;\n\n get targetPointer() {\n if (this._targetPointer.isNull) {\n let targetObj = this.ResolvePath(this._targetPath).obj;\n\n if (this._targetPath === null)\n return throwNullException(\"this._targetPath\");\n if (this._targetPath.lastComponent === null)\n return throwNullException(\"this._targetPath.lastComponent\");\n\n if (this._targetPath.lastComponent.isIndex) {\n if (targetObj === null) return throwNullException(\"targetObj\");\n this._targetPointer.container =\n targetObj.parent instanceof Container ? targetObj.parent : null;\n this._targetPointer.index = this._targetPath.lastComponent.index;\n } else {\n this._targetPointer = Pointer.StartOf(\n targetObj instanceof Container ? targetObj : null\n );\n }\n }\n\n return this._targetPointer.copy();\n }\n\n public _targetPointer: Pointer = Pointer.Null;\n\n get targetPathString() {\n if (this.targetPath == null) return null;\n\n return this.CompactPathString(this.targetPath);\n }\n set targetPathString(value: string | null) {\n if (value == null) {\n this.targetPath = null;\n } else {\n this.targetPath = new Path(value);\n }\n }\n\n public variableDivertName: string | null = null;\n get hasVariableTarget() {\n return this.variableDivertName != null;\n }\n\n public pushesToStack: boolean = false;\n public stackPushType: PushPopType = 0;\n\n public isExternal: boolean = false;\n public externalArgs: number = 0;\n\n public isConditional: boolean = false;\n\n constructor(stackPushType?: PushPopType) {\n super();\n this.pushesToStack = false;\n\n if (typeof stackPushType !== \"undefined\") {\n this.pushesToStack = true;\n this.stackPushType = stackPushType;\n }\n }\n\n public Equals(obj: Divert | null) {\n let otherDivert = obj;\n if (otherDivert instanceof Divert) {\n if (this.hasVariableTarget == otherDivert.hasVariableTarget) {\n if (this.hasVariableTarget) {\n return this.variableDivertName == otherDivert.variableDivertName;\n } else {\n if (this.targetPath === null)\n return throwNullException(\"this.targetPath\");\n return this.targetPath.Equals(otherDivert.targetPath);\n }\n }\n }\n return false;\n }\n\n public toString() {\n if (this.hasVariableTarget) {\n return \"Divert(variable: \" + this.variableDivertName + \")\";\n } else if (this.targetPath == null) {\n return \"Divert(null)\";\n } else {\n let sb = new StringBuilder();\n\n let targetStr = this.targetPath.toString();\n // int? targetLineNum = DebugLineNumberOfPath (targetPath);\n let targetLineNum = null;\n if (targetLineNum != null) {\n targetStr = \"line \" + targetLineNum;\n }\n\n sb.Append(\"Divert\");\n\n if (this.isConditional) sb.Append(\"?\");\n\n if (this.pushesToStack) {\n if (this.stackPushType == PushPopType.Function) {\n sb.Append(\" function\");\n } else {\n sb.Append(\" tunnel\");\n }\n }\n\n sb.Append(\" -> \");\n sb.Append(this.targetPathString);\n\n sb.Append(\" (\");\n sb.Append(targetStr);\n sb.Append(\")\");\n\n return sb.toString();\n }\n }\n}\n","import { InkObject } from \"./Object\";\nimport { Path } from \"./Path\";\nimport { Container } from \"./Container\";\nimport { throwNullException } from \"./NullException\";\n\nexport class ChoicePoint extends InkObject {\n public _pathOnChoice: Path | null = null;\n public hasCondition: boolean = false;\n public hasStartContent: boolean = false;\n public hasChoiceOnlyContent: boolean = false;\n public isInvisibleDefault: boolean = false;\n public onceOnly: boolean = true;\n\n constructor(onceOnly: boolean = true) {\n super();\n this.onceOnly = onceOnly;\n }\n get pathOnChoice(): Path | null {\n if (this._pathOnChoice != null && this._pathOnChoice.isRelative) {\n let choiceTargetObj = this.choiceTarget;\n if (choiceTargetObj) {\n this._pathOnChoice = choiceTargetObj.path;\n }\n }\n return this._pathOnChoice;\n }\n set pathOnChoice(value: Path | null) {\n this._pathOnChoice = value;\n }\n get choiceTarget(): Container | null {\n if (this._pathOnChoice === null)\n return throwNullException(\"ChoicePoint._pathOnChoice\");\n return this.ResolvePath(this._pathOnChoice).container;\n }\n get pathStringOnChoice(): string {\n if (this.pathOnChoice === null)\n return throwNullException(\"ChoicePoint.pathOnChoice\");\n return this.CompactPathString(this.pathOnChoice);\n }\n set pathStringOnChoice(value: string) {\n this.pathOnChoice = new Path(value);\n }\n get flags(): number {\n let flags = 0;\n if (this.hasCondition) flags |= 1;\n if (this.hasStartContent) flags |= 2;\n if (this.hasChoiceOnlyContent) flags |= 4;\n if (this.isInvisibleDefault) flags |= 8;\n if (this.onceOnly) flags |= 16;\n return flags;\n }\n set flags(value: number) {\n this.hasCondition = (value & 1) > 0;\n this.hasStartContent = (value & 2) > 0;\n this.hasChoiceOnlyContent = (value & 4) > 0;\n this.isInvisibleDefault = (value & 8) > 0;\n this.onceOnly = (value & 16) > 0;\n }\n public toString(): string {\n if (this.pathOnChoice === null)\n return throwNullException(\"ChoicePoint.pathOnChoice\");\n // int? targetLineNum = DebugLineNumberOfPath (pathOnChoice);\n let targetLineNum = null;\n let targetString = this.pathOnChoice.toString();\n\n if (targetLineNum != null) {\n targetString = \" line \" + targetLineNum + \"(\" + targetString + \")\";\n }\n\n return \"Choice: -> \" + targetString;\n }\n}\n","import { InkObject } from \"./Object\";\nimport { Path } from \"./Path\";\n\nexport class VariableReference extends InkObject {\n public name: string | null;\n public pathForCount: Path | null = null;\n\n get containerForCount() {\n if (this.pathForCount === null) return null;\n return this.ResolvePath(this.pathForCount).container;\n }\n get pathStringForCount() {\n if (this.pathForCount === null) return null;\n\n return this.CompactPathString(this.pathForCount);\n }\n set pathStringForCount(value: string | null) {\n if (value === null) this.pathForCount = null;\n else this.pathForCount = new Path(value);\n }\n\n constructor(name: string | null = null) {\n super();\n this.name = name;\n }\n\n public toString() {\n if (this.name != null) {\n return \"var(\" + this.name + \")\";\n } else {\n let pathStr = this.pathStringForCount;\n return \"read_count(\" + pathStr + \")\";\n }\n }\n}\n","import { InkObject } from \"./Object\";\n\nexport class VariableAssignment extends InkObject {\n public readonly variableName: string | null;\n public readonly isNewDeclaration: boolean;\n public isGlobal: boolean;\n\n constructor(variableName: string | null, isNewDeclaration: boolean) {\n super();\n this.variableName = variableName || null;\n this.isNewDeclaration = !!isNewDeclaration;\n this.isGlobal = false;\n }\n\n public toString(): string {\n return \"VarAssign to \" + this.variableName;\n }\n}\n","import { InkObject } from \"./Object\";\n\nexport class Void extends InkObject {}\n","import { Value, ValueType, IntValue, ListValue, BoolValue } from \"./Value\";\nimport { StoryException } from \"./StoryException\";\nimport { Void } from \"./Void\";\nimport { Path } from \"./Path\";\nimport { InkList, InkListItem } from \"./InkList\";\nimport { InkObject } from \"./Object\";\nimport { asOrNull, asOrThrows, asBooleanOrThrows } from \"./TypeAssertion\";\nimport { throwNullException } from \"./NullException\";\n\ntype BinaryOp = (left: T, right: T) => any;\ntype UnaryOp = (val: T) => any;\n\nexport class NativeFunctionCall extends InkObject {\n public static readonly Add: string = \"+\";\n public static readonly Subtract: string = \"-\";\n public static readonly Divide: string = \"/\";\n public static readonly Multiply: string = \"*\";\n public static readonly Mod: string = \"%\";\n public static readonly Negate: string = \"_\";\n public static readonly Equal: string = \"==\";\n public static readonly Greater: string = \">\";\n public static readonly Less: string = \"<\";\n public static readonly GreaterThanOrEquals: string = \">=\";\n public static readonly LessThanOrEquals: string = \"<=\";\n public static readonly NotEquals: string = \"!=\";\n public static readonly Not: string = \"!\";\n public static readonly And: string = \"&&\";\n public static readonly Or: string = \"||\";\n public static readonly Min: string = \"MIN\";\n public static readonly Max: string = \"MAX\";\n public static readonly Pow: string = \"POW\";\n public static readonly Floor: string = \"FLOOR\";\n public static readonly Ceiling: string = \"CEILING\";\n public static readonly Int: string = \"INT\";\n public static readonly Float: string = \"FLOAT\";\n public static readonly Has: string = \"?\";\n public static readonly Hasnt: string = \"!?\";\n public static readonly Intersect: string = \"^\";\n public static readonly ListMin: string = \"LIST_MIN\";\n public static readonly ListMax: string = \"LIST_MAX\";\n public static readonly All: string = \"LIST_ALL\";\n public static readonly Count: string = \"LIST_COUNT\";\n public static readonly ValueOfList: string = \"LIST_VALUE\";\n public static readonly Invert: string = \"LIST_INVERT\";\n\n public static CallWithName(functionName: string) {\n return new NativeFunctionCall(functionName);\n }\n\n public static CallExistsWithName(functionName: string) {\n this.GenerateNativeFunctionsIfNecessary();\n return this._nativeFunctions!.get(functionName);\n }\n\n get name() {\n if (this._name === null)\n return throwNullException(\"NativeFunctionCall._name\");\n return this._name;\n }\n set name(value: string) {\n this._name = value;\n if (!this._isPrototype) {\n if (NativeFunctionCall._nativeFunctions === null)\n throwNullException(\"NativeFunctionCall._nativeFunctions\");\n else\n this._prototype =\n NativeFunctionCall._nativeFunctions.get(this._name) || null;\n }\n }\n public _name: string | null = null;\n\n get numberOfParameters() {\n if (this._prototype) {\n return this._prototype.numberOfParameters;\n } else {\n return this._numberOfParameters;\n }\n }\n set numberOfParameters(value: number) {\n this._numberOfParameters = value;\n }\n public _numberOfParameters: number = 0;\n\n public Call(parameters: InkObject[]): InkObject | null {\n if (this._prototype) {\n return this._prototype.Call(parameters);\n }\n\n if (this.numberOfParameters != parameters.length) {\n throw new Error(\"Unexpected number of parameters\");\n }\n\n let hasList = false;\n for (let p of parameters) {\n if (p instanceof Void)\n throw new StoryException(\n 'Attempting to perform operation on a void value. Did you forget to \"return\" a value from a function you called here?'\n );\n if (p instanceof ListValue) hasList = true;\n }\n\n if (parameters.length == 2 && hasList) {\n return this.CallBinaryListOperation(parameters);\n }\n\n let coercedParams = this.CoerceValuesToSingleType(parameters);\n let coercedType = coercedParams[0].valueType;\n\n if (coercedType == ValueType.Int) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.Float) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.String) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.DivertTarget) {\n return this.CallType(coercedParams);\n } else if (coercedType == ValueType.List) {\n return this.CallType(coercedParams);\n }\n\n return null;\n }\n\n public CallType(parametersOfSingleType: Array>) {\n let param1 = asOrThrows(parametersOfSingleType[0], Value);\n let valType = param1.valueType;\n\n let val1 = param1 as Value;\n\n let paramCount = parametersOfSingleType.length;\n\n if (paramCount == 2 || paramCount == 1) {\n if (this._operationFuncs === null)\n return throwNullException(\"NativeFunctionCall._operationFuncs\");\n let opForTypeObj = this._operationFuncs.get(valType);\n if (!opForTypeObj) {\n const key = ValueType[valType];\n throw new StoryException(\n \"Cannot perform operation \" + this.name + \" on \" + key\n );\n }\n\n if (paramCount == 2) {\n let param2 = asOrThrows(parametersOfSingleType[1], Value);\n\n let val2 = param2 as Value;\n\n let opForType = opForTypeObj as BinaryOp;\n\n if (val1.value === null || val2.value === null)\n return throwNullException(\"NativeFunctionCall.Call BinaryOp values\");\n let resultVal = opForType(val1.value, val2.value);\n\n return Value.Create(resultVal);\n } else {\n let opForType = opForTypeObj as UnaryOp;\n\n if (val1.value === null)\n return throwNullException(\"NativeFunctionCall.Call UnaryOp value\");\n let resultVal = opForType(val1.value);\n\n // This code is different from upstream. Since JavaScript treats\n // integers and floats as the same numbers, it's impossible\n // to force an number to be either an integer or a float.\n //\n // It can be useful to force a specific number type\n // (especially for divisions), so the result of INT() & FLOAT()\n // is coerced to the the proper value type.\n //\n // Note that we also force all other unary operation to\n // return the same value type, although this is only\n // meaningful for numbers. See `Value.Create`.\n if (this.name === NativeFunctionCall.Int) {\n return Value.Create(resultVal, ValueType.Int);\n } else if (this.name === NativeFunctionCall.Float) {\n return Value.Create(resultVal, ValueType.Float);\n } else {\n return Value.Create(resultVal, param1.valueType);\n }\n }\n } else {\n throw new Error(\n \"Unexpected number of parameters to NativeFunctionCall: \" +\n parametersOfSingleType.length\n );\n }\n }\n\n public CallBinaryListOperation(parameters: InkObject[]) {\n if (\n (this.name == \"+\" || this.name == \"-\") &&\n parameters[0] instanceof ListValue &&\n parameters[1] instanceof IntValue\n )\n return this.CallListIncrementOperation(parameters);\n\n let v1 = asOrThrows(parameters[0], Value);\n let v2 = asOrThrows(parameters[1], Value);\n\n if (\n (this.name == \"&&\" || this.name == \"||\") &&\n (v1.valueType != ValueType.List || v2.valueType != ValueType.List)\n ) {\n if (this._operationFuncs === null)\n return throwNullException(\"NativeFunctionCall._operationFuncs\");\n let op = this._operationFuncs.get(ValueType.Int) as BinaryOp;\n if (op === null)\n return throwNullException(\n \"NativeFunctionCall.CallBinaryListOperation op\"\n );\n let result = asBooleanOrThrows(\n op(v1.isTruthy ? 1 : 0, v2.isTruthy ? 1 : 0)\n );\n return new BoolValue(result);\n }\n\n if (v1.valueType == ValueType.List && v2.valueType == ValueType.List)\n return this.CallType([v1, v2]);\n\n throw new StoryException(\n \"Can not call use \" +\n this.name +\n \" operation on \" +\n ValueType[v1.valueType] +\n \" and \" +\n ValueType[v2.valueType]\n );\n }\n\n public CallListIncrementOperation(listIntParams: InkObject[]) {\n let listVal = asOrThrows(listIntParams[0], ListValue);\n let intVal = asOrThrows(listIntParams[1], IntValue);\n\n let resultInkList = new InkList();\n\n if (listVal.value === null)\n return throwNullException(\n \"NativeFunctionCall.CallListIncrementOperation listVal.value\"\n );\n for (let [listItemKey, listItemValue] of listVal.value) {\n let listItem = InkListItem.fromSerializedKey(listItemKey);\n\n if (this._operationFuncs === null)\n return throwNullException(\"NativeFunctionCall._operationFuncs\");\n let intOp = this._operationFuncs.get(ValueType.Int) as BinaryOp;\n\n if (intVal.value === null)\n return throwNullException(\n \"NativeFunctionCall.CallListIncrementOperation intVal.value\"\n );\n let targetInt = intOp(listItemValue, intVal.value);\n\n let itemOrigin = null;\n if (listVal.value.origins === null)\n return throwNullException(\n \"NativeFunctionCall.CallListIncrementOperation listVal.value.origins\"\n );\n for (let origin of listVal.value.origins) {\n if (origin.name == listItem.originName) {\n itemOrigin = origin;\n break;\n }\n }\n if (itemOrigin != null) {\n let incrementedItem = itemOrigin.TryGetItemWithValue(\n targetInt,\n InkListItem.Null\n );\n if (incrementedItem.exists)\n resultInkList.Add(incrementedItem.result, targetInt);\n }\n }\n\n return new ListValue(resultInkList);\n }\n\n public CoerceValuesToSingleType(parametersIn: InkObject[]) {\n let valType = ValueType.Int;\n\n let specialCaseList: null | ListValue = null;\n\n for (let obj of parametersIn) {\n let val = asOrThrows(obj, Value);\n if (val.valueType > valType) {\n valType = val.valueType;\n }\n\n if (val.valueType == ValueType.List) {\n specialCaseList = asOrNull(val, ListValue);\n }\n }\n\n let parametersOut = [];\n\n if (ValueType[valType] == ValueType[ValueType.List]) {\n for (let inkObjectVal of parametersIn) {\n let val = asOrThrows(inkObjectVal, Value);\n if (val.valueType == ValueType.List) {\n parametersOut.push(val);\n } else if (val.valueType == ValueType.Int) {\n let intVal = parseInt(val.valueObject);\n\n specialCaseList = asOrThrows(specialCaseList, ListValue);\n if (specialCaseList.value === null)\n return throwNullException(\n \"NativeFunctionCall.CoerceValuesToSingleType specialCaseList.value\"\n );\n let list = specialCaseList.value.originOfMaxItem;\n\n if (list === null)\n return throwNullException(\n \"NativeFunctionCall.CoerceValuesToSingleType list\"\n );\n let item = list.TryGetItemWithValue(intVal, InkListItem.Null);\n if (item.exists) {\n let castedValue = new ListValue(item.result, intVal);\n parametersOut.push(castedValue);\n } else\n throw new StoryException(\n \"Could not find List item with the value \" +\n intVal +\n \" in \" +\n list.name\n );\n } else {\n const key = ValueType[val.valueType];\n throw new StoryException(\n \"Cannot mix Lists and \" + key + \" values in this operation\"\n );\n }\n }\n } else {\n for (let inkObjectVal of parametersIn) {\n let val = asOrThrows(inkObjectVal, Value);\n let castedValue = val.Cast(valType);\n parametersOut.push(castedValue);\n }\n }\n\n return parametersOut;\n }\n\n constructor(name: string);\n constructor(name: string, numberOfParameters: number);\n constructor();\n constructor() {\n super();\n\n if (arguments.length === 0) {\n NativeFunctionCall.GenerateNativeFunctionsIfNecessary();\n } else if (arguments.length === 1) {\n let name = arguments[0];\n NativeFunctionCall.GenerateNativeFunctionsIfNecessary();\n this.name = name;\n } else if (arguments.length === 2) {\n let name = arguments[0];\n let numberOfParameters = arguments[1];\n\n this._isPrototype = true;\n this.name = name;\n this.numberOfParameters = numberOfParameters;\n }\n }\n\n public static Identity(t: T): any {\n return t;\n }\n\n public static GenerateNativeFunctionsIfNecessary() {\n if (this._nativeFunctions == null) {\n this._nativeFunctions = new Map();\n\n // Int operations\n this.AddIntBinaryOp(this.Add, (x, y) => x + y);\n this.AddIntBinaryOp(this.Subtract, (x, y) => x - y);\n this.AddIntBinaryOp(this.Multiply, (x, y) => x * y);\n this.AddIntBinaryOp(this.Divide, (x, y) => Math.floor(x / y));\n this.AddIntBinaryOp(this.Mod, (x, y) => x % y);\n this.AddIntUnaryOp(this.Negate, (x) => -x);\n\n this.AddIntBinaryOp(this.Equal, (x, y) => x == y);\n this.AddIntBinaryOp(this.Greater, (x, y) => x > y);\n this.AddIntBinaryOp(this.Less, (x, y) => x < y);\n this.AddIntBinaryOp(this.GreaterThanOrEquals, (x, y) => x >= y);\n this.AddIntBinaryOp(this.LessThanOrEquals, (x, y) => x <= y);\n this.AddIntBinaryOp(this.NotEquals, (x, y) => x != y);\n this.AddIntUnaryOp(this.Not, (x) => x == 0);\n\n this.AddIntBinaryOp(this.And, (x, y) => x != 0 && y != 0);\n this.AddIntBinaryOp(this.Or, (x, y) => x != 0 || y != 0);\n\n this.AddIntBinaryOp(this.Max, (x, y) => Math.max(x, y));\n this.AddIntBinaryOp(this.Min, (x, y) => Math.min(x, y));\n\n this.AddIntBinaryOp(this.Pow, (x, y) => Math.pow(x, y));\n this.AddIntUnaryOp(this.Floor, NativeFunctionCall.Identity);\n this.AddIntUnaryOp(this.Ceiling, NativeFunctionCall.Identity);\n this.AddIntUnaryOp(this.Int, NativeFunctionCall.Identity);\n this.AddIntUnaryOp(this.Float, (x) => x);\n\n // Float operations\n this.AddFloatBinaryOp(this.Add, (x, y) => x + y);\n this.AddFloatBinaryOp(this.Subtract, (x, y) => x - y);\n this.AddFloatBinaryOp(this.Multiply, (x, y) => x * y);\n this.AddFloatBinaryOp(this.Divide, (x, y) => x / y);\n this.AddFloatBinaryOp(this.Mod, (x, y) => x % y);\n this.AddFloatUnaryOp(this.Negate, (x) => -x);\n\n this.AddFloatBinaryOp(this.Equal, (x, y) => x == y);\n this.AddFloatBinaryOp(this.Greater, (x, y) => x > y);\n this.AddFloatBinaryOp(this.Less, (x, y) => x < y);\n this.AddFloatBinaryOp(this.GreaterThanOrEquals, (x, y) => x >= y);\n this.AddFloatBinaryOp(this.LessThanOrEquals, (x, y) => x <= y);\n this.AddFloatBinaryOp(this.NotEquals, (x, y) => x != y);\n this.AddFloatUnaryOp(this.Not, (x) => x == 0.0);\n\n this.AddFloatBinaryOp(this.And, (x, y) => x != 0.0 && y != 0.0);\n this.AddFloatBinaryOp(this.Or, (x, y) => x != 0.0 || y != 0.0);\n\n this.AddFloatBinaryOp(this.Max, (x, y) => Math.max(x, y));\n this.AddFloatBinaryOp(this.Min, (x, y) => Math.min(x, y));\n\n this.AddFloatBinaryOp(this.Pow, (x, y) => Math.pow(x, y));\n this.AddFloatUnaryOp(this.Floor, (x) => Math.floor(x));\n this.AddFloatUnaryOp(this.Ceiling, (x) => Math.ceil(x));\n this.AddFloatUnaryOp(this.Int, (x) => Math.floor(x));\n this.AddFloatUnaryOp(this.Float, NativeFunctionCall.Identity);\n\n // String operations\n this.AddStringBinaryOp(this.Add, (x, y) => x + y); // concat\n this.AddStringBinaryOp(this.Equal, (x, y) => x === y);\n this.AddStringBinaryOp(this.NotEquals, (x, y) => !(x === y));\n this.AddStringBinaryOp(this.Has, (x, y) => x.includes(y));\n this.AddStringBinaryOp(this.Hasnt, (x, y) => !x.includes(y));\n\n this.AddListBinaryOp(this.Add, (x, y) => x.Union(y));\n this.AddListBinaryOp(this.Subtract, (x, y) => x.Without(y));\n this.AddListBinaryOp(this.Has, (x, y) => x.Contains(y));\n this.AddListBinaryOp(this.Hasnt, (x, y) => !x.Contains(y));\n this.AddListBinaryOp(this.Intersect, (x, y) => x.Intersect(y));\n\n this.AddListBinaryOp(this.Equal, (x, y) => x.Equals(y));\n this.AddListBinaryOp(this.Greater, (x, y) => x.GreaterThan(y));\n this.AddListBinaryOp(this.Less, (x, y) => x.LessThan(y));\n this.AddListBinaryOp(this.GreaterThanOrEquals, (x, y) =>\n x.GreaterThanOrEquals(y)\n );\n this.AddListBinaryOp(this.LessThanOrEquals, (x, y) =>\n x.LessThanOrEquals(y)\n );\n this.AddListBinaryOp(this.NotEquals, (x, y) => !x.Equals(y));\n\n this.AddListBinaryOp(this.And, (x, y) => x.Count > 0 && y.Count > 0);\n this.AddListBinaryOp(this.Or, (x, y) => x.Count > 0 || y.Count > 0);\n\n this.AddListUnaryOp(this.Not, (x) => (x.Count == 0 ? 1 : 0));\n\n this.AddListUnaryOp(this.Invert, (x) => x.inverse);\n this.AddListUnaryOp(this.All, (x) => x.all);\n this.AddListUnaryOp(this.ListMin, (x) => x.MinAsList());\n this.AddListUnaryOp(this.ListMax, (x) => x.MaxAsList());\n this.AddListUnaryOp(this.Count, (x) => x.Count);\n this.AddListUnaryOp(this.ValueOfList, (x) => x.maxItem.Value);\n\n let divertTargetsEqual = (d1: Path, d2: Path) => d1.Equals(d2);\n let divertTargetsNotEqual = (d1: Path, d2: Path) => !d1.Equals(d2);\n this.AddOpToNativeFunc(\n this.Equal,\n 2,\n ValueType.DivertTarget,\n divertTargetsEqual\n );\n this.AddOpToNativeFunc(\n this.NotEquals,\n 2,\n ValueType.DivertTarget,\n divertTargetsNotEqual\n );\n }\n }\n\n public AddOpFuncForType(\n valType: ValueType,\n op: UnaryOp | BinaryOp\n ): void {\n if (this._operationFuncs == null) {\n this._operationFuncs = new Map();\n }\n\n this._operationFuncs.set(valType, op);\n }\n\n public static AddOpToNativeFunc(\n name: string,\n args: number,\n valType: ValueType,\n op: UnaryOp | BinaryOp\n ): void {\n if (this._nativeFunctions === null)\n return throwNullException(\"NativeFunctionCall._nativeFunctions\");\n let nativeFunc = this._nativeFunctions.get(name);\n if (!nativeFunc) {\n nativeFunc = new NativeFunctionCall(name, args);\n this._nativeFunctions.set(name, nativeFunc);\n }\n\n nativeFunc.AddOpFuncForType(valType, op);\n }\n\n public static AddIntBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.Int, op);\n }\n public static AddIntUnaryOp(name: string, op: UnaryOp) {\n this.AddOpToNativeFunc(name, 1, ValueType.Int, op);\n }\n\n public static AddFloatBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.Float, op);\n }\n public static AddFloatUnaryOp(name: string, op: UnaryOp) {\n this.AddOpToNativeFunc(name, 1, ValueType.Float, op);\n }\n\n public static AddStringBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.String, op);\n }\n\n public static AddListBinaryOp(name: string, op: BinaryOp) {\n this.AddOpToNativeFunc(name, 2, ValueType.List, op);\n }\n public static AddListUnaryOp(name: string, op: UnaryOp) {\n this.AddOpToNativeFunc(name, 1, ValueType.List, op);\n }\n\n public toString() {\n return 'Native \"' + this.name + '\"';\n }\n\n public _prototype: NativeFunctionCall | null = null;\n public _isPrototype: boolean = false;\n public _operationFuncs: Map | UnaryOp> | null =\n null;\n public static _nativeFunctions: Map | null = null;\n}\n","import { InkObject } from \"./Object\";\n\nexport class Tag extends InkObject {\n public readonly text: string;\n\n constructor(tagText: string) {\n super();\n this.text = tagText.toString() || \"\";\n }\n\n public toString(): string {\n return \"# \" + this.text;\n }\n}\n","import { Path } from \"./Path\";\nimport { CallStack } from \"./CallStack\";\nimport { throwNullException } from \"./NullException\";\nimport { InkObject } from \"./Object\";\n\nexport class Choice extends InkObject {\n public text: string = \"\";\n public index: number = 0;\n public threadAtGeneration: CallStack.Thread | null = null;\n public sourcePath: string = \"\";\n public targetPath: Path | null = null;\n public isInvisibleDefault: boolean = false;\n public originalThreadIndex: number = 0;\n\n get pathStringOnChoice(): string {\n if (this.targetPath === null)\n return throwNullException(\"Choice.targetPath\");\n return this.targetPath.toString();\n }\n set pathStringOnChoice(value: string) {\n this.targetPath = new Path(value);\n }\n}\n","import { InkListItem, SerializedInkListItem } from \"./InkList\";\nimport { TryGetResult } from \"./TryGetResult\";\n\nexport class ListDefinition {\n public _name: string;\n public _items: Map | null;\n public _itemNameToValues: Map;\n\n constructor(name: string, items: Map | null) {\n this._name = name || \"\";\n this._items = null;\n this._itemNameToValues = items || new Map();\n }\n get name() {\n return this._name;\n }\n get items() {\n if (this._items == null) {\n this._items = new Map();\n for (let [key, value] of this._itemNameToValues) {\n let item = new InkListItem(this.name, key);\n this._items.set(item.serialized(), value);\n }\n }\n\n return this._items;\n }\n\n public ValueForItem(item: InkListItem) {\n if (!item.itemName) return 0;\n\n let intVal = this._itemNameToValues.get(item.itemName);\n if (typeof intVal !== \"undefined\") return intVal;\n else return 0;\n }\n public ContainsItem(item: InkListItem) {\n if (!item.itemName) return false;\n if (item.originName != this.name) return false;\n\n return this._itemNameToValues.has(item.itemName);\n }\n public ContainsItemWithName(itemName: string) {\n return this._itemNameToValues.has(itemName);\n }\n public TryGetItemWithValue(\n val: number,\n /* out */ item: InkListItem\n ): TryGetResult {\n for (let [key, value] of this._itemNameToValues) {\n if (value == val) {\n item = new InkListItem(this.name, key);\n return { result: item, exists: true };\n }\n }\n\n item = InkListItem.Null;\n return { result: item, exists: false };\n }\n public TryGetValueForItem(\n item: InkListItem,\n /* out */ intVal: number\n ): TryGetResult {\n if (!item.itemName) return { result: 0, exists: false };\n let value = this._itemNameToValues.get(item.itemName);\n\n if (!value) return { result: 0, exists: false };\n return { result: value, exists: true };\n }\n}\n","import { InkListItem } from \"./InkList\";\nimport { ListValue } from \"./Value\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { TryGetResult } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\n\nexport class ListDefinitionsOrigin {\n protected _lists: Map;\n protected _allUnambiguousListValueCache: Map;\n\n constructor(lists: ListDefinition[]) {\n this._lists = new Map();\n this._allUnambiguousListValueCache = new Map();\n\n for (let list of lists) {\n this._lists.set(list.name, list);\n\n for (let [key, val] of list.items) {\n let item = InkListItem.fromSerializedKey(key);\n let listValue = new ListValue(item, val);\n\n if (!item.itemName) {\n throw new Error(\"item.itemName is null or undefined.\");\n }\n\n this._allUnambiguousListValueCache.set(item.itemName, listValue);\n this._allUnambiguousListValueCache.set(item.fullName, listValue);\n }\n }\n }\n get lists(): ListDefinition[] {\n let listOfLists: ListDefinition[] = [];\n\n for (let [, value] of this._lists) {\n listOfLists.push(value);\n }\n\n return listOfLists;\n }\n public TryListGetDefinition(\n name: string | null,\n /* out */ def: ListDefinition | null\n ): TryGetResult {\n if (name === null) {\n return { result: def, exists: false };\n }\n // initially, this function returns a boolean and the second parameter is an out.\n let definition = this._lists.get(name);\n if (!definition) return { result: def, exists: false };\n\n return { result: definition, exists: true };\n }\n public FindSingleItemListWithName(name: string | null) {\n if (name === null) {\n return throwNullException(\"name\");\n }\n let val = this._allUnambiguousListValueCache.get(name);\n\n if (typeof val !== \"undefined\") {\n return val;\n }\n\n return null;\n }\n}\n","import { Container } from \"./Container\";\nimport {\n Value,\n IntValue,\n FloatValue,\n StringValue,\n DivertTargetValue,\n VariablePointerValue,\n ListValue,\n BoolValue,\n} from \"./Value\";\nimport { Glue } from \"./Glue\";\nimport { ControlCommand } from \"./ControlCommand\";\nimport { PushPopType } from \"./PushPop\";\nimport { Divert } from \"./Divert\";\nimport { ChoicePoint } from \"./ChoicePoint\";\nimport { VariableReference } from \"./VariableReference\";\nimport { VariableAssignment } from \"./VariableAssignment\";\nimport { NativeFunctionCall } from \"./NativeFunctionCall\";\nimport { Void } from \"./Void\";\nimport { Tag } from \"./Tag\";\nimport { Path } from \"./Path\";\nimport { Choice } from \"./Choice\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { ListDefinitionsOrigin } from \"./ListDefinitionsOrigin\";\nimport { InkListItem, InkList } from \"./InkList\";\nimport { InkObject } from \"./Object\";\nimport { asOrNull } from \"./TypeAssertion\";\nimport { throwNullException } from \"./NullException\";\nimport { SimpleJson } from \"./SimpleJson\";\n\nexport class JsonSerialisation {\n public static JArrayToRuntimeObjList(\n jArray: any[],\n skipLast: boolean = false\n ) {\n let count = jArray.length;\n if (skipLast) count--;\n\n let list: InkObject[] = [];\n\n for (let i = 0; i < count; i++) {\n let jTok = jArray[i];\n let runtimeObj = this.JTokenToRuntimeObject(jTok);\n if (runtimeObj === null) {\n return throwNullException(\"runtimeObj\");\n }\n list.push(runtimeObj);\n }\n\n return list;\n }\n\n public static WriteDictionaryRuntimeObjs(\n writer: SimpleJson.Writer,\n dictionary: Map\n ) {\n writer.WriteObjectStart();\n for (let [key, value] of dictionary) {\n writer.WritePropertyStart(key);\n this.WriteRuntimeObject(writer, value);\n writer.WritePropertyEnd();\n }\n writer.WriteObjectEnd();\n }\n\n public static WriteListRuntimeObjs(\n writer: SimpleJson.Writer,\n list: InkObject[]\n ) {\n writer.WriteArrayStart();\n for (let value of list) {\n this.WriteRuntimeObject(writer, value);\n }\n writer.WriteArrayEnd();\n }\n\n public static WriteIntDictionary(\n writer: SimpleJson.Writer,\n dict: Map\n ) {\n writer.WriteObjectStart();\n for (let [key, value] of dict) {\n writer.WriteIntProperty(key, value);\n }\n writer.WriteObjectEnd();\n }\n\n public static WriteRuntimeObject(\n writer: SimpleJson.Writer,\n obj: InkObject\n ): void {\n let container = asOrNull(obj, Container);\n if (container) {\n this.WriteRuntimeContainer(writer, container);\n return;\n }\n\n let divert = asOrNull(obj, Divert);\n if (divert) {\n let divTypeKey = \"->\";\n if (divert.isExternal) {\n divTypeKey = \"x()\";\n } else if (divert.pushesToStack) {\n if (divert.stackPushType == PushPopType.Function) {\n divTypeKey = \"f()\";\n } else if (divert.stackPushType == PushPopType.Tunnel) {\n divTypeKey = \"->t->\";\n }\n }\n\n let targetStr;\n if (divert.hasVariableTarget) {\n targetStr = divert.variableDivertName;\n } else {\n targetStr = divert.targetPathString;\n }\n\n writer.WriteObjectStart();\n writer.WriteProperty(divTypeKey, targetStr);\n\n if (divert.hasVariableTarget) {\n writer.WriteProperty(\"var\", true);\n }\n\n if (divert.isConditional) {\n writer.WriteProperty(\"c\", true);\n }\n\n if (divert.externalArgs > 0) {\n writer.WriteIntProperty(\"exArgs\", divert.externalArgs);\n }\n\n writer.WriteObjectEnd();\n return;\n }\n\n let choicePoint = asOrNull(obj, ChoicePoint);\n if (choicePoint) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"*\", choicePoint.pathStringOnChoice);\n writer.WriteIntProperty(\"flg\", choicePoint.flags);\n writer.WriteObjectEnd();\n return;\n }\n\n let boolVal = asOrNull(obj, BoolValue);\n if (boolVal) {\n writer.WriteBool(boolVal.value);\n return;\n }\n\n let intVal = asOrNull(obj, IntValue);\n if (intVal) {\n writer.WriteInt(intVal.value);\n return;\n }\n\n let floatVal = asOrNull(obj, FloatValue);\n if (floatVal) {\n writer.WriteFloat(floatVal.value);\n return;\n }\n\n let strVal = asOrNull(obj, StringValue);\n if (strVal) {\n if (strVal.isNewline) {\n writer.Write(\"\\n\", false);\n } else {\n writer.WriteStringStart();\n writer.WriteStringInner(\"^\");\n writer.WriteStringInner(strVal.value);\n writer.WriteStringEnd();\n }\n return;\n }\n\n let listVal = asOrNull(obj, ListValue);\n if (listVal) {\n this.WriteInkList(writer, listVal);\n return;\n }\n\n let divTargetVal = asOrNull(obj, DivertTargetValue);\n if (divTargetVal) {\n writer.WriteObjectStart();\n if (divTargetVal.value === null) {\n return throwNullException(\"divTargetVal.value\");\n }\n writer.WriteProperty(\"^->\", divTargetVal.value.componentsString);\n writer.WriteObjectEnd();\n\n return;\n }\n\n let varPtrVal = asOrNull(obj, VariablePointerValue);\n if (varPtrVal) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"^var\", varPtrVal.value);\n writer.WriteIntProperty(\"ci\", varPtrVal.contextIndex);\n writer.WriteObjectEnd();\n return;\n }\n\n let glue = asOrNull(obj, Glue);\n if (glue) {\n writer.Write(\"<>\");\n return;\n }\n\n let controlCmd = asOrNull(obj, ControlCommand);\n if (controlCmd) {\n writer.Write(\n JsonSerialisation._controlCommandNames[controlCmd.commandType]\n );\n return;\n }\n\n let nativeFunc = asOrNull(obj, NativeFunctionCall);\n if (nativeFunc) {\n let name = nativeFunc.name;\n\n if (name == \"^\") name = \"L^\";\n\n writer.Write(name);\n return;\n }\n\n let varRef = asOrNull(obj, VariableReference);\n if (varRef) {\n writer.WriteObjectStart();\n let readCountPath = varRef.pathStringForCount;\n if (readCountPath != null) {\n writer.WriteProperty(\"CNT?\", readCountPath);\n } else {\n writer.WriteProperty(\"VAR?\", varRef.name);\n }\n\n writer.WriteObjectEnd();\n return;\n }\n\n let varAss = asOrNull(obj, VariableAssignment);\n if (varAss) {\n writer.WriteObjectStart();\n\n let key = varAss.isGlobal ? \"VAR=\" : \"temp=\";\n writer.WriteProperty(key, varAss.variableName);\n\n // Reassignment?\n if (!varAss.isNewDeclaration) writer.WriteProperty(\"re\", true);\n\n writer.WriteObjectEnd();\n\n return;\n }\n\n let voidObj = asOrNull(obj, Void);\n if (voidObj) {\n writer.Write(\"void\");\n return;\n }\n\n let tag = asOrNull(obj, Tag);\n if (tag) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"#\", tag.text);\n writer.WriteObjectEnd();\n return;\n }\n\n let choice = asOrNull(obj, Choice);\n if (choice) {\n this.WriteChoice(writer, choice);\n return;\n }\n\n throw new Error(\"Failed to convert runtime object to Json token: \" + obj);\n }\n\n public static JObjectToDictionaryRuntimeObjs(jObject: Record) {\n let dict: Map = new Map();\n\n for (let key in jObject) {\n if (jObject.hasOwnProperty(key)) {\n let inkObject = this.JTokenToRuntimeObject(jObject[key]);\n if (inkObject === null) {\n return throwNullException(\"inkObject\");\n }\n dict.set(key, inkObject);\n }\n }\n\n return dict;\n }\n\n public static JObjectToIntDictionary(jObject: Record) {\n let dict: Map = new Map();\n for (let key in jObject) {\n if (jObject.hasOwnProperty(key)) {\n dict.set(key, parseInt(jObject[key]));\n }\n }\n return dict;\n }\n\n public static JTokenToRuntimeObject(token: any): InkObject | null {\n if (\n (typeof token === \"number\" && !isNaN(token)) ||\n typeof token === \"boolean\"\n ) {\n return Value.Create(token);\n }\n\n if (typeof token === \"string\") {\n let str = token.toString();\n\n // String value\n let firstChar = str[0];\n if (firstChar == \"^\") return new StringValue(str.substring(1));\n else if (firstChar == \"\\n\" && str.length == 1)\n return new StringValue(\"\\n\");\n\n // Glue\n if (str == \"<>\") return new Glue();\n\n // Control commands (would looking up in a hash set be faster?)\n for (let i = 0; i < JsonSerialisation._controlCommandNames.length; ++i) {\n let cmdName = JsonSerialisation._controlCommandNames[i];\n if (str == cmdName) {\n return new ControlCommand(i);\n }\n }\n\n // Native functions\n if (str == \"L^\") str = \"^\";\n if (NativeFunctionCall.CallExistsWithName(str))\n return NativeFunctionCall.CallWithName(str);\n\n // Pop\n if (str == \"->->\") return ControlCommand.PopTunnel();\n else if (str == \"~ret\") return ControlCommand.PopFunction();\n\n // Void\n if (str == \"void\") return new Void();\n }\n\n if (typeof token === \"object\" && !Array.isArray(token)) {\n let obj = token as Record;\n let propValue;\n\n // Divert target value to path\n if (obj[\"^->\"]) {\n propValue = obj[\"^->\"];\n return new DivertTargetValue(new Path(propValue.toString()));\n }\n\n // VariablePointerValue\n if (obj[\"^var\"]) {\n propValue = obj[\"^var\"];\n let varPtr = new VariablePointerValue(propValue.toString());\n if (\"ci\" in obj) {\n propValue = obj[\"ci\"];\n varPtr.contextIndex = parseInt(propValue);\n }\n return varPtr;\n }\n\n // Divert\n let isDivert = false;\n let pushesToStack = false;\n let divPushType = PushPopType.Function;\n let external = false;\n if ((propValue = obj[\"->\"])) {\n isDivert = true;\n } else if ((propValue = obj[\"f()\"])) {\n isDivert = true;\n pushesToStack = true;\n divPushType = PushPopType.Function;\n } else if ((propValue = obj[\"->t->\"])) {\n isDivert = true;\n pushesToStack = true;\n divPushType = PushPopType.Tunnel;\n } else if ((propValue = obj[\"x()\"])) {\n isDivert = true;\n external = true;\n pushesToStack = false;\n divPushType = PushPopType.Function;\n }\n\n if (isDivert) {\n let divert = new Divert();\n divert.pushesToStack = pushesToStack;\n divert.stackPushType = divPushType;\n divert.isExternal = external;\n\n let target = propValue.toString();\n\n if ((propValue = obj[\"var\"])) divert.variableDivertName = target;\n else divert.targetPathString = target;\n\n divert.isConditional = !!obj[\"c\"];\n\n if (external) {\n if ((propValue = obj[\"exArgs\"]))\n divert.externalArgs = parseInt(propValue);\n }\n\n return divert;\n }\n\n // Choice\n if ((propValue = obj[\"*\"])) {\n let choice = new ChoicePoint();\n choice.pathStringOnChoice = propValue.toString();\n\n if ((propValue = obj[\"flg\"])) choice.flags = parseInt(propValue);\n\n return choice;\n }\n\n // Variable reference\n if ((propValue = obj[\"VAR?\"])) {\n return new VariableReference(propValue.toString());\n } else if ((propValue = obj[\"CNT?\"])) {\n let readCountVarRef = new VariableReference();\n readCountVarRef.pathStringForCount = propValue.toString();\n return readCountVarRef;\n }\n\n // Variable assignment\n let isVarAss = false;\n let isGlobalVar = false;\n if ((propValue = obj[\"VAR=\"])) {\n isVarAss = true;\n isGlobalVar = true;\n } else if ((propValue = obj[\"temp=\"])) {\n isVarAss = true;\n isGlobalVar = false;\n }\n if (isVarAss) {\n let varName = propValue.toString();\n let isNewDecl = !obj[\"re\"];\n let varAss = new VariableAssignment(varName, isNewDecl);\n varAss.isGlobal = isGlobalVar;\n return varAss;\n }\n if (obj[\"#\"] !== undefined) {\n propValue = obj[\"#\"];\n return new Tag(propValue.toString());\n }\n\n // List value\n if ((propValue = obj[\"list\"])) {\n // var listContent = (Dictionary)propValue;\n let listContent = propValue as Record;\n let rawList = new InkList();\n if ((propValue = obj[\"origins\"])) {\n // var namesAsObjs = (List)propValue;\n let namesAsObjs = propValue as string[];\n // rawList.SetInitialOriginNames(namesAsObjs.Cast().ToList());\n rawList.SetInitialOriginNames(namesAsObjs);\n }\n\n for (let key in listContent) {\n if (listContent.hasOwnProperty(key)) {\n let nameToVal = listContent[key];\n let item = new InkListItem(key);\n let val = parseInt(nameToVal);\n rawList.Add(item, val);\n }\n }\n\n return new ListValue(rawList);\n }\n\n if (obj[\"originalChoicePath\"] != null) return this.JObjectToChoice(obj);\n }\n\n // Array is always a Runtime.Container\n if (Array.isArray(token)) {\n return this.JArrayToContainer(token);\n }\n\n if (token === null || token === undefined) return null;\n\n throw new Error(\n \"Failed to convert token to runtime object: \" +\n this.toJson(token, [\"parent\"])\n );\n }\n\n public static toJson(\n me: T,\n removes?: (keyof T)[],\n space?: number\n ): string {\n return JSON.stringify(\n me,\n (k, v) => (removes?.some((r) => r === k) ? undefined : v),\n space\n );\n }\n\n public static WriteRuntimeContainer(\n writer: SimpleJson.Writer,\n container: Container | null,\n withoutName: boolean = false\n ) {\n writer.WriteArrayStart();\n if (container === null) {\n return throwNullException(\"container\");\n }\n for (let c of container.content) this.WriteRuntimeObject(writer, c);\n\n let namedOnlyContent = container.namedOnlyContent;\n let countFlags = container.countFlags;\n let hasNameProperty = container.name != null && !withoutName;\n\n let hasTerminator =\n namedOnlyContent != null || countFlags > 0 || hasNameProperty;\n if (hasTerminator) {\n writer.WriteObjectStart();\n }\n\n if (namedOnlyContent != null) {\n for (let [key, value] of namedOnlyContent) {\n let name = key;\n let namedContainer = asOrNull(value, Container);\n writer.WritePropertyStart(name);\n this.WriteRuntimeContainer(writer, namedContainer, true);\n writer.WritePropertyEnd();\n }\n }\n\n if (countFlags > 0) writer.WriteIntProperty(\"#f\", countFlags);\n\n if (hasNameProperty) writer.WriteProperty(\"#n\", container.name);\n\n if (hasTerminator) writer.WriteObjectEnd();\n else writer.WriteNull();\n\n writer.WriteArrayEnd();\n }\n\n public static JArrayToContainer(jArray: any[]) {\n let container = new Container();\n container.content = this.JArrayToRuntimeObjList(jArray, true);\n\n let terminatingObj = jArray[jArray.length - 1] as Record;\n if (terminatingObj != null) {\n let namedOnlyContent = new Map();\n\n for (let key in terminatingObj) {\n if (key == \"#f\") {\n container.countFlags = parseInt(terminatingObj[key]);\n } else if (key == \"#n\") {\n container.name = terminatingObj[key].toString();\n } else {\n let namedContentItem = this.JTokenToRuntimeObject(\n terminatingObj[key]\n );\n // var namedSubContainer = namedContentItem as Container;\n let namedSubContainer = asOrNull(namedContentItem, Container);\n if (namedSubContainer) namedSubContainer.name = key;\n namedOnlyContent.set(key, namedContentItem);\n }\n }\n\n container.namedOnlyContent = namedOnlyContent;\n }\n\n return container;\n }\n\n public static JObjectToChoice(jObj: Record) {\n let choice = new Choice();\n choice.text = jObj[\"text\"].toString();\n choice.index = parseInt(jObj[\"index\"]);\n choice.sourcePath = jObj[\"originalChoicePath\"].toString();\n choice.originalThreadIndex = parseInt(jObj[\"originalThreadIndex\"]);\n choice.pathStringOnChoice = jObj[\"targetPath\"].toString();\n return choice;\n }\n\n public static WriteChoice(writer: SimpleJson.Writer, choice: Choice) {\n writer.WriteObjectStart();\n writer.WriteProperty(\"text\", choice.text);\n writer.WriteIntProperty(\"index\", choice.index);\n writer.WriteProperty(\"originalChoicePath\", choice.sourcePath);\n writer.WriteIntProperty(\"originalThreadIndex\", choice.originalThreadIndex);\n writer.WriteProperty(\"targetPath\", choice.pathStringOnChoice);\n writer.WriteObjectEnd();\n }\n\n public static WriteInkList(writer: SimpleJson.Writer, listVal: ListValue) {\n let rawList = listVal.value;\n if (rawList === null) {\n return throwNullException(\"rawList\");\n }\n\n writer.WriteObjectStart();\n writer.WritePropertyStart(\"list\");\n writer.WriteObjectStart();\n\n for (let [key, val] of rawList) {\n let item = InkListItem.fromSerializedKey(key);\n let itemVal = val;\n\n if (item.itemName === null) {\n return throwNullException(\"item.itemName\");\n }\n\n writer.WritePropertyNameStart();\n writer.WritePropertyNameInner(item.originName ? item.originName : \"?\");\n writer.WritePropertyNameInner(\".\");\n writer.WritePropertyNameInner(item.itemName);\n writer.WritePropertyNameEnd();\n\n writer.Write(itemVal);\n\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n\n writer.WritePropertyEnd();\n\n if (\n rawList.Count == 0 &&\n rawList.originNames != null &&\n rawList.originNames.length > 0\n ) {\n writer.WritePropertyStart(\"origins\");\n writer.WriteArrayStart();\n for (let name of rawList.originNames) writer.Write(name);\n writer.WriteArrayEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n }\n\n public static ListDefinitionsToJToken(origin: ListDefinitionsOrigin) {\n let result: Record = {};\n\n for (let def of origin.lists) {\n let listDefJson: Record = {};\n\n for (let [key, val] of def.items) {\n let item = InkListItem.fromSerializedKey(key);\n if (item.itemName === null) {\n return throwNullException(\"item.itemName\");\n }\n listDefJson[item.itemName] = val;\n }\n\n result[def.name] = listDefJson;\n }\n\n return result;\n }\n\n public static JTokenToListDefinitions(obj: Record) {\n // var defsObj = (Dictionary)obj;\n let defsObj = obj;\n\n let allDefs: ListDefinition[] = [];\n\n for (let key in defsObj) {\n if (defsObj.hasOwnProperty(key)) {\n let name = key.toString();\n // var listDefJson = (Dictionary)kv.Value;\n let listDefJson = defsObj[key] as Record;\n\n // Cast (string, object) to (string, int) for items\n let items: Map = new Map();\n\n for (let nameValueKey in listDefJson) {\n if (defsObj.hasOwnProperty(key)) {\n let nameValue = listDefJson[nameValueKey];\n items.set(nameValueKey, parseInt(nameValue));\n }\n }\n\n let def = new ListDefinition(name, items);\n allDefs.push(def);\n }\n }\n\n return new ListDefinitionsOrigin(allDefs);\n }\n\n private static _controlCommandNames = (() => {\n let _controlCommandNames: string[] = [];\n\n _controlCommandNames[ControlCommand.CommandType.EvalStart] = \"ev\";\n _controlCommandNames[ControlCommand.CommandType.EvalOutput] = \"out\";\n _controlCommandNames[ControlCommand.CommandType.EvalEnd] = \"/ev\";\n _controlCommandNames[ControlCommand.CommandType.Duplicate] = \"du\";\n _controlCommandNames[ControlCommand.CommandType.PopEvaluatedValue] = \"pop\";\n _controlCommandNames[ControlCommand.CommandType.PopFunction] = \"~ret\";\n _controlCommandNames[ControlCommand.CommandType.PopTunnel] = \"->->\";\n _controlCommandNames[ControlCommand.CommandType.BeginString] = \"str\";\n _controlCommandNames[ControlCommand.CommandType.EndString] = \"/str\";\n _controlCommandNames[ControlCommand.CommandType.NoOp] = \"nop\";\n _controlCommandNames[ControlCommand.CommandType.ChoiceCount] = \"choiceCnt\";\n _controlCommandNames[ControlCommand.CommandType.Turns] = \"turn\";\n _controlCommandNames[ControlCommand.CommandType.TurnsSince] = \"turns\";\n _controlCommandNames[ControlCommand.CommandType.ReadCount] = \"readc\";\n _controlCommandNames[ControlCommand.CommandType.Random] = \"rnd\";\n _controlCommandNames[ControlCommand.CommandType.SeedRandom] = \"srnd\";\n _controlCommandNames[ControlCommand.CommandType.VisitIndex] = \"visit\";\n _controlCommandNames[ControlCommand.CommandType.SequenceShuffleIndex] =\n \"seq\";\n _controlCommandNames[ControlCommand.CommandType.StartThread] = \"thread\";\n _controlCommandNames[ControlCommand.CommandType.Done] = \"done\";\n _controlCommandNames[ControlCommand.CommandType.End] = \"end\";\n _controlCommandNames[ControlCommand.CommandType.ListFromInt] = \"listInt\";\n _controlCommandNames[ControlCommand.CommandType.ListRange] = \"range\";\n _controlCommandNames[ControlCommand.CommandType.ListRandom] = \"lrnd\";\n\n for (let i = 0; i < ControlCommand.CommandType.TOTAL_VALUES; ++i) {\n if (_controlCommandNames[i] == null)\n throw new Error(\"Control command not accounted for in serialisation\");\n }\n\n return _controlCommandNames;\n })();\n}\n","import { PushPopType } from \"./PushPop\";\nimport { Path } from \"./Path\";\nimport { Story } from \"./Story\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { ListValue } from \"./Value\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { Pointer } from \"./Pointer\";\nimport { InkObject } from \"./Object\";\nimport { Debug } from \"./Debug\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\nimport { SimpleJson } from \"./SimpleJson\";\n\nexport class CallStack {\n get elements() {\n return this.callStack;\n }\n\n get depth() {\n return this.elements.length;\n }\n\n get currentElement() {\n let thread = this._threads[this._threads.length - 1];\n let cs = thread.callstack;\n return cs[cs.length - 1];\n }\n\n get currentElementIndex() {\n return this.callStack.length - 1;\n }\n\n get currentThread(): CallStack.Thread {\n return this._threads[this._threads.length - 1];\n }\n set currentThread(value: CallStack.Thread) {\n Debug.Assert(\n this._threads.length == 1,\n \"Shouldn't be directly setting the current thread when we have a stack of them\"\n );\n\n this._threads.length = 0;\n this._threads.push(value);\n }\n\n get canPop() {\n return this.callStack.length > 1;\n }\n\n constructor(storyContext: Story);\n constructor(toCopy: CallStack);\n constructor() {\n if (arguments[0] instanceof Story) {\n let storyContext = arguments[0] as Story;\n\n this._startOfRoot = Pointer.StartOf(storyContext.rootContentContainer);\n this.Reset();\n } else {\n let toCopy = arguments[0] as CallStack;\n\n this._threads = [];\n for (let otherThread of toCopy._threads) {\n this._threads.push(otherThread.Copy());\n }\n this._threadCounter = toCopy._threadCounter;\n this._startOfRoot = toCopy._startOfRoot.copy();\n }\n }\n\n public Reset() {\n this._threads = [];\n this._threads.push(new CallStack.Thread());\n\n this._threads[0].callstack.push(\n new CallStack.Element(PushPopType.Tunnel, this._startOfRoot)\n );\n }\n\n public SetJsonToken(jObject: Record, storyContext: Story) {\n this._threads.length = 0;\n\n // TODO: (List) jObject [\"threads\"];\n let jThreads: any[] = jObject[\"threads\"];\n\n for (let jThreadTok of jThreads) {\n // TODO: var jThreadObj = (Dictionary)jThreadTok;\n let jThreadObj = jThreadTok;\n let thread = new CallStack.Thread(jThreadObj, storyContext);\n this._threads.push(thread);\n }\n\n // TODO: (int)jObject [\"threadCounter\"];\n this._threadCounter = parseInt(jObject[\"threadCounter\"]);\n this._startOfRoot = Pointer.StartOf(storyContext.rootContentContainer);\n }\n public WriteJson(w: SimpleJson.Writer) {\n w.WriteObject((writer) => {\n writer.WritePropertyStart(\"threads\");\n writer.WriteArrayStart();\n\n for (let thread of this._threads) {\n thread.WriteJson(writer);\n }\n\n writer.WriteArrayEnd();\n writer.WritePropertyEnd();\n\n writer.WritePropertyStart(\"threadCounter\");\n writer.WriteInt(this._threadCounter);\n writer.WritePropertyEnd();\n });\n }\n\n public PushThread() {\n let newThread = this.currentThread.Copy();\n this._threadCounter++;\n newThread.threadIndex = this._threadCounter;\n this._threads.push(newThread);\n }\n\n public ForkThread() {\n let forkedThread = this.currentThread.Copy();\n this._threadCounter++;\n forkedThread.threadIndex = this._threadCounter;\n return forkedThread;\n }\n\n public PopThread() {\n if (this.canPopThread) {\n this._threads.splice(this._threads.indexOf(this.currentThread), 1); // should be equivalent to a pop()\n } else {\n throw new Error(\"Can't pop thread\");\n }\n }\n\n get canPopThread() {\n return this._threads.length > 1 && !this.elementIsEvaluateFromGame;\n }\n\n get elementIsEvaluateFromGame() {\n return this.currentElement.type == PushPopType.FunctionEvaluationFromGame;\n }\n\n public Push(\n type: PushPopType,\n externalEvaluationStackHeight: number = 0,\n outputStreamLengthWithPushed: number = 0\n ) {\n let element = new CallStack.Element(\n type,\n this.currentElement.currentPointer,\n false\n );\n\n element.evaluationStackHeightWhenPushed = externalEvaluationStackHeight;\n element.functionStartInOutputStream = outputStreamLengthWithPushed;\n\n this.callStack.push(element);\n }\n\n public CanPop(type: PushPopType | null = null) {\n if (!this.canPop) return false;\n\n if (type == null) return true;\n\n return this.currentElement.type == type;\n }\n\n public Pop(type: PushPopType | null = null) {\n if (this.CanPop(type)) {\n this.callStack.pop();\n return;\n } else {\n throw new Error(\"Mismatched push/pop in Callstack\");\n }\n }\n\n public GetTemporaryVariableWithName(\n name: string | null,\n contextIndex: number = -1\n ) {\n if (contextIndex == -1) contextIndex = this.currentElementIndex + 1;\n\n let contextElement = this.callStack[contextIndex - 1];\n\n let varValue = tryGetValueFromMap(\n contextElement.temporaryVariables,\n name,\n null\n );\n if (varValue.exists) {\n return varValue.result;\n } else {\n return null;\n }\n }\n\n public SetTemporaryVariable(\n name: string,\n value: any,\n declareNew: boolean,\n contextIndex: number = -1\n ) {\n if (contextIndex == -1) contextIndex = this.currentElementIndex + 1;\n\n let contextElement = this.callStack[contextIndex - 1];\n\n if (!declareNew && !contextElement.temporaryVariables.get(name)) {\n throw new Error(\"Could not find temporary variable to set: \" + name);\n }\n\n let oldValue = tryGetValueFromMap(\n contextElement.temporaryVariables,\n name,\n null\n );\n if (oldValue.exists)\n ListValue.RetainListOriginsForAssignment(oldValue.result, value);\n\n contextElement.temporaryVariables.set(name, value);\n }\n\n public ContextForVariableNamed(name: string) {\n if (this.currentElement.temporaryVariables.get(name)) {\n return this.currentElementIndex + 1;\n } else {\n return 0;\n }\n }\n\n public ThreadWithIndex(index: number) {\n let filtered = this._threads.filter((t) => {\n if (t.threadIndex == index) return t;\n });\n\n return filtered.length > 0 ? filtered[0] : null;\n }\n\n get callStack() {\n return this.currentThread.callstack;\n }\n\n get callStackTrace() {\n let sb = new StringBuilder();\n\n for (let t = 0; t < this._threads.length; t++) {\n let thread = this._threads[t];\n let isCurrent = t == this._threads.length - 1;\n sb.AppendFormat(\n \"=== THREAD {0}/{1} {2}===\\n\",\n t + 1,\n this._threads.length,\n isCurrent ? \"(current) \" : \"\"\n );\n\n for (let i = 0; i < thread.callstack.length; i++) {\n if (thread.callstack[i].type == PushPopType.Function)\n sb.Append(\" [FUNCTION] \");\n else sb.Append(\" [TUNNEL] \");\n\n let pointer = thread.callstack[i].currentPointer;\n if (!pointer.isNull) {\n sb.Append(\"\");\n }\n }\n }\n\n return sb.toString();\n }\n\n public _threads!: CallStack.Thread[]; // Banged because it's initialized in Reset().\n public _threadCounter: number = 0;\n public _startOfRoot: Pointer = Pointer.Null;\n}\n\nexport namespace CallStack {\n export class Element {\n public currentPointer: Pointer;\n public inExpressionEvaluation: boolean;\n public temporaryVariables: Map;\n public type: PushPopType;\n\n public evaluationStackHeightWhenPushed: number = 0;\n public functionStartInOutputStream: number = 0;\n\n constructor(\n type: PushPopType,\n pointer: Pointer,\n inExpressionEvaluation: boolean = false\n ) {\n this.currentPointer = pointer.copy();\n this.inExpressionEvaluation = inExpressionEvaluation;\n this.temporaryVariables = new Map();\n this.type = type;\n }\n\n public Copy() {\n let copy = new Element(\n this.type,\n this.currentPointer,\n this.inExpressionEvaluation\n );\n copy.temporaryVariables = new Map(this.temporaryVariables);\n copy.evaluationStackHeightWhenPushed =\n this.evaluationStackHeightWhenPushed;\n copy.functionStartInOutputStream = this.functionStartInOutputStream;\n return copy;\n }\n }\n\n export class Thread {\n public callstack: Element[];\n public threadIndex: number = 0;\n public previousPointer: Pointer = Pointer.Null;\n\n constructor();\n constructor(jThreadObj: any, storyContext: Story);\n constructor() {\n this.callstack = [];\n\n if (arguments[0] && arguments[1]) {\n let jThreadObj = arguments[0];\n let storyContext = arguments[1];\n\n // TODO: (int) jThreadObj['threadIndex'] can raise;\n this.threadIndex = parseInt(jThreadObj[\"threadIndex\"]);\n\n let jThreadCallstack = jThreadObj[\"callstack\"];\n\n for (let jElTok of jThreadCallstack) {\n let jElementObj = jElTok;\n\n // TODO: (int) jElementObj['type'] can raise;\n let pushPopType: PushPopType = parseInt(jElementObj[\"type\"]);\n\n let pointer = Pointer.Null;\n\n let currentContainerPathStr: string;\n // TODO: jElementObj.TryGetValue (\"cPath\", out currentContainerPathStrToken);\n let currentContainerPathStrToken = jElementObj[\"cPath\"];\n if (typeof currentContainerPathStrToken !== \"undefined\") {\n currentContainerPathStr = currentContainerPathStrToken.toString();\n\n let threadPointerResult = storyContext.ContentAtPath(\n new Path(currentContainerPathStr)\n );\n pointer.container = threadPointerResult.container;\n pointer.index = parseInt(jElementObj[\"idx\"]);\n\n if (threadPointerResult.obj == null)\n throw new Error(\n \"When loading state, internal story location couldn't be found: \" +\n currentContainerPathStr +\n \". Has the story changed since this save data was created?\"\n );\n else if (threadPointerResult.approximate) {\n if (pointer.container === null) {\n return throwNullException(\"pointer.container\");\n }\n storyContext.Warning(\n \"When loading state, exact internal story location couldn't be found: '\" +\n currentContainerPathStr +\n \"', so it was approximated to '\" +\n pointer.container.path.toString() +\n \"' to recover. Has the story changed since this save data was created?\"\n );\n }\n }\n\n let inExpressionEvaluation = !!jElementObj[\"exp\"];\n\n let el = new Element(pushPopType, pointer, inExpressionEvaluation);\n\n let temps = jElementObj[\"temp\"];\n if (typeof temps !== \"undefined\") {\n el.temporaryVariables =\n JsonSerialisation.JObjectToDictionaryRuntimeObjs(temps);\n } else {\n el.temporaryVariables.clear();\n }\n\n this.callstack.push(el);\n }\n\n let prevContentObjPath = jThreadObj[\"previousContentObject\"];\n if (typeof prevContentObjPath !== \"undefined\") {\n let prevPath = new Path(prevContentObjPath.toString());\n this.previousPointer = storyContext.PointerAtPath(prevPath);\n }\n }\n }\n\n public Copy() {\n let copy = new Thread();\n copy.threadIndex = this.threadIndex;\n for (let e of this.callstack) {\n copy.callstack.push(e.Copy());\n }\n copy.previousPointer = this.previousPointer.copy();\n return copy;\n }\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n\n writer.WritePropertyStart(\"callstack\");\n writer.WriteArrayStart();\n for (let el of this.callstack) {\n writer.WriteObjectStart();\n if (!el.currentPointer.isNull) {\n if (el.currentPointer.container === null) {\n return throwNullException(\"el.currentPointer.container\");\n }\n writer.WriteProperty(\n \"cPath\",\n el.currentPointer.container.path.componentsString\n );\n writer.WriteIntProperty(\"idx\", el.currentPointer.index);\n }\n\n writer.WriteProperty(\"exp\", el.inExpressionEvaluation);\n writer.WriteIntProperty(\"type\", el.type);\n\n if (el.temporaryVariables.size > 0) {\n writer.WritePropertyStart(\"temp\");\n JsonSerialisation.WriteDictionaryRuntimeObjs(\n writer,\n el.temporaryVariables\n );\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n }\n writer.WriteArrayEnd();\n writer.WritePropertyEnd();\n\n writer.WriteIntProperty(\"threadIndex\", this.threadIndex);\n\n if (!this.previousPointer.isNull) {\n let resolvedPointer = this.previousPointer.Resolve();\n if (resolvedPointer === null) {\n return throwNullException(\"this.previousPointer.Resolve()\");\n }\n writer.WriteProperty(\n \"previousContentObject\",\n resolvedPointer.path.toString()\n );\n }\n\n writer.WriteObjectEnd();\n }\n }\n}\n","import {\n AbstractValue,\n Value,\n VariablePointerValue,\n ListValue,\n IntValue,\n FloatValue,\n BoolValue,\n} from \"./Value\";\nimport { VariableAssignment } from \"./VariableAssignment\";\nimport { InkObject } from \"./Object\";\nimport { ListDefinitionsOrigin } from \"./ListDefinitionsOrigin\";\nimport { StoryException } from \"./StoryException\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { asOrThrows, asOrNull, isEquatable } from \"./TypeAssertion\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { throwNullException } from \"./NullException\";\nimport { CallStack } from \"./CallStack\";\nimport { StatePatch } from \"./StatePatch\";\nimport { SimpleJson } from \"./SimpleJson\";\n\nexport class VariablesState {\n // The way variableChangedEvent is a bit different than the reference implementation.\n // Originally it uses the C# += operator to add delegates, but in js we need to maintain\n // an actual collection of delegates (ie. callbacks) to register a new one, there is a\n // special ObserveVariableChange method below.\n public variableChangedEventCallbacks: Array<\n (variableName: string, newValue: InkObject) => void\n > = [];\n public variableChangedEvent(variableName: string, newValue: InkObject): void {\n for (let callback of this.variableChangedEventCallbacks) {\n callback(variableName, newValue);\n }\n }\n\n public patch: StatePatch | null = null;\n\n get batchObservingVariableChanges() {\n return this._batchObservingVariableChanges;\n }\n set batchObservingVariableChanges(value: boolean) {\n this._batchObservingVariableChanges = value;\n if (value) {\n this._changedVariablesForBatchObs = new Set();\n } else {\n if (this._changedVariablesForBatchObs != null) {\n for (let variableName of this._changedVariablesForBatchObs) {\n let currentValue = this._globalVariables.get(variableName);\n if (!currentValue) {\n throwNullException(\"currentValue\");\n } else {\n this.variableChangedEvent(variableName, currentValue);\n }\n }\n\n this._changedVariablesForBatchObs = null;\n }\n }\n }\n\n get callStack() {\n return this._callStack;\n }\n set callStack(callStack) {\n this._callStack = callStack;\n }\n\n private _batchObservingVariableChanges: boolean = false;\n\n // the original code uses a magic getter and setter for global variables,\n // allowing things like variableState['varname]. This is not quite possible\n // in js without a Proxy, so it is replaced with this $ function.\n public $(variableName: string, value: any) {\n if (typeof value === \"undefined\") {\n let varContents = null;\n\n if (this.patch !== null) {\n varContents = this.patch.TryGetGlobal(variableName, null);\n if (varContents.exists)\n return (varContents.result as AbstractValue).valueObject;\n }\n\n varContents = this._globalVariables.get(variableName);\n\n if (typeof varContents === \"undefined\") {\n varContents = this._defaultGlobalVariables.get(variableName);\n }\n\n if (typeof varContents !== \"undefined\")\n return (varContents as AbstractValue).valueObject;\n else return null;\n } else {\n if (typeof this._defaultGlobalVariables.get(variableName) === \"undefined\")\n throw new StoryException(\n \"Cannot assign to a variable (\" +\n variableName +\n \") that hasn't been declared in the story\"\n );\n\n let val = Value.Create(value);\n if (val == null) {\n if (value == null) {\n throw new Error(\"Cannot pass null to VariableState\");\n } else {\n throw new Error(\n \"Invalid value passed to VariableState: \" + value.toString()\n );\n }\n }\n\n this.SetGlobal(variableName, val);\n }\n }\n\n constructor(\n callStack: CallStack,\n listDefsOrigin: ListDefinitionsOrigin | null\n ) {\n this._globalVariables = new Map();\n this._callStack = callStack;\n this._listDefsOrigin = listDefsOrigin;\n\n // if es6 proxies are available, use them.\n try {\n // the proxy is used to allow direct manipulation of global variables.\n // It first tries to access the objects own property, and if none is\n // found it delegates the call to the $ method, defined below\n let p = new Proxy(this, {\n get(target: any, name) {\n return name in target ? target[name] : target.$(name);\n },\n set(target: any, name, value) {\n if (name in target) target[name] = value;\n else target.$(name, value);\n return true; // returning a falsy value make the trap fail\n },\n });\n\n return p;\n } catch (e) {\n // thr proxy object is not available in this context. we should warn the\n // dev but writting to the console feels a bit intrusive.\n // console.log(\"ES6 Proxy not available - direct manipulation of global variables can't work, use $() instead.\");\n }\n }\n\n public ApplyPatch() {\n if (this.patch === null) {\n return throwNullException(\"this.patch\");\n }\n\n for (let [namedVarKey, namedVarValue] of this.patch.globals) {\n this._globalVariables.set(namedVarKey, namedVarValue);\n }\n\n if (this._changedVariablesForBatchObs !== null) {\n for (let name of this.patch.changedVariables) {\n this._changedVariablesForBatchObs.add(name);\n }\n }\n\n this.patch = null;\n }\n\n public SetJsonToken(jToken: Record) {\n this._globalVariables.clear();\n\n for (let [varValKey, varValValue] of this._defaultGlobalVariables) {\n let loadedToken = jToken[varValKey];\n if (typeof loadedToken !== \"undefined\") {\n let tokenInkObject =\n JsonSerialisation.JTokenToRuntimeObject(loadedToken);\n if (tokenInkObject === null) {\n return throwNullException(\"tokenInkObject\");\n }\n this._globalVariables.set(varValKey, tokenInkObject);\n } else {\n this._globalVariables.set(varValKey, varValValue);\n }\n }\n }\n\n public static dontSaveDefaultValues: boolean = true;\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n for (let [keyValKey, keyValValue] of this._globalVariables) {\n let name = keyValKey;\n let val = keyValValue;\n\n if (VariablesState.dontSaveDefaultValues) {\n if (this._defaultGlobalVariables.has(name)) {\n let defaultVal = this._defaultGlobalVariables.get(name)!;\n if (this.RuntimeObjectsEqual(val, defaultVal)) continue;\n }\n }\n\n writer.WritePropertyStart(name);\n JsonSerialisation.WriteRuntimeObject(writer, val);\n writer.WritePropertyEnd();\n }\n writer.WriteObjectEnd();\n }\n\n public RuntimeObjectsEqual(\n obj1: InkObject | null,\n obj2: InkObject | null\n ): boolean {\n if (obj1 === null) {\n return throwNullException(\"obj1\");\n }\n if (obj2 === null) {\n return throwNullException(\"obj2\");\n }\n\n if (obj1.constructor !== obj2.constructor) return false;\n\n let boolVal = asOrNull(obj1, BoolValue);\n if (boolVal !== null) {\n return boolVal.value === asOrThrows(obj2, BoolValue).value;\n }\n\n let intVal = asOrNull(obj1, IntValue);\n if (intVal !== null) {\n return intVal.value === asOrThrows(obj2, IntValue).value;\n }\n\n let floatVal = asOrNull(obj1, FloatValue);\n if (floatVal !== null) {\n return floatVal.value === asOrThrows(obj2, FloatValue).value;\n }\n\n let val1 = asOrNull(obj1, Value);\n let val2 = asOrNull(obj2, Value);\n if (val1 !== null && val2 !== null) {\n if (isEquatable(val1.valueObject) && isEquatable(val2.valueObject)) {\n return val1.valueObject.Equals(val2.valueObject);\n } else {\n return val1.valueObject === val2.valueObject;\n }\n }\n\n throw new Error(\n \"FastRoughDefinitelyEquals: Unsupported runtime object type: \" +\n obj1.constructor.name\n );\n }\n\n public GetVariableWithName(\n name: string | null,\n contextIndex: number = -1\n ): InkObject | null {\n let varValue = this.GetRawVariableWithName(name, contextIndex);\n\n // var varPointer = varValue as VariablePointerValue;\n let varPointer = asOrNull(varValue, VariablePointerValue);\n if (varPointer !== null) {\n varValue = this.ValueAtVariablePointer(varPointer);\n }\n\n return varValue;\n }\n\n public TryGetDefaultVariableValue(name: string | null): InkObject | null {\n let val = tryGetValueFromMap(this._defaultGlobalVariables, name, null);\n return val.exists ? val.result : null;\n }\n\n public GlobalVariableExistsWithName(name: string) {\n return (\n this._globalVariables.has(name) ||\n (this._defaultGlobalVariables !== null &&\n this._defaultGlobalVariables.has(name))\n );\n }\n\n public GetRawVariableWithName(name: string | null, contextIndex: number) {\n let varValue: InkObject | null = null;\n\n if (contextIndex == 0 || contextIndex == -1) {\n let variableValue = null;\n if (this.patch !== null) {\n variableValue = this.patch.TryGetGlobal(name, null);\n if (variableValue.exists) return variableValue.result!;\n }\n\n // this is a conditional assignment\n variableValue = tryGetValueFromMap(this._globalVariables, name, null);\n if (variableValue.exists) return variableValue.result;\n\n if (this._defaultGlobalVariables !== null) {\n variableValue = tryGetValueFromMap(\n this._defaultGlobalVariables,\n name,\n null\n );\n if (variableValue.exists) return variableValue.result;\n }\n\n if (this._listDefsOrigin === null)\n return throwNullException(\"VariablesState._listDefsOrigin\");\n let listItemValue = this._listDefsOrigin.FindSingleItemListWithName(name);\n if (listItemValue) return listItemValue;\n }\n\n varValue = this._callStack.GetTemporaryVariableWithName(name, contextIndex);\n\n return varValue;\n }\n\n public ValueAtVariablePointer(pointer: VariablePointerValue) {\n return this.GetVariableWithName(pointer.variableName, pointer.contextIndex);\n }\n\n public Assign(varAss: VariableAssignment, value: InkObject) {\n let name = varAss.variableName;\n if (name === null) {\n return throwNullException(\"name\");\n }\n let contextIndex = -1;\n\n let setGlobal = false;\n if (varAss.isNewDeclaration) {\n setGlobal = varAss.isGlobal;\n } else {\n setGlobal = this.GlobalVariableExistsWithName(name);\n }\n\n if (varAss.isNewDeclaration) {\n // var varPointer = value as VariablePointerValue;\n let varPointer = asOrNull(value, VariablePointerValue);\n if (varPointer !== null) {\n let fullyResolvedVariablePointer =\n this.ResolveVariablePointer(varPointer);\n value = fullyResolvedVariablePointer;\n }\n } else {\n let existingPointer = null;\n do {\n // existingPointer = GetRawVariableWithName (name, contextIndex) as VariablePointerValue;\n existingPointer = asOrNull(\n this.GetRawVariableWithName(name, contextIndex),\n VariablePointerValue\n );\n if (existingPointer != null) {\n name = existingPointer.variableName;\n contextIndex = existingPointer.contextIndex;\n setGlobal = contextIndex == 0;\n }\n } while (existingPointer != null);\n }\n\n if (setGlobal) {\n this.SetGlobal(name, value);\n } else {\n this._callStack.SetTemporaryVariable(\n name,\n value,\n varAss.isNewDeclaration,\n contextIndex\n );\n }\n }\n\n public SnapshotDefaultGlobals() {\n this._defaultGlobalVariables = new Map(this._globalVariables);\n }\n\n public RetainListOriginsForAssignment(\n oldValue: InkObject,\n newValue: InkObject\n ) {\n let oldList = asOrThrows(oldValue, ListValue);\n let newList = asOrThrows(newValue, ListValue);\n\n if (oldList.value && newList.value && newList.value.Count == 0) {\n newList.value.SetInitialOriginNames(oldList.value.originNames);\n }\n }\n\n public SetGlobal(variableName: string | null, value: InkObject) {\n let oldValue = null;\n\n if (this.patch === null) {\n oldValue = tryGetValueFromMap(this._globalVariables, variableName, null);\n }\n\n if (this.patch !== null) {\n oldValue = this.patch.TryGetGlobal(variableName, null);\n if (!oldValue.exists) {\n oldValue = tryGetValueFromMap(\n this._globalVariables,\n variableName,\n null\n );\n }\n }\n\n ListValue.RetainListOriginsForAssignment(oldValue!.result!, value);\n\n if (variableName === null) {\n return throwNullException(\"variableName\");\n }\n\n if (this.patch !== null) {\n this.patch.SetGlobal(variableName, value);\n } else {\n this._globalVariables.set(variableName, value);\n }\n\n // TODO: Not sure !== is equivalent to !value.Equals(oldValue)\n if (\n this.variableChangedEvent !== null &&\n oldValue !== null &&\n value !== oldValue.result\n ) {\n if (this.batchObservingVariableChanges) {\n if (this._changedVariablesForBatchObs === null) {\n return throwNullException(\"this._changedVariablesForBatchObs\");\n }\n\n if (this.patch !== null) {\n this.patch.AddChangedVariable(variableName);\n } else if (this._changedVariablesForBatchObs !== null) {\n this._changedVariablesForBatchObs.add(variableName);\n }\n } else {\n this.variableChangedEvent(variableName, value);\n }\n }\n }\n\n public ResolveVariablePointer(varPointer: VariablePointerValue) {\n let contextIndex = varPointer.contextIndex;\n\n if (contextIndex == -1)\n contextIndex = this.GetContextIndexOfVariableNamed(\n varPointer.variableName\n );\n\n let valueOfVariablePointedTo = this.GetRawVariableWithName(\n varPointer.variableName,\n contextIndex\n );\n\n // var doubleRedirectionPointer = valueOfVariablePointedTo as VariablePointerValue;\n let doubleRedirectionPointer = asOrNull(\n valueOfVariablePointedTo,\n VariablePointerValue\n );\n if (doubleRedirectionPointer != null) {\n return doubleRedirectionPointer;\n } else {\n return new VariablePointerValue(varPointer.variableName, contextIndex);\n }\n }\n\n public GetContextIndexOfVariableNamed(varName: string) {\n if (this.GlobalVariableExistsWithName(varName)) return 0;\n\n return this._callStack.currentElementIndex;\n }\n\n /**\n * This function is specific to the js version of ink. It allows to register a\n * callback that will be called when a variable changes. The original code uses\n * `state.variableChangedEvent += callback` instead.\n *\n * @param {function} callback\n */\n public ObserveVariableChange(\n callback: (variableName: string, newValue: InkObject) => void\n ) {\n this.variableChangedEventCallbacks.push(callback);\n }\n\n private _globalVariables: Map;\n private _defaultGlobalVariables: Map = new Map();\n\n private _callStack: CallStack;\n private _changedVariablesForBatchObs: Set | null = new Set();\n private _listDefsOrigin: ListDefinitionsOrigin | null;\n}\n","// Taken from https://gist.github.com/blixt/f17b47c62508be59987b\n// Ink uses a seedable PRNG of which there is none in native javascript.\nexport class PRNG {\n private seed: number;\n\n constructor(seed: number) {\n this.seed = seed % 2147483647;\n if (this.seed <= 0) this.seed += 2147483646;\n }\n public next(): number {\n return (this.seed = (this.seed * 48271) % 2147483647);\n }\n public nextFloat(): number {\n return (this.next() - 1) / 2147483646;\n }\n}\n","import { InkObject } from \"./Object\";\nimport { Container } from \"./Container\";\n\nexport class StatePatch {\n get globals() {\n return this._globals;\n }\n get changedVariables() {\n return this._changedVariables;\n }\n get visitCounts() {\n return this._visitCounts;\n }\n get turnIndices() {\n return this._turnIndices;\n }\n\n constructor();\n constructor(toCopy: StatePatch | null);\n constructor() {\n if (arguments.length === 1 && arguments[0] !== null) {\n let toCopy = arguments[0] as StatePatch;\n this._globals = new Map(toCopy._globals);\n this._changedVariables = new Set(toCopy._changedVariables);\n this._visitCounts = new Map(toCopy._visitCounts);\n this._turnIndices = new Map(toCopy._turnIndices);\n } else {\n this._globals = new Map();\n this._changedVariables = new Set();\n this._visitCounts = new Map();\n this._turnIndices = new Map();\n }\n }\n\n public TryGetGlobal(name: string | null, /* out */ value: InkObject | null) {\n if (name !== null && this._globals.has(name)) {\n return { result: this._globals.get(name), exists: true };\n }\n\n return { result: value, exists: false };\n }\n\n public SetGlobal(name: string, value: InkObject) {\n this._globals.set(name, value);\n }\n\n public AddChangedVariable(name: string) {\n return this._changedVariables.add(name);\n }\n\n public TryGetVisitCount(container: Container, /* out */ count: number) {\n if (this._visitCounts.has(container)) {\n return { result: this._visitCounts.get(container), exists: true };\n }\n\n return { result: count, exists: false };\n }\n\n public SetVisitCount(container: Container, count: number) {\n this._visitCounts.set(container, count);\n }\n\n public SetTurnIndex(container: Container, index: number) {\n this._turnIndices.set(container, index);\n }\n\n public TryGetTurnIndex(container: Container, /* out */ index: number) {\n if (this._turnIndices.has(container)) {\n return { result: this._turnIndices.get(container), exists: true };\n }\n\n return { result: index, exists: false };\n }\n\n private _globals: Map;\n private _changedVariables: Set = new Set();\n private _visitCounts: Map = new Map();\n private _turnIndices: Map = new Map();\n}\n","export class SimpleJson {\n public static TextToDictionary(text: string) {\n return new SimpleJson.Reader(text).ToDictionary();\n }\n\n public static TextToArray(text: string) {\n return new SimpleJson.Reader(text).ToArray();\n }\n}\n\nexport namespace SimpleJson {\n export class Reader {\n constructor(text: string) {\n this._rootObject = JSON.parse(text);\n }\n\n public ToDictionary() {\n return this._rootObject as Record;\n }\n\n public ToArray() {\n return this._rootObject as any[];\n }\n\n private _rootObject: any[] | Record;\n }\n\n // In C#, this class writes json tokens directly to a StringWriter or\n // another stream. Here, a temporary hierarchy is created in the form\n // of a javascript object, which is serialised in the `toString` method.\n // See individual methods and properties for more information.\n export class Writer {\n public WriteObject(inner: (w: Writer) => void) {\n this.WriteObjectStart();\n inner(this);\n this.WriteObjectEnd();\n }\n\n // Add a new object.\n public WriteObjectStart() {\n this.StartNewObject(true);\n\n let newObject: Record = {};\n\n if (this.state === SimpleJson.Writer.State.Property) {\n // This object is created as the value of a property,\n // inside an other object.\n this.Assert(this.currentCollection !== null);\n this.Assert(this.currentPropertyName !== null);\n\n let propertyName = this._propertyNameStack.pop();\n this.currentCollection![propertyName!] = newObject;\n this._collectionStack.push(newObject);\n } else if (this.state === SimpleJson.Writer.State.Array) {\n // This object is created as the child of an array.\n this.Assert(this.currentCollection !== null);\n\n this.currentCollection!.push(newObject);\n this._collectionStack.push(newObject);\n } else {\n // This object is the root object.\n this.Assert(this.state === SimpleJson.Writer.State.None);\n this._jsonObject = newObject;\n this._collectionStack.push(newObject);\n }\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Object)\n );\n }\n\n public WriteObjectEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.Object);\n this._collectionStack.pop();\n this._stateStack.pop();\n }\n\n // Write a property name / value pair to the current object.\n public WriteProperty(\n name: any,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n innerOrContent: ((w: Writer) => void) | string | boolean | null\n ) {\n this.WritePropertyStart(name);\n if (arguments[1] instanceof Function) {\n let inner = arguments[1];\n inner(this);\n } else {\n let content: string | boolean | null = arguments[1];\n this.Write(content);\n }\n this.WritePropertyEnd();\n }\n\n // Int and Float are separate calls, since there both are\n // numbers in JavaScript, but need to be handled differently.\n\n public WriteIntProperty(name: any, content: number) {\n this.WritePropertyStart(name);\n this.WriteInt(content);\n this.WritePropertyEnd();\n }\n\n public WriteFloatProperty(name: any, content: number) {\n this.WritePropertyStart(name);\n this.WriteFloat(content);\n this.WritePropertyEnd();\n }\n\n // Prepare a new property name, which will be use to add the\n // new object when calling _addToCurrentObject() from a Write\n // method.\n public WritePropertyStart(name: any) {\n this.Assert(this.state === SimpleJson.Writer.State.Object);\n this._propertyNameStack.push(name);\n\n this.IncrementChildCount();\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Property)\n );\n }\n\n public WritePropertyEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.Property);\n this.Assert(this.childCount === 1);\n this._stateStack.pop();\n }\n\n // Prepare a new property name, except this time, the property name\n // will be created by concatenating all the strings passed to\n // WritePropertyNameInner.\n public WritePropertyNameStart() {\n this.Assert(this.state === SimpleJson.Writer.State.Object);\n this.IncrementChildCount();\n\n this._currentPropertyName = \"\";\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Property)\n );\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.PropertyName)\n );\n }\n\n public WritePropertyNameEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.PropertyName);\n this.Assert(this._currentPropertyName !== null);\n this._propertyNameStack.push(this._currentPropertyName!);\n this._currentPropertyName = null;\n this._stateStack.pop();\n }\n\n public WritePropertyNameInner(str: string) {\n this.Assert(this.state === SimpleJson.Writer.State.PropertyName);\n this.Assert(this._currentPropertyName !== null);\n this._currentPropertyName += str;\n }\n\n // Add a new array.\n public WriteArrayStart() {\n this.StartNewObject(true);\n\n let newObject: any[] = [];\n\n if (this.state === SimpleJson.Writer.State.Property) {\n // This array is created as the value of a property,\n // inside an object.\n this.Assert(this.currentCollection !== null);\n this.Assert(this.currentPropertyName !== null);\n\n let propertyName = this._propertyNameStack.pop();\n this.currentCollection![propertyName!] = newObject;\n this._collectionStack.push(newObject);\n } else if (this.state === SimpleJson.Writer.State.Array) {\n // This array is created as the child of another array.\n this.Assert(this.currentCollection !== null);\n\n this.currentCollection!.push(newObject);\n this._collectionStack.push(newObject);\n } else {\n // This array is the root object.\n this.Assert(this.state === SimpleJson.Writer.State.None);\n this._jsonObject = newObject;\n this._collectionStack.push(newObject);\n }\n\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.Array)\n );\n }\n\n public WriteArrayEnd() {\n this.Assert(this.state === SimpleJson.Writer.State.Array);\n this._collectionStack.pop();\n this._stateStack.pop();\n }\n\n // Add the value to the appropriate collection (array / object), given the current\n // context.\n public Write(\n value: number | string | boolean | null,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n escape: boolean = true\n ) {\n if (value === null) {\n console.error(\"Warning: trying to write a null value\");\n return;\n }\n\n this.StartNewObject(false);\n this._addToCurrentObject(value);\n }\n\n public WriteBool(value: boolean | null) {\n if (value === null) {\n return;\n }\n\n this.StartNewObject(false);\n this._addToCurrentObject(value);\n }\n\n public WriteInt(value: number | null) {\n if (value === null) {\n return;\n }\n\n this.StartNewObject(false);\n\n // Math.floor is used as a precaution:\n // 1. to ensure that the value is written as an integer\n // (without a fractional part -> 1 instead of 1.0), even\n // though it should be the default behaviour of\n // JSON.serialize;\n // 2. to ensure that if a floating number is passed\n // accidentally, it's converted to an integer.\n //\n // This guarantees savegame compatibility with the reference\n // implementation.\n this._addToCurrentObject(Math.floor(value));\n }\n\n // Since JSON doesn't support NaN and Infinity, these values\n // are converted here.\n public WriteFloat(value: number | null) {\n if (value === null) {\n return;\n }\n\n this.StartNewObject(false);\n if (value == Number.POSITIVE_INFINITY) {\n this._addToCurrentObject(3.4e38);\n } else if (value == Number.NEGATIVE_INFINITY) {\n this._addToCurrentObject(-3.4e38);\n } else if (isNaN(value)) {\n this._addToCurrentObject(0.0);\n } else {\n this._addToCurrentObject(value);\n }\n }\n\n public WriteNull() {\n this.StartNewObject(false);\n this._addToCurrentObject(null);\n }\n\n // Prepare a string before adding it to the current collection in\n // WriteStringEnd(). The string will be a concatenation of all the\n // strings passed to WriteStringInner.\n public WriteStringStart() {\n this.StartNewObject(false);\n this._currentString = \"\";\n this._stateStack.push(\n new SimpleJson.Writer.StateElement(SimpleJson.Writer.State.String)\n );\n }\n\n public WriteStringEnd() {\n this.Assert(this.state == SimpleJson.Writer.State.String);\n this._stateStack.pop();\n this._addToCurrentObject(this._currentString);\n this._currentString = null;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public WriteStringInner(str: string | null, escape: boolean = true) {\n this.Assert(this.state === SimpleJson.Writer.State.String);\n\n if (str === null) {\n console.error(\"Warning: trying to write a null string\");\n return;\n }\n\n this._currentString += str;\n }\n\n // Serialise the root object into a JSON string.\n public toString() {\n if (this._jsonObject === null) {\n return \"\";\n }\n\n return JSON.stringify(this._jsonObject);\n }\n\n // Prepare the state stack when adding new objects / values.\n private StartNewObject(container: boolean) {\n if (container) {\n this.Assert(\n this.state === SimpleJson.Writer.State.None ||\n this.state === SimpleJson.Writer.State.Property ||\n this.state === SimpleJson.Writer.State.Array\n );\n } else {\n this.Assert(\n this.state === SimpleJson.Writer.State.Property ||\n this.state === SimpleJson.Writer.State.Array\n );\n }\n\n if (this.state === SimpleJson.Writer.State.Property) {\n this.Assert(this.childCount === 0);\n }\n\n if (\n this.state === SimpleJson.Writer.State.Array ||\n this.state === SimpleJson.Writer.State.Property\n ) {\n this.IncrementChildCount();\n }\n }\n\n // These getters peek all the different stacks.\n\n private get state() {\n if (this._stateStack.length > 0) {\n return this._stateStack[this._stateStack.length - 1].type;\n } else {\n return SimpleJson.Writer.State.None;\n }\n }\n\n private get childCount() {\n if (this._stateStack.length > 0) {\n return this._stateStack[this._stateStack.length - 1].childCount;\n } else {\n return 0;\n }\n }\n\n private get currentCollection() {\n if (this._collectionStack.length > 0) {\n return this._collectionStack[this._collectionStack.length - 1];\n } else {\n return null;\n }\n }\n\n private get currentPropertyName() {\n if (this._propertyNameStack.length > 0) {\n return this._propertyNameStack[this._propertyNameStack.length - 1];\n } else {\n return null;\n }\n }\n\n private IncrementChildCount() {\n this.Assert(this._stateStack.length > 0);\n let currEl = this._stateStack.pop()!;\n currEl.childCount++;\n this._stateStack.push(currEl);\n }\n\n private Assert(condition: boolean) {\n if (!condition) throw Error(\"Assert failed while writing JSON\");\n }\n\n // This method did not exist in the original C# code. It adds\n // the given value to the current collection (used by Write methods).\n private _addToCurrentObject(value: number | string | boolean | null) {\n this.Assert(this.currentCollection !== null);\n if (this.state === SimpleJson.Writer.State.Array) {\n this.Assert(Array.isArray(this.currentCollection));\n (this.currentCollection as any[]).push(value);\n } else if (this.state === SimpleJson.Writer.State.Property) {\n this.Assert(!Array.isArray(this.currentCollection));\n this.Assert(this.currentPropertyName !== null);\n (this.currentCollection as Record)[\n this.currentPropertyName!\n ] = value;\n this._propertyNameStack.pop();\n }\n }\n\n // In addition to `_stateStack` present in the original code,\n // this implementation of SimpleJson use two other stacks and two\n // temporary variables holding the current context.\n\n // Used to keep track of the current property name being built\n // with `WritePropertyNameStart`, `WritePropertyNameInner` and\n // `WritePropertyNameEnd`.\n private _currentPropertyName: string | null = null;\n\n // Used to keep track of the current string value being built\n // with `WriteStringStart`, `WriteStringInner` and\n // `WriteStringEnd`.\n private _currentString: string | null = null;\n\n private _stateStack: SimpleJson.Writer.StateElement[] = [];\n\n // Keep track of the current collection being built (either an array\n // or an object). For instance, at the '?' step during the hiarchy\n // creation, this hierarchy:\n // [3, {a: [b, ?]}] will have this corresponding stack:\n // (bottom) [Array, Object, Array] (top)\n private _collectionStack: Array> = [];\n\n // Keep track of the current property being assigned. For instance, at\n // the '?' step during the hiarchy creation, this hierarchy:\n // [3, {a: [b, {c: ?}]}] will have this corresponding stack:\n // (bottom) [a, c] (top)\n private _propertyNameStack: string[] = [];\n\n // Object containing the entire hiearchy.\n private _jsonObject: Record | any[] | null = null;\n }\n\n export namespace Writer {\n export enum State {\n None,\n Object,\n Array,\n Property,\n PropertyName,\n String,\n }\n\n export class StateElement {\n public type: SimpleJson.Writer.State = SimpleJson.Writer.State.None;\n public childCount: number = 0;\n\n constructor(type: SimpleJson.Writer.State) {\n this.type = type;\n }\n }\n }\n}\n","// TODO: Unify with Compiler.\n\nexport type ErrorHandler = (message: string, type: ErrorType) => void;\n\nexport enum ErrorType {\n Author,\n Warning,\n Error,\n}\n","import { Container } from \"./Container\";\nimport { InkObject } from \"./Object\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { StoryState } from \"./StoryState\";\nimport { ControlCommand } from \"./ControlCommand\";\nimport { PushPopType } from \"./PushPop\";\nimport { ChoicePoint } from \"./ChoicePoint\";\nimport { Choice } from \"./Choice\";\nimport { Divert } from \"./Divert\";\nimport {\n Value,\n StringValue,\n IntValue,\n DivertTargetValue,\n VariablePointerValue,\n ListValue,\n} from \"./Value\";\nimport { Path } from \"./Path\";\nimport { Void } from \"./Void\";\nimport { Tag } from \"./Tag\";\nimport { VariableAssignment } from \"./VariableAssignment\";\nimport { VariableReference } from \"./VariableReference\";\nimport { NativeFunctionCall } from \"./NativeFunctionCall\";\nimport { StoryException } from \"./StoryException\";\nimport { PRNG } from \"./PRNG\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { ListDefinitionsOrigin } from \"./ListDefinitionsOrigin\";\nimport { ListDefinition } from \"./ListDefinition\";\nimport { Stopwatch } from \"./StopWatch\";\nimport { Pointer } from \"./Pointer\";\nimport { InkList, InkListItem, KeyValuePair } from \"./InkList\";\nimport { asOrNull, asOrThrows } from \"./TypeAssertion\";\nimport { DebugMetadata } from \"./DebugMetadata\";\nimport { throwNullException } from \"./NullException\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { ErrorHandler, ErrorType } from \"./Error\";\n\nexport { InkList } from \"./InkList\";\n\nif (!Number.isInteger) {\n Number.isInteger = function isInteger(nVal: any) {\n return (\n typeof nVal === \"number\" &&\n isFinite(nVal) &&\n nVal > -9007199254740992 &&\n nVal < 9007199254740992 &&\n Math.floor(nVal) === nVal\n );\n };\n}\n\nexport class Story extends InkObject {\n public static inkVersionCurrent = 20;\n\n public inkVersionMinimumCompatible = 18;\n\n get currentChoices() {\n let choices: Choice[] = [];\n\n if (this._state === null) {\n return throwNullException(\"this._state\");\n }\n for (let c of this._state.currentChoices) {\n if (!c.isInvisibleDefault) {\n c.index = choices.length;\n choices.push(c);\n }\n }\n\n return choices;\n }\n\n get currentText() {\n this.IfAsyncWeCant(\"call currentText since it's a work in progress\");\n return this.state.currentText;\n }\n\n get currentTags() {\n this.IfAsyncWeCant(\"call currentTags since it's a work in progress\");\n return this.state.currentTags;\n }\n\n get currentErrors() {\n return this.state.currentErrors;\n }\n\n get currentWarnings() {\n return this.state.currentWarnings;\n }\n\n get currentFlowName() {\n return this.state.currentFlowName;\n }\n\n get hasError() {\n return this.state.hasError;\n }\n\n get hasWarning() {\n return this.state.hasWarning;\n }\n\n get variablesState() {\n return this.state.variablesState;\n }\n\n get listDefinitions() {\n return this._listDefinitions;\n }\n\n get state() {\n return this._state;\n }\n\n public onError: ErrorHandler | null = null;\n\n public onDidContinue: (() => void) | null = null;\n\n public onMakeChoice: ((arg1: Choice) => void) | null = null;\n\n public onEvaluateFunction: ((arg1: string, arg2: any[]) => void) | null =\n null;\n\n public onCompleteEvaluateFunction:\n | ((arg1: string, arg2: any[], arg3: string, arg4: any) => void)\n | null = null;\n\n public onChoosePathString: ((arg1: string, arg2: any[]) => void) | null =\n null;\n\n // TODO: Implement Profiler\n public StartProfiling() {\n /* */\n }\n public EndProfiling() {\n /* */\n }\n\n constructor(contentContainer: Container, lists: ListDefinition[] | null);\n constructor(jsonString: string);\n constructor(json: Record);\n constructor() {\n super();\n\n // Discrimination between constructors\n let contentContainer: Container;\n let lists: ListDefinition[] | null = null;\n let json: Record | null = null;\n\n if (arguments[0] instanceof Container) {\n contentContainer = arguments[0] as Container;\n\n if (typeof arguments[1] !== \"undefined\") {\n lists = arguments[1] as ListDefinition[];\n }\n\n // ------ Story (Container contentContainer, List lists = null)\n this._mainContentContainer = contentContainer;\n // ------\n } else {\n if (typeof arguments[0] === \"string\") {\n let jsonString = arguments[0] as string;\n json = SimpleJson.TextToDictionary(jsonString);\n } else {\n json = arguments[0] as Record;\n }\n }\n\n // ------ Story (Container contentContainer, List lists = null)\n if (lists != null) this._listDefinitions = new ListDefinitionsOrigin(lists);\n\n this._externals = new Map();\n // ------\n\n // ------ Story(string jsonString) : this((Container)null)\n if (json !== null) {\n let rootObject: Record = json;\n\n let versionObj = rootObject[\"inkVersion\"];\n if (versionObj == null)\n throw new Error(\n \"ink version number not found. Are you sure it's a valid .ink.json file?\"\n );\n\n let formatFromFile = parseInt(versionObj);\n if (formatFromFile > Story.inkVersionCurrent) {\n throw new Error(\n \"Version of ink used to build story was newer than the current version of the engine\"\n );\n } else if (formatFromFile < this.inkVersionMinimumCompatible) {\n throw new Error(\n \"Version of ink used to build story is too old to be loaded by this version of the engine\"\n );\n } else if (formatFromFile != Story.inkVersionCurrent) {\n console.warn(\n \"WARNING: Version of ink used to build story doesn't match current version of engine. Non-critical, but recommend synchronising.\"\n );\n }\n\n let rootToken = rootObject[\"root\"];\n if (rootToken == null)\n throw new Error(\n \"Root node for ink not found. Are you sure it's a valid .ink.json file?\"\n );\n\n let listDefsObj;\n if ((listDefsObj = rootObject[\"listDefs\"])) {\n this._listDefinitions =\n JsonSerialisation.JTokenToListDefinitions(listDefsObj);\n }\n\n this._mainContentContainer = asOrThrows(\n JsonSerialisation.JTokenToRuntimeObject(rootToken),\n Container\n );\n\n this.ResetState();\n }\n // ------\n }\n\n // Merge together `public string ToJson()` and `void ToJson(SimpleJson.Writer writer)`.\n // Will only return a value if writer was not provided.\n public ToJson(writer?: SimpleJson.Writer): string | void {\n let shouldReturn = false;\n\n if (!writer) {\n shouldReturn = true;\n writer = new SimpleJson.Writer();\n }\n\n writer.WriteObjectStart();\n\n writer.WriteIntProperty(\"inkVersion\", Story.inkVersionCurrent);\n\n writer.WriteProperty(\"root\", (w) =>\n JsonSerialisation.WriteRuntimeContainer(w, this._mainContentContainer)\n );\n\n if (this._listDefinitions != null) {\n writer.WritePropertyStart(\"listDefs\");\n writer.WriteObjectStart();\n\n for (let def of this._listDefinitions.lists) {\n writer.WritePropertyStart(def.name);\n writer.WriteObjectStart();\n\n for (let [key, value] of def.items) {\n let item = InkListItem.fromSerializedKey(key);\n let val = value;\n writer.WriteIntProperty(item.itemName, val);\n }\n\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteObjectEnd();\n\n if (shouldReturn) return writer.toString();\n }\n\n public ResetState() {\n this.IfAsyncWeCant(\"ResetState\");\n\n this._state = new StoryState(this);\n this._state.variablesState.ObserveVariableChange(\n this.VariableStateDidChangeEvent.bind(this)\n );\n\n this.ResetGlobals();\n }\n\n public ResetErrors() {\n if (this._state === null) {\n return throwNullException(\"this._state\");\n }\n this._state.ResetErrors();\n }\n\n public ResetCallstack() {\n this.IfAsyncWeCant(\"ResetCallstack\");\n if (this._state === null) {\n return throwNullException(\"this._state\");\n }\n this._state.ForceEnd();\n }\n\n public ResetGlobals() {\n if (this._mainContentContainer.namedContent.get(\"global decl\")) {\n let originalPointer = this.state.currentPointer.copy();\n\n this.ChoosePath(new Path(\"global decl\"), false);\n\n this.ContinueInternal();\n\n this.state.currentPointer = originalPointer;\n }\n\n this.state.variablesState.SnapshotDefaultGlobals();\n }\n\n public SwitchFlow(flowName: string) {\n this.IfAsyncWeCant(\"switch flow\");\n if (this._asyncSaving) {\n throw new Error(\n \"Story is already in background saving mode, can't switch flow to \" +\n flowName\n );\n }\n\n this.state.SwitchFlow_Internal(flowName);\n }\n\n public RemoveFlow(flowName: string) {\n this.state.RemoveFlow_Internal(flowName);\n }\n\n public SwitchToDefaultFlow() {\n this.state.SwitchToDefaultFlow_Internal();\n }\n\n public Continue() {\n this.ContinueAsync(0);\n return this.currentText;\n }\n\n get canContinue() {\n return this.state.canContinue;\n }\n\n get asyncContinueComplete() {\n return !this._asyncContinueActive;\n }\n\n public ContinueAsync(millisecsLimitAsync: number) {\n if (!this._hasValidatedExternals) this.ValidateExternalBindings();\n\n this.ContinueInternal(millisecsLimitAsync);\n }\n\n public ContinueInternal(millisecsLimitAsync = 0) {\n if (this._profiler != null) this._profiler.PreContinue();\n\n let isAsyncTimeLimited = millisecsLimitAsync > 0;\n this._recursiveContinueCount++;\n\n if (!this._asyncContinueActive) {\n this._asyncContinueActive = isAsyncTimeLimited;\n\n if (!this.canContinue) {\n throw new Error(\n \"Can't continue - should check canContinue before calling Continue\"\n );\n }\n\n this._state.didSafeExit = false;\n this._state.ResetOutput();\n\n if (this._recursiveContinueCount == 1)\n this._state.variablesState.batchObservingVariableChanges = true;\n }\n\n let durationStopwatch = new Stopwatch();\n durationStopwatch.Start();\n\n let outputStreamEndsInNewline = false;\n this._sawLookaheadUnsafeFunctionAfterNewline = false;\n do {\n try {\n outputStreamEndsInNewline = this.ContinueSingleStep();\n } catch (e) {\n if (!(e instanceof StoryException)) throw e;\n\n this.AddError(e.message, undefined, e.useEndLineNumber);\n break;\n }\n\n if (outputStreamEndsInNewline) break;\n\n if (\n this._asyncContinueActive &&\n durationStopwatch.ElapsedMilliseconds > millisecsLimitAsync\n ) {\n break;\n }\n } while (this.canContinue);\n\n durationStopwatch.Stop();\n\n if (outputStreamEndsInNewline || !this.canContinue) {\n if (this._stateSnapshotAtLastNewline !== null) {\n this.RestoreStateSnapshot();\n }\n\n if (!this.canContinue) {\n if (this.state.callStack.canPopThread)\n this.AddError(\n \"Thread available to pop, threads should always be flat by the end of evaluation?\"\n );\n\n if (\n this.state.generatedChoices.length == 0 &&\n !this.state.didSafeExit &&\n this._temporaryEvaluationContainer == null\n ) {\n if (this.state.callStack.CanPop(PushPopType.Tunnel))\n this.AddError(\n \"unexpectedly reached end of content. Do you need a '->->' to return from a tunnel?\"\n );\n else if (this.state.callStack.CanPop(PushPopType.Function))\n this.AddError(\n \"unexpectedly reached end of content. Do you need a '~ return'?\"\n );\n else if (!this.state.callStack.canPop)\n this.AddError(\n \"ran out of content. Do you need a '-> DONE' or '-> END'?\"\n );\n else\n this.AddError(\n \"unexpectedly reached end of content for unknown reason. Please debug compiler!\"\n );\n }\n }\n\n this.state.didSafeExit = false;\n this._sawLookaheadUnsafeFunctionAfterNewline = false;\n\n if (this._recursiveContinueCount == 1)\n this._state.variablesState.batchObservingVariableChanges = false;\n\n this._asyncContinueActive = false;\n if (this.onDidContinue !== null) this.onDidContinue();\n }\n\n this._recursiveContinueCount--;\n\n if (this._profiler != null) this._profiler.PostContinue();\n\n // In the following code, we're masking a lot of non-null assertion,\n // because testing for against `hasError` or `hasWarning` makes sure\n // the arrays are present and contain at least one element.\n if (this.state.hasError || this.state.hasWarning) {\n if (this.onError !== null) {\n if (this.state.hasError) {\n for (let err of this.state.currentErrors!) {\n this.onError(err, ErrorType.Error);\n }\n }\n if (this.state.hasWarning) {\n for (let err of this.state.currentWarnings!) {\n this.onError(err, ErrorType.Warning);\n }\n }\n this.ResetErrors();\n } else {\n let sb = new StringBuilder();\n sb.Append(\"Ink had \");\n if (this.state.hasError) {\n sb.Append(`${this.state.currentErrors!.length}`);\n sb.Append(\n this.state.currentErrors!.length == 1 ? \" error\" : \"errors\"\n );\n if (this.state.hasWarning) sb.Append(\" and \");\n }\n if (this.state.hasWarning) {\n sb.Append(`${this.state.currentWarnings!.length}`);\n sb.Append(\n this.state.currentWarnings!.length == 1 ? \" warning\" : \"warnings\"\n );\n if (this.state.hasWarning) sb.Append(\" and \");\n }\n sb.Append(\n \". It is strongly suggested that you assign an error handler to story.onError. The first issue was: \"\n );\n sb.Append(\n this.state.hasError\n ? this.state.currentErrors![0]\n : this.state.currentWarnings![0]\n );\n\n throw new StoryException(sb.toString());\n }\n }\n }\n\n public ContinueSingleStep() {\n if (this._profiler != null) this._profiler.PreStep();\n\n this.Step();\n\n if (this._profiler != null) this._profiler.PostStep();\n\n if (!this.canContinue && !this.state.callStack.elementIsEvaluateFromGame) {\n this.TryFollowDefaultInvisibleChoice();\n }\n\n if (this._profiler != null) this._profiler.PreSnapshot();\n\n if (!this.state.inStringEvaluation) {\n if (this._stateSnapshotAtLastNewline !== null) {\n if (this._stateSnapshotAtLastNewline.currentTags === null) {\n return throwNullException(\"this._stateAtLastNewline.currentTags\");\n }\n if (this.state.currentTags === null) {\n return throwNullException(\"this.state.currentTags\");\n }\n\n let change = this.CalculateNewlineOutputStateChange(\n this._stateSnapshotAtLastNewline.currentText,\n this.state.currentText,\n this._stateSnapshotAtLastNewline.currentTags.length,\n this.state.currentTags.length\n );\n\n if (\n change == Story.OutputStateChange.ExtendedBeyondNewline ||\n this._sawLookaheadUnsafeFunctionAfterNewline\n ) {\n this.RestoreStateSnapshot();\n\n return true;\n } else if (change == Story.OutputStateChange.NewlineRemoved) {\n this.DiscardSnapshot();\n }\n }\n\n if (this.state.outputStreamEndsInNewline) {\n if (this.canContinue) {\n if (this._stateSnapshotAtLastNewline == null) this.StateSnapshot();\n } else {\n this.DiscardSnapshot();\n }\n }\n }\n\n if (this._profiler != null) this._profiler.PostSnapshot();\n\n return false;\n }\n\n public CalculateNewlineOutputStateChange(\n prevText: string | null,\n currText: string | null,\n prevTagCount: number,\n currTagCount: number\n ) {\n if (prevText === null) {\n return throwNullException(\"prevText\");\n }\n if (currText === null) {\n return throwNullException(\"currText\");\n }\n\n let newlineStillExists =\n currText.length >= prevText.length &&\n currText.charAt(prevText.length - 1) == \"\\n\";\n if (\n prevTagCount == currTagCount &&\n prevText.length == currText.length &&\n newlineStillExists\n )\n return Story.OutputStateChange.NoChange;\n\n if (!newlineStillExists) {\n return Story.OutputStateChange.NewlineRemoved;\n }\n\n if (currTagCount > prevTagCount)\n return Story.OutputStateChange.ExtendedBeyondNewline;\n\n for (let i = prevText.length; i < currText.length; i++) {\n let c = currText.charAt(i);\n if (c != \" \" && c != \"\\t\") {\n return Story.OutputStateChange.ExtendedBeyondNewline;\n }\n }\n\n return Story.OutputStateChange.NoChange;\n }\n\n public ContinueMaximally() {\n this.IfAsyncWeCant(\"ContinueMaximally\");\n\n let sb = new StringBuilder();\n\n while (this.canContinue) {\n sb.Append(this.Continue());\n }\n\n return sb.toString();\n }\n\n public ContentAtPath(path: Path) {\n return this.mainContentContainer.ContentAtPath(path);\n }\n\n public KnotContainerWithName(name: string) {\n let namedContainer = this.mainContentContainer.namedContent.get(name);\n if (namedContainer instanceof Container) return namedContainer;\n else return null;\n }\n\n public PointerAtPath(path: Path) {\n if (path.length == 0) return Pointer.Null;\n\n let p = new Pointer();\n\n let pathLengthToUse = path.length;\n\n let result = null;\n if (path.lastComponent === null) {\n return throwNullException(\"path.lastComponent\");\n }\n\n if (path.lastComponent.isIndex) {\n pathLengthToUse = path.length - 1;\n result = this.mainContentContainer.ContentAtPath(\n path,\n undefined,\n pathLengthToUse\n );\n p.container = result.container;\n p.index = path.lastComponent.index;\n } else {\n result = this.mainContentContainer.ContentAtPath(path);\n p.container = result.container;\n p.index = -1;\n }\n\n if (\n result.obj == null ||\n (result.obj == this.mainContentContainer && pathLengthToUse > 0)\n ) {\n this.Error(\n \"Failed to find content at path '\" +\n path +\n \"', and no approximation of it was possible.\"\n );\n } else if (result.approximate)\n this.Warning(\n \"Failed to find content at path '\" +\n path +\n \"', so it was approximated to: '\" +\n result.obj.path +\n \"'.\"\n );\n\n return p;\n }\n\n public StateSnapshot() {\n this._stateSnapshotAtLastNewline = this._state;\n this._state = this._state.CopyAndStartPatching();\n }\n\n public RestoreStateSnapshot() {\n if (this._stateSnapshotAtLastNewline === null) {\n throwNullException(\"_stateSnapshotAtLastNewline\");\n }\n this._stateSnapshotAtLastNewline.RestoreAfterPatch();\n\n this._state = this._stateSnapshotAtLastNewline;\n this._stateSnapshotAtLastNewline = null;\n\n if (!this._asyncSaving) {\n this._state.ApplyAnyPatch();\n }\n }\n\n public DiscardSnapshot() {\n if (!this._asyncSaving) this._state.ApplyAnyPatch();\n\n this._stateSnapshotAtLastNewline = null;\n }\n\n public CopyStateForBackgroundThreadSave() {\n this.IfAsyncWeCant(\"start saving on a background thread\");\n\n if (this._asyncSaving)\n throw new Error(\n \"Story is already in background saving mode, can't call CopyStateForBackgroundThreadSave again!\"\n );\n\n let stateToSave = this._state;\n this._state = this._state.CopyAndStartPatching();\n this._asyncSaving = true;\n return stateToSave;\n }\n\n public BackgroundSaveComplete() {\n if (this._stateSnapshotAtLastNewline === null) {\n this._state.ApplyAnyPatch();\n }\n\n this._asyncSaving = false;\n }\n\n public Step() {\n let shouldAddToStream = true;\n\n let pointer = this.state.currentPointer.copy();\n if (pointer.isNull) {\n return;\n }\n\n // Container containerToEnter = pointer.Resolve () as Container;\n let containerToEnter = asOrNull(pointer.Resolve(), Container);\n\n while (containerToEnter) {\n this.VisitContainer(containerToEnter, true);\n\n // No content? the most we can do is step past it\n if (containerToEnter.content.length == 0) {\n break;\n }\n\n pointer = Pointer.StartOf(containerToEnter);\n // containerToEnter = pointer.Resolve() as Container;\n containerToEnter = asOrNull(pointer.Resolve(), Container);\n }\n\n this.state.currentPointer = pointer.copy();\n\n if (this._profiler != null) this._profiler.Step(this.state.callStack);\n\n // Is the current content object:\n // - Normal content\n // - Or a logic/flow statement - if so, do it\n // Stop flow if we hit a stack pop when we're unable to pop (e.g. return/done statement in knot\n // that was diverted to rather than called as a function)\n let currentContentObj = pointer.Resolve();\n let isLogicOrFlowControl =\n this.PerformLogicAndFlowControl(currentContentObj);\n\n // Has flow been forced to end by flow control above?\n if (this.state.currentPointer.isNull) {\n return;\n }\n\n if (isLogicOrFlowControl) {\n shouldAddToStream = false;\n }\n\n // Choice with condition?\n // var choicePoint = currentContentObj as ChoicePoint;\n let choicePoint = asOrNull(currentContentObj, ChoicePoint);\n if (choicePoint) {\n let choice = this.ProcessChoice(choicePoint);\n if (choice) {\n this.state.generatedChoices.push(choice);\n }\n\n currentContentObj = null;\n shouldAddToStream = false;\n }\n\n // If the container has no content, then it will be\n // the \"content\" itself, but we skip over it.\n if (currentContentObj instanceof Container) {\n shouldAddToStream = false;\n }\n\n // Content to add to evaluation stack or the output stream\n if (shouldAddToStream) {\n // If we're pushing a variable pointer onto the evaluation stack, ensure that it's specific\n // to our current (possibly temporary) context index. And make a copy of the pointer\n // so that we're not editing the original runtime object.\n // var varPointer = currentContentObj as VariablePointerValue;\n let varPointer = asOrNull(currentContentObj, VariablePointerValue);\n if (varPointer && varPointer.contextIndex == -1) {\n // Create new object so we're not overwriting the story's own data\n let contextIdx = this.state.callStack.ContextForVariableNamed(\n varPointer.variableName\n );\n currentContentObj = new VariablePointerValue(\n varPointer.variableName,\n contextIdx\n );\n }\n\n // Expression evaluation content\n if (this.state.inExpressionEvaluation) {\n this.state.PushEvaluationStack(currentContentObj);\n }\n // Output stream content (i.e. not expression evaluation)\n else {\n this.state.PushToOutputStream(currentContentObj);\n }\n }\n\n // Increment the content pointer, following diverts if necessary\n this.NextContent();\n\n // Starting a thread should be done after the increment to the content pointer,\n // so that when returning from the thread, it returns to the content after this instruction.\n // var controlCmd = currentContentObj as ;\n let controlCmd = asOrNull(currentContentObj, ControlCommand);\n if (\n controlCmd &&\n controlCmd.commandType == ControlCommand.CommandType.StartThread\n ) {\n this.state.callStack.PushThread();\n }\n }\n\n public VisitContainer(container: Container, atStart: boolean) {\n if (!container.countingAtStartOnly || atStart) {\n if (container.visitsShouldBeCounted)\n this.state.IncrementVisitCountForContainer(container);\n\n if (container.turnIndexShouldBeCounted)\n this.state.RecordTurnIndexVisitToContainer(container);\n }\n }\n\n private _prevContainers: Container[] = [];\n public VisitChangedContainersDueToDivert() {\n let previousPointer = this.state.previousPointer.copy();\n let pointer = this.state.currentPointer.copy();\n\n if (pointer.isNull || pointer.index == -1) return;\n\n this._prevContainers.length = 0;\n if (!previousPointer.isNull) {\n // Container prevAncestor = previousPointer.Resolve() as Container ?? previousPointer.container as Container;\n let resolvedPreviousAncestor = previousPointer.Resolve();\n let prevAncestor =\n asOrNull(resolvedPreviousAncestor, Container) ||\n asOrNull(previousPointer.container, Container);\n while (prevAncestor) {\n this._prevContainers.push(prevAncestor);\n // prevAncestor = prevAncestor.parent as Container;\n prevAncestor = asOrNull(prevAncestor.parent, Container);\n }\n }\n\n let currentChildOfContainer = pointer.Resolve();\n\n if (currentChildOfContainer == null) return;\n\n // Container currentContainerAncestor = currentChildOfContainer.parent as Container;\n let currentContainerAncestor = asOrNull(\n currentChildOfContainer.parent,\n Container\n );\n let allChildrenEnteredAtStart = true;\n while (\n currentContainerAncestor &&\n (this._prevContainers.indexOf(currentContainerAncestor) < 0 ||\n currentContainerAncestor.countingAtStartOnly)\n ) {\n // Check whether this ancestor container is being entered at the start,\n // by checking whether the child object is the first.\n let enteringAtStart =\n currentContainerAncestor.content.length > 0 &&\n currentChildOfContainer == currentContainerAncestor.content[0] &&\n allChildrenEnteredAtStart;\n\n if (!enteringAtStart) allChildrenEnteredAtStart = false;\n\n // Mark a visit to this container\n this.VisitContainer(currentContainerAncestor, enteringAtStart);\n\n currentChildOfContainer = currentContainerAncestor;\n // currentContainerAncestor = currentContainerAncestor.parent as Container;\n currentContainerAncestor = asOrNull(\n currentContainerAncestor.parent,\n Container\n );\n }\n }\n\n public ProcessChoice(choicePoint: ChoicePoint) {\n let showChoice = true;\n\n // Don't create choice if choice point doesn't pass conditional\n if (choicePoint.hasCondition) {\n let conditionValue = this.state.PopEvaluationStack();\n if (!this.IsTruthy(conditionValue)) {\n showChoice = false;\n }\n }\n\n let startText = \"\";\n let choiceOnlyText = \"\";\n\n if (choicePoint.hasChoiceOnlyContent) {\n // var choiceOnlyStrVal = state.PopEvaluationStack () as StringValue;\n let choiceOnlyStrVal = asOrThrows(\n this.state.PopEvaluationStack(),\n StringValue\n );\n choiceOnlyText = choiceOnlyStrVal.value || \"\";\n }\n\n if (choicePoint.hasStartContent) {\n // var startStrVal = state.PopEvaluationStack () as StringValue;\n let startStrVal = asOrThrows(\n this.state.PopEvaluationStack(),\n StringValue\n );\n startText = startStrVal.value || \"\";\n }\n\n // Don't create choice if player has already read this content\n if (choicePoint.onceOnly) {\n let visitCount = this.state.VisitCountForContainer(\n choicePoint.choiceTarget\n );\n if (visitCount > 0) {\n showChoice = false;\n }\n }\n\n // We go through the full process of creating the choice above so\n // that we consume the content for it, since otherwise it'll\n // be shown on the output stream.\n if (!showChoice) {\n return null;\n }\n\n let choice = new Choice();\n choice.targetPath = choicePoint.pathOnChoice;\n choice.sourcePath = choicePoint.path.toString();\n choice.isInvisibleDefault = choicePoint.isInvisibleDefault;\n choice.threadAtGeneration = this.state.callStack.ForkThread();\n\n choice.text = (startText + choiceOnlyText).replace(/^[ \\t]+|[ \\t]+$/g, \"\");\n\n return choice;\n }\n\n public IsTruthy(obj: InkObject) {\n let truthy = false;\n if (obj instanceof Value) {\n let val = obj;\n\n if (val instanceof DivertTargetValue) {\n let divTarget = val;\n this.Error(\n \"Shouldn't use a divert target (to \" +\n divTarget.targetPath +\n \") as a conditional value. Did you intend a function call 'likeThis()' or a read count check 'likeThis'? (no arrows)\"\n );\n return false;\n }\n\n return val.isTruthy;\n }\n return truthy;\n }\n\n public PerformLogicAndFlowControl(contentObj: InkObject | null) {\n if (contentObj == null) {\n return false;\n }\n\n // Divert\n if (contentObj instanceof Divert) {\n let currentDivert = contentObj;\n\n if (currentDivert.isConditional) {\n let conditionValue = this.state.PopEvaluationStack();\n\n // False conditional? Cancel divert\n if (!this.IsTruthy(conditionValue)) return true;\n }\n\n if (currentDivert.hasVariableTarget) {\n let varName = currentDivert.variableDivertName;\n\n let varContents =\n this.state.variablesState.GetVariableWithName(varName);\n\n if (varContents == null) {\n this.Error(\n \"Tried to divert using a target from a variable that could not be found (\" +\n varName +\n \")\"\n );\n } else if (!(varContents instanceof DivertTargetValue)) {\n // var intContent = varContents as IntValue;\n let intContent = asOrNull(varContents, IntValue);\n\n let errorMessage =\n \"Tried to divert to a target from a variable, but the variable (\" +\n varName +\n \") didn't contain a divert target, it \";\n if (intContent instanceof IntValue && intContent.value == 0) {\n errorMessage += \"was empty/null (the value 0).\";\n } else {\n errorMessage += \"contained '\" + varContents + \"'.\";\n }\n\n this.Error(errorMessage);\n }\n\n let target = asOrThrows(varContents, DivertTargetValue);\n this.state.divertedPointer = this.PointerAtPath(target.targetPath);\n } else if (currentDivert.isExternal) {\n this.CallExternalFunction(\n currentDivert.targetPathString,\n currentDivert.externalArgs\n );\n return true;\n } else {\n this.state.divertedPointer = currentDivert.targetPointer.copy();\n }\n\n if (currentDivert.pushesToStack) {\n this.state.callStack.Push(\n currentDivert.stackPushType,\n undefined,\n this.state.outputStream.length\n );\n }\n\n if (this.state.divertedPointer.isNull && !currentDivert.isExternal) {\n if (\n currentDivert &&\n currentDivert.debugMetadata &&\n currentDivert.debugMetadata.sourceName != null\n ) {\n this.Error(\n \"Divert target doesn't exist: \" +\n currentDivert.debugMetadata.sourceName\n );\n } else {\n this.Error(\"Divert resolution failed: \" + currentDivert);\n }\n }\n\n return true;\n }\n\n // Start/end an expression evaluation? Or print out the result?\n else if (contentObj instanceof ControlCommand) {\n let evalCommand = contentObj;\n\n switch (evalCommand.commandType) {\n case ControlCommand.CommandType.EvalStart:\n this.Assert(\n this.state.inExpressionEvaluation === false,\n \"Already in expression evaluation?\"\n );\n this.state.inExpressionEvaluation = true;\n break;\n\n case ControlCommand.CommandType.EvalEnd:\n this.Assert(\n this.state.inExpressionEvaluation === true,\n \"Not in expression evaluation mode\"\n );\n this.state.inExpressionEvaluation = false;\n break;\n\n case ControlCommand.CommandType.EvalOutput:\n // If the expression turned out to be empty, there may not be anything on the stack\n if (this.state.evaluationStack.length > 0) {\n let output = this.state.PopEvaluationStack();\n\n // Functions may evaluate to Void, in which case we skip output\n if (!(output instanceof Void)) {\n // TODO: Should we really always blanket convert to string?\n // It would be okay to have numbers in the output stream the\n // only problem is when exporting text for viewing, it skips over numbers etc.\n let text = new StringValue(output.toString());\n\n this.state.PushToOutputStream(text);\n }\n }\n break;\n\n case ControlCommand.CommandType.NoOp:\n break;\n\n case ControlCommand.CommandType.Duplicate:\n this.state.PushEvaluationStack(this.state.PeekEvaluationStack());\n break;\n\n case ControlCommand.CommandType.PopEvaluatedValue:\n this.state.PopEvaluationStack();\n break;\n\n case ControlCommand.CommandType.PopFunction:\n case ControlCommand.CommandType.PopTunnel:\n let popType =\n evalCommand.commandType == ControlCommand.CommandType.PopFunction\n ? PushPopType.Function\n : PushPopType.Tunnel;\n\n let overrideTunnelReturnTarget: DivertTargetValue | null = null;\n if (popType == PushPopType.Tunnel) {\n let popped = this.state.PopEvaluationStack();\n // overrideTunnelReturnTarget = popped as DivertTargetValue;\n overrideTunnelReturnTarget = asOrNull(popped, DivertTargetValue);\n if (overrideTunnelReturnTarget === null) {\n this.Assert(\n popped instanceof Void,\n \"Expected void if ->-> doesn't override target\"\n );\n }\n }\n\n if (this.state.TryExitFunctionEvaluationFromGame()) {\n break;\n } else if (\n this.state.callStack.currentElement.type != popType ||\n !this.state.callStack.canPop\n ) {\n let names: Map = new Map();\n names.set(\n PushPopType.Function,\n \"function return statement (~ return)\"\n );\n names.set(PushPopType.Tunnel, \"tunnel onwards statement (->->)\");\n\n let expected = names.get(this.state.callStack.currentElement.type);\n if (!this.state.callStack.canPop) {\n expected = \"end of flow (-> END or choice)\";\n }\n\n let errorMsg =\n \"Found \" + names.get(popType) + \", when expected \" + expected;\n\n this.Error(errorMsg);\n } else {\n this.state.PopCallStack();\n\n if (overrideTunnelReturnTarget)\n this.state.divertedPointer = this.PointerAtPath(\n overrideTunnelReturnTarget.targetPath\n );\n }\n break;\n\n case ControlCommand.CommandType.BeginString:\n this.state.PushToOutputStream(evalCommand);\n\n this.Assert(\n this.state.inExpressionEvaluation === true,\n \"Expected to be in an expression when evaluating a string\"\n );\n this.state.inExpressionEvaluation = false;\n break;\n\n case ControlCommand.CommandType.EndString:\n let contentStackForString: InkObject[] = [];\n\n let outputCountConsumed = 0;\n for (let i = this.state.outputStream.length - 1; i >= 0; --i) {\n let obj = this.state.outputStream[i];\n\n outputCountConsumed++;\n\n // var command = obj as ControlCommand;\n let command = asOrNull(obj, ControlCommand);\n if (\n command &&\n command.commandType == ControlCommand.CommandType.BeginString\n ) {\n break;\n }\n\n if (obj instanceof StringValue) {\n contentStackForString.push(obj);\n }\n }\n\n // Consume the content that was produced for this string\n this.state.PopFromOutputStream(outputCountConsumed);\n\n // The C# version uses a Stack for contentStackForString, but we're\n // using a simple array, so we need to reverse it before using it\n contentStackForString = contentStackForString.reverse();\n\n // Build string out of the content we collected\n let sb = new StringBuilder();\n for (let c of contentStackForString) {\n sb.Append(c.toString());\n }\n\n // Return to expression evaluation (from content mode)\n this.state.inExpressionEvaluation = true;\n this.state.PushEvaluationStack(new StringValue(sb.toString()));\n break;\n\n case ControlCommand.CommandType.ChoiceCount:\n let choiceCount = this.state.generatedChoices.length;\n this.state.PushEvaluationStack(new IntValue(choiceCount));\n break;\n\n case ControlCommand.CommandType.Turns:\n this.state.PushEvaluationStack(\n new IntValue(this.state.currentTurnIndex + 1)\n );\n break;\n\n case ControlCommand.CommandType.TurnsSince:\n case ControlCommand.CommandType.ReadCount:\n let target = this.state.PopEvaluationStack();\n if (!(target instanceof DivertTargetValue)) {\n let extraNote = \"\";\n if (target instanceof IntValue)\n extraNote =\n \". Did you accidentally pass a read count ('knot_name') instead of a target ('-> knot_name')?\";\n this.Error(\n \"TURNS_SINCE / READ_COUNT expected a divert target (knot, stitch, label name), but saw \" +\n target +\n extraNote\n );\n break;\n }\n\n // var divertTarget = target as DivertTargetValue;\n let divertTarget = asOrThrows(target, DivertTargetValue);\n // var container = ContentAtPath (divertTarget.targetPath).correctObj as Container;\n let container = asOrNull(\n this.ContentAtPath(divertTarget.targetPath).correctObj,\n Container\n );\n\n let eitherCount;\n if (container != null) {\n if (\n evalCommand.commandType == ControlCommand.CommandType.TurnsSince\n )\n eitherCount = this.state.TurnsSinceForContainer(container);\n else eitherCount = this.state.VisitCountForContainer(container);\n } else {\n if (\n evalCommand.commandType == ControlCommand.CommandType.TurnsSince\n )\n eitherCount = -1;\n else eitherCount = 0;\n\n this.Warning(\n \"Failed to find container for \" +\n evalCommand.toString() +\n \" lookup at \" +\n divertTarget.targetPath.toString()\n );\n }\n\n this.state.PushEvaluationStack(new IntValue(eitherCount));\n break;\n\n case ControlCommand.CommandType.Random: {\n let maxInt = asOrNull(this.state.PopEvaluationStack(), IntValue);\n let minInt = asOrNull(this.state.PopEvaluationStack(), IntValue);\n\n if (minInt == null || minInt instanceof IntValue === false)\n return this.Error(\n \"Invalid value for minimum parameter of RANDOM(min, max)\"\n );\n\n if (maxInt == null || minInt instanceof IntValue === false)\n return this.Error(\n \"Invalid value for maximum parameter of RANDOM(min, max)\"\n );\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (maxInt.value === null) {\n return throwNullException(\"maxInt.value\");\n }\n if (minInt.value === null) {\n return throwNullException(\"minInt.value\");\n }\n\n // This code is differs a bit from the reference implementation, since\n // JavaScript has no true integers. Hence integer arithmetics and\n // interger overflows don't apply here. A loss of precision can\n // happen with big numbers however.\n //\n // The case where 'randomRange' is lower than zero is handled below,\n // so there's no need to test against Number.MIN_SAFE_INTEGER.\n let randomRange = maxInt.value - minInt.value + 1;\n if (!isFinite(randomRange) || randomRange > Number.MAX_SAFE_INTEGER) {\n randomRange = Number.MAX_SAFE_INTEGER;\n this.Error(\n \"RANDOM was called with a range that exceeds the size that ink numbers can use.\"\n );\n }\n if (randomRange <= 0)\n this.Error(\n \"RANDOM was called with minimum as \" +\n minInt.value +\n \" and maximum as \" +\n maxInt.value +\n \". The maximum must be larger\"\n );\n\n let resultSeed = this.state.storySeed + this.state.previousRandom;\n let random = new PRNG(resultSeed);\n\n let nextRandom = random.next();\n let chosenValue = (nextRandom % randomRange) + minInt.value;\n this.state.PushEvaluationStack(new IntValue(chosenValue));\n\n // Next random number (rather than keeping the Random object around)\n this.state.previousRandom = nextRandom;\n break;\n }\n\n case ControlCommand.CommandType.SeedRandom:\n let seed = asOrNull(this.state.PopEvaluationStack(), IntValue);\n if (seed == null || seed instanceof IntValue === false)\n return this.Error(\"Invalid value passed to SEED_RANDOM\");\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (seed.value === null) {\n return throwNullException(\"minInt.value\");\n }\n\n this.state.storySeed = seed.value;\n this.state.previousRandom = 0;\n\n this.state.PushEvaluationStack(new Void());\n break;\n\n case ControlCommand.CommandType.VisitIndex:\n let count =\n this.state.VisitCountForContainer(\n this.state.currentPointer.container\n ) - 1; // index not count\n this.state.PushEvaluationStack(new IntValue(count));\n break;\n\n case ControlCommand.CommandType.SequenceShuffleIndex:\n let shuffleIndex = this.NextSequenceShuffleIndex();\n this.state.PushEvaluationStack(new IntValue(shuffleIndex));\n break;\n\n case ControlCommand.CommandType.StartThread:\n // Handled in main step function\n break;\n\n case ControlCommand.CommandType.Done:\n // We may exist in the context of the initial\n // act of creating the thread, or in the context of\n // evaluating the content.\n if (this.state.callStack.canPopThread) {\n this.state.callStack.PopThread();\n }\n\n // In normal flow - allow safe exit without warning\n else {\n this.state.didSafeExit = true;\n\n // Stop flow in current thread\n this.state.currentPointer = Pointer.Null;\n }\n\n break;\n\n // Force flow to end completely\n case ControlCommand.CommandType.End:\n this.state.ForceEnd();\n break;\n\n case ControlCommand.CommandType.ListFromInt:\n // var intVal = state.PopEvaluationStack () as IntValue;\n let intVal = asOrNull(this.state.PopEvaluationStack(), IntValue);\n // var listNameVal = state.PopEvaluationStack () as StringValue;\n let listNameVal = asOrThrows(\n this.state.PopEvaluationStack(),\n StringValue\n );\n\n if (intVal === null) {\n throw new StoryException(\n \"Passed non-integer when creating a list element from a numerical value.\"\n );\n }\n\n let generatedListValue = null;\n\n if (this.listDefinitions === null) {\n return throwNullException(\"this.listDefinitions\");\n }\n let foundListDef = this.listDefinitions.TryListGetDefinition(\n listNameVal.value,\n null\n );\n if (foundListDef.exists) {\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (intVal.value === null) {\n return throwNullException(\"minInt.value\");\n }\n\n let foundItem = foundListDef.result!.TryGetItemWithValue(\n intVal.value,\n InkListItem.Null\n );\n if (foundItem.exists) {\n generatedListValue = new ListValue(\n foundItem.result!,\n intVal.value\n );\n }\n } else {\n throw new StoryException(\n \"Failed to find LIST called \" + listNameVal.value\n );\n }\n\n if (generatedListValue == null) generatedListValue = new ListValue();\n\n this.state.PushEvaluationStack(generatedListValue);\n break;\n\n case ControlCommand.CommandType.ListRange:\n let max = asOrNull(this.state.PopEvaluationStack(), Value);\n let min = asOrNull(this.state.PopEvaluationStack(), Value);\n\n // var targetList = state.PopEvaluationStack () as ListValue;\n let targetList = asOrNull(this.state.PopEvaluationStack(), ListValue);\n\n if (targetList === null || min === null || max === null)\n throw new StoryException(\n \"Expected list, minimum and maximum for LIST_RANGE\"\n );\n\n if (targetList.value === null) {\n return throwNullException(\"targetList.value\");\n }\n let result = targetList.value.ListWithSubRange(\n min.valueObject,\n max.valueObject\n );\n\n this.state.PushEvaluationStack(new ListValue(result));\n break;\n\n case ControlCommand.CommandType.ListRandom: {\n let listVal = this.state.PopEvaluationStack() as ListValue;\n if (listVal === null)\n throw new StoryException(\"Expected list for LIST_RANDOM\");\n\n let list = listVal.value;\n\n let newList: InkList | null = null;\n\n if (list === null) {\n throw throwNullException(\"list\");\n }\n if (list.Count == 0) {\n newList = new InkList();\n } else {\n // Generate a random index for the element to take\n let resultSeed = this.state.storySeed + this.state.previousRandom;\n let random = new PRNG(resultSeed);\n\n let nextRandom = random.next();\n let listItemIndex = nextRandom % list.Count;\n\n // This bit is a little different from the original\n // C# code, since iterators do not work in the same way.\n // First, we iterate listItemIndex - 1 times, calling next().\n // The listItemIndex-th time is made outside of the loop,\n // in order to retrieve the value.\n let listEnumerator = list.entries();\n for (let i = 0; i <= listItemIndex - 1; i++) {\n listEnumerator.next();\n }\n let value = listEnumerator.next().value;\n let randomItem: KeyValuePair = {\n Key: InkListItem.fromSerializedKey(value[0]),\n Value: value[1],\n };\n\n // Origin list is simply the origin of the one element\n if (randomItem.Key.originName === null) {\n return throwNullException(\"randomItem.Key.originName\");\n }\n newList = new InkList(randomItem.Key.originName, this);\n newList.Add(randomItem.Key, randomItem.Value);\n\n this.state.previousRandom = nextRandom;\n }\n\n this.state.PushEvaluationStack(new ListValue(newList));\n break;\n }\n\n default:\n this.Error(\"unhandled ControlCommand: \" + evalCommand);\n break;\n }\n\n return true;\n }\n\n // Variable assignment\n else if (contentObj instanceof VariableAssignment) {\n let varAss = contentObj;\n let assignedVal = this.state.PopEvaluationStack();\n\n this.state.variablesState.Assign(varAss, assignedVal);\n\n return true;\n }\n\n // Variable reference\n else if (contentObj instanceof VariableReference) {\n let varRef = contentObj;\n let foundValue = null;\n\n // Explicit read count value\n if (varRef.pathForCount != null) {\n let container = varRef.containerForCount;\n let count = this.state.VisitCountForContainer(container);\n foundValue = new IntValue(count);\n }\n\n // Normal variable reference\n else {\n foundValue = this.state.variablesState.GetVariableWithName(varRef.name);\n\n if (foundValue == null) {\n this.Warning(\n \"Variable not found: '\" +\n varRef.name +\n \"'. Using default value of 0 (false). This can happen with temporary variables if the declaration hasn't yet been hit. Globals are always given a default value on load if a value doesn't exist in the save state.\"\n );\n foundValue = new IntValue(0);\n }\n }\n\n this.state.PushEvaluationStack(foundValue);\n\n return true;\n }\n\n // Native function call\n else if (contentObj instanceof NativeFunctionCall) {\n let func = contentObj;\n let funcParams = this.state.PopEvaluationStack(func.numberOfParameters);\n let result = func.Call(funcParams);\n this.state.PushEvaluationStack(result);\n return true;\n }\n\n // No control content, must be ordinary content\n return false;\n }\n\n public ChoosePathString(\n path: string,\n resetCallstack = true,\n args: any[] = []\n ) {\n this.IfAsyncWeCant(\"call ChoosePathString right now\");\n if (this.onChoosePathString !== null) this.onChoosePathString(path, args);\n\n if (resetCallstack) {\n this.ResetCallstack();\n } else {\n if (this.state.callStack.currentElement.type == PushPopType.Function) {\n let funcDetail = \"\";\n let container =\n this.state.callStack.currentElement.currentPointer.container;\n if (container != null) {\n funcDetail = \"(\" + container.path.toString() + \") \";\n }\n throw new Error(\n \"Story was running a function \" +\n funcDetail +\n \"when you called ChoosePathString(\" +\n path +\n \") - this is almost certainly not not what you want! Full stack trace: \\n\" +\n this.state.callStack.callStackTrace\n );\n }\n }\n\n this.state.PassArgumentsToEvaluationStack(args);\n this.ChoosePath(new Path(path));\n }\n\n public IfAsyncWeCant(activityStr: string) {\n if (this._asyncContinueActive)\n throw new Error(\n \"Can't \" +\n activityStr +\n \". Story is in the middle of a ContinueAsync(). Make more ContinueAsync() calls or a single Continue() call beforehand.\"\n );\n }\n\n public ChoosePath(p: Path, incrementingTurnIndex: boolean = true) {\n this.state.SetChosenPath(p, incrementingTurnIndex);\n\n // Take a note of newly visited containers for read counts etc\n this.VisitChangedContainersDueToDivert();\n }\n\n public ChooseChoiceIndex(choiceIdx: number) {\n choiceIdx = choiceIdx;\n let choices = this.currentChoices;\n this.Assert(\n choiceIdx >= 0 && choiceIdx < choices.length,\n \"choice out of range\"\n );\n\n let choiceToChoose = choices[choiceIdx];\n if (this.onMakeChoice !== null) this.onMakeChoice(choiceToChoose);\n\n if (choiceToChoose.threadAtGeneration === null) {\n return throwNullException(\"choiceToChoose.threadAtGeneration\");\n }\n if (choiceToChoose.targetPath === null) {\n return throwNullException(\"choiceToChoose.targetPath\");\n }\n\n this.state.callStack.currentThread = choiceToChoose.threadAtGeneration;\n\n this.ChoosePath(choiceToChoose.targetPath);\n }\n\n public HasFunction(functionName: string) {\n try {\n return this.KnotContainerWithName(functionName) != null;\n } catch (e) {\n return false;\n }\n }\n\n public EvaluateFunction(\n functionName: string,\n args: any[] = [],\n returnTextOutput: boolean = false\n ): Story.EvaluateFunctionTextOutput | any {\n // EvaluateFunction behaves slightly differently than the C# version.\n // In C#, you can pass a (second) parameter `out textOutput` to get the\n // text outputted by the function. This is not possible in js. Instead,\n // we maintain the regular signature (functionName, args), plus an\n // optional third parameter returnTextOutput. If set to true, we will\n // return both the textOutput and the returned value, as an object.\n\n if (this.onEvaluateFunction !== null)\n this.onEvaluateFunction(functionName, args);\n\n this.IfAsyncWeCant(\"evaluate a function\");\n\n if (functionName == null) {\n throw new Error(\"Function is null\");\n } else if (functionName == \"\" || functionName.trim() == \"\") {\n throw new Error(\"Function is empty or white space.\");\n }\n\n let funcContainer = this.KnotContainerWithName(functionName);\n if (funcContainer == null) {\n throw new Error(\"Function doesn't exist: '\" + functionName + \"'\");\n }\n\n let outputStreamBefore: InkObject[] = [];\n outputStreamBefore.push(...this.state.outputStream);\n this._state.ResetOutput();\n\n this.state.StartFunctionEvaluationFromGame(funcContainer, args);\n\n // Evaluate the function, and collect the string output\n let stringOutput = new StringBuilder();\n while (this.canContinue) {\n stringOutput.Append(this.Continue());\n }\n let textOutput = stringOutput.toString();\n\n this._state.ResetOutput(outputStreamBefore);\n\n let result = this.state.CompleteFunctionEvaluationFromGame();\n if (this.onCompleteEvaluateFunction != null)\n this.onCompleteEvaluateFunction(functionName, args, textOutput, result);\n\n return returnTextOutput ? { returned: result, output: textOutput } : result;\n }\n\n public EvaluateExpression(exprContainer: Container) {\n let startCallStackHeight = this.state.callStack.elements.length;\n\n this.state.callStack.Push(PushPopType.Tunnel);\n\n this._temporaryEvaluationContainer = exprContainer;\n\n this.state.GoToStart();\n\n let evalStackHeight = this.state.evaluationStack.length;\n\n this.Continue();\n\n this._temporaryEvaluationContainer = null;\n\n // Should have fallen off the end of the Container, which should\n // have auto-popped, but just in case we didn't for some reason,\n // manually pop to restore the state (including currentPath).\n if (this.state.callStack.elements.length > startCallStackHeight) {\n this.state.PopCallStack();\n }\n\n let endStackHeight = this.state.evaluationStack.length;\n if (endStackHeight > evalStackHeight) {\n return this.state.PopEvaluationStack();\n } else {\n return null;\n }\n }\n\n public allowExternalFunctionFallbacks: boolean = false;\n\n public CallExternalFunction(\n funcName: string | null,\n numberOfArguments: number\n ) {\n if (funcName === null) {\n return throwNullException(\"funcName\");\n }\n let funcDef = this._externals.get(funcName);\n let fallbackFunctionContainer = null;\n\n let foundExternal = typeof funcDef !== \"undefined\";\n\n if (\n foundExternal &&\n !funcDef!.lookAheadSafe &&\n this._stateSnapshotAtLastNewline !== null\n ) {\n this._sawLookaheadUnsafeFunctionAfterNewline = true;\n return;\n }\n\n if (!foundExternal) {\n if (this.allowExternalFunctionFallbacks) {\n fallbackFunctionContainer = this.KnotContainerWithName(funcName);\n this.Assert(\n fallbackFunctionContainer !== null,\n \"Trying to call EXTERNAL function '\" +\n funcName +\n \"' which has not been bound, and fallback ink function could not be found.\"\n );\n\n // Divert direct into fallback function and we're done\n this.state.callStack.Push(\n PushPopType.Function,\n undefined,\n this.state.outputStream.length\n );\n this.state.divertedPointer = Pointer.StartOf(fallbackFunctionContainer);\n return;\n } else {\n this.Assert(\n false,\n \"Trying to call EXTERNAL function '\" +\n funcName +\n \"' which has not been bound (and ink fallbacks disabled).\"\n );\n }\n }\n\n // Pop arguments\n let args: any[] = [];\n for (let i = 0; i < numberOfArguments; ++i) {\n // var poppedObj = state.PopEvaluationStack () as Value;\n let poppedObj = asOrThrows(this.state.PopEvaluationStack(), Value);\n let valueObj = poppedObj.valueObject;\n args.push(valueObj);\n }\n\n // Reverse arguments from the order they were popped,\n // so they're the right way round again.\n args.reverse();\n\n // Run the function!\n let funcResult = funcDef!.function(args);\n\n // Convert return value (if any) to the a type that the ink engine can use\n let returnObj = null;\n if (funcResult != null) {\n returnObj = Value.Create(funcResult);\n this.Assert(\n returnObj !== null,\n \"Could not create ink value from returned object of type \" +\n typeof funcResult\n );\n } else {\n returnObj = new Void();\n }\n\n this.state.PushEvaluationStack(returnObj);\n }\n\n public BindExternalFunctionGeneral(\n funcName: string,\n func: Story.ExternalFunction,\n lookaheadSafe: boolean\n ) {\n this.IfAsyncWeCant(\"bind an external function\");\n this.Assert(\n !this._externals.has(funcName),\n \"Function '\" + funcName + \"' has already been bound.\"\n );\n this._externals.set(funcName, {\n function: func,\n lookAheadSafe: lookaheadSafe,\n });\n }\n\n public TryCoerce(value: any) {\n // We're skipping type coercition in this implementation. First of, js\n // is loosely typed, so it's not that important. Secondly, there is no\n // clean way (AFAIK) for the user to describe what type of parameters\n // they expect.\n return value;\n }\n\n public BindExternalFunction(\n funcName: string,\n func: Story.ExternalFunction,\n lookaheadSafe: boolean\n ) {\n this.Assert(func != null, \"Can't bind a null function\");\n\n this.BindExternalFunctionGeneral(\n funcName,\n (args: any) => {\n this.Assert(\n args.length >= func.length,\n \"External function expected \" + func.length + \" arguments\"\n );\n\n let coercedArgs = [];\n for (let i = 0, l = args.length; i < l; i++) {\n coercedArgs[i] = this.TryCoerce(args[i]);\n }\n return func.apply(null, coercedArgs);\n },\n lookaheadSafe\n );\n }\n\n public UnbindExternalFunction(funcName: string) {\n this.IfAsyncWeCant(\"unbind an external a function\");\n this.Assert(\n this._externals.has(funcName),\n \"Function '\" + funcName + \"' has not been bound.\"\n );\n this._externals.delete(funcName);\n }\n\n public ValidateExternalBindings(): void;\n public ValidateExternalBindings(\n c: Container | null,\n missingExternals: Set\n ): void;\n public ValidateExternalBindings(\n o: InkObject | null,\n missingExternals: Set\n ): void;\n public ValidateExternalBindings() {\n let c: Container | null = null;\n let o: InkObject | null = null;\n let missingExternals: Set = arguments[1] || new Set();\n\n if (arguments[0] instanceof Container) {\n c = arguments[0];\n }\n\n if (arguments[0] instanceof InkObject) {\n o = arguments[0];\n }\n\n if (c === null && o === null) {\n this.ValidateExternalBindings(\n this._mainContentContainer,\n missingExternals\n );\n this._hasValidatedExternals = true;\n\n // No problem! Validation complete\n if (missingExternals.size == 0) {\n this._hasValidatedExternals = true;\n } else {\n let message = \"Error: Missing function binding for external\";\n message += missingExternals.size > 1 ? \"s\" : \"\";\n message += \": '\";\n message += Array.from(missingExternals).join(\"', '\");\n message += \"' \";\n message += this.allowExternalFunctionFallbacks\n ? \", and no fallback ink function found.\"\n : \" (ink fallbacks disabled)\";\n\n this.Error(message);\n }\n } else if (c != null) {\n for (let innerContent of c.content) {\n let container = innerContent as Container;\n if (container == null || !container.hasValidName)\n this.ValidateExternalBindings(innerContent, missingExternals);\n }\n for (let [, value] of c.namedContent) {\n this.ValidateExternalBindings(\n asOrNull(value, InkObject),\n missingExternals\n );\n }\n } else if (o != null) {\n let divert = asOrNull(o, Divert);\n if (divert && divert.isExternal) {\n let name = divert.targetPathString;\n if (name === null) {\n return throwNullException(\"name\");\n }\n if (!this._externals.has(name)) {\n if (this.allowExternalFunctionFallbacks) {\n let fallbackFound =\n this.mainContentContainer.namedContent.has(name);\n if (!fallbackFound) {\n missingExternals.add(name);\n }\n } else {\n missingExternals.add(name);\n }\n }\n }\n }\n }\n\n public ObserveVariable(\n variableName: string,\n observer: Story.VariableObserver\n ) {\n this.IfAsyncWeCant(\"observe a new variable\");\n\n if (this._variableObservers === null) this._variableObservers = new Map();\n\n if (!this.state.variablesState.GlobalVariableExistsWithName(variableName))\n throw new Error(\n \"Cannot observe variable '\" +\n variableName +\n \"' because it wasn't declared in the ink story.\"\n );\n\n if (this._variableObservers.has(variableName)) {\n this._variableObservers.get(variableName)!.push(observer);\n } else {\n this._variableObservers.set(variableName, [observer]);\n }\n }\n\n public ObserveVariables(\n variableNames: string[],\n observers: Story.VariableObserver[]\n ) {\n for (let i = 0, l = variableNames.length; i < l; i++) {\n this.ObserveVariable(variableNames[i], observers[i]);\n }\n }\n\n public RemoveVariableObserver(\n observer?: Story.VariableObserver,\n specificVariableName?: string\n ) {\n // A couple of things to know about this method:\n //\n // 1. Since `RemoveVariableObserver` is exposed to the JavaScript world,\n // optionality is marked as `undefined` rather than `null`.\n // To keep things simple, null-checks are performed using regular\n // equality operators, where undefined == null.\n //\n // 2. Since C# delegates are translated to arrays of functions,\n // -= becomes a call to splice and null-checks are replaced by\n // emptiness-checks.\n //\n this.IfAsyncWeCant(\"remove a variable observer\");\n\n if (this._variableObservers === null) return;\n\n if (specificVariableName != null) {\n if (this._variableObservers.has(specificVariableName)) {\n if (observer != null) {\n let variableObservers =\n this._variableObservers.get(specificVariableName);\n if (variableObservers != null) {\n variableObservers.splice(variableObservers.indexOf(observer), 1);\n if (variableObservers.length === 0) {\n this._variableObservers.delete(specificVariableName);\n }\n }\n } else {\n this._variableObservers.delete(specificVariableName);\n }\n }\n } else if (observer != null) {\n let keys = this._variableObservers.keys();\n for (let varName of keys) {\n let variableObservers = this._variableObservers.get(varName);\n if (variableObservers != null) {\n variableObservers.splice(variableObservers.indexOf(observer), 1);\n if (variableObservers.length === 0) {\n this._variableObservers.delete(varName);\n }\n }\n }\n }\n }\n\n public VariableStateDidChangeEvent(\n variableName: string,\n newValueObj: InkObject\n ) {\n if (this._variableObservers === null) return;\n\n let observers = this._variableObservers.get(variableName);\n if (typeof observers !== \"undefined\") {\n if (!(newValueObj instanceof Value)) {\n throw new Error(\n \"Tried to get the value of a variable that isn't a standard type\"\n );\n }\n // var val = newValueObj as Value;\n let val = asOrThrows(newValueObj, Value);\n\n for (let observer of observers) {\n observer(variableName, val.valueObject);\n }\n }\n }\n\n get globalTags() {\n return this.TagsAtStartOfFlowContainerWithPathString(\"\");\n }\n\n public TagsForContentAtPath(path: string) {\n return this.TagsAtStartOfFlowContainerWithPathString(path);\n }\n\n public TagsAtStartOfFlowContainerWithPathString(pathString: string) {\n let path = new Path(pathString);\n\n let flowContainer = this.ContentAtPath(path).container;\n if (flowContainer === null) {\n return throwNullException(\"flowContainer\");\n }\n while (true) {\n let firstContent: InkObject = flowContainer.content[0];\n if (firstContent instanceof Container) flowContainer = firstContent;\n else break;\n }\n\n let tags: string[] | null = null;\n\n for (let c of flowContainer.content) {\n // var tag = c as Runtime.Tag;\n let tag = asOrNull(c, Tag);\n if (tag) {\n if (tags == null) tags = [];\n tags.push(tag.text);\n } else break;\n }\n\n return tags;\n }\n\n public BuildStringOfHierarchy() {\n let sb = new StringBuilder();\n\n this.mainContentContainer.BuildStringOfHierarchy(\n sb,\n 0,\n this.state.currentPointer.Resolve()\n );\n\n return sb.toString();\n }\n\n public BuildStringOfContainer(container: Container) {\n let sb = new StringBuilder();\n container.BuildStringOfHierarchy(\n sb,\n 0,\n this.state.currentPointer.Resolve()\n );\n return sb.toString();\n }\n\n public NextContent() {\n this.state.previousPointer = this.state.currentPointer.copy();\n\n if (!this.state.divertedPointer.isNull) {\n this.state.currentPointer = this.state.divertedPointer.copy();\n this.state.divertedPointer = Pointer.Null;\n\n this.VisitChangedContainersDueToDivert();\n\n if (!this.state.currentPointer.isNull) {\n return;\n }\n }\n\n let successfulPointerIncrement = this.IncrementContentPointer();\n\n if (!successfulPointerIncrement) {\n let didPop = false;\n\n if (this.state.callStack.CanPop(PushPopType.Function)) {\n this.state.PopCallStack(PushPopType.Function);\n\n if (this.state.inExpressionEvaluation) {\n this.state.PushEvaluationStack(new Void());\n }\n\n didPop = true;\n } else if (this.state.callStack.canPopThread) {\n this.state.callStack.PopThread();\n\n didPop = true;\n } else {\n this.state.TryExitFunctionEvaluationFromGame();\n }\n\n if (didPop && !this.state.currentPointer.isNull) {\n this.NextContent();\n }\n }\n }\n\n public IncrementContentPointer() {\n let successfulIncrement = true;\n\n let pointer = this.state.callStack.currentElement.currentPointer.copy();\n pointer.index++;\n\n if (pointer.container === null) {\n return throwNullException(\"pointer.container\");\n }\n while (pointer.index >= pointer.container.content.length) {\n successfulIncrement = false;\n\n // Container nextAncestor = pointer.container.parent as Container;\n let nextAncestor = asOrNull(pointer.container.parent, Container);\n if (nextAncestor instanceof Container === false) {\n break;\n }\n\n let indexInAncestor = nextAncestor!.content.indexOf(pointer.container);\n if (indexInAncestor == -1) {\n break;\n }\n\n pointer = new Pointer(nextAncestor, indexInAncestor);\n\n pointer.index++;\n\n successfulIncrement = true;\n if (pointer.container === null) {\n return throwNullException(\"pointer.container\");\n }\n }\n\n if (!successfulIncrement) pointer = Pointer.Null;\n\n this.state.callStack.currentElement.currentPointer = pointer.copy();\n\n return successfulIncrement;\n }\n\n public TryFollowDefaultInvisibleChoice() {\n let allChoices = this._state.currentChoices;\n\n let invisibleChoices = allChoices.filter((c) => c.isInvisibleDefault);\n\n if (\n invisibleChoices.length == 0 ||\n allChoices.length > invisibleChoices.length\n )\n return false;\n\n let choice = invisibleChoices[0];\n\n if (choice.targetPath === null) {\n return throwNullException(\"choice.targetPath\");\n }\n\n if (choice.threadAtGeneration === null) {\n return throwNullException(\"choice.threadAtGeneration\");\n }\n\n this.state.callStack.currentThread = choice.threadAtGeneration;\n\n if (this._stateSnapshotAtLastNewline !== null) {\n this.state.callStack.currentThread = this.state.callStack.ForkThread();\n }\n\n this.ChoosePath(choice.targetPath, false);\n\n return true;\n }\n\n public NextSequenceShuffleIndex() {\n // var numElementsIntVal = state.PopEvaluationStack () as IntValue;\n let numElementsIntVal = asOrNull(this.state.PopEvaluationStack(), IntValue);\n if (!(numElementsIntVal instanceof IntValue)) {\n this.Error(\"expected number of elements in sequence for shuffle index\");\n return 0;\n }\n\n let seqContainer = this.state.currentPointer.container;\n if (seqContainer === null) {\n return throwNullException(\"seqContainer\");\n }\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (numElementsIntVal.value === null) {\n return throwNullException(\"numElementsIntVal.value\");\n }\n let numElements = numElementsIntVal.value;\n\n // var seqCountVal = state.PopEvaluationStack () as IntValue;\n let seqCountVal = asOrThrows(this.state.PopEvaluationStack(), IntValue);\n let seqCount = seqCountVal.value;\n\n // Originally a primitive type, but here, can be null.\n // TODO: Replace by default value?\n if (seqCount === null) {\n return throwNullException(\"seqCount\");\n }\n\n let loopIndex = seqCount / numElements;\n let iterationIndex = seqCount % numElements;\n\n let seqPathStr = seqContainer.path.toString();\n let sequenceHash = 0;\n for (let i = 0, l = seqPathStr.length; i < l; i++) {\n sequenceHash += seqPathStr.charCodeAt(i) || 0;\n }\n let randomSeed = sequenceHash + loopIndex + this.state.storySeed;\n let random = new PRNG(Math.floor(randomSeed));\n\n let unpickedIndices = [];\n for (let i = 0; i < numElements; ++i) {\n unpickedIndices.push(i);\n }\n\n for (let i = 0; i <= iterationIndex; ++i) {\n let chosen = random.next() % unpickedIndices.length;\n let chosenIndex = unpickedIndices[chosen];\n unpickedIndices.splice(chosen, 1);\n\n if (i == iterationIndex) {\n return chosenIndex;\n }\n }\n\n throw new Error(\"Should never reach here\");\n }\n\n public Error(message: string, useEndLineNumber = false): never {\n let e = new StoryException(message);\n e.useEndLineNumber = useEndLineNumber;\n throw e;\n }\n\n public Warning(message: string) {\n this.AddError(message, true);\n }\n\n public AddError(\n message: string,\n isWarning = false,\n useEndLineNumber = false\n ) {\n let dm = this.currentDebugMetadata;\n\n let errorTypeStr = isWarning ? \"WARNING\" : \"ERROR\";\n\n if (dm != null) {\n let lineNum = useEndLineNumber ? dm.endLineNumber : dm.startLineNumber;\n message =\n \"RUNTIME \" +\n errorTypeStr +\n \": '\" +\n dm.fileName +\n \"' line \" +\n lineNum +\n \": \" +\n message;\n } else if (!this.state.currentPointer.isNull) {\n message =\n \"RUNTIME \" +\n errorTypeStr +\n \": (\" +\n this.state.currentPointer +\n \"): \" +\n message;\n } else {\n message = \"RUNTIME \" + errorTypeStr + \": \" + message;\n }\n\n this.state.AddError(message, isWarning);\n\n // In a broken state don't need to know about any other errors.\n if (!isWarning) this.state.ForceEnd();\n }\n\n public Assert(condition: boolean, message: string | null = null) {\n if (condition == false) {\n if (message == null) {\n message = \"Story assert\";\n }\n\n throw new Error(message + \" \" + this.currentDebugMetadata);\n }\n }\n\n get currentDebugMetadata(): DebugMetadata | null {\n let dm: DebugMetadata | null;\n\n let pointer = this.state.currentPointer;\n if (!pointer.isNull && pointer.Resolve() !== null) {\n dm = pointer.Resolve()!.debugMetadata;\n if (dm !== null) {\n return dm;\n }\n }\n\n for (let i = this.state.callStack.elements.length - 1; i >= 0; --i) {\n pointer = this.state.callStack.elements[i].currentPointer;\n if (!pointer.isNull && pointer.Resolve() !== null) {\n dm = pointer.Resolve()!.debugMetadata;\n if (dm !== null) {\n return dm;\n }\n }\n }\n\n for (let i = this.state.outputStream.length - 1; i >= 0; --i) {\n let outputObj = this.state.outputStream[i];\n dm = outputObj.debugMetadata;\n if (dm !== null) {\n return dm;\n }\n }\n\n return null;\n }\n\n get mainContentContainer() {\n if (this._temporaryEvaluationContainer) {\n return this._temporaryEvaluationContainer;\n } else {\n return this._mainContentContainer;\n }\n }\n\n /**\n * `_mainContentContainer` is almost guaranteed to be set in the\n * constructor, unless the json is malformed.\n */\n private _mainContentContainer!: Container;\n private _listDefinitions: ListDefinitionsOrigin | null = null;\n\n private _externals: Map;\n private _variableObservers: Map | null =\n null;\n private _hasValidatedExternals: boolean = false;\n\n private _temporaryEvaluationContainer: Container | null = null;\n\n /**\n * `state` is almost guaranteed to be set in the constructor, unless\n * using the compiler-specific constructor which will likely not be used in\n * the real world.\n */\n private _state!: StoryState;\n\n private _asyncContinueActive: boolean = false;\n private _stateSnapshotAtLastNewline: StoryState | null = null;\n private _sawLookaheadUnsafeFunctionAfterNewline: boolean = false;\n\n private _recursiveContinueCount: number = 0;\n\n private _asyncSaving: boolean = false;\n\n private _profiler: any | null = null; // TODO: Profiler\n}\n\nexport namespace Story {\n export enum OutputStateChange {\n NoChange = 0,\n ExtendedBeyondNewline = 1,\n NewlineRemoved = 2,\n }\n\n export interface EvaluateFunctionTextOutput {\n returned: any;\n output: string;\n }\n\n export interface ExternalFunctionDef {\n function: ExternalFunction;\n lookAheadSafe: boolean;\n }\n\n export type VariableObserver = (variableName: string, newValue: any) => void;\n export type ExternalFunction = (...args: any) => any;\n}\n","import { CallStack } from \"./CallStack\";\nimport { Choice } from \"./Choice\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { InkObject } from \"./Object\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { Story } from \"./Story\";\nimport { throwNullException } from \"./NullException\";\n\nexport class Flow {\n public name: string;\n public callStack: CallStack;\n public outputStream: InkObject[];\n public currentChoices: Choice[];\n\n constructor(name: String, story: Story);\n constructor(name: String, story: Story, jObject: Record);\n constructor() {\n let name = arguments[0] as string;\n let story = arguments[1] as Story;\n\n this.name = name;\n this.callStack = new CallStack(story);\n\n if (arguments[2]) {\n let jObject = arguments[2] as Record;\n\n this.callStack.SetJsonToken(jObject[\"callstack\"], story);\n this.outputStream = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"outputStream\"]\n );\n this.currentChoices = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"currentChoices\"]\n ) as Choice[];\n\n let jChoiceThreadsObj = jObject[\"choiceThreads\"];\n if (typeof jChoiceThreadsObj !== \"undefined\") {\n this.LoadFlowChoiceThreads(jChoiceThreadsObj, story);\n }\n } else {\n this.outputStream = [];\n this.currentChoices = [];\n }\n }\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n\n writer.WriteProperty(\"callstack\", (w) => this.callStack.WriteJson(w));\n writer.WriteProperty(\"outputStream\", (w) =>\n JsonSerialisation.WriteListRuntimeObjs(w, this.outputStream)\n );\n\n let hasChoiceThreads = false;\n for (let c of this.currentChoices) {\n if (c.threadAtGeneration === null)\n return throwNullException(\"c.threadAtGeneration\");\n\n c.originalThreadIndex = c.threadAtGeneration.threadIndex;\n\n if (this.callStack.ThreadWithIndex(c.originalThreadIndex) === null) {\n if (!hasChoiceThreads) {\n hasChoiceThreads = true;\n writer.WritePropertyStart(\"choiceThreads\");\n writer.WriteObjectStart();\n }\n\n writer.WritePropertyStart(c.originalThreadIndex);\n c.threadAtGeneration.WriteJson(writer);\n writer.WritePropertyEnd();\n }\n }\n\n if (hasChoiceThreads) {\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n }\n\n writer.WriteProperty(\"currentChoices\", (w) => {\n w.WriteArrayStart();\n for (let c of this.currentChoices) {\n JsonSerialisation.WriteChoice(w, c);\n }\n w.WriteArrayEnd();\n });\n\n writer.WriteObjectEnd();\n }\n\n public LoadFlowChoiceThreads(\n jChoiceThreads: Record,\n story: Story\n ) {\n for (let choice of this.currentChoices) {\n let foundActiveThread = this.callStack.ThreadWithIndex(\n choice.originalThreadIndex\n );\n if (foundActiveThread !== null) {\n choice.threadAtGeneration = foundActiveThread.Copy();\n } else {\n let jSavedChoiceThread =\n jChoiceThreads[`${choice.originalThreadIndex}`];\n choice.threadAtGeneration = new CallStack.Thread(\n jSavedChoiceThread,\n story\n );\n }\n }\n }\n}\n","import { CallStack } from \"./CallStack\";\nimport { VariablesState } from \"./VariablesState\";\nimport { ValueType, Value, StringValue, ListValue } from \"./Value\";\nimport { PushPopType } from \"./PushPop\";\nimport { Tag } from \"./Tag\";\nimport { Glue } from \"./Glue\";\nimport { Path } from \"./Path\";\nimport { ControlCommand } from \"./ControlCommand\";\nimport { StringBuilder } from \"./StringBuilder\";\nimport { JsonSerialisation } from \"./JsonSerialisation\";\nimport { PRNG } from \"./PRNG\";\nimport { Void } from \"./Void\";\nimport { Pointer } from \"./Pointer\";\nimport { tryGetValueFromMap } from \"./TryGetResult\";\nimport { Choice } from \"./Choice\";\nimport { asOrNull, asOrThrows, nullIfUndefined } from \"./TypeAssertion\";\nimport { Debug } from \"./Debug\";\nimport { Container } from \"./Container\";\nimport { InkObject } from \"./Object\";\nimport { throwNullException } from \"./NullException\";\nimport { Story } from \"./Story\";\nimport { StatePatch } from \"./StatePatch\";\nimport { SimpleJson } from \"./SimpleJson\";\nimport { Flow } from \"./Flow\";\nimport { InkList } from \"./InkList\";\n\nexport class StoryState {\n public readonly kInkSaveStateVersion = 9;\n public readonly kMinCompatibleLoadVersion = 8;\n\n public onDidLoadState: (() => void) | null = null;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public ToJson(indented: boolean = false) {\n let writer = new SimpleJson.Writer();\n this.WriteJson(writer);\n return writer.toString();\n }\n public toJson(indented: boolean = false) {\n return this.ToJson(indented);\n }\n\n public LoadJson(json: string) {\n let jObject = SimpleJson.TextToDictionary(json);\n this.LoadJsonObj(jObject);\n if (this.onDidLoadState !== null) this.onDidLoadState();\n }\n\n public VisitCountAtPathString(pathString: string) {\n let visitCountOut;\n\n if (this._patch !== null) {\n let container = this.story.ContentAtPath(new Path(pathString)).container;\n if (container === null)\n throw new Error(\"Content at path not found: \" + pathString);\n\n visitCountOut = this._patch.TryGetVisitCount(container, 0);\n if (visitCountOut.exists) return visitCountOut.result;\n }\n\n visitCountOut = tryGetValueFromMap(this._visitCounts, pathString, null);\n if (visitCountOut.exists) return visitCountOut.result;\n\n return 0;\n }\n\n public VisitCountForContainer(container: Container | null): number {\n if (container === null) {\n return throwNullException(\"container\");\n }\n if (!container.visitsShouldBeCounted) {\n this.story.Error(\n \"Read count for target (\" +\n container.name +\n \" - on \" +\n container.debugMetadata +\n \") unknown. The story may need to be compiled with countAllVisits flag (-c).\"\n );\n return 0;\n }\n\n if (this._patch !== null) {\n let count = this._patch.TryGetVisitCount(container, 0);\n if (count.exists) {\n return count.result!;\n }\n }\n\n let containerPathStr = container.path.toString();\n let count2 = tryGetValueFromMap(this._visitCounts, containerPathStr, null);\n if (count2.exists) {\n return count2.result!;\n }\n\n return 0;\n }\n\n public IncrementVisitCountForContainer(container: Container) {\n if (this._patch !== null) {\n let currCount = this.VisitCountForContainer(container);\n currCount++;\n this._patch.SetVisitCount(container, currCount);\n return;\n }\n\n let containerPathStr = container.path.toString();\n let count = tryGetValueFromMap(this._visitCounts, containerPathStr, null);\n if (count.exists) {\n this._visitCounts.set(containerPathStr, count.result! + 1);\n } else {\n this._visitCounts.set(containerPathStr, 1);\n }\n }\n\n public RecordTurnIndexVisitToContainer(container: Container) {\n if (this._patch !== null) {\n this._patch.SetTurnIndex(container, this.currentTurnIndex);\n return;\n }\n\n let containerPathStr = container.path.toString();\n this._turnIndices.set(containerPathStr, this.currentTurnIndex);\n }\n\n public TurnsSinceForContainer(container: Container) {\n if (!container.turnIndexShouldBeCounted) {\n this.story.Error(\n \"TURNS_SINCE() for target (\" +\n container.name +\n \" - on \" +\n container.debugMetadata +\n \") unknown. The story may need to be compiled with countAllVisits flag (-c).\"\n );\n }\n\n if (this._patch !== null) {\n let index = this._patch.TryGetTurnIndex(container, 0);\n if (index.exists) {\n return this.currentTurnIndex - index.result!;\n }\n }\n\n let containerPathStr = container.path.toString();\n let index2 = tryGetValueFromMap(this._turnIndices, containerPathStr, 0);\n if (index2.exists) {\n return this.currentTurnIndex - index2.result!;\n } else {\n return -1;\n }\n }\n\n get callstackDepth() {\n return this.callStack.depth;\n }\n\n get outputStream() {\n return this._currentFlow.outputStream;\n }\n\n get currentChoices() {\n // If we can continue generating text content rather than choices,\n // then we reflect the choice list as being empty, since choices\n // should always come at the end.\n if (this.canContinue) return [];\n return this._currentFlow.currentChoices;\n }\n\n get generatedChoices() {\n return this._currentFlow.currentChoices;\n }\n\n get currentErrors() {\n return this._currentErrors;\n }\n private _currentErrors: string[] | null = null;\n\n get currentWarnings() {\n return this._currentWarnings;\n }\n private _currentWarnings: string[] | null = null;\n\n get variablesState() {\n return this._variablesState;\n }\n set variablesState(value) {\n this._variablesState = value;\n }\n private _variablesState: VariablesState;\n\n get callStack() {\n return this._currentFlow.callStack;\n }\n\n get evaluationStack() {\n return this._evaluationStack;\n }\n private _evaluationStack: InkObject[];\n\n public divertedPointer: Pointer = Pointer.Null;\n\n get currentTurnIndex() {\n return this._currentTurnIndex;\n }\n set currentTurnIndex(value) {\n this._currentTurnIndex = value;\n }\n private _currentTurnIndex: number = 0;\n\n public storySeed: number = 0;\n public previousRandom: number = 0;\n public didSafeExit: boolean = false;\n\n public story: Story;\n\n get currentPathString() {\n let pointer = this.currentPointer;\n if (pointer.isNull) {\n return null;\n } else {\n if (pointer.path === null) {\n return throwNullException(\"pointer.path\");\n }\n return pointer.path.toString();\n }\n }\n\n get currentPointer() {\n return this.callStack.currentElement.currentPointer.copy();\n }\n\n set currentPointer(value) {\n this.callStack.currentElement.currentPointer = value.copy();\n }\n\n get previousPointer() {\n return this.callStack.currentThread.previousPointer.copy();\n }\n\n set previousPointer(value) {\n this.callStack.currentThread.previousPointer = value.copy();\n }\n\n get canContinue() {\n return !this.currentPointer.isNull && !this.hasError;\n }\n\n get hasError() {\n return this.currentErrors != null && this.currentErrors.length > 0;\n }\n\n get hasWarning() {\n return this.currentWarnings != null && this.currentWarnings.length > 0;\n }\n\n get currentText() {\n if (this._outputStreamTextDirty) {\n let sb = new StringBuilder();\n\n for (let outputObj of this.outputStream) {\n // var textContent = outputObj as StringValue;\n let textContent = asOrNull(outputObj, StringValue);\n if (textContent !== null) {\n sb.Append(textContent.value);\n }\n }\n\n this._currentText = this.CleanOutputWhitespace(sb.toString());\n this._outputStreamTextDirty = false;\n }\n\n return this._currentText;\n }\n private _currentText: string | null = null;\n\n public CleanOutputWhitespace(str: string) {\n let sb = new StringBuilder();\n\n let currentWhitespaceStart = -1;\n let startOfLine = 0;\n\n for (let i = 0; i < str.length; i++) {\n let c = str.charAt(i);\n\n let isInlineWhitespace = c == \" \" || c == \"\\t\";\n\n if (isInlineWhitespace && currentWhitespaceStart == -1)\n currentWhitespaceStart = i;\n\n if (!isInlineWhitespace) {\n if (\n c != \"\\n\" &&\n currentWhitespaceStart > 0 &&\n currentWhitespaceStart != startOfLine\n ) {\n sb.Append(\" \");\n }\n currentWhitespaceStart = -1;\n }\n\n if (c == \"\\n\") startOfLine = i + 1;\n\n if (!isInlineWhitespace) sb.Append(c);\n }\n\n return sb.toString();\n }\n\n get currentTags() {\n if (this._outputStreamTagsDirty) {\n this._currentTags = [];\n\n for (let outputObj of this.outputStream) {\n // var tag = outputObj as Tag;\n let tag = asOrNull(outputObj, Tag);\n if (tag !== null) {\n this._currentTags.push(tag.text);\n }\n }\n\n this._outputStreamTagsDirty = false;\n }\n\n return this._currentTags;\n }\n private _currentTags: string[] | null = null;\n\n get currentFlowName() {\n return this._currentFlow.name;\n }\n\n get inExpressionEvaluation() {\n return this.callStack.currentElement.inExpressionEvaluation;\n }\n set inExpressionEvaluation(value) {\n this.callStack.currentElement.inExpressionEvaluation = value;\n }\n\n constructor(story: Story) {\n this.story = story;\n\n this._currentFlow = new Flow(this.kDefaultFlowName, story);\n this.OutputStreamDirty();\n\n this._evaluationStack = [];\n\n this._variablesState = new VariablesState(\n this.callStack,\n story.listDefinitions\n );\n\n this._visitCounts = new Map();\n this._turnIndices = new Map();\n this.currentTurnIndex = -1;\n\n let timeSeed = new Date().getTime();\n this.storySeed = new PRNG(timeSeed).next() % 100;\n this.previousRandom = 0;\n\n this.GoToStart();\n }\n\n public GoToStart() {\n this.callStack.currentElement.currentPointer = Pointer.StartOf(\n this.story.mainContentContainer\n );\n }\n\n public SwitchFlow_Internal(flowName: string | null) {\n if (flowName === null)\n throw new Error(\"Must pass a non-null string to Story.SwitchFlow\");\n\n if (this._namedFlows === null) {\n this._namedFlows = new Map();\n this._namedFlows.set(this.kDefaultFlowName, this._currentFlow);\n }\n\n if (flowName === this._currentFlow.name) {\n return;\n }\n\n let flow: Flow;\n let content = tryGetValueFromMap(this._namedFlows, flowName, null);\n if (content.exists) {\n flow = content.result!;\n } else {\n flow = new Flow(flowName, this.story);\n this._namedFlows.set(flowName, flow);\n }\n\n this._currentFlow = flow;\n this.variablesState.callStack = this._currentFlow.callStack;\n\n this.OutputStreamDirty();\n }\n\n public SwitchToDefaultFlow_Internal() {\n if (this._namedFlows === null) return;\n this.SwitchFlow_Internal(this.kDefaultFlowName);\n }\n\n public RemoveFlow_Internal(flowName: string | null) {\n if (flowName === null)\n throw new Error(\"Must pass a non-null string to Story.DestroyFlow\");\n if (flowName === this.kDefaultFlowName)\n throw new Error(\"Cannot destroy default flow\");\n\n if (this._currentFlow.name === flowName) {\n this.SwitchToDefaultFlow_Internal();\n }\n\n if (this._namedFlows === null)\n return throwNullException(\"this._namedFlows\");\n this._namedFlows.delete(flowName);\n }\n\n public CopyAndStartPatching() {\n let copy = new StoryState(this.story);\n\n copy._patch = new StatePatch(this._patch);\n\n copy._currentFlow.name = this._currentFlow.name;\n copy._currentFlow.callStack = new CallStack(this._currentFlow.callStack);\n copy._currentFlow.currentChoices.push(...this._currentFlow.currentChoices);\n copy._currentFlow.outputStream.push(...this._currentFlow.outputStream);\n copy.OutputStreamDirty();\n\n if (this._namedFlows !== null) {\n copy._namedFlows = new Map();\n for (let [namedFlowKey, namedFlowValue] of this._namedFlows) {\n copy._namedFlows.set(namedFlowKey, namedFlowValue);\n }\n copy._namedFlows.set(this._currentFlow.name, copy._currentFlow);\n }\n\n if (this.hasError) {\n copy._currentErrors = [];\n copy._currentErrors.push(...(this.currentErrors || []));\n }\n\n if (this.hasWarning) {\n copy._currentWarnings = [];\n copy._currentWarnings.push(...(this.currentWarnings || []));\n }\n\n copy.variablesState = this.variablesState;\n copy.variablesState.callStack = copy.callStack;\n copy.variablesState.patch = copy._patch;\n\n copy.evaluationStack.push(...this.evaluationStack);\n\n if (!this.divertedPointer.isNull)\n copy.divertedPointer = this.divertedPointer.copy();\n\n copy.previousPointer = this.previousPointer.copy();\n\n copy._visitCounts = this._visitCounts;\n copy._turnIndices = this._turnIndices;\n\n copy.currentTurnIndex = this.currentTurnIndex;\n copy.storySeed = this.storySeed;\n copy.previousRandom = this.previousRandom;\n\n copy.didSafeExit = this.didSafeExit;\n\n return copy;\n }\n\n public RestoreAfterPatch() {\n this.variablesState.callStack = this.callStack;\n this.variablesState.patch = this._patch;\n }\n\n public ApplyAnyPatch() {\n if (this._patch === null) return;\n\n this.variablesState.ApplyPatch();\n\n for (let [key, value] of this._patch.visitCounts)\n this.ApplyCountChanges(key, value, true);\n\n for (let [key, value] of this._patch.turnIndices)\n this.ApplyCountChanges(key, value, false);\n\n this._patch = null;\n }\n\n public ApplyCountChanges(\n container: Container,\n newCount: number,\n isVisit: boolean\n ) {\n let counts = isVisit ? this._visitCounts : this._turnIndices;\n counts.set(container.path.toString(), newCount);\n }\n\n public WriteJson(writer: SimpleJson.Writer) {\n writer.WriteObjectStart();\n\n writer.WritePropertyStart(\"flows\");\n writer.WriteObjectStart();\n\n // NOTE: Never pass `WriteJson` directly as an argument to `WriteProperty`.\n // Call it inside a function to make sure `this` is correctly bound\n // and passed down the call hierarchy.\n\n if (this._namedFlows !== null) {\n for (let [namedFlowKey, namedFlowValue] of this._namedFlows) {\n writer.WriteProperty(namedFlowKey, (w) => namedFlowValue.WriteJson(w));\n }\n } else {\n writer.WriteProperty(this._currentFlow.name, (w) =>\n this._currentFlow.WriteJson(w)\n );\n }\n\n writer.WriteObjectEnd();\n writer.WritePropertyEnd();\n\n writer.WriteProperty(\"currentFlowName\", this._currentFlow.name);\n\n writer.WriteProperty(\"variablesState\", (w) =>\n this.variablesState.WriteJson(w)\n );\n\n writer.WriteProperty(\"evalStack\", (w) =>\n JsonSerialisation.WriteListRuntimeObjs(w, this.evaluationStack)\n );\n\n if (!this.divertedPointer.isNull) {\n if (this.divertedPointer.path === null) {\n return throwNullException(\"divertedPointer\");\n }\n writer.WriteProperty(\n \"currentDivertTarget\",\n this.divertedPointer.path.componentsString\n );\n }\n\n writer.WriteProperty(\"visitCounts\", (w) =>\n JsonSerialisation.WriteIntDictionary(w, this._visitCounts)\n );\n writer.WriteProperty(\"turnIndices\", (w) =>\n JsonSerialisation.WriteIntDictionary(w, this._turnIndices)\n );\n\n writer.WriteIntProperty(\"turnIdx\", this.currentTurnIndex);\n writer.WriteIntProperty(\"storySeed\", this.storySeed);\n writer.WriteIntProperty(\"previousRandom\", this.previousRandom);\n\n writer.WriteIntProperty(\"inkSaveVersion\", this.kInkSaveStateVersion);\n\n writer.WriteIntProperty(\"inkFormatVersion\", Story.inkVersionCurrent);\n\n writer.WriteObjectEnd();\n }\n\n public LoadJsonObj(value: Record) {\n let jObject = value;\n\n let jSaveVersion = jObject[\"inkSaveVersion\"];\n if (jSaveVersion == null) {\n throw new Error(\"ink save format incorrect, can't load.\");\n } else if (parseInt(jSaveVersion) < this.kMinCompatibleLoadVersion) {\n throw new Error(\n \"Ink save format isn't compatible with the current version (saw '\" +\n jSaveVersion +\n \"', but minimum is \" +\n this.kMinCompatibleLoadVersion +\n \"), so can't load.\"\n );\n }\n\n let flowsObj = jObject[\"flows\"];\n if (flowsObj != null) {\n let flowsObjDict = flowsObj as Record;\n\n // Single default flow\n if (Object.keys(flowsObjDict).length === 1) {\n this._namedFlows = null;\n } else if (this._namedFlows === null) {\n this._namedFlows = new Map();\n } else {\n this._namedFlows.clear();\n }\n\n let flowsObjDictEntries = Object.entries(flowsObjDict);\n for (let [namedFlowObjKey, namedFlowObjValue] of flowsObjDictEntries) {\n let name = namedFlowObjKey;\n let flowObj = namedFlowObjValue as Record;\n\n let flow = new Flow(name, this.story, flowObj);\n\n if (Object.keys(flowsObjDict).length === 1) {\n this._currentFlow = new Flow(name, this.story, flowObj);\n } else {\n if (this._namedFlows === null)\n return throwNullException(\"this._namedFlows\");\n this._namedFlows.set(name, flow);\n }\n }\n\n if (this._namedFlows != null && this._namedFlows.size > 1) {\n let currFlowName = jObject[\"currentFlowName\"] as string;\n // Adding a bang at the end, because we're trusting the save, as\n // done in upstream. If the save is corrupted, the execution\n // is undefined.\n this._currentFlow = this._namedFlows.get(currFlowName)!;\n }\n } else {\n this._namedFlows = null;\n this._currentFlow.name = this.kDefaultFlowName;\n this._currentFlow.callStack.SetJsonToken(\n jObject[\"callstackThreads\"] as Record,\n this.story\n );\n this._currentFlow.outputStream = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"outputStream\"] as any[]\n );\n this._currentFlow.currentChoices =\n JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"currentChoices\"] as any[]\n ) as Choice[];\n\n let jChoiceThreadsObj = jObject[\"choiceThreads\"];\n this._currentFlow.LoadFlowChoiceThreads(jChoiceThreadsObj, this.story);\n }\n\n this.OutputStreamDirty();\n\n this.variablesState.SetJsonToken(jObject[\"variablesState\"]);\n this.variablesState.callStack = this._currentFlow.callStack;\n\n this._evaluationStack = JsonSerialisation.JArrayToRuntimeObjList(\n jObject[\"evalStack\"]\n );\n\n let currentDivertTargetPath = jObject[\"currentDivertTarget\"];\n if (currentDivertTargetPath != null) {\n let divertPath = new Path(currentDivertTargetPath.toString());\n this.divertedPointer = this.story.PointerAtPath(divertPath);\n }\n\n this._visitCounts = JsonSerialisation.JObjectToIntDictionary(\n jObject[\"visitCounts\"]\n );\n this._turnIndices = JsonSerialisation.JObjectToIntDictionary(\n jObject[\"turnIndices\"]\n );\n this.currentTurnIndex = parseInt(jObject[\"turnIdx\"]);\n this.storySeed = parseInt(jObject[\"storySeed\"]);\n this.previousRandom = parseInt(jObject[\"previousRandom\"]);\n }\n\n public ResetErrors() {\n this._currentErrors = null;\n this._currentWarnings = null;\n }\n public ResetOutput(objs: InkObject[] | null = null) {\n this.outputStream.length = 0;\n if (objs !== null) this.outputStream.push(...objs);\n this.OutputStreamDirty();\n }\n\n public PushToOutputStream(obj: InkObject | null) {\n // var text = obj as StringValue;\n let text = asOrNull(obj, StringValue);\n if (text !== null) {\n let listText = this.TrySplittingHeadTailWhitespace(text);\n if (listText !== null) {\n for (let textObj of listText) {\n this.PushToOutputStreamIndividual(textObj);\n }\n this.OutputStreamDirty();\n return;\n }\n }\n\n this.PushToOutputStreamIndividual(obj);\n this.OutputStreamDirty();\n }\n\n public PopFromOutputStream(count: number) {\n this.outputStream.splice(this.outputStream.length - count, count);\n this.OutputStreamDirty();\n }\n\n public TrySplittingHeadTailWhitespace(single: StringValue) {\n let str = single.value;\n if (str === null) {\n return throwNullException(\"single.value\");\n }\n\n let headFirstNewlineIdx = -1;\n let headLastNewlineIdx = -1;\n for (let i = 0; i < str.length; i++) {\n let c = str[i];\n if (c == \"\\n\") {\n if (headFirstNewlineIdx == -1) headFirstNewlineIdx = i;\n headLastNewlineIdx = i;\n } else if (c == \" \" || c == \"\\t\") continue;\n else break;\n }\n\n let tailLastNewlineIdx = -1;\n let tailFirstNewlineIdx = -1;\n for (let i = str.length - 1; i >= 0; i--) {\n let c = str[i];\n if (c == \"\\n\") {\n if (tailLastNewlineIdx == -1) tailLastNewlineIdx = i;\n tailFirstNewlineIdx = i;\n } else if (c == \" \" || c == \"\\t\") continue;\n else break;\n }\n\n // No splitting to be done?\n if (headFirstNewlineIdx == -1 && tailLastNewlineIdx == -1) return null;\n\n let listTexts: StringValue[] = [];\n let innerStrStart = 0;\n let innerStrEnd = str.length;\n\n if (headFirstNewlineIdx != -1) {\n if (headFirstNewlineIdx > 0) {\n let leadingSpaces = new StringValue(\n str.substring(0, headFirstNewlineIdx)\n );\n listTexts.push(leadingSpaces);\n }\n listTexts.push(new StringValue(\"\\n\"));\n innerStrStart = headLastNewlineIdx + 1;\n }\n\n if (tailLastNewlineIdx != -1) {\n innerStrEnd = tailFirstNewlineIdx;\n }\n\n if (innerStrEnd > innerStrStart) {\n let innerStrText = str.substring(\n innerStrStart,\n innerStrEnd - innerStrStart\n );\n listTexts.push(new StringValue(innerStrText));\n }\n\n if (tailLastNewlineIdx != -1 && tailFirstNewlineIdx > headLastNewlineIdx) {\n listTexts.push(new StringValue(\"\\n\"));\n if (tailLastNewlineIdx < str.length - 1) {\n let numSpaces = str.length - tailLastNewlineIdx - 1;\n let trailingSpaces = new StringValue(\n str.substring(tailLastNewlineIdx + 1, numSpaces)\n );\n listTexts.push(trailingSpaces);\n }\n }\n\n return listTexts;\n }\n\n public PushToOutputStreamIndividual(obj: InkObject | null) {\n let glue = asOrNull(obj, Glue);\n let text = asOrNull(obj, StringValue);\n\n let includeInOutput = true;\n\n if (glue) {\n this.TrimNewlinesFromOutputStream();\n includeInOutput = true;\n } else if (text) {\n let functionTrimIndex = -1;\n let currEl = this.callStack.currentElement;\n if (currEl.type == PushPopType.Function) {\n functionTrimIndex = currEl.functionStartInOutputStream;\n }\n\n let glueTrimIndex = -1;\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let o = this.outputStream[i];\n let c = o instanceof ControlCommand ? o : null;\n let g = o instanceof Glue ? o : null;\n\n if (g != null) {\n glueTrimIndex = i;\n break;\n } else if (\n c != null &&\n c.commandType == ControlCommand.CommandType.BeginString\n ) {\n if (i >= functionTrimIndex) {\n functionTrimIndex = -1;\n }\n break;\n }\n }\n\n let trimIndex = -1;\n if (glueTrimIndex != -1 && functionTrimIndex != -1)\n trimIndex = Math.min(functionTrimIndex, glueTrimIndex);\n else if (glueTrimIndex != -1) trimIndex = glueTrimIndex;\n else trimIndex = functionTrimIndex;\n\n if (trimIndex != -1) {\n if (text.isNewline) {\n includeInOutput = false;\n } else if (text.isNonWhitespace) {\n if (glueTrimIndex > -1) this.RemoveExistingGlue();\n\n if (functionTrimIndex > -1) {\n let callStackElements = this.callStack.elements;\n for (let i = callStackElements.length - 1; i >= 0; i--) {\n let el = callStackElements[i];\n if (el.type == PushPopType.Function) {\n el.functionStartInOutputStream = -1;\n } else {\n break;\n }\n }\n }\n }\n } else if (text.isNewline) {\n if (this.outputStreamEndsInNewline || !this.outputStreamContainsContent)\n includeInOutput = false;\n }\n }\n\n if (includeInOutput) {\n if (obj === null) {\n return throwNullException(\"obj\");\n }\n this.outputStream.push(obj);\n this.OutputStreamDirty();\n }\n }\n\n public TrimNewlinesFromOutputStream() {\n let removeWhitespaceFrom = -1;\n\n let i = this.outputStream.length - 1;\n while (i >= 0) {\n let obj = this.outputStream[i];\n let cmd = asOrNull(obj, ControlCommand);\n let txt = asOrNull(obj, StringValue);\n\n if (cmd != null || (txt != null && txt.isNonWhitespace)) {\n break;\n } else if (txt != null && txt.isNewline) {\n removeWhitespaceFrom = i;\n }\n i--;\n }\n\n // Remove the whitespace\n if (removeWhitespaceFrom >= 0) {\n i = removeWhitespaceFrom;\n while (i < this.outputStream.length) {\n let text = asOrNull(this.outputStream[i], StringValue);\n if (text) {\n this.outputStream.splice(i, 1);\n } else {\n i++;\n }\n }\n }\n\n this.OutputStreamDirty();\n }\n\n public RemoveExistingGlue() {\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let c = this.outputStream[i];\n if (c instanceof Glue) {\n this.outputStream.splice(i, 1);\n } else if (c instanceof ControlCommand) {\n break;\n }\n }\n\n this.OutputStreamDirty();\n }\n\n get outputStreamEndsInNewline() {\n if (this.outputStream.length > 0) {\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let obj = this.outputStream[i];\n if (obj instanceof ControlCommand) break;\n let text = this.outputStream[i];\n if (text instanceof StringValue) {\n if (text.isNewline) return true;\n else if (text.isNonWhitespace) break;\n }\n }\n }\n\n return false;\n }\n\n get outputStreamContainsContent() {\n for (let content of this.outputStream) {\n if (content instanceof StringValue) return true;\n }\n return false;\n }\n\n get inStringEvaluation() {\n for (let i = this.outputStream.length - 1; i >= 0; i--) {\n let cmd = asOrNull(this.outputStream[i], ControlCommand);\n if (\n cmd instanceof ControlCommand &&\n cmd.commandType == ControlCommand.CommandType.BeginString\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n public PushEvaluationStack(obj: InkObject | null) {\n // var listValue = obj as ListValue;\n let listValue = asOrNull(obj, ListValue);\n if (listValue) {\n // Update origin when list is has something to indicate the list origin\n let rawList = listValue.value;\n if (rawList === null) {\n return throwNullException(\"rawList\");\n }\n\n if (rawList.originNames != null) {\n if (!rawList.origins) rawList.origins = [];\n rawList.origins.length = 0;\n\n for (let n of rawList.originNames) {\n if (this.story.listDefinitions === null)\n return throwNullException(\"StoryState.story.listDefinitions\");\n let def = this.story.listDefinitions.TryListGetDefinition(n, null);\n if (def.result === null)\n return throwNullException(\"StoryState def.result\");\n if (rawList.origins.indexOf(def.result) < 0)\n rawList.origins.push(def.result);\n }\n }\n }\n\n if (obj === null) {\n return throwNullException(\"obj\");\n }\n this.evaluationStack.push(obj);\n }\n\n public PopEvaluationStack(): InkObject;\n public PopEvaluationStack(numberOfObjects: number): InkObject[];\n public PopEvaluationStack(numberOfObjects?: number) {\n if (typeof numberOfObjects === \"undefined\") {\n let obj = this.evaluationStack.pop();\n return nullIfUndefined(obj);\n } else {\n if (numberOfObjects > this.evaluationStack.length) {\n throw new Error(\"trying to pop too many objects\");\n }\n\n let popped = this.evaluationStack.splice(\n this.evaluationStack.length - numberOfObjects,\n numberOfObjects\n );\n return nullIfUndefined(popped);\n }\n }\n\n public PeekEvaluationStack() {\n return this.evaluationStack[this.evaluationStack.length - 1];\n }\n\n public ForceEnd() {\n this.callStack.Reset();\n\n this._currentFlow.currentChoices.length = 0;\n\n this.currentPointer = Pointer.Null;\n this.previousPointer = Pointer.Null;\n\n this.didSafeExit = true;\n }\n\n public TrimWhitespaceFromFunctionEnd() {\n Debug.Assert(this.callStack.currentElement.type == PushPopType.Function);\n let functionStartPoint =\n this.callStack.currentElement.functionStartInOutputStream;\n\n if (functionStartPoint == -1) {\n functionStartPoint = 0;\n }\n\n for (let i = this.outputStream.length - 1; i >= functionStartPoint; i--) {\n let obj = this.outputStream[i];\n let txt = asOrNull(obj, StringValue);\n let cmd = asOrNull(obj, ControlCommand);\n\n if (txt == null) continue;\n if (cmd) break;\n\n if (txt.isNewline || txt.isInlineWhitespace) {\n this.outputStream.splice(i, 1);\n this.OutputStreamDirty();\n } else {\n break;\n }\n }\n }\n\n public PopCallStack(popType: PushPopType | null = null) {\n if (this.callStack.currentElement.type == PushPopType.Function)\n this.TrimWhitespaceFromFunctionEnd();\n\n this.callStack.Pop(popType);\n }\n\n public SetChosenPath(path: Path, incrementingTurnIndex: boolean) {\n // Changing direction, assume we need to clear current set of choices\n this._currentFlow.currentChoices.length = 0;\n\n let newPointer = this.story.PointerAtPath(path);\n if (!newPointer.isNull && newPointer.index == -1) newPointer.index = 0;\n\n this.currentPointer = newPointer;\n\n if (incrementingTurnIndex) {\n this.currentTurnIndex++;\n }\n }\n\n public StartFunctionEvaluationFromGame(\n funcContainer: Container,\n args: any[]\n ) {\n this.callStack.Push(\n PushPopType.FunctionEvaluationFromGame,\n this.evaluationStack.length\n );\n this.callStack.currentElement.currentPointer =\n Pointer.StartOf(funcContainer);\n\n this.PassArgumentsToEvaluationStack(args);\n }\n\n public PassArgumentsToEvaluationStack(args: any[] | null) {\n if (args !== null) {\n for (let i = 0; i < args.length; i++) {\n if (\n !(typeof args[i] === \"number\" || typeof args[i] === \"string\") ||\n args[i] instanceof InkList\n ) {\n throw new Error(\n \"ink arguments when calling EvaluateFunction / ChoosePathStringWithParameters must be\" +\n \"number, string or InkList. Argument was \" +\n (nullIfUndefined(arguments[i]) === null)\n ? \"null\"\n : arguments[i].constructor.name\n );\n }\n\n this.PushEvaluationStack(Value.Create(args[i]));\n }\n }\n }\n\n public TryExitFunctionEvaluationFromGame() {\n if (\n this.callStack.currentElement.type ==\n PushPopType.FunctionEvaluationFromGame\n ) {\n this.currentPointer = Pointer.Null;\n this.didSafeExit = true;\n return true;\n }\n\n return false;\n }\n\n public CompleteFunctionEvaluationFromGame() {\n if (\n this.callStack.currentElement.type !=\n PushPopType.FunctionEvaluationFromGame\n ) {\n throw new Error(\n \"Expected external function evaluation to be complete. Stack trace: \" +\n this.callStack.callStackTrace\n );\n }\n\n let originalEvaluationStackHeight =\n this.callStack.currentElement.evaluationStackHeightWhenPushed;\n\n let returnedObj: InkObject | null = null;\n while (this.evaluationStack.length > originalEvaluationStackHeight) {\n let poppedObj = this.PopEvaluationStack();\n if (returnedObj === null) returnedObj = poppedObj;\n }\n\n this.PopCallStack(PushPopType.FunctionEvaluationFromGame);\n\n if (returnedObj) {\n if (returnedObj instanceof Void) return null;\n\n // Some kind of value, if not void\n // var returnVal = returnedObj as Runtime.Value;\n let returnVal = asOrThrows(returnedObj, Value);\n\n // DivertTargets get returned as the string of components\n // (rather than a Path, which isn't public)\n if (returnVal.valueType == ValueType.DivertTarget) {\n return returnVal.valueObject.toString();\n }\n\n // Other types can just have their exact object type:\n // int, float, string. VariablePointers get returned as strings.\n return returnVal.valueObject;\n }\n\n return null;\n }\n\n public AddError(message: string, isWarning: boolean) {\n if (!isWarning) {\n if (this._currentErrors == null) this._currentErrors = [];\n this._currentErrors.push(message);\n } else {\n if (this._currentWarnings == null) this._currentWarnings = [];\n this._currentWarnings.push(message);\n }\n }\n\n public OutputStreamDirty() {\n this._outputStreamTextDirty = true;\n this._outputStreamTagsDirty = true;\n }\n\n private _visitCounts: Map;\n private _turnIndices: Map;\n\n private _outputStreamTextDirty = true;\n private _outputStreamTagsDirty = true;\n\n private _patch: StatePatch | null = null;\n\n private _currentFlow: Flow;\n private _namedFlows: Map | null = null;\n private readonly kDefaultFlowName = \"DEFAULT_FLOW\";\n}\n","// This is simple replacement of the Stopwatch class from the .NET Framework.\n// The original class can count time with much more accuracy than the Javascript version.\n// It might be worth considering using `window.performance` in the browser\n// or `process.hrtime()` in node.\nexport class Stopwatch {\n private startTime: number | undefined;\n\n constructor() {\n this.startTime = undefined;\n }\n\n get ElapsedMilliseconds(): number {\n if (typeof this.startTime === \"undefined\") {\n return 0;\n }\n return new Date().getTime() - this.startTime;\n }\n\n public Start() {\n this.startTime = new Date().getTime();\n }\n public Stop() {\n this.startTime = undefined;\n }\n}\n"],"names":["Debug","Path","_components","_componentsString","_isRelative","arguments","componentsString","Component","head","tail","push","this","concat","Array","relative","length","slice","self","lastComponentIdx","i","l","isIndex","index","pathToAppend","p","upwardMoves","isParent","join","isRelative","value","substring","split","str","test","parseInt","otherPath","Equals","c","path","asOrNull","obj","type","unsafeTypeAssertion","asOrThrows","Error","asINamedContentOrNull","hasValidName","name","nullIfUndefined","isEquatable","_typeof","indexOrName","parentId","toString","otherComp","Assert","condition","message","console","warn","trace","variable","NullException","throwNullException","InkObject","_debugMetadata","parent","debugMetadata","root","rootContentContainer","targetContent","ContentAtPath","dm","startLineNumber","_path","comps","child","container","Container","namedChild","unshift","content","indexOf","nearestContainer","GetComponent","contentContainer","globalPath","ownPath","minPathLength","Math","min","lastSharedPathCompIndex","ownComp","numUpwardsMoves","componentCount","newPathComps","up","ToParent","down","globalPathStr","relativePathStr","PathByAppendingPath","ConvertPathToRelative","ancestor","prop","StringBuilder","string","Append","format","args","replace","match","num","InkListItem","originName","itemName","fullName","nameParts","otherItem","JSON","stringify","key","parse","isLikeInkListItem","Null","inkListItem","item","hasOwnProperty","InkList","otherList","_originNames","originNames","origins","singleOriginListName","originStory","SetInitialOriginName","listDefinitions","def","TryListGetDefinition","exists","result","singleElement","Add","Key","Value","itemOrItemName","AddItem","origin","intVal","TryGetValueForItem","foundListDef","ContainsItemWithName","itemVal","ValueForItem","fromSerializedKey","has","serialized","serializedKey","set","delete","size","maxOriginName","maxItem","every","Count","initialOriginName","initialOriginNames","max","isNull","list","items","ContainsKey","union","intersection","listToRemove","minItem","minBound","maxBound","ordered","orderedItems","minValue","maxValue","Number","MAX_SAFE_INTEGER","isInteger","subList","SetInitialOriginNames","otherInkList","sort","x","y","localeCompare","sb","NaN","myListItem","listValue","FindSingleItemListWithName","Map","StoryException","useEndLineNumber","tryGetValueFromMap","map","val","get","ValueType","AbstractValue","Create","valueObject","targetType","valueType","preferredNumberType","Int","IntValue","Float","isNaN","FloatValue","BoolValue","Boolean","StringValue","String","DivertTargetValue","ListValue","Bool","newType","BadCastException","_isNewline","_this2","_isInlineWhitespace","isNewline","isInlineWhitespace","parsedInt","defaultValue","tryParseInt","parsedFloat","parseFloat","tryParseFloat","targetPath","DivertTarget","VariablePointerValue","variableName","contextIndex","_contextIndex","VariablePointer","listOrSingleItem","singleValue","List","oldValue","newValue","oldList","newList","SearchResult","approximate","searchResult","_content","AddContent","namedOnlyContentDict","namedContent","inkObject","named","existingNamedOnly","namedOnlyContent","AddToNamedContentOnly","flags","visitsShouldBeCounted","CountFlags","Visits","turnIndexShouldBeCounted","Turns","countingAtStartOnly","CountStartOnly","flag","_pathToFirstLeafContent","internalPathToFirstLeafContent","components","contentObjOrList","contentObj","TryAddNamedContent","namedContentObj","AssertType","partialPathStart","partialPathLength","currentContainer","currentObj","comp","foundObj","ContentWithPathComponent","splice","otherContainer","component","foundContent","BuildStringOfHierarchy","indentation","pointedObj","appendIndentation","AppendFormat","AppendLine","onlyNamed","PushPopType","Glue","ControlCommand","commandType","CommandType","NotSet","_commandType","EvalStart","EvalOutput","EvalEnd","Duplicate","PopEvaluatedValue","PopFunction","PopTunnel","BeginString","EndString","NoOp","ChoiceCount","TurnsSince","ReadCount","Random","SeedRandom","VisitIndex","SequenceShuffleIndex","StartThread","Done","End","ListFromInt","ListRange","ListRandom","Pointer","PathByAppendingComponent","Divert","stackPushType","pushesToStack","_targetPath","targetObj","targetPointer","Resolve","_targetPointer","ResolvePath","lastComponent","StartOf","copy","CompactPathString","variableDivertName","otherDivert","hasVariableTarget","targetStr","isConditional","Function","targetPathString","ChoicePoint","onceOnly","_pathOnChoice","choiceTargetObj","choiceTarget","pathOnChoice","hasCondition","hasStartContent","hasChoiceOnlyContent","isInvisibleDefault","VariableReference","pathForCount","pathStringForCount","VariableAssignment","isNewDeclaration","isGlobal","Void","NativeFunctionCall","GenerateNativeFunctionsIfNecessary","numberOfParameters","_isPrototype","_name","_nativeFunctions","_prototype","_numberOfParameters","parameters","Call","hasList","CallBinaryListOperation","coercedParams","CoerceValuesToSingleType","coercedType","CallType","parametersOfSingleType","param1","valType","val1","paramCount","_operationFuncs","opForTypeObj","val2","opForType","resultVal","CallListIncrementOperation","v1","v2","op","asBooleanOrThrows","isTruthy","listIntParams","listVal","resultInkList","listItemKey","listItemValue","listItem","intOp","targetInt","itemOrigin","incrementedItem","TryGetItemWithValue","parametersIn","specialCaseList","parametersOut","originOfMaxItem","castedValue","Cast","functionName","t","AddIntBinaryOp","Subtract","Multiply","Divide","floor","Mod","AddIntUnaryOp","Negate","Equal","Greater","Less","GreaterThanOrEquals","LessThanOrEquals","NotEquals","Not","And","Or","Max","Min","Pow","pow","Floor","Identity","Ceiling","AddFloatBinaryOp","AddFloatUnaryOp","ceil","AddStringBinaryOp","Has","includes","Hasnt","AddListBinaryOp","Union","Without","Contains","Intersect","GreaterThan","LessThan","AddListUnaryOp","Invert","inverse","All","all","ListMin","MinAsList","ListMax","MaxAsList","ValueOfList","AddOpToNativeFunc","d1","d2","nativeFunc","AddOpFuncForType","Tag","tagText","text","Choice","ListDefinition","_items","_itemNameToValues","ListDefinitionsOrigin","lists","_lists","_allUnambiguousListValueCache","listOfLists","definition","JsonSerialisation","jArray","skipLast","count","jTok","runtimeObj","JTokenToRuntimeObject","writer","dictionary","WriteObjectStart","WritePropertyStart","WriteRuntimeObject","WritePropertyEnd","WriteObjectEnd","WriteArrayStart","WriteArrayEnd","dict","WriteIntProperty","WriteRuntimeContainer","divert","divTypeKey","isExternal","Tunnel","WriteProperty","externalArgs","choicePoint","pathStringOnChoice","boolVal","WriteBool","WriteInt","floatVal","WriteFloat","strVal","Write","WriteStringStart","WriteStringInner","WriteStringEnd","WriteInkList","divTargetVal","varPtrVal","controlCmd","_controlCommandNames","varRef","readCountPath","varAss","tag","choice","WriteChoice","jObject","token","firstChar","CallExistsWithName","CallWithName","isArray","propValue","varPtr","isDivert","divPushType","external","target","readCountVarRef","isVarAss","isGlobalVar","varName","isNewDecl","undefined","listContent","rawList","namesAsObjs","nameToVal","JObjectToChoice","JArrayToContainer","toJson","me","removes","space","k","v","some","r","withoutName","countFlags","hasNameProperty","hasTerminator","namedContainer","WriteNull","JArrayToRuntimeObjList","terminatingObj","namedContentItem","namedSubContainer","jObj","sourcePath","originalThreadIndex","WritePropertyNameStart","WritePropertyNameInner","WritePropertyNameEnd","listDefJson","defsObj","allDefs","nameValueKey","nameValue","TOTAL_VALUES","CallStack","Story","storyContext","_startOfRoot","Reset","toCopy","_threads","otherThread","Copy","_threadCounter","callStack","elements","cs","callstack","Thread","Element","jThreadObj","thread","w","WriteObject","_this","WriteJson","newThread","currentThread","threadIndex","forkedThread","canPopThread","elementIsEvaluateFromGame","currentElement","FunctionEvaluationFromGame","externalEvaluationStackHeight","outputStreamLengthWithPushed","element","currentPointer","evaluationStackHeightWhenPushed","functionStartInOutputStream","canPop","CanPop","pop","currentElementIndex","contextElement","varValue","temporaryVariables","declareNew","RetainListOriginsForAssignment","filtered","filter","isCurrent","pointer","inExpressionEvaluation","jThreadCallstack","jElTok","jElementObj","pushPopType","currentContainerPathStr","currentContainerPathStrToken","threadPointerResult","Warning","el","temps","JObjectToDictionaryRuntimeObjs","clear","prevContentObjPath","prevPath","previousPointer","PointerAtPath","e","WriteDictionaryRuntimeObjs","resolvedPointer","VariablesState","listDefsOrigin","Set","_globalVariables","_callStack","_listDefsOrigin","Proxy","$","variableChangedEventCallbacks","callback","_batchObservingVariableChanges","_changedVariablesForBatchObs","currentValue","variableChangedEvent","varContents","patch","TryGetGlobal","_defaultGlobalVariables","SetGlobal","globals","namedVarKey","namedVarValue","changedVariables","add","jToken","varValKey","varValValue","loadedToken","tokenInkObject","keyValKey","keyValValue","dontSaveDefaultValues","defaultVal","RuntimeObjectsEqual","obj1","obj2","constructor","GetRawVariableWithName","varPointer","ValueAtVariablePointer","variableValue","GetTemporaryVariableWithName","GetVariableWithName","setGlobal","GlobalVariableExistsWithName","ResolveVariablePointer","existingPointer","SetTemporaryVariable","batchObservingVariableChanges","AddChangedVariable","GetContextIndexOfVariableNamed","doubleRedirectionPointer","PRNG","seed","next","StatePatch","_globals","_changedVariables","_visitCounts","_turnIndices","SimpleJson","Reader","ToDictionary","ToArray","_rootObject","Writer","inner","StartNewObject","newObject","state","State","Property","currentCollection","currentPropertyName","propertyName","_propertyNameStack","_collectionStack","None","_jsonObject","_stateStack","StateElement","Object","innerOrContent","IncrementChildCount","childCount","_currentPropertyName","PropertyName","_addToCurrentObject","error","POSITIVE_INFINITY","NEGATIVE_INFINITY","_currentString","currEl","ErrorType","OutputStateChange","Flow","story","SetJsonToken","outputStream","currentChoices","jChoiceThreadsObj","LoadFlowChoiceThreads","WriteListRuntimeObjs","hasChoiceThreads","threadAtGeneration","ThreadWithIndex","jChoiceThreads","foundActiveThread","jSavedChoiceThread","StoryState","_currentFlow","kDefaultFlowName","OutputStreamDirty","_evaluationStack","_variablesState","currentTurnIndex","timeSeed","Date","getTime","storySeed","previousRandom","GoToStart","indented","ToJson","json","TextToDictionary","LoadJsonObj","onDidLoadState","pathString","visitCountOut","_patch","TryGetVisitCount","containerPathStr","count2","currCount","VisitCountForContainer","SetVisitCount","SetTurnIndex","TryGetTurnIndex","index2","depth","canContinue","_currentErrors","_currentWarnings","_currentTurnIndex","hasError","currentErrors","currentWarnings","_outputStreamTextDirty","textContent","_currentText","CleanOutputWhitespace","currentWhitespaceStart","startOfLine","charAt","_outputStreamTagsDirty","_currentTags","mainContentContainer","flowName","_namedFlows","flow","variablesState","SwitchFlow_Internal","SwitchToDefaultFlow_Internal","namedFlowKey","namedFlowValue","hasWarning","evaluationStack","divertedPointer","didSafeExit","ApplyPatch","visitCounts","ApplyCountChanges","turnIndices","newCount","isVisit","WriteIntDictionary","kInkSaveStateVersion","inkVersionCurrent","jSaveVersion","kMinCompatibleLoadVersion","flowsObj","flowsObjDict","keys","entries","flowObj","currFlowName","currentDivertTargetPath","divertPath","JObjectToIntDictionary","objs","listText","TrySplittingHeadTailWhitespace","textObj","PushToOutputStreamIndividual","single","headFirstNewlineIdx","headLastNewlineIdx","tailLastNewlineIdx","tailFirstNewlineIdx","listTexts","innerStrStart","innerStrEnd","leadingSpaces","innerStrText","numSpaces","trailingSpaces","glue","includeInOutput","TrimNewlinesFromOutputStream","functionTrimIndex","glueTrimIndex","o","isNonWhitespace","RemoveExistingGlue","callStackElements","outputStreamEndsInNewline","outputStreamContainsContent","removeWhitespaceFrom","cmd","txt","n","numberOfObjects","functionStartPoint","popType","TrimWhitespaceFromFunctionEnd","Pop","incrementingTurnIndex","newPointer","funcContainer","Push","PassArgumentsToEvaluationStack","PushEvaluationStack","callStackTrace","originalEvaluationStackHeight","returnedObj","poppedObj","PopEvaluationStack","PopCallStack","returnVal","isWarning","Stopwatch","startTime","nVal","isFinite","_mainContentContainer","jsonString","_listDefinitions","_externals","rootObject","versionObj","formatFromFile","inkVersionMinimumCompatible","listDefsObj","rootToken","JTokenToListDefinitions","ResetState","choices","_state","IfAsyncWeCant","currentText","currentTags","currentFlowName","shouldReturn","ObserveVariableChange","VariableStateDidChangeEvent","bind","ResetGlobals","ResetErrors","ForceEnd","originalPointer","ChoosePath","ContinueInternal","SnapshotDefaultGlobals","_asyncSaving","RemoveFlow_Internal","ContinueAsync","_asyncContinueActive","millisecsLimitAsync","_hasValidatedExternals","ValidateExternalBindings","_profiler","PreContinue","isAsyncTimeLimited","_recursiveContinueCount","ResetOutput","durationStopwatch","Start","_sawLookaheadUnsafeFunctionAfterNewline","ContinueSingleStep","AddError","ElapsedMilliseconds","Stop","_stateSnapshotAtLastNewline","RestoreStateSnapshot","generatedChoices","_temporaryEvaluationContainer","onDidContinue","PostContinue","onError","err","PreStep","Step","PostStep","TryFollowDefaultInvisibleChoice","PreSnapshot","inStringEvaluation","change","CalculateNewlineOutputStateChange","ExtendedBeyondNewline","NewlineRemoved","DiscardSnapshot","StateSnapshot","PostSnapshot","prevText","currText","prevTagCount","currTagCount","newlineStillExists","NoChange","Continue","pathLengthToUse","CopyAndStartPatching","RestoreAfterPatch","ApplyAnyPatch","stateToSave","shouldAddToStream","containerToEnter","VisitContainer","currentContentObj","isLogicOrFlowControl","PerformLogicAndFlowControl","ProcessChoice","contextIdx","ContextForVariableNamed","PushToOutputStream","NextContent","PushThread","atStart","IncrementVisitCountForContainer","RecordTurnIndexVisitToContainer","_prevContainers","prevAncestor","currentChildOfContainer","currentContainerAncestor","allChildrenEnteredAtStart","enteringAtStart","showChoice","conditionValue","IsTruthy","startText","choiceOnlyText","ForkThread","divTarget","currentDivert","intContent","errorMessage","CallExternalFunction","sourceName","evalCommand","output","PeekEvaluationStack","overrideTunnelReturnTarget","popped","TryExitFunctionEvaluationFromGame","names","expected","errorMsg","contentStackForString","outputCountConsumed","command","PopFromOutputStream","reverse","choiceCount","extraNote","eitherCount","divertTarget","correctObj","TurnsSinceForContainer","maxInt","minInt","randomRange","resultSeed","nextRandom","chosenValue","shuffleIndex","NextSequenceShuffleIndex","PopThread","listNameVal","generatedListValue","foundItem","targetList","ListWithSubRange","listItemIndex","listEnumerator","randomItem","assignedVal","Assign","foundValue","containerForCount","func","funcParams","resetCallstack","onChoosePathString","ResetCallstack","funcDetail","activityStr","SetChosenPath","VisitChangedContainersDueToDivert","choiceIdx","choiceToChoose","onMakeChoice","KnotContainerWithName","returnTextOutput","onEvaluateFunction","trim","outputStreamBefore","StartFunctionEvaluationFromGame","stringOutput","textOutput","CompleteFunctionEvaluationFromGame","onCompleteEvaluateFunction","returned","exprContainer","startCallStackHeight","evalStackHeight","funcName","numberOfArguments","funcDef","fallbackFunctionContainer","foundExternal","lookAheadSafe","allowExternalFunctionFallbacks","valueObj","funcResult","function","returnObj","lookaheadSafe","BindExternalFunctionGeneral","_this3","coercedArgs","TryCoerce","apply","missingExternals","from","innerContent","fallbackFound","observer","_variableObservers","variableNames","observers","ObserveVariable","specificVariableName","variableObservers","newValueObj","TagsAtStartOfFlowContainerWithPathString","flowContainer","firstContent","tags","IncrementContentPointer","didPop","successfulIncrement","nextAncestor","indexInAncestor","allChoices","invisibleChoices","numElementsIntVal","seqContainer","numElements","seqCount","loopIndex","iterationIndex","seqPathStr","sequenceHash","charCodeAt","randomSeed","random","unpickedIndices","chosen","chosenIndex","currentDebugMetadata","errorTypeStr","lineNum","endLineNumber","fileName"],"mappings":"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"} \ No newline at end of file diff --git a/prototype/inkjs-full-posixhandler.js b/prototype/inkjs-full-posixhandler.js new file mode 100644 index 0000000..570fe1a --- /dev/null +++ b/prototype/inkjs-full-posixhandler.js @@ -0,0 +1 @@ +"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("path"),t=require("fs");function r(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var n=r(e),o=r(t);function i(e,t){for(var r=0;r)/u).forEach(function (fragment) { + let fragmentWidth = measureText(fragment); + + if (fragment === ' ') { + let stretch = (spaceWidth * 3) / 6; + let shrink = (spaceWidth * 3) / 9; + + nodes.push(linebreak.glue(spaceWidth, stretch, shrink)); + } else if (fragment === '|') { + // nodes.push(linebreak.penalty(hyphenWidth, 100, 1)); + nodes.push(linebreak.penalty(hyphenWidth * 0.25, 100, 1)); + } else if (fragment.match(/(<.*?>)/u)) { + nodes.push(linebreak.tag(fragmentWidth, fragment)); + } else if (fragment.match(/[.,:;!?] /u)) { + let punctuation = fragment.match(/([.,:;!?])( )/u); + let punctuationSymbolWidth = measureText(punctuation[1]) * 0.25; + let punctuationWidth = measureText(punctuation[1]) * 0.75 + spaceWidth; + nodes.push(linebreak.box(punctuationSymbolWidth, punctuation[1])); + let stretch = (punctuationWidth * 3) / 6; + let shrink = (punctuationWidth * 3) / 9; + + nodes.push(linebreak.glue(punctuationWidth, stretch, shrink)); + } else if (fragment.match(/(\s+)/u)) { + + } else { + nodes.push(linebreak.box(fragmentWidth, fragment)); + } + }); + + nodes.push(linebreak.glue(0, linebreak.infinity, 0)); + nodes.push(linebreak.penalty(0, -linebreak.infinity, 1)); + + let demerits = { + line: 10, + flagged: 100, + fitness: 3000 + }; + + let breaks = linebreak(nodes, measure, { tolerance: 3, demerits }); + + if (!breaks.length) { + breaks = linebreak(nodes, measure, { tolerance: 10, demerits }); + } + + return { nodes, breaks }; +} diff --git a/prototype/linebreak.js b/prototype/linebreak.js new file mode 100644 index 0000000..526dba0 --- /dev/null +++ b/prototype/linebreak.js @@ -0,0 +1,334 @@ +var linebreak = function (nodes, lines, settings = { + demerits: { + line: 10, + flagged: 100, + fitness: 3000 + }, + tolerance: 2 +}) { + const options = settings; + activeNodes = new LinkedList(), + sum = { + width: 0, + stretch: 0, + shrink: 0 + }, + lineLengths = lines, + breaks = [], + tmp = { + data: { + demerits: Infinity + } + }; + + function breakpoint(position, demerits, ratio, line, fitnessClass, totals, previous) { + return { + position: position, + demerits: demerits, + ratio: ratio, + line: line, + fitnessClass: fitnessClass, + totals: totals || { + width: 0, + stretch: 0, + shrink: 0 + }, + previous: previous + }; + } + + function computeCost(start, end, active, currentLine) { + var width = sum.width - active.totals.width, + stretch = 0, + shrink = 0, + // If the current line index is within the list of linelengths, use it, otherwise use + // the last line length of the list. + lineLength = currentLine < lineLengths.length ? lineLengths[currentLine - 1] : lineLengths[lineLengths.length - 1]; + + if (nodes[end].type === 'penalty') { + width += nodes[end].width; + } + + if (width < lineLength) { + // Calculate the stretch ratio + stretch = sum.stretch - active.totals.stretch; + + if (stretch > 0) { + return (lineLength - width) / stretch; + } else { + return linebreak.infinity; + } + + } else if (width > lineLength) { + // Calculate the shrink ratio + shrink = sum.shrink - active.totals.shrink; + + if (shrink > 0) { + return (lineLength - width) / shrink; + } else { + return linebreak.infinity; + } + } else { + // perfect match + return 0; + } + } + + + // Add width, stretch and shrink values from the current + // break point up to the next box or forced penalty. + function computeSum(breakPointIndex) { + var result = { + width: sum.width, + stretch: sum.stretch, + shrink: sum.shrink + }, + i = 0; + + for (i = breakPointIndex; i < nodes.length; i += 1) { + if (nodes[i].type === 'glue') { + result.width += nodes[i].width; + result.stretch += nodes[i].stretch; + result.shrink += nodes[i].shrink; + } else if (nodes[i].type === 'box' || (nodes[i].type === 'penalty' && nodes[i].penalty === -linebreak.infinity && i > breakPointIndex)) { + break; + } + } + return result; + } + + let graphNodes = []; + let graphEdges = []; + + // The main loop of the algorithm + function mainLoop(node, index, nodes) { + var active = activeNodes.first, + next = null, + ratio = 0, + demerits = 0, + candidates = [], + badness, + currentLine = 0, + tmpSum, + currentClass = 0, + fitnessClass, + candidate, + newNode; + + // The inner loop iterates through all the active nodes with line < currentLine and then + // breaks out to insert the new active node candidates before looking at the next active + // nodes for the next lines. The result of this is that the active node list is always + // sorted by line number. + while (active !== null) { + + candidates = [{ + demerits: Infinity + }, { + demerits: Infinity + }, { + demerits: Infinity + }, { + demerits: Infinity + }]; + + // Iterate through the linked list of active nodes to find new potential active nodes + // and deactivate current active nodes. + while (active !== null) { + next = active.next; + currentLine = active.data.line + 1; + ratio = computeCost(active.data.position, index, active.data, currentLine); + + // Deactive nodes when the distance between the current active node and the + // current node becomes too large (i.e. it exceeds the stretch limit and the stretch + // ratio becomes negative) or when the current node is a forced break (i.e. the end + // of the paragraph when we want to remove all active nodes, but possibly have a final + // candidate active node---if the paragraph can be set using the given tolerance value.) + if (ratio < -1 || (node.type === 'penalty' && node.penalty === -linebreak.infinity)) { + activeNodes.remove(active); + } + + // If the ratio is within the valid range of -1 <= ratio <= tolerance calculate the + // total demerits and record a candidate active node. + if (-1 <= ratio && ratio <= options.tolerance) { + badness = 100 * Math.pow(Math.abs(ratio), 3); + + // Positive penalty + if (node.type === 'penalty' && node.penalty >= 0) { + demerits = Math.pow(options.demerits.line + badness, 2) + Math.pow(node.penalty, 2); + // Negative penalty but not a forced break + } else if (node.type === 'penalty' && node.penalty !== -linebreak.infinity) { + demerits = Math.pow(options.demerits.line + badness, 2) - Math.pow(node.penalty, 2); + // All other cases + } else { + demerits = Math.pow(options.demerits.line + badness, 2); + } + + if (node.type === 'penalty' && nodes[active.data.position].type === 'penalty') { + demerits += options.demerits.flagged * node.flagged * nodes[active.data.position].flagged; + } + + // Calculate the fitness class for this candidate active node. + if (ratio < -0.5) { + currentClass = 0; + } else if (ratio <= 0.5) { + currentClass = 1; + } else if (ratio <= 1) { + currentClass = 2; + } else { + currentClass = 3; + } + + // Add a fitness penalty to the demerits if the fitness classes of two adjacent lines + // differ too much. + if (Math.abs(currentClass - active.data.fitnessClass) > 1) { + demerits += options.demerits.fitness; + } + + // Add the total demerits of the active node to get the total demerits of this candidate node. + demerits += active.data.demerits; + + // Only store the best candidate for each fitness class + if (demerits < candidates[currentClass].demerits) { + candidates[currentClass] = { + active: active, + demerits: demerits, + ratio: ratio + }; + } + } + + active = next; + + // Stop iterating through active nodes to insert new candidate active nodes in the active list + // before moving on to the active nodes for the next line. + // TODO: The Knuth and Plass paper suggests a conditional for currentLine < j0. This means paragraphs + // with identical line lengths will not be sorted by line number. Find out if that is a desirable outcome. + // For now I left this out, as it only adds minimal overhead to the algorithm and keeping the active node + // list sorted has a higher priority. + if (active !== null && active.data.line >= currentLine) { + break; + } + } + + tmpSum = computeSum(index); + + for (fitnessClass = 0; fitnessClass < candidates.length; fitnessClass += 1) { + candidate = candidates[fitnessClass]; + + if (candidate.demerits < Infinity) { + newNode = new Node(breakpoint(index, candidate.demerits, candidate.ratio, + candidate.active.data.line + 1, fitnessClass, tmpSum, candidate.active)); + + graphNodes.push({ + id: index + }); + + graphEdges.push({ + from: index, + to: candidate.active.data.position, + label: candidate.ratio.toFixed(2) + }); + + if (active !== null) { + activeNodes.insertBefore(active, newNode); + } else { + activeNodes.push(newNode); + } + } + } + } + } + + // Add an active node for the start of the paragraph. + activeNodes.push(new Node(breakpoint(0, 0, 0, 0, 0, undefined, null))); + + graphNodes.push({ + id: 0 + }); + + nodes.forEach(function (node, index, nodes) { + if (node.type === 'box') { + sum.width += node.width; + } else if (node.type === 'glue') { + if (index > 0 && nodes[index - 1].type === 'box') { + mainLoop(node, index, nodes); + } + sum.width += node.width; + sum.stretch += node.stretch; + sum.shrink += node.shrink; + } else if (node.type === 'penalty' && node.penalty !== linebreak.infinity) { + mainLoop(node, index, nodes); + } + }); + + + if (activeNodes.size !== 0) { + // Find the best active node (the one with the least total demerits.) + activeNodes.forEach(function (node) { + if (node.data.demerits < tmp.data.demerits) { + tmp = node; + } + }); + + graphNodes.forEach(function (n) { + let label = nodes[n.id].value; + + if (nodes[n.id].type === 'glue') { + label = nodes[n.id - 1].value; + } else if (nodes[n.id].type === 'penalty') { + label = nodes[n.id - 1].value; + } else { + label = nodes[n.id].value; + } + n.label = label; + }); + + while (tmp !== null) { + breaks.push({ + position: tmp.data.position, + ratio: tmp.data.ratio + }); + tmp = tmp.data.previous; + } + return breaks.reverse(); + } else { + console.warn('Overfull paragraph.'); + } + return []; +}; + +linebreak.infinity = 10000; + +linebreak.glue = function (width, stretch, shrink) { + return { + type: 'glue', + width: width, + stretch: stretch, + shrink: shrink + }; +}; + +linebreak.box = function (width, value) { + return { + type: 'box', + width: width, + value: value + }; +}; + +linebreak.tag = function (width, value) { + return { + type: 'tag', + width: width, + value: value + } +} + +linebreak.penalty = function (width, penalty, flagged) { + return { + type: 'penalty', + width: width, + penalty: penalty, + flagged: flagged + }; +}; diff --git a/prototype/linked-list.js b/prototype/linked-list.js new file mode 100644 index 0000000..44f6481 --- /dev/null +++ b/prototype/linked-list.js @@ -0,0 +1,187 @@ +class LinkedList { + constructor() { + this.head = null; + this.tail = null; + this.listSize = 0; + } + + get size() { + return this.listSize; + } + + isLinked(node) { + return !((node && node.prev === null && node.next === null && this.tail !== node && this.head !== node) || this.isEmpty()); + } + + isEmpty() { + return this.listSize === 0; + } + + get first() { + return this.head; + } + + get last() { + return this.last; + } + + + toString() { + return this.toArray().toString(); + } + + toArray() { + var node = this.head, + result = []; + while (node !== null) { + result.push(node); + node = node.next; + } + return result; + } + + // Note that modifying the list during + // iteration is not safe. + forEach(fun) { + var node = this.head; + while (node !== null) { + fun(node); + node = node.next; + } + } + + contains(n) { + var node = this.head; + if (!this.isLinked(n)) { + return false; + } + while (node !== null) { + if (node === n) { + return true; + } + node = node.next; + } + return false; + } + + at(i) { + var node = this.head, index = 0; + + if (i >= this.listLength || i < 0) { + return null; + } + + while (node !== null) { + if (i === index) { + return node; + } + node = node.next; + index += 1; + } + return null; + } + + insertAfter(node, newNode) { + if (!this.isLinked(node)) { + return this; + } + newNode.prev = node; + newNode.next = node.next; + if (node.next === null) { + this.tail = newNode; + } else { + node.next.prev = newNode; + } + node.next = newNode; + this.listSize += 1; + return this; + } + + insertBefore(node, newNode) { + if (!this.isLinked(node)) { + return this; + } + newNode.prev = node.prev; + newNode.next = node; + if (node.prev === null) { + this.head = newNode; + } else { + node.prev.next = newNode; + } + node.prev = newNode; + this.listSize += 1; + return this; + } + + push(node) { + if (this.head === null) { + this.unshift(node); + } else { + this.insertAfter(this.tail, node); + } + return this; + } + + unshift(node) { + if (this.head === null) { + this.head = node; + this.tail = node; + node.prev = null; + node.next = null; + this.listSize += 1; + } else { + this.insertBefore(this.head, node); + } + return this; + } + + remove(node) { + if (!this.isLinked(node)) { + return this; + } + if (node.prev === null) { + this.head = node.next; + } else { + node.prev.next = node.next; + } + if (node.next === null) { + this.tail = node.prev; + } else { + node.next.prev = node.prev; + } + this.listSize -= 1; + return this; + } + + pop() { + var node = this.tail; + this.tail.prev.next = null; + this.tail = this.tail.prev; + this.listSize -= 1; + node.prev = null; + node.next = null; + return node; + } + + shift() { + var node = this.head; + this.head.next.prev = null; + this.head = this.head.next; + this.listSize -= 1; + node.prev = null; + node.next = null; + return node; + } +} + +class Node { + constructor(data) { + this.prev = null; + this.next = null; + this.data = data; + } + + toString() { + return this.data.toString(); + } +} diff --git a/prototype/main.js b/prototype/main.js new file mode 100644 index 0000000..e8e79c5 --- /dev/null +++ b/prototype/main.js @@ -0,0 +1,108 @@ +// Modules to control application life and create native browser window +const { contextBridge, ipcMain, session, app, BrowserWindow } = require('electron') +const path = require('path') +const fs = require('fs'); +const vm = require('vm'); +require('./speech'); + +// const fetch = require('node-fetch'); + +// // Use a polyfill for fetch +// if (!globalThis.fetch) { +// globalThis.fetch = fetch; +// } + +// const hyphenopolyScript = fs.readFileSync(require.resolve('./Hyphenopoly_Loader.js'), 'utf-8'); +// vm.runInThisContext(hyphenopolyScript, { filename: 'Hyphenopoly_Loader.js' }); + +// Hyphenopoly.config({ +// require: { +// 'en-us': 'FORCEHYPHENOPOLY', +// 'de': 'Silbentrennungsalgorithmus', +// }, +// paths: { +// maindir: './', +// patterndir: './patterns/', +// }, +// setup: { +// selectors: { +// '.hyphenate': { +// hyphen: '­', +// }, +// '.hyphenatePipe': { +// hyphen: '|', +// }, +// }, +// }, +// }); + +// contextBridge.exposeInMainWorld('api', { +// hyphenateWord: async (word, selector = '.hyphenate') => { +// const hyphenator = await Hyphenopoly.hyphenators['en-us']; +// return hyphenator(word, selector); +// }, +// }); + +const debug = true; + +function createWindow () { + // Create the browser window. + const mainWindow = new BrowserWindow({ + width: 800, + height: 600, + // fullscreen: true, + // frame: false, + // titleBarStyle: 'hidden', + autoHideMenuBar: true, + webPreferences: { + nodeIntegration: false, + contextIsolation: true, + enableRemoteModule: false, + // contentSecurityPolicy: "script-src 'self' 'unsafe-inline';", + preload: path.join(__dirname, 'preload.js') + } + }) + + if(!debug) + mainWindow.removeMenu(); + + // and load the index.html of the app. + mainWindow.loadFile('index.html') + + mainWindow.maximize() + // Open the DevTools. + // mainWindow.webContents.openDevTools() +} + +// This method will be called when Electron has finished +// initialization and is ready to create browser windows. +// Some APIs can only be used after this event occurs. +app.whenReady().then(() => { + + session.defaultSession.webRequest.onHeadersReceived((details, callback) => { + callback({ + responseHeaders: { + ...details.responseHeaders, + 'Content-Security-Policy': ['default-src \'self\'; script-src \'self\' \'unsafe-inline\' \'unsafe-eval\' blob:; style-src \'self\' \'unsafe-inline\''] + } + }) + }) + + createWindow() + + app.on('activate', function () { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (BrowserWindow.getAllWindows().length === 0) createWindow() + }) +}) + +// Quit when all windows are closed, except on macOS. There, it's common +// for applications and their menu bar to stay active until the user quits +// explicitly with Cmd + Q. +app.on('window-all-closed', function () { + if (process.platform !== 'darwin') app.quit() +}) + +// In this file you can include the rest of your app's specific main process +// code. You can also put them in separate files and require them here. diff --git a/prototype/package-lock.json b/prototype/package-lock.json new file mode 100644 index 0000000..bd4cb46 --- /dev/null +++ b/prototype/package-lock.json @@ -0,0 +1,1754 @@ +{ + "name": "electron-quick-start", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "electron-quick-start", + "version": "1.0.0", + "license": "CC0-1.0", + "dependencies": { + "axios": "^1.4.0", + "crypto": "^1.0.1", + "fs": "^0.0.1-security", + "node-fetch": "^3.3.1", + "play-sound": "^1.1.5" + }, + "devDependencies": { + "electron": "^25.1.0" + } + }, + "node_modules/@electron/get": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.2.tgz", + "integrity": "sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", + "dev": true + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true, + "optional": true + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", + "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in." + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "optional": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "optional": true + }, + "node_modules/electron": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-25.1.0.tgz", + "integrity": "sha512-VKk4G/0euO7ysMKQKHXmI4d3/qR4uHsAtVFXK2WfQUVxBmc160OAm2R6PN9/EXmgXEioKQBtbc2/lvWyYpDbuA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^18.11.18", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "optional": true + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/find-exec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/find-exec/-/find-exec-1.0.2.tgz", + "integrity": "sha512-/cs763F5i7Nm/aG+hjBv2nJB/Bl2w0tnuZd5bbfcV+WYapn8T4ez3B87H6MgvsmdheDkitj/rHi557wvE+XylQ==" + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true, + "optional": true + }, + "node_modules/get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "dev": true, + "optional": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "optional": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "optional": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "optional": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "optional": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "optional": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", + "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/play-sound": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/play-sound/-/play-sound-1.1.5.tgz", + "integrity": "sha512-gbdF1iLNyL5r9Ne9YwARGMkrvfR4EL9G1ZLtFPLkI2tQt0kkHw5CHM5E6Gl/lDuuk/Uj/O5Q29Bi08jMK4egbA==", + "dependencies": { + "find-exec": "1.0.2" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true, + "optional": true + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "optional": true + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + }, + "dependencies": { + "@electron/get": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.2.tgz", + "integrity": "sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "global-agent": "^3.0.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + } + }, + "@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", + "dev": true + }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "dev": true, + "optional": true, + "requires": { + "@types/node": "*" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true, + "optional": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true + }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true + }, + "cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + } + }, + "clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==" + }, + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + } + } + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "optional": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "optional": true + }, + "electron": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-25.1.0.tgz", + "integrity": "sha512-VKk4G/0euO7ysMKQKHXmI4d3/qR4uHsAtVFXK2WfQUVxBmc160OAm2R6PN9/EXmgXEioKQBtbc2/lvWyYpDbuA==", + "dev": true, + "requires": { + "@electron/get": "^2.0.0", + "@types/node": "^18.11.18", + "extract-zip": "^2.0.1" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true + }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "optional": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "optional": true + }, + "extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "requires": { + "@types/yauzl": "^2.9.1", + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, + "find-exec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/find-exec/-/find-exec-1.0.2.tgz", + "integrity": "sha512-/cs763F5i7Nm/aG+hjBv2nJB/Bl2w0tnuZd5bbfcV+WYapn8T4ez3B87H6MgvsmdheDkitj/rHi557wvE+XylQ==" + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, + "fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true, + "optional": true + }, + "get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "dev": true, + "optional": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "optional": true, + "requires": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "dependencies": { + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "optional": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "got": { + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", + "dev": true, + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "optional": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "optional": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "optional": true + }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "optional": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "keyv": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "optional": true, + "requires": { + "escape-string-regexp": "^4.0.0" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-fetch": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", + "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "play-sound": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/play-sound/-/play-sound-1.1.5.tgz", + "integrity": "sha512-gbdF1iLNyL5r9Ne9YwARGMkrvfR4EL9G1ZLtFPLkI2tQt0kkHw5CHM5E6Gl/lDuuk/Uj/O5Q29Bi08jMK4egbA==", + "requires": { + "find-exec": "1.0.2" + } + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "requires": { + "lowercase-keys": "^2.0.0" + } + }, + "roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "optional": true, + "requires": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "optional": true + }, + "serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "optional": true, + "requires": { + "type-fest": "^0.13.1" + } + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true, + "optional": true + }, + "sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "requires": { + "debug": "^4.1.0" + } + }, + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "optional": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "optional": true + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/prototype/package.json b/prototype/package.json new file mode 100644 index 0000000..63bc7fe --- /dev/null +++ b/prototype/package.json @@ -0,0 +1,29 @@ +{ + "name": "electron-quick-start", + "version": "1.0.0", + "description": "A minimal Electron application", + "main": "main.js", + "scripts": { + "start": "electron ." + }, + "repository": "https://github.com/electron/electron-quick-start", + "keywords": [ + "Electron", + "quick", + "start", + "tutorial", + "demo" + ], + "author": "GitHub", + "license": "CC0-1.0", + "devDependencies": { + "electron": "^25.1.0" + }, + "dependencies": { + "axios": "^1.4.0", + "crypto": "^1.0.1", + "fs": "^0.0.1-security", + "node-fetch": "^3.3.1", + "play-sound": "^1.1.5" + } +} diff --git a/prototype/patterns/af.wasm b/prototype/patterns/af.wasm new file mode 100644 index 0000000..8433fa5 Binary files /dev/null and b/prototype/patterns/af.wasm differ diff --git a/prototype/patterns/as.wasm b/prototype/patterns/as.wasm new file mode 100644 index 0000000..b897458 Binary files /dev/null and b/prototype/patterns/as.wasm differ diff --git a/prototype/patterns/be.wasm b/prototype/patterns/be.wasm new file mode 100644 index 0000000..28f845c Binary files /dev/null and b/prototype/patterns/be.wasm differ diff --git a/prototype/patterns/bg.wasm b/prototype/patterns/bg.wasm new file mode 100644 index 0000000..f9a5057 Binary files /dev/null and b/prototype/patterns/bg.wasm differ diff --git a/prototype/patterns/bn.wasm b/prototype/patterns/bn.wasm new file mode 100644 index 0000000..deda4a2 Binary files /dev/null and b/prototype/patterns/bn.wasm differ diff --git a/prototype/patterns/ca.wasm b/prototype/patterns/ca.wasm new file mode 100644 index 0000000..1bd9f68 Binary files /dev/null and b/prototype/patterns/ca.wasm differ diff --git a/prototype/patterns/cs.wasm b/prototype/patterns/cs.wasm new file mode 100644 index 0000000..696f50f Binary files /dev/null and b/prototype/patterns/cs.wasm differ diff --git a/prototype/patterns/cy.wasm b/prototype/patterns/cy.wasm new file mode 100644 index 0000000..e3eaa3e Binary files /dev/null and b/prototype/patterns/cy.wasm differ diff --git a/prototype/patterns/da.wasm b/prototype/patterns/da.wasm new file mode 100644 index 0000000..362245f Binary files /dev/null and b/prototype/patterns/da.wasm differ diff --git a/prototype/patterns/de-x-syllable.wasm b/prototype/patterns/de-x-syllable.wasm new file mode 100644 index 0000000..d28be79 Binary files /dev/null and b/prototype/patterns/de-x-syllable.wasm differ diff --git a/prototype/patterns/de.wasm b/prototype/patterns/de.wasm new file mode 100644 index 0000000..2e9e683 Binary files /dev/null and b/prototype/patterns/de.wasm differ diff --git a/prototype/patterns/el-monoton.wasm b/prototype/patterns/el-monoton.wasm new file mode 100644 index 0000000..8351a90 Binary files /dev/null and b/prototype/patterns/el-monoton.wasm differ diff --git a/prototype/patterns/el-polyton.wasm b/prototype/patterns/el-polyton.wasm new file mode 100644 index 0000000..913afb8 Binary files /dev/null and b/prototype/patterns/el-polyton.wasm differ diff --git a/prototype/patterns/en-gb.wasm b/prototype/patterns/en-gb.wasm new file mode 100644 index 0000000..07cfcfc Binary files /dev/null and b/prototype/patterns/en-gb.wasm differ diff --git a/prototype/patterns/en-us.wasm b/prototype/patterns/en-us.wasm new file mode 100644 index 0000000..a57665a Binary files /dev/null and b/prototype/patterns/en-us.wasm differ diff --git a/prototype/patterns/eo.wasm b/prototype/patterns/eo.wasm new file mode 100644 index 0000000..0ca7ae0 Binary files /dev/null and b/prototype/patterns/eo.wasm differ diff --git a/prototype/patterns/es.wasm b/prototype/patterns/es.wasm new file mode 100644 index 0000000..fc4de14 Binary files /dev/null and b/prototype/patterns/es.wasm differ diff --git a/prototype/patterns/et.wasm b/prototype/patterns/et.wasm new file mode 100644 index 0000000..fe54913 Binary files /dev/null and b/prototype/patterns/et.wasm differ diff --git a/prototype/patterns/eu.wasm b/prototype/patterns/eu.wasm new file mode 100644 index 0000000..6b11705 Binary files /dev/null and b/prototype/patterns/eu.wasm differ diff --git a/prototype/patterns/fi.wasm b/prototype/patterns/fi.wasm new file mode 100644 index 0000000..181387d Binary files /dev/null and b/prototype/patterns/fi.wasm differ diff --git a/prototype/patterns/fo.wasm b/prototype/patterns/fo.wasm new file mode 100644 index 0000000..aaa071e Binary files /dev/null and b/prototype/patterns/fo.wasm differ diff --git a/prototype/patterns/fr.wasm b/prototype/patterns/fr.wasm new file mode 100644 index 0000000..92ffe87 Binary files /dev/null and b/prototype/patterns/fr.wasm differ diff --git a/prototype/patterns/fur.wasm b/prototype/patterns/fur.wasm new file mode 100644 index 0000000..69b2e9b Binary files /dev/null and b/prototype/patterns/fur.wasm differ diff --git a/prototype/patterns/ga.wasm b/prototype/patterns/ga.wasm new file mode 100644 index 0000000..12b5be6 Binary files /dev/null and b/prototype/patterns/ga.wasm differ diff --git a/prototype/patterns/gl.wasm b/prototype/patterns/gl.wasm new file mode 100644 index 0000000..3173c7f Binary files /dev/null and b/prototype/patterns/gl.wasm differ diff --git a/prototype/patterns/gu.wasm b/prototype/patterns/gu.wasm new file mode 100644 index 0000000..2916e1a Binary files /dev/null and b/prototype/patterns/gu.wasm differ diff --git a/prototype/patterns/hi.wasm b/prototype/patterns/hi.wasm new file mode 100644 index 0000000..05493b1 Binary files /dev/null and b/prototype/patterns/hi.wasm differ diff --git a/prototype/patterns/hr.wasm b/prototype/patterns/hr.wasm new file mode 100644 index 0000000..b28e0b5 Binary files /dev/null and b/prototype/patterns/hr.wasm differ diff --git a/prototype/patterns/hsb.wasm b/prototype/patterns/hsb.wasm new file mode 100644 index 0000000..1c684bf Binary files /dev/null and b/prototype/patterns/hsb.wasm differ diff --git a/prototype/patterns/hu.wasm b/prototype/patterns/hu.wasm new file mode 100644 index 0000000..5a0a285 Binary files /dev/null and b/prototype/patterns/hu.wasm differ diff --git a/prototype/patterns/hy.wasm b/prototype/patterns/hy.wasm new file mode 100644 index 0000000..1cdf968 Binary files /dev/null and b/prototype/patterns/hy.wasm differ diff --git a/prototype/patterns/ia.wasm b/prototype/patterns/ia.wasm new file mode 100644 index 0000000..7cf5f8d Binary files /dev/null and b/prototype/patterns/ia.wasm differ diff --git a/prototype/patterns/id.wasm b/prototype/patterns/id.wasm new file mode 100644 index 0000000..694aaf2 Binary files /dev/null and b/prototype/patterns/id.wasm differ diff --git a/prototype/patterns/is.wasm b/prototype/patterns/is.wasm new file mode 100644 index 0000000..107d4dc Binary files /dev/null and b/prototype/patterns/is.wasm differ diff --git a/prototype/patterns/it.wasm b/prototype/patterns/it.wasm new file mode 100644 index 0000000..f67f261 Binary files /dev/null and b/prototype/patterns/it.wasm differ diff --git a/prototype/patterns/ka.wasm b/prototype/patterns/ka.wasm new file mode 100644 index 0000000..a8cc192 Binary files /dev/null and b/prototype/patterns/ka.wasm differ diff --git a/prototype/patterns/kmr.wasm b/prototype/patterns/kmr.wasm new file mode 100644 index 0000000..02ecf9d Binary files /dev/null and b/prototype/patterns/kmr.wasm differ diff --git a/prototype/patterns/kn.wasm b/prototype/patterns/kn.wasm new file mode 100644 index 0000000..e8d03a8 Binary files /dev/null and b/prototype/patterns/kn.wasm differ diff --git a/prototype/patterns/la.wasm b/prototype/patterns/la.wasm new file mode 100644 index 0000000..281886d Binary files /dev/null and b/prototype/patterns/la.wasm differ diff --git a/prototype/patterns/lt.wasm b/prototype/patterns/lt.wasm new file mode 100644 index 0000000..3fb1716 Binary files /dev/null and b/prototype/patterns/lt.wasm differ diff --git a/prototype/patterns/lv.wasm b/prototype/patterns/lv.wasm new file mode 100644 index 0000000..26a4c39 Binary files /dev/null and b/prototype/patterns/lv.wasm differ diff --git a/prototype/patterns/mk.wasm b/prototype/patterns/mk.wasm new file mode 100644 index 0000000..2859187 Binary files /dev/null and b/prototype/patterns/mk.wasm differ diff --git a/prototype/patterns/ml.wasm b/prototype/patterns/ml.wasm new file mode 100644 index 0000000..325718f Binary files /dev/null and b/prototype/patterns/ml.wasm differ diff --git a/prototype/patterns/mn-cyrl.wasm b/prototype/patterns/mn-cyrl.wasm new file mode 100644 index 0000000..9fcf825 Binary files /dev/null and b/prototype/patterns/mn-cyrl.wasm differ diff --git a/prototype/patterns/mr.wasm b/prototype/patterns/mr.wasm new file mode 100644 index 0000000..13daa1f Binary files /dev/null and b/prototype/patterns/mr.wasm differ diff --git a/prototype/patterns/nb.wasm b/prototype/patterns/nb.wasm new file mode 100644 index 0000000..bf606c3 Binary files /dev/null and b/prototype/patterns/nb.wasm differ diff --git a/prototype/patterns/nl.wasm b/prototype/patterns/nl.wasm new file mode 100644 index 0000000..16be015 Binary files /dev/null and b/prototype/patterns/nl.wasm differ diff --git a/prototype/patterns/nn.wasm b/prototype/patterns/nn.wasm new file mode 100644 index 0000000..4dad4b5 Binary files /dev/null and b/prototype/patterns/nn.wasm differ diff --git a/prototype/patterns/no.wasm b/prototype/patterns/no.wasm new file mode 100644 index 0000000..e74d261 Binary files /dev/null and b/prototype/patterns/no.wasm differ diff --git a/prototype/patterns/oc.wasm b/prototype/patterns/oc.wasm new file mode 100644 index 0000000..1ef3a9e Binary files /dev/null and b/prototype/patterns/oc.wasm differ diff --git a/prototype/patterns/or.wasm b/prototype/patterns/or.wasm new file mode 100644 index 0000000..d3dc33e Binary files /dev/null and b/prototype/patterns/or.wasm differ diff --git a/prototype/patterns/pa.wasm b/prototype/patterns/pa.wasm new file mode 100644 index 0000000..9fe4ea8 Binary files /dev/null and b/prototype/patterns/pa.wasm differ diff --git a/prototype/patterns/pi.wasm b/prototype/patterns/pi.wasm new file mode 100644 index 0000000..1766b08 Binary files /dev/null and b/prototype/patterns/pi.wasm differ diff --git a/prototype/patterns/pl.wasm b/prototype/patterns/pl.wasm new file mode 100644 index 0000000..6bd889f Binary files /dev/null and b/prototype/patterns/pl.wasm differ diff --git a/prototype/patterns/pms.wasm b/prototype/patterns/pms.wasm new file mode 100644 index 0000000..0d7d62f Binary files /dev/null and b/prototype/patterns/pms.wasm differ diff --git a/prototype/patterns/pt.wasm b/prototype/patterns/pt.wasm new file mode 100644 index 0000000..207196e Binary files /dev/null and b/prototype/patterns/pt.wasm differ diff --git a/prototype/patterns/rm.wasm b/prototype/patterns/rm.wasm new file mode 100644 index 0000000..b7663fa Binary files /dev/null and b/prototype/patterns/rm.wasm differ diff --git a/prototype/patterns/ro.wasm b/prototype/patterns/ro.wasm new file mode 100644 index 0000000..2243b89 Binary files /dev/null and b/prototype/patterns/ro.wasm differ diff --git a/prototype/patterns/ru.wasm b/prototype/patterns/ru.wasm new file mode 100644 index 0000000..434e6e0 Binary files /dev/null and b/prototype/patterns/ru.wasm differ diff --git a/prototype/patterns/sh-cyrl.wasm b/prototype/patterns/sh-cyrl.wasm new file mode 100644 index 0000000..42a8c9a Binary files /dev/null and b/prototype/patterns/sh-cyrl.wasm differ diff --git a/prototype/patterns/sh-latn.wasm b/prototype/patterns/sh-latn.wasm new file mode 100644 index 0000000..c710227 Binary files /dev/null and b/prototype/patterns/sh-latn.wasm differ diff --git a/prototype/patterns/sk.wasm b/prototype/patterns/sk.wasm new file mode 100644 index 0000000..c77071b Binary files /dev/null and b/prototype/patterns/sk.wasm differ diff --git a/prototype/patterns/sl.wasm b/prototype/patterns/sl.wasm new file mode 100644 index 0000000..418998d Binary files /dev/null and b/prototype/patterns/sl.wasm differ diff --git a/prototype/patterns/sq.wasm b/prototype/patterns/sq.wasm new file mode 100644 index 0000000..edf9a54 Binary files /dev/null and b/prototype/patterns/sq.wasm differ diff --git a/prototype/patterns/sr-cyrl.wasm b/prototype/patterns/sr-cyrl.wasm new file mode 100644 index 0000000..a233b67 Binary files /dev/null and b/prototype/patterns/sr-cyrl.wasm differ diff --git a/prototype/patterns/sv.wasm b/prototype/patterns/sv.wasm new file mode 100644 index 0000000..b41a768 Binary files /dev/null and b/prototype/patterns/sv.wasm differ diff --git a/prototype/patterns/ta.wasm b/prototype/patterns/ta.wasm new file mode 100644 index 0000000..0dc6392 Binary files /dev/null and b/prototype/patterns/ta.wasm differ diff --git a/prototype/patterns/te.wasm b/prototype/patterns/te.wasm new file mode 100644 index 0000000..a0af5bb Binary files /dev/null and b/prototype/patterns/te.wasm differ diff --git a/prototype/patterns/th.wasm b/prototype/patterns/th.wasm new file mode 100644 index 0000000..5f81d0d Binary files /dev/null and b/prototype/patterns/th.wasm differ diff --git a/prototype/patterns/tk.wasm b/prototype/patterns/tk.wasm new file mode 100644 index 0000000..1df7032 Binary files /dev/null and b/prototype/patterns/tk.wasm differ diff --git a/prototype/patterns/tr.wasm b/prototype/patterns/tr.wasm new file mode 100644 index 0000000..e1c7e23 Binary files /dev/null and b/prototype/patterns/tr.wasm differ diff --git a/prototype/patterns/uk.wasm b/prototype/patterns/uk.wasm new file mode 100644 index 0000000..7e3a549 Binary files /dev/null and b/prototype/patterns/uk.wasm differ diff --git a/prototype/patterns/zh-latn-pinyin.wasm b/prototype/patterns/zh-latn-pinyin.wasm new file mode 100644 index 0000000..072beb5 Binary files /dev/null and b/prototype/patterns/zh-latn-pinyin.wasm differ diff --git a/prototype/preload.js b/prototype/preload.js new file mode 100644 index 0000000..d81cf7c --- /dev/null +++ b/prototype/preload.js @@ -0,0 +1,25 @@ +/** + * The preload script runs before. It has access to web APIs + * as well as Electron's renderer process modules and some + * polyfilled Node.js functions. + * + * https://www.electronjs.org/docs/latest/tutorial/sandbox + */ +window.addEventListener('DOMContentLoaded', () => { + const replaceText = (selector, text) => { + const element = document.getElementById(selector) + if (element) element.innerText = text + } + + for (const type of ['chrome', 'node', 'electron']) { + replaceText(`${type}-version`, process.versions[type]) + } +}) + +const { contextBridge, ipcRenderer } = require('electron'); + +contextBridge.exposeInMainWorld( + "elevenlabs", { + getSpeech: (text) => ipcRenderer.invoke('getSpeech', text) + } +); \ No newline at end of file diff --git a/prototype/renderer.js b/prototype/renderer.js new file mode 100644 index 0000000..cd4173b --- /dev/null +++ b/prototype/renderer.js @@ -0,0 +1,10 @@ +/** + * This file is loaded via the - + - \ No newline at end of file + diff --git a/public/js/Hyphenopoly.js b/public/js/Hyphenopoly.js new file mode 100644 index 0000000..eab4e66 --- /dev/null +++ b/public/js/Hyphenopoly.js @@ -0,0 +1,931 @@ +/** + * @license Hyphenopoly 5.2.0-beta.1 - client side hyphenation for webbrowsers + * ©2023 Mathias Nater, Güttingen (mathiasnater at gmail dot com) + * https://github.com/mnater/Hyphenopoly + * + * Released under the MIT license + * http://mnater.github.io/Hyphenopoly/LICENSE + */ + +/* globals Hyphenopoly:readonly */ +((w, o) => { + "use strict"; + const SOFTHYPHEN = "\u00AD"; + + /** + * Event + */ + const event = ((H) => { + const knownEvents = new Map([ + ["afterElementHyphenation", []], + ["beforeElementHyphenation", []], + ["engineReady", []], + [ + "error", [ + (e) => { + if (e.runDefault) { + w.console.warn(e); + } + } + ] + ], + ["hyphenopolyEnd", []], + ["hyphenopolyStart", []] + ]); + if (H.hev) { + const userEvents = new Map(o.entries(H.hev)); + knownEvents.forEach((eventFuncs, eventName) => { + if (userEvents.has(eventName)) { + eventFuncs.unshift(userEvents.get(eventName)); + } + }); + } + return { + "fire": ((eventName, eventData) => { + eventData.runDefault = true; + eventData.preventDefault = () => { + eventData.runDefault = false; + }; + knownEvents.get(eventName).forEach((eventFn) => { + eventFn(eventData); + }); + }) + }; + })(Hyphenopoly); + + /** + * Register copy event on element + * @param {Object} el The element + * @returns {undefined} + */ + function registerOnCopy(el) { + el.addEventListener( + "copy", + (e) => { + e.preventDefault(); + const sel = w.getSelection(); + const div = document.createElement("div"); + div.appendChild(sel.getRangeAt(0).cloneContents()); + e.clipboardData.setData("text/plain", sel.toString().replace(RegExp(SOFTHYPHEN, "g"), "")); + e.clipboardData.setData("text/html", div.innerHTML.replace(RegExp(SOFTHYPHEN, "g"), "")); + }, + true + ); + } + + /** + * Convert settings from H.setup-Object to Map + * This is a IIFE to keep complexity low. + */ + ((H) => { + /** + * Create a Map with a default Map behind the scenes. This mimics + * kind of a prototype chain of an object, but without the object- + * injection security risk. + * + * @param {Map} defaultsMap - A Map with default values + * @returns {Proxy} - A Proxy for the Map (dot-notation or get/set) + */ + function createMapWithDefaults(defaultsMap) { + const userMap = new Map(); + + /** + * The get-trap: get the value from userMap or else from defaults + * @param {Sring} key - The key to retrieve the value for + * @returns {*} + */ + function get(key) { + return (userMap.has(key)) + ? userMap.get(key) + : defaultsMap.get(key); + } + + /** + * The set-trap: set the value to userMap and don't touch defaults + * @param {Sring} key - The key for the value + * @param {*} value - The value + * @returns {*} + */ + function set(key, value) { + userMap.set(key, value); + } + return new Proxy(defaultsMap, { + "get": (_target, prop) => { + if (prop === "set") { + return set; + } + if (prop === "get") { + return get; + } + return get(prop); + }, + "ownKeys": () => { + return [ + ...new Set( + [...defaultsMap.keys(), ...userMap.keys()] + ) + ]; + } + }); + } + + const settings = createMapWithDefaults(new Map([ + ["defaultLanguage", "en-us"], + [ + "dontHyphenate", (() => { + const list = "abbr,acronym,audio,br,button,code,img,input,kbd,label,math,option,pre,samp,script,style,sub,sup,svg,textarea,var,video"; + return createMapWithDefaults( + new Map(list.split(",").map((val) => { + return [val, true]; + })) + ); + })() + ], + ["dontHyphenateClass", "donthyphenate"], + ["exceptions", new Map()], + ["keepAlive", true], + ["normalize", false], + ["processShadows", false], + ["safeCopy", true], + ["substitute", new Map()], + ["timeout", 1000] + ])); + o.entries(H.s).forEach(([key, value]) => { + switch (key) { + case "selectors": + // Set settings.selectors to array of selectors + settings.set("selectors", o.keys(value)); + + /* + * For each selector add a property to settings with + * selector specific settings + */ + o.entries(value).forEach(([sel, selSettings]) => { + const selectorSettings = createMapWithDefaults(new Map([ + ["compound", "hyphen"], + ["hyphen", SOFTHYPHEN], + ["leftmin", 0], + ["leftminPerLang", 0], + ["minWordLength", 6], + ["mixedCase", true], + ["orphanControl", 1], + ["rightmin", 0], + ["rightminPerLang", 0] + ])); + o.entries(selSettings).forEach( + ([selSetting, setVal]) => { + if (typeof setVal === "object") { + selectorSettings.set( + selSetting, + new Map(o.entries(setVal)) + ); + } else { + selectorSettings.set(selSetting, setVal); + } + } + ); + settings.set(sel, selectorSettings); + }); + break; + case "dontHyphenate": + case "exceptions": + o.entries(value).forEach(([k, v]) => { + settings.get(key).set(k, v); + }); + break; + case "substitute": + o.entries(value).forEach(([lang, subst]) => { + settings.substitute.set( + lang, + new Map(o.entries(subst)) + ); + }); + break; + default: + settings.set(key, value); + } + }); + H.c = settings; + })(Hyphenopoly); + + ((H) => { + const C = H.c; + let mainLanguage = null; + + event.fire( + "hyphenopolyStart", + { + "msg": "hyphenopolyStart" + } + ); + + /** + * Factory for elements + * @returns {Object} elements-object + */ + function makeElementCollection() { + const list = new Map(); + + /* + * Counter counts the elements to be hyphenated. + * Needs to be an object (Pass by reference) + */ + const counter = [0]; + + /** + * Add element to elements + * @param {object} el The element + * @param {string} lang The language of the element + * @param {string} sel The selector of the element + * @returns {Object} An element-object + */ + function add(el, lang, sel) { + const elo = { + "element": el, + "selector": sel + }; + if (!list.has(lang)) { + list.set(lang, []); + } + list.get(lang).push(elo); + counter[0] += 1; + return elo; + } + + /** + * Removes elements from the list and updates the counter + * @param {string} lang - The lang of the elements to remove + */ + function rem(lang) { + let langCount = 0; + if (list.has(lang)) { + langCount = list.get(lang).length; + list.delete(lang); + counter[0] -= langCount; + if (counter[0] === 0) { + event.fire( + "hyphenopolyEnd", + { + "msg": "hyphenopolyEnd" + } + ); + if (!C.keepAlive) { + window.Hyphenopoly = null; + } + } + } + } + + return { + add, + counter, + list, + rem + }; + } + + /** + * Get language of element by searching its parents or fallback + * @param {Object} el The element + * @param {string} parentLang Lang of parent if available + * @param {boolean} fallback Will falback to mainlanguage + * @returns {string|null} The language or null + */ + function getLang(el, parentLang = "", fallback = true) { + // Find closest el with lang attr not empty + el = el.closest("[lang]:not([lang=''])"); + if (el && el.lang) { + return el.lang.toLowerCase(); + } + if (parentLang) { + return parentLang; + } + return (fallback) + ? mainLanguage + : null; + } + + /** + * Collect elements that have a selector defined in C.selectors + * and add them to elements. + * @param {Object} [parent = null] The start point element + * @param {string} [selector = null] The selector matching the parent + * @returns {Object} elements-object + */ + function collectElements(parent = null, selector = null) { + const elements = makeElementCollection(); + + const dontHyphenateSelector = (() => { + let s = "." + C.dontHyphenateClass; + o.getOwnPropertyNames(C.dontHyphenate).forEach((tag) => { + if (C.dontHyphenate.get(tag)) { + s += "," + tag; + } + }); + return s; + })(); + const matchingSelectors = C.selectors.join(",") + "," + dontHyphenateSelector; + + /** + * Recursively walk all elements in el, lending lang and selName + * add them to elements if necessary. + * @param {Object} el The element to scan + * @param {string} pLang The language of the parent element + * @param {string} sel The selector of the parent element + * @param {boolean} isChild If el is a child element + * @returns {undefined} + */ + function processElements(el, pLang, sel, isChild = false) { + const eLang = getLang(el, pLang); + const langDef = H.cf.langs.get(eLang); + if (langDef === "H9Y") { + elements.add(el, eLang, sel); + if (!isChild && C.safeCopy) { + registerOnCopy(el); + } + } else if (!langDef && eLang !== "zxx") { + event.fire( + "error", + Error(`Element with '${eLang}' found, but '${eLang}.wasm' not loaded. Check language tags!`) + ); + } + el.childNodes.forEach((n) => { + if (n.nodeType === 1 && !n.matches(matchingSelectors)) { + processElements(n, eLang, sel, true); + } + }); + } + + /** + * Searches the DOM for each sel + * @param {object} root The DOM root + * @returns {undefined} + */ + function getElems(root) { + C.selectors.forEach((sel) => { + root.querySelectorAll(sel).forEach((n) => { + processElements(n, getLang(n), sel, false); + }); + }); + } + + if (parent === null) { + if (C.processShadows) { + w.document.querySelectorAll("*").forEach((m) => { + if (m.shadowRoot) { + getElems(m.shadowRoot); + } + }); + } + getElems(w.document); + } else { + processElements(parent, getLang(parent), selector); + } + return elements; + } + + const wordHyphenatorPool = new Map(); + + /** + * Factory for hyphenatorFunctions for a specific language and selector + * @param {Object} lo Language-Object + * @param {string} lang The language + * @param {string} sel The selector + * @returns {function} The hyphenate function + */ + function createWordHyphenator(lo, lang, sel) { + const poolKey = lang + "-" + sel; + if (wordHyphenatorPool.has(poolKey)) { + return wordHyphenatorPool.get(poolKey); + } + + const selSettings = C.get(sel); + lo.cache.set(sel, new Map()); + + /** + * HyphenateFunction for non-compound words + * @param {string} word The word + * @returns {string} The hyphenated word + */ + function hyphenateNormal(word) { + if (word.length > 61) { + event.fire( + "error", + Error("Found word longer than 61 characters") + ); + } else if (!lo.reNotAlphabet.test(word)) { + return lo.hyphenate( + word, + selSettings.hyphen.charCodeAt(0), + selSettings.leftminPerLang.get(lang), + selSettings.rightminPerLang.get(lang) + ); + } + return word; + } + + /** + * HyphenateFunction for compound words + * @param {string} word The word + * @returns {string} The hyphenated compound word + */ + function hyphenateCompound(word) { + const zeroWidthSpace = "\u200B"; + let parts = null; + let wordHyphenator = null; + if (selSettings.compound === "auto" || + selSettings.compound === "all") { + wordHyphenator = createWordHyphenator(lo, lang, sel); + parts = word.split("-").map((p) => { + if (p.length >= selSettings.minWordLength) { + return wordHyphenator(p); + } + return p; + }); + if (selSettings.compound === "auto") { + word = parts.join("-"); + } else { + word = parts.join("-" + zeroWidthSpace); + } + } else { + word = word.replace("-", "-" + zeroWidthSpace); + } + return word; + } + + /** + * Checks if a string is mixed case + * @param {string} s The string + * @returns {boolean} true if s is mixed case + */ + function isMixedCase(s) { + return [...s].map((c) => { + return (c === c.toLowerCase()); + }).some((v, i, a) => { + return (v !== a[0]); + }); + } + + /** + * HyphenateFunction for words (compound or not) + * @param {string} word The word + * @returns {string} The hyphenated word + */ + function hyphenator(word) { + let hw = lo.cache.get(sel).get(word); + if (!hw) { + if (lo.exc.has(word)) { + hw = lo.exc.get(word).replace( + /-/g, + selSettings.hyphen + ); + } else if (!selSettings.mixedCase && isMixedCase(word)) { + hw = word; + } else if (word.indexOf("-") === -1) { + hw = hyphenateNormal(word); + } else { + hw = hyphenateCompound(word); + } + lo.cache.get(sel).set(word, hw); + } + return hw; + } + wordHyphenatorPool.set(poolKey, hyphenator); + return hyphenator; + } + + const orphanControllerPool = new Map(); + + /** + * Factory for function that handles orphans + * @param {string} sel The selector + * @returns {function} The function created + */ + function createOrphanController(sel) { + if (orphanControllerPool.has(sel)) { + return orphanControllerPool.get(sel); + } + const selSettings = C.get(sel); + + /** + * Function template + * @param {string} ignore unused result of replace + * @param {string} leadingWhiteSpace The leading whiteSpace + * @param {string} lastWord The last word + * @param {string} trailingWhiteSpace The trailing whiteSpace + * @returns {string} Treated end of text + */ + function controlOrphans( + ignore, + leadingWhiteSpace, + lastWord, + trailingWhiteSpace + ) { + if (selSettings.orphanControl === 3 && leadingWhiteSpace === " ") { + // \u00A0 = no-break space (nbsp) + leadingWhiteSpace = "\u00A0"; + } + return leadingWhiteSpace + lastWord.replace(RegExp(selSettings.hyphen, "g"), "") + trailingWhiteSpace; + } + orphanControllerPool.set(sel, controlOrphans); + return controlOrphans; + } + + const wordRegExpPool = new Map(); + + /** + * Hyphenate an entitiy (text string or Element-Object) + * @param {string} lang - the language of the string + * @param {string} sel - the selectorName of settings + * @param {string} entity - the entity to be hyphenated + * @returns {string | null} hyphenated str according to setting of sel + */ + function hyphenate(lang, sel, entity) { + const lo = H.languages.get(lang); + const selSettings = C.get(sel); + const minWordLength = selSettings.minWordLength; + + + const regExpWord = (() => { + const key = lang + minWordLength; + if (wordRegExpPool.has(key)) { + return wordRegExpPool.get(key); + } + + /* + * Transpiled RegExp of + * /[${alphabet}\p{Mn}Subset\p{Letter}\00AD-] + * {${minwordlength},}/gui + */ + const reWord = RegExp( + `[${lo.alphabet}a-z\u0300-\u036F\u0483-\u0487\u00DF-\u00F6\u00F8-\u00FE\u0101\u0103\u0105\u0107\u0109\u010D\u010F\u0111\u0113\u0117\u0119\u011B\u011D\u011F\u0123\u0125\u012B\u012F\u0131\u0135\u0137\u013C\u013E\u0142\u0144\u0146\u0148\u014D\u0151\u0153\u0155\u0159\u015B\u015D\u015F\u0161\u0165\u016B\u016D\u016F\u0171\u0173\u017A\u017C\u017E\u017F\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u0219\u021B\u02BC\u0390\u03AC-\u03CE\u03D0\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF\u03F2\u0430-\u044F\u0451-\u045C\u045E\u045F\u0491\u04AF\u04E9\u0561-\u0585\u0587\u0905-\u090C\u090F\u0910\u0913-\u0928\u092A-\u0930\u0932\u0933\u0935-\u0939\u093D\u0960\u0961\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A85-\u0A8B\u0A8F\u0A90\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B60\u0B61\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60\u0D61\u0D7A-\u0D7F\u0E01-\u0E2E\u0E30\u0E32\u0E33\u0E40-\u0E45\u10D0-\u10F0\u1200-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u1E0D\u1E37\u1E41\u1E43\u1E45\u1E47\u1E6D\u1F00-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB2-\u1FB4\u1FB6\u1FB7\u1FC2-\u1FC4\u1FC6\u1FC7\u1FD2\u1FD3\u1FD6\u1FD7\u1FE2-\u1FE7\u1FF2-\u1FF4\u1FF6\u1FF7\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CC9\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\u00AD\u200B-\u200D-]{${minWordLength},}`, "gui" + ); + wordRegExpPool.set(key, reWord); + return reWord; + })(); + + /** + * Hyphenate text according to setting in sel + * @param {string} text - the strint to be hyphenated + * @returns {string} hyphenated string according to setting of sel + */ + function hyphenateText(text) { + if (C.normalize) { + text = text.normalize("NFC"); + } + let tn = text.replace( + regExpWord, + createWordHyphenator(lo, lang, sel) + ); + if (selSettings.orphanControl !== 1) { + tn = tn.replace( + /(\u0020*)(\S+)(\s*)$/, + createOrphanController(sel) + ); + } + return tn; + } + + /** + * Hyphenate element according to setting in sel + * @param {object} el - the HTMLElement to be hyphenated + * @returns {undefined} + */ + function hyphenateElement(el) { + event.fire( + "beforeElementHyphenation", + { + el, + lang + } + ); + el.childNodes.forEach((n) => { + if ( + n.nodeType === 3 && + (/\S/).test(n.data) && + n.data.length >= minWordLength + ) { + n.data = hyphenateText(n.data); + } + }); + H.res.els.counter[0] -= 1; + event.fire( + "afterElementHyphenation", + { + el, + lang + } + ); + } + let r = null; + if (typeof entity === "string") { + r = hyphenateText(entity); + } else if (entity instanceof HTMLElement) { + hyphenateElement(entity); + } + return r; + } + + /** + * Creates a language-specific string hyphenator + * @param {String} lang - The language this hyphenator hyphenates + */ + function createStringHyphenator(lang) { + return ((entity, sel = ".hyphenate") => { + if (typeof entity !== "string") { + event.fire( + "error", + Error("This use of hyphenators is deprecated. See https://mnater.github.io/Hyphenopoly/Hyphenators.html") + ); + } + return hyphenate(lang, sel, entity); + }); + } + + /** + * Creates a polyglot HTML hyphenator + */ + function createDOMHyphenator() { + return ((entity, sel = ".hyphenate") => { + collectElements(entity, sel).list.forEach((els, l) => { + els.forEach((elo) => { + hyphenate(l, elo.selector, elo.element); + }); + }); + return null; + }); + } + + H.unhyphenate = () => { + H.res.els.list.forEach((els) => { + els.forEach((elo) => { + const n = elo.element.firstChild; + n.data = n.data.replace(RegExp(C[elo.selector].hyphen, "g"), ""); + }); + }); + return Promise.resolve(H.res.els); + }; + + /** + * Hyphenate all elements with a given language + * @param {string} lang The language + * @param {Array} elArr Array of elements + * @returns {undefined} + */ + function hyphenateLangElements(lang, elements) { + const elArr = elements.list.get(lang); + if (elArr) { + elArr.forEach((elo) => { + hyphenate(lang, elo.selector, elo.element); + }); + } else { + event.fire( + "error", + Error(`Engine for language '${lang}' loaded, but no elements found.`) + ); + } + if (elements.counter[0] === 0) { + w.clearTimeout(H.timeOutHandler); + H.hide(0, null); + event.fire( + "hyphenopolyEnd", + { + "msg": "hyphenopolyEnd" + } + ); + if (!C.keepAlive) { + window.Hyphenopoly = null; + } + } + } + + /** + * Convert the exceptions from user input to Map + * @param {string} lang - The language for which the Map is created + * @return {Map} + */ + function createExceptionMap(lang) { + let exc = ""; + if (C.exceptions.has(lang)) { + exc = C.exceptions.get(lang); + } + if (C.exceptions.has("global")) { + if (exc === "") { + exc = C.exceptions.get("global"); + } else { + exc += ", " + C.exceptions.get("global"); + } + } + if (exc === "") { + return new Map(); + } + return new Map(exc.split(", ").map((e) => { + return [e.replace(/-/g, ""), e]; + })); + } + + /** + * Setup lo + * @param {string} lang The language + * @param {function} hyphenateFunction The hyphenateFunction + * @param {string} alphabet List of used characters + * @param {number} leftmin leftmin + * @param {number} rightmin rightmin + * @returns {undefined} + */ + function prepareLanguagesObj( + lang, + hyphenateFunction, + alphabet, + patternLeftmin, + patternRightmin + ) { + C.selectors.forEach((sel) => { + const selSettings = C.get(sel); + if (selSettings.leftminPerLang === 0) { + selSettings.set("leftminPerLang", new Map()); + } + if (selSettings.rightminPerLang === 0) { + selSettings.set("rightminPerLang", new Map()); + } + selSettings.leftminPerLang.set(lang, Math.max( + patternLeftmin, + selSettings.leftmin, + Number(selSettings.leftminPerLang.get(lang)) || 0 + )); + + selSettings.rightminPerLang.set(lang, Math.max( + patternRightmin, + selSettings.rightmin, + Number(selSettings.rightminPerLang.get(lang)) || 0 + )); + }); + if (!H.languages) { + H.languages = new Map(); + } + alphabet = alphabet.replace(/\\*-/g, "\\-"); + H.languages.set(lang, { + alphabet, + "cache": new Map(), + "exc": createExceptionMap(lang), + "hyphenate": hyphenateFunction, + "ready": true, + "reNotAlphabet": RegExp(`[^${alphabet}]`, "i") + }); + H.hy6ors.get(lang).resolve(createStringHyphenator(lang)); + event.fire( + "engineReady", + { + lang + } + ); + if (H.res.els) { + hyphenateLangElements(lang, H.res.els); + } + } + + const decode = (() => { + const utf16ledecoder = new TextDecoder("utf-16le"); + return ((ui16) => { + return utf16ledecoder.decode(ui16); + }); + })(); + + /** + * Setup env for hyphenateFunction + * @param {ArrayBuffer} buf Memory buffer + * @param {function} hyphenateFunc hyphenateFunction + * @returns {function} hyphenateFunction with closured environment + */ + function encloseHyphenateFunction(buf, hyphenateFunc) { + const wordStore = new Uint16Array(buf, 0, 64); + return ((word, hyphencc, leftmin, rightmin) => { + wordStore.set([ + ...[...word].map((c) => { + return c.charCodeAt(0); + }), + 0 + ]); + const len = hyphenateFunc(leftmin, rightmin, hyphencc); + if (len > 0) { + word = decode( + new Uint16Array(buf, 0, len) + ); + } + return word; + }); + } + + /** + * Instantiate Wasm Engine + * @param {string} lang The language + * @returns {undefined} + */ + function instantiateWasmEngine(heProm, lang) { + const wa = window.WebAssembly; + + /** + * Register character substitutions in the .wasm-hyphenEngine + * @param {number} alphalen - The length of the alphabet + * @param {object} exp - Export-object of the hyphenEngine + */ + function registerSubstitutions(alphalen, exp) { + if (C.substitute.has(lang)) { + const subst = C.substitute.get(lang); + subst.forEach((substituer, substituted) => { + const substitutedU = substituted.toUpperCase(); + const substitutedUcc = (substitutedU === substituted) + ? 0 + : substitutedU.charCodeAt(0); + alphalen = exp.subst( + substituted.charCodeAt(0), + substitutedUcc, + substituer.charCodeAt(0) + ); + }); + } + return alphalen; + } + + /** + * Instantiate the hyphenEngine + * @param {object} res - The fetched ressource + */ + function handleWasm(res) { + const exp = res.instance.exports; + // eslint-disable-next-line multiline-ternary + let alphalen = (wa.Global) ? exp.lct.value : exp.lct; + alphalen = registerSubstitutions(alphalen, exp); + heProm.l.forEach((l) => { + prepareLanguagesObj( + l, + encloseHyphenateFunction( + exp.mem.buffer, + exp.hyphenate + ), + decode(new Uint16Array(exp.mem.buffer, 1408, alphalen)), + /* eslint-disable multiline-ternary */ + (wa.Global) ? exp.lmi.value : exp.lmi, + (wa.Global) ? exp.rmi.value : exp.rmi + /* eslint-enable multiline-ternary */ + ); + }); + } + heProm.w.then((response) => { + if (response.ok) { + if ( + wa.instantiateStreaming && + (response.headers.get("Content-Type") === "application/wasm") + ) { + return wa.instantiateStreaming(response); + } + return response.arrayBuffer().then((ab) => { + return wa.instantiate(ab); + }); + } + return Promise.reject(Error(`File ${lang}.wasm can't be loaded from ${H.paths.patterndir}`)); + }).then(handleWasm, (e) => { + event.fire("error", e); + H.res.els.rem(lang); + }); + } + + H.main = () => { + H.res.DOM.then(() => { + mainLanguage = getLang(w.document.documentElement, "", false); + if (!mainLanguage && C.defaultLanguage !== "") { + mainLanguage = C.defaultLanguage; + } + const elements = collectElements(); + H.res.els = elements; + elements.list.forEach((ignore, lang) => { + if (H.languages && + H.languages.has(lang) && + H.languages.get(lang).ready + ) { + hyphenateLangElements(lang, elements); + } + }); + }); + + H.res.he.forEach(instantiateWasmEngine); + + Promise.all( + // Make sure all lang specific hyphenators and DOM are ready + [...H.hy6ors.entries()]. + reduce((accumulator, value) => { + if (value[0] !== "HTML") { + return accumulator.concat(value[1]); + } + return accumulator; + }, []). + concat(H.res.DOM) + ).then(() => { + H.hy6ors.get("HTML").resolve(createDOMHyphenator()); + }, (e) => { + event.fire("error", e); + }); + }; + H.main(); + })(Hyphenopoly); +})(window, Object); diff --git a/public/js/Hyphenopoly_Loader.js b/public/js/Hyphenopoly_Loader.js new file mode 100644 index 0000000..ecab413 --- /dev/null +++ b/public/js/Hyphenopoly_Loader.js @@ -0,0 +1,347 @@ +/** + * @license Hyphenopoly_Loader 5.2.0-beta.1 - client side hyphenation + * ©2023 Mathias Nater, Güttingen (mathiasnater at gmail dot com) + * https://github.com/mnater/Hyphenopoly + * + * Released under the MIT license + * http://mnater.github.io/Hyphenopoly/LICENSE + */ +/* globals Hyphenopoly:readonly */ +window.Hyphenopoly = {}; + +((w, d, H, o) => { + "use strict"; + + /** + * Shortcut for new Map + * @param {any} init - initialiser for new Map + * @returns {Map} + */ + const mp = (init) => { + return new Map(init); + }; + + const scriptName = "Hyphenopoly_Loader.js"; + const thisScript = d.currentScript.src; + const store = sessionStorage; + let mainScriptLoaded = false; + + /** + * The main function runs the feature test and loads Hyphenopoly if + * necessary. + */ + const main = (() => { + const shortcuts = { + "ac": "appendChild", + "ce": "createElement", + "ct": "createTextNode" + }; + + /** + * Create deferred Promise + * + * From http://lea.verou.me/2016/12/resolve-promises-externally-with- + * this-one-weird-trick/ + * @return {promise} + */ + const defProm = () => { + let res = null; + let rej = null; + const promise = new Promise((resolve, reject) => { + res = resolve; + rej = reject; + }); + promise.resolve = res; + promise.reject = rej; + return promise; + }; + + H.ac = new AbortController(); + const fetchOptions = { + "credentials": H.s.CORScredentials, + "signal": H.ac.signal + }; + + let stylesNode = null; + + /** + * Define function H.hide. + * This function hides (state = 1) or unhides (state = 0) + * the whole document (mode == 0) or + * each selected element (mode == 1) or + * text of each selected element (mode == 2) or + * nothing (mode == -1) + * @param {integer} state - State + * @param {integer} mode - Mode + */ + H.hide = (state, mode) => { + if (state) { + let vis = "{visibility:hidden!important}"; + stylesNode = d[shortcuts.ce]("style"); + let myStyle = ""; + if (mode === 0) { + myStyle = "html" + vis; + } else if (mode !== -1) { + if (mode === 2) { + vis = "{color:transparent!important}"; + } + o.keys(H.s.selectors).forEach((sel) => { + myStyle += sel + vis; + }); + } + stylesNode[shortcuts.ac](d[shortcuts.ct](myStyle)); + d.head[shortcuts.ac](stylesNode); + } else if (stylesNode) { + stylesNode.remove(); + } + }; + + const tester = (() => { + let fakeBody = null; + return { + + /** + * Append fakeBody with tests to document + * @returns {Object|null} The body element or null, if no tests + */ + "ap": () => { + if (fakeBody) { + d.documentElement[shortcuts.ac](fakeBody); + return fakeBody; + } + return null; + }, + + /** + * Remove fakeBody + * @returns {undefined} + */ + "cl": () => { + if (fakeBody) { + fakeBody.remove(); + } + }, + + /** + * Create and append div with CSS-hyphenated word + * @param {string} lang Language + * @returns {undefined} + */ + "cr": (lang) => { + if (H.cf.langs.has(lang)) { + return; + } + fakeBody = fakeBody || d[shortcuts.ce]("body"); + const testDiv = d[shortcuts.ce]("div"); + const ha = "hyphens:auto"; + testDiv.lang = lang; + testDiv.style.cssText = `visibility:hidden;-webkit-${ha};-ms-${ha};${ha};width:48px;font-size:12px;line-height:12px;border:none;padding:0;word-wrap:normal`; + testDiv[shortcuts.ac]( + d[shortcuts.ct](H.lrq.get(lang).wo.toLowerCase()) + ); + fakeBody[shortcuts.ac](testDiv); + } + }; + })(); + + /** + * Checks if hyphens (ev.prefixed) is set to auto for the element. + * @param {Object} elm - the element + * @returns {Boolean} result of the check + */ + const checkCSSHyphensSupport = (elmStyle) => { + const h = elmStyle.hyphens || + elmStyle.webkitHyphens || + elmStyle.msHyphens; + return (h === "auto"); + }; + + H.res = { + "he": mp() + }; + + /** + * Load hyphenEngines to H.res.he + * + * Make sure each .wasm is loaded exactly once, even for fallbacks + * Store a list of languages to by hyphenated with each .wasm + * @param {string} lang The language + * @returns {undefined} + */ + const loadhyphenEngine = (lang) => { + const fn = H.lrq.get(lang).fn; + H.cf.pf = true; + H.cf.langs.set(lang, "H9Y"); + if (H.res.he.has(fn)) { + H.res.he.get(fn).l.push(lang); + } else { + H.res.he.set( + fn, + { + "l": [lang], + "w": w.fetch(H.paths.patterndir + fn + ".wasm", fetchOptions) + } + ); + } + }; + H.lrq.forEach((value, lang) => { + if (value.wo === "FORCEHYPHENOPOLY" || H.cf.langs.get(lang) === "H9Y") { + loadhyphenEngine(lang); + } else { + tester.cr(lang); + } + }); + const testContainer = tester.ap(); + if (testContainer) { + testContainer.querySelectorAll("div").forEach((n) => { + if (checkCSSHyphensSupport(n.style) && n.offsetHeight > 12) { + H.cf.langs.set(n.lang, "CSS"); + } else { + loadhyphenEngine(n.lang); + } + }); + tester.cl(); + } + const hev = H.hev; + if (H.cf.pf) { + H.res.DOM = new Promise((res) => { + if (d.readyState === "loading") { + d.addEventListener( + "DOMContentLoaded", + res, + { + "once": true, + "passive": true + } + ); + } else { + res(); + } + }); + H.hide(1, H.s.hide); + H.timeOutHandler = w.setTimeout(() => { + H.hide(0, null); + // eslint-disable-next-line no-bitwise + if (H.s.timeout & 1) { + H.ac.abort(); + } + // eslint-disable-next-line no-console + console.info(scriptName + " timed out."); + }, H.s.timeout); + if (mainScriptLoaded) { + H.main(); + } else { + // Load main script + fetch(H.paths.maindir + "Hyphenopoly.js", fetchOptions). + then((response) => { + if (response.ok) { + response.blob().then((blb) => { + const script = d[shortcuts.ce]("script"); + script.src = URL.createObjectURL(blb); + d.head[shortcuts.ac](script); + mainScriptLoaded = true; + URL.revokeObjectURL(script.src); + }); + } + }); + } + H.hy6ors = mp(); + H.cf.langs.forEach((langDef, lang) => { + if (langDef === "H9Y") { + H.hy6ors.set(lang, defProm()); + } + }); + H.hy6ors.set("HTML", defProm()); + H.hyphenators = new Proxy(H.hy6ors, { + "get": (target, key) => { + return target.get(key); + }, + "set": () => { + // Inhibit setting of hyphenators + return true; + } + }); + (() => { + if (hev && hev.polyfill) { + hev.polyfill(); + } + })(); + } else { + (() => { + if (hev && hev.tearDown) { + hev.tearDown(); + } + w.Hyphenopoly = null; + })(); + } + (() => { + if (H.cft) { + store.setItem(scriptName, JSON.stringify( + { + "langs": [...H.cf.langs.entries()], + "pf": H.cf.pf + } + )); + } + })(); + }); + + H.config = (c) => { + /** + * Sets default properties for an Object + * @param {object} obj - The object to set defaults to + * @param {object} defaults - The defaults to set + * @returns {object} + */ + const setDefaults = (obj, defaults) => { + if (obj) { + o.entries(defaults).forEach(([k, v]) => { + // eslint-disable-next-line security/detect-object-injection + obj[k] = obj[k] || v; + }); + return obj; + } + return defaults; + }; + + H.cft = Boolean(c.cacheFeatureTests); + if (H.cft && store.getItem(scriptName)) { + H.cf = JSON.parse(store.getItem(scriptName)); + H.cf.langs = mp(H.cf.langs); + } else { + H.cf = { + "langs": mp(), + "pf": false + }; + } + + const maindir = thisScript.slice(0, (thisScript.lastIndexOf("/") + 1)); + const patterndir = maindir + "patterns/"; + H.paths = setDefaults(c.paths, { + maindir, + patterndir + }); + H.s = setDefaults(c.setup, { + "CORScredentials": "include", + "hide": "all", + "selectors": {".hyphenate": {}}, + "timeout": 1000 + }); + // Change mode string to mode int + H.s.hide = ["all", "element", "text"].indexOf(H.s.hide); + if (c.handleEvent) { + H.hev = c.handleEvent; + } + + const fallbacks = mp(o.entries(c.fallbacks || {})); + H.lrq = mp(); + o.entries(c.require).forEach(([lang, wo]) => { + H.lrq.set(lang.toLowerCase(), { + "fn": fallbacks.get(lang) || lang, + wo + }); + }); + + main(); + }; +})(window, document, Hyphenopoly, Object); diff --git a/public/js/animation-queue-module.js b/public/js/animation-queue-module.js index 0fccc85..563bc22 100644 --- a/public/js/animation-queue-module.js +++ b/public/js/animation-queue-module.js @@ -10,19 +10,18 @@ class AnimationQueueModule extends BaseModule { super('animation-queue', 'Animation Queue'); // Module dependencies - this.dependencies = ['tts-player']; + this.dependencies = []; // Queue of scheduled animations/functions this.timeoutQueue = []; // Animation timing properties - use parent's config system this.updateConfig({ - speed: 0.05, // Base animation speed (seconds per character) + speed: 1.0, // Speed multiplier for delays (1.0 = no scaling, delays are pre-calculated) fastForwardEnabled: false }); this.delay = 0; // Current accumulated delay - this.tts = null; // TTS module reference // Bind methods using parent's bindMethods utility this.bindMethods([ @@ -33,22 +32,23 @@ class AnimationQueueModule extends BaseModule { 'beginFastForward', 'endFastForward', 'emitAnimationComplete', - 'cleanupStaleTasks', - 'isAnyTtsSpeaking' + 'cleanupStaleTasks' ]); } async initialize() { try { this.reportProgress(20, "Initializing Animation Queue"); - - // Try to get the TTS module, but it's not a hard dependency - // We'll check for it again at runtime when needed - this.tts = this.getModule('tts-player'); - if (!this.tts) { - console.log("Animation Queue: TTS Player module not found yet, will try again when needed"); - } - + + // Listen for speed changes from UI + document.addEventListener('animation:speed:change', (event) => { + if (event.detail && typeof event.detail.speed === 'number') { + // Speed from UI is a rate multiplier (0.5-2.0 typically) + this.config.speed = event.detail.speed; + console.log(`AnimationQueue: Speed updated to ${this.config.speed}`); + } + }); + this.reportProgress(100, "Animation Queue ready"); return true; } catch (error) { @@ -76,29 +76,6 @@ class AnimationQueueModule extends BaseModule { // Record the delay for tracking this.delay = Math.max(this.delay, delay); - // If we don't have a reference to the TTS module yet, try to get it - if (!this.tts) { - this.tts = this.getModule('tts-player'); - } - - // Handle TTS if text is provided and TTS is available and enabled - let ttsSpeaking = false; - if (options.text && this.tts && typeof this.tts.isEnabled === 'function' && this.tts.isEnabled()) { - // If we're fast forwarding, don't speak - if (!this.config.fastForwardEnabled) { - ttsSpeaking = true; - // Request TTS to speak the text - this.tts.speak(options.text, (result) => { - ttsSpeaking = false; - - // Check if this was keeping the queue busy - if (this.timeoutQueue.length === 0) { - this.emitAnimationComplete(); - } - }); - } - } - // Create a timeout object const timeoutObject = { func: func, @@ -106,8 +83,7 @@ class AnimationQueueModule extends BaseModule { timeoutId: null, executed: false, startTime: Date.now(), - ttsSpeaking: ttsSpeaking, - + // Add an execute method that marks the timeout as executed execute: function() { if (!this.executed) { @@ -138,7 +114,7 @@ class AnimationQueueModule extends BaseModule { } // If queue is empty and no TTS is speaking, emit animation complete - if (this.timeoutQueue.length === 0 && !this.isAnyTtsSpeaking()) { + if (this.timeoutQueue.length === 0 && true) { this.emitAnimationComplete(); } @@ -152,7 +128,7 @@ class AnimationQueueModule extends BaseModule { */ emitAnimationComplete() { // Only emit if queue is empty and no TTS is speaking - if (this.timeoutQueue.length === 0 && !this.isAnyTtsSpeaking()) { + if (this.timeoutQueue.length === 0 && true) { // Use parent's dispatchEvent method this.dispatchEvent('ui:animation:complete', { timestamp: Date.now() @@ -197,45 +173,16 @@ class AnimationQueueModule extends BaseModule { } /** - * Check if any TTS is currently speaking - * @returns {boolean} - True if TTS is speaking - */ - isAnyTtsSpeaking() { - // If we don't have a reference to the TTS module yet, try to get it - if (!this.tts) { - this.tts = this.getModule('tts-player'); - } - - // Check if TTS is speaking - if (this.tts && typeof this.tts.isSpeaking === 'function') { - return this.tts.isSpeaking(); - } - - // Default to false if TTS module is not available - return false; - } - - /** - * Fast forward all pending animations and stop TTS + * Fast forward all pending animations */ fastForward() { if (this.timeoutQueue.length === 0) { console.log('AnimationQueue: No animations to fast forward'); return; } - + console.log(`AnimationQueue: Fast forwarding ${this.timeoutQueue.length} pending items`); - // If we don't have a reference to the TTS module yet, try to get it - if (!this.tts) { - this.tts = this.getModule('tts-player'); - } - - // Stop any active TTS - if (this.tts && typeof this.tts.stop === 'function') { - this.tts.stop(); - } - // Execute all pending animations immediately this.timeoutQueue.forEach(timeout => { // Clear the timeout @@ -275,23 +222,13 @@ class AnimationQueueModule extends BaseModule { */ beginFastForward() { if (this.config.fastForwardEnabled) return; - + // Update config using parent's updateConfig method this.updateConfig({ fastForwardEnabled: true }); - - // If we don't have a reference to the TTS module yet, try to get it - if (!this.tts) { - this.tts = this.getModule('tts-player'); - } - - // Stop any active TTS - if (this.tts && typeof this.tts.stop === 'function') { - this.tts.stop(); - } - + // Use parent's dispatchEvent method this.dispatchEvent('ui:animation:fastforward', { state: true }); - + console.log('AnimationQueue: Fast forward mode activated'); } diff --git a/public/js/api-tts-module-base.js b/public/js/api-tts-module-base.js index 79ba0be..2cc5323 100644 --- a/public/js/api-tts-module-base.js +++ b/public/js/api-tts-module-base.js @@ -23,6 +23,7 @@ export class ApiTTSModuleBase extends TTSHandlerModule { // State this.currentAudio = null; + this.currentPlaybackFinish = null; // Bind additional methods this.bindMethods([ @@ -33,7 +34,9 @@ export class ApiTTSModuleBase extends TTSHandlerModule { 'selectVoiceForLocale', 'selectDefaultVoice', 'generateSpeechAudio', - 'preprocessText' + 'preprocessText', + 'getPlaybackVolume', + 'applyCurrentVolume' ]); } @@ -77,6 +80,16 @@ export class ApiTTSModuleBase extends TTSHandlerModule { // Set up event listeners for API key and URL changes document.addEventListener('tts:api:keyChanged', this.handleApiKeyChanged); document.addEventListener('tts:api:urlChanged', this.handleApiUrlChanged); + this.addEventListener(document, 'preference-updated', (event) => { + const { category, key } = event.detail || {}; + if (category !== 'audio') { + return; + } + + if (['masterVolume', 'ttsVolume', 'master_volume', 'tts_volume'].includes(key)) { + this.applyCurrentVolume(); + } + }); // Load voices await this.loadVoices(); @@ -90,9 +103,9 @@ export class ApiTTSModuleBase extends TTSHandlerModule { this.isReady = !!this.apiKey; if (!this.isReady) { - console.error(`${this.name}: Missing API key, initialization failed`); - this.reportProgress(100, `${this.name} initialization failed - missing API key`); - return false; // Properly report failure when API key is missing + console.info(`${this.name}: API key not configured; provider unavailable until configured`); + this.reportProgress(100, `${this.name} not configured`); + return true; } // Only mark as complete if we have an API key @@ -190,49 +203,106 @@ export class ApiTTSModuleBase extends TTSHandlerModule { * Speak preloaded audio data * @param {Object} preloadData - Preloaded audio data * @param {Function} callback - Callback for when speech completes - * @returns {boolean} - Success status + * @returns {Promise} - Resolves when audio finishes playing */ - speakPreloaded(preloadData, callback = null) { + async speakPreloaded(preloadData, callback = null) { if (!preloadData || !preloadData.audioData) { console.error(`${this.name}: Invalid preloaded data`); - if (callback) callback({ success: false, reason: 'invalid_data' }); - return false; + const result = { success: false, reason: 'invalid_data' }; + if (callback) callback(result); + return result; } - - // Create an audio element to play the audio - const audioBlob = new Blob([preloadData.audioData], { type: 'audio/mp3' }); - const audioUrl = URL.createObjectURL(audioBlob); - const audio = new Audio(audioUrl); - - // Set up state - this.isSpeaking = true; - this.currentAudio = audio; - - // Set up event handlers - audio.onended = () => { - this.isSpeaking = false; - this.currentAudio = null; - URL.revokeObjectURL(audioUrl); - - if (callback) callback({ success: true }); - }; - - audio.onerror = (error) => { - console.error(`${this.name}: Audio playback error:`, error); - this.isSpeaking = false; - this.currentAudio = null; - URL.revokeObjectURL(audioUrl); - - if (callback) callback({ success: false, reason: 'playback_error', error }); - }; - - // Play the audio - audio.play().catch(error => { - console.error(`${this.name}: Failed to play audio:`, error); - if (callback) callback({ success: false, reason: 'playback_error', error }); + + return new Promise((resolve) => { + // Create an audio element to play the audio + const audioBlob = new Blob([preloadData.audioData], { type: 'audio/mp3' }); + const audioUrl = URL.createObjectURL(audioBlob); + const audio = new Audio(audioUrl); + let settled = false; + + audio.volume = this.getPlaybackVolume(); + console.log(`${this.name}: Playback volume set to ${audio.volume.toFixed(2)}`); + + // Set up state + this.isSpeaking = true; + this.currentAudio = audio; + + const finish = (result) => { + if (settled) { + return; + } + + settled = true; + this.isSpeaking = false; + if (this.currentAudio === audio) { + this.currentAudio = null; + } + if (this.currentPlaybackFinish === finish) { + this.currentPlaybackFinish = null; + } + URL.revokeObjectURL(audioUrl); + + if (callback) callback(result); + resolve(result); + }; + this.currentPlaybackFinish = finish; + + // Set up event handlers + audio.onended = () => { + finish({ success: true }); + }; + + audio.onerror = (error) => { + console.error(`${this.name}: Audio playback error:`, error); + finish({ success: false, reason: 'playback_error', error }); + }; + + // Play the audio + audio.play().then(() => { + document.dispatchEvent(new CustomEvent('tts:audio-started', { + detail: { provider: this.id || this.name } + })); + }).catch(error => { + console.error(`${this.name}: Failed to play audio:`, error); + finish({ success: false, reason: 'playback_error', error }); + }); }); - - return true; + } + + /** + * Get the current effective TTS playback volume. + * @returns {number} Volume from 0 to 1. + */ + getPlaybackVolume() { + const persistenceManager = this.getModule('persistence-manager'); + if (!persistenceManager) { + return 1.0; + } + + const masterVolume = persistenceManager.getPreference( + 'audio', + 'masterVolume', + persistenceManager.getPreference('audio', 'master_volume', 1.0) + ); + const ttsVolume = persistenceManager.getPreference( + 'audio', + 'ttsVolume', + persistenceManager.getPreference('audio', 'tts_volume', 1.0) + ); + + return Math.max(0, Math.min(1, masterVolume * ttsVolume)); + } + + /** + * Apply updated volume settings to currently playing audio. + */ + applyCurrentVolume() { + if (!this.currentAudio) { + return; + } + + this.currentAudio.volume = this.getPlaybackVolume(); + console.log(`${this.name}: Updated current playback volume to ${this.currentAudio.volume.toFixed(2)}`); } /** @@ -245,6 +315,9 @@ export class ApiTTSModuleBase extends TTSHandlerModule { // Stop current audio this.currentAudio.pause(); this.currentAudio.currentTime = 0; + if (this.currentPlaybackFinish) { + this.currentPlaybackFinish({ success: false, reason: 'stopped' }); + } // Clean up this.isSpeaking = false; @@ -258,6 +331,33 @@ export class ApiTTSModuleBase extends TTSHandlerModule { } return true; // Already stopped } + + fadeOutCurrentAudio(duration = 1000) { + if (!this.currentAudio) { + return Promise.resolve(true); + } + + const audio = this.currentAudio; + const startVolume = audio.volume; + const startedAt = performance.now(); + + return new Promise((resolve) => { + const tick = () => { + const progress = Math.min(1, (performance.now() - startedAt) / duration); + audio.volume = startVolume * (1 - progress); + + if (progress >= 1) { + this.stop(); + resolve(true); + return; + } + + requestAnimationFrame(tick); + }; + + tick(); + }); + } /** * Speak text @@ -290,6 +390,29 @@ export class ApiTTSModuleBase extends TTSHandlerModule { return true; } + /** + * Calculate audio duration from audio buffer + * @param {ArrayBuffer} audioData - Audio data buffer + * @returns {Promise} - Duration in milliseconds + */ + async calculateAudioDuration(audioData) { + try { + // Use Web Audio API to decode audio and get duration + const audioContext = new (window.AudioContext || window.webkitAudioContext)(); + const audioBuffer = await audioContext.decodeAudioData(audioData.slice(0)); + const durationMs = audioBuffer.duration * 1000; + + // Close the audio context to free resources + await audioContext.close(); + + console.log(`${this.name}: Calculated audio duration: ${durationMs.toFixed(0)}ms`); + return durationMs; + } catch (error) { + console.warn(`${this.name}: Failed to calculate audio duration:`, error); + return 0; + } + } + /** * Preload speech for later playback * @param {string} text - Text to preload @@ -299,20 +422,26 @@ export class ApiTTSModuleBase extends TTSHandlerModule { if (!this.isReady) { return { success: false, reason: 'not_ready' }; } - + try { // Generate speech const result = await this.generateSpeechAudio(text); - + if (!result.success) { return { success: false, reason: 'generation_failed' }; } - + + // Calculate actual audio duration if not provided + let duration = result.duration || 0; + if (duration === 0 && result.audioData) { + duration = await this.calculateAudioDuration(result.audioData); + } + return { success: true, audioData: result.audioData, text, - duration: result.duration || 0 + duration: duration }; } catch (error) { return { success: false, reason: 'generation_error', error }; @@ -366,7 +495,7 @@ export class ApiTTSModuleBase extends TTSHandlerModule { // Save to preferences const persistenceManager = this.getModule('persistence-manager'); - if (persistenceManager) { + if (persistenceManager && oldKey !== newKey) { persistenceManager.updatePreference('tts', `${this.id}_api_key`, newKey); } @@ -384,12 +513,16 @@ export class ApiTTSModuleBase extends TTSHandlerModule { // If we have a key now (and didn't before), try initializing voices if (this.isReady && !wasReady) { // Reload voices with the new API key - this.loadVoices().then(() => { + this.loadVoices().then((voicesLoaded) => { + this.isReady = voicesLoaded !== false && !!this.apiKey; // Then set up voice from preferences this.setupVoiceFromPreferences().then(() => { - console.log(`${this.name}: Successfully initialized with new API key`); + console.log(`${this.name}: API key status: ${this.isReady ? 'ready' : 'not ready'}`); // Notify the factory of our readiness change ttsFactory.updateTTSAvailability(); + document.dispatchEvent(new CustomEvent('tts:status:updated', { + detail: { provider: this.id, ready: this.isReady } + })); }); }); } else { @@ -415,7 +548,7 @@ export class ApiTTSModuleBase extends TTSHandlerModule { // Save to preferences const persistenceManager = this.getModule('persistence-manager'); - if (persistenceManager) { + if (persistenceManager && oldUrl !== newUrl) { persistenceManager.updatePreference('tts', `${this.id}_api_url`, newUrl); } @@ -424,16 +557,20 @@ export class ApiTTSModuleBase extends TTSHandlerModule { console.log(`${this.name}: API URL changed, reinitializing`); // Reload voices with the new API URL if we're ready - this.loadVoices().then(() => { + this.loadVoices().then((voicesLoaded) => { + this.isReady = voicesLoaded !== false && !!this.apiKey; // Then set up voice from preferences this.setupVoiceFromPreferences().then(() => { - console.log(`${this.name}: Successfully reinitialized with new API URL`); + console.log(`${this.name}: API URL status: ${this.isReady ? 'ready' : 'not ready'}`); // Notify the TTS factory const ttsFactory = this.getModule('tts-factory'); if (ttsFactory) { ttsFactory.updateTTSAvailability(); } + document.dispatchEvent(new CustomEvent('tts:status:updated', { + detail: { provider: this.id, ready: this.isReady } + })); }); }); } diff --git a/public/js/audio-manager-module.js b/public/js/audio-manager-module.js index 4244be6..e1e15cb 100644 --- a/public/js/audio-manager-module.js +++ b/public/js/audio-manager-module.js @@ -8,12 +8,24 @@ class AudioManagerModule extends BaseModule { constructor() { super('audio-manager', 'Audio Manager'); this.sounds = new Map(); + this.sfxCache = new Map(); this.currentAudio = null; this.currentLoop = null; + this.currentMusic = null; + this.queuedMusic = null; this.masterVolume = 1.0; this.musicVolume = 1.0; this.sfxVolume = 1.0; this.ttsVolume = 1.0; + this.musicDuckingFactor = 1.0; + this.activeTtsPlaybackCount = 0; + this.ttsQueueEmpty = true; + this.pendingMusicPlayback = null; + this.assetRoots = { + images: '/images/', + music: '/music/', + sounds: '/sounds/' + }; // Add persistence-manager as a dependency this.dependencies = ['persistence-manager']; @@ -41,6 +53,8 @@ class AudioManagerModule extends BaseModule { try { // Set up audio context if needed this.setupAudioContext(); + this.loadPersistedVolumes(); + this.setupEventListeners(); // Load some basic sound effects this.reportProgress(80, "Loading sound effects"); @@ -52,6 +66,60 @@ class AudioManagerModule extends BaseModule { return false; } } + + loadPersistedVolumes() { + const persistenceManager = this.getModule('persistence-manager'); + if (!persistenceManager) { + return; + } + + this.masterVolume = this.clampVolume(persistenceManager.getPreference('audio', 'masterVolume', this.masterVolume)); + this.musicVolume = this.clampVolume(persistenceManager.getPreference('audio', 'musicVolume', this.musicVolume)); + this.sfxVolume = this.clampVolume(persistenceManager.getPreference('audio', 'sfxVolume', this.sfxVolume)); + this.ttsVolume = this.clampVolume(persistenceManager.getPreference('audio', 'ttsVolume', this.ttsVolume)); + } + + setupEventListeners() { + this.addEventListener(document, 'story:media-cue', (event) => { + this.handleMediaCue(event.detail || {}); + }); + + this.addEventListener(document, 'story:media-block', (event) => { + this.handleMediaBlock(event.detail || {}); + }); + + this.addEventListener(document, 'preference-updated', (event) => { + const { category, key, value } = event.detail || {}; + if (category !== 'audio') { + return; + } + + if (key === 'masterVolume') this.setMasterVolume(value); + if (key === 'musicVolume') this.setMusicVolume(value); + if (key === 'sfxVolume') this.setSfxVolume(value); + if (key === 'ttsVolume') this.setTtsVolume(value); + }); + + this.addEventListener(document, 'tts:playback-start', () => { + this.activeTtsPlaybackCount += 1; + this.ttsQueueEmpty = false; + this.duckMusicForSpeech(); + }); + + this.addEventListener(document, 'tts:playback-end', () => { + this.activeTtsPlaybackCount = Math.max(0, this.activeTtsPlaybackCount - 1); + this.restoreMusicIfSpeechFinished(); + }); + + this.addEventListener(document, 'tts:queue-empty', () => { + this.ttsQueueEmpty = true; + this.restoreMusicIfSpeechFinished(); + }); + + const unlock = () => this.unlockPendingAudio(); + document.addEventListener('pointerdown', unlock, { passive: true }); + document.addEventListener('keydown', unlock); + } /** * Set up Web Audio API context if needed @@ -73,6 +141,7 @@ class AudioManagerModule extends BaseModule { loadSound(id, url) { return new Promise((resolve, reject) => { const audio = new Audio(url); + audio.preload = 'auto'; audio.addEventListener('canplaythrough', () => { this.sounds.set(id, audio); resolve(audio); @@ -105,13 +174,15 @@ class AudioManagerModule extends BaseModule { audio.loop = true; this.currentLoop = audio; } else { - if (this.currentAudio) { - this.currentAudio.pause(); - this.currentAudio.currentTime = 0; - } - this.currentAudio = audio; + this.currentAudio = audio.cloneNode(true); + this.currentAudio.volume = this.getSfxVolume(); + this.currentAudio.play().catch(error => { + console.error('Error playing audio:', error); + }); + return this.currentAudio; } + audio.volume = this.getMusicVolume(); audio.play().catch(error => { console.error('Error playing audio:', error); }); @@ -134,17 +205,14 @@ class AudioManagerModule extends BaseModule { } this.currentLoop = new Audio(url); this.currentLoop.loop = true; + this.currentLoop.volume = this.getMusicVolume(); this.currentLoop.play().catch(error => { console.error('Error playing audio loop:', error); }); return this.currentLoop; } else { - if (this.currentAudio) { - this.currentAudio.pause(); - this.currentAudio.removeAttribute('src'); - this.currentAudio.load(); - } this.currentAudio = new Audio(url); + this.currentAudio.volume = this.getSfxVolume(); this.currentAudio.play().catch(error => { console.error('Error playing audio:', error); }); @@ -191,7 +259,7 @@ class AudioManagerModule extends BaseModule { * @param {number} volume - The volume level (0.0 to 1.0) */ setMasterVolume(volume) { - this.masterVolume = Math.max(0, Math.min(1, volume)); + this.masterVolume = this.clampVolume(volume); this.updateVolumes(); } @@ -200,11 +268,7 @@ class AudioManagerModule extends BaseModule { * @param {number} volume - The volume level (0.0 to 1.0) */ setTtsVolume(volume) { - this.ttsVolume = Math.max(0, Math.min(1, volume)); - // Apply to current non-loop audio if it exists - if (this.currentAudio) { - this.currentAudio.volume = this.masterVolume * this.ttsVolume; - } + this.ttsVolume = this.clampVolume(volume); } /** @@ -212,11 +276,8 @@ class AudioManagerModule extends BaseModule { * @param {number} volume - The volume level (0.0 to 1.0) */ setMusicVolume(volume) { - this.musicVolume = Math.max(0, Math.min(1, volume)); - // Apply to current loop if it exists - if (this.currentLoop) { - this.currentLoop.volume = this.masterVolume * this.musicVolume; - } + this.musicVolume = this.clampVolume(volume); + this.updateVolumes(); } /** @@ -224,11 +285,8 @@ class AudioManagerModule extends BaseModule { * @param {number} volume - The volume level (0.0 to 1.0) */ setSfxVolume(volume) { - this.sfxVolume = Math.max(0, Math.min(1, volume)); - // Apply to current non-loop audio if it exists - if (this.currentAudio) { - this.currentAudio.volume = this.masterVolume * this.sfxVolume; - } + this.sfxVolume = this.clampVolume(volume); + this.updateVolumes(); } /** @@ -247,6 +305,258 @@ class AudioManagerModule extends BaseModule { if (this.currentLoop) { this.currentLoop.volume = this.masterVolume * this.musicVolume; } + + if (this.currentMusic) { + this.currentMusic.volume = this.getMusicVolume(); + } + } + + clampVolume(volume) { + return Math.max(0, Math.min(1, Number.isFinite(Number(volume)) ? Number(volume) : 1)); + } + + getSfxVolume() { + return this.masterVolume * this.sfxVolume; + } + + getMusicVolume() { + return this.masterVolume * this.musicVolume * this.musicDuckingFactor; + } + + getUnduckedMusicVolume() { + return this.masterVolume * this.musicVolume; + } + + duckMusicForSpeech() { + console.log('AudioManager: Ducking music for TTS playback'); + this.fadeMusicTo(0.7, 500); + } + + restoreMusicAfterSpeech() { + console.log('AudioManager: Restoring music after TTS queue drained'); + this.fadeMusicTo(1.0, 900); + } + + restoreMusicIfSpeechFinished() { + if (this.activeTtsPlaybackCount === 0 && this.ttsQueueEmpty) { + this.restoreMusicAfterSpeech(); + } + } + + fadeMusicTo(factor, duration = 700) { + this.musicDuckingFactor = Math.max(0, Math.min(1, factor)); + if (!this.currentMusic) { + return; + } + + const audio = this.currentMusic; + const startVolume = audio.volume; + const targetVolume = this.getUnduckedMusicVolume() * this.musicDuckingFactor; + const start = performance.now(); + + const tick = () => { + const progress = Math.min(1, (performance.now() - start) / duration); + audio.volume = startVolume + ((targetVolume - startVolume) * progress); + if (progress < 1) { + requestAnimationFrame(tick); + } + }; + + tick(); + } + + getAssetUrl(kind, filename) { + const root = this.assetRoots[kind]; + if (!root) { + throw new Error(`Unknown audio asset kind: ${kind}`); + } + + const safeName = String(filename || '').replace(/\\/g, '/').replace(/^\/+/, ''); + if (!safeName || safeName.includes('..') || /^[a-z]+:/i.test(safeName)) { + throw new Error(`Unsafe asset filename: ${filename}`); + } + + return root + safeName.split('/').map(encodeURIComponent).join('/'); + } + + async preloadSfx(filename) { + const url = this.getAssetUrl('sounds', filename); + if (this.sfxCache.has(url)) { + return this.sfxCache.get(url); + } + + const promise = new Promise((resolve, reject) => { + const audio = new Audio(url); + audio.preload = 'auto'; + audio.volume = this.getSfxVolume(); + audio.addEventListener('canplaythrough', () => resolve(audio), { once: true }); + audio.addEventListener('error', () => reject(new Error(`Failed to preload sound effect: ${url}`)), { once: true }); + audio.load(); + }); + + this.sfxCache.set(url, promise); + return promise; + } + + async preloadMediaCues(cues = []) { + const tasks = cues + .filter(cue => cue && cue.type === 'sfx' && cue.filename) + .map(cue => this.preloadSfx(cue.filename).catch(error => { + console.warn('AudioManager: SFX preload failed:', error); + return null; + })); + + await Promise.all(tasks); + } + + handleMediaCue(cue) { + if (!cue || !cue.type) { + return; + } + + if (cue.type === 'sfx') { + this.playSfx(cue.filename); + } else if (cue.type === 'music') { + this.playMusic(cue.filename, cue.mode || 'crossfade', { loop: cue.loop !== false }); + } + } + + handleMediaBlock(block) { + if (!block || block.type !== 'music') { + return; + } + + this.playMusic(block.filename, block.mode || 'crossfade', { loop: block.loop !== false }); + } + + async playSfx(filename) { + try { + const template = await this.preloadSfx(filename); + const audio = template.cloneNode(true); + audio.volume = this.getSfxVolume(); + this.currentAudio = audio; + audio.addEventListener('ended', () => { + if (this.currentAudio === audio) { + this.currentAudio = null; + } + }, { once: true }); + await audio.play(); + console.log(`AudioManager: Playing sound effect ${filename}`); + return audio; + } catch (error) { + console.error('AudioManager: Failed to play sound effect:', error); + return null; + } + } + + async playMusic(filename, mode = 'crossfade', options = {}) { + const url = this.getAssetUrl('music', filename); + const shouldLoop = options.loop !== false; + + if (mode === 'queue' && this.currentMusic && !this.currentMusic.paused) { + this.queuedMusic = { filename, mode: 'cut', options: { loop: shouldLoop } }; + this.currentMusic.addEventListener('ended', () => { + const queued = this.queuedMusic; + this.queuedMusic = null; + if (queued) this.playMusic(queued.filename, queued.mode, queued.options); + }, { once: true }); + console.log(`AudioManager: Queued music ${filename}`); + return this.currentMusic; + } + + const next = new Audio(url); + next.loop = shouldLoop; + next.volume = mode === 'crossfade' && this.currentMusic ? 0 : this.getMusicVolume(); + next.addEventListener('ended', () => { + if (this.currentMusic === next) { + this.currentMusic = null; + } + }); + + if (mode === 'cut' || !this.currentMusic) { + this.stopCurrentMusic(); + this.currentMusic = next; + await this.startMusicAudio(next, filename); + return next; + } + + const previous = this.currentMusic; + this.currentMusic = next; + await this.startMusicAudio(next, filename); + this.crossfade(previous, next, 1500); + console.log(`AudioManager: Crossfading music to ${filename}`); + return next; + } + + async startMusicAudio(audio, filename) { + try { + await audio.play(); + console.log(`AudioManager: Playing music ${filename}`); + } catch (error) { + this.pendingMusicPlayback = { audio, filename }; + console.warn('AudioManager: Music playback is waiting for user interaction:', error); + } + } + + async unlockPendingAudio() { + if (this.audioContext && this.audioContext.state === 'suspended') { + try { + await this.audioContext.resume(); + } catch (error) { + console.warn('AudioManager: Failed to resume audio context:', error); + } + } + + if (!this.pendingMusicPlayback) { + return; + } + + const pending = this.pendingMusicPlayback; + this.pendingMusicPlayback = null; + pending.audio.volume = this.getMusicVolume(); + + try { + await pending.audio.play(); + console.log(`AudioManager: Resumed pending music ${pending.filename}`); + } catch (error) { + this.pendingMusicPlayback = pending; + console.warn('AudioManager: Pending music still blocked:', error); + } + } + + stopCurrentMusic() { + if (!this.currentMusic) { + return; + } + + this.currentMusic.pause(); + this.currentMusic.currentTime = 0; + this.currentMusic = null; + } + + crossfade(previous, next, duration = 1500) { + const start = performance.now(); + const previousStart = previous ? previous.volume : 0; + const target = this.getMusicVolume(); + + const tick = () => { + const progress = Math.min(1, (performance.now() - start) / duration); + if (previous) previous.volume = previousStart * (1 - progress); + next.volume = target * progress; + + if (progress < 1) { + requestAnimationFrame(tick); + return; + } + + if (previous) { + previous.pause(); + previous.currentTime = 0; + } + next.volume = this.getMusicVolume(); + }; + + tick(); } /** diff --git a/public/js/browser-tts-module.js b/public/js/browser-tts-module.js index 9a83a69..156c900 100644 --- a/public/js/browser-tts-module.js +++ b/public/js/browser-tts-module.js @@ -248,6 +248,9 @@ export class BrowserTTSModule extends TTSHandlerModule { this.utteranceHandlers = { start: () => { this.isSpeaking = true; + document.dispatchEvent(new CustomEvent('tts:audio-started', { + detail: { provider: this.id || this.name } + })); }, end: () => { this.isSpeaking = false; @@ -443,13 +446,8 @@ export class BrowserTTSModule extends TTSHandlerModule { } if (typeof options.speed === 'number') { - this.voiceOptions.speed = Math.max(0.5, Math.min(2.0, options.speed)); - - // Save speed preference - const persistenceManager = this.getModule('persistence-manager'); - if (persistenceManager) { - persistenceManager.updatePreference('tts', 'browser_speed', options.speed); - } + // Web Speech rate uses 1.0 as normal, matching the app-wide slider. + this.voiceOptions.speed = Math.max(0.1, Math.min(10.0, options.speed)); } if (typeof options.pitch === 'number') { diff --git a/public/js/debug-utils-module.js b/public/js/debug-utils-module.js index fe8b7fe..19fb1f9 100644 --- a/public/js/debug-utils-module.js +++ b/public/js/debug-utils-module.js @@ -9,7 +9,7 @@ export class DebugUtilsModule extends BaseModule { super('debug-utils', 'Debug Utilities'); // Declare dependencies explicitly - this.dependencies = ['text-buffer', 'socket-client', 'tts-player', 'ui-controller', 'game-loop']; + this.dependencies = ['text-buffer', 'socket-client', 'tts-factory', 'ui-controller', 'game-loop']; } /** @@ -83,31 +83,27 @@ export class DebugUtilsModule extends BaseModule { */ testTTS(text = "This is a test of the text to speech system.") { console.log("Debug: Testing TTS with:", text); - - // Get the TTS module properly through dependency system - const ttsPlayer = this.getModule('tts-player'); - if (!ttsPlayer) { - console.error("Debug: TTS module not found"); + + // Get the TTS factory properly through dependency system + const ttsFactory = this.getModule('tts-factory'); + if (!ttsFactory) { + console.error("Debug: TTS factory not found"); return false; } - - const wasEnabled = ttsPlayer.isEnabled(); - - // Enable TTS temporarily if it was disabled - if (!wasEnabled && ttsPlayer.toggle) { - ttsPlayer.toggle(); + + const activeHandler = ttsFactory.getActiveHandler(); + if (!activeHandler) { + console.error("Debug: No active TTS handler"); + return false; } - + // Speak the text - ttsPlayer.speak(text, (result) => { + ttsFactory.speak(text).then((result) => { console.log("Debug: TTS completed with result:", result); - - // Restore previous enabled state - if (!wasEnabled && ttsPlayer.toggle) { - ttsPlayer.toggle(); - } + }).catch((error) => { + console.error("Debug: TTS error:", error); }); - + return true; } @@ -123,10 +119,10 @@ export class DebugUtilsModule extends BaseModule { const socketClient = this.getModule('socket-client'); const gameLoop = this.getModule('game-loop'); const textBuffer = this.getModule('text-buffer'); - const ttsHandler = this.getModule('tts-player'); - + const ttsFactory = this.getModule('tts-factory'); + // Check if all modules are available - if (!uiController || !socketClient || !gameLoop || !textBuffer || !ttsHandler) { + if (!uiController || !socketClient || !gameLoop || !textBuffer || !ttsFactory) { console.error("Debug: One or more required modules not found"); return false; } diff --git a/public/js/elevenlabs-tts-module.js b/public/js/elevenlabs-tts-module.js index 9b32a36..e080bd5 100644 --- a/public/js/elevenlabs-tts-module.js +++ b/public/js/elevenlabs-tts-module.js @@ -41,17 +41,25 @@ export class ElevenLabsTTSModule extends ApiTTSModuleBase { // API key is already loaded in parent initialize() method // Just check if it's available if (!this.apiKey) { - console.error('ElevenLabs TTS: API key not configured'); - return false; + console.info('ElevenLabs TTS: API key not configured; provider unavailable until configured'); + this.isReady = false; + this.reportProgress(100, 'ElevenLabs TTS not configured'); + return true; } // Load voices from ElevenLabs try { this.reportProgress(50, 'Loading ElevenLabs voices'); - await this.loadVoices(this.apiKey); + const voicesLoaded = await this.loadVoices(this.apiKey); + if (!voicesLoaded) { + this.isReady = false; + this.reportProgress(100, 'ElevenLabs TTS not ready'); + return true; + } } catch (error) { console.error('ElevenLabs TTS: Failed to load voices:', error); - return false; + this.isReady = false; + return true; } // Load preferences @@ -65,9 +73,9 @@ export class ElevenLabsTTSModule extends ApiTTSModuleBase { this.voiceOptions.model = preferredModel; } - const preferredSpeed = persistenceManager.getPreference('tts', `${this.id}_speed`, this.voiceOptions.speed); + const preferredSpeed = persistenceManager.getPreference('tts', 'speed', this.voiceOptions.speed); if (typeof preferredSpeed === 'number') { - this.voiceOptions.speed = preferredSpeed; + this.voiceOptions.speed = this.getApiSpeed(preferredSpeed); } this.isReady = true; @@ -119,7 +127,7 @@ export class ElevenLabsTTSModule extends ApiTTSModuleBase { if (!response.ok) { console.error(`ElevenLabs TTS: API error ${response.status} ${response.statusText}`); - return true; // Continue with default voices + return false; } const data = await response.json(); @@ -136,10 +144,10 @@ export class ElevenLabsTTSModule extends ApiTTSModuleBase { return true; } - return true; // Continue with default voices + return this.voices.length > 0; } catch (error) { console.error('ElevenLabs TTS: Error loading voices:', error); - return true; // Continue with default voices + return false; } } @@ -188,7 +196,7 @@ export class ElevenLabsTTSModule extends ApiTTSModuleBase { similarity_boost: 0.75, style: 0.0, use_speaker_boost: true, - speed: this.voiceOptions.speed || 1.0 + speed: this.getApiSpeed(this.voiceOptions.speed) } }; @@ -198,13 +206,15 @@ export class ElevenLabsTTSModule extends ApiTTSModuleBase { headers: { 'Content-Type': 'application/json', 'xi-api-key': this.apiKey, - 'Accept': 'audio/wav' + 'Accept': 'audio/mpeg' }, body: JSON.stringify(payload) }); - + if (!response.ok) { - throw new Error(`API error: ${response.status} ${response.statusText}`); + const errorText = await response.text(); + console.error(`ElevenLabs API error ${response.status}: ${errorText}`); + throw new Error(`API error: ${response.status} ${response.statusText} - ${errorText}`); } // Get audio blob from response @@ -244,7 +254,7 @@ export class ElevenLabsTTSModule extends ApiTTSModuleBase { } if (typeof options.speed === 'number') { - this.voiceOptions.speed = Math.max(0.5, Math.min(2.0, options.speed)); + this.voiceOptions.speed = this.getApiSpeed(options.speed); } // Handle ElevenLabs-specific options @@ -258,6 +268,10 @@ export class ElevenLabsTTSModule extends ApiTTSModuleBase { } } } + + getApiSpeed(speed) { + return Math.max(0.7, Math.min(1.2, Number.isFinite(speed) ? speed : 1.0)); + } } const elevenLabsTTSModule = new ElevenLabsTTSModule(); diff --git a/public/js/game-loop-module.js b/public/js/game-loop-module.js index 9387036..6799423 100644 --- a/public/js/game-loop-module.js +++ b/public/js/game-loop-module.js @@ -9,7 +9,7 @@ class GameLoopModule extends BaseModule { super('game-loop', 'Game Loop'); // Dependencies - this.dependencies = ['ui-controller', 'socket-client', 'tts-player', 'text-buffer']; + this.dependencies = ['ui-controller', 'socket-client', 'text-buffer']; // Game state this.gameState = { @@ -25,9 +25,11 @@ class GameLoopModule extends BaseModule { // Bind methods using parent's bindMethods utility this.bindMethods([ 'start', + 'setupUiEventListeners', 'setupSocketEventListeners', 'updateGameState', 'updateUIState', + 'refreshGameApiState', 'requestStartGame', 'requestSaveGame', 'requestLoadGame', @@ -46,6 +48,7 @@ class GameLoopModule extends BaseModule { try { // The dependencies are now automatically available via getModule this.updateUIState(); + this.setupUiEventListeners(); console.log("GameLoop: Setting up socket listeners and connecting..."); @@ -58,6 +61,15 @@ class GameLoopModule extends BaseModule { console.error("Error starting game loop:", error); } } + + setupUiEventListeners() { + if (this.uiEventsBound) return; + this.uiEventsBound = true; + + document.addEventListener('ui:game:restart', () => this.requestStartGame()); + document.addEventListener('ui:game:save', () => this.requestSaveGame()); + document.addEventListener('ui:game:load', () => this.requestLoadGame()); + } setupSocketEventListeners() { // Get the socket client module using parent's getModule method @@ -81,14 +93,7 @@ class GameLoopModule extends BaseModule { socketClient.on('connect', () => { console.log("GameLoop: Socket connected event received."); - // Request a new game start when we connect - // Only request start game if one isn't already in progress - if (!this.gameState.started) { - console.log("GameLoop: Requesting start game on connect."); - this.requestStartGame(); - } else { - console.log("GameLoop: Game already started, skipping duplicate start request."); - } + this.refreshGameApiState(); }); // Listen for game state updates @@ -107,9 +112,22 @@ class GameLoopModule extends BaseModule { socketClient.on('gameIntroduction', (data) => { console.log("GameLoop: Received gameIntroduction"); this.gameState.started = true; + this.gameState.canSave = true; this.updateUIState(); // Text processing is handled by socket-client -> text-buffer -> ui-controller pipeline }); + + socketClient.on('gameSaved', () => { + this.gameState.canLoad = true; + this.updateUIState(); + }); + + socketClient.on('gameLoaded', () => { + this.gameState.started = true; + this.gameState.canSave = true; + this.gameState.canLoad = true; + this.updateUIState(); + }); // Connect to the socket server socketClient.connect().then(success => { @@ -120,6 +138,21 @@ class GameLoopModule extends BaseModule { } }); } + + async refreshGameApiState() { + const socketClient = this.getModule('socket-client'); + if (!socketClient || !socketClient.getConnectionStatus()) return; + + const [running, hasSave] = await Promise.all([ + socketClient.isGameRunning(), + socketClient.hasSaveGame(1) + ]); + + this.gameState.started = Boolean(running?.result); + this.gameState.canSave = this.gameState.started; + this.gameState.canLoad = Boolean(hasSave?.result); + this.updateUIState(); + } /** * Update the game state @@ -149,38 +182,85 @@ class GameLoopModule extends BaseModule { if (!uiController) return; // Update UI components based on game state - uiController.updateButtonStates(this.gameState); + const state = { + canRestart: true, + canSave: Boolean(this.gameState.started), + canLoad: Boolean(this.gameState.canLoad), + gameStarted: Boolean(this.gameState.started) + }; + document.body.dataset.gameRunning = state.gameStarted ? 'true' : 'false'; + uiController.updateButtonStates(state); } /** * Request to start a new game */ - requestStartGame() { + async requestStartGame() { const socketClient = this.getModule('socket-client'); if (!socketClient) return; - - socketClient.requestStartGame(); + + const uiController = this.getModule('ui-controller'); + if (uiController) { + uiController.clearDisplay(); + } + const textBuffer = this.getModule('text-buffer'); + if (textBuffer && typeof textBuffer.clear === 'function') { + textBuffer.clear(); + } + const response = await socketClient.newGame(); + if (!response?.success) { + console.error('GameLoop: newGame failed', response); + return; + } this.gameState.started = true; + this.gameState.canSave = true; + this.gameState.canLoad = Boolean(response.canLoad); + this.updateUIState(); } /** * Request to save the current game */ - requestSaveGame() { + async requestSaveGame() { const socketClient = this.getModule('socket-client'); - if (!socketClient) return; - - socketClient.requestSaveGame(); + if (!socketClient || !this.gameState.started) return; + + const response = await socketClient.saveGame(1); + if (response?.success) { + this.gameState.canLoad = true; + this.updateUIState(); + } } /** * Request to load a saved game */ - requestLoadGame() { + async requestLoadGame() { const socketClient = this.getModule('socket-client'); if (!socketClient) return; - - socketClient.requestLoadGame(); + + const hasSave = await socketClient.hasSaveGame(1); + if (!hasSave?.result) { + this.gameState.canLoad = false; + this.updateUIState(); + return; + } + + const uiController = this.getModule('ui-controller'); + if (uiController) { + uiController.clearDisplay(); + } + const textBuffer = this.getModule('text-buffer'); + if (textBuffer && typeof textBuffer.clear === 'function') { + textBuffer.clear(); + } + const response = await socketClient.loadGame(1); + if (response?.success) { + this.gameState.started = true; + this.gameState.canSave = true; + this.gameState.canLoad = true; + this.updateUIState(); + } } /** diff --git a/public/js/knuth-and-plass.js b/public/js/knuth-and-plass.js index f752665..9e0808a 100644 --- a/public/js/knuth-and-plass.js +++ b/public/js/knuth-and-plass.js @@ -1,4 +1,4 @@ -function kap(text, measureText, measure, hyphenation) { +function kap(text, measureText, measure, hyphenation) { console.log("Typesetting hyphenated text:", text, measure); if (!hyphenation) { text = text.replace(/\|/g, ''); @@ -48,9 +48,9 @@ function kap(text, measureText, measure, hyphenation) { let breaks = linebreak(nodes, measure, { tolerance: 3, demerits }); - if (!breaks.length) { - breaks = linebreak(nodes, measure, { tolerance: 10, demerits }); - } - - return { nodes, breaks }; -} + if (!breaks.length) { + breaks = linebreak(nodes, measure, { tolerance: 10, demerits }); + } + + return { nodes, breaks }; +} diff --git a/public/js/kokoro-tts-module.js b/public/js/kokoro-tts-module.js index 7011e42..fe2b6ad 100644 --- a/public/js/kokoro-tts-module.js +++ b/public/js/kokoro-tts-module.js @@ -20,6 +20,12 @@ export class KokoroTTSModule extends TTSHandlerModule { this.lastProgressTime = null; this.lastProgressValue = null; this.modelLoaded = false; + + // Options for playback + this.options = { + volume: 1.0, + rate: 1.0 + }; // Bind additional methods beyond those in TTSHandlerModule this.bindMethods([ @@ -30,7 +36,8 @@ export class KokoroTTSModule extends TTSHandlerModule { 'preprocessText', 'pause', 'resume', - 'getDefaultVoices' + 'getDefaultVoices', + 'setVoiceOptions' ]); } @@ -51,6 +58,16 @@ export class KokoroTTSModule extends TTSHandlerModule { console.error('Kokoro TTS: Required dependency persistence-manager not found'); return false; } + + const ttsEnabled = persistenceManager.getPreference('tts', 'enabled', false); + const preferredHandler = persistenceManager.getPreference('tts', 'preferred_handler', 'none'); + if (!ttsEnabled || preferredHandler !== this.id) { + this.voices = this.getDefaultVoices(); + this.isReady = false; + this.reportProgress(100, 'Kokoro TTS not selected'); + console.log('Kokoro TTS: Skipping model load because provider is not selected'); + return true; + } // Try to check if the kokoro-js.js resource exists before proceeding try { @@ -206,9 +223,11 @@ export class KokoroTTSModule extends TTSHandlerModule { if (!event.data.success || event.data.error) { resolver.reject(new Error(event.data.error || 'Speech generation failed')); } else { + const audioData = event.data.result && event.data.result.buffer; + console.log('Kokoro: Generation complete, audioData:', audioData ? `${audioData.byteLength} bytes` : 'UNDEFINED'); resolver.resolve({ success: true, - audioData: event.data.result && event.data.result.buffer, + audioData: audioData, duration: event.data.duration || 0 }); } @@ -333,6 +352,21 @@ export class KokoroTTSModule extends TTSHandlerModule { return true; } + + setVoiceOptions(options = {}) { + if (options.voice) { + const voice = this.voices.find(v => v.id === options.voice) || { id: options.voice }; + this.setVoice(voice); + } + + if (typeof options.speed === 'number') { + this.setOptions({ rate: Math.max(0.5, Math.min(2.0, options.speed)) }); + } + + if (typeof options.volume === 'number') { + this.setOptions({ volume: Math.max(0, Math.min(1, options.volume)) }); + } + } /** * Get available voices @@ -435,7 +469,11 @@ export class KokoroTTSModule extends TTSHandlerModule { // Start playback this.currentAudio = audio; this.isSpeaking = true; - audio.play().catch(error => { + audio.play().then(() => { + document.dispatchEvent(new CustomEvent('tts:audio-started', { + detail: { provider: this.id || this.name } + })); + }).catch(error => { this.isSpeaking = false; if (callback) { callback({ success: false, reason: 'playback_error', error }); @@ -498,7 +536,11 @@ export class KokoroTTSModule extends TTSHandlerModule { // Start playback this.currentAudio = audio; this.isSpeaking = true; - audio.play().catch(error => { + audio.play().then(() => { + document.dispatchEvent(new CustomEvent('tts:audio-started', { + detail: { provider: this.id || this.name } + })); + }).catch(error => { this.isSpeaking = false; if (callback) { callback({ success: false, reason: 'playback_error', error }); @@ -645,4 +687,4 @@ export class KokoroTTSModule extends TTSHandlerModule { const kokoroTTSModule = new KokoroTTSModule(); -export { kokoroTTSModule }; \ No newline at end of file +export { kokoroTTSModule }; diff --git a/public/js/layout-renderer-module.js b/public/js/layout-renderer-module.js index 395106c..fbf7864 100644 --- a/public/js/layout-renderer-module.js +++ b/public/js/layout-renderer-module.js @@ -9,7 +9,7 @@ class LayoutRendererModule extends BaseModule { super('layout-renderer', 'Layout Renderer'); // Module dependencies - this.dependencies = ['animation-queue', 'tts-player']; + this.dependencies = []; // Configuration this.updateConfig({ @@ -22,8 +22,8 @@ class LayoutRendererModule extends BaseModule { // Bind methods this.bindMethods([ 'renderParagraph', - 'renderWord', - 'scheduleWordAnimation' + 'initializeContainers', + 'adjustJustification' ]); } @@ -34,14 +34,6 @@ class LayoutRendererModule extends BaseModule { async initialize() { try { this.reportProgress(10, "Initializing Layout Renderer"); - - // Check for animation queue dependency - const animationQueue = this.getModule('animation-queue'); - if (!animationQueue) { - console.warn("Layout Renderer: Animation Queue module not found in registry"); - return false; - } - this.reportProgress(100, "Layout Renderer ready"); return true; } catch (error) { @@ -65,199 +57,212 @@ class LayoutRendererModule extends BaseModule { } /** - * Render a paragraph from layout data - * @param {Object} layout - Layout data from paragraph-layout + * Render a paragraph from layout data (pure DOM creation, no animation) + * @param {Object} layoutData - Layout data containing breaks, nodes, and measures * @param {Object} options - Rendering options * @returns {HTMLElement} - The created paragraph element */ - renderParagraph(layout, options = {}) { - const animationQueue = this.getModule('animation-queue'); + renderParagraph(layoutData, options = {}) { + const { id = `p-${Date.now()}` } = options; + const { breaks, nodes, measures, fontSize, fontFamily, lineHeightPx } = layoutData; - const { - container = document.getElementById('paragraphs'), - id = `p-${Date.now()}`, - className = '', - style = {}, - animateWords = true, - animationSpeed = this.config.animation.defaultSpeed, - tts = false, - onComplete = null - } = options; - - if (!layout || !layout.breaks || !layout.nodes || !container) { - console.error('Invalid layout data or container'); + if (!breaks || !nodes) { + console.error('LayoutRenderer: Invalid layout data'); return null; } - - // Create paragraph element - const paragraphElement = document.createElement('p'); - paragraphElement.id = id; - paragraphElement.className = `paragraph ${className}`.trim(); - paragraphElement.style.position = 'relative'; - - // Get line height and container width for positioning - const lineHeight = parseFloat(window.getComputedStyle(document.querySelector('#story')).lineHeight) || 1.5; - const containerWidth = parseFloat(window.getComputedStyle(container).width); - - // Calculate paragraph height based on number of lines - const numLines = layout.breaks.length - 1; - const paragraphHeight = numLines * lineHeight; - paragraphElement.style.height = `${paragraphHeight}em`; - - // Apply custom style properties - for (const prop in style) { - paragraphElement.style[prop] = style[prop]; + + // Create paragraph container + const paragraph = document.createElement('p'); + paragraph.id = id; + paragraph.className = [ + layoutData.role ? `story-${layoutData.role}` : '', + layoutData.addTopSpace ? 'story-textblock-start' : '', + layoutData.dropCap ? 'story-dropcap-paragraph' : '' + ].filter(Boolean).join(' '); + paragraph.style.position = 'relative'; + paragraph.style.margin = '0'; + if (fontSize) paragraph.style.fontSize = fontSize; + if (fontFamily) paragraph.style.fontFamily = fontFamily; + if (Array.isArray(measures) && measures.length > 0) { + paragraph.style.width = `${Math.max(...measures)}px`; + paragraph.style.maxWidth = '100%'; } - - // Populate with words - const wordElements = []; - let lineIndex = 0; - let totalDelay = 0; - - // Calculate each word's position based on layout data - for (let i = 0; i < layout.nodes.length; i++) { - const wordNode = layout.nodes[i]; - - // Get the current line index from breaks array - while (lineIndex < layout.breaks.length - 1 && i >= layout.breaks[lineIndex + 1]) { - lineIndex++; - } - - // Create the word element - const wordElement = this.renderWord(wordNode.text, animateWords); - wordElements.push(wordElement); - - // Position the word absolutely within paragraph - if (wordNode.x !== undefined && wordNode.y !== undefined) { - // Use calculated position - wordElement.style.position = 'absolute'; - wordElement.style.left = `${wordNode.x}px`; - wordElement.style.top = `${lineIndex * lineHeight}em`; - } else { - // Fallback for missing positioning data - wordElement.style.position = 'relative'; - wordElement.style.marginRight = '0.25em'; - } - - // Add to paragraph - paragraphElement.appendChild(wordElement); - - // Handle whitespace after the word - if (wordNode.spaceAfter) { - const spaceElement = document.createElement('span'); - spaceElement.className = 'space'; - spaceElement.innerHTML = ' '; - - if (wordNode.x !== undefined) { - // Position space after word - spaceElement.style.position = 'absolute'; - const wordWidth = wordElement.offsetWidth || wordNode.width || wordNode.text.length * 8; - spaceElement.style.left = `${wordNode.x + wordWidth}px`; - spaceElement.style.top = `${lineIndex * lineHeight}em`; - } else { - spaceElement.style.position = 'relative'; - } - - paragraphElement.appendChild(spaceElement); - } + + // Calculate paragraph height + const storyElement = document.getElementById('story'); + if (!storyElement) { + console.error('LayoutRenderer: Story container not found'); + return null; } - - // Add the paragraph to the container - container.appendChild(paragraphElement); - - // Schedule animations for words if enabled - if (animateWords && animationQueue) { - // Schedule animations for each word with a faster timing - const baseDelay = 0; // Starting delay - const wordDelay = 20; // Delay between words in ms (reduced from 40) - - wordElements.forEach((wordElement, index) => { - const delay = baseDelay + (index * wordDelay); - totalDelay = Math.max(totalDelay, delay); - - this.scheduleWordAnimation(wordElement, delay, animationSpeed); - }); - - // Schedule TTS if enabled - start it earlier in the animation sequence - if (tts) { - const ttsPlayer = this.getModule('tts-player'); - if (ttsPlayer) { - // Get the full text for TTS - const fullText = layout.originalText || layout.processedText || paragraphElement.textContent; - - // Schedule TTS with the animation queue - start after just a few words appear - animationQueue.schedule(() => { - ttsPlayer.speak(fullText, (result) => { - if (!result || !result.success) { - console.warn('TTS playback issue:', result ? result.reason : 'unknown'); - } - }); - }, Math.min(100, wordDelay * 3)); // Start TTS earlier + + const lineHeight = lineHeightPx || parseFloat(window.getComputedStyle(paragraph).lineHeight) || 24; + const maxLineWidth = Array.isArray(measures) && measures.length > 0 + ? Math.max(...measures) + : storyElement.clientWidth; + // Height should include all lines (breaks.length represents number of lines) + const numLines = breaks.length - 1; + paragraph.style.height = `${lineHeight * numLines}px`; + + console.log(`LayoutRenderer: Rendering paragraph ${id} - ${breaks.length} breaks (${numLines} lines), lineHeight: ${lineHeight}px, total height: ${lineHeight * numLines}px`); + + // Debug: log break ratios + breaks.forEach((brk, idx) => { + if (idx > 0) { + console.log(` Line ${idx - 1}: break position ${brk.position}, ratio ${brk.ratio ? brk.ratio.toFixed(3) : 'undefined'}`); + } + }); + + // Position words according to layout with proper justification + let wordCount = 0; + let lastChild = null; + let syllable = ""; + const stack = [paragraph]; + + if (layoutData.dropCap && layoutData.dropCapText) { + const dropCap = document.createElement('span'); + dropCap.className = 'drop-cap story-drop-cap'; + dropCap.textContent = layoutData.dropCapText; + paragraph.appendChild(dropCap); + } + + for (let i = 1; i < breaks.length; i++) { + const lineIndex = i - 1; + const lineWidth = measures[Math.min(lineIndex, measures.length - 1)]; + const lineOffset = maxLineWidth - lineWidth; + const currentBreak = breaks[i]; + const isFinalLine = i === breaks.length - 1; + const ratio = isFinalLine ? 0 : (currentBreak.ratio || 0); + + let currentLeft = 0; + lastChild = null; + + // Iterate through nodes on this line (break positions are inclusive) + for (let j = breaks[i-1].position; j <= currentBreak.position; j++) { + const node = nodes[j]; + + if (node.type === 'box' && node.value !== '' && j < currentBreak.position) { + const followsGlue = j > 0 && nodes[j - 1].type === 'glue'; + const isTrailingPunctuation = /^[,.;:!?)]$/.test(node.value) && !followsGlue; + + // Check if this box follows a penalty (hyphenation point) + if (lastChild && isTrailingPunctuation) { + syllable += node.value; + lastChild.innerHTML = syllable; + currentLeft += node.width; + } else if (j > breaks[i-1].position + 1 && + nodes[j-1].type === 'penalty' && + lastChild) { + // Combine with previous syllable using zero-width non-joiner + syllable += '\u200c' + node.value; + lastChild.innerHTML = syllable; + currentLeft += node.width; + } else { + // Create new word span + const word = document.createElement('span'); + word.className = 'word'; + word.style.position = 'absolute'; + word.style.display = 'inline-block'; + word.style.whiteSpace = 'nowrap'; + word.dataset.line = String(lineIndex); + word.dataset.lineStart = String(lineOffset); + word.dataset.lineWidth = String(lineWidth); + + // Calculate position with proper line and justification + const topPercent = (lineIndex * lineHeight * 100) / parseFloat(paragraph.style.height); + const leftPercent = ((lineOffset + currentLeft) * 100) / maxLineWidth; + + word.style.top = `${topPercent}%`; + word.style.left = `${leftPercent}%`; + word.style.opacity = '0'; // Hidden until animated + word.style.visibility = 'hidden'; + syllable = node.value; + word.innerHTML = syllable; + lastChild = word; + + if (wordCount < 5 || (wordCount % 20 === 0)) { + console.log(` Word ${wordCount} "${node.value}" at line ${lineIndex}, top: ${topPercent.toFixed(1)}%, left: ${leftPercent.toFixed(1)}%`); + } + wordCount++; + + stack[stack.length - 1].appendChild(word); + currentLeft += node.width; + } + + } else if (node.type === 'tag') { + if (node.value.substr(0, 2) === ' 1) stack.pop(); + } else { + const template = document.createElement('div'); + template.innerHTML = node.value; + const tag = template.firstChild; + if (tag) { + tag.style.display = 'contents'; + stack[stack.length - 1].appendChild(tag); + stack.push(tag); + } + } + + } else if (node.type === 'glue' && j > breaks[i-1].position && node.width !== 0 && j <= currentBreak.position) { + // Apply justification: adjust glue width based on line's ratio + let adjustedWidth = node.width; + + if (ratio > 0) { + // Line needs stretching + adjustedWidth = node.width + (node.stretch * ratio); + } else if (ratio < 0) { + // Line needs shrinking + adjustedWidth = node.width + (node.shrink * ratio); + } + // If ratio === 0, line fits perfectly, use natural width + + if (wordCount < 3) { + // Debug first line's glue adjustments + console.log(` Glue at position ${j}: natural=${node.width.toFixed(2)}px, adjusted=${adjustedWidth.toFixed(2)}px, ratio=${ratio.toFixed(3)}, left before: ${currentLeft.toFixed(2)}px`); + } + + // Increment position by the adjusted glue width + currentLeft += adjustedWidth; + + } else if (node.type === 'penalty' && node.penalty === 100 && j === currentBreak.position) { + // Add hyphen at line break + if (lastChild) { + lastChild.innerHTML = `${lastChild.innerHTML}-`; + continue; + } + + const word = document.createElement('span'); + word.className = 'word'; + word.style.position = 'absolute'; + word.style.display = 'inline-block'; + word.style.whiteSpace = 'nowrap'; + word.dataset.line = String(lineIndex); + word.dataset.lineStart = String(lineOffset); + word.dataset.lineWidth = String(lineWidth); + const topPercent = (lineIndex * lineHeight * 100) / parseFloat(paragraph.style.height); + const leftPercent = ((lineOffset + currentLeft) * 100) / maxLineWidth; + word.style.top = `${topPercent}%`; + word.style.left = `${leftPercent}%`; + word.style.opacity = '0'; + word.style.visibility = 'hidden'; + word.innerHTML = "-"; + stack[stack.length - 1].appendChild(word); } } - - // Schedule completion callback - if (onComplete && typeof onComplete === 'function') { - const completionDelay = totalDelay + 200; // Reduced completion delay - animationQueue.schedule(onComplete, completionDelay); - } - } else if (onComplete && typeof onComplete === 'function') { - // If not animating, call onComplete immediately - setTimeout(onComplete, 0); } - - return paragraphElement; + + return paragraph; + } + + /** + * Paragraph positions are already computed from browser DOM measurements. + * Keep this hook for callers that still invoke it, but do not reflow the + * prototype layout after rendering. + * @param {HTMLElement} paragraph - Rendered paragraph element + */ + adjustJustification(paragraph) { + return paragraph; } - /** - * Render a single word - * @param {string} word - Word to render - * @param {boolean} animate - Whether to prepare for animation - * @returns {HTMLElement} - The created word element - */ - renderWord(word, animate = true) { - const wordElement = this.createWordElement(word); - - // Apply initial styles for animation - if (animate) { - wordElement.style.opacity = '0'; - wordElement.style.transform = 'translateY(5px)'; - wordElement.style.display = 'inline-block'; - } - - return wordElement; - } - - /** - * Create a word element - * @param {string} word - Word to render - * @returns {HTMLElement} - The created word element - */ - createWordElement(word) { - const wordElement = document.createElement('span'); - wordElement.className = 'word'; - wordElement.textContent = word; - return wordElement; - } - - /** - * Schedule a word animation with the animation queue - * @param {HTMLElement} wordElement - Word element to animate - * @param {number} delay - Delay before animation starts - * @param {number} speed - Animation speed factor - */ - scheduleWordAnimation(wordElement, delay, speed) { - const animationQueue = this.getModule('animation-queue'); - if (!animationQueue) return; - - const actualDelay = delay * speed; - - animationQueue.schedule(() => { - wordElement.style.opacity = '1'; - wordElement.style.transform = 'translateY(0)'; - wordElement.style.transition = `opacity 0.2s ease-out, transform 0.3s ease-out`; - }, actualDelay); - } } // Create the singleton instance @@ -265,3 +270,11 @@ const LayoutRenderer = new LayoutRendererModule(); // Export the module export { LayoutRenderer }; + +// Register with the module registry +if (window.moduleRegistry) { + window.moduleRegistry.register(LayoutRenderer); +} + +// Keep a reference in window for loader system +window.LayoutRenderer = LayoutRenderer; diff --git a/public/js/loader.js b/public/js/loader.js index 086cdda..1707102 100644 --- a/public/js/loader.js +++ b/public/js/loader.js @@ -24,6 +24,8 @@ const ModuleState = { ERROR: 'ERROR' }; +const MODULE_CACHE_BUSTER = '20260514-new-game-click'; + /** * Module Loader - Manages the loading of all modules */ @@ -61,7 +63,10 @@ const ModuleLoader = (function() { // Load available module scripts loadModuleScripts().then(() => { // Once scripts are loaded, initialize modules - initializeModules(); + initializeModules().catch(error => { + console.error('Module Loader: Initialization failed:', error); + finalizeLoading(); + }); }); } @@ -98,17 +103,19 @@ const ModuleLoader = (function() { { id: 'persistence-manager', script: '/js/persistence-manager-module.js', weight: 12 }, { id: 'localization', script: '/js/localization-module.js', weight: 12 }, { id: 'text-processor', script: '/js/text-processor-module.js', weight: 15 }, + { id: 'markup-parser', script: '/js/markup-parser-module.js', weight: 5 }, { id: 'paragraph-layout', script: '/js/paragraph-layout-module.js', weight: 17 }, { id: 'sentence-queue', script: '/js/sentence-queue-module.js', weight: 12 }, { id: 'layout-renderer', script: '/js/layout-renderer-module.js', weight: 13 }, // Add Layout Renderer module { id: 'animation-queue', script: '/js/animation-queue-module.js', weight: 12 }, - + { id: 'playback-coordinator', script: '/js/playback-coordinator-module.js', weight: 8 }, // Synchronizes animation + TTS + // Audio and TTS modules { id: 'audio-manager', script: '/js/audio-manager-module.js', weight: 12 }, - { id: 'kokoro', script: '/js/kokoro-tts-module.js', weight: 50 }, - { id: 'browser', script: '/js/browser-tts-module.js', weight: 12 }, - { id: 'elevenlabs', script: '/js/elevenlabs-tts-module.js', weight: 12 }, - { id: 'openai', script: '/js/openai-tts-module.js', weight: 12 }, + { id: 'kokoro-tts', script: '/js/kokoro-tts-module.js', weight: 50 }, + { id: 'browser-tts', script: '/js/browser-tts-module.js', weight: 12 }, + { id: 'elevenlabs-tts', script: '/js/elevenlabs-tts-module.js', weight: 12 }, + { id: 'openai-tts', script: '/js/openai-tts-module.js', weight: 12 }, { id: 'tts-factory', script: '/js/tts-factory-module.js', weight: 13 }, // TTSFactory must be loaded before TTSPlayer // UI and interaction modules @@ -310,7 +317,7 @@ const ModuleLoader = (function() { } }); - return result.reverse(); // Reverse to get correct order + return result; // Dependencies are pushed before dependents. }; const optimalOrder = calculateOptimalLoadOrder(); @@ -404,7 +411,7 @@ const ModuleLoader = (function() { } }); - return result.reverse(); // Reverse for correct dependency order + return result; // Dependencies are pushed before dependents. } /** @@ -442,7 +449,8 @@ const ModuleLoader = (function() { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.type = 'module'; - script.src = src; + const separator = src.includes('?') ? '&' : '?'; + script.src = `${src}${separator}v=${MODULE_CACHE_BUSTER}`; // Monitor loading progress using a fake progress indicator (0-10%) if (moduleId && moduleWeights[moduleId]) { @@ -492,7 +500,7 @@ const ModuleLoader = (function() { /** * Initialize all registered modules */ - function initializeModules() { + async function initializeModules() { const modules = moduleRegistry.getAllModules(); // Find the game loop module instance @@ -505,8 +513,19 @@ const ModuleLoader = (function() { console.log(`${moduleId} depends on: ${dependencies.length ? dependencies.join(', ') : 'none'}`); }); - // For each registered module, start initialization - Object.values(modules).forEach(async (module) => { + const moduleList = Object.values(modules); + const initializationOrder = sortModulesByDependencies(moduleList); + + console.group('%cActual Module Initialization Order', 'color: green; font-weight: bold'); + initializationOrder.forEach((module, index) => { + console.log(`${index + 1}. ${module.id} (${module.name})`); + }); + console.groupEnd(); + + // Initialize in dependency order. This makes the loader guarantee that + // by the time the overlay disappears, every module has run its own + // initialize() after its declared dependencies are available. + for (const module of initializationOrder) { try { // Create a progress callback for this module const progressCallback = (percent, message) => { @@ -539,7 +558,13 @@ const ModuleLoader = (function() { } catch (error) { console.error(`Error initializing module ${module.id}:`, error); } - }); + + if (module.id === 'game-loop') { + gameLoopModule = module; + } + } + + checkAllFinished(); } /** diff --git a/public/js/localization-module.js b/public/js/localization-module.js index 3035f24..6cf1284 100644 --- a/public/js/localization-module.js +++ b/public/js/localization-module.js @@ -147,6 +147,7 @@ class LocalizationModule extends BaseModule { const persistenceManager = this.getModule('persistence-manager'); if (persistenceManager) { persistenceManager.updatePreference('app', 'locale', normalizedLocale); + persistenceManager.updatePreference('tts', 'language', normalizedLocale); } // Dispatch locale change event diff --git a/public/js/markup-parser-module.js b/public/js/markup-parser-module.js new file mode 100644 index 0000000..cbb920a --- /dev/null +++ b/public/js/markup-parser-module.js @@ -0,0 +1,274 @@ +/** + * Markup Parser Module + * Parses author-facing story markup into renderable blocks and timed cue metadata. + */ +import { BaseModule } from './base-module.js'; + +class MarkupParserModule extends BaseModule { + constructor() { + super('markup-parser', 'Markup Parser'); + this.dependencies = []; + this.assetRoots = { + images: '/images/', + music: '/music/', + sounds: '/sounds/' + }; + + this.bindMethods([ + 'parse', + 'parseParagraph', + 'parseInline', + 'parseMusicOptions', + 'markdownToHtml', + 'smartypants', + 'escapeHtml', + 'normalizeParagraph', + 'buildParagraphBlock', + 'resolveAssetUrl' + ]); + } + + async initialize() { + this.reportProgress(100, "Markup parser ready"); + return true; + } + + parse(input) { + const text = String(input || '').replace(/\r\n?/g, '\n'); + const blocks = []; + let paragraphBuffer = []; + let nextParagraphRole = null; + + const flushParagraph = () => { + if (paragraphBuffer.length === 0) return; + + const raw = paragraphBuffer.join('\n'); + paragraphBuffer = []; + const paragraph = this.parseParagraph(raw); + if (!paragraph.text) return; + + const role = nextParagraphRole || 'body'; + nextParagraphRole = null; + blocks.push(this.buildParagraphBlock(paragraph, role)); + }; + + text.split('\n').forEach((line) => { + const trimmed = line.trim(); + + if (!trimmed) { + flushParagraph(); + return; + } + + const chapter = trimmed.match(/^::chapter(?:\[(.*?)\]|\s+(.+))$/i); + if (chapter) { + flushParagraph(); + const heading = (chapter[1] || chapter[2] || '').trim(); + if (heading) { + blocks.push({ + type: 'heading', + text: this.normalizeParagraph(heading), + layoutText: this.markdownToHtml(this.normalizeParagraph(heading)), + role: 'chapter-heading' + }); + } + nextParagraphRole = 'chapter-first'; + return; + } + + const section = trimmed.match(/^::(?:section|textblock)(?:\[(.*?)\]|\s+(.+))?$/i); + if (section) { + flushParagraph(); + const heading = (section[1] || section[2] || '').trim(); + if (heading) { + blocks.push({ + type: 'heading', + text: this.normalizeParagraph(heading), + layoutText: this.markdownToHtml(this.normalizeParagraph(heading)), + role: 'section-heading' + }); + } + nextParagraphRole = 'textblock-first'; + return; + } + + const image = trimmed.match(/^::image\[(widescreen|portrait)\]\(([^)]+)\)$/i); + if (image) { + flushParagraph(); + blocks.push({ + type: 'image', + size: image[1].toLowerCase(), + filename: image[2].trim(), + url: this.resolveAssetUrl('images', image[2].trim()) + }); + return; + } + + const music = trimmed.match(/^::music(?:\[([^\]]*)\])?\(([^)]+)\)$/i); + if (music) { + flushParagraph(); + const options = this.parseMusicOptions(music[1] || 'crossfade'); + blocks.push({ + type: 'music', + ...options, + filename: music[2].trim(), + url: this.resolveAssetUrl('music', music[2].trim()) + }); + return; + } + + paragraphBuffer.push(line); + }); + + flushParagraph(); + + return blocks; + } + + parseMusicOptions(optionText) { + const options = { + mode: 'crossfade', + loop: true, + leadInSeconds: 0 + }; + + String(optionText || '') + .split(/[,\s]+/) + .map(token => token.trim()) + .filter(Boolean) + .forEach(token => { + const lower = token.toLowerCase(); + const [key, value] = lower.split('='); + + if (['queue', 'crossfade', 'cut'].includes(lower)) { + options.mode = lower; + } else if (['loop', 'looped', 'repeat'].includes(lower)) { + options.loop = true; + } else if (['once', 'single', 'no-loop', 'noloop'].includes(lower)) { + options.loop = false; + } else if (key === 'loop') { + options.loop = !['false', '0', 'no', 'once'].includes(value); + } else if (['lead', 'lead-in', 'leadins', 'lead-in-seconds', 'delay', 'intro'].includes(key)) { + const seconds = Number(value); + options.leadInSeconds = Number.isFinite(seconds) ? Math.max(0, seconds) : 0; + } else if (/^\d+(\.\d+)?s?$/.test(lower)) { + options.leadInSeconds = Number(lower.replace(/s$/, '')); + } + }); + + return options; + } + + parseParagraph(rawText) { + const inline = this.parseInline(this.normalizeParagraph(rawText)); + return { + text: inline.text, + layoutText: this.markdownToHtml(inline.text), + cueMarkers: inline.cueMarkers + }; + } + + buildParagraphBlock(paragraph, role) { + return { + type: 'paragraph', + text: paragraph.text, + layoutText: paragraph.layoutText, + cueMarkers: paragraph.cueMarkers, + role, + isFirstParagraphInChapter: role === 'chapter-first' || role === 'textblock-first', + dropCap: role === 'chapter-first', + addTopSpace: role === 'textblock-first' + }; + } + + parseInline(text) { + const cueMarkers = []; + let output = ''; + let cursor = 0; + const markerPattern = /\{\{\s*(sfx|music)\s*:\s*(?:(queue|crossfade|cut)\s*:\s*)?([^}]+?)\s*\}\}/gi; + + for (const match of text.matchAll(markerPattern)) { + output += text.slice(cursor, match.index); + const charIndex = output.length; + const wordIndex = this.countWords(output); + const type = match[1].toLowerCase(); + const mode = type === 'music' ? (match[2] || 'crossfade').toLowerCase() : null; + + cueMarkers.push({ + type, + mode, + filename: match[3].trim(), + url: this.resolveAssetUrl(type === 'sfx' ? 'sounds' : 'music', match[3].trim()), + charIndex, + wordIndex + }); + + cursor = match.index + match[0].length; + } + + output += text.slice(cursor); + + return { + text: output.replace(/\s{2,}/g, ' ').trim(), + cueMarkers + }; + } + + markdownToHtml(text) { + const escaped = this.smartypants(this.escapeHtml(text)); + + return escaped + .replace(/\*\*\*([^*]+?)\*\*\*/g, '$1') + .replace(/___([^_]+?)___/g, '$1') + .replace(/\*\*([^*]+?)\*\*/g, '$1') + .replace(/__([^_]+?)__/g, '$1') + .replace(/\*([^*\s][^*]*?)\*/g, '$1') + .replace(/_([^_\s][^_]*?)_/g, '$1'); + } + + smartypants(text) { + return String(text) + .replace(/---/g, '\u2014') + .replace(/--/g, '\u2013') + .replace(/\.\.\./g, '\u2026') + .replace(/(^|[\s([{\u2014])"([^"]*)"/g, '$1\u201c$2\u201d') + .replace(/(^|[\s([{\u2014])'([^']*)'/g, '$1\u2018$2\u2019'); + } + + escapeHtml(text) { + return String(text) + .replace(/&/g, '&') + .replace(//g, '>'); + } + + normalizeParagraph(text) { + return String(text).replace(/\s*\n\s*/g, ' ').trim(); + } + + countWords(text) { + const words = String(text).trim().match(/\S+/g); + return words ? words.length : 0; + } + + resolveAssetUrl(kind, filename) { + const root = this.assetRoots[kind]; + const safeName = String(filename || '').replace(/\\/g, '/').replace(/^\/+/, ''); + + if (!root || !safeName || safeName.includes('..') || /^[a-z]+:/i.test(safeName)) { + return ''; + } + + return root + safeName.split('/').map(encodeURIComponent).join('/'); + } +} + +const MarkupParser = new MarkupParserModule(); + +export { MarkupParser }; + +if (window.moduleRegistry) { + window.moduleRegistry.register(MarkupParser); +} + +window.MarkupParser = MarkupParser; diff --git a/public/js/openai-tts-module.js b/public/js/openai-tts-module.js index 6ba2a25..0ed4491 100644 --- a/public/js/openai-tts-module.js +++ b/public/js/openai-tts-module.js @@ -7,6 +7,18 @@ import { ApiTTSModuleBase } from './api-tts-module-base.js'; export class OpenAITTSModule extends ApiTTSModuleBase { constructor() { super('openai-tts', 'OpenAI TTS'); + + this.supportedVoices = [ + { id: 'alloy', name: 'Alloy', language: 'en' }, + { id: 'ash', name: 'Ash', language: 'en' }, + { id: 'coral', name: 'Coral', language: 'en' }, + { id: 'echo', name: 'Echo', language: 'en' }, + { id: 'fable', name: 'Fable', language: 'en' }, + { id: 'nova', name: 'Nova', language: 'en' }, + { id: 'onyx', name: 'Onyx', language: 'en' }, + { id: 'sage', name: 'Sage', language: 'en' }, + { id: 'shimmer', name: 'Shimmer', language: 'en' } + ]; // Voice options specific to OpenAI this.voiceOptions = { @@ -16,20 +28,8 @@ export class OpenAITTSModule extends ApiTTSModuleBase { response_format: 'mp3' // OpenAI supports mp3, opus, aac, and flac (not wav) }; - // Predefined voices - OpenAI has a fixed set - this.voices = [ - { id: 'alloy', name: 'Alloy', language: 'en' }, - { id: 'ash', name: 'Ash', language: 'en' }, - { id: 'ballad', name: 'Ballad', language: 'en' }, - { id: 'coral', name: 'Coral', language: 'en' }, - { id: 'echo', name: 'Echo', language: 'en' }, - { id: 'fable', name: 'Fable', language: 'en' }, - { id: 'onyx', name: 'Onyx', language: 'en' }, - { id: 'nova', name: 'Nova', language: 'en' }, - { id: 'sage', name: 'Sage', language: 'en' }, - { id: 'shimmer', name: 'Shimmer', language: 'en' }, - { id: 'verse', name: 'Verse', language: 'en' } - ]; + // OpenAI has a documented fixed voice set for this speech endpoint. + this.voices = [...this.supportedVoices]; } /** @@ -65,14 +65,16 @@ export class OpenAITTSModule extends ApiTTSModuleBase { // API key is already loaded in parent initialize() method // Just check if it's available if (!this.apiKey) { - console.error('OpenAI TTS: API key not configured'); - return false; + console.info('OpenAI TTS: API key not configured; provider unavailable until configured'); + this.isReady = false; + this.reportProgress(100, 'OpenAI TTS not configured'); + return true; } // Load preferences const preferredVoice = persistenceManager.getPreference('tts', `${this.id}_voice`, this.voiceOptions.voice); if (preferredVoice) { - this.voiceOptions.voice = preferredVoice; + this.voiceOptions.voice = this.normalizeVoiceId(preferredVoice); } const preferredModel = persistenceManager.getPreference('tts', `${this.id}_model`, this.voiceOptions.model); @@ -80,13 +82,17 @@ export class OpenAITTSModule extends ApiTTSModuleBase { this.voiceOptions.model = preferredModel; } - const preferredSpeed = persistenceManager.getPreference('tts', `${this.id}_speed`, this.voiceOptions.speed); + const preferredSpeed = persistenceManager.getPreference('tts', 'speed', this.voiceOptions.speed); if (typeof preferredSpeed === 'number') { - this.voiceOptions.speed = preferredSpeed; + this.voiceOptions.speed = this.getApiSpeed(preferredSpeed); } - // Setup available voices - this.voices = this.getAvailableVoices(); + const apiReachable = await this.loadVoices(); + if (!apiReachable) { + this.isReady = false; + this.reportProgress(100, 'OpenAI TTS not ready'); + return true; + } this.isReady = true; this.reportProgress(100, 'OpenAI TTS initialized'); @@ -103,8 +109,31 @@ export class OpenAITTSModule extends ApiTTSModuleBase { * @returns {Promise} - Resolves with success status */ async loadVoices() { - // OpenAI has a fixed set of voices, no need to fetch them - return true; + // OpenAI exposes a documented fixed TTS voice set, not a voice-list + // endpoint. Use /models as a lightweight credential/endpoint check. + this.voices = this.getAvailableVoices(); + if (!this.apiKey) { + return true; + } + + try { + const response = await fetch(`${this.apiBaseUrl}/models`, { + method: 'GET', + headers: { + 'Authorization': `Bearer ${this.apiKey}` + } + }); + + if (!response.ok) { + console.error(`OpenAI TTS: API validation failed ${response.status} ${response.statusText}`); + return false; + } + + return true; + } catch (error) { + console.error('OpenAI TTS: API validation error:', error); + return false; + } } /** @@ -135,6 +164,7 @@ export class OpenAITTSModule extends ApiTTSModuleBase { * @returns {Array} - Array of voice objects */ getAvailableVoices() { + this.voices = [...this.supportedVoices]; return this.voices; } @@ -156,9 +186,9 @@ export class OpenAITTSModule extends ApiTTSModuleBase { const payload = { model: this.voiceOptions.model || 'tts-1', input: processedText, - voice: this.voiceOptions.voice || 'alloy', + voice: this.normalizeVoiceId(this.voiceOptions.voice), response_format: this.voiceOptions.response_format || 'mp3', - speed: this.voiceOptions.speed || 1.0 + speed: this.getApiSpeed(this.voiceOptions.speed) }; // Make API request @@ -203,24 +233,19 @@ export class OpenAITTSModule extends ApiTTSModuleBase { setVoiceOptions(options = {}) { // Handle common options if (options.voice) { - this.voiceOptions.voice = options.voice; + this.voiceOptions.voice = this.normalizeVoiceId(options.voice); // Save voice preference const persistenceManager = this.getModule('persistence-manager'); if (persistenceManager) { - persistenceManager.updatePreference('tts', `${this.id}_voice`, options.voice); + persistenceManager.updatePreference('tts', `${this.id}_voice`, this.voiceOptions.voice); } } if (typeof options.speed === 'number') { - // OpenAI API supports speed values from 0.25 to 4.0 with 1 as default - if (options.speed <= 0.5) { - // Map [0, 0.5] -> [0.25, 1] - this.voiceOptions.speed = 0.25 + (1 - 0.25) * (options.speed / 0.5); - } else { - // Map [0.5, 1] -> [1, 4] - this.voiceOptions.speed = 1 + (4 - 1) * ((options.speed - 0.5) / 0.5); - } + // OpenAI speech speed uses 1.0 as normal. The app-wide slider also + // uses 1.0 as normal, so only clamp at the provider API boundary. + this.voiceOptions.speed = this.getApiSpeed(options.speed); } // Handle OpenAI-specific options @@ -248,8 +273,34 @@ export class OpenAITTSModule extends ApiTTSModuleBase { } } } + + getVoiceId(voice) { + if (!voice) return ''; + if (typeof voice === 'string') return voice; + return voice.id || voice.name || ''; + } + + normalizeVoiceId(voice) { + const voiceId = this.getVoiceId(voice).toLowerCase(); + const supported = new Set(this.supportedVoices.map(item => item.id)); + + if (supported.has(voiceId)) { + return voiceId; + } + + if (voiceId) { + console.warn(`OpenAI TTS: Unsupported voice "${voiceId}", falling back to alloy`); + } + + return 'alloy'; + } + + getApiSpeed(speed) { + const value = Number.isFinite(speed) ? speed : 1.0; + return Math.max(0.25, Math.min(4.0, value)); + } } const openAITTSModule = new OpenAITTSModule(); -export { openAITTSModule }; \ No newline at end of file +export { openAITTSModule }; diff --git a/public/js/options-ui-module.js b/public/js/options-ui-module.js index 599904a..0d3164e 100644 --- a/public/js/options-ui-module.js +++ b/public/js/options-ui-module.js @@ -45,7 +45,8 @@ class OptionsUIModule extends BaseModule { 'setupInitialState', 'dispatchApiChangeEvent', 'getPreference', - 'updatePreference' + 'updatePreference', + 'renderProviderStatuses' ]); } @@ -183,20 +184,21 @@ class OptionsUIModule extends BaseModule { const speedValue = document.createElement('span'); speedValue.className = 'slider-value'; speedValue.textContent = '100%'; + this.elements.ttsSpeedValue = speedValue; speedContainer.appendChild(speedValue); this.elements.ttsSpeed = createUIElement('input', { type: 'range', min: 50, - max: 200, + max: 150, value: 100, - 'data-pref-bind': 'app.speed', - 'data-pref-transform': 'range:0.5,2.0' + 'data-pref-bind': 'tts.speed', + 'data-pref-transform': 'centered-speed' }, null, speedContainer); // Update displayed value when slider changes this.elements.ttsSpeed.addEventListener('input', () => { - speedValue.textContent = `${this.elements.ttsSpeed.value}%`; + this.updateSpeedDisplay(); }); appSettingsSection.appendChild(speedContainer); @@ -239,6 +241,11 @@ class OptionsUIModule extends BaseModule { }, null, ttsSystemContainer); ttsSection.appendChild(ttsSystemContainer); + + const providerStatusContainer = document.createElement('div'); + providerStatusContainer.className = 'provider-status-list'; + this.elements.providerStatus = providerStatusContainer; + ttsSection.appendChild(providerStatusContainer); // TTS Voice const ttsVoiceContainer = document.createElement('div'); @@ -510,7 +517,12 @@ class OptionsUIModule extends BaseModule { if (this.elements.ttsSystem) { this.elements.ttsSystem.addEventListener('change', async (event) => { this.updateApiSettingsVisibility(event.target.value); + const ttsFactory = this.getModule('tts-factory'); + if (ttsFactory) { + await ttsFactory.refreshHandlerStatus(event.target.value); + } await this.populateVoices(); + this.renderProviderStatuses(); }); } @@ -595,6 +607,7 @@ class OptionsUIModule extends BaseModule { // Update API settings visibility this.updateApiSettingsVisibility(this.elements.ttsSystem.value); + this.renderProviderStatuses(); } /** @@ -604,8 +617,10 @@ class OptionsUIModule extends BaseModule { const ttsFactory = this.getModule('tts-factory'); if (!ttsFactory || !this.elements.ttsVoice) return; - // Get voices for current TTS system - const voices = await ttsFactory.getVoices() || []; + const selectedHandler = this.elements.ttsSystem?.value || this.getPreference('tts', 'preferred_handler', 'none'); + const voices = typeof ttsFactory.getVoicesForHandler === 'function' + ? await ttsFactory.getVoicesForHandler(selectedHandler) || [] + : await ttsFactory.getVoices() || []; console.log('Options UI: TTS voices:', voices); // Populate dropdown @@ -614,9 +629,35 @@ class OptionsUIModule extends BaseModule { voices, 'id', 'name', - this.getPreference('tts', 'voice', '') + this.getPreference('tts', `${selectedHandler}_voice`, this.getPreference('tts', 'voice', '')) ); } + + renderProviderStatuses() { + const container = this.elements.providerStatus; + const ttsFactory = this.getModule('tts-factory'); + if (!container || !ttsFactory || typeof ttsFactory.getHandlerStatuses !== 'function') { + return; + } + + container.innerHTML = ''; + const statuses = ttsFactory.getHandlerStatuses(); + statuses.forEach(status => { + const row = document.createElement('div'); + row.className = 'provider-status-row'; + + const name = document.createElement('span'); + name.textContent = status.name; + row.appendChild(name); + + const value = document.createElement('span'); + value.className = 'provider-status-value'; + value.textContent = `${status.ready ? 'ready' : 'not ready'} - ${status.message}`; + row.appendChild(value); + + container.appendChild(row); + }); + } /** * Populate the languages dropdown @@ -737,6 +778,7 @@ class OptionsUIModule extends BaseModule { document.addEventListener('tts:voices:updated', () => { console.log('Options UI: Received tts:voices:updated event, updating voice dropdown'); this.populateVoices(); + this.renderProviderStatuses(); }); // Set up language change listener @@ -750,6 +792,36 @@ class OptionsUIModule extends BaseModule { console.log('Options UI: Received TTS engine change event:', event.detail); await this.populateVoices(); this.updateApiSettingsVisibility(this.elements.ttsSystem.value); + this.renderProviderStatuses(); + }); + + document.addEventListener('tts:status:updated', () => { + this.renderProviderStatuses(); + }); + + document.addEventListener('tts:enabled:change', async (event) => { + if (!event.detail || typeof event.detail.enabled !== 'boolean') { + return; + } + + if (this.elements.ttsEnabled) { + this.elements.ttsEnabled.checked = event.detail.enabled; + } + + const ttsFactory = this.getModule('tts-factory'); + if (!ttsFactory) { + return; + } + + if (event.detail.enabled) { + const preferredHandler = this.getPreference('tts', 'preferred_handler', 'none'); + if (preferredHandler !== 'none') { + await ttsFactory.setActiveHandler(preferredHandler); + } + } else { + await ttsFactory.disableAfterCurrentPlayback(); + } + this.renderProviderStatuses(); }); } @@ -766,6 +838,7 @@ class OptionsUIModule extends BaseModule { // Setup all bindings in the modal this.bindings = persistenceManager.setupBindings('#options-modal'); console.log('Options UI: Preference bindings set up', this.bindings.length); + this.updateSpeedDisplay(); // Add event listeners for side effects when preferences change document.addEventListener('preference-updated', (event) => { @@ -793,16 +866,46 @@ class OptionsUIModule extends BaseModule { if (!ttsFactory) return; if (key === 'preferred_handler') { - this.populateVoices(); + const enabled = this.getPreference('tts', 'enabled', false); + const activation = enabled && value !== 'none' + ? ttsFactory.setActiveHandler(value) + : Promise.resolve(ttsFactory.disableAfterCurrentPlayback()); + activation.then(() => { + this.populateVoices(); + this.renderProviderStatuses(); + }); this.updateApiSettingsVisibility(value); } else if (key === 'voice') { ttsFactory.configure({ voice: value }); } else if (key === 'speed') { ttsFactory.configure({ speed: value }); + } else if (key === 'language') { + ttsFactory.configure({ language: value }); } else if (key === 'enabled') { - ttsFactory.configure({ enabled: value }); - } + if (!value) { + ttsFactory.disableAfterCurrentPlayback(); + } else { + const preferredHandler = this.getPreference('tts', 'preferred_handler', 'none'); + if (preferredHandler !== 'none') { + ttsFactory.setActiveHandler(preferredHandler); + } + } + document.dispatchEvent(new CustomEvent('tts:enabled:change', { + detail: { enabled: value } + })); + } else if (key.endsWith('_api_key')) { + const provider = key.replace('_api_key', ''); + this.dispatchApiChangeEvent('api:keyChanged', provider, 'key', value); + ttsFactory.refreshHandlerStatus(provider).then(() => this.renderProviderStatuses()); + } else if (key.endsWith('_api_url')) { + const provider = key.replace('_api_url', ''); + this.dispatchApiChangeEvent('api:urlChanged', provider, 'url', value); + ttsFactory.refreshHandlerStatus(provider).then(() => this.renderProviderStatuses()); } + if (key === 'speed' && this.elements.ttsSpeed) { + this.updateSpeedDisplay(); + } + } // Handle locale changes if (category === 'app' && key === 'locale') { @@ -810,16 +913,26 @@ class OptionsUIModule extends BaseModule { if (localization) { localization.setLocale(value); } + const ttsFactory = this.getModule('tts-factory'); + if (ttsFactory) { + ttsFactory.configure({ language: value }); + } + this.updatePreference('tts', 'language', value); } }); } + + updateSpeedDisplay() { + if (!this.elements.ttsSpeed || !this.elements.ttsSpeedValue) { + return; + } + + this.elements.ttsSpeedValue.textContent = `${this.elements.ttsSpeed.value}%`; + } } // Create the singleton instance const OptionsUI = new OptionsUIModule(); -// Register with the module registry -moduleRegistry.register(OptionsUI); - // Export the module export { OptionsUI }; diff --git a/public/js/paragraph-layout-module.js b/public/js/paragraph-layout-module.js index b7238a8..62deec7 100644 --- a/public/js/paragraph-layout-module.js +++ b/public/js/paragraph-layout-module.js @@ -8,14 +8,12 @@ import { BaseModule } from './base-module.js'; class ParagraphLayoutModule extends BaseModule { constructor() { super('paragraph-layout', 'Paragraph Layout'); - - // Module dependencies + this.dependencies = ['text-processor']; - - // Caching canvas context for text measurements - this.textMeasureCtx = null; - - // Configuration - use parent's config system + + this.ruler = null; + this.rulerStack = []; + this.updateConfig({ maxLineWidth: 600, hyphenationEnabled: true, @@ -24,8 +22,7 @@ class ParagraphLayoutModule extends BaseModule { defaultLineHeight: 1.5, debugMode: false }); - - // Bind methods using parent's bindMethods utility + this.bindMethods([ 'calculateLayout', 'measureText', @@ -37,27 +34,20 @@ class ParagraphLayoutModule extends BaseModule { 'loadLayoutDependencies' ]); } - + async initialize() { try { this.reportProgress(20, "Initializing paragraph layout"); - - // Get text processor using parent's getModule method + const textProcessor = this.getModule('text-processor'); - if (!textProcessor) { - console.warn("Paragraph Layout: Text Processor not found, will use fallback processing"); + console.warn("Paragraph Layout: Text Processor not found, will use unprocessed text"); } - - // Load required dependencies + await this.loadLayoutDependencies(); - - // Create off-screen canvas for text measurements this.initializeTextMeasurement(); - - // Set up event listeners for config changes this.setupEventListeners(); - + this.reportProgress(100, "Paragraph layout ready"); return true; } catch (error) { @@ -65,23 +55,15 @@ class ParagraphLayoutModule extends BaseModule { return false; } } - - /** - * Load required dependencies for layout calculations - */ + async loadLayoutDependencies() { try { this.reportProgress(30, "Loading layout dependencies"); - - // Load LinkedList.js first as it's required by linebreak.js + await this.loadScript('/js/linked-list.js'); - - // Load linebreak.js which is required by knuth-and-plass.js await this.loadScript('/js/linebreak.js'); - - // Load knuth-and-plass.js which contains the kap function await this.loadScript('/js/knuth-and-plass.js'); - + this.reportProgress(50, "Layout dependencies loaded"); return true; } catch (error) { @@ -89,148 +71,163 @@ class ParagraphLayoutModule extends BaseModule { return false; } } - - /** - * Initialize text measurement canvas - */ + initializeTextMeasurement() { - // Create off-screen canvas for text measurements - const canvas = document.createElement('canvas'); - canvas.width = 2000; - canvas.height = 100; - this.textMeasureCtx = canvas.getContext('2d'); - - // Set default font + let ruler = document.getElementById('ruler'); + + if (!ruler) { + ruler = document.createElement('span'); + ruler.id = 'ruler'; + document.body.appendChild(ruler); + } + + Object.assign(ruler.style, { + visibility: 'hidden', + position: 'absolute', + top: '-8000px', + left: '-8000px', + width: 'auto', + display: 'inline', + textIndent: '0', + textAlign: 'left', + hyphens: 'none', + marginBlockEnd: '0' + }); + + this.ruler = ruler; + this.rulerStack = [ruler]; this.updateFont(this.config.defaultFontSize, this.config.defaultFontFamily); } - + setupEventListeners() { - // Use parent's addEventListener for automatic cleanup this.addEventListener(document, 'ui:font:change', (event) => { if (event.detail) { const { fontSize, fontFamily } = event.detail; if (fontSize || fontFamily) { this.updateFont( - fontSize || this.config.defaultFontSize, + fontSize || this.config.defaultFontSize, fontFamily || this.config.defaultFontFamily ); } } }); - - // Listen for config changes + this.addEventListener(document, 'ui:hyphenation:toggle', (event) => { if (event.detail && typeof event.detail.enabled === 'boolean') { this.updateConfig({ hyphenationEnabled: event.detail.enabled }); } }); } - - /** - * Update the font for text measurements - * @param {string} fontSize - Font size (with units) - * @param {string} fontFamily - Font family - */ + updateFont(fontSize, fontFamily) { - if (!this.textMeasureCtx) { - console.warn("Text measurement context not initialized"); + if (!this.ruler) { + console.warn("Text measurement ruler not initialized"); return; } - - // Update config if values are provided + if (fontSize) this.updateConfig({ defaultFontSize: fontSize }); if (fontFamily) this.updateConfig({ defaultFontFamily: fontFamily }); - - // Set font on measurement context - this.textMeasureCtx.font = `${fontSize} ${fontFamily}`; - + + this.ruler.style.fontSize = fontSize; + this.ruler.style.fontFamily = fontFamily; + this.ruler.style.fontFeatureSettings = "'kern' on, 'liga' on, 'onum' on, 'clig' on, 'hlig' on"; + if (this.config.debugMode) { console.log(`Font updated: ${fontSize} ${fontFamily}`); } } - - /** - * Measure text width using canvas context - * @param {string} text - Text to measure - * @returns {number} - Text width in pixels - */ + measureText(text) { - if (!this.textMeasureCtx) return 0; + if (!this.ruler) return 0; if (!text) return 0; - - const metrics = this.textMeasureCtx.measureText(text); - return metrics.width; + + if (text.substr(0, 2) === ' 1) { + const child = this.rulerStack.pop(); + const parent = this.rulerStack[this.rulerStack.length - 1]; + if (child.parentElement === parent) { + parent.removeChild(child); + } + } + return 0; + } + + if (text.substr(0, 1) === '<') { + const template = document.createElement('div'); + template.innerHTML = text; + const child = template.firstChild; + + if (child) { + const parent = this.rulerStack[this.rulerStack.length - 1]; + this.rulerStack.push(child); + parent.appendChild(child); + } + + return 0; + } + + if (text === '|') return 0; + if (text === ' ') text = '\u00A0'; + + const parent = this.rulerStack[this.rulerStack.length - 1]; + const textNode = document.createTextNode(text); + parent.appendChild(textNode); + const rect = parent.getClientRects()[0] || parent.getBoundingClientRect(); + const width = rect ? rect.width : 0; + parent.removeChild(textNode); + + return width; } - - /** - * Process text for layout (apply hyphenation and smartypants) - * @param {string} text - Text to process - * @returns {string} - Processed text - */ + processTextForLayout(text) { if (!text) return ''; - + let processedText = text; const textProcessor = this.getModule('text-processor'); - - // Apply text processing if available - if (textProcessor) { - // Apply smartypants (typographic punctuation) if available - if (typeof textProcessor.applySmartypants === 'function') { - processedText = textProcessor.applySmartypants(processedText); - } - - // Apply hyphenation if enabled and available - if (this.config.hyphenationEnabled && typeof textProcessor.hyphenateText === 'function') { - processedText = textProcessor.hyphenateText(processedText); - } + + if (textProcessor && typeof textProcessor.process === 'function') { + processedText = textProcessor.process(processedText, { + smartypants: true, + hyphenate: this.config.hyphenationEnabled, + hyphenSelector: '.hyphenatePipe' + }); } else if (this.config.debugMode) { console.log("Text processor not available, skipping text processing"); } - + return processedText; } - - /** - * Calculate layout for a paragraph using Knuth and Plass algorithm - * @param {string} text - Text to layout - * @param {Object} options - Layout options - * @returns {Object} - Layout data with line breaks - */ + calculateLayout(text, options = {}) { if (!text) return null; - + try { - // Check if the kap function is available if (typeof window.kap !== 'function') { console.error("Paragraph Layout: kap function not available. Make sure knuth-and-plass.js is loaded."); return null; } - - // Process text for layout (hyphenation, etc) + const processedText = this.processTextForLayout(text); - - // Prepare options by merging with defaults const layoutOptions = { width: options.width || this.config.maxLineWidth, fontSize: options.fontSize || this.config.defaultFontSize, fontFamily: options.fontFamily || this.config.defaultFontFamily, lineHeight: options.lineHeight || this.config.defaultLineHeight, - tolerance: options.tolerance || 3, // Tolerance for line breaking algorithm + lineHeightPx: options.lineHeightPx, + tolerance: options.tolerance || 3, demerits: options.demerits || { - line: 10, // Demerits for each line break - flagged: 100, // Demerits for flagged break points (like hyphens) - fitness: 3000 // Demerits for consecutive lines with very different looseness/tightness + line: 10, + flagged: 100, + fitness: 3000 } }; - - // Update font for measurement + this.updateFont(layoutOptions.fontSize, layoutOptions.fontFamily); - - // Create measure array - this is crucial for proper line breaking - // The first value is the full width, subsequent values can be for indented lines - const measure = [layoutOptions.width]; - + const numericFontSize = parseFloat(layoutOptions.fontSize) || 16; + const lineHeightPx = layoutOptions.lineHeightPx || (numericFontSize * layoutOptions.lineHeight); + + const measure = options.measures || [layoutOptions.width]; + if (this.config.debugMode) { console.log("Paragraph Layout: Calculating layout for text", { text: processedText, @@ -238,8 +235,7 @@ class ParagraphLayoutModule extends BaseModule { options: layoutOptions }); } - - // Use the global Knuth and Plass algorithm function with proper parameters + const layout = window.kap( processedText, this.measureText.bind(this), @@ -248,55 +244,47 @@ class ParagraphLayoutModule extends BaseModule { layoutOptions.tolerance, layoutOptions.demerits ); - - // If layout failed, return null + if (!layout || !layout.breaks || !layout.nodes) { console.warn("Paragraph Layout: Failed to calculate layout for text"); return null; } - + if (this.config.debugMode) { console.log("Paragraph Layout: Layout calculated", { breaks: layout.breaks.length, nodes: layout.nodes.length }); } - - // Return layout data with original text for reference + return { ...layout, originalText: text, - processedText: processedText, + processedText, width: layoutOptions.width, - lineHeight: layoutOptions.lineHeight + lineHeight: layoutOptions.lineHeight, + lineHeightPx, + fontSize: layoutOptions.fontSize, + fontFamily: layoutOptions.fontFamily }; } catch (error) { console.error("Error calculating layout:", error); return null; } } - - /** - * Set debug mode - * @param {boolean} enabled - Whether debug mode should be enabled - */ + setDebugMode(enabled) { - // Use parent's updateConfig method this.updateConfig({ debugMode: enabled }); console.log(`Paragraph Layout: Debug mode ${enabled ? 'enabled' : 'disabled'}`); } } -// Create the singleton instance const ParagraphLayout = new ParagraphLayoutModule(); -// Register with the module registry if (window.moduleRegistry) { window.moduleRegistry.register(ParagraphLayout); } -// Export the module export { ParagraphLayout }; -// Keep a reference in window for loader system window.ParagraphLayout = ParagraphLayout; diff --git a/public/js/patterns/de.wasm b/public/js/patterns/de.wasm new file mode 100644 index 0000000..2e9e683 Binary files /dev/null and b/public/js/patterns/de.wasm differ diff --git a/public/js/persistence-manager-module.js b/public/js/persistence-manager-module.js index 2b25e44..0d62aa7 100644 --- a/public/js/persistence-manager-module.js +++ b/public/js/persistence-manager-module.js @@ -32,6 +32,8 @@ class PersistenceManagerModule extends BaseModule { tts: { enabled: false, preferred_handler: 'none', + speed: 1.0, + language: 'en-us', voice: '', 'elevenlabs-tts_api_key': '', 'elevenlabs-tts_api_url': 'https://api.elevenlabs.io/v1', @@ -260,6 +262,11 @@ class PersistenceManagerModule extends BaseModule { if (!this.preferences[category]) { this.preferences[category] = {}; } + + if (Object.prototype.hasOwnProperty.call(this.preferences[category], setting) && + Object.is(this.preferences[category][setting], value)) { + return true; + } // Store value this.preferences[category][setting] = value; @@ -612,7 +619,17 @@ class PersistenceManagerModule extends BaseModule { if (element.dataset.prefTransform) { try { // Check if it's a range transformer in format 'range:min,max' - if (element.dataset.prefTransform.startsWith('range:')) { + if (element.dataset.prefTransform === 'centered-speed') { + transformer = { + toElement: (value) => Math.round(((Number(value) || 1) * 50) + 50), + toPreference: (value) => Math.max(0.5, Math.min(2.0, (parseInt(value, 10) - 50) / 50)) + }; + } else if (element.dataset.prefTransform === 'multiplier-percent') { + transformer = { + toElement: (value) => Math.round((Number(value) || 1) * 100), + toPreference: (value) => Math.max(0.25, Math.min(4.0, parseInt(value, 10) / 100)) + }; + } else if (element.dataset.prefTransform.startsWith('range:')) { const rangeValues = element.dataset.prefTransform.substring(6).split(','); if (rangeValues.length === 2) { const min = parseFloat(rangeValues[0]); diff --git a/public/js/playback-coordinator-module.js b/public/js/playback-coordinator-module.js new file mode 100644 index 0000000..62376e6 --- /dev/null +++ b/public/js/playback-coordinator-module.js @@ -0,0 +1,356 @@ +/** + * Playback Coordinator Module + * Synchronizes text animation with TTS audio playback to ensure exact timing match + */ +import { BaseModule } from './base-module.js'; + +class PlaybackCoordinatorModule extends BaseModule { + constructor() { + super('playback-coordinator', 'Playback Coordinator'); + + // Module dependencies + this.dependencies = ['animation-queue', 'tts-factory']; + + // Current playback state + this.isPlaying = false; + this.currentSentence = null; + + // Bind methods + this.bindMethods([ + 'play', + 'calculateWordTimings', + 'animateWords', + 'waitForAudioStart', + 'fastForward', + 'stop' + ]); + } + + /** + * Initialize the module + * @returns {Promise} - Resolves with success status + */ + async initialize() { + try { + this.reportProgress(50, "Initializing Playback Coordinator"); + + // Verify dependencies + const animQueue = this.getModule('animation-queue'); + const ttsFactory = this.getModule('tts-factory'); + + if (!animQueue || !ttsFactory) { + console.error("PlaybackCoordinator: Missing required dependencies"); + return false; + } + + this.reportProgress(100, "Playback Coordinator ready"); + return true; + } catch (error) { + console.error("Error initializing Playback Coordinator:", error); + return false; + } + } + + /** + * Play a sentence with synchronized animation + TTS + * @param {Object} sentence - Prepared sentence object with layout, TTS, and animation data + * @returns {Promise} - Resolves when playback completes + */ + async play(sentence) { + if (this.isPlaying) { + console.warn('PlaybackCoordinator: Already playing, canceling previous'); + await this.stop(); + } + + this.isPlaying = true; + this.currentSentence = sentence; + + try { + // Start TTS first, then begin text animation when the audio element + // confirms playback has started. Sentence preparation/prefetching is + // handled by SentenceQueue and can still run while this sentence plays. + const ttsPromise = this.playTTS(sentence); + await this.waitForAudioStart(sentence, ttsPromise); + const animPromise = this.animateWords(sentence); + + // Wait for both to complete + await Promise.all([ttsPromise, animPromise]); + + console.log(`PlaybackCoordinator: Completed sentence ${sentence.id}`); + } catch (error) { + console.error('PlaybackCoordinator: Error during playback:', error); + throw error; + } finally { + this.isPlaying = false; + this.currentSentence = null; + } + } + + /** + * Play TTS audio for a sentence + * @param {Object} sentence - Sentence object with TTS data + * @returns {Promise} - Resolves when TTS completes + */ + async playTTS(sentence) { + if (!sentence.tts || !sentence.tts.enabled) { + // TTS disabled, return immediately + return Promise.resolve(); + } + + try { + document.dispatchEvent(new CustomEvent('tts:playback-start', { + detail: { sentenceId: sentence.id } + })); + if (typeof sentence.tts.play === 'function') { + await sentence.tts.play(); + } else { + console.warn('PlaybackCoordinator: TTS play function not available'); + } + } catch (error) { + console.error('PlaybackCoordinator: TTS playback error:', error); + // Don't throw - allow animation to continue + } finally { + document.dispatchEvent(new CustomEvent('tts:playback-end', { + detail: { sentenceId: sentence.id } + })); + } + } + + async waitForAudioStart(sentence, ttsPromise) { + if (!sentence.tts || !sentence.tts.enabled) { + return; + } + + return new Promise((resolve) => { + let settled = false; + const cleanup = () => { + document.removeEventListener('tts:audio-started', onStarted); + document.removeEventListener('tts:playback-end', onEnded); + clearTimeout(timeout); + }; + const finish = (reason) => { + if (settled) { + return; + } + settled = true; + cleanup(); + console.log(`PlaybackCoordinator: Animation start released (${reason}) for ${sentence.id}`); + resolve(); + }; + const onStarted = () => finish('audio-started'); + const onEnded = (event) => { + if (!event.detail || event.detail.sentenceId === sentence.id) { + finish('tts-ended-before-start'); + } + }; + const timeout = setTimeout(() => finish('audio-start-timeout'), 1500); + + document.addEventListener('tts:audio-started', onStarted, { once: true }); + document.addEventListener('tts:playback-end', onEnded); + + Promise.resolve(ttsPromise).then(() => finish('tts-promise-resolved')).catch(() => finish('tts-promise-rejected')); + }); + } + + /** + * Animate words using calculated timings + * @param {Object} sentence - Sentence object with animation data and DOM element + * @returns {Promise} - Resolves when animation completes + */ + async animateWords(sentence) { + if (!sentence.element || !sentence.animation || !sentence.animation.wordTimings) { + console.error('PlaybackCoordinator: Missing animation data'); + return Promise.resolve(); + } + + const animQueue = this.getModule('animation-queue'); + if (!animQueue) { + console.error('PlaybackCoordinator: Animation queue not available'); + return Promise.resolve(); + } + + const wordElements = sentence.element.querySelectorAll('.word'); + let wordTimings = sentence.animation.wordTimings; + let cueTimings = sentence.animation.cueTimings || []; + + if (wordElements.length !== wordTimings.length) { + console.info(`PlaybackCoordinator: Word count mismatch (DOM: ${wordElements.length}, timings: ${wordTimings.length}); recalculating timings from rendered words`); + const renderedWords = Array.from(wordElements).map(word => word.textContent || ''); + const duration = sentence.tts?.duration || sentence.animation.totalDuration || 0; + wordTimings = this.calculateWordTimings(renderedWords, duration).wordTimings; + cueTimings = cueTimings.map(cue => { + const wordIndex = Math.max(0, Math.min(cue.wordIndex || 0, wordTimings.length - 1)); + return { + ...cue, + delay: (wordTimings[wordIndex] || { delay: duration }).delay + }; + }); + } + + return new Promise((resolve) => { + const totalDuration = wordTimings.length > 0 + ? Math.max(...wordTimings.map(timing => timing.delay + timing.duration)) + : 0; + + console.log(`PlaybackCoordinator: Animating ${wordTimings.length} words over ${totalDuration}ms`); + if (wordTimings.length > 0) { + console.log(` First word delay: ${wordTimings[0].delay}ms, Last word delay: ${wordTimings[wordTimings.length-1].delay}ms`); + } + + // Schedule each word animation + wordTimings.forEach((timing, i) => { + if (i < wordElements.length) { + animQueue.schedule(() => { + const word = wordElements[i]; + const duration = Math.max(0, timing.duration || 0); + const transitionDuration = `${duration}ms`; + + word.style.transition = `opacity ${transitionDuration} linear, transform ${transitionDuration} ease-out`; + word.style.visibility = 'visible'; + word.style.opacity = '1'; + word.style.transform = 'translateY(0)'; + }, timing.delay); + } + }); + + cueTimings.forEach(cue => { + animQueue.schedule(() => { + document.dispatchEvent(new CustomEvent('story:media-cue', { + detail: { + sentenceId: sentence.id, + ...cue + } + })); + }, cue.delay || 0); + }); + + // Schedule completion callback + animQueue.schedule(() => { + resolve(); + }, totalDuration + 100); // Small buffer + }); + } + + /** + * Calculate word-level timing to match total TTS duration + * This is a utility method that can be called by SentenceQueue during preparation + * @param {Array} words - Array of words to animate + * @param {number} totalDuration - Total duration in milliseconds + * @returns {Object} - Object with wordTimings array and totalDuration + */ + calculateWordTimings(words, totalDuration) { + if (!words || words.length === 0) { + return { + wordTimings: [], + totalDuration: 0 + }; + } + + // Calculate characters per word + const totalChars = words.reduce((sum, word) => sum + word.length, 0); + + if (totalChars === 0) { + // Edge case: all empty words + return { + wordTimings: words.map(word => ({ word, delay: 0, duration: 0 })), + totalDuration: 0 + }; + } + + const msPerChar = totalDuration / totalChars; + + let currentDelay = 0; + const wordTimings = words.map(word => { + const duration = word.length * msPerChar; + const timing = { + word: word, + delay: currentDelay, + duration: duration + }; + currentDelay += duration; + return timing; + }); + + return { + wordTimings, + totalDuration: Math.round(currentDelay) + }; + } + + /** + * Fast forward current playback + * Completes all animations immediately and stops TTS + */ + async fastForward() { + if (!this.isPlaying || !this.currentSentence) { + return; + } + + console.log('PlaybackCoordinator: Fast forwarding'); + + const animQueue = this.getModule('animation-queue'); + if (animQueue) { + animQueue.fastForward(); + } + + const ttsFactory = this.getModule('tts-factory'); + if (ttsFactory && typeof ttsFactory.fadeOut === 'function') { + await ttsFactory.fadeOut(1000); + } else if (this.currentSentence.tts && typeof this.currentSentence.tts.stop === 'function') { + await new Promise(resolve => { + setTimeout(() => { + this.currentSentence.tts.stop(); + resolve(); + }, 1000); + }); + } + + // Complete all word animations immediately + if (this.currentSentence.element) { + const wordElements = this.currentSentence.element.querySelectorAll('.word'); + wordElements.forEach(word => { + word.style.opacity = '1'; + word.style.transform = 'translateY(0)'; + }); + } + } + + /** + * Stop current playback + */ + async stop() { + if (!this.isPlaying) { + return; + } + + console.log('PlaybackCoordinator: Stopping'); + + // Stop TTS + if (this.currentSentence && this.currentSentence.tts && typeof this.currentSentence.tts.stop === 'function') { + this.currentSentence.tts.stop(); + } + + // Clear animation queue + const animQueue = this.getModule('animation-queue'); + if (animQueue) { + animQueue.clearAll(); + } + + this.isPlaying = false; + this.currentSentence = null; + } +} + +// Create the singleton instance +const PlaybackCoordinator = new PlaybackCoordinatorModule(); + +// Export the module +export { PlaybackCoordinator }; + +// Register with the module registry +if (window.moduleRegistry) { + window.moduleRegistry.register(PlaybackCoordinator); +} + +// Keep a reference in window for loader system +window.PlaybackCoordinator = PlaybackCoordinator; diff --git a/public/js/sentence-queue-module.js b/public/js/sentence-queue-module.js index a1828c5..4009968 100644 --- a/public/js/sentence-queue-module.js +++ b/public/js/sentence-queue-module.js @@ -9,20 +9,29 @@ class SentenceQueueModule extends BaseModule { super('sentence-queue', 'Sentence Queue'); // Dependencies - this.dependencies = ['text-buffer', 'tts-factory', 'tts-player']; - + this.dependencies = ['text-buffer', 'tts-factory', 'paragraph-layout', 'audio-manager']; + // Queue state this.sentenceQueue = []; this.isProcessing = false; this.onSentenceReadyCallback = null; - + + // Cache for prefetched sentences + this.preparedCache = new Map(); + // Bind methods this.bindMethods([ 'initialize', 'addSentence', 'processNextSentence', 'setOnSentenceReady', - 'completeSentence' + 'completeSentence', + 'prepareSentence', + 'prepareLayout', + 'extractWords', + 'getDropCapText', + 'extractDropCapText', + 'calculateAnimationTiming' ]); } @@ -69,9 +78,13 @@ class SentenceQueueModule extends BaseModule { * @param {Function} callback - Callback to call when sentence is processed */ addSentence(sentence, callback) { + const queueItem = typeof sentence === 'object' && sentence !== null + ? { ...sentence, callback } + : { text: sentence, callback }; + this.sentenceQueue.push({ - text: sentence, - callback: callback + ...queueItem, + text: String(queueItem.text || '').trim() }); // Process the queue if not already processing @@ -87,36 +100,78 @@ class SentenceQueueModule extends BaseModule { if (this.sentenceQueue.length === 0 || this.isProcessing) { return; } - + this.isProcessing = true; - const item = this.sentenceQueue[0]; // Don't remove yet - + const item = this.sentenceQueue[0]; + try { - // Get TTS Factory - const ttsFactory = this.getModule('tts-factory'); - - if (!ttsFactory) { - console.error("SentenceQueue: TTSFactory dependency not found"); - this.completeSentence(item, { success: false, reason: 'no_tts_factory' }); - return; - } - - // Create a speech metadata object - const speechMetadata = await this.prepareSpeechMetadata(item.text); - - // If we have a callback for ready sentences, call it with the metadata - if (this.onSentenceReadyCallback) { - this.onSentenceReadyCallback(item.text, speechMetadata, () => { - // Remove from queue and process next - this.completeSentence(item, { success: true }); - }); + // Check if sentence is already in cache + const cacheKey = `${item.id || ''}:${item.text}`; + let sentence = this.preparedCache.get(cacheKey); + + if (!sentence) { + // Prepare complete sentence object (TTS + layout in parallel) + sentence = await this.prepareSentence(item); } else { - // No callback, just complete - this.completeSentence(item, { success: true }); + console.log('SentenceQueue: Using cached sentence'); + this.preparedCache.delete(cacheKey); } + + // Prefetch next sentence while current displays + if (this.sentenceQueue.length > 1) { + const nextItem = this.sentenceQueue[1]; + const nextCacheKey = `${nextItem.id || ''}:${nextItem.text}`; + if (!this.preparedCache.has(nextCacheKey)) { + document.dispatchEvent(new CustomEvent('story:process-state', { + detail: { state: 'playing-generating', reason: 'prefetch-start', sentenceId: nextItem.id } + })); + console.log('Process state: playing-generating', { reason: 'prefetch-start', sentenceId: nextItem.id }); + this.prepareSentence(nextItem) + .then(prepared => { + this.preparedCache.set(nextCacheKey, prepared); + console.log('SentenceQueue: Prefetched next sentence'); + document.dispatchEvent(new CustomEvent('story:process-state', { + detail: { state: 'playing-ready', reason: 'prefetch-complete', sentenceId: nextItem.id } + })); + console.log('Process state: playing-ready', { reason: 'prefetch-complete', sentenceId: nextItem.id }); + }) + .catch(err => console.warn('SentenceQueue: Prefetch failed:', err)); + } + } else { + document.dispatchEvent(new CustomEvent('story:process-state', { + detail: { state: 'playing-ready', reason: 'no-prefetch-needed', sentenceId: item.id } + })); + console.log('Process state: playing-ready', { reason: 'no-prefetch-needed', sentenceId: item.id }); + } + + // Notify display handler with complete sentence + if (this.onSentenceReadyCallback) { + await new Promise(resolve => { + sentence.onComplete = resolve; + this.onSentenceReadyCallback(sentence, resolve); + }); + } + + // Remove from queue and continue + this.sentenceQueue.shift(); + if (item.callback) item.callback({ success: true }); + } catch (error) { - console.error("Error processing sentence:", error); - this.completeSentence(item, { success: false, reason: error.message }); + console.error("SentenceQueue: Error processing sentence:", error); + if (item.callback) item.callback({ success: false, error }); + } finally { + this.isProcessing = false; + if (this.sentenceQueue.length > 0) { + this.processNextSentence(); + } else { + document.dispatchEvent(new CustomEvent('story:process-state', { + detail: { state: 'ready', reason: 'queue-empty' } + })); + document.dispatchEvent(new CustomEvent('tts:queue-empty', { + detail: { reason: 'sentence-queue-empty' } + })); + console.log('Process state: ready', { reason: 'queue-empty' }); + } } } @@ -127,14 +182,14 @@ class SentenceQueueModule extends BaseModule { */ async prepareSpeechMetadata(text) { const ttsFactory = this.getModule('tts-factory'); - const ttsPlayer = this.getModule('tts-player'); - - if (!ttsFactory || !ttsPlayer) { + + if (!ttsFactory) { throw new Error("TTS dependencies not found"); } - - // Check if TTS is enabled - const isTtsEnabled = ttsPlayer.isEnabled(); + + // Check if TTS is enabled via active handler + const activeHandler = ttsFactory.getActiveHandler(); + const isTtsEnabled = activeHandler !== null; // If TTS is disabled, estimate duration based on character count if (!isTtsEnabled) { @@ -175,26 +230,19 @@ class SentenceQueueModule extends BaseModule { * @returns {Object} - Speech metadata object with estimated duration */ estimateSpeechDuration(text) { - // Average reading speed is about 14-15 characters per second - // We'll use a slightly slower rate for TTS + // Average aloud narration is around 12 characters per second at 1x. const charactersPerSecond = 12; - const ttsPlayer = this.getModule('tts-player'); - - // Get the current speed setting if available + let speedMultiplier = 1.0; - if (ttsPlayer) { - const ttsFactory = this.getModule('tts-factory'); - if (ttsFactory) { - // Get the current speed setting (typically 0.5-2.0) - const speed = ttsFactory.speed || 1.0; - speedMultiplier = speed; - } + const ttsFactory = this.getModule('tts-factory'); + if (ttsFactory) { + speedMultiplier = Number.isFinite(ttsFactory.speed) ? Math.max(0.25, ttsFactory.speed) : 1.0; } // Calculate estimated duration in milliseconds const charCount = text.length; const durationSeconds = charCount / (charactersPerSecond * speedMultiplier); - const durationMs = Math.max(durationSeconds * 1000, 500); // Minimum 500ms + const durationMs = Math.max(durationSeconds * 1000, 800); return { text: text, @@ -207,6 +255,264 @@ class SentenceQueueModule extends BaseModule { }; } + /** + * Prepare a complete sentence object with TTS and layout + * @param {string} text - Text to prepare + * @returns {Promise} - Complete sentence object + */ + async prepareSentence(item) { + const text = typeof item === 'string' ? item : item.text; + const id = item.id || `paragraph-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; + const metadata = typeof item === 'object' && item !== null ? item : {}; + + try { + if (metadata.type && metadata.type !== 'paragraph') { + if (metadata.type === 'music') { + const audioManager = this.getModule('audio-manager'); + if (audioManager && typeof audioManager.playMusic === 'function') { + audioManager.getAssetUrl('music', metadata.filename); + } + } + + return { + id, + kind: metadata.type, + text: text || '', + status: 'ready', + metadata, + tts: { duration: 0, provider: null, audioData: null, play: null, stop: null, enabled: false }, + animation: { wordTimings: [], cueTimings: [], totalDuration: 0 }, + element: null, + onComplete: null + }; + } + + const audioManager = this.getModule('audio-manager'); + if (audioManager && typeof audioManager.preloadMediaCues === 'function') { + await audioManager.preloadMediaCues(metadata.cueMarkers || []); + } + + // Prepare TTS and layout in parallel + const [ttsData, layoutData] = await Promise.all([ + this.prepareSpeechMetadata(text), + this.prepareLayout(text, metadata) + ]); + + // Calculate animation timing based on TTS duration + const words = this.extractWords(layoutData.nodes); + const animation = this.calculateAnimationTiming(words, ttsData.duration, metadata.cueMarkers || []); + + console.log(`SentenceQueue: Prepared sentence "${text.substring(0, 50)}..." - TTS duration: ${ttsData.duration}ms, Words: ${words.length}, Animation total: ${animation.totalDuration}ms, Layout breaks: ${layoutData.breaks.length}`); + + return { + id, + text, + paragraphIndex: metadata.paragraphIndex ?? null, + isFirstParagraphInChapter: Boolean(metadata.isFirstParagraphInChapter), + role: metadata.role || 'body', + dropCap: Boolean(metadata.dropCap), + addTopSpace: Boolean(metadata.addTopSpace), + cueMarkers: metadata.cueMarkers || [], + status: 'ready', + layout: layoutData, + tts: { + duration: ttsData.duration, + provider: ttsData.handler, + audioData: ttsData.audioData || null, + play: ttsData.play, + stop: ttsData.stop, + enabled: ttsData.isTtsEnabled + }, + animation: animation, + element: null, + onComplete: null + }; + } catch (error) { + console.error('SentenceQueue: Error preparing sentence:', error); + throw error; + } + } + + /** + * Prepare layout for a sentence + * @param {string} text - Text to prepare layout for + * @returns {Promise} - Layout data + */ + async prepareLayout(text, metadata = {}) { + const paragraphLayout = this.getModule('paragraph-layout'); + + if (!paragraphLayout) { + throw new Error("ParagraphLayout module not found"); + } + + try { + if (document.fonts && document.fonts.ready) { + await document.fonts.ready; + } + + // Calculate layout with Knuth-Plass + const storyElement = document.getElementById('story'); + if (!storyElement) { + throw new Error("Story container not found"); + } + + // Get actual CSS values from the paragraph typography rule, not the + // container. The measured font and rendered font must be identical. + const containerWidth = storyElement.clientWidth; + const probe = document.createElement('p'); + probe.style.visibility = 'hidden'; + probe.style.position = 'absolute'; + probe.style.left = '-8000px'; + probe.style.top = '-8000px'; + storyElement.appendChild(probe); + const computedStyle = window.getComputedStyle(probe); + const fontSize = parseFloat(computedStyle.fontSize); + const lineHeight = parseFloat(computedStyle.lineHeight); + const fontFamily = computedStyle.fontFamily; + probe.remove(); + + console.log(`SentenceQueue: Container metrics - width: ${containerWidth}px, fontSize: ${fontSize}px, lineHeight: ${lineHeight}px`); + + // Standard book indentation: no indent on the first chapter paragraph, + // first-line indent on following paragraphs. + const dropCapLines = metadata.dropCap ? 2 : 0; + const dropCapWidth = metadata.dropCap ? lineHeight * 1.45 : 0; + const indentWidth = (metadata.isFirstParagraphInChapter || metadata.addTopSpace) ? 0 : lineHeight * 1.5; + const layoutText = metadata.layoutText || text; + const layoutPlainText = metadata.dropCap ? this.extractDropCapText(layoutText) : layoutText; + + // Measures are consumed in line order by the line breaker. + const measures = metadata.dropCap + ? [ + Math.max(120, containerWidth - dropCapWidth), + Math.max(120, containerWidth - dropCapWidth), + containerWidth + ] + : [ + Math.max(120, containerWidth - indentWidth), + containerWidth, + containerWidth + ]; + + console.log(`SentenceQueue: Layout calculation - indentWidth: ${indentWidth.toFixed(1)}px, measures: [${measures.map(m => m.toFixed(1)).join(', ')}]`); + + const layout = paragraphLayout.calculateLayout(layoutPlainText, { + measures, + fontSize: `${fontSize}px`, + fontFamily, + lineHeight: lineHeight / fontSize, + lineHeightPx: lineHeight + }); + + if (!layout) { + throw new Error('Paragraph layout calculation failed'); + } + + return { + breaks: layout.breaks, + nodes: layout.nodes, + processedText: layout.processedText || text, + sourceLayoutText: layoutText, + measures, + indentWidth, + dropCap: Boolean(metadata.dropCap), + dropCapText: metadata.dropCap ? this.getDropCapText(layoutText) : '', + dropCapLines, + addTopSpace: Boolean(metadata.addTopSpace), + role: metadata.role || 'body', + fontSize: layout.fontSize, + fontFamily: layout.fontFamily, + lineHeight: layout.lineHeight, + lineHeightPx: layout.lineHeightPx + }; + } catch (error) { + console.error('SentenceQueue: Error preparing layout:', error); + throw error; + } + } + + /** + * Extract words from layout nodes + * @param {Array} nodes - Layout nodes from Knuth-Plass algorithm + * @returns {Array} - Array of words + */ + extractWords(nodes) { + if (!nodes || !Array.isArray(nodes)) { + return []; + } + + return nodes + .filter(node => node.type === 'box') + .map(node => node.value || ''); + } + + getDropCapText(text) { + const plain = String(text || '').replace(/<[^>]+>/g, ''); + const match = plain.match(/^([“"']?[A-Za-zÀ-ÖØ-öø-ÿ])/u); + return match ? match[1] : ''; + } + + extractDropCapText(text) { + const dropCap = this.getDropCapText(text); + if (!dropCap) return text; + return String(text).replace(dropCap, '').trimStart(); + } + + /** + * Calculate animation timing based on TTS duration + * @param {Array} words - Array of words to animate + * @param {number} totalDuration - Total duration in milliseconds + * @returns {Object} - Animation timing data + */ + calculateAnimationTiming(words, totalDuration, cueMarkers = []) { + if (!words || words.length === 0) { + return { + wordTimings: [], + cueTimings: [], + totalDuration: 0 + }; + } + + const totalChars = words.reduce((sum, word) => sum + word.length, 0); + + if (totalChars === 0) { + return { + wordTimings: words.map(word => ({ word, delay: 0, duration: 0 })), + cueTimings: [], + totalDuration: 0 + }; + } + + const msPerChar = totalDuration / totalChars; + + let currentDelay = 0; + const wordTimings = words.map(word => { + const duration = word.length * msPerChar; + const timing = { + word: word, + delay: currentDelay, + duration: duration + }; + currentDelay += duration; + return timing; + }); + + const cueTimings = (cueMarkers || []).map(cue => { + const wordIndex = Math.max(0, Math.min(cue.wordIndex || 0, wordTimings.length - 1)); + const timing = wordTimings[wordIndex] || { delay: currentDelay }; + return { + ...cue, + delay: timing.delay + }; + }); + + return { + wordTimings, + cueTimings, + totalDuration: Math.round(currentDelay) + }; + } + /** * Complete processing of a sentence * @param {Object} item - Queue item diff --git a/public/js/socket-client-module.js b/public/js/socket-client-module.js index 6bc7beb..09b7d24 100644 --- a/public/js/socket-client-module.js +++ b/public/js/socket-client-module.js @@ -27,6 +27,13 @@ class SocketClientModule extends BaseModule { 'disconnect', 'send', 'sendCommand', + 'callGameApi', + 'newGame', + 'loadGame', + 'saveGame', + 'hasSaveGame', + 'getSaveGames', + 'isGameRunning', 'requestStartGame', 'requestSaveGame', 'requestLoadGame', @@ -186,6 +193,9 @@ class SocketClientModule extends BaseModule { // Add text to the buffer if available if (this.textBuffer) { console.log(`Socket Client: Processing text fragment: "${text.substring(0, 50)}${text.length > 50 ? '...' : ''}"`); + document.dispatchEvent(new CustomEvent('story:process-state', { + detail: { state: 'waiting-generating', reason: 'server-response-received' } + })); this.textBuffer.addText(text); } else { console.error('Socket Client: Text buffer not available'); @@ -277,6 +287,9 @@ class SocketClientModule extends BaseModule { try { this.socket.emit('playerCommand', { command }); + document.dispatchEvent(new CustomEvent('story:process-state', { + detail: { state: 'command-waiting', reason: 'command-sent', command } + })); return true; } catch (error) { console.error('Socket Client: Error sending command:', error); @@ -284,23 +297,57 @@ class SocketClientModule extends BaseModule { } } + async callGameApi(method, args = []) { + if (!this.isConnected || !this.socket) { + const connected = await this.connect(); + if (!connected || !this.socket) { + return { success: false, error: 'not_connected' }; + } + } + + return new Promise((resolve) => { + if (!this.socket) { + resolve({ success: false, error: 'not_connected' }); + return; + } + + this.socket.emit('gameApi', { method, args }, (response) => { + resolve(response || { success: false, error: 'empty_response' }); + }); + }); + } + + newGame() { + return this.callGameApi('newGame', []); + } + + loadGame(slot = 1) { + return this.callGameApi('loadGame', [slot]); + } + + saveGame(slot = 1) { + return this.callGameApi('saveGame', [slot]); + } + + hasSaveGame(slot = 1) { + return this.callGameApi('hasSaveGame', [slot]); + } + + getSaveGames() { + return this.callGameApi('getSaveGames', []); + } + + isGameRunning() { + return this.callGameApi('isGameRunning', []); + } + /** * Request to start a new game * @returns {boolean} - Success status */ requestStartGame() { - if (!this.isConnected || !this.socket) { - console.error('Socket Client: Not connected, cannot start game'); - return false; - } - - try { - this.socket.emit('startGame'); - return true; - } catch (error) { - console.error('Socket Client: Error starting game:', error); - return false; - } + this.newGame(); + return true; } /** @@ -308,18 +355,8 @@ class SocketClientModule extends BaseModule { * @returns {boolean} - Success status */ requestSaveGame() { - if (!this.isConnected || !this.socket) { - console.error('Socket Client: Not connected, cannot save game'); - return false; - } - - try { - this.socket.emit('saveGame'); - return true; - } catch (error) { - console.error('Socket Client: Error saving game:', error); - return false; - } + this.saveGame(1); + return true; } /** @@ -327,18 +364,8 @@ class SocketClientModule extends BaseModule { * @returns {boolean} - Success status */ requestLoadGame() { - if (!this.isConnected || !this.socket) { - console.error('Socket Client: Not connected, cannot load game'); - return false; - } - - try { - this.socket.emit('loadGame'); - return true; - } catch (error) { - console.error('Socket Client: Error loading game:', error); - return false; - } + this.loadGame(1); + return true; } /** diff --git a/public/js/text-buffer-module.js b/public/js/text-buffer-module.js index 1a03db6..c30e827 100644 --- a/public/js/text-buffer-module.js +++ b/public/js/text-buffer-module.js @@ -13,10 +13,15 @@ class TextBufferModule extends BaseModule { this.processingLock = false; this.processingQueue = []; this.isProcessingActive = false; + this.paragraphCounter = 0; + this.currentTextBlockId = 0; + this.markupParser = null; + this.dependencies = ['markup-parser']; // Bind methods using parent's bindMethods utility this.bindMethods([ 'addText', + 'splitIntoParagraphs', 'processNextFromQueue', 'processSentences', 'processNextSentence', @@ -33,6 +38,11 @@ class TextBufferModule extends BaseModule { */ async initialize() { try { + this.markupParser = this.getModule('markup-parser'); + if (!this.markupParser) { + console.warn("TextBuffer: Markup parser not found, using plain paragraph splitting"); + } + // Use parent's addEventListener for automatic cleanup this.addEventListener(document, 'ui:paragraph:complete', (event) => { if (this.processingQueue.length > 0 && !this.isProcessingActive) { @@ -83,9 +93,39 @@ class TextBufferModule extends BaseModule { if (!text) return; console.log(`TextBuffer: Adding text: "${text.substring(0, 50)}${text.length > 50 ? '...' : ''}"`); - - // Add to processing queue instead of directly to buffer - this.processingQueue.push(text); + + const blocks = this.markupParser && typeof this.markupParser.parse === 'function' + ? this.markupParser.parse(text) + : this.splitIntoParagraphs(text).map(paragraphText => ({ + type: 'paragraph', + text: paragraphText, + layoutText: paragraphText, + cueMarkers: [], + role: 'body', + isFirstParagraphInChapter: false + })); + + blocks.forEach(block => { + if (block.type === 'paragraph') { + const paragraphId = `paragraph-${this.paragraphCounter + 1}`; + this.processingQueue.push({ + ...block, + id: paragraphId, + paragraphIndex: this.paragraphCounter, + textBlockId: this.currentTextBlockId + }); + this.paragraphCounter += 1; + } else { + this.processingQueue.push({ + ...block, + id: `${block.type}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}` + }); + + if (block.type === 'image') { + this.currentTextBlockId += 1; + } + } + }); // Process the queue if not already processing if (!this.isProcessingActive && this.onSentenceReadyCallback) { @@ -94,6 +134,20 @@ class TextBufferModule extends BaseModule { console.log('TextBuffer: Text queued for processing'); } } + + /** + * Split an incoming narrative fragment into book paragraphs. + * Single newlines inside a paragraph are normalized to spaces; blank lines + * mark distinct paragraphs. + * @param {string} text - Raw text fragment + * @returns {Array} - Normalized paragraph strings + */ + splitIntoParagraphs(text) { + return String(text) + .split(/\n\s*\n/g) + .map(paragraph => paragraph.replace(/\s*\n\s*/g, ' ').trim()) + .filter(Boolean); + } /** * Process the next text fragment from the queue @@ -104,18 +158,32 @@ class TextBufferModule extends BaseModule { } this.isProcessingActive = true; - const text = this.processingQueue.shift(); + const paragraph = this.processingQueue.shift(); console.log(`TextBuffer: Processing next fragment from queue, remaining: ${this.processingQueue.length}`); - - // Add text to buffer - this.buffer += text; - - // If we have a trailing newline as a complete sentence, add a period - this.buffer = this.buffer.replace(/\n$/g, '.\n'); - - // Process sentences - this.processSentences(); + + this.buffer = paragraph.text; + + super.dispatchEvent('buffer:sentence', { + sentence: paragraph.text, + paragraph, + remaining: this.processingQueue.length + }); + + if (this.onSentenceReadyCallback) { + this.onSentenceReadyCallback(paragraph, () => {}); + this.buffer = ''; + this.isProcessingActive = false; + this.processingLock = false; + + if (this.processingQueue.length > 0) { + queueMicrotask(() => this.processNextFromQueue()); + } else { + super.dispatchEvent('buffer:empty', {}); + } + } else { + this.isProcessingActive = false; + } } /** @@ -238,6 +306,8 @@ class TextBufferModule extends BaseModule { this.processingQueue = []; this.isProcessingActive = false; this.processingLock = false; + this.paragraphCounter = 0; + this.currentTextBlockId = 0; } /** diff --git a/public/js/text-processor-module.js b/public/js/text-processor-module.js index 02fa077..7ecd729 100644 --- a/public/js/text-processor-module.js +++ b/public/js/text-processor-module.js @@ -3,7 +3,6 @@ * Handles text formatting and typography enhancements like smart quotes and hyphenation */ import { BaseModule } from './base-module.js'; -import Hyphenopoly from './hyphenopoly.module.js'; class TextProcessorModule extends BaseModule { constructor() { @@ -25,7 +24,9 @@ class TextProcessorModule extends BaseModule { 'isHyphenationAvailable', 'hyphenate', 'setLocale', - 'handleLocaleChanged' + 'handleLocaleChanged', + 'loadHyphenopolyLoader', + 'normalizeHyphenationLocale' ]); } @@ -161,104 +162,89 @@ class TextProcessorModule extends BaseModule { } /** - * Initialize hyphenation using Hyphenopoly module + * Initialize hyphenation using the browser Hyphenopoly loader used by the prototype. * @returns {Promise} - Resolves when hyphenation is initialized */ - initializeHyphenation() { - return new Promise((resolve, reject) => { - try { - console.log("Initializing hyphenation with Hyphenopoly module"); - - // Configure Hyphenopoly with our requirements - const hyphenatorPromise = Hyphenopoly.config({ - require: [this.locale], - hyphen: '\u00AD', // Soft hyphen character - minWordLength: 5, - leftmin: 2, - rightmin: 2, - compound: "hyphen", - // Define a custom loader for the patterns - loader: (file) => { - return new Promise((resolve, reject) => { - // Determine correct pattern file based on locale - let patternFile = file; - - // Special handling for 'en' locale - use en-us.wasm if available - if (file === 'en.wasm') { - patternFile = 'en-us.wasm'; - } - - const patternPath = `/js/patterns/${patternFile}`; - console.log(`Loading hyphenation pattern: ${patternPath}`); - - fetch(patternPath) - .then(response => { - if (!response.ok) { - throw new Error(`Failed to load ${file}: ${response.status} ${response.statusText}`); - } - return response.arrayBuffer(); - }) - .then(arrayBuffer => { - resolve(arrayBuffer); - }) - .catch(error => { - console.error(`Error loading hyphenation pattern ${file}:`, error); - reject(error); - }); - }); - }, - handleEvent: { - error: (e) => { - console.warn(`Hyphenopoly error: ${e.msg}`); - }, - engineReady: (e) => { - console.log(`Hyphenopoly engine ready for ${e.msg}`); - } + async initializeHyphenation() { + try { + console.log("Initializing hyphenation with browser Hyphenopoly loader"); + + const locale = this.normalizeHyphenationLocale(this.locale); + this.hyphenator = null; + this.hyphenatorReady = false; + + await this.loadHyphenopolyLoader(); + + window.Hyphenopoly.config({ + require: { + [locale]: "FORCEHYPHENOPOLY" + }, + paths: { + maindir: "/js/", + patterndir: "/js/patterns/" + }, + setup: { + hide: "element", + selectors: { + ".hyphenate": { hyphen: "\u00AD" }, + ".hyphenatePipe": { hyphen: "|" } } - }); - - // Get the hyphenator for our locale - hyphenatorPromise.get(this.locale) - .then(hyphenator => { - this.hyphenator = hyphenator; - this.hyphenatorReady = true; - console.log(`Hyphenator ready for ${this.locale}`); - - // Dispatch event that hyphenation is ready - document.dispatchEvent(new CustomEvent('hyphenation-loaded')); - resolve(true); // Successfully initialized - }) - .catch(error => { - console.error(`Failed to initialize hyphenator for ${this.locale}:`, error); - // Try to fall back to en-us if the current locale failed - if (this.locale !== 'en-us') { - console.log("Falling back to en-us hyphenation"); - return hyphenatorPromise.get('en-us'); - } - throw error; - }) - .then(fallbackHyphenator => { - if (fallbackHyphenator) { - this.hyphenator = fallbackHyphenator; - this.hyphenatorReady = true; - console.log("Using fallback en-us hyphenator"); - - // Dispatch event that hyphenation is ready - document.dispatchEvent(new CustomEvent('hyphenation-loaded')); - resolve(true); // Successfully initialized with fallback - } - }) - .catch(error => { - console.error("Failed to initialize hyphenation even with fallback:", error); - reject(error); // Failed to initialize - }); - } catch (error) { - console.error("Error setting up hyphenation:", error); - reject(error); // Failed to initialize + }, + handleEvent: { + error: (event) => { + console.warn(`Hyphenopoly error: ${event.msg || event.message || event.type}`); + }, + engineReady: (event) => { + console.log(`Hyphenopoly engine ready: ${event.msg || locale}`); + } + } + }); + + this.hyphenator = await window.Hyphenopoly.hyphenators[locale]; + this.hyphenatorReady = true; + this.locale = locale; + + console.log(`Hyphenator ready for ${locale}`); + document.dispatchEvent(new CustomEvent('hyphenation-loaded')); + return true; + } catch (error) { + this.hyphenator = null; + this.hyphenatorReady = false; + console.error("Failed to initialize Hyphenopoly browser hyphenation:", error); + throw error; + } + } + + loadHyphenopolyLoader() { + return new Promise((resolve, reject) => { + if (window.Hyphenopoly && typeof window.Hyphenopoly.config === 'function') { + resolve(); + return; } + + const existingScript = document.querySelector('script[src="/js/Hyphenopoly_Loader.js"]'); + if (existingScript) { + existingScript.addEventListener('load', () => resolve(), { once: true }); + existingScript.addEventListener('error', () => reject(new Error('Failed to load Hyphenopoly loader')), { once: true }); + return; + } + + const script = document.createElement('script'); + script.src = '/js/Hyphenopoly_Loader.js'; + script.async = true; + script.onload = () => resolve(); + script.onerror = () => reject(new Error('Failed to load Hyphenopoly loader')); + document.head.appendChild(script); }); } + normalizeHyphenationLocale(locale) { + const normalized = String(locale || 'en-us').toLowerCase(); + if (normalized === 'en') return 'en-us'; + if (normalized === 'de-de') return 'de'; + return normalized; + } + /** * Check if hyphenation is available * @returns {boolean} - True if hyphenation is available @@ -270,15 +256,17 @@ class TextProcessorModule extends BaseModule { /** * Hyphenate a text using the Hyphenopoly module * @param {string} text - The text to hyphenate + * @param {string} selector - Optional selector for Hyphenopoly * @returns {string} - The hyphenated text */ - hyphenate(text) { + hyphenate(text, selector = null) { if (!this.isHyphenationAvailable()) { return text; } - + try { - return this.hyphenator(text); + // If selector provided, pass it to hyphenator + return selector ? this.hyphenator(text, selector) : this.hyphenator(text); } catch (error) { console.error("Error hyphenating text:", error); return text; @@ -291,27 +279,31 @@ class TextProcessorModule extends BaseModule { * @param {Object} options - Processing options * @param {boolean} [options.smartypants=true] - Whether to apply SmartyPants processing * @param {boolean} [options.hyphenate=true] - Whether to apply hyphenation + * @param {string} [options.hyphenSelector=null] - Selector for hyphen character (e.g., '.hyphenatePipe') * @returns {string} - The processed text */ process(text, options = {}) { const opts = { smartypants: true, hyphenate: true, + hyphenSelector: null, ...options }; - + let result = text; - + // Apply SmartyPants if available and requested - if (opts.smartypants && this.smartyPants) { + if (opts.smartypants && this.smartypantsu) { + result = this.smartypantsu(result, 1); + } else if (opts.smartypants && this.smartyPants) { result = this.smartyPants(result); } - + // Apply hyphenation if available and requested if (opts.hyphenate && this.isHyphenationAvailable()) { - result = this.hyphenate(result); + result = this.hyphenate(result, opts.hyphenSelector); } - + return result; } } diff --git a/public/js/tts-factory-module.js b/public/js/tts-factory-module.js index e95c775..7d0ab10 100644 --- a/public/js/tts-factory-module.js +++ b/public/js/tts-factory-module.js @@ -23,7 +23,10 @@ class TTSFactoryModule extends BaseModule { this.initStatus = {}; this.activeHandler = null; this.ttsAvailable = false; - this.speed = 1; // Default speed + this.speed = 1; // Speech speed multiplier. 1.0 is normal speed. + this.language = 'en-us'; + this.voice = ''; + this.volume = 1.0; // IndexedDB Cache Configuration this.db = null; // Will hold the DB connection @@ -48,6 +51,7 @@ class TTSFactoryModule extends BaseModule { 'stop', 'pause', 'resume', + 'fadeOut', 'getVoices', 'getPreference', 'isSpeaking', @@ -76,22 +80,29 @@ class TTSFactoryModule extends BaseModule { 'registerHandlers', 'initializeHandlerSystem', 'debugLogAllRegisteredModules', - 'debugTTSHandlers' // Added method + 'debugTTSHandlers', + 'emitProcessState', + 'getEffectiveVoiceId', + 'disableAfterCurrentPlayback', + 'getHandlerStatuses', + 'getVoicesForHandler', + 'refreshHandlerStatus' ]); // Listen for kokoro:ready event document.addEventListener('kokoro:ready', (event) => { if (event.detail && typeof event.detail.success === 'boolean') { console.log('TTS Factory: Received kokoro:ready event with success =', event.detail.success); - this.initStatus['kokoro'] = event.detail.success; + this.initStatus['kokoro-tts'] = event.detail.success; // If this is the current active handler or we don't have an active handler yet, // try to activate Kokoro if it's now ready - if ((this.activeHandler === 'kokoro' || !this.activeHandler) && event.detail.success) { - // Only attempt to set active handler if TTS is enabled + if ((this.activeHandler === 'kokoro-tts' || !this.activeHandler) && event.detail.success) { + // Only activate Kokoro when it was explicitly selected. const ttsEnabled = this.getPreference('tts', 'enabled', false); - if (ttsEnabled) { - this.setActiveHandler('kokoro'); + const preferredHandler = this.getPreference('tts', 'preferred_handler', 'none'); + if (ttsEnabled && preferredHandler === 'kokoro-tts') { + this.setActiveHandler('kokoro-tts'); } } @@ -99,6 +110,14 @@ class TTSFactoryModule extends BaseModule { this.updateTTSAvailability(); } }); + + document.addEventListener('tts:speechCompleted', () => { + const persistenceManager = this.getModule('persistence-manager'); + const enabled = persistenceManager?.getPreference('tts', 'enabled', false); + if (!enabled && this.activeHandler) { + this.setActiveHandler('none'); + } + }); // Listen for handler availability changes document.addEventListener('tts:handler:availabilityChanged', (event) => { @@ -198,15 +217,29 @@ class TTSFactoryModule extends BaseModule { } }); + // Listen for speed change events from UI + document.addEventListener('tts:speed:change', (event) => { + if (event.detail && typeof event.detail.speed === 'number') { + this.configure({ speed: event.detail.speed }); + console.log(`TTS Factory: Speed updated to ${this.speed} from UI event`); + } + }); + + document.addEventListener('locale-changed', (event) => { + if (event.detail?.locale) { + this.configure({ language: event.detail.locale }); + } + }); + // Listen for kokoro error events document.addEventListener('kokoro:error', (event) => { console.error('TTS Factory: Received kokoro error event:', event.detail); - if (this.handlers['kokoro']) { - this.initStatus['kokoro'] = false; + if (this.handlers['kokoro-tts']) { + this.initStatus['kokoro-tts'] = false; this.updateTTSAvailability(); - + // If kokoro was our active handler, try fallback - if (this.activeHandler === 'kokoro') { + if (this.activeHandler === 'kokoro-tts') { console.warn('TTS Factory: Kokoro handler failed, falling back'); this.attemptFallbackHandler(); } @@ -367,8 +400,8 @@ class TTSFactoryModule extends BaseModule { // Default settings for first run const defaults = { - 'speed': 0.5, // Default speech rate (0-1 range) - 'preferred_handler': 'kokoro', // Default to Kokoro TTS + 'speed': 1.0, // Default speech speed multiplier + 'preferred_handler': 'none', // Development default: TTS disabled 'enabled': false, // TTS disabled by default 'voice': '', // Empty default - will be selected based on handler 'language': 'en-US', // Default language @@ -387,9 +420,10 @@ class TTSFactoryModule extends BaseModule { } } - // Load speech rate preference + // Load speech rate preference exactly as persisted. Do not migrate or + // rewrite this value on load; the UI must reflect the browser state. const savedSpeed = persistenceManager.getPreference('tts', 'speed'); - if (typeof savedSpeed === 'number') { + if (Number.isFinite(savedSpeed)) { this.speed = savedSpeed; console.log(`TTS Factory: Loaded speed preference: ${this.speed}`); } else { @@ -400,6 +434,9 @@ class TTSFactoryModule extends BaseModule { // Load other preferences we need for initialization const preferredHandler = persistenceManager.getPreference('tts', 'preferred_handler'); console.log(`TTS Factory: Loaded preferred handler: ${preferredHandler || 'none'}`); + this.language = persistenceManager.getPreference('tts', 'language', defaults.language); + this.voice = persistenceManager.getPreference('tts', 'voice', defaults.voice); + this.volume = persistenceManager.getPreference('tts', 'volume', defaults.volume); // We'll handle the preferred handler in initializeHandlerSystem() @@ -469,7 +506,14 @@ class TTSFactoryModule extends BaseModule { if (persistenceManager) { preferredHandler = persistenceManager.getPreference('tts', 'preferred_handler'); + const ttsEnabled = persistenceManager.getPreference('tts', 'enabled', false); console.log(`TTS Factory: Preferred handler from settings: ${preferredHandler || 'none'}`); + if (!ttsEnabled) { + console.log('TTS Factory: TTS toggle is disabled, starting with no active handler'); + this.activeHandler = null; + this.updateTTSAvailability(); + return true; + } } // Special case for 'none' preference @@ -500,8 +544,11 @@ class TTSFactoryModule extends BaseModule { } } - // If we don't have a preferred handler or it's not registered, try fallbacks - return this.attemptFallbackHandler(); + // Default to no TTS. Games or users can explicitly select a provider later. + console.log('TTS Factory: No preferred TTS handler selected, defaulting to none'); + this.activeHandler = null; + this.updateTTSAvailability(); + return true; } /** @@ -509,8 +556,8 @@ class TTSFactoryModule extends BaseModule { * @returns {Promise} - Success status */ async attemptFallbackHandler() { - // Fallback order: Kokoro -> Browser -> None - const fallbackOrder = ['kokoro', 'browser']; + // Providers are opt-in. Keep the baseline as text-only unless explicitly selected. + const fallbackOrder = []; // Try each fallback in order for (const handlerId of fallbackOrder) { @@ -529,8 +576,8 @@ class TTSFactoryModule extends BaseModule { } } - // If all fallbacks failed, update TTS availability - console.warn('TTS Factory: All handlers failed to initialize, TTS will be unavailable'); + // If no explicit provider is selected, update TTS availability and continue. + console.log('TTS Factory: No fallback handler selected, TTS will be unavailable'); this.activeHandler = null; this.updateTTSAvailability(); @@ -603,11 +650,16 @@ class TTSFactoryModule extends BaseModule { persistenceManager.updatePreference('tts', 'preferred_handler', 'none'); } - // Dispatch event + // Dispatch events document.dispatchEvent(new CustomEvent('tts:handler:changed', { detail: { handler: 'none', available: false } })); - + + // Also dispatch tts:engine:change for compatibility with Options UI + document.dispatchEvent(new CustomEvent('tts:engine:change', { + detail: { engine: 'none', handler: 'none', available: false } + })); + this.updateTTSAvailability(); return true; } @@ -629,17 +681,17 @@ class TTSFactoryModule extends BaseModule { console.log(`TTS Factory: Setting active handler to ${id}`); - // Check if the handler is ready (just for logging) + if (this.handlers[id].isReady !== true) { + console.log(`TTS Factory: Initializing handler ${id} before activation`); + await this.initializeHandler(id); + } + + // Check if the handler is ready after initialization const isReady = this.handlers[id].isReady === true; if (!isReady) { console.warn(`TTS Factory: Handler ${id} is not ready - TTS will be considered disabled until ready`); } - // Stop any current speech - if (this.activeHandler && this.handlers[this.activeHandler]) { - this.handlers[this.activeHandler].stop(); - } - // Set the new active handler this.activeHandler = id; @@ -647,17 +699,34 @@ class TTSFactoryModule extends BaseModule { const persistenceManager = this.getModule('persistence-manager'); if (persistenceManager) { persistenceManager.updatePreference('tts', 'preferred_handler', id); + this.voice = persistenceManager.getPreference('tts', 'voice', this.voice || ''); + this.language = persistenceManager.getPreference('tts', 'language', this.language || 'en-us'); + this.speed = persistenceManager.getPreference('tts', 'speed', this.speed || 1.0); + } + + const handler = this.handlers[id]; + if (handler && typeof handler.setVoiceOptions === 'function') { + handler.setVoiceOptions({ + voice: this.voice, + speed: this.speed, + language: this.language + }); } - // Dispatch event + // Dispatch events const event = new CustomEvent('tts:handler:changed', { detail: { handler: id, available: isReady } }); document.dispatchEvent(event); - + + // Also dispatch tts:engine:change for compatibility with Options UI + document.dispatchEvent(new CustomEvent('tts:engine:change', { + detail: { engine: id, handler: id, available: isReady } + })); + // Update overall TTS availability this.updateTTSAvailability(); - + return true; } @@ -725,7 +794,7 @@ class TTSFactoryModule extends BaseModule { const preloadData = await handler.preloadSpeech(text); if (preloadData && preloadData.success) { // Cache the speech - await this.cacheSpeech(hash, preloadData); + await this.cacheSpeech(hash, preloadData.audioData, preloadData.duration); // Speak the preloaded speech return handler.speakPreloaded(preloadData, result => { @@ -790,13 +859,13 @@ class TTSFactoryModule extends BaseModule { // If the handler has a preloadSpeech method, use it if (typeof this.handlers[this.activeHandler].preloadSpeech === 'function') { const preloadData = await this.handlers[this.activeHandler].preloadSpeech(text); - - // Cache the generated speech data - if (preloadData) { - await this.cacheSpeech(hash, preloadData); + + // Cache the generated speech data (extract audioData from result object) + if (preloadData && preloadData.audioData) { + await this.cacheSpeech(hash, preloadData.audioData, preloadData.duration); console.log(`TTS Factory: Added speech to cache for hash ${hash} (size: ${this.currentCacheSize}/${this.maxCacheSizeBytes})`); } - + return preloadData; } else { console.warn(`TTS Factory: Handler ${this.activeHandler} does not support preloading`); @@ -862,6 +931,24 @@ class TTSFactoryModule extends BaseModule { return false; } } + + fadeOut(duration = 1000) { + const handlers = Object.values(this.handlers); + const fades = handlers.map(handler => { + if (!handler) return Promise.resolve(false); + if (typeof handler.fadeOutCurrentAudio === 'function') { + return handler.fadeOutCurrentAudio(duration); + } else if (handler.isSpeaking && typeof handler.stop === 'function') { + return new Promise(resolve => { + setTimeout(() => { + resolve(handler.stop()); + }, duration); + }); + } + return Promise.resolve(false); + }); + return Promise.all(fades); + } /** * Get voices from the active handler @@ -957,41 +1044,170 @@ class TTSFactoryModule extends BaseModule { document.dispatchEvent(event); } } + + disableAfterCurrentPlayback() { + const previousHandler = this.activeHandler; + if (previousHandler) { + const persistenceManager = this.getModule('persistence-manager'); + if (persistenceManager) { + persistenceManager.updatePreference('tts', 'last_enabled_handler', previousHandler); + } + } + + this.activeHandler = null; + console.log('TTS Factory: TTS disabled for future generation; current playback may finish'); + document.dispatchEvent(new CustomEvent('tts:handler:changed', { + detail: { handler: 'none', available: false, previousHandler } + })); + document.dispatchEvent(new CustomEvent('tts:engine:change', { + detail: { engine: 'none', handler: 'none', available: false, previousHandler } + })); + this.updateTTSAvailability(); + return true; + } + + getHandlerStatuses() { + const statuses = [{ + id: 'none', + name: 'None', + ready: true, + active: !this.activeHandler, + message: 'Text-only mode' + }]; + + for (const id in this.handlers) { + const handler = this.handlers[id]; + statuses.push({ + id, + name: typeof handler.getName === 'function' ? handler.getName() : id, + ready: handler.isReady === true, + active: this.activeHandler === id, + message: this.getHandlerStatusMessage(id, handler) + }); + } + + return statuses; + } + + getHandlerStatusMessage(id, handler) { + if (!handler) return 'Not registered'; + if (handler.isReady === true) return 'Ready'; + if (id === 'kokoro-tts') return handler.state === 'INITIALIZING' ? 'Loading model' : 'Not loaded'; + if (handler.apiKey === '') return 'API key missing'; + if (handler.apiKey && handler.isReady !== true) return 'API unavailable or invalid settings'; + return 'Not ready'; + } + + async refreshHandlerStatus(id) { + if (!id || id === 'none') { + this.updateTTSAvailability(); + return true; + } + + if (!this.handlers[id]) { + return false; + } + + const handler = this.handlers[id]; + if (id === 'kokoro-tts') { + this.updateTTSAvailability(); + return handler.isReady === true; + } + + const success = await this.initializeHandler(id); + this.updateTTSAvailability(); + document.dispatchEvent(new CustomEvent('tts:status:updated', { + detail: { statuses: this.getHandlerStatuses() } + })); + return success; + } + + async getVoicesForHandler(handlerId) { + if (!handlerId || handlerId === 'none' || !this.handlers[handlerId]) { + return []; + } + + const handler = this.handlers[handlerId]; + if (handler.isReady !== true && handlerId !== 'kokoro-tts') { + await this.initializeHandler(handlerId); + } + + if (typeof handler.getVoices === 'function') { + return await handler.getVoices() || []; + } + + return Array.isArray(handler.voices) ? handler.voices : []; + } /** * Configure TTS settings for all handlers * @param {Object} options - TTS options - * @param {number} [options.speed] - Normalized speech rate (0-1 range) + * @param {number} [options.speed] - Speech speed multiplier */ configure(options = {}) { if (!options || typeof options !== 'object') { return; } + + const persistenceManager = this.getModule('persistence-manager'); + const voiceOptions = {}; - // Handle speed option if (typeof options.speed === 'number') { - // Save speed setting - this.speed = Math.max(0.1, Math.min(3.0, options.speed)); - - // Save to preferences - const persistenceManager = this.getModule('persistence-manager'); + this.speed = Math.max(0.5, Math.min(2.0, options.speed)); + voiceOptions.speed = this.speed; if (persistenceManager) { persistenceManager.updatePreference('tts', 'speed', this.speed); } - - // Update all handlers - for (const id in this.handlers) { - const handler = this.handlers[id]; - if (handler && typeof handler.setVoiceOptions === 'function') { - handler.setVoiceOptions({ speed: this.speed }); + } + + if (typeof options.voice === 'string' && options.voice) { + this.voice = options.voice; + voiceOptions.voice = options.voice; + if (persistenceManager) { + persistenceManager.updatePreference('tts', 'voice', options.voice); + if (this.activeHandler) { + persistenceManager.updatePreference('tts', `${this.activeHandler}_voice`, options.voice); } } } + + if (typeof options.language === 'string' && options.language) { + this.language = options.language.toLowerCase(); + voiceOptions.language = this.language; + if (persistenceManager) { + persistenceManager.updatePreference('tts', 'language', this.language); + } + } + + if (typeof options.volume === 'number') { + this.volume = Math.max(0, Math.min(1, options.volume)); + voiceOptions.volume = this.volume; + if (persistenceManager) { + persistenceManager.updatePreference('tts', 'volume', this.volume); + } + } + + for (const id in this.handlers) { + const handler = this.handlers[id]; + if (handler && typeof handler.setVoiceOptions === 'function') { + handler.setVoiceOptions(voiceOptions); + } else if (handler && typeof handler.configure === 'function') { + handler.configure(voiceOptions); + } + if (voiceOptions.language && !voiceOptions.voice && handler && typeof handler.selectVoiceForLocale === 'function') { + handler.selectVoiceForLocale(voiceOptions.language); + } + } // Update UI that TTS settings have changed document.dispatchEvent(new CustomEvent('tts:configured', { detail: { - options: { speed: this.speed }, + options: { + speed: this.speed, + voice: this.voice, + language: this.language, + volume: this.volume + }, activeHandler: this.activeHandler } })); @@ -1016,6 +1232,7 @@ class TTSFactoryModule extends BaseModule { const cachedData = await this.getCachedSpeech(hash); if (cachedData) { console.log(`TTS Factory: Using cached speech for hash ${hash} (hits: ${this.cacheHits}, misses: ${this.cacheMisses})`); + this.emitProcessState('playing-ready', { reason: 'tts-cache-hit', hash }); // Move this item to the end of the Map to mark it as most recently used // this.audioCache.delete(hash); // this.audioCache.set(hash, cachedData); @@ -1025,17 +1242,19 @@ class TTSFactoryModule extends BaseModule { // Cache miss - need to generate new speech data this.cacheMisses++; + this.emitProcessState('waiting-generating', { reason: 'tts-cache-miss', hash }); // If the handler has a preloadSpeech method, use it if (typeof this.handlers[this.activeHandler].preloadSpeech === 'function') { const preloadData = await this.handlers[this.activeHandler].preloadSpeech(text); - - // Cache the generated speech data - if (preloadData) { - await this.cacheSpeech(hash, preloadData); + + // Cache the generated speech data (extract audioData from result object) + if (preloadData && preloadData.audioData) { + await this.cacheSpeech(hash, preloadData.audioData, preloadData.duration); console.log(`TTS Factory: Added speech to cache for hash ${hash} (size: ${this.currentCacheSize}/${this.maxCacheSizeBytes})`); + this.emitProcessState('playing-ready', { reason: 'tts-generated', hash }); } - + return preloadData; } else { console.warn(`TTS Factory: Handler ${this.activeHandler} does not support preloading`); @@ -1053,21 +1272,18 @@ class TTSFactoryModule extends BaseModule { * @returns {Promise} - Hash string */ async generateSpeechHash(text) { - // Get the active handler for voice information const handler = this.getActiveHandler(); - - // Include handler ID and voice options in the hash to ensure uniqueness across voices - let voiceInfo = ''; - if (handler && handler.voiceOptions && handler.voiceOptions.voice) { - // Use the voice ID or name to identify the voice - voiceInfo = handler.voiceOptions.voice.id || handler.voiceOptions.voice; - } - - // Also include speed setting in the hash + const provider = this.activeHandler || 'none'; + const voiceInfo = this.getEffectiveVoiceId(handler); const speed = this.speed || 1.0; - - // Create a composite key for hashing - const key = `${text}|${this.activeHandler}|${voiceInfo}|${speed}`; + const language = this.language || 'en-us'; + const key = JSON.stringify({ + provider, + voice: voiceInfo, + speed, + language, + text + }); try { const encoder = new TextEncoder(); @@ -1117,17 +1333,22 @@ class TTSFactoryModule extends BaseModule { console.warn('TTS Factory: Cache not ready, cannot retrieve cached speech'); return null; } - + try { const item = await this._getDBItem(hash); if (item && item.audioData) { console.log(`TTS Factory: Found cached speech for hash ${hash}`); - return item.audioData; + // Return in the same format as handlers' preloadSpeech() method + return { + success: true, + audioData: item.audioData, + duration: item.duration || 0 + }; } } catch (error) { console.error('TTS Factory: Error retrieving cached speech:', error); } - + return null; } @@ -1137,24 +1358,26 @@ class TTSFactoryModule extends BaseModule { * @param {ArrayBuffer} audioData - Audio data to cache * @returns {Promise} - Success status */ - async cacheSpeech(hash, audioData) { + async cacheSpeech(hash, audioData, duration = 0) { if (!this.db || this.cacheStatus !== 'ready') { console.warn('TTS Factory: Cache not ready, cannot cache speech'); return false; } - + if (!audioData) { console.error('TTS Factory: No audio data provided to cache'); return false; } - + + console.log(`TTS Factory: cacheSpeech called with audioData:`, audioData ? `${audioData.byteLength} bytes` : 'UNDEFINED', 'duration:', duration); + try { // Make sure we have room in the cache await this.manageCacheSize(audioData.byteLength); - - // Store the speech data - await this._putDBItem(hash, audioData); - + + // Store the speech data with duration + await this._putDBItem(hash, audioData, duration); + console.log(`TTS Factory: Cached speech for hash ${hash}`); return true; } catch (error) { @@ -1243,6 +1466,20 @@ class TTSFactoryModule extends BaseModule { return false; } } + + getEffectiveVoiceId(handler = this.getActiveHandler()) { + if (!handler) return this.voice || ''; + const voice = handler.voiceOptions?.voice || handler.currentVoice || this.voice || ''; + if (typeof voice === 'string') return voice; + return voice.id || voice.name || ''; + } + + emitProcessState(state, detail = {}) { + console.log(`Process state: ${state}`, detail); + document.dispatchEvent(new CustomEvent('story:process-state', { + detail: { state, ...detail } + })); + } /** * Opens and initializes the IndexedDB database. @@ -1365,9 +1602,10 @@ class TTSFactoryModule extends BaseModule { * Adds or updates an item in the IndexedDB store. * @param {string} hash - The key (hash) of the item to store. * @param {ArrayBuffer} audioData - The audio data to cache. + * @param {number} duration - Duration of the audio in milliseconds. * @returns {Promise} */ - async _putDBItem(hash, audioData) { + async _putDBItem(hash, audioData, duration = 0) { if (!this.db || this.cacheStatus !== 'ready') { console.warn("IndexedDB not ready, cannot put item."); return Promise.reject(new Error("IndexedDB not ready")); @@ -1380,7 +1618,7 @@ class TTSFactoryModule extends BaseModule { return new Promise((resolve, reject) => { const transaction = this.db.transaction([this.storeName], 'readwrite'); const store = transaction.objectStore(this.storeName); - const request = store.put({ hash, audioData, size: audioData.byteLength, lastAccessed: Date.now() }); + const request = store.put({ hash, audioData, size: audioData.byteLength, duration: duration || 0, lastAccessed: Date.now() }); request.onerror = (event) => { console.error("Error putting item into IndexedDB:", event.target.error); @@ -1459,8 +1697,27 @@ class TTSFactoryModule extends BaseModule { if (typeof cursor.value.size === 'number') { totalSize += cursor.value.size; } else { - console.warn(`Item with hash ${cursor.key} missing or invalid size property.`); - // Optionally try to get blob size here, but might be slow + // Old cache entry without size - calculate it + if (cursor.value.audioData && cursor.value.audioData.byteLength) { + const calculatedSize = cursor.value.audioData.byteLength; + totalSize += calculatedSize; + + // Update the entry with the size property + const transaction = this.db.transaction([this.storeName], 'readwrite'); + const store = transaction.objectStore(this.storeName); + const updatedValue = { + ...cursor.value, + size: calculatedSize + }; + store.put(updatedValue); + console.log(`Updated cache entry ${cursor.key} with size: ${calculatedSize} bytes`); + } else { + console.warn(`Item with hash ${cursor.key} missing size and cannot calculate - will be deleted`); + // Delete invalid entry + const transaction = this.db.transaction([this.storeName], 'readwrite'); + const store = transaction.objectStore(this.storeName); + store.delete(cursor.key); + } } cursor.continue(); } else { @@ -1593,8 +1850,11 @@ class TTSFactoryModule extends BaseModule { } } - // If we couldn't initialize the preferred handler, try fallbacks - return this.attemptFallbackHandler(); + // Default to no TTS. Games or users can explicitly select a provider later. + console.log('TTS Factory: No preferred TTS handler selected, defaulting to none'); + this.activeHandler = null; + this.updateTTSAvailability(); + return true; } /** @@ -1602,8 +1862,8 @@ class TTSFactoryModule extends BaseModule { * @returns {Promise} - Success status */ async attemptFallbackHandler() { - // Fallback order: Kokoro -> Browser -> None - const fallbackOrder = ['kokoro', 'browser']; + // Providers are opt-in. Keep the baseline as text-only unless explicitly selected. + const fallbackOrder = []; // Try each fallback in order for (const handlerId of fallbackOrder) { @@ -1622,8 +1882,8 @@ class TTSFactoryModule extends BaseModule { } } - // If all fallbacks failed, update TTS availability - console.warn('TTS Factory: All handlers failed to initialize, TTS will be unavailable'); + // If no explicit provider is selected, update TTS availability and continue. + console.log('TTS Factory: No fallback handler selected, TTS will be unavailable'); this.activeHandler = null; this.updateTTSAvailability(); @@ -1737,4 +1997,4 @@ class TTSFactoryModule extends BaseModule { const TTSFactory = new TTSFactoryModule(); // Export the module -export { TTSFactory }; \ No newline at end of file +export { TTSFactory }; diff --git a/public/js/ui-controller-module.js b/public/js/ui-controller-module.js index 94091a1..96d921f 100644 --- a/public/js/ui-controller-module.js +++ b/public/js/ui-controller-module.js @@ -7,7 +7,7 @@ class UIControllerModule extends BaseModule { // Remove 'tts' from direct dependencies to break circular dependency // UI Controller will access TTS through the Game Loop instead - this.dependencies = ['animation-queue', 'ui-display-handler', 'ui-input-handler', 'ui-effects', 'text-buffer', 'socket-client']; + this.dependencies = ['animation-queue', 'ui-display-handler', 'ui-input-handler', 'ui-effects', 'text-buffer', 'socket-client', 'sentence-queue', 'playback-coordinator']; // References to sub-modules this.displayHandler = null; @@ -43,6 +43,12 @@ class UIControllerModule extends BaseModule { 'applyBookSizing', 'setupEventListeners', 'setupMainUI', + 'bindTopControls', + 'syncTopControls', + 'getStoredTtsPreference', + 'setStoredTtsPreference', + 'sliderValueFromSpeed', + 'speedFromSliderValue', 'initializeTextBuffer', 'showUI', 'hideUI', @@ -103,15 +109,25 @@ class UIControllerModule extends BaseModule { return false; } - this.reportProgress(50, 'Setting up event listeners'); - - // Set up event listeners between components - this.setupEventListeners(); - - this.reportProgress(70, 'Setting up main UI'); + this.reportProgress(50, 'Setting up main UI'); // Initialize main UI container await this.setupMainUI(); + + this.reportProgress(70, 'Setting up event listeners'); + + // Set up event listeners after the display handler has created controls + this.setupEventListeners(); + this.bindTopControls(); + this.syncTopControls(); + requestAnimationFrame(() => { + this.bindTopControls(); + this.syncTopControls(); + }); + setTimeout(() => { + this.bindTopControls(); + this.syncTopControls(); + }, 250); this.reportProgress(80, 'Initializing text buffer'); @@ -146,22 +162,45 @@ class UIControllerModule extends BaseModule { this.applyBookSizing(); // Set up window resize handler - window.addEventListener('resize', () => this.applyBookSizing()); + const handleViewportResize = () => this.applyBookSizing(); + window.addEventListener('resize', handleViewportResize); + if (window.visualViewport) { + window.visualViewport.addEventListener('resize', handleViewportResize); + } + if (window.ResizeObserver && document.body) { + this.bodyResizeObserver = new ResizeObserver(handleViewportResize); + this.bodyResizeObserver.observe(document.body); + } } applyBookSizing() { - // Apply book sizing based on viewport dimensions const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; - const aspectRatio = viewportWidth / viewportHeight; + const viewportAspectRatio = viewportWidth / viewportHeight; + const bookWidth = 2727; + const bookHeight = 1691; + const bookScale = Math.min(viewportWidth / bookWidth, viewportHeight / bookHeight); - document.documentElement.style.setProperty('--viewport-aspect-ratio', aspectRatio); - - const maxBookHeight = viewportHeight * 0.9; - document.documentElement.style.setProperty('--book-height', `${maxBookHeight}px`); - - const bookWidth = maxBookHeight * Math.min(aspectRatio, 1.613); document.documentElement.style.setProperty('--book-width', `${bookWidth}px`); + document.documentElement.style.setProperty('--book-height', `${bookHeight}px`); + document.documentElement.style.setProperty('--book-scale', bookScale); + document.documentElement.style.setProperty('--viewport-aspect-ratio', viewportAspectRatio); + document.documentElement.style.setProperty( + '--viewport-dimension', + viewportWidth / viewportHeight > bookWidth / bookHeight ? 'vw' : 'vh' + ); + + document.dispatchEvent(new CustomEvent('book:scaled', { + detail: { + bookWidth, + bookHeight, + bookScale, + displayWidth: bookWidth * bookScale, + displayHeight: bookHeight * bookScale, + viewportWidth, + viewportHeight + } + })); } setupEventListeners() { @@ -169,62 +208,46 @@ class UIControllerModule extends BaseModule { const saveButton = document.getElementById('save'); const loadButton = document.getElementById('reload'); const restartButton = document.getElementById('rewind'); - const speechToggle = document.getElementById('speech'); const optionsButton = document.getElementById('options'); // Get persistence manager module const persistenceManager = this.getModule('persistence-manager'); + const ttsFactory = this.getModule('tts-factory'); // Set up save button if (saveButton) { - saveButton.addEventListener('click', () => { + saveButton.addEventListener('click', (event) => { + event.preventDefault(); + if (saveButton.getAttribute('disabled') === 'disabled') return; document.dispatchEvent(new CustomEvent('ui:game:save')); }); } // Set up load button if (loadButton) { - loadButton.addEventListener('click', () => { + loadButton.addEventListener('click', (event) => { + event.preventDefault(); + if (loadButton.getAttribute('disabled') === 'disabled') return; document.dispatchEvent(new CustomEvent('ui:game:load')); }); } // Set up restart button if (restartButton) { - restartButton.addEventListener('click', () => { + restartButton.addEventListener('click', (event) => { + event.preventDefault(); + event.__newGameHandled = true; document.dispatchEvent(new CustomEvent('ui:game:restart')); }); } - - // Set up speech toggle button - if (speechToggle) { - // Initialize ttsEnabled from persistence manager - if (persistenceManager) { - const prefs = persistenceManager.getAllPreferences(); - this.ttsEnabled = prefs.tts?.enabled ?? false; - - // Update button state - this.updateButtonStates(); + + this.addEventListener(document, 'click', (event) => { + if (event.target && event.target.closest && event.target.closest('#rewind')) { + event.preventDefault(); + if (event.__newGameHandled) return; + document.dispatchEvent(new CustomEvent('ui:game:restart')); } - - speechToggle.addEventListener('click', () => { - // Toggle TTS state - this.ttsEnabled = !this.ttsEnabled; - - // Update UI - this.updateButtonStates(); - - // Save preference - if (persistenceManager) { - persistenceManager.updatePreference('tts', 'enabled', this.ttsEnabled); - } - - // Notify other components - document.dispatchEvent(new CustomEvent('ui:tts:toggle', { - detail: { enabled: this.ttsEnabled } - })); - }); - } + }); // Set up options button if (optionsButton) { @@ -232,9 +255,31 @@ class UIControllerModule extends BaseModule { document.dispatchEvent(new CustomEvent('ui:options:toggle')); }); } + + this.addEventListener(document, 'ui:command', (event) => { + if (!event.detail || event.detail.moduleId === this.id) return; + this.handleCommand(event.detail); + }); + + this.addEventListener(document, 'click', (event) => { + if (event.target && event.target.closest && event.target.closest('#options-modal, #controls, #player_input, #command_input')) { + return; + } + + const playbackCoordinator = this.getModule('playback-coordinator'); + if (playbackCoordinator && playbackCoordinator.isPlaying) { + this.handleCommand({ type: 'continue', source: 'book-click' }); + } + + if (this.inputHandler && typeof this.inputHandler.focusInput === 'function') { + this.inputHandler.focusInput(); + } + }); // Listen for book events document.addEventListener('book:ready', () => { + this.bindTopControls(); + this.syncTopControls(); this.updateButtonStates({ canSave: true, canLoad: true, @@ -275,8 +320,9 @@ class UIControllerModule extends BaseModule { this.updateButtonStates(); // Ensure persistence is updated - if (persistenceManager) { - persistenceManager.updatePreference('tts', 'enabled', this.ttsEnabled); + const currentPersistenceManager = this.getModule('persistence-manager'); + if (currentPersistenceManager) { + currentPersistenceManager.updatePreference('tts', 'enabled', this.ttsEnabled); } } }); @@ -294,64 +340,26 @@ class UIControllerModule extends BaseModule { this.updateButtonStates(); // Ensure persistence is updated - if (persistenceManager) { - persistenceManager.updatePreference('tts', 'enabled', this.ttsEnabled); + const currentPersistenceManager = this.getModule('persistence-manager'); + if (currentPersistenceManager) { + currentPersistenceManager.updatePreference('tts', 'enabled', this.ttsEnabled); } } }); - - // Set up speed slider in main UI - const speedSlider = document.getElementById('speed'); - const speedReset = document.getElementById('speed_reset'); - - if (speedSlider) { - // Initialize speed from persistence manager - if (persistenceManager) { - const prefs = persistenceManager.getAllPreferences(); - // Get the unified speed value (0-1 range) - const speed = prefs.tts?.speed ?? 0.5; - // Convert to slider range (0-100) - speedSlider.value = Math.round(speed * 100); + + document.addEventListener('preference-updated', (event) => { + const { category, key, value } = event.detail || {}; + if (category !== 'tts') { + return; } - - speedSlider.addEventListener('input', (e) => { - // Convert slider value (0-100) to normalized speed (0-1) - const speed = parseInt(e.target.value) / 100; - - // Scale for different TTS engines - // This value is used for real-time preview only - const rate = this.ttsEnabled ? speed * 2 : 1; - - // Update animation speed - document.dispatchEvent(new CustomEvent('animation:speed:change', { - detail: { speed: rate } - })); - - // Update TTS speed - document.dispatchEvent(new CustomEvent('tts:speed:change', { - detail: { speed: speed } - })); - - // Save preference - if (persistenceManager) { - persistenceManager.updatePreference('tts', 'speed', speed); - } - }); - } - - if (speedReset) { - speedReset.addEventListener('click', () => { - // Reset to default speed (0.5) - if (speedSlider) { - // Default value is 0.5 in normalized form (0-1), - // which is 50 in slider range (0-100) - speedSlider.value = 50; - - // Trigger the input event to update all components - speedSlider.dispatchEvent(new Event('input')); - } - }); - } + + if (key === 'enabled') { + this.ttsEnabled = value === true; + this.syncTopControls(); + } else if (key === 'speed') { + this.syncTopControls(); + } + }); // Listen for speed change events from other components document.addEventListener('tts:speed:change', (event) => { @@ -359,17 +367,157 @@ class UIControllerModule extends BaseModule { // Update the main UI speed slider const speedSlider = document.getElementById('speed'); if (speedSlider) { - // Convert normalized speed (0-1) to slider range (0-100) - speedSlider.value = Math.round(event.detail.speed * 100); + speedSlider.value = this.sliderValueFromSpeed(event.detail.speed); } // Save to persistence manager - if (persistenceManager) { - persistenceManager.updatePreference('tts', 'speed', event.detail.speed); + const currentPersistenceManager = this.getModule('persistence-manager'); + if (currentPersistenceManager) { + currentPersistenceManager.updatePreference('tts', 'speed', event.detail.speed); } } }); } + + sliderValueFromSpeed(speed) { + const value = Number.isFinite(Number(speed)) ? Number(speed) : 1; + return Math.round((Math.max(0.5, Math.min(2.0, value)) * 50) + 50); + } + + speedFromSliderValue(value) { + const sliderValue = Number.isFinite(Number(value)) ? Number(value) : 50; + return Math.max(0.5, Math.min(2.0, (sliderValue - 50) / 50)); + } + + bindTopControls() { + const speechToggle = document.getElementById('speech'); + const speedSlider = document.getElementById('speed'); + const speedReset = document.getElementById('speed_reset'); + + if (speechToggle && speechToggle.dataset.uiControllerBound !== 'true') { + speechToggle.dataset.uiControllerBound = 'true'; + speechToggle.removeAttribute('disabled'); + speechToggle.addEventListener('click', async (event) => { + event.preventDefault(); + event.stopPropagation(); + + const persistenceManager = this.getModule('persistence-manager'); + const ttsFactory = this.getModule('tts-factory'); + const currentEnabled = this.getStoredTtsPreference('enabled', this.ttsEnabled); + const nextEnabled = !currentEnabled; + this.ttsEnabled = nextEnabled; + console.log(`UIController: Top speech toggle set to ${nextEnabled ? 'enabled' : 'disabled'}`); + + this.setStoredTtsPreference('enabled', nextEnabled); + + if (ttsFactory) { + if (nextEnabled) { + const preferredHandler = persistenceManager?.getPreference('tts', 'preferred_handler', 'none') || 'none'; + if (preferredHandler !== 'none') { + await ttsFactory.setActiveHandler(preferredHandler); + } + } else { + await ttsFactory.disableAfterCurrentPlayback(); + } + } + + this.syncTopControls(); + document.dispatchEvent(new CustomEvent('tts:enabled:change', { + detail: { enabled: nextEnabled, source: 'topbar' } + })); + }); + } + + if (speedSlider && speedSlider.dataset.uiControllerBound !== 'true') { + speedSlider.dataset.uiControllerBound = 'true'; + speedSlider.min = speedSlider.min || '50'; + speedSlider.max = speedSlider.max || '150'; + speedSlider.addEventListener('input', (event) => { + const persistenceManager = this.getModule('persistence-manager'); + const speed = this.speedFromSliderValue(event.target.value); + + document.dispatchEvent(new CustomEvent('animation:speed:change', { + detail: { speed: 1 } + })); + + document.dispatchEvent(new CustomEvent('tts:speed:change', { + detail: { speed } + })); + + this.setStoredTtsPreference('speed', speed); + }); + } + + if (speedReset && speedReset.dataset.uiControllerBound !== 'true') { + speedReset.dataset.uiControllerBound = 'true'; + speedReset.addEventListener('click', () => { + const slider = document.getElementById('speed'); + if (slider) { + slider.value = this.sliderValueFromSpeed(1); + slider.dispatchEvent(new Event('input')); + } + }); + } + } + + syncTopControls() { + this.bindTopControls(); + + this.ttsEnabled = this.getStoredTtsPreference('enabled', this.ttsEnabled) === true; + + const speedSlider = document.getElementById('speed'); + if (speedSlider) { + const speed = this.getStoredTtsPreference('speed', 1); + const value = String(this.sliderValueFromSpeed(speed)); + if (speedSlider.value !== value) { + speedSlider.value = value; + } + } + + this.updateButtonStates(); + } + + getStoredTtsPreference(key, defaultValue) { + const persistenceManager = this.getModule('persistence-manager'); + if (persistenceManager && typeof persistenceManager.getPreference === 'function') { + const value = persistenceManager.getPreference('tts', key, undefined); + if (typeof value !== 'undefined' && value !== null) { + return value; + } + } + + try { + const raw = localStorage.getItem('ai-interactive-fiction-preferences'); + if (raw) { + const prefs = JSON.parse(raw); + if (prefs && prefs.tts && Object.prototype.hasOwnProperty.call(prefs.tts, key)) { + return prefs.tts[key]; + } + } + } catch (error) { + console.warn('UIController: Failed to read TTS preference fallback:', error); + } + + return defaultValue; + } + + setStoredTtsPreference(key, value) { + const persistenceManager = this.getModule('persistence-manager'); + if (persistenceManager && typeof persistenceManager.updatePreference === 'function') { + persistenceManager.updatePreference('tts', key, value); + } + + try { + const storageKey = 'ai-interactive-fiction-preferences'; + const raw = localStorage.getItem(storageKey); + const prefs = raw ? JSON.parse(raw) : {}; + prefs.tts = prefs.tts || {}; + prefs.tts[key] = value; + localStorage.setItem(storageKey, JSON.stringify(prefs)); + } catch (error) { + console.warn('UIController: Failed to write TTS preference fallback:', error); + } + } async setupMainUI() { // Ensure all UI components exist @@ -383,36 +531,45 @@ class UIControllerModule extends BaseModule { this.rightPage = document.getElementById('page_right'); this.storyElement = document.getElementById('story'); } + + if (this.inputHandler && typeof this.inputHandler.focusInput === 'function') { + requestAnimationFrame(() => this.inputHandler.focusInput()); + } } initializeTextBuffer() { - // Initialize text buffer handling - if (this.textBuffer) { - console.log('UIController: Setting up text buffer callback'); - this.textBuffer.setOnSentenceReady((text, callback) => { - console.log('UIController: Received sentence from text buffer, displaying'); - - // Use the display handler to show text with proper formatting and TTS - this.displayText(text) - .then(() => { - console.log('UIController: Display of sentence completed, continuing...'); - - // Signal that we're ready to process the next sentence - if (typeof callback === 'function') { - // Use a small timeout to prevent potential stack overflow with many sentences - setTimeout(() => callback(), 10); - } - }) - .catch(error => { - console.error('UIController: Error displaying text:', error); - // Continue anyway to prevent blocking - if (typeof callback === 'function') callback(); - }); - }); - console.log('UIController: Text buffer callback set up'); - } else { - console.warn('UIController: Text buffer module not found'); + // Connect SentenceQueue to UIDisplayHandler + const sentenceQueue = this.getModule('sentence-queue'); + const displayHandler = this.getModule('ui-display-handler'); + + if (!sentenceQueue || !displayHandler) { + console.error('UIController: Required modules not found (sentence-queue or ui-display-handler)'); + return; } + + console.log('UIController: Setting up SentenceQueue → UIDisplayHandler pipeline'); + + // Set up callback for when sentences are ready to display + sentenceQueue.setOnSentenceReady(async (sentence, callback) => { + try { + console.log(`UIController: Rendering sentence ${sentence.id}`); + await displayHandler.renderSentence(sentence); + console.log(`UIController: Sentence ${sentence.id} rendered successfully`); + + // Signal completion to process next sentence + if (typeof callback === 'function') { + callback(); + } + } catch (error) { + console.error('UIController: Error rendering sentence:', error); + // Still proceed to prevent blocking + if (typeof callback === 'function') { + callback(); + } + } + }); + + console.log('UIController: SentenceQueue pipeline configured'); } handleCommand(command) { @@ -425,8 +582,13 @@ class UIControllerModule extends BaseModule { this.effects.processCommand(command); break; case 'continue': - if (this.animationQueue) { - this.animationQueue.fastForward(); + { + const playbackCoordinator = this.getModule('playback-coordinator'); + if (playbackCoordinator && playbackCoordinator.isPlaying) { + playbackCoordinator.fastForward(); + } else if (this.animationQueue) { + this.animationQueue.fastForward(); + } } break; case 'input': @@ -473,7 +635,7 @@ class UIControllerModule extends BaseModule { const speechToggle = document.getElementById('speech'); // Update save button state - if (saveButton) { + if (saveButton && typeof canSave === 'boolean') { if (canSave) { saveButton.removeAttribute('disabled'); } else { @@ -482,7 +644,7 @@ class UIControllerModule extends BaseModule { } // Update load button state - if (loadButton) { + if (loadButton && typeof canLoad === 'boolean') { if (canLoad) { loadButton.removeAttribute('disabled'); } else { @@ -491,35 +653,28 @@ class UIControllerModule extends BaseModule { } // Update restart button state - if (restartButton) { + if (restartButton && typeof canRestart === 'boolean') { if (canRestart) { restartButton.removeAttribute('disabled'); } else { restartButton.setAttribute('disabled', 'disabled'); } } + + document.body.dataset.gameRunning = state.gameStarted ? 'true' : 'false'; // Update speech toggle button state if (speechToggle) { // Update the button appearance based on TTS state using existing styles - if (!this.ttsAvailable) { - // TTS is not available, disable the button - speechToggle.setAttribute('disabled', 'disabled'); - speechToggle.title = 'Text-to-speech is not available'; + speechToggle.removeAttribute('disabled'); + if (this.ttsEnabled) { + speechToggle.style.fontWeight = 'bold'; + speechToggle.style.color = '#000'; + speechToggle.title = this.ttsAvailable ? 'Disable speech' : 'Speech enabled, selected provider is not ready'; } else { - // TTS is available, remove disabled attribute - speechToggle.removeAttribute('disabled'); - - // Update based on whether TTS is enabled - if (this.ttsEnabled) { - speechToggle.style.fontWeight = 'bold'; - speechToggle.style.color = '#000'; - speechToggle.title = 'Disable speech'; - } else { - speechToggle.style.fontWeight = 'normal'; - speechToggle.style.color = '#999'; - speechToggle.title = 'Enable speech'; - } + speechToggle.style.fontWeight = 'normal'; + speechToggle.style.color = '#999'; + speechToggle.title = 'Enable speech'; } } } diff --git a/public/js/ui-display-handler-module.js b/public/js/ui-display-handler-module.js index 69bbc5c..51d9653 100644 --- a/public/js/ui-display-handler-module.js +++ b/public/js/ui-display-handler-module.js @@ -9,13 +9,17 @@ class UIDisplayHandlerModule extends BaseModule { super('ui-display-handler', 'UI Display Handler'); // Module dependencies - this.dependencies = ['paragraph-layout', 'layout-renderer', 'animation-queue']; + this.dependencies = ['layout-renderer', 'playback-coordinator']; // DOM elements this.container = null; this.pageLeft = null; this.pageRight = null; this.paragraphContainer = null; + this.renderedItems = []; + this.resizeTimer = null; + this.storyResizeObserver = null; + this.lastStoryMetrics = null; // Resources to preload this.cssPath = '/css/style.css'; @@ -28,6 +32,12 @@ class UIDisplayHandlerModule extends BaseModule { this.bindMethods([ 'initializeContainers', 'displayText', + 'renderSentence', + 'renderHeading', + 'handleDeferredMediaBlock', + 'rerenderStory', + 'clear', + 'scheduleRerender', 'measureText', 'loadCSS', 'showChoices', @@ -49,9 +59,8 @@ class UIDisplayHandlerModule extends BaseModule { this.reportProgress(30, "Getting module dependencies"); // Get references to required modules using parent's getModule method - this.paragraphLayout = this.getModule('paragraph-layout'); this.layoutRenderer = this.getModule('layout-renderer'); - this.animationQueue = this.getModule('animation-queue'); + this.playbackCoordinator = this.getModule('playback-coordinator'); this.reportProgress(50, "Initializing display containers"); @@ -61,6 +70,40 @@ class UIDisplayHandlerModule extends BaseModule { this.reportProgress(70, "Setting up typography"); this.reportProgress(90, "Setting up event listeners"); + this.addEventListener(document, 'book:resized', () => { + this.scheduleRerender(); + }); + + if (window.ResizeObserver && this.paragraphContainer) { + this.storyResizeObserver = new ResizeObserver((entries) => { + const entry = entries[0]; + if (!entry) { + return; + } + + const computedStyle = window.getComputedStyle(this.paragraphContainer); + const metrics = { + width: Math.round(entry.contentRect.width), + fontSize: computedStyle.fontSize, + lineHeight: computedStyle.lineHeight + }; + + if (!this.lastStoryMetrics) { + this.lastStoryMetrics = metrics; + return; + } + + const changed = metrics.width !== this.lastStoryMetrics.width || + metrics.fontSize !== this.lastStoryMetrics.fontSize || + metrics.lineHeight !== this.lastStoryMetrics.lineHeight; + + this.lastStoryMetrics = metrics; + if (changed) { + this.scheduleRerender(); + } + }); + this.storyResizeObserver.observe(this.paragraphContainer); + } this.reportProgress(100, "UI Display Handler ready"); return true; @@ -70,6 +113,11 @@ class UIDisplayHandlerModule extends BaseModule { } } + scheduleRerender() { + clearTimeout(this.resizeTimer); + this.resizeTimer = setTimeout(() => this.rerenderStory(), 80); + } + /** * Load CSS file asynchronously and wait for it to be applied @@ -160,9 +208,9 @@ class UIDisplayHandlerModule extends BaseModule { controls.id = 'controls'; controls.className = 'buttons'; controls.innerHTML = ` - speech - speed* - restart + speech + speed* + new game save load options @@ -220,6 +268,13 @@ class UIDisplayHandlerModule extends BaseModule { this.container.className = 'container'; this.pageRight.appendChild(this.container); } + + if (!document.getElementById('start_prompt')) { + const startPrompt = document.createElement('div'); + startPrompt.id = 'start_prompt'; + startPrompt.textContent = 'Klick on new game or load to start the game'; + this.pageRight.appendChild(startPrompt); + } // Create paragraph container inside story container this.paragraphContainer = document.getElementById('paragraphs'); @@ -272,33 +327,194 @@ class UIDisplayHandlerModule extends BaseModule { /** - * Display text in the UI + * Display text in the UI (backward compatibility) + * Note: Text should flow through SentenceQueue instead * @param {string} text - Text to display * @param {Object} options - Display options * @returns {Promise} - Promise resolving to the displayed paragraph element */ displayText(text, options = {}) { if (!text) return Promise.resolve(null); - - return new Promise((resolve) => { - // Generate a unique ID for this paragraph - const paragraphId = `p-${Date.now()}-${this.currentParagraphId++}`; - - // Add to pending paragraphs queue - this.pendingParagraphs.push({ - id: paragraphId, - text, - options, - resolve + + // For backward compatibility, delegate to sentence queue + console.warn('UIDisplayHandler.displayText called directly, text should flow through SentenceQueue'); + + const sentenceQueue = this.getModule('sentence-queue'); + if (sentenceQueue) { + return new Promise(resolve => { + sentenceQueue.addSentence(text, () => resolve(null)); }); - - // If this is the only paragraph, process it immediately - if (this.pendingParagraphs.length === 1) { - this.processNextParagraph(); - } else { - console.log(`UIDisplayHandler: Queued paragraph (${this.pendingParagraphs.length} total)`); + } + + return Promise.resolve(null); + } + + /** + * Render a prepared sentence to the display + * @param {Object} sentence - Prepared sentence object from SentenceQueue + * @returns {Promise} - Promise resolving to the paragraph element + */ + async renderSentence(sentence) { + if (!sentence || !sentence.layout) { + if (sentence && sentence.kind === 'heading') { + return this.renderHeading(sentence); } + if (sentence && (sentence.kind === 'image' || sentence.kind === 'music')) { + return this.handleDeferredMediaBlock(sentence); + } + console.error('UIDisplayHandler: Invalid sentence object'); + return null; + } + + try { + // Render DOM from layout data + const paragraphElement = this.layoutRenderer.renderParagraph( + sentence.layout, + { id: sentence.id } + ); + + // Append to container + if (this.paragraphContainer) { + this.paragraphContainer.appendChild(paragraphElement); + if (typeof this.layoutRenderer.adjustJustification === 'function') { + this.layoutRenderer.adjustJustification(paragraphElement); + } + } else { + console.error('UIDisplayHandler: Paragraph container not found'); + return null; + } + + // Store element reference in sentence + sentence.element = paragraphElement; + this.renderedItems.push({ + type: 'paragraph', + id: sentence.id, + text: sentence.text, + metadata: { + layoutText: sentence.layout?.sourceLayoutText || sentence.text, + cueMarkers: sentence.cueMarkers || [], + role: sentence.role || 'body', + isFirstParagraphInChapter: sentence.isFirstParagraphInChapter, + dropCap: sentence.dropCap, + addTopSpace: sentence.addTopSpace, + paragraphIndex: sentence.paragraphIndex + } + }); + + // Start coordinated playback (animation + TTS) + await this.playbackCoordinator.play(sentence); + + // Scroll to bottom + if (this.pageRight) { + this.pageRight.scrollTop = this.pageRight.scrollHeight; + } + + // Call completion callback + if (sentence.onComplete) { + sentence.onComplete(); + } + + return paragraphElement; + + } catch (error) { + console.error('UIDisplayHandler: Error rendering sentence:', error); + throw error; + } + } + + async renderHeading(sentence) { + const heading = document.createElement('p'); + heading.id = sentence.id; + heading.className = 'story-chapter-heading'; + heading.innerHTML = sentence.metadata?.layoutText || sentence.text; + this.renderedItems.push({ + type: 'heading', + id: sentence.id, + text: sentence.text, + layoutText: sentence.metadata?.layoutText || sentence.text }); + + if (this.paragraphContainer) { + this.paragraphContainer.appendChild(heading); + } + + if (sentence.onComplete) { + sentence.onComplete(); + } + + return heading; + } + + async rerenderStory() { + if (!this.paragraphContainer || this.renderedItems.length === 0) return; + + const sentenceQueue = this.getModule('sentence-queue'); + if (!sentenceQueue || typeof sentenceQueue.prepareLayout !== 'function') return; + + console.log('UIDisplayHandler: Re-typesetting story after page resize'); + const scrollTop = this.pageRight ? this.pageRight.scrollTop : 0; + this.paragraphContainer.innerHTML = ''; + + for (const item of this.renderedItems) { + if (item.type === 'heading') { + const heading = document.createElement('p'); + heading.id = item.id; + heading.className = 'story-chapter-heading'; + heading.innerHTML = item.layoutText || item.text; + this.paragraphContainer.appendChild(heading); + continue; + } + + if (item.type !== 'paragraph') continue; + + const layout = await sentenceQueue.prepareLayout(item.text, item.metadata || {}); + const paragraph = this.layoutRenderer.renderParagraph(layout, { id: item.id }); + paragraph.querySelectorAll('.word').forEach(word => { + word.style.transition = 'none'; + word.style.visibility = 'visible'; + word.style.opacity = '1'; + word.style.transform = 'translateY(0)'; + }); + this.paragraphContainer.appendChild(paragraph); + } + + if (this.pageRight) { + this.pageRight.scrollTop = scrollTop; + } + } + + async handleDeferredMediaBlock(sentence) { + document.dispatchEvent(new CustomEvent('story:media-block', { + detail: { + id: sentence.id, + type: sentence.kind, + ...(sentence.metadata || {}) + } + })); + + if (sentence.kind === 'music') { + const leadInSeconds = Number(sentence.metadata?.leadInSeconds || sentence.metadata?.leadIn || 0); + if (leadInSeconds > 0) { + console.log(`UIDisplayHandler: Waiting ${leadInSeconds}s before continuing after music block`); + await new Promise(resolve => setTimeout(resolve, leadInSeconds * 1000)); + } + } + + if (sentence.onComplete) { + sentence.onComplete(); + } + + return null; + } + + clear() { + if (this.container) { + this.container.innerHTML = ''; + this.paragraphContainer = document.createElement('div'); + this.paragraphContainer.id = 'paragraphs'; + this.container.appendChild(this.paragraphContainer); + } + this.renderedItems = []; } /** @@ -376,3 +592,11 @@ const uiDisplayHandler = new UIDisplayHandlerModule(); // Export the module export { uiDisplayHandler as UIDisplayHandler }; + +// Register with the module registry +if (window.moduleRegistry) { + window.moduleRegistry.register(uiDisplayHandler); +} + +// Keep a reference in window for loader system +window.UIDisplayHandler = uiDisplayHandler; diff --git a/public/js/ui-input-handler-module.js b/public/js/ui-input-handler-module.js index b661c14..8d05308 100644 --- a/public/js/ui-input-handler-module.js +++ b/public/js/ui-input-handler-module.js @@ -5,7 +5,7 @@ class UIInputHandlerModule extends BaseModule { super('ui-input-handler', 'UI Input Handler'); // Explicitly declare ui-display-handler as a dependency - this.dependencies = ['ui-display-handler']; + this.dependencies = ['ui-display-handler', 'markup-parser', 'playback-coordinator']; // Input elements this.inputArea = null; @@ -28,7 +28,10 @@ class UIInputHandlerModule extends BaseModule { 'handleKeyboardInput', 'submitCommand', 'addToHistory', - 'resetCursorPosition' + 'formatCommandHistory', + 'resetCursorPosition', + 'focusInput', + 'setProcessState' ]); console.log('UIInputHandler: Constructor initialized'); @@ -53,6 +56,9 @@ class UIInputHandlerModule extends BaseModule { this.reportProgress(60, 'Setting up input elements'); this.setupInputElements(); + this.addEventListener(document, 'story:process-state', (event) => { + this.setProcessState(event.detail?.state || 'ready', event.detail || {}); + }); this.reportProgress(100, 'UI Input Handler ready'); return true; @@ -67,14 +73,47 @@ class UIInputHandlerModule extends BaseModule { * @param {KeyboardEvent} event - The keyboard event */ handleKeyboardInput(event) { - // Handle global keyboard shortcuts here - // This is different from the input field's specific key handling - - // For example: Escape key to blur the input + if (!this.playerInput) return; + if (event.key === 'Escape') { - if (document.activeElement === this.playerInput) { - this.playerInput.blur(); + this.playerInput.blur(); + return; + } + + const optionsModal = document.getElementById('options-modal'); + if (optionsModal && optionsModal.style.display !== 'none') { + return; + } + + if (event.key === ' ' && this.isPlaybackActive()) { + document.dispatchEvent(new CustomEvent('ui:command', { + detail: { type: 'continue', source: 'spacebar' } + })); + } + + if (event.key === 'Enter' && !event.shiftKey) { + event.preventDefault(); + if (document.body.dataset.gameRunning !== 'true') { + return; } + this.submitCommand(); + return; + } + + if (event.ctrlKey || event.metaKey || event.altKey) { + return; + } + + if (event.key.length === 1 && document.activeElement !== this.playerInput) { + if (document.body.dataset.gameRunning !== 'true') { + return; + } + event.preventDefault(); + this.focusInput(); + const start = this.playerInput.selectionStart ?? this.playerInput.value.length; + const end = this.playerInput.selectionEnd ?? start; + this.playerInput.setRangeText(event.key, start, end, 'end'); + this.playerInput.dispatchEvent(new Event('input', { bubbles: true })); } } @@ -144,8 +183,8 @@ class UIInputHandlerModule extends BaseModule { playerInput.style.whiteSpace = 'pre-wrap'; inputWrapper.appendChild(playerInput); - this.playerInput = playerInput; } + this.playerInput = playerInput; // Create the cursor if needed let cursor = document.getElementById('cursor'); @@ -153,8 +192,8 @@ class UIInputHandlerModule extends BaseModule { cursor = document.createElement('span'); cursor.id = 'cursor'; inputWrapper.appendChild(cursor); - this.cursor = cursor; } + this.cursor = cursor; // Set up input event handlers if (playerInput) { @@ -171,16 +210,94 @@ class UIInputHandlerModule extends BaseModule { // Position the cursor if (playerInput && cursor) { this.positionCursor(playerInput, cursor); - - // Focus the input to let user start typing immediately - setTimeout(() => { - playerInput.focus(); - }, 100); + this.setProcessState('ready', { reason: 'input-initialized' }); + this.focusInput(); + requestAnimationFrame(() => this.focusInput()); + setTimeout(() => this.focusInput(), 250); } console.log('UIInputHandler: Input elements setup complete'); } + focusInput() { + if (document.body.dataset.gameRunning !== 'true') { + return; + } + + if (!this.playerInput) { + this.playerInput = document.getElementById('player_input'); + } + + if (this.playerInput && !this.playerInput.disabled) { + this.playerInput.focus(); + } + } + + setProcessState(state, detail = {}) { + const knownStates = [ + 'ready', + 'command-waiting', + 'waiting-generating', + 'playing-generating', + 'playing-ready' + ]; + const nextState = knownStates.includes(state) ? state : 'ready'; + + this.applyMouseCursor(nextState); + + if (this.cursor) { + knownStates.forEach(value => this.cursor.classList.remove(`cursor-${value}`)); + this.cursor.classList.add(`cursor-${nextState}`); + this.cursor.dataset.processState = nextState; + this.cursor.setAttribute('aria-label', 'text input cursor'); + this.cursor.innerHTML = ''; + } + + console.log(`Cursor process state: ${nextState}`, detail); + } + + applyMouseCursor(state) { + const root = document.documentElement; + if (!root) { + return; + } + + root.dataset.processState = state; + const cursor = this.getMouseCursor(state); + if (cursor) { + root.style.setProperty('--process-cursor', cursor); + } else { + root.style.removeProperty('--process-cursor'); + } + } + + getMouseCursor(state) { + if (state === 'ready') { + return ''; + } + + const svg = this.getMouseCursorSvg(state); + const fallback = state === 'command-waiting' ? 'wait' : 'progress'; + return `url("${this.toCursorDataUrl(svg)}") 12 12, ${fallback}`; + } + + getMouseCursorSvg(state) { + const stroke = '#222222'; + const common = `xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"`; + const icons = { + 'command-waiting': ``, + 'waiting-generating': ``, + 'playing-generating': ``, + 'playing-ready': `` + }; + + return icons[state] || icons['waiting-generating']; + } + + toCursorDataUrl(svg) { + return `data:image/svg+xml,${encodeURIComponent(svg.replace(/\s+/g, ' ').trim())}`; + } + /** * Handle player input changes * @param {Event} e - Input event @@ -271,7 +388,7 @@ class UIInputHandlerModule extends BaseModule { if (this.commandHistoryElement && this.commandHistoryElement.appendChild) { const historyItem = document.createElement('div'); historyItem.className = 'history-item'; - historyItem.textContent = `> ${command}`; + historyItem.innerHTML = `> ${this.formatCommandHistory(command)}`; this.commandHistoryElement.appendChild(historyItem); // Limit visible history items @@ -284,6 +401,23 @@ class UIInputHandlerModule extends BaseModule { } } + formatCommandHistory(command) { + const parser = this.getModule('markup-parser') || window.MarkupParser; + if (parser && typeof parser.markdownToHtml === 'function') { + return parser.markdownToHtml(command); + } + + return String(command) + .replace(/&/g, '&') + .replace(//g, '>'); + } + + isPlaybackActive() { + const playbackCoordinator = this.getModule('playback-coordinator') || window.PlaybackCoordinator; + return Boolean(playbackCoordinator && playbackCoordinator.isPlaying); + } + /** * Resets the cursor position to the start. */ diff --git a/public/kokoro-loader.html b/public/kokoro-loader.html index 7f9c7aa..ec2c3da 100644 --- a/public/kokoro-loader.html +++ b/public/kokoro-loader.html @@ -185,15 +185,21 @@ window.KokoroLoader.instance.generate(data.text, { voice: data.voice, speed: data.speed }) .then(result => { log(`Generation successful for request ${data.id}`, 'success'); - - // Convert the result to a proper format for the parent window - const audio = new Uint8Array(result.buffer); - + + // Kokoro returns a Uint8Array directly, not an object with .buffer + const audio = result instanceof Uint8Array ? result : new Uint8Array(result.buffer || result); + log(`Audio data: ${audio.length} bytes (Uint8Array)`); + + // Create a copy of the underlying ArrayBuffer + const bufferCopy = audio.buffer.slice(0); + log(`Sending audio buffer: ${bufferCopy.byteLength} bytes`); + window.parent.postMessage({ type: 'kokoro-generated', id: data.id, success: true, - result: { buffer: audio.buffer } + result: { buffer: bufferCopy }, + duration: 0 // Duration not provided by Kokoro, will be estimated }, '*'); }) .catch(error => { diff --git a/public/music/Dark Jodler.mp3 b/public/music/Dark Jodler.mp3 new file mode 100644 index 0000000..b371cf8 Binary files /dev/null and b/public/music/Dark Jodler.mp3 differ diff --git a/public/music/Kaiserpunk Jodler.mp3 b/public/music/Kaiserpunk Jodler.mp3 new file mode 100644 index 0000000..faf0a7c Binary files /dev/null and b/public/music/Kaiserpunk Jodler.mp3 differ diff --git a/public/music/Kaiserpunk Waltz.mp3 b/public/music/Kaiserpunk Waltz.mp3 new file mode 100644 index 0000000..ec14b25 Binary files /dev/null and b/public/music/Kaiserpunk Waltz.mp3 differ diff --git a/public/music/README.md b/public/music/README.md new file mode 100644 index 0000000..f14ef1f --- /dev/null +++ b/public/music/README.md @@ -0,0 +1,34 @@ +Music +===== + +Story music paths resolve relative to this directory. + +Block music markup: + +```text +::music[crossfade, loop, lead=4](track-name.ogg) +``` + +Inline music cue: + +```text +The candles gutter. {{music:cut:danger.ogg}} Something moves upstairs. +``` + +Supported modes: + +- `queue`: start the new track after the current track ends. +- `crossfade`: fade from the current track into the new track. +- `cut`: stop the current track and start the new track immediately. + +Supported playback flags: + +- `loop`: repeat the track. +- `once`: play the track one time. +- `lead=`: for block music, let the music play alone for this many seconds before the next text/TTS paragraph starts. + +Music volume is controlled by master volume and music volume in the options menu. While TTS is playing, music is ducked to 70% of its configured volume and restored when TTS playback is idle. + +Browsers require a user interaction before audio can play, so music should begin after `new game` or `load`, not during passive page load. + +Document third-party source and license information here or next to the file. diff --git a/public/music/Versuch Quintett.mp3 b/public/music/Versuch Quintett.mp3 new file mode 100644 index 0000000..c1f7d6c Binary files /dev/null and b/public/music/Versuch Quintett.mp3 differ diff --git a/public/sounds/README.md b/public/sounds/README.md new file mode 100644 index 0000000..a5ffe0f --- /dev/null +++ b/public/sounds/README.md @@ -0,0 +1,22 @@ +Sound Effects +============= + +Story sound effect paths resolve relative to this directory. + +Use inline sound effect markup inside narrative text: + +```text +The old door opens {{sfx:squeaky-door.ogg}} into the dark. +``` + +The marker is removed from displayed text and from TTS input. It is kept as a timed media cue, preloaded by the client, and played when the text animation reaches that cue position. + +Supported browser-friendly formats are recommended: `.ogg`, `.mp3`, and `.wav`. Keep files small enough for responsive preload. + +Sound effect loudness is controlled by the master volume and sound effects volume sliders in the options menu. + +Document third-party source and license information here or next to the file. + +Current test asset: + +- `squeaky-door.ogg`: Wikimedia Commons, "Squeaky door.ogg", sourced from PDSounds and marked public domain. diff --git a/public/sounds/squeaky-door.ogg b/public/sounds/squeaky-door.ogg new file mode 100644 index 0000000..11779c6 Binary files /dev/null and b/public/sounds/squeaky-door.ogg differ diff --git a/references/STORY_MARKUP.md b/references/STORY_MARKUP.md new file mode 100644 index 0000000..8e85aea --- /dev/null +++ b/references/STORY_MARKUP.md @@ -0,0 +1,94 @@ +# Story Markup + +The story stream supports plain paragraphs plus a small set of structural and media cues. + +## Inline Text + +Markdown emphasis is supported inside paragraphs and headings: + +- `*italic*` or `_italic_` +- `**bold**` or `__bold__` +- `***bold italic***` or `___bold italic___` + +SmartyPants processing still runs after markup parsing, so straight quotes, apostrophes, and dashes are converted typographically before layout and hyphenation. + +## Paragraphs And Sections + +Plain narrative is rendered paragraph by paragraph. Each ordinary paragraph uses the normal first-line indent, and adjacent paragraphs are not separated by a blank line. + +Use an explicit section marker when the next paragraph should begin a new text block: + +```text +::section + +The first paragraph of the section begins here. + +The second paragraph begins here. +``` + +- The first paragraph after `::section` is not horizontally indented. +- It gets one line of vertical separation from previous content. +- Following paragraphs use the normal first-line indent. + +Paragraphs are separated by one or more blank lines. Single newlines inside a paragraph are normalized to spaces. + +## Chapters + +Use: + +```text +::chapter[The House on the Hill] + +The first paragraph begins here. + +The second paragraph begins here. +``` + +The chapter heading is rendered in the same font and size as block text, centered and italic. The first following paragraph is unindented and marked for a three-line drop cap. Following paragraphs are indented normally. + +## Images + +Image blocks are parsed, queued, and emitted as future media blocks, but image rendering is not implemented yet. + +```text +::image[widescreen](mansion-rain.jpg) +::image[portrait](portrait-letter.jpg) +``` + +`widescreen` means 100% page width and 50% page height. `portrait` means 100% page width and 100% page height. Filenames are relative to the future image directory. + +## Sound Effects + +Sound effects can appear inside regular paragraphs: + +```text +The door opens {{sfx:door-creak.ogg}} and the hall exhales. +``` + +The marker is removed from displayed text and TTS text. It is preserved as a timed cue and emitted when the word animation reaches the marker position. Actual preload and playback are not implemented yet. + +The animation engine emits `story:media-cue` with `type: "sfx"`, `filename`, `wordIndex`, and `delay`. + +## Music + +Music can be queued as a block: + +```text +::music[crossfade, loop, lead=4](rain-theme.ogg) +``` + +It can also be placed inline: + +```text +The candles gutter. {{music:cut:danger.ogg}} Something moves upstairs. +``` + +Supported modes are: + +- `queue`: play after the current track finishes. +- `crossfade`: crossfade from the current track to the new one. +- `cut`: stop the current track and start the new one immediately. +- `loop` or `once`: whether the track repeats. +- `lead=`: how long the music plays alone before the next text/TTS paragraph starts. + +Inline music markers emit `story:media-cue`. Block music directives emit `story:media-block`; block directives also delay the following paragraph when `lead` is set. diff --git a/scripts/check-node-version.js b/scripts/check-node-version.js new file mode 100644 index 0000000..36cbb0d --- /dev/null +++ b/scripts/check-node-version.js @@ -0,0 +1,11 @@ +const minimum = { major: 18, minor: 17 }; +const [major, minor] = process.versions.node.split('.').map(Number); + +if (major < minimum.major || (major === minimum.major && minor < minimum.minor)) { + console.error( + `Node.js ${minimum.major}.${minimum.minor}+ is required. ` + + `Current runtime is ${process.versions.node}.` + ); + console.error('Use Node 22 LTS for this project, then rerun the command.'); + process.exit(1); +} diff --git a/src/server.ts b/src/server.ts index 57c1a2e..42cfeb5 100644 --- a/src/server.ts +++ b/src/server.ts @@ -24,36 +24,120 @@ const DEFAULT_PORT = 3001; const PORT = process.env.PORT ? parseInt(process.env.PORT) : DEFAULT_PORT; const PORT_RANGE = 10; // Try up to 10 ports starting from the default -// Serve static files from the public directory -app.use(express.static(path.join(__dirname, '../public'))); +// Serve static files from the public directory. During local development the +// browser must not keep stale ES modules, otherwise UI fixes appear to do +// nothing until a hard cache clear. +app.use(express.static(path.join(__dirname, '../public'), { + etag: false, + lastModified: false, + setHeaders: (res) => { + res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); + res.setHeader('Pragma', 'no-cache'); + res.setHeader('Expires', '0'); + } +})); // Set up game sessions -const gameSessions = new Map(); +const gameSessions = new Map(); + +function normalizeSaveSlot(slot: unknown): number { + const value = Number(slot); + return Number.isInteger(value) && value > 0 ? value : 1; +} + +async function startDemoGameForSocket(socket: any): Promise { + const gameRunner = new GameRunner(); + const worldFile = process.env.DEFAULT_WORLD_FILE || './data/worlds/example_world.yml'; + + await gameRunner.initialize(worldFile); + gameSessions.set(socket.id, gameRunner); + + const gameState = gameRunner.getGameState(); + socket.emit('gameIntroduction', { + introduction: gameState.world.introduction, + initialRoomDescription: gameRunner.getCurrentRoomDescription(), + currentRoomId: gameState.currentRoomId + }); + + return gameRunner; +} + +async function handleGameApi(socket: any, method: string, args: unknown[] = []) { + const saveGames: Map = socket.data.saveGames || new Map(); + socket.data.saveGames = saveGames; + + switch (method) { + case 'newGame': + case 'newGame()': + await startDemoGameForSocket(socket); + return { success: true, result: true, running: true, canLoad: saveGames.size > 0 }; + + case 'loadGame': + case 'loadGame()': { + const slot = normalizeSaveSlot(args[0]); + if (!saveGames.has(slot)) { + return { success: false, error: 'missing_save', result: false }; + } + await startDemoGameForSocket(socket); + socket.emit('gameLoaded', { slot }); + return { success: true, result: true, running: true, slot }; + } + + case 'saveGame': + case 'saveGame()': { + const gameRunner = gameSessions.get(socket.id); + if (!gameRunner) { + return { success: false, error: 'game_not_running', result: false }; + } + const slot = normalizeSaveSlot(args[0]); + saveGames.set(slot, gameRunner.getGameState()); + socket.emit('gameSaved', { slot }); + return { success: true, result: true, slot }; + } + + case 'hasSaveGame': + case 'hasSaveGame()': { + const slot = normalizeSaveSlot(args[0]); + return { success: true, result: saveGames.has(slot), slot }; + } + + case 'getSaveGames': + case 'getSaveGames()': + return { success: true, result: Array.from(saveGames.keys()).sort((a, b) => a - b) }; + + case 'isGameRunning': + case 'isGameRunning()': + return { success: true, result: gameSessions.has(socket.id) }; + + default: + return { success: false, error: `unknown_method:${method}` }; + } +} // Handle socket connections io.on('connection', (socket) => { - console.log(`New client connected: ${socket.id}`); - - // Start a new game - socket.on('startGame', async () => { - try { - // Initialize game runner - const gameRunner = new GameRunner(); - const worldFile = process.env.DEFAULT_WORLD_FILE || './data/worlds/example_world.yml'; - - // Initialize the game - await gameRunner.initialize(worldFile); - - // Store game session - gameSessions.set(socket.id, gameRunner); - - // Send introduction to client - const gameState = gameRunner.getGameState(); - socket.emit('gameIntroduction', { - introduction: gameState.world.introduction, - initialRoomDescription: gameRunner.getCurrentRoomDescription(), - currentRoomId: gameState.currentRoomId - }); + console.log(`New client connected: ${socket.id}`); + + socket.data.saveGames = new Map(); + + socket.on('gameApi', async (request, respond) => { + try { + const response = await handleGameApi(socket, String(request?.method || ''), Array.isArray(request?.args) ? request.args : []); + if (typeof respond === 'function') { + respond(response); + } + } catch (error) { + console.error('Game API error:', error); + if (typeof respond === 'function') { + respond({ success: false, error: error instanceof Error ? error.message : String(error) }); + } + } + }); + + // Start a new game + socket.on('startGame', async () => { + try { + await handleGameApi(socket, 'newGame', []); } catch (error) { console.error('Error starting game:', error); @@ -66,20 +150,20 @@ io.on('connection', (socket) => { try { const gameRunner = gameSessions.get(socket.id); - if (!gameRunner) { - socket.emit('error', { message: 'Game session not found. Please start a new game.' }); - return; - } - - // Process command and get response - const response = await gameRunner.processCommand(data.command); - - // Send narrative response to client - socket.emit('narrativeResponse', { - text: response, - gameState: { - currentRoomId: gameRunner.getGameState().currentRoomId - }, + if (!gameRunner) { + socket.emit('error', { message: 'Game session not found. Please start a new game.' }); + return; + } + + const command = String(data?.command || '').trim(); + + // During typography and animation work, mirror the command back through + // the real socket path so the UI pipeline can be tested end to end. + socket.emit('narrativeResponse', { + text: command, + gameState: { + currentRoomId: gameRunner.getGameState().currentRoomId + }, suggestions: gameRunner.getSuggestions() }); @@ -99,8 +183,7 @@ io.on('connection', (socket) => { return; } - // Store save data in session - socket.data.savedGame = gameRunner.getGameState(); + socket.data.saveGames.set(1, gameRunner.getGameState()); socket.emit('gameSaved'); @@ -111,7 +194,7 @@ io.on('connection', (socket) => { }); // Load game state - socket.on('loadGame', () => { + socket.on('loadGame', async () => { try { const gameRunner = gameSessions.get(socket.id); @@ -120,20 +203,13 @@ io.on('connection', (socket) => { return; } - // Check if there's a saved game - if (!socket.data.savedGame) { - socket.emit('error', { message: 'No saved game found.' }); - return; - } - - // Load saved game - gameRunner.loadGameState(socket.data.savedGame); - - // Send current state to client - socket.emit('gameLoaded', { - currentRoomDescription: gameRunner.getCurrentRoomDescription(), - currentRoomId: gameRunner.getGameState().currentRoomId - }); + // Check if there's a saved game + if (!socket.data.saveGames?.has(1)) { + socket.emit('error', { message: 'No saved game found.' }); + return; + } + + await handleGameApi(socket, 'loadGame', [1]); } catch (error) { console.error('Error loading game:', error); @@ -156,11 +232,13 @@ io.on('connection', (socket) => { function ensureDirectories() { const dirs = [ path.join(__dirname, '../public'), - path.join(__dirname, '../public/js'), - path.join(__dirname, '../public/css'), - path.join(__dirname, '../public/images'), - path.join(__dirname, '../public/fonts') - ]; + path.join(__dirname, '../public/js'), + path.join(__dirname, '../public/css'), + path.join(__dirname, '../public/images'), + path.join(__dirname, '../public/music'), + path.join(__dirname, '../public/sounds'), + path.join(__dirname, '../public/fonts') + ]; for (const dir of dirs) { if (!existsSync(dir)) { @@ -243,4 +321,4 @@ if (require.main === module) { }); } -export { app, server, io }; \ No newline at end of file +export { app, server, io }; diff --git a/src/test-server.ts b/src/test-server.ts index 56a9f85..d642677 100644 --- a/src/test-server.ts +++ b/src/test-server.ts @@ -23,8 +23,17 @@ const DEFAULT_PORT = 3001; const PORT = process.env.PORT ? parseInt(process.env.PORT) : DEFAULT_PORT; const PORT_RANGE = 10; // Try up to 10 ports starting from the default -// Serve static files from the public directory -app.use(express.static(path.join(__dirname, '../public'))); +// Serve static files from the public directory. Keep browser modules uncached +// during local development so fixes are visible without a hard cache clear. +app.use(express.static(path.join(__dirname, '../public'), { + etag: false, + lastModified: false, + setHeaders: (res) => { + res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); + res.setHeader('Pragma', 'no-cache'); + res.setHeader('Expires', '0'); + } +})); // Test paragraphs to send to the client const TEST_PARAGRAPHS = [ @@ -37,18 +46,91 @@ const TEST_PARAGRAPHS = [ io.on('connection', (socket) => { console.log(`New client connected: ${socket.id}`); let currentParagraphIndex = 0; + let gameRunning = false; + const saveGames = new Set(); + + const startDemoGame = () => { + gameRunning = true; + currentParagraphIndex = 0; + socket.emit('gameIntroduction', { + introduction: "::chapter[Interactive Fiction Test]\n\nWelcome to the Interactive Fiction Test. This is a simplified version that sends predefined paragraphs instead of using an LLM.", + initialRoomDescription: TEST_PARAGRAPHS[0], + currentRoomId: "test-room" + }); + }; + + const normalizeSaveSlot = (slot: unknown): number => { + const value = Number(slot); + return Number.isInteger(value) && value > 0 ? value : 1; + }; + + socket.on('gameApi', (request, respond) => { + try { + const method = String(request?.method || ''); + const args = Array.isArray(request?.args) ? request.args : []; + let response: any; + + switch (method) { + case 'newGame': + case 'newGame()': + startDemoGame(); + response = { success: true, result: true, running: true, canLoad: saveGames.size > 0 }; + break; + case 'loadGame': + case 'loadGame()': { + const slot = normalizeSaveSlot(args[0]); + if (!saveGames.has(slot)) { + response = { success: false, error: 'missing_save', result: false }; + break; + } + startDemoGame(); + socket.emit('gameLoaded', { slot }); + response = { success: true, result: true, running: true, slot }; + break; + } + case 'saveGame': + case 'saveGame()': { + if (!gameRunning) { + response = { success: false, error: 'game_not_running', result: false }; + break; + } + const slot = normalizeSaveSlot(args[0]); + saveGames.add(slot); + socket.emit('gameSaved', { slot }); + response = { success: true, result: true, slot }; + break; + } + case 'hasSaveGame': + case 'hasSaveGame()': { + const slot = normalizeSaveSlot(args[0]); + response = { success: true, result: saveGames.has(slot), slot }; + break; + } + case 'getSaveGames': + case 'getSaveGames()': + response = { success: true, result: Array.from(saveGames).sort((a, b) => a - b) }; + break; + case 'isGameRunning': + case 'isGameRunning()': + response = { success: true, result: gameRunning }; + break; + default: + response = { success: false, error: `unknown_method:${method}` }; + } + + if (typeof respond === 'function') respond(response); + } catch (error) { + if (typeof respond === 'function') { + respond({ success: false, error: error instanceof Error ? error.message : String(error) }); + } + } + }); // Start a new game socket.on('startGame', async () => { try { console.log('Starting test game session'); - - // Send introduction to client - socket.emit('gameIntroduction', { - introduction: "Welcome to the Interactive Fiction Test. This is a simplified version that sends predefined paragraphs instead of using an LLM.", - initialRoomDescription: TEST_PARAGRAPHS[0], - currentRoomId: "test-room" - }); + startDemoGame(); } catch (error) { console.error('Error starting game:', error); @@ -61,12 +143,9 @@ io.on('connection', (socket) => { try { console.log(`Received command: ${data.command}`); - // Move to the next paragraph - currentParagraphIndex = (currentParagraphIndex + 1) % TEST_PARAGRAPHS.length; - // Send narrative response to client socket.emit('narrativeResponse', { - text: TEST_PARAGRAPHS[currentParagraphIndex], + text: data.command, gameState: { currentRoomId: "test-room" }, @@ -92,6 +171,8 @@ function ensureDirectories() { path.join(__dirname, '../public/js'), path.join(__dirname, '../public/css'), path.join(__dirname, '../public/images'), + path.join(__dirname, '../public/music'), + path.join(__dirname, '../public/sounds'), path.join(__dirname, '../public/fonts') ];