@@ -34,6 +34,8 @@ export default class Engine {
3434 this . story = args . story ;
3535 this . labels = Object . keys ( this . story ) ;
3636 this . handler = args . handler ;
37+ this . meter = 0 ;
38+ this . limit = 10e3 ; // bottles.kni, for example, runs long
3739 this . options = [ ] ;
3840 this . keywords = { } ;
3941 this . noOption = null ;
@@ -47,6 +49,7 @@ export default class Engine {
4749 this . dialog . engine = this ;
4850 this . randomer = args . randomer || Math ;
4951 this . waypoint = this . capture ( ) ;
52+ this . answerOnClearMeterFault = [ ] ;
5053 Object . seal ( this ) ;
5154 }
5255
@@ -63,11 +66,15 @@ export default class Engine {
6366 this . resume ( ) ;
6467 }
6568
69+ /**
70+ * Runs the event loop until it yields.
71+ */
6672 continue ( ) {
67- let _continue ;
68- do {
73+ this . meter = 0 ;
74+ for ( ; ; ) {
6975 if ( this . debug ) {
7076 console . log ( `${ this . label } ${ this . instruction . type } ${ describe ( this . instruction ) } ` ) ;
77+ console . log ( this . top ) ;
7178 }
7279 if ( this . instruction == null ) {
7380 // TODO user error for non-console interaction.
@@ -79,8 +86,31 @@ export default class Engine {
7986 console . error ( `Unexpected instruction type: ${ this . instruction . type } ` , this . instruction ) ;
8087 this . resume ( ) ;
8188 }
82- _continue = this [ `$${ this . instruction . type } ` ] ( this . instruction ) ;
83- } while ( _continue ) ;
89+ const proceed = this [ `$${ this . instruction . type } ` ] ( this . instruction ) ;
90+ if ( ! proceed ) {
91+ return ;
92+ }
93+ this . meter += 1 ;
94+ if ( this . meter >= this . limit ) {
95+ this . display ( ) ;
96+ this . dialog . meterFault ( ) ;
97+ return ;
98+ }
99+ }
100+ }
101+
102+ clearMeterFault ( ) {
103+ if ( this . meter >= this . limit ) {
104+ this . render . clear ( ) ;
105+ this . continue ( ) ;
106+
107+ // flush answers posted while faulted
108+ const count = this . answerOnClearMeterFault . length ;
109+ const answers = this . answerOnClearMeterFault . splice ( 0 , count ) ;
110+ for ( const answer of answers ) {
111+ this . answer ( answer ) ;
112+ }
113+ }
84114 }
85115
86116 goto ( label ) {
@@ -170,6 +200,10 @@ export default class Engine {
170200 }
171201
172202 answer ( text ) {
203+ if ( this . meter >= this . limit ) {
204+ this . answerOnClearMeterFault . push ( text ) ;
205+ return ;
206+ }
173207 if ( this . handler && this . handler . answer ) {
174208 this . handler . answer ( text , this ) ;
175209 }
@@ -256,6 +290,9 @@ export default class Engine {
256290 ] ;
257291 }
258292
293+ /**
294+ * Resumes from a snapshot.
295+ */
259296 resume ( snapshot ) {
260297 this . render . clear ( ) ;
261298 this . flush ( ) ;
0 commit comments