diff --git a/examples/duchess_party.html b/examples/duchess_party.html index fb691cb..e0b99cf 100644 --- a/examples/duchess_party.html +++ b/examples/duchess_party.html @@ -123,7 +123,8 @@ StoryManager.getAllStorylets = function(tag=null) { return allStorylets; } -StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { +StoryManager.getStorylets = + function(n=null, tag=null, selection="weighted", respect_interrupt=true) { /* Get n storylets, prioritizing the highest-priority ones first. @@ -143,12 +144,24 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { if (allStorylets[i].interrupt) return [allStorylets[i]]; } - // Get n stories in priority order + // Return n or the max if (n != null) { n = Math.min(n, allStorylets.length); if (n == 0) return []; } else n = allStorylets.length; + + let selectedStorylets; + if (selection == "ordered") + selectedStorylets = this.sortByPriority(allStorylets, n); + else if (selection == "weighted") + selectedStorylets = this.weightedRandom(allStorylets, n); + + return selectedStorylets; +} + +// Get storylets strictly by priority +StoryManager.sortByPriority = function(allStorylets, n) { let selectedStorylets = []; // Select by strict priority; randomize among matching priority. @@ -166,8 +179,29 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { return selectedStorylets; } -// Set up macros +// Get storylets via weighted random choice +StoryManager.weightedRandom = function(allStorylets, n) { + let selectedStorylets = []; + let sum, counter, index, rand; + while (selectedStorylets.length < n) { + sum = allStorylets.reduce((a, x) => a + x.priority, 0); + counter = 0; + rand = Math.random() * sum; + for (let i=0; i + + + +Simple progress example + + + + + + + + + + + + + + + + + + JavaScript is required. Please enable it to continue. + Your browser lacks required capabilities. Please upgrade it or switch to another to continue. + Loading… + + You <<linkToNextStorylet "start walking">> through the woods.You walk deeper into the woods. You see a <<print $currentStorylet.animal>> <br> +<<set $progress = $progress + 1>> +<<linkToNextStorylet "Keep walking">>You reach the end of the forest! + + + diff --git a/examples/progress_example.tw b/examples/progress_example.tw new file mode 100644 index 0000000..6475c47 --- /dev/null +++ b/examples/progress_example.tw @@ -0,0 +1,51 @@ +:: StoryTitle +Simple progress example + +:: StoryData +{ + "ifid": "724F804D-9451-4347-BB4D-A0725429BC93" +} + +:: Story JavaScript [script] +Config.passages.nobr = true; // No unspecified linebreaks. + +let animals = ["moose", "fox", "toad"]; +State.variables.progress = 0; + +StoryManager.storylets["walk"] = { + name: "Walking", + generate: function*() { + for (let animal of animals) { + yield { + passage: "Walking", + animal: animal, + priority: 1 + } + } + } +} + +StoryManager.storylets["end"] = { + name: "The End", + generate: function*() { + if (State.variables.progress > 3) { + yield { + passage: "End", + priority: 2 + } + } + } +} + + +:: Start + +You <> through the woods. + +:: Walking +You walk deeper into the woods. You see a <> +<> +<> + +:: End +You reach the end of the forest! \ No newline at end of file diff --git a/examples/simple_space_example.html b/examples/simple_space_example.html index 3259378..fee05fe 100644 --- a/examples/simple_space_example.html +++ b/examples/simple_space_example.html @@ -123,7 +123,8 @@ StoryManager.getAllStorylets = function(tag=null) { return allStorylets; } -StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { +StoryManager.getStorylets = + function(n=null, tag=null, selection="weighted", respect_interrupt=true) { /* Get n storylets, prioritizing the highest-priority ones first. @@ -143,12 +144,24 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { if (allStorylets[i].interrupt) return [allStorylets[i]]; } - // Get n stories in priority order + // Return n or the max if (n != null) { n = Math.min(n, allStorylets.length); if (n == 0) return []; } else n = allStorylets.length; + + let selectedStorylets; + if (selection == "ordered") + selectedStorylets = this.sortByPriority(allStorylets, n); + else if (selection == "weighted") + selectedStorylets = this.weightedRandom(allStorylets, n); + + return selectedStorylets; +} + +// Get storylets strictly by priority +StoryManager.sortByPriority = function(allStorylets, n) { let selectedStorylets = []; // Select by strict priority; randomize among matching priority. @@ -166,19 +179,40 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { return selectedStorylets; } -// Set up macros +// Get storylets via weighted random choice +StoryManager.weightedRandom = function(allStorylets, n) { + let selectedStorylets = []; + let sum, counter, index, rand; + while (selectedStorylets.length < n) { + sum = allStorylets.reduce((a, x) => a + x.priority, 0); + counter = 0; + rand = Math.random() * sum; + for (let i=0; i> - <> + <> \ + <> \ [[_storylet.description|_storylet.passage][$currentStorylet=_storylet]] - <> - <> + <> \ + <> \ `); } }) diff --git a/examples/tutorial.html b/examples/tutorial.html index 4a6620d..d0e391a 100644 --- a/examples/tutorial.html +++ b/examples/tutorial.html @@ -123,7 +123,8 @@ StoryManager.getAllStorylets = function(tag=null) { return allStorylets; } -StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { +StoryManager.getStorylets = + function(n=null, tag=null, selection="weighted", respect_interrupt=true) { /* Get n storylets, prioritizing the highest-priority ones first. @@ -143,12 +144,24 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { if (allStorylets[i].interrupt) return [allStorylets[i]]; } - // Get n stories in priority order + // Return n or the max if (n != null) { n = Math.min(n, allStorylets.length); if (n == 0) return []; } else n = allStorylets.length; + + let selectedStorylets; + if (selection == "ordered") + selectedStorylets = this.sortByPriority(allStorylets, n); + else if (selection == "weighted") + selectedStorylets = this.weightedRandom(allStorylets, n); + + return selectedStorylets; +} + +// Get storylets strictly by priority +StoryManager.sortByPriority = function(allStorylets, n) { let selectedStorylets = []; // Select by strict priority; randomize among matching priority. @@ -166,19 +179,40 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { return selectedStorylets; } -// Set up macros +// Get storylets via weighted random choice +StoryManager.weightedRandom = function(allStorylets, n) { + let selectedStorylets = []; + let sum, counter, index, rand; + while (selectedStorylets.length < n) { + sum = allStorylets.reduce((a, x) => a + x.priority, 0); + counter = 0; + rand = Math.random() * sum; + for (let i=0; i> - <> + <> \ + <> \ [[_storylet.description|_storylet.passage][$currentStorylet=_storylet]] - <> - <> + <> \ + <> \ `); } }) diff --git a/storymanager.js b/storymanager.js index 130f705..5ca0c89 100644 --- a/storymanager.js +++ b/storymanager.js @@ -20,7 +20,8 @@ StoryManager.getAllStorylets = function(tag=null) { return allStorylets; } -StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { +StoryManager.getStorylets = + function(n=null, tag=null, selection="ordered", respect_interrupt=true) { /* Get n storylets, prioritizing the highest-priority ones first. @@ -34,18 +35,34 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { // Check for interruptions - // TODO: Handle more than one interruption if (respect_interrupt) { - for (let i in allStorylets) - if (allStorylets[i].interrupt) return [allStorylets[i]]; + let interruptions = []; + for (let storylet of allStorylets) + if (storylet.interrupt) interruptions.push(storylet); + if (interruptions.length > 0) { + interruptions.sort((a, b) => b.priority - a.priority); + return [interruptions[0]]; + } } - // Get n stories in priority order + // Return n or the max if (n != null) { n = Math.min(n, allStorylets.length); if (n == 0) return []; } else n = allStorylets.length; + + let selectedStorylets; + if (selection == "ordered") + selectedStorylets = this.sortByPriority(allStorylets, n); + else if (selection == "weighted") + selectedStorylets = this.weightedRandom(allStorylets, n); + + return selectedStorylets; +} + +// Get storylets strictly by priority +StoryManager.sortByPriority = function(allStorylets, n) { let selectedStorylets = []; // Select by strict priority; randomize among matching priority. @@ -63,14 +80,35 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { return selectedStorylets; } -// Set up macros +// Get storylets via weighted random choice +StoryManager.weightedRandom = function(allStorylets, n) { + let selectedStorylets = []; + let sum, counter, index, rand; + while (selectedStorylets.length < n) { + sum = allStorylets.reduce((a, x) => a + x.priority, 0); + counter = 0; + rand = Math.random() * sum; + for (let i=0; i rand) { + selectedStorylets.push(allStorylets.splice(i, 1)[0]); + break; + } + counter += allStorylets[i].priority; + } + } + return selectedStorylets; +} + + +// Set up macros +// --------------------------------------------------------------- Macro.add("getStoryletLinks", { handler: function() { let n, tag; - [n=null, tag=null] = this.args; - State.temporary.nextStorylets = StoryManager.getStorylets(n, tag); - $(this.output).wiki(` + [n=null, tag=null, selection="ordered"] = this.args; + State.temporary.nextStorylets = StoryManager.getStorylets(n, tag, selection); + $(this.output).wiki(`\ <> \ <> \ [[_storylet.description|_storylet.passage][$currentStorylet=_storylet]] @@ -78,7 +116,15 @@ Macro.add("getStoryletLinks", { <> \ `); } -}) +}); +Macro.add("linkToNextStorylet", { + handler: function() { + let text, tag, selection; + [text, tag=null, selection="weighted"] = this.args; + State.temporary.nextStorylet = StoryManager.getStorylets(1, tag, selection)[0]; + $(this.output).wiki(`<>[[${text}|_nextStorylet.passage][$currentStorylet=_nextStorylet]]<>`); + } +}); window.SM = StoryManager; \ No newline at end of file