-
Notifications
You must be signed in to change notification settings - Fork 159
Expand file tree
/
Copy pathChatScript-System-Functions-Manual.html
More file actions
3351 lines (3329 loc) · 156 KB
/
Copy pathChatScript-System-Functions-Manual.html
File metadata and controls
3351 lines (3329 loc) · 156 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>ChatScript-System-Functions-Manual</title>
<style>
html {
color: #1a1a1a;
background-color: #fdfdfd;
}
body {
margin: 0 auto;
max-width: 36em;
padding-left: 50px;
padding-right: 50px;
padding-top: 50px;
padding-bottom: 50px;
hyphens: auto;
overflow-wrap: break-word;
text-rendering: optimizeLegibility;
font-kerning: normal;
}
@media (max-width: 600px) {
body {
font-size: 0.9em;
padding: 12px;
}
h1 {
font-size: 1.8em;
}
}
@media print {
html {
background-color: white;
}
body {
background-color: transparent;
color: black;
font-size: 12pt;
}
p, h2, h3 {
orphans: 3;
widows: 3;
}
h2, h3, h4 {
page-break-after: avoid;
}
}
p {
margin: 1em 0;
}
a {
color: #1a1a1a;
}
a:visited {
color: #1a1a1a;
}
img {
max-width: 100%;
}
svg {
height; auto;
max-width: 100%;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 1.4em;
}
h5, h6 {
font-size: 1em;
font-style: italic;
}
h6 {
font-weight: normal;
}
ol, ul {
padding-left: 1.7em;
margin-top: 1em;
}
li > ol, li > ul {
margin-top: 0;
}
blockquote {
margin: 1em 0 1em 1.7em;
padding-left: 1em;
border-left: 2px solid #e6e6e6;
color: #606060;
}
code {
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
font-size: 85%;
margin: 0;
hyphens: manual;
}
pre {
margin: 1em 0;
overflow: auto;
}
pre code {
padding: 0;
overflow: visible;
overflow-wrap: normal;
}
.sourceCode {
background-color: transparent;
overflow: visible;
}
hr {
background-color: #1a1a1a;
border: none;
height: 1px;
margin: 1em 0;
}
table {
margin: 1em 0;
border-collapse: collapse;
width: 100%;
overflow-x: auto;
display: block;
font-variant-numeric: lining-nums tabular-nums;
}
table caption {
margin-bottom: 0.75em;
}
tbody {
margin-top: 0.5em;
border-top: 1px solid #1a1a1a;
border-bottom: 1px solid #1a1a1a;
}
th {
border-top: 1px solid #1a1a1a;
padding: 0.25em 0.5em 0.25em 0.5em;
}
td {
padding: 0.125em 0.5em 0.25em 0.5em;
}
header {
margin-bottom: 4em;
text-align: center;
}
#TOC li {
list-style: none;
}
#TOC ul {
padding-left: 1.3em;
}
#TOC > ul {
padding-left: 0;
}
#TOC a:not(:hover) {
text-decoration: none;
}
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
/* The extra [class] is a hack that increases specificity enough to
override a similar rule in reveal.js */
ul.task-list[class]{list-style: none;}
ul.task-list li input[type="checkbox"] {
font-size: inherit;
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
</style>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="chatscript-system-functions-manual">ChatScript System Functions
Manual</h1>
<p>Copyright Bruce Wilcox, gowilcox@gmail.com
www.brilligunderstanding.com <br>Revision 6/13/2022 cs13.2</p>
<ul>
<li><a
href="ChatScript-System-Functions-Manual.html#topic-functions">Topic
Functions</a></li>
<li><a
href="ChatScript-System-Functions-Manual.html#marking-functions">Marking
Functions</a></li>
<li><a
href="ChatScript-System-Functions-Manual.html#input-functions">Input
Functions</a></li>
<li><a
href="ChatScript-System-Functions-Manual.html#number-functions">Number
Functions</a></li>
<li><a
href="ChatScript-System-Functions-Manual.html#output-functions">Output
Functions</a></li>
<li><a
href="ChatScript-System-Functions-Manual.html#control-flow-functions">Control
Flow Functions</a></li>
<li><a
href="ChatScript-System-Functions-Manual.html#external-access-functions">External
Access Functions</a></li>
<li><a href="ChatScript-System-Functions-Manual.html#json-functions">JSON
Functions</a></li>
<li><a
href="ChatScript-System-Functions-Manual.html#word-manipulation-functions">Word
Manipulation Functions</a></li>
<li><a
href="ChatScript-System-Functions-Manual.html#multipurpose-functions">Multipurpose
Functions</a></li>
<li><a href="ChatScript-System-Functions-Manual.html#fact-functions">Facts
Functions</a></li>
<li><a href="ChatScript-System-Functions-Manual.html#Misc-functions">Misc
Functions</a></li>
</ul>
<p>System functions are predefined and can be intermixed with direct
output. Generally they are used from the output side of a rule, but in
many cases nothing prevents you from invoking them from inside a
pattern. When used in a pattern, they do not write out any text output
to the user. But their output will be tested the same as it would from
an <code>if</code> statement, meaning 0 and false are failures.</p>
<p>You can write them with or without a <code>^</code> in front of their
name in output. With is clearer, but you don’t have to. The only times
you must is if the first thing you want to do in a gambit is call a
function (unlikely) or you are in a pattern.</p>
<pre><code>t: name(xxx)
u: ( [find (me go) ])</code></pre>
<p>These are ambiguous. In the gambit is it function call or label. In
the responder is find a function name or just a word?</p>
<p>The above gambit is treated as a label and pattern. You can force it
to be a function call by one of these:</p>
<pre><code>t: ^name(xxx) # explicilty say it is a function
t: () name(xxx) # explicitly add an empty pattern</code></pre>
<h2 id="rule-tags">Rule Tags</h2>
<p>Some functions out or take “rule tags”. All rules have an internal
label consisting of <code>~topic.toplevelindex.rejoinderindex</code>.
E.g.</p>
<pre><code>~introductions.0.5</code></pre>
<p>stands for the 0th rule in the <code>~introductions</code> topic,
rejoinder #5.</p>
<h1 id="topic-functions">Topic Functions</h1>
<h3 id="addtopic-topicname"><code>^addtopic ( topicname )</code></h3>
<p>adds the named topic as a pending topic at the head of the list.
Typically you don’t need to do this, because finding a reaction from a
topic which is not a system, disabled, or nostay topic will
automatically add the topic to the pending list. Never returns a fail
code even if the topic name is bad.</p>
<h3
id="available-ruletag-optionalfail"><code>^available ( ruletag optionalfail )</code></h3>
<p>Sees if the named rule is available (1) or used up (0). If you supply
the optional argument, the function will fail if the rule is not
available.</p>
<h3 id="cleartopics"><code>^cleartopics()</code></h3>
<p>Empty the pending topics list.</p>
<h3
id="counttopic-topic-what"><code>^counttopic ( topic what )</code></h3>
<p>For the given topic, return how many rules match what.</p>
<p>What is <code>gambits</code>, <code>responders</code>,
<code>availablegambits</code>,
<code>availableresponders</code>,<code>rules</code>,
<code>used</code>.</p>
<p>That is, how many gambits exist, how many available gambits exist
(not erased), how many responders exist, how many available responders
exist (not erased), how many top level rules (gambits + responders)
exist, and how many top level rules have been erased.</p>
<h3
id="gambit-value-value-..."><code>^gambit ( value value ... )</code></h3>
<p>If value is a topic name, runs the topic in gambit mode to see if any
gambits arise. If none arise from the first value, it will try the
second, and so on. It does not fail unless a rule forces it to fail or
the named topic doesn’t exist or is disabled. You can supply an optional
last argument <code>FAIL</code>, in which case it will return
<code>FAILRULE_BIT</code> if it didn’t fail but it didn’t generate any
new output either.</p>
<p>The value may be <code>~</code>, which means use the current topic
you are within. It can also be <code>PENDING</code>, which means pick a
topic from the pending topics stack (they are all pending being returned
to but not including the current topic). Or it can be any other word,
which will be a keyword of some topic to pick. E.g.,</p>
<pre><code>^gambit(~ PENDING ~mygeneraltopic FAIL)</code></pre>
<h3 id="findrule-label"><code>^findrule ( label )</code></h3>
<p>On the assumption that you only have one occurence of a rule label in
your script, if you provide that label to this function, it will find
the corresponding rule anywhere in your script and return the rule tag
corresponding to it. If you have more than one such labelled Rule it
merely returns the first one it finds (which will be earliest rule in
earliest compiled topic).</p>
<h3 id="getrule-what-label"><code>^getrule ( what label )</code></h3>
<p>for the given rule label or tag, return some fragment of the
rule.</p>
<p><em>what</em> can be <code>tag</code>,
<code>type</code>,<code>label</code>, <code>pattern</code>,
<code>output</code>,<code>topic</code>, and <code>usable</code>.</p>
<p>The type will be <code>t</code>, <code>?</code>, <code>s</code>,
<code>a</code>, etc.</p>
<p>If a rule label is involved, optional third argument if given means
only find enabled rules with that label. For usable, returns 1 if is can
be used or null if it has been erased. The label <code>~</code> means
the current rule. The label <code>0</code> means the top level rule
above us (if we are a rejoinder, otherwise it is the same as
<code>~</code>).</p>
<p>If ^getrule(label) is called from ^testpattern, then the label
associated with the pattern will be used, if it has one.</p>
<h3 id="hasgambit-topic"><code>^hasgambit ( topic )</code></h3>
<p>fails if topic does not have any gambits left unexecuted.</p>
<p>Even it if does, they may not execute if they have patterns and they
don’t match. Optional second argument, if <code>any</code> will return
normally if topic has any gambits (executed or not) and will failrule if
topic has no gambits (a reactor topic).</p>
<h3 id="keep"><code>^keep()</code></h3>
<p>do not erase this top level rule when it executes its output part
(you could declare a topic to be this, although it wouldn’t affect
gambits).</p>
<p>Doing <code>keep()</code> on a gambit is quite risky since gambits
after it may not ever fire.</p>
<h3 id="lastused-topic-what"><code>^lastused ( topic what )</code></h3>
<p>given a topic name, get the volley of the last what, where
<em>what</em> is <code>GAMBIT</code>, <code>RESPONDER</code>,
<code>REJOINDER</code>, <code>ANY</code>. If it has never happened, the
value is <code>0</code>.</p>
<h3 id="next-what-label"><code>^next ( what {label} )</code></h3>
<p>Given what of <code>GAMBIT</code> or <code>RESPONDER</code> or
<code>REJOINDER</code> or <code>RULE</code> and a rule label or tag,
find the next rule of that what. Fails if none is found.</p>
<p><code>REJOINDER</code> will fail if it reaches the next top level
rule.</p>
<p>If <em>label</em> is <code>~</code>, it will use the last call’s
answer as the starting point, enabling you to walk rules in
succession.</p>
<p>There is also <code>^next(FACT @xxx)</code> - see fact manual.</p>
<p>For <code>^next(INPUT)</code> the system will read the next sentence
and prep the system with it. This means that all patterns and code
executing thereafter will be in the context of the next input sentence.
That sentence is now used up, and will not be seen next when the current
revised sentence finishes.</p>
<p>Sample code might be:</p>
<pre><code>t: Do you have any pets
a: ( ~yes ) refine()
b: ( %more ) ^next(input) refine()
c: ( ~pets ) ... # react to pet
c: () ^retry(SENTENCE) # return to try input from scratch
b: () What kind do you have?
c: ( ~pets ) ... # react to pet</code></pre>
<p>If <em>label</em> is <code>LOOP</code>, the system will stop
processing code in the current loop and return to the next iteration of
it, e.g. C++/Java continue, except that it will stop all code and return
to however high up the loop really is, exiting topics and functions
willy nilly if need be.</p>
<h3 id="poptopic-topicname"><code>^poptopic ( topicname )</code></h3>
<p>Removes the named topic as a pending topic. The intent is not to
automatically return here in future conversation. If topicname is
omitted, removes the current topic AND makes the current topic fail
execution at this point.</p>
<h3 id="refine"><code>^refine ( ? )</code></h3>
<p>This is like a switch statement in <em>C language</em>. It executes
in order the rejoinders attached to its rule in sequence.</p>
<p>When the pattern of one matches, it executes that output and is done,
regardless of whether or not the output fails or generates nothing. It
does not “fail”, unless you add an optional FAIL argument. You can also
provide a rule tag. Normally it uses the rule the refine is executing
from, but you can direct it to refine from any rule.</p>
<h3 id="rejoinder-taglabel"><code>^rejoinder ( {tag/label} )</code></h3>
<p>Without argument, see if the prior input ended with a potential
rejoinder rule, and if so test it on the current sentence. If we match
and dont fail on a rejoinder, the rejoinder is satisfied. If we fail to
match on the 1st input sentence, the rejoinder remains in place for a
second sentence. If that doesn’t match, it is canceled. It is also
canceled if output matching the first sentence sets a rejoinder.</p>
<p>You can give an optional tag or label to pretend the named rule had
been the one to set a rejoinder and so therefore execute its rejoinders
explicitly.</p>
<h3
id="respond-value-value-..."><code>^respond ( value value ... )</code></h3>
<p>Tests the sentence against the named value topic in responder mode to
see if any rule matches (executes the rule when matched). It does not
fail (though it may not generate any output), unless a rule forces it to
fail or the topic requested does not exist or is disabled.</p>
<p>This rule will not erase but the responding rule might. If the first
value fails to generate an answer, it tries the second, and so on. You
can supply an optional last argument <code>FAIL</code>, in which case it
will return <code>FAILRULE_BIT</code> if it didn’t fail but it didn’t
generate any new output either. You could instead supply an optional
last argument <code>TEST</code>, in which case a topic is executed to
see if a rule will match. If so, the tag is returned and no output is
made from the topic (and no rule is used up).</p>
<p>If a value designates a labelled or tagged rule (e.g.,
<code>~mytopic.mylabel</code> or <code>~mytopic.1.0</code>) then the
system will skip over all rules until it reaches that rule, then begin
linear scanning, even if the topic is designated random.</p>
<p>The <em>value</em> may be <code>~</code>, which means use the current
topic you are within.</p>
<p>It can also be <code>PENDING</code>, which means pick a topic from
the pending topics stack (they are all pending being returned to but not
including the current topic). Or it can be any other word, which will be
a keyword of some topic to pick.</p>
<h3 id="retry-item"><code>^retry ( item )</code></h3>
<p>If <em>item</em> is <code>RULE</code> reexecute the current rule. It
will automatically try to match one word later than its first match
previously.</p>
<p>If <em>item</em> is <code>TOPIC</code> it will try the topic over
again.</p>
<p>If <em>item</em> is <code>SENTENCE</code> it will retry doing the
sentence again. To prevent infinite loops, it will not perform more than
5 retries during a volley. <code>SENTENCE</code> is particularly useful
with changing the tokenflags to get input processing done differently.
If item is INPUT it will retry all input again.</p>
<p><code>^retry(TOPRULE)</code> will return back to the top level rule
(not of the topic but of a rejoinder set) and retry.<br />
It’s the same if the current rule was a top level rule, but if the
current rule is from <code>^refine()</code>, then it returns to the
outermost rule to restart. If the current rule is not from
<code>^refine()</code>, then <code>TOPRULE</code> means the lexically
placed toprule above the current rule and a <code>^reuse()</code> will
be performed to go to it.</p>
<h3
id="reuse-rule-label-optional-enable-optional-fail"><code>^reuse ( rule label optional-enable optional-FAIL )</code></h3>
<p>Uses the output script of another rule. The label can either be a
simple rule label within the current topic, or it can be a dotted pair
of a topic name and a label within that topic or it can be a rule
tag.</p>
<p><code>^reuse</code> stops at the first correctly labeled rule it can
find and issues a RULE fail if it cannot find one. Assuming nothing
fails, it will return 0 regardless of whether or not any output was
generated.</p>
<p>When it executes the output of the other rule, that rule is credited
with matching and is disabled if it is allowed. If not allowed, the
calling rule will be disabled if it can be.</p>
<pre><code>t: NAME () My name is Bob.
?: ( << what you name >> )
^reuse(NAME)
?: ( << what you girlfriend name >> )
^reuse(~SARAH.NAME)</code></pre>
<p>Normally reuse will use the output of a rule whether or not the rule
has been disabled. But, if you supply a 2nd argument (whatever it is),
then it will ignore disabled ones and try to find one with the same
label that is not disabled. You can also supply a <code>FAIL</code>
argument (as either 2nd or 3rd) which indicates the system should issue
a RULE FAIL if it doesn’t generate any output.</p>
<p>If you want to use a common rule to hold an answer and ONLY fire when
reused, perhaps with rejoinders, the most efficient way to do that is
with a rule whose pattern can never match. E.g. like this:</p>
<pre><code>s: COMMON (?) some answer
a: () some rejoinder...</code></pre>
<p>You make <code>^reuses</code> go to COMMON (or whatever you name it)
or even <code>^setrejoinder</code> on it. The rule itself can never
trigger because it only considers its pattern when the input is a
statement, but the pattern says the input must be a question. So this
rule never matches on its own.</p>
<p>There are also a variety of functions that return facts about a
topic, but you have to read the facts manual to learn about them.</p>
<h3 id="sequence"><code>^sequence ( ? )</code></h3>
<p>This is like <code>^refine</code>, except instead of only executing
the first rejoinder that matches, it executes all matching rejoinders in
order. If one of the rule outputs fails, it stops by failing the calling
rule.</p>
<p>Normally <code>^sequence</code> uses the rejoinders of the rule that
it is executing from, but you can direct it to <code>^sequence</code>
the rejoinders of any rule.</p>
<h3
id="setrejoinder-kind-tag"><code>^setrejoinder ( {kind} tag )</code></h3>
<p>Force the output rejoinder to be set to the given tag or rule label.
It’s as though that rule had just executed, so the rules beneath it will
be the rejoinders to try.</p>
<p>If <em>kind</em> is <code>input</code> then the input rejoinder is
set.</p>
<p>If <em>kind</em> is <code>output</code> or is omitted, then it sets
the output rejoinder.</p>
<p><code>^setrejoinder</code> does not jump anywhere. It establishes the
context for <code>^rejoinder</code>.</p>
<p>When you do:</p>
<pre><code>t: what is your name
a: ATX(_~propernoun) Hi, '_0</code></pre>
<p>the outputrejoinder is set to <code>ATX</code>. You can change that
if you want. When the next volley comes in, the outputrejoinder is now
the inputrejoinder and used for <code>^rejoinder</code>. You can modify
that as well. Both can exist simultaneously, you have the input context
and you set an output context before having used up the
inputrejoinder.</p>
<p>Setting a rejoinder on a rule means starting with the rejoinder
immediately after it. If <em>kind</em> is output and the <em>tag</em> is
<code>null</code>, the output rejoinder is cleared (analogous to
^disable).</p>
<p>If the <em>kind</em> is input and the <em>tag</em> is
<code>null</code>, the input rejoinder is cleared.</p>
<p>To kill a set outputrejoinder, use ^disable(OUTPUTREJOINDER).</p>
<h3 id="topicflags-topic"><code>^topicflags ( topic )</code></h3>
<p>Given a topic name, return the control bits for that topic. The bits
are mapped in dictionary_system.h as <code>TOPIC_*</code>.</p>
<h3 id="sleep-milliseconds"><code>^sleep ( milliseconds )</code></h3>
<p>This stalls the engine for that many milliseconds. If this is a
server, the server is unavailable until sleep is done. Use with care. A
good use is when starting up a server instance and the boot process
involves reading from an API. If your machine runs 30 instances of
ChatScript launched at once (to use max CPU), then all of them hitting
the same API at once may be bad for the API and forcing a randomized
sleep based on processid is a good use.</p>
<h1 id="marking-functions">Marking Functions</h1>
<h3
id="mark-word-location-one-all"><code>^mark ( word location {ONE ALL})</code></h3>
<p>Marking and unmarking words and concepts is fundamental to the
pattern matching mechanism, so the system provides both an automatic
marking mechanism and manual override abilities. You can manually mark
or unmark something. Automatic system marking marks all concepts implied
by chasing up membership in other concepts, as does this call
<code>^mark</code>. <code>word</code> can be any word, which also means
you can mark something with a concept name whether or not the concept
actually is defined anywhere.</p>
<p>There are two mechanisms supported using <code>^mark</code> and
<code>^unmark</code>: specific and generic.</p>
<p>With <code>specific</code>, you name words or concepts to mark or
unmark, either at a particular point in the sentence or throughout the
sentence. By default, or using the optional third argument
<code>ALL</code>, not only is what you name marked, but anything it in
turn is a part of is marked. The optional third argument
<code>ONE</code> will only mark that named word/concept and none of the
hierarchy implied by its membership in yet some other concept.</p>
<p>With <code>generic</code> you disable or reenable all existing marks
on a word or words in the sentence. In fact, you go beyond that because
during patttern matching words you disable are invisble entirely, and
matching proceeds as if they do not exist.</p>
<p><code>Specific</code>: effects are permanent for the volley and cross
over to other rules. In documentation below, use of <code>_0</code>
symbolizes use of any match variable.</p>
<p>^mark and ^unmark can mark/unmark a single thing, or the hierarchy of
things.<br />
Mark takes a possible 3rd argument ONE or ALL (defaulted) which makes it
mark either just the thing you gave or traverse the hierarchy and mark
all of it.</p>
<h3 id="mark-meat-_0"><code>^mark ( ~meat _0 )</code></h3>
<p>This marks <code>~meat</code> as though it has been seen at whereever
sentence location <code>_0</code> is bound to (start and end)</p>
<h3 id="mark-meat-n"><code>^mark ( ~meat n )</code></h3>
<p>Assuming <code>n</code> is within 1 and sentence word limit, this
marks meat at nth word location. If <code>n</code> was gotten from
^position of a match variable, it is the range of that match
variable.</p>
<h3 id="mark-tomboy-_0"><code>^mark ( tomboy _0 )</code></h3>
<p>This marks the word tomboy as visible at the location designated,
even though this word is not actually in the sentence. While patterns
will react to its presence, it will not show up in any memorizations
using <code>_</code>.</p>
<p>While usually you mark a concept, you can also mark a word (though
you should generally use the canonical form of the word to trigger all
its normal concept hierarchy markings as well).</p>
<p>Although <code>^conceptlist</code> (see Facts manual) normally only
reports concepts marked at a word, if you explicitly mark using a word
and not a concept, that will also be reported in
<code>^conceptlist</code>.</p>
<h3 id="mark-meat"><code>^mark ( ~meat )</code></h3>
<p>With location omitted, this marks <code>~meat</code> as though it has
been seen at sentence start (location 1).</p>
<h3 id="mark"><code>^mark()</code></h3>
<p>Memorizes the set of all * unmarks (generic unmarks) and then turns
them off so normal matching will occur.</p>
<h3 id="unmark"><code>^unmark()</code></h3>
<p>Restores the set of generic unmarks that were flipped off using
<code>^mark()</code>.</p>
<h3 id="unmark-word-_0"><code>^unmark ( word _0 )</code></h3>
<p>The inverse of specific <code>^mark</code>, this takes a
matchvariable that was filled at the position in the sentence you want
erased and removes the mark on the word or concept set or topic name
given. Pattern matching for it in that position will now fail. If the
word was a phrase, then all words in that phrase have the mark removed.
Thus <code>South Georgia</code> which has <code>Georgia</code> embedded
within it, and both might be ~geographic_area, will have both words
unmarked if you unmark ~geographic_area. But it is not symmetric to
<code>^mark</code> because it does not remove all implied marks that
mark may have set.</p>
<p>If you end up calling ^unmark with a 2nd argument of null, it will
just return without failure. This can happen if you pass null to an
outputmacro: <sup>myfn(</sup>var) and then ^unmark(xxx ^var).</p>
<p>^Unmark can remove either the single thing, or ^unmark(* _0) removes
ALL marks and makes the word completely invisible (not seen in a
wildcard match), whereas ^unmark(@ _0) removes all marks but leaves the
word occupying space in the sentence and will be seen in a wildcard
match.</p>
<p>When you call unmark, the analysis of the sentence HAS ALREADY
HAPPENED.<br />
If a ~noun was detected, so has ~noun_and_some_concept. So if you then
erase ~noun mark, it has NO impact on other marks made.</p>
<h3 id="unmark-n"><code>^unmark ( * n )</code></h3>
<p>Assuming <code>n</code> is within <code>1</code> and sentence word
limit, this unmarks all concepts at nth word location. If n was gotten
from <code>^position</code> of a match variable, it is the range of that
match variable.</p>
<h3 id="unmark-word-all"><code>^unmark ( word all )</code></h3>
<p>All references to word (or <code>~concept</code> if you named one)
are removed from anywhere in the sentence.</p>
<p><code>Generic:</code> effects are transient if done inside a pattern,
last the volley if done in output. When you are trying to analyze pieces
of a sentence, you may want to have a pattern that finds a kind of word,
notes information, then hides that kind of word and reanalyzes the input
again looking for another of that ilk.</p>
<p>Being able to temporarily hide marks can be quite useful, and this
means typically you use <code>^unmark</code> of some flavor to hide
words, and then <code>^mark</code> later to reenable access to those
hidden words.</p>
<h3 id="unmark-_0"><code>^unmark ( * _0 )</code></h3>
<p>Turns off ALL matches on this location temporarily. The word becomes
invisible and takes up no space in the sentence. It disables matching at
any of the words spanned by the match variable. This unmark will also
block subsequent specific marking using <code>^mark</code> at their
locations.</p>
<h3 id="unmark-_0-1"><code>^unmark ( @ _0 )</code></h3>
<p>Turns off ALL matches on this location range but keep the word
visible. It cannot be matched by anything but a wildcard and takes up
its space in the sentence. Often this is used before something like
<code>mark(~city _0)</code> where you are taking something with
ambiguous meanings, like “nice”, and removing all wrong meanings (and
right ones) and putting back just right ones. This is a way for the rest
of processing to only see the correct interpretation of a word.</p>
<p>Turns off matching on all words of the sentence.</p>
<h3 id="mark-_0"><code>^mark ( * _0 )</code></h3>
<p>To restore all marks to some location after having used ^unmark(*
_0)</p>
<h3 id="unmark-1"><code>^unmark ( * )</code></h3>
<p>Turn off all words of the sentence. Probably not that useful.</p>
<h3 id="mark-1"><code>^mark ( * )</code></h3>
<p>Restores all marks of the sentence, for words that had ^unmark(* _0)
performed.</p>
<p>Reminder: If you do a generic unmark from within a pattern, it is
transient and will be turned off when the pattern match finishes (so you
don’t ruin later rules), whereas when you do it from output, then the
change persists for the rest of the volley. Furthermore it is handy to
flip specific collections of generic unmarks on an off.</p>
<h3 id="replacewordword-_0"><code>^replaceword(word _0)</code></h3>
<p>You can change the word itself at the location just by providing the
word you want used and the location in the sentence (as a match variable
or position index). Replacing a word does not make it visible to pattern
matching. It is merely what will be retrieved (for both original and
canonical).</p>
<h3
id="addwordatword-canonical-_0"><code>^addwordAt(word canonical _0)</code></h3>
<p>Inserts word into sentence at the position of given match variable,
moving what was there one farther over. The second argument designates
the canonical to use and the third is a a position, and can be a match
variable name or something that evaluates into a word index. Does not
alter pos-tagging or parsing and does not mark itself. You can use ^mark
to cause marking to happen. Fails if sentence is already full to brim
with words.</p>
<h3
id="position-how-matchvariable"><code>^position ( how matchvariable )</code></h3>
<p>This returns the integer representing where the named match variable
is located.</p>
<p><em>how</em> can be <code>START</code>, <code>END</code>, or
<code>BOTH</code>. Both means an encoding of where the start and end of
the the match was. See <code>@_n</code> in pattern matching to set a
position or the <code>^setposition</code> function.</p>
<h3 id="marked-word"><code>^marked ( word )</code></h3>
<p>returns <code>1</code> if word is marked, returns
<code>FAILRULE_BIT</code> if the given word is not currently marked from
the current sentence.</p>
<h3
id="setposition-_var-start-end"><code>^setposition ( _var start end )</code></h3>
<p>Sets the match location data of a match var to the number values
given.</p>
<p>Alternatively you can do <code>^setposition ( _var _var1 )</code>,
which is redundant with just doing <code>_var = _var1</code>.</p>
<p>Another alternative is
<code>^setposition ( _var1 _var2 original )</code>, which will set the
position of <code>_var1</code> to the actual positions that the original
word <code>_var2</code> was expanded to. This is equivalent to using</p>
<pre><code>$_start = ^position( START _var2 )
$_end = ^position( END _var2 )
$_original = ^originalinputrange( $_start $_end )
$_originalStart = $_original >> 8
$_originalEnd = $_original & 255
$_actual = ^actualinputrange( $_originalStart $_originalEnd )
$_actualStart = $_actual >> 8
$_actualEnd = $_actual & 255
^setposition( _var1 $_actualStart $_actualEnd )</code></pre>
<h3
id="setcanon-wordindex-value"><code>^setcanon ( wordindex value )</code></h3>
<p>Changes the canonical value for this word.</p>
<h3
id="settag-wordindex-value"><code>^settag ( wordindex value )</code></h3>
<p>Changes the pos tag for the word.</p>
<h3
id="setoriginal-wordindex-value"><code>^setoriginal ( wordindex value )</code></h3>
<p>Changes the original value for this word.</p>
<h3
id="setrole-wordindex-value"><code>^setrole ( wordindex value )</code></h3>
<p>Changes the parse role for this word. These are used in conjunction
with <code>$cs_externaltag</code> to replace the CS inbuilt English
postagger and parser with one from outside. See end of ChatScript
PosParser manual.</p>
<h3
id="savesentence-label-restoresentence-label"><code>^savesentence ( label )</code>
/ <code>^restoresentence ( label )</code></h3>
<p>These two functions save and restore the current entire sentence
preparation context. That means everything that pattern matching depends
upon from the current sentence can be saved, you can go on to a new
sentence (either via <code>^next(INPUT)</code> or
<code>^analyze()</code> or whatever), and then rapidly flip back to some
previous sentence analysis. Label is a value used to label the saved
analysis. This only works during the current volley.</p>
<p>Cannot be used in document mode. <code>^savesentence</code> returns
the number of 4-byte words the save took.</p>
<h1 id="input-functions">Input Functions</h1>
<h3 id="analyze-stream"><code>^analyze ( stream )</code></h3>
<p>The stream generates output (not printed to user) and then prepares
the content as though it were current input sentence. This means the
current sentence flagging and marking are all replaced by this one’s. It
does not affect any pending input still to be processed. If the stream
is quoted string, the quotes are removed. This would be common, for
example, when analyzing output from the chatbot gotten via grabbing
facts with “chatoutput” as the verb.</p>
<p>Note that the stream is considered a single sentence. If you want to
supply multiple sentences, you need to call <code>^tokenize</code> and
then loop on the facts created.</p>
<p>Note that <code>^analyze</code> does not call any prepass topic you
may have, but you can invoke that topic directly aterwards yourself.</p>
<h3
id="tokenize-word-sentence-stream"><code>^tokenize ( {WORD SENTENCE} stream )</code></h3>
<p><code>WORD</code> or <code>SENTENCE</code> are optional parameters
(<code>SENTENCE</code> is default).</p>
<p>If <code>SENTENCE</code>, then splits the stream into sentences and
creates facts of each like this:
<code>(sentence ^tokenize ^tokenize)</code>.</p>
<p>If <code>WORD</code>, then splits it entirely into words paying no
attention to sentence boundaries.</p>
<h3 id="capitalized-n"><code>^capitalized ( n )</code></h3>
<p>Returns <code>1</code> if the nth word of the sentences starts with a
capital letter in user input, else returns <code>0</code>.</p>
<p>If <em>n</em> is alphabetic, it returns whether or not it starts with
a capital letter. Illegal values of n return failrule.</p>
<h3 id="input"><code>^input ( … )</code></h3>
<p>The arguments, separated by spaces, are injected back into the input
stream as the next input, processed before any pending additional input.
Typically this command is then followed by <code>^fail(SENTENCE)</code>
to cancel current processing and move onto the revised input.</p>
<p>Since the sentence is fed in immediately after the current input, if
you want to feed in multiple sentences, you must reverse the order so
the last sentence to be processed is submitted via input first. You can
detect that the current sentence comes from <code>^input</code> and not
from the user by <code>%revisedInput</code> (bool) being true (1).</p>
<p>Note: the input sentence is not what the user originally typed, so
don’t expect it to reflect appropriately in %originalInput. Also it is
tokenized on entry, so things like commas may already have been
separated.</p>
<h3
id="original-_n-or-originalrawuser"><code>^original ( _n ) or ^original(rawuser)</code></h3>
<p>The argument is the name of a match variable. Whatever it has
memorized will be used to locate the corresponding series of words in
the original raw input from the user that led to this match. That is,
the value is prior to any spell correction done by ChatScript.</p>
<pre><code>u: (my _life) ^original(_0)</code></pre>
<p>For input “my lif” spell correction will change the input to “life”,
which matches here, but ^original will return “lif”.</p>
<p><code>^original(rawuser)</code> returns exactly what user sent in,
before any adjustments are made to it. (Some adjustments are made even
before spellcheck).</p>
<h3 id="position-which-_var"><code>^position ( which _var )</code></h3>
<p>If <em>which</em> is <code>start</code> this returns the starting
index of the word matched in the named <code>_var</code>.</p>
<p>If <em>which</em> is <code>end</code> this returns the ending index.
E.g.,</p>
<p>if the value of <code>_1</code> was <em>the fox</em>, it might be
that start was 3 and end was 4 in the sentence <em>it was the fox</em>
.</p>
<p>If the match var matched a fundmental meaning, then you can use which
values of <code>subject</code>, <code>verb</code>, and
<code>object</code>. The verb is where start and end both yield.</p>
<h3
id="removetokenflags-value"><code>^removetokenflags ( value )</code></h3>
<p>Rremoves these flags from the tokenflags returned from the
preprocessing stage.</p>
<h3 id="settokenflags-value"><code>^settokenflags ( value )</code></h3>
<p>Adds these flags to the tokenflags return from the preprocessing
stage. Particularly useful for setting the <code>#QUESTIONMARK</code>
flag indicating the input was perceived to be a question.</p>
<p>For example, I treat <em>tell me about cars</em> sentences as
questions by marking them as such from script (equivalent to <em>what do
you know about cars?</em>).</p>
<p>Note that the change will not impact rule matching within the topic
you have just done the change, because it has commited the set of rules
it will try to match. So it only applies to later topics.</p>
<h3
id="setwildcardindex-value"><code>^setwildcardindex ( value )</code></h3>
<p>Tells the system to start at <code>value</code> for future
allocations of wildcard slots. This is only useful inside some pattern
where you are trying to protect data from some previous match. Eg.</p>
<pre><code>u: (_~animals) refine()
a: ( ^setwildcardindex(_1) _~color)</code></pre>
<p><code>_0</code> is set to an animal. Normally the rejoinder would set
a color onto <code>_0</code> and clobber it, but the call to
<code>^setwildcardindex</code> forces it to use <code>_1</code> instead,
so both <code>_0</code> and <code>_1</code> have values.</p>
<h3
id="isnormalword-letteronly-value"><code>^isnormalword ({letteronly} value)</code></h3>
<p>Fails if value has a character that is not alphabetic, numberic, a
hyphen, an underscore, or an apostrophe. If the optional letteronly is
given, then only alphabetic is allowed.</p>
<h1 id="number-functions">Number Functions</h1>
<h3
id="compute-number-operator-number"><code>^compute ( number operator number )</code></h3>
<p>Performs arithmetic and puts the result into the output stream.</p>
<p>Numbers can be integer or float and will convert appropriately. There
are a range of operators that have synonyms, so you can pass in directly
what the user wrote. The answer will be <code>?</code> if the operation
makes no sense and infinity if you divide by <code>0</code>.</p>
<p><code>~numberOperator</code> recognizes these operations:</p>
<table>
<thead>
<tr class="header">
<th>operator symbol</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>+</code></td>
<td>plus add and (addition)</td>
</tr>
<tr class="even">
<td><code>-</code></td>
<td>minus subtract deduct (subtraction)</td>
</tr>
<tr class="odd">
<td><code>*</code></td>
<td>x time multiply (multiplication)</td>
</tr>
<tr class="even">
<td><code>/</code></td>
<td>divide quotient (float division)</td>
</tr>
<tr class="odd">
<td><code>%</code></td>
<td>remainder modulo mod (integer only- modulo)</td>
</tr>
<tr class="even">
<td><code>root</code></td>
<td>square_root (square root)</td>
</tr>
<tr class="odd">
<td><code>^^</code></td>
<td>power exponent (exponent )</td>
</tr>
<tr class="even">
<td><code><<</code> and <code>>></code></td>
<td>shift (limited to shifting 31 bits or less)</td>
</tr>
<tr class="odd">
<td><code>random</code></td>
<td>( 0 random 7 means 0,1,2,3,4,5,6 - integer only)</td>
</tr>
</tbody>
</table>
<p>Basic operations can be done directly in assignment statements
like:</p>
<pre><code>$var = $x + 43 - 28</code></pre>
<p>The random function is only pseudo-random. A specific username is
assigned a seed based on their name. Thereafter the seed evolves by the
dialog but it is repeatable when the same user starts over again. If you
want truly random, use %fullmstime % $howmany to get range 0 ..
$howmany-1</p>
<h3
id="timefromseconds-seconds-offset"><code>^timefromseconds ( seconds {offset} )</code></h3>
<p>This converts time in seconds (Unix epoch time) from the given time
in whatever timezone, to a string like <code>%time</code> returns. You
can compute a difference in times by merely doing a subtraction of the
two times. <code>%fulltime</code> will give you the current time that
you could plug in here. The optional second argument will displace that
time by the hours offset (can be plus or minus).</p>
<h3
id="timeinfofromseconds-seconds"><code>^timeinfofromseconds ( seconds )</code></h3>
<p>This converts time in seconds (Unix epoch time) into its component
bits, spread across 7 match variables. Starting by default at
<code>_0</code>, if you assign it like this:</p>
<pre><code>_3 = ^timeinfofromseconds(%fulltime)</code></pre>
<p>it will start at <code>_3</code>. The items you get are:</p>
<table>
<thead>
<tr class="header">
<th>value</th>
<th>offset</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>seconds</td>
<td>0</td>
</tr>
<tr class="even">
<td>minutes</td>
<td>1</td>
</tr>
<tr class="odd">
<td>hours</td>
<td>2</td>
</tr>
<tr class="even">
<td>date in month</td>
<td>3</td>
</tr>
<tr class="odd">
<td>month name</td>
<td>4</td>
</tr>
<tr class="even">
<td>year</td>
<td>5</td>
</tr>
<tr class="odd">
<td>day name of week</td>
<td>6</td>
</tr>
<tr class="even">
<td>month index (jan==0)</td>
<td>7</td>
</tr>
<tr class="odd">
<td>dayofweek index (sun==0)</td>
<td>8</td>
</tr>
</tbody>
</table>
<h3
id="timetoseconds-seconds-minutes-hours-date-of-month-month-year"><code>^timetoseconds ( seconds minutes hours date-of-month month year )</code></h3>
<p>This converts time data since 1970 (Unix epoch time). Analogous to
<code>%fulltime</code>, which returns the current time in seconds. Month
can be number 1-12 or name of month or abbreviation of month.
Date-of-month must be 1 or more. Year must be on or 1970 and less than
2100. Optional 7th argument indicates whether time is within daylight
savings or not , values can be 1 or 0, t or f, T or F. Default is
false.</p>
<h3 id="isnumber-value"><code>^isnumber ( value )</code></h3>
<p>Fails if value is not an integer, float, or currency,</p>
<h1 id="output-functions">Output Functions</h1>
<p>The following functions cannot be used during postprocessing since
output has been finished in theory and you can now analyze it.</p>
<h3 id="flushoutput"><code>^flushoutput()</code></h3>
<p>Takes any current pending output stream data and sends it out. If the
rule later fails, the output has been protected and will still go out
(though the rule will not erase itself).</p>
<h3
id="insertprint-where-stream"><code>^insertprint ( where stream )</code></h3>
<p>The stream will be put into output, but it will be placed before
output number where or before output issued by the topic named by where.
The output is safe in that even if the rule later fails, this output
will go out. Before the where, you may put in output control flags as
either a simple value or a value list in parens.</p>
<h3
id="keephistory-who-count"><code>^keephistory ( who count )</code></h3>
<p>The history of either <code>BOT</code> or <code>USER</code> (values
of who) will be cut back to the count give. This affects detecting
repeated input on the part of the user or detecting repeating output by
the chatbot.</p>
<h3 id="lastsaid"><code>^lastsaid ()</code></h3>
<p>Returns what the bot said last volley.</p>
<h3
id="print-stdout-log-stream"><code>^print ( {stdout, log} stream )</code></h3>
<p>Sends the results of outputing that stream to the user. It is
isolated from the normal output stream, and goes to the user whether or
not one later generates a failure code from the rule. Before the output
you may put in output control flags as either a simple value without a
<code>#</code> (e.g., <code>OUTPUT_EVALCODE</code> ) or a value list in
parens.</p>
<p>By default it goes to the user log (or if log is specified) but if
stdout is specified it goes to the console.</p>
<p>Flags include:</p>
<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 49%" />
</colgroup>
<thead>
<tr class="header">
<th>Flag</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>OUTPUT_EVALCODE</code></td>
<td>is automatic, so not particularly useful. <br>Useful ones would
control how print decides to space things</td>
</tr>
<tr class="even">
<td><code>OUTPUT_RAW</code></td>
<td>does not attempt to interpret ( or <code>{</code> or <code>[</code>
or <code>"</code></td>
</tr>
<tr class="odd">
<td><code>OUTPUT_RETURNVALUE_ONLY</code></td>
<td>does not go to the user, is merely return as an answer. Print
normally stores directly into the response system, meaning failing the
rule later has no effect. Print normally does not return a value so you
can’t store it into a variable. And print has a number of flags that can
affect its formatting that dont exist with normal output. This flag
converts print into an ordinary function returning a value, reversing
all those differences</td>
</tr>
<tr class="even">
<td><code>OUTPUT_NOCOMMANUMBER</code></td>
<td>dont add commas to numbers</td>
</tr>
<tr class="odd">
<td><code>OUTPUT_NOQUOTES</code></td>