Reading choices
This commit is contained in:
@@ -3,12 +3,15 @@ package hank;
|
||||
import hiss.HTypes;
|
||||
import hiss.CCInterp;
|
||||
import hiss.StaticFiles;
|
||||
import hiss.HissReader;
|
||||
using hiss.HissTools;
|
||||
|
||||
class Story {
|
||||
var teller: StoryTeller;
|
||||
var interp: CCInterp;
|
||||
var storyScript: String;
|
||||
// Separate reader for Hiss expressions:
|
||||
var reader: HissReader;
|
||||
|
||||
public function new(storyScript: String, storyTeller: StoryTeller) {
|
||||
StaticFiles.compileWith("reader-macros.hiss");
|
||||
@@ -18,9 +21,11 @@ class Story {
|
||||
teller = storyTeller;
|
||||
|
||||
interp = new CCInterp();
|
||||
|
||||
reader = new HissReader(interp); // It references the same CCInterp but has its own readtable
|
||||
|
||||
interp.importFunction(storyTeller, storyTeller.handleOutput, "*handle-output*");
|
||||
interp.importFunction(storyTeller, storyTeller.handleChoices, "*handle-choices*");
|
||||
interp.importFunction(reader, reader.read, "hiss-read");
|
||||
|
||||
interp.load("hanklib.hiss");
|
||||
}
|
||||
|
||||
16
src/hank/examples/choices.hank
Normal file
16
src/hank/examples/choices.hank
Normal file
@@ -0,0 +1,16 @@
|
||||
-> start
|
||||
|
||||
== end
|
||||
|
||||
Good choice.
|
||||
|
||||
== start
|
||||
|
||||
You have to make a choice.
|
||||
|
||||
* (label) A
|
||||
-> start
|
||||
+ {t} B
|
||||
-> start
|
||||
* C
|
||||
-> end
|
||||
@@ -10,6 +10,17 @@
|
||||
(cond
|
||||
((string? part) part)))
|
||||
|
||||
(defun divert (target) (print (+ "Diverting to " target)))
|
||||
(defstruct choice once-only depth label condition output chosen-count on-chosen)
|
||||
(defvar *choices* [])
|
||||
(defvar *labeled-choices* (dict))
|
||||
(defmacro defchoice (&rest args)
|
||||
"Define a new choice and return its id"
|
||||
`(let (c (make-choice ,@args)
|
||||
label (choice-label c)
|
||||
id (length *choices*))
|
||||
(print c)
|
||||
(push! *choices* c)
|
||||
(when label (dict-set! *labeled-choices* label c))
|
||||
id))
|
||||
|
||||
(enable-continuations)
|
||||
(defvar *choice-points* [])
|
||||
@@ -1,5 +1,7 @@
|
||||
(def-reader-macro "->" (start stream)
|
||||
`(funcall ,(read-symbol "" stream)))
|
||||
// TODO don't just funcall, check the scope tree of divert targets (split by .)
|
||||
// TODO diverts should quit when finished unless another -> starts a tunnel or tunnels back
|
||||
|
||||
(def-reader-macro "==" (start stream)
|
||||
(let (knot-name
|
||||
@@ -13,6 +15,47 @@
|
||||
(eval (print `(defun ,knot-name () ,@knot-body (quit))))
|
||||
nil))
|
||||
|
||||
(defun read-choice (start stream)
|
||||
"will be called with start=nil for all choices following the first in a choice point"
|
||||
(let (start-char
|
||||
(or start (HStream:peek stream 1))
|
||||
once-only
|
||||
(case start-char
|
||||
("*" t)
|
||||
("+" nil))
|
||||
depth
|
||||
(+ (if start 1 0) (HStream:count-consecutive stream start-char))
|
||||
label
|
||||
(case
|
||||
(begin
|
||||
(HStream:drop-whitespace stream)
|
||||
(HStream:peek stream 1))
|
||||
("("
|
||||
(trim (substring (first (HStream:take-until stream [")"])) 1))))
|
||||
condition
|
||||
(case
|
||||
(begin
|
||||
(HStream:drop-whitespace stream)
|
||||
(HStream:peek stream 1))
|
||||
("{"
|
||||
(hiss-read "" (HStream:from-string (trim (substring (first (HStream:take-until stream ["}"])) 1)))))
|
||||
(default t))
|
||||
output
|
||||
(read-output "" stream)
|
||||
on-chosen
|
||||
`(begin
|
||||
,@(read-all (first (HStream:take-until stream [(* depth "*") (* depth "+") (+ (* depth "-") " ")] nil nil t)))))
|
||||
(defchoice once-only depth label condition output 0 on-chosen)))
|
||||
|
||||
|
||||
(defun read-choice-point (start stream)
|
||||
// TODO
|
||||
(read-choice start stream))
|
||||
|
||||
|
||||
(set-macro-string "*" read-choice-point)
|
||||
(set-macro-string "+" read-choice-point)
|
||||
|
||||
(defun read-output (start stream)
|
||||
`(output ,(HStream:take-line stream "rl")))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user