Imported Upstream version 6.12.1~dfsg.1
[debian_inform6-library.git] / verblibm.h
blobc33712068f90edbfa67814d5294d11a20ba46834
1 ! ==============================================================================
2 ! VERBLIBM: Core of standard verbs library.
4 ! Supplied for use with Inform 6 -- Release 6.12.1 -- Serial number 160605
6 ! Copyright Graham Nelson 1993-2004 and David Griffith 2012-2016
8 ! This code is licensed under either the traditional Inform license as
9 ! described by the DM4 or the Artistic License version 2.0. See the
10 ! file COPYING in the distribution archive or at
11 ! https://github.com/DavidGriffith/inform6lib/
13 ! This file is automatically Included in your game file by "VerbLib".
14 ! ==============================================================================
16 System_file;
18 #Ifdef MODULE_MODE;
19 Constant DEBUG;
20 Constant Grammar__Version 2;
21 Include "linklpa";
22 Include "linklv";
23 #Endif; ! MODULE_MODE
25 ! ------------------------------------------------------------------------------
27 [ Banner i;
28 #Ifdef LanguageBanner;
29 LanguageBanner();
30 i = 0; ! suppress warning
31 #Ifnot;
32 if (Story) {
33 #Ifdef TARGET_ZCODE;
34 #IfV5; style bold; #Endif;
35 print "^", (string) Story;
36 #IfV5; style roman; #Endif;
37 #Ifnot; ! TARGET_GLULX;
38 glk_set_style(style_Header);
39 print "^", (string) Story;
40 glk_set_style(style_Normal);
41 #Endif; ! TARGET_
43 if (Headline) print (string) Headline;
44 #Ifdef TARGET_ZCODE;
45 print "Release ", (HDR_GAMERELEASE-->0) & $03ff, " / Serial number ";
46 for (i=0 : i<6 : i++) print (char) HDR_GAMESERIAL->i;
47 #Ifnot; ! TARGET_GLULX;
48 print "Release ";
49 @aloads ROM_GAMERELEASE 0 i;
50 print i;
51 print " / Serial number ";
52 for (i=0 : i<6 : i++) print (char) ROM_GAMESERIAL->i;
53 #Endif; ! TARGET_
54 print " / Inform v"; inversion;
55 print " Library v", (string) LibRelease, " ";
56 #Ifdef STRICT_MODE;
57 print "S";
58 #Endif; ! STRICT_MODE
59 #Ifdef INFIX;
60 print "X";
61 #Ifnot;
62 #Ifdef DEBUG;
63 print "D";
64 #Endif; ! DEBUG
65 #Endif; ! INFIX
66 new_line;
67 #Endif; ! LanguageBanner
70 [ VersionSub ix;
71 #Ifdef LanguageVersionSub;
72 LanguageVersionSub();
73 ix = 0; ! suppress warning
74 #Ifnot;
75 Banner();
76 #Ifdef TARGET_ZCODE;
77 ix = 0; ! shut up compiler warning
78 if (standard_interpreter > 0) {
79 print "Standard interpreter ", standard_interpreter/256, ".", standard_interpreter%256,
80 " (", HDR_TERPNUMBER->0;
81 #Iftrue (#version_number == 6);
82 print (char) '.', HDR_TERPVERSION->0;
83 #Ifnot;
84 print (char) HDR_TERPVERSION->0;
85 #Endif;
86 print ") / ";
88 else {
89 print "Interpreter ", HDR_TERPNUMBER->0, " Version ";
90 #Iftrue (#version_number == 6);
91 print HDR_TERPVERSION->0;
92 #Ifnot;
93 print (char) HDR_TERPVERSION->0;
94 #Endif;
95 print " / ";
98 #Ifnot; ! TARGET_GLULX;
99 @gestalt 1 0 ix;
100 print "Interpreter version ", ix / $10000, ".", (ix & $FF00) / $100,
101 ".", ix & $FF, " / ";
102 @gestalt 0 0 ix;
103 print "VM ", ix / $10000, ".", (ix & $FF00) / $100, ".", ix & $FF, " / ";
104 #Endif; ! TARGET_;
105 print "Library serial number ", (string) LibSerial, "^";
106 #Ifdef LanguageVersion;
107 print (string) LanguageVersion, "^";
108 #Endif; ! LanguageVersion
109 #Endif; ! LanguageVersionSub
112 [ RunTimeError n p1 p2;
113 #Ifdef LanguageError;
114 LanguageError(n, p1, p2);
115 #Ifnot;
116 #Ifdef DEBUG;
117 print "** Library error ", n, " (", p1, ", ", p2, ") **^** ";
118 switch (n) {
119 1: print "preposition not found (this should not occur)";
120 2: print "Property value not routine or string: ~", (property) p2, "~ of ~", (name) p1,
121 "~ (", p1, ")";
122 3: print "Entry in property list not routine or string: ~", (property) p2, "~ list of ~",
123 (name) p1, "~ (", p1, ")";
124 4: print "Too many timers/daemons are active simultaneously.
125 The limit is the library constant MAX_TIMERS
126 (currently ", MAX_TIMERS, ") and should be increased";
127 5: print "Object ~", (name) p1, "~ has no ~", (property) p2, "~ property";
128 7: print "The object ~", (name) p1, "~ can only be used as a player object if it has
129 the ~number~ property";
130 8: print "Attempt to take random entry from an empty table array";
131 9: print p1, " is not a valid direction property number";
132 10: print "The player-object is outside the object tree";
133 11: print "The room ~", (name) p1, "~ has no ~", (property) p2, "~ property";
134 12: print "Tried to set a non-existent pronoun using SetPronoun";
135 13: print "A 'topic' token can only be followed by a preposition";
136 14: print "Overflowed buffer limit of ", p1, " using '@@64output_stream 3' ", (string) p2;
137 15: print "LoopWithinObject broken because the object ", (name) p1, " was moved while the loop passed through it.";
138 16: print "Attempt to use illegal narrative_voice of ", p1, ".";
139 default:
140 print "(unexplained)";
142 " **";
143 #Ifnot;
144 "** Library error ", n, " (", p1, ", ", p2, ") **";
145 #Endif; ! DEBUG
146 #Endif; ! LanguageError
149 ! ----------------------------------------------------------------------------
150 ! The WriteListFrom routine, a flexible object-lister taking care of
151 ! plurals, inventory information, various formats and so on. This is used
152 ! by everything in the library which ever wants to list anything.
154 ! If there were no objects to list, it prints nothing and returns false;
155 ! otherwise it returns true.
157 ! o is the object, and style is a bitmap, whose bits are given by:
158 ! ----------------------------------------------------------------------------
161 Constant NEWLINE_BIT $0001; ! New-line after each entry
162 Constant INDENT_BIT $0002; ! Indent each entry by depth
163 Constant FULLINV_BIT $0004; ! Full inventory information after entry
164 Constant ENGLISH_BIT $0008; ! English sentence style, with commas and and
165 Constant RECURSE_BIT $0010; ! Recurse downwards with usual rules
166 Constant ALWAYS_BIT $0020; ! Always recurse downwards
167 Constant TERSE_BIT $0040; ! More terse English style
168 Constant PARTINV_BIT $0080; ! Only brief inventory information after entry
169 Constant DEFART_BIT $0100; ! Use the definite article in list
170 Constant WORKFLAG_BIT $0200; ! At top level (only), only list objects
171 ! which have the "workflag" attribute
172 Constant ISARE_BIT $0400; ! Print " is" or " are" before list
173 Constant CONCEAL_BIT $0800; ! Omit objects with "concealed" or "scenery":
174 ! if WORKFLAG_BIT also set, then does _not_
175 ! apply at top level, but does lower down
176 Constant NOARTICLE_BIT $1000; ! Print no articles, definite or not
177 Constant ID_BIT $2000; ! Print object id after each entry
179 [ NextEntry o odepth;
180 for (::) {
181 o = sibling(o);
182 if (o == 0) return 0;
183 if (lt_value && o.list_together ~= lt_value) continue;
184 if (c_style & WORKFLAG_BIT && odepth==0 && o hasnt workflag) continue;
185 if (c_style & CONCEAL_BIT && (o has concealed || o has scenery)) continue;
186 return o;
190 [ WillRecurs o;
191 if (c_style & ALWAYS_BIT) rtrue;
192 if (c_style & RECURSE_BIT == 0) rfalse;
193 if ((o has transparent or supporter) || (o has container && o has open)) rtrue;
194 rfalse;
197 [ ListEqual o1 o2;
198 if (child(o1) && WillRecurs(o1)) rfalse;
199 if (child(o2) && WillRecurs(o2)) rfalse;
200 if (c_style & (FULLINV_BIT + PARTINV_BIT)) {
201 if ((o1 hasnt worn && o2 has worn) || (o2 hasnt worn && o1 has worn)) rfalse;
202 if ((o1 hasnt light && o2 has light) || (o2 hasnt light && o1 has light)) rfalse;
203 if (o1 has container) {
204 if (o2 hasnt container) rfalse;
205 if ((o1 has open && o2 hasnt open) || (o2 has open && o1 hasnt open))
206 rfalse;
208 else if (o2 has container)
209 rfalse;
211 return Identical(o1, o2);
214 [ SortTogether obj value;
215 ! print "Sorting together possessions of ", (object) obj, " by value ", value, "^";
216 ! for (x=child(obj) : x : x=sibling(x))
217 ! print (the) x, " no: ", x, " lt: ", x.list_together, "^";
218 while (child(obj)) {
219 if (child(obj).list_together ~= value) move child(obj) to out_obj;
220 else move child(obj) to in_obj;
222 while (child(in_obj)) move child(in_obj) to obj;
223 while (child(out_obj)) move child(out_obj) to obj;
226 [ SortOutList obj i k l;
227 ! print "^^Sorting out list from ", (name) obj, "^ ";
228 ! for (i=child(location) : i : i=sibling(i))
229 ! print (name) i, " --> ";
230 ! new_line;
232 .AP_SOL;
234 for (i=obj : i : i=sibling(i)) {
235 k = i.list_together;
236 if (k ~= 0) {
237 ! print "Scanning ", (name) i, " with lt=", k, "^";
238 for (i=sibling(i) : i && i.list_together == k :) i = sibling(i);
239 if (i == 0) rfalse;
240 ! print "First not in block is ", (name) i, " with lt=", i.list_together, "^";
241 for (l=sibling(i) : l : l=sibling(l))
242 if (l.list_together == k) {
243 SortTogether(parent(obj), k);
244 ! print "^^After ST:^ ";
245 ! for (i=child(location) : i : i=sibling(i))
246 ! print (name) i, " --> ";
247 ! new_line;
248 obj = child(parent(obj));
249 jump AP_SOL;
255 #Ifdef TARGET_ZCODE;
257 [ Print__Spaces n; ! To avoid a bug occurring in Inform 6.01 to 6.10
258 if (n == 0) return;
259 spaces n;
262 #Ifnot; ! TARGET_GLULX;
264 [ Print__Spaces n;
265 while (n > 0) {
266 @streamchar ' ';
267 n = n - 1;
271 #Endif; ! TARGET_
273 [ WriteListFrom o style depth
274 s1 s2 s3 s4 s5 s6;
276 if (o == nothing) return 0;
278 s1 = c_style; s2 = lt_value; s3 = listing_together;
279 s4 = listing_size; s5 = wlf_indent; s6 = inventory_stage;
281 if (o == child(parent(o))) {
282 SortOutList(o);
283 o = child(parent(o));
285 c_style = style;
286 wlf_indent = 0;
287 if (WriteListR(o, depth) == 0) return 0;
289 c_style = s1; lt_value = s2; listing_together = s3;
290 listing_size = s4; wlf_indent = s5; inventory_stage = s6;
291 rtrue;
294 [ WriteListR o depth stack_pointer classes_p sizes_p i j k k2 l m n q senc mr;
295 if (depth > 0 && o == child(parent(o))) {
296 SortOutList(o);
297 o = child(parent(o));
299 for (::) {
300 if (o == 0) rfalse;
301 if (c_style & WORKFLAG_BIT && depth==0 && o hasnt workflag) {
302 o = sibling(o);
303 continue;
305 if (c_style & CONCEAL_BIT && (o has concealed || o has scenery)) {
306 o = sibling(o);
307 continue;
309 break;
311 classes_p = match_classes + stack_pointer;
312 sizes_p = match_list + stack_pointer;
314 for (i=o,j=0 : i && (j+stack_pointer)<128 : i=NextEntry(i,depth),j++) {
315 classes_p->j = 0;
316 if (i.plural) k++;
319 if (c_style & ISARE_BIT) {
320 if (j == 1 && o hasnt pluralname) Tense(IS__TX, WAS__TX);
321 else Tense(ARE__TX, WERE__TX);
322 if (c_style & NEWLINE_BIT) print ":^";
323 else print (char) ' ';
324 c_style = c_style - ISARE_BIT;
327 stack_pointer = stack_pointer+j+1;
329 if (k < 2) jump EconomyVersion; ! It takes two to plural
330 n = 1;
331 for (i=o,k=0 : k<j : i=NextEntry(i,depth),k++)
332 if (classes_p->k == 0) {
333 classes_p->k = n; sizes_p->n = 1;
334 for (l=NextEntry(i,depth),m=k+1 : l && m<j : l=NextEntry(l,depth),m++)
335 if (classes_p->m == 0 && i.plural && l.plural ~= 0) {
336 if (ListEqual(i, l) == 1) {
337 sizes_p->n = sizes_p->n + 1;
338 classes_p->m = n;
341 n++;
343 n--;
345 for (i=1,j=o,k=0 : i<=n : i++,senc++) {
346 while (((classes_p->k) ~= i) && ((classes_p->k) ~= -i)) {
347 k++; j=NextEntry(j, depth);
349 m = sizes_p->i;
350 if (j == 0) mr = 0;
351 else {
352 if (j.list_together ~= 0 or lt_value && metaclass(j.list_together) == Routine or String &&
353 j.list_together == mr) senc--;
354 mr = j.list_together;
357 senc--;
359 for (i=1,j=o,k=0,mr=0 : senc>=0 : i++,senc--) {
360 while (((classes_p->k) ~= i) && ((classes_p->k) ~= -i)) {
361 k++; j=NextEntry(j, depth);
363 if (j.list_together ~= 0 or lt_value) {
364 if (j.list_together == mr) {
365 senc++;
366 jump Omit_FL2;
368 k2 = NextEntry(j, depth);
369 if (k2 == 0 || k2.list_together ~= j.list_together) jump Omit_WL2;
370 k2 = metaclass(j.list_together);
371 if (k2 == Routine or String) {
372 q = j; listing_size = 1; l = k; m = i;
373 while (m < n && q.list_together == j.list_together) {
374 m++;
375 while (((classes_p->l) ~= m) && ((classes_p->l) ~= -m)) {
376 l++; q = NextEntry(q, depth);
378 if (q.list_together == j.list_together) listing_size++;
380 ! print " [", listing_size, "] ";
381 if (listing_size == 1) jump Omit_WL2;
382 if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
383 if (k2 == String) {
384 q = 0;
385 for (l=0 : l<listing_size : l++) q = q+sizes_p->(l+i);
386 EnglishNumber(q); print " ";
387 print (string) j.list_together;
388 if (c_style & ENGLISH_BIT) print " (";
389 if (c_style & INDENT_BIT) print ":^";
391 q = c_style;
392 if (k2 ~= String) {
393 inventory_stage = 1;
394 parser_one = j; parser_two = depth+wlf_indent;
395 if (RunRoutines(j, list_together) == 1) jump Omit__Sublist2;
398 #Ifdef TARGET_ZCODE;
399 @push lt_value; @push listing_together; @push listing_size;
400 #Ifnot; ! TARGET_GLULX;
401 @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
402 #Endif; ! TARGET_;
404 lt_value = j.list_together; listing_together = j; wlf_indent++;
405 WriteListR(j, depth, stack_pointer); wlf_indent--;
407 #Ifdef TARGET_ZCODE;
408 @pull listing_size; @pull listing_together; @pull lt_value;
409 #Ifnot; ! TARGET_GLULX;
410 @copy sp listing_size;
411 @copy sp listing_together;
412 @copy sp lt_value;
413 #Endif; ! TARGET_;
415 if (k2 == String) {
416 if (q & ENGLISH_BIT) print ")";
418 else {
419 inventory_stage = 2;
420 parser_one = j; parser_two = depth+wlf_indent;
421 RunRoutines(j, list_together);
424 .Omit__Sublist2;
426 if (q & NEWLINE_BIT && c_style & NEWLINE_BIT == 0) new_line;
427 c_style = q;
428 mr = j.list_together;
429 jump Omit_EL2;
433 .Omit_WL2;
435 if (WriteBeforeEntry(j, depth, 0, senc) == 1) jump Omit_FL2;
436 if (sizes_p->i == 1) {
437 if (c_style & NOARTICLE_BIT) print (name) j;
438 else {
439 if (c_style & DEFART_BIT) print (the) j;
440 else print (a) j;
442 if (c_style & ID_BIT) print " (", j, ")";
444 else {
445 if (c_style & DEFART_BIT) PrefaceByArticle(j, 1, sizes_p->i);
446 print (number) sizes_p->i, " ";
447 PrintOrRun(j, plural, 1);
449 if (sizes_p->i > 1 && j hasnt pluralname) {
450 give j pluralname;
451 WriteAfterEntry(j, depth, stack_pointer);
452 give j ~pluralname;
454 else {
455 WriteAfterEntry(j,depth,stack_pointer);
457 .Omit_EL2;
459 if (c_style & ENGLISH_BIT) {
460 if (senc == 1) print (SerialComma) i+senc, (string) AND__TX;
461 if (senc > 1) print (string) COMMA__TX;
463 .Omit_FL2;
465 rtrue;
467 .EconomyVersion;
469 n = j;
470 for (i=1,j=o : i<=n : j=NextEntry(j,depth),i++,senc++) {
471 if (j.list_together ~= 0 or lt_value && metaclass(j.list_together) == Routine or String &&
472 j.list_together==mr) senc--;
473 mr = j.list_together;
476 for (i=1,j=o,mr=0 : i<=senc : j=NextEntry(j,depth),i++) {
477 if (j.list_together ~= 0 or lt_value) {
478 if (j.list_together == mr) {
479 i--;
480 jump Omit_FL;
482 k = NextEntry(j, depth);
483 if (k == 0 || k.list_together ~= j.list_together) jump Omit_WL;
484 k = metaclass(j.list_together);
485 if (k == Routine or String) {
486 if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
487 if (k == String) {
488 q = j; l = 0;
489 do {
490 q = NextEntry(q, depth); l++;
491 } until (q == 0 || q.list_together ~= j.list_together);
492 EnglishNumber(l); print " ";
493 print (string) j.list_together;
494 if (c_style & ENGLISH_BIT) print " (";
495 if (c_style & INDENT_BIT) print ":^";
497 q = c_style;
498 if (k ~= String) {
499 inventory_stage = 1;
500 parser_one = j; parser_two = depth+wlf_indent;
501 if (RunRoutines(j, list_together) == 1) jump Omit__Sublist;
504 #Ifdef TARGET_ZCODE;
505 @push lt_value; @push listing_together; @push listing_size;
506 #Ifnot; ! TARGET_GLULX;
507 @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
508 #Endif; ! TARGET_;
510 lt_value = j.list_together; listing_together = j; wlf_indent++;
511 WriteListR(j, depth, stack_pointer); wlf_indent--;
513 #Ifdef TARGET_ZCODE;
514 @pull listing_size; @pull listing_together; @pull lt_value;
515 #Ifnot; ! TARGET_GLULX;
516 @copy sp listing_size; @copy sp listing_together; @copy sp lt_value;
517 #Endif; ! TARGET_;
519 if (k == String) {
520 if (q & ENGLISH_BIT) print ")";
522 else {
523 inventory_stage = 2;
524 parser_one = j; parser_two = depth+wlf_indent;
525 RunRoutines(j, list_together);
528 .Omit__Sublist;
530 if (q & NEWLINE_BIT && c_style & NEWLINE_BIT == 0) new_line;
531 c_style = q;
532 mr = j.list_together;
533 jump Omit_EL;
537 .Omit_WL;
539 if (WriteBeforeEntry(j, depth, i, senc) == 1) jump Omit_FL;
540 if (c_style & NOARTICLE_BIT) print (name) j;
541 else {
542 if (c_style & DEFART_BIT) print (the) j;
543 else print (a) j;
545 if (c_style & ID_BIT) print " (", j, ")";
546 WriteAfterEntry(j, depth, stack_pointer);
548 .Omit_EL;
550 if (c_style & ENGLISH_BIT) {
551 if (i == senc-1) print (SerialComma) senc, (string) AND__TX;
552 if (i < senc-1) print (string) COMMA__TX;
555 .Omit_FL;
558 ]; ! end of WriteListR
560 [ WriteBeforeEntry o depth ipos sentencepos
561 flag;
563 inventory_stage = 1;
564 if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
565 if (o.invent && (c_style & (PARTINV_BIT|FULLINV_BIT))) {
566 flag = PrintOrRun(o, invent, 1);
567 if (flag) {
568 if (c_style & ENGLISH_BIT) {
569 if (ipos == sentencepos-1)
570 print (SerialComma) sentencepos, (string) AND__TX;
571 if (ipos < sentencepos-1)
572 print (string) COMMA__TX;
574 if (c_style & NEWLINE_BIT) new_line;
577 return flag;
580 [ WriteAfterEntry o depth stack_p
581 p recurse_flag parenth_flag eldest_child child_count combo i j;
583 inventory_stage = 2;
584 if (c_style & PARTINV_BIT) {
585 if (o.invent && RunRoutines(o, invent))
586 if (c_style & NEWLINE_BIT) ""; else rtrue;
588 combo = 0;
589 if (o has light && location hasnt light) combo=combo+1;
590 if (o has container && o hasnt open) combo=combo+2;
591 if ((o has container && (o has open || o has transparent))) {
592 objectloop(i in o) {
593 if (i hasnt concealed && i hasnt scenery) {
594 j = true; break;
597 if (~~j) combo=combo+4;
599 if (combo) L__M(##ListMiscellany, combo, o);
600 } ! end of PARTINV_BIT processing
602 if (c_style & FULLINV_BIT) {
603 if (o.invent && RunRoutines(o, invent))
604 if (c_style & NEWLINE_BIT) ""; else rtrue;
606 if (o has light && o has worn) { L__M(##ListMiscellany, 8, o); parenth_flag = true; }
607 else {
608 if (o has light) { L__M(##ListMiscellany, 9, o); parenth_flag = true; }
609 if (o has worn) { L__M(##ListMiscellany, 10, o); parenth_flag = true; }
612 if (o has container)
613 if (o has openable) {
614 if (parenth_flag) print (string) AND__TX;
615 else L__M(##ListMiscellany, 11, o);
616 if (o has open)
617 if (child(o)) L__M(##ListMiscellany, 12, o);
618 else L__M(##ListMiscellany, 13, o);
619 else
620 if (o has lockable && o has locked) L__M(##ListMiscellany, 15, o);
621 else L__M(##ListMiscellany, 14, o);
622 parenth_flag = true;
624 else
625 if (child(o)==0 && o has transparent)
626 if (parenth_flag) L__M(##ListMiscellany, 16, o);
627 else L__M(##ListMiscellany, 17, o);
629 if (parenth_flag) print ")";
630 } ! end of FULLINV_BIT processing
632 if (c_style & CONCEAL_BIT) {
633 child_count = 0;
634 objectloop (p in o)
635 if (p hasnt concealed && p hasnt scenery) { child_count++; eldest_child = p; }
637 else { child_count = children(o); eldest_child = child(o); }
639 if (child_count && (c_style & ALWAYS_BIT)) {
640 if (c_style & ENGLISH_BIT) L__M(##ListMiscellany, 18, o);
641 recurse_flag = true;
644 if (child_count && (c_style & RECURSE_BIT)) {
645 if (o has supporter) {
646 if (c_style & ENGLISH_BIT) {
647 if (c_style & TERSE_BIT) L__M(##ListMiscellany, 19, o);
648 else L__M(##ListMiscellany, 20, o);
649 if (o has animate) print (string) WHOM__TX;
650 else print (string) WHICH__TX;
652 recurse_flag = true;
654 if (o has container && (o has open || o has transparent)) {
655 if (c_style & ENGLISH_BIT) {
656 if (c_style & TERSE_BIT) L__M(##ListMiscellany, 21, o);
657 else L__M(##ListMiscellany, 22, o);
658 if (o has animate) print (string) WHOM__TX;
659 else print (string) WHICH__TX;
661 recurse_flag = true;
665 if (recurse_flag && (c_style & ENGLISH_BIT))
666 if (child_count > 1 || eldest_child has pluralname) Tense(ARE2__TX, WERE2__TX);
667 else Tense(IS2__TX, WAS2__TX);
669 if (c_style & NEWLINE_BIT) new_line;
671 if (recurse_flag) {
672 o = child(o);
673 #Ifdef TARGET_ZCODE;
674 @push lt_value; @push listing_together; @push listing_size;
675 #Ifnot; ! TARGET_GLULX;
676 @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
677 #Endif;
678 lt_value = 0; listing_together = 0; listing_size = 0;
679 WriteListR(o, depth+1, stack_p);
680 #Ifdef TARGET_ZCODE;
681 @pull listing_size; @pull listing_together; @pull lt_value;
682 #Ifnot; ! TARGET_GLULX;
683 @copy sp listing_size; @copy sp listing_together; @copy sp lt_value;
684 #Endif;
685 if (c_style & TERSE_BIT) print ")";
689 ! ----------------------------------------------------------------------------
690 ! LoopWithinObject(rtn,obj,arg)
692 ! rtn is the address of a user-supplied routine.
693 ! obj is an optional parent object whose dependents are to be processed; the
694 ! default is the current actor (normally the player).
695 ! arg is an optional argument passed to the rtn; this can be a single variable
696 ! or constant, or the address of an array (which enables multiple values to be
697 ! passed and returned).
699 ! For each object o which is a child, grandchild, great-grandchild, etc, of the
700 ! original obj, LoopWithinObject() calls rtn(o,arg).
702 ! The rtn should perform any appropriate testing or processing on each object o,
703 ! using the optional arg value if necessary. If the rtn returns true (or any
704 ! positive value), the children of o, if any, are also tested; those children
705 ! are skipped if rtn returns false. To terminate the loop before all objects
706 ! have been processed, rtn should return a large negative number (eg -99).
708 ! To deal with supporters and open containers, so that objects are processed
709 ! only if they are accessible to the player, rtn might end with these
710 ! statements:
711 ! if ((o has transparent or supporter) || (o has container && o has open)) rtrue;
712 ! rfalse;
713 ! or alternatively with:
714 ! c_style = RECURSE_BIT; return WillRecurs(o);
716 ! LoopWithinObject() returns the number of objects which have been processed.
717 ! ----------------------------------------------------------------------------
719 [ LoopWithinObject rtn obj arg
720 n o x y;
721 if (obj == 0) obj = actor;
722 o = child(obj);
723 while (o) {
724 y = parent(o); n++;
725 x = rtn(o, arg); ! user-supplied routine returning x.
726 ! if x < 0: skip up to next parent
727 ! if x = 0: jump across to next sibling
728 ! if x > 0: continue down to child objects
729 if (y ~= parent(o)) { RunTimeError(15, o); rfalse; }
730 if (x > 0 && child(o)) o = child(o);
731 else
732 while (o) {
733 if (++x > 0 && sibling(o)) { o = sibling(o); break; }
734 o = parent(o);
735 if (o == obj) return n;
741 ! ----------------------------------------------------------------------------
742 ! Much better menus can be created using one of the optional library
743 ! extensions. These are provided for compatibility with previous practice:
744 ! ----------------------------------------------------------------------------
746 [ LowKey_Menu menu_choices EntryR ChoiceR lines main_title i j;
747 menu_nesting++;
749 .LKRD;
751 menu_item = 0;
752 lines = EntryR();
753 main_title = item_name;
755 print "--- "; print (string) main_title; print " ---^^";
757 if (menu_choices ofclass Routine) menu_choices();
758 else print (string) menu_choices;
760 for (::) {
761 L__M(##Miscellany, 52, lines);
762 print "> ";
764 #Ifdef TARGET_ZCODE;
765 #IfV3;
766 read buffer parse;
767 #Ifnot;
768 read buffer parse DrawStatusLine;
769 #Endif; ! V3
770 j = parse->1; ! number of words
771 #Ifnot; ! TARGET_GLULX;
772 KeyboardPrimitive(buffer, parse);
773 j = parse-->0; ! number of words
774 #Endif; ! TARGET_
776 i = parse-->1;
777 if (j == 0 || (i == QUIT1__WD or QUIT2__WD)) {
778 menu_nesting--; if (menu_nesting > 0) rfalse;
779 if (deadflag == 0) <<Look>>;
780 rfalse;
782 i = TryNumber(1);
783 if (i == 0) jump LKRD;
784 if (i < 1 || i > lines) continue;
785 menu_item = i;
786 j = ChoiceR();
787 if (j == 2) jump LKRD;
788 if (j == 3) rfalse;
792 #Ifdef TARGET_ZCODE;
794 #IfV3;
796 [ DoMenu menu_choices EntryR ChoiceR; LowKey_Menu(menu_choices, EntryR, ChoiceR); ];
798 #Endif; ! V3
800 #IfV5;
802 [ DoMenu menu_choices EntryR ChoiceR
803 lines main_title main_wid cl i j oldcl pkey ch cw y x;
804 if (pretty_flag == 0) return LowKey_Menu(menu_choices, EntryR, ChoiceR);
805 menu_nesting++;
806 menu_item = 0;
807 lines = EntryR();
808 main_title = item_name; main_wid = item_width;
809 cl = 7;
811 .ReDisplay;
813 oldcl = 0;
814 @erase_window $ffff;
815 #Iftrue (#version_number == 6);
816 @set_cursor -1;
817 ch = HDR_FONTWUNITS->0;
818 #Ifnot;
819 ch = 1;
820 #Endif;
821 i = ch * (lines+7);
822 @split_window i;
823 i = HDR_SCREENWCHARS->0;
824 if (i == 0) i = 80;
825 @set_window 1;
826 @set_cursor 1 1;
828 #Iftrue (#version_number == 6);
829 @set_font 4 -> cw;
830 cw = HDR_FONTHUNITS->0;
831 #Ifnot;
832 cw = 1;
833 #Endif;
835 style reverse;
836 spaces(i); j=1+(i/2-main_wid)*cw;
837 @set_cursor 1 j;
838 print (string) main_title;
839 y=1+ch; @set_cursor y 1; spaces(i);
840 x=1+cw; @set_cursor y x; print (string) NKEY__TX;
841 j=1+(i-13)*cw; @set_cursor y j; print (string) PKEY__TX;
842 y=y+ch; @set_cursor y 1; spaces(i);
843 @set_cursor y x; print (string) RKEY__TX;
844 j=1+(i-18)*cw; @set_cursor y j;
846 if (menu_nesting == 1) print (string) QKEY1__TX;
847 else print (string) QKEY2__TX;
848 style roman;
849 y = y+2*ch;
850 @set_cursor y x; font off;
852 if (menu_choices ofclass String) print (string) menu_choices;
853 else menu_choices();
855 x = 1+3*cw;
856 for (::) {
857 if (cl ~= oldcl) {
858 if (oldcl>0) {
859 y=1+(oldcl-1)*ch; @set_cursor y x; print " ";
861 y=1+(cl-1)*ch; @set_cursor y x; print ">";
864 oldcl = cl;
865 @read_char 1 -> pkey;
866 if (pkey == NKEY1__KY or NKEY2__KY or 130) {
867 cl++; if (cl == 7+lines) cl = 7; continue;
869 if (pkey == PKEY1__KY or PKEY2__KY or 129) {
870 cl--; if (cl == 6) cl = 6+lines; continue;
872 if (pkey == QKEY1__KY or QKEY2__KY or 27 or 131) break;
873 if (pkey == 10 or 13 or 132) {
874 @set_window 0; font on;
875 new_line; new_line; new_line;
877 menu_item = cl-6;
878 EntryR();
880 @erase_window $ffff;
881 @split_window ch;
882 i = HDR_SCREENWCHARS->0; if ( i== 0) i = 80;
883 @set_window 1; @set_cursor 1 1; style reverse; spaces(i);
884 j=1+(i/2-item_width)*cw;
885 @set_cursor 1 j;
886 print (string) item_name;
887 style roman; @set_window 0; new_line;
889 i = ChoiceR();
890 if (i == 2) jump ReDisplay;
891 if (i == 3) break;
893 L__M(##Miscellany, 53);
894 @read_char 1 -> pkey; jump ReDisplay;
898 menu_nesting--; if (menu_nesting > 0) rfalse;
899 font on; @set_cursor 1 1;
900 @erase_window $ffff; @set_window 0;
901 #Iftrue (#version_number == 6);
902 @set_cursor -2;
903 #Endif;
904 new_line; new_line; new_line;
905 if (deadflag == 0) <<Look>>;
908 #Endif; ! V5
910 #Ifnot; ! TARGET_GLULX
912 [ DoMenu menu_choices EntryR ChoiceR
913 winwid winhgt lines main_title main_wid cl i oldcl pkey;
915 if (pretty_flag == 0 || gg_statuswin == 0) return LowKey_Menu(menu_choices, EntryR, ChoiceR);
917 menu_nesting++;
918 menu_item = 0;
919 lines = EntryR();
920 main_title = item_name;
921 main_wid = item_width;
923 cl = 0;
925 ! If we printed "hit arrow keys" here, it would be appropriate to
926 ! check for the availability of Glk input keys. But we actually
927 ! print "hit N/P/Q". So it's reasonable to silently accept Glk
928 ! arrow key codes as secondary options.
930 .ReDisplay;
932 glk_window_clear(gg_statuswin);
933 glk_window_clear(gg_mainwin);
934 glk_set_window(gg_statuswin);
935 StatusLineHeight(lines+7);
936 glk_window_get_size(gg_statuswin, gg_arguments, gg_arguments+4);
937 winwid = gg_arguments-->0;
938 winhgt = gg_arguments-->1;
939 glk_set_style(style_Subheader);
940 glk_window_move_cursor(gg_statuswin, winwid/2-main_wid, 0);
941 print (string) main_title;
942 glk_window_move_cursor(gg_statuswin, 1, 1);
943 print (string) NKEY__TX;
944 glk_window_move_cursor(gg_statuswin, winwid-13, 1);
945 print (string) PKEY__TX;
946 glk_window_move_cursor(gg_statuswin, 1, 2);
947 print (string) RKEY__TX;
948 glk_window_move_cursor(gg_statuswin, winwid-18, 2);
949 if (menu_nesting == 1) print (string) QKEY1__TX;
950 else print (string) QKEY2__TX;
951 glk_set_style(style_Normal);
952 glk_window_move_cursor(gg_statuswin, 1, 4);
953 if (menu_choices ofclass String) print (string) menu_choices;
954 else menu_choices();
956 oldcl = -1;
958 for (::) {
959 if (cl ~= oldcl) {
960 if (cl < 0 || cl >= lines) cl = 0;
961 if (oldcl >= 0) {
962 glk_window_move_cursor(gg_statuswin, 3, oldcl+6);
963 print (char) ' ';
965 oldcl = cl;
966 glk_window_move_cursor(gg_statuswin, 3, oldcl+6);
967 print (char) '>';
969 pkey = KeyCharPrimitive(gg_statuswin, true);
970 if (pkey == $80000000) jump ReDisplay;
971 if (pkey == NKEY1__KY or NKEY2__KY or $fffffffb) {
972 cl++;
973 if (cl >= lines) cl = 0;
974 continue;
976 if (pkey == PKEY1__KY or PKEY2__KY or $fffffffc) {
977 cl--;
978 if (cl < 0) cl = lines-1;
979 continue;
981 if (pkey == QKEY1__KY or QKEY2__KY or $fffffff8 or $fffffffe) break;
982 if (pkey == $fffffffa or $fffffffd) {
983 glk_set_window(gg_mainwin);
984 new_line; new_line; new_line;
985 menu_item = cl+1;
986 EntryR();
987 glk_window_clear(gg_statuswin);
988 glk_window_clear(gg_mainwin);
989 glk_set_window(gg_statuswin);
990 StatusLineHeight(1);
991 glk_window_get_size(gg_statuswin, gg_arguments, gg_arguments+4);
992 winwid = gg_arguments-->0;
993 winhgt = gg_arguments-->1;
994 glk_set_style(style_Subheader);
995 glk_window_move_cursor(gg_statuswin, winwid/2-item_width, 0);
996 print (string) item_name;
997 glk_set_style(style_Normal);
998 glk_set_window(gg_mainwin);
999 new_line;
1000 i = ChoiceR();
1001 if (i == 2) jump ReDisplay;
1002 if (i == 3) break;
1003 L__M(##Miscellany, 53);
1004 pkey = KeyCharPrimitive(gg_mainwin, 1);
1005 jump ReDisplay;
1009 ! done with this menu...
1010 menu_nesting--;
1011 if (menu_nesting > 0) rfalse;
1012 glk_set_window(gg_mainwin);
1013 glk_window_clear(gg_mainwin);
1014 new_line; new_line; new_line;
1015 if (deadflag == 0) <<Look>>;
1018 #Endif; ! TARGET_
1020 ! ----------------------------------------------------------------------------
1021 ! A cunning routine (which could have been a daemon, but isn't, for the
1022 ! sake of efficiency) to move objects which could be in many rooms about
1023 ! so that the player never catches one not in place
1024 ! ----------------------------------------------------------------------------
1026 [ MoveFloatingObjects i k l m address flag;
1027 if (location == player or nothing) return;
1028 objectloop (i) {
1029 address = i.&found_in;
1030 if (address && i hasnt non_floating && ~~IndirectlyContains(player, i)) {
1031 if (metaclass(address-->0) == Routine)
1032 flag = i.found_in();
1033 else {
1034 flag = false;
1035 k = i.#found_in/WORDSIZE;
1036 for (l=0 : l<k : l++) {
1037 m = address-->l;
1038 if ((m in Class && location ofclass m) ||
1039 m == location || m in location) {
1040 flag = true;
1041 break;
1045 if (flag) {
1046 if (i notin location) move i to location;
1047 } else {
1048 if (parent(i)) remove i;
1054 ! ----------------------------------------------------------------------------
1055 ! Two little routines for moving the player safely.
1056 ! ----------------------------------------------------------------------------
1058 [ PlayerTo newplace flag;
1059 NoteDeparture();
1060 move player to newplace;
1061 while (parent(newplace)) newplace = parent(newplace);
1062 location = real_location = newplace;
1063 MoveFloatingObjects(); AdjustLight(1);
1064 switch (flag) {
1065 0: <Look>;
1066 1: NoteArrival(); ScoreArrival();
1067 2: LookSub(1);
1071 [ MovePlayer direc; <Go direc>; <Look>; ];
1073 ! ----------------------------------------------------------------------------
1074 ! The handy YesOrNo routine, and some "meta" verbs
1075 ! ----------------------------------------------------------------------------
1077 [ YesOrNo noStatusRedraw
1078 i j;
1079 for (::) {
1080 #Ifdef TARGET_ZCODE;
1081 if (location == nothing || parent(player) == nothing || noStatusRedraw)
1082 read buffer parse;
1083 else read buffer parse DrawStatusLine;
1084 j = parse->1;
1085 #Ifnot; ! TARGET_GLULX;
1086 noStatusRedraw = 0; ! suppress warning
1087 KeyboardPrimitive(buffer, parse);
1088 j = parse-->0;
1089 #Endif; ! TARGET_
1090 if (j) { ! at least one word entered
1091 i = parse-->1;
1092 if (i == YES1__WD or YES2__WD or YES3__WD) rtrue;
1093 if (i == NO1__WD or NO2__WD or NO3__WD) rfalse;
1095 L__M(##Quit, 1); print "> ";
1099 #Ifdef TARGET_ZCODE;
1101 [ QuitSub;
1102 L__M(##Quit, 2);
1103 if (YesOrNo()) quit;
1106 [ RestartSub;
1107 L__M(##Restart, 1);
1108 if (YesOrNo()) { @restart; L__M(##Restart, 2); }
1111 [ RestoreSub;
1112 restore Rmaybe;
1113 return L__M(##Restore, 1);
1114 .RMaybe;
1115 L__M(##Restore, 2);
1118 [ SaveSub flag;
1119 #IfV5;
1120 @save -> flag;
1121 switch (flag) {
1122 0: L__M(##Save, 1);
1123 1: L__M(##Save, 2);
1125 RestoreColours();
1126 L__M(##Restore, 2);
1128 #Ifnot;
1129 save Smaybe;
1130 return L__M(##Save, 1);
1131 .SMaybe;
1132 L__M(##Save, 2);
1133 #Endif; ! V5
1136 [ VerifySub;
1137 @verify ?Vmaybe;
1138 jump Vwrong;
1139 .Vmaybe;
1140 return L__M(##Verify, 1);
1141 .Vwrong;
1142 L__M(##Verify, 2);
1145 [ ScriptOnSub;
1146 transcript_mode = ((HDR_GAMEFLAGS-->0) & 1);
1147 if (transcript_mode) return L__M(##ScriptOn, 1);
1148 @output_stream 2;
1149 if (((HDR_GAMEFLAGS-->0) & 1) == 0) return L__M(##ScriptOn, 3);
1150 L__M(##ScriptOn, 2); VersionSub();
1151 transcript_mode = true;
1154 [ ScriptOffSub;
1155 transcript_mode = ((HDR_GAMEFLAGS-->0) & 1);
1156 if (transcript_mode == false) return L__M(##ScriptOff, 1);
1157 L__M(##ScriptOff, 2);
1158 @output_stream -2;
1159 if ((HDR_GAMEFLAGS-->0) & 1) return L__M(##ScriptOff, 3);
1160 transcript_mode = false;
1163 [ CommandsOnSub;
1164 @output_stream 4;
1165 xcommsdir = 1;
1166 L__M(##CommandsOn, 1);
1169 [ CommandsOffSub;
1170 if (xcommsdir == 1) @output_stream -4;
1171 xcommsdir = 0;
1172 L__M(##CommandsOff, 1);
1175 [ CommandsReadSub;
1176 @input_stream 1;
1177 xcommsdir = 2;
1178 L__M(##CommandsRead, 1);
1181 #Ifnot; ! TARGET_GLULX;
1183 [ QuitSub;
1184 L__M(##Quit, 2);
1185 if (YesOrNo()) quit;
1188 [ RestartSub;
1189 L__M(##Restart,1);
1190 if (YesOrNo()) { @restart; L__M(##Restart, 2); }
1193 [ RestoreSub res fref;
1194 fref = glk_fileref_create_by_prompt($01, $02, 0);
1195 if (fref == 0) jump RFailed;
1196 gg_savestr = glk_stream_open_file(fref, $02, GG_SAVESTR_ROCK);
1197 glk_fileref_destroy(fref);
1198 if (gg_savestr == 0) jump RFailed;
1199 @restore gg_savestr res;
1200 glk_stream_close(gg_savestr, 0);
1201 gg_savestr = 0;
1202 .RFailed;
1203 L__M(##Restore, 1);
1206 [ SaveSub res fref;
1207 fref = glk_fileref_create_by_prompt($01, $01, 0);
1208 if (fref == 0) jump SFailed;
1209 gg_savestr = glk_stream_open_file(fref, $01, GG_SAVESTR_ROCK);
1210 glk_fileref_destroy(fref);
1211 if (gg_savestr == 0) jump SFailed;
1212 @save gg_savestr res;
1213 if (res == -1) {
1214 ! The player actually just typed "restore". We're going to print
1215 ! L__M(##Restore,2); the Z-Code Inform library does this correctly
1216 ! now. But first, we have to recover all the Glk objects; the values
1217 ! in our global variables are all wrong.
1218 GGRecoverObjects();
1219 glk_stream_close(gg_savestr, 0);
1220 gg_savestr = 0;
1221 return L__M(##Restore, 2);
1223 glk_stream_close(gg_savestr, 0);
1224 gg_savestr = 0;
1225 if (res == 0) return L__M(##Save, 2);
1226 .SFailed;
1227 L__M(##Save, 1);
1230 [ VerifySub res;
1231 @verify res;
1232 if (res == 0) return L__M(##Verify, 1);
1233 L__M(##Verify, 2);
1236 [ ScriptOnSub;
1237 if (gg_scriptstr) return L__M(##ScriptOn, 1);
1238 if (gg_scriptfref == 0) {
1239 gg_scriptfref = glk_fileref_create_by_prompt($102, $05, GG_SCRIPTFREF_ROCK);
1240 if (gg_scriptfref == 0) jump S1Failed;
1242 gg_scriptstr = glk_stream_open_file(gg_scriptfref, $05, GG_SCRIPTSTR_ROCK);
1243 if (gg_scriptstr == 0) jump S1Failed;
1244 glk_window_set_echo_stream(gg_mainwin, gg_scriptstr);
1245 L__M(##ScriptOn, 2);
1246 VersionSub();
1247 return;
1248 .S1Failed;
1249 L__M(##ScriptOn, 3);
1252 [ ScriptOffSub;
1253 if (gg_scriptstr == 0) return L__M(##ScriptOff,1);
1254 L__M(##ScriptOff, 2);
1255 glk_stream_close(gg_scriptstr, 0);
1256 gg_scriptstr = 0;
1259 [ CommandsOnSub fref;
1260 if (gg_commandstr) {
1261 if (gg_command_reading) return L__M(##CommandsOn, 2);
1262 else return L__M(##CommandsOn, 3);
1264 fref = glk_fileref_create_by_prompt($103, $01, 0);
1265 if (fref == 0) return L__M(##CommandsOn, 4);
1266 gg_command_reading = false;
1267 gg_commandstr = glk_stream_open_file(fref, $01, GG_COMMANDWSTR_ROCK);
1268 glk_fileref_destroy(fref);
1269 if (gg_commandstr == 0) return L__M(##CommandsOn, 4);
1270 L__M(##CommandsOn, 1);
1273 [ CommandsOffSub;
1274 if (gg_commandstr == 0) return L__M(##CommandsOff, 2);
1275 if (gg_command_reading) return L__M(##CommandsRead, 5);
1276 glk_stream_close(gg_commandstr, 0);
1277 gg_commandstr = 0;
1278 gg_command_reading = false;
1279 L__M(##CommandsOff, 1);
1282 [ CommandsReadSub fref;
1283 if (gg_commandstr) {
1284 if (gg_command_reading) return L__M(##CommandsRead, 2);
1285 else return L__M(##CommandsRead, 3);
1287 fref = glk_fileref_create_by_prompt($103, $02, 0);
1288 if (fref == 0) return L__M(##CommandsRead, 4);
1289 gg_command_reading = true;
1290 gg_commandstr = glk_stream_open_file(fref, $02, GG_COMMANDRSTR_ROCK);
1291 glk_fileref_destroy(fref);
1292 if (gg_commandstr == 0) return L__M(##CommandsRead, 4);
1293 L__M(##CommandsRead, 1);
1296 #Endif; ! TARGET_;
1298 [ NotifyOnSub; notify_mode = true; L__M(##NotifyOn); ];
1299 [ NotifyOffSub; notify_mode = false; L__M(##NotifyOff); ];
1301 [ Places1Sub i j k;
1302 L__M(##Places, 1);
1303 objectloop (i has visited) j++;
1304 objectloop (i has visited) {
1305 print (name) i; k++;
1306 if (k == j) return L__M(##Places, 2);
1307 if (k == j-1) print (SerialComma) j, (string) AND__TX;
1308 else print (string) COMMA__TX;
1312 [ Objects1Sub i j f;
1313 L__M(##Objects, 1);
1314 objectloop (i has moved) {
1315 f = 1; print (the) i; j = parent(i);
1316 if (j) {
1317 if (j == player) {
1318 if (i has worn) L__M(##Objects, 3, j, i);
1319 else L__M(##Objects, 4, j, i);
1320 jump Obj__Ptd;
1322 if (j has animate) { L__M(##Objects, 5, j, i); jump Obj__Ptd; }
1323 if (j has visited) { L__M(##Objects, 6, j, i); jump Obj__Ptd; }
1324 if (j has container) { L__M(##Objects, 8, j, i); jump Obj__Ptd; }
1325 if (j has supporter) { L__M(##Objects, 9, j, i); jump Obj__Ptd; }
1326 if (j has enterable) { L__M(##Objects, 7, j, i); jump Obj__Ptd; }
1328 L__M(##Objects, 10, j, i);
1330 .Obj__Ptd;
1332 new_line;
1334 if (f == 0) L__M(##Objects, 2);
1337 ! ----------------------------------------------------------------------------
1338 ! The scoring system
1339 ! ----------------------------------------------------------------------------
1341 [ ScoreSub;
1342 #Ifdef NO_SCORE;
1343 if (deadflag == 0) L__M(##Score, 2);
1344 #Ifnot;
1345 if (deadflag) new_line;
1346 L__M(##Score, 1);
1347 if(PrintRank() == false) LibraryExtensions.RunAll(ext_printrank);
1348 #Endif; ! NO_SCORE
1351 #Ifndef TaskScore;
1352 [ TaskScore i;
1353 return task_scores->i;
1355 #Endif;
1357 [ Achieved num;
1358 if (task_done->num == 0) {
1359 task_done->num = 1;
1360 score = score + TaskScore(num);
1364 [ PANum m n;
1365 print " ";
1366 n = m;
1367 if (n < 0) { n = -m; n = n*10; }
1368 if (n < 10) { print " "; jump Panuml; }
1369 if (n < 100) { print " "; jump Panuml; }
1370 if (n < 1000) { print " "; }
1372 .Panuml;
1374 print m, " ";
1377 [ FullScoreSub i;
1378 ScoreSub();
1379 if (score == 0 || TASKS_PROVIDED == 1) rfalse;
1380 new_line;
1381 L__M(##FullScore, 1);
1382 for (i=0 : i<NUMBER_TASKS : i++)
1383 if (task_done->i == 1) {
1384 PANum(TaskScore(i));
1385 if(PrintTaskName(i) == false)
1386 LibraryExtensions.RunAll(ext_printtaskname,i);
1388 if (things_score) {
1389 PANum(things_score);
1390 L__M(##FullScore, 2);
1392 if (places_score) {
1393 PANum(places_score);
1394 L__M(##FullScore, 3);
1396 new_line; PANum(score); L__M(##FullScore, 4);
1399 ! ----------------------------------------------------------------------------
1400 ! Real verbs start here: Inventory
1401 ! ----------------------------------------------------------------------------
1403 [ InvWideSub;
1404 if (actor == player)
1405 inventory_style = ENGLISH_BIT+FULLINV_BIT+RECURSE_BIT;
1406 else
1407 inventory_style = ENGLISH_BIT+PARTINV_BIT;
1408 <Inv, actor>;
1409 inventory_style = 0;
1412 [ InvTallSub;
1413 if (actor == player)
1414 inventory_style = NEWLINE_BIT+INDENT_BIT+FULLINV_BIT+RECURSE_BIT;
1415 else
1416 inventory_style = NEWLINE_BIT+INDENT_BIT+PARTINV_BIT;
1417 <Inv, actor>;
1418 inventory_style = 0;
1421 [ InvSub x;
1422 if (child(actor) == 0) return L__M(##Inv, 1);
1423 if (inventory_style == 0)
1424 if (actor == player) return InvTallSub();
1425 else return InvWideSub();
1426 L__M(##Inv, 2);
1427 if (inventory_style & NEWLINE_BIT) L__M(##Inv, 3); else print " ";
1429 WriteListFrom(child(actor), inventory_style, 1);
1430 if (inventory_style & ENGLISH_BIT) L__M(##Inv, 4);
1432 #Ifndef MANUAL_PRONOUNS;
1433 objectloop (x in player) PronounNotice(x);
1434 #Endif;
1435 x = 0; ! To prevent a "not used" error
1436 AfterRoutines();
1439 ! ----------------------------------------------------------------------------
1440 ! The object tree and determining the possibility of moves
1441 ! ----------------------------------------------------------------------------
1443 [ CommonAncestor o1 o2 i j;
1444 ! Find the nearest object indirectly containing o1 and o2,
1445 ! or return 0 if there is no common ancestor.
1446 i = o1;
1447 while (i) {
1448 j = o2;
1449 while (j) {
1450 if (j == i) return i;
1451 j = parent(j);
1453 i = parent(i);
1455 return 0;
1458 [ IndirectlyContains o1 o2;
1459 ! Does o1 indirectly contain o2? (Same as testing if their common ancestor is o1.)
1460 while (o2) {
1461 if (o1 == o2) rtrue;
1462 if (o2 ofclass Class) rfalse;
1463 o2 = parent(o2);
1465 rfalse;
1468 [ ObjectScopedBySomething item i j k l m;
1469 i = item;
1470 objectloop (j .& add_to_scope) {
1471 l = j.&add_to_scope;
1472 k = (j.#add_to_scope)/WORDSIZE;
1473 if (l-->0 ofclass Routine) continue;
1474 for (m=0 : m<k : m++)
1475 if (l-->m == i) return j;
1477 rfalse;
1480 [ ObjectIsUntouchable item flag1 flag2 ancestor i;
1481 ! Determine if there's any barrier preventing the actor from moving
1482 ! things to "item". Return false if no barrier; otherwise print a
1483 ! suitable message and return true.
1484 ! If flag1 is set, do not print any message.
1485 ! If flag2 is set, also apply Take/Remove restrictions.
1487 ! If the item has been added to scope by something, it's first necessary
1488 ! for that something to be touchable.
1490 ancestor = CommonAncestor(actor, item);
1491 if (ancestor == 0) {
1492 ancestor = item;
1493 while (ancestor && (i = ObjectScopedBySomething(ancestor)) == 0)
1494 ancestor = parent(ancestor);
1495 if (i) {
1496 if (ObjectIsUntouchable(i, flag1, flag2)) return;
1497 ! An item immediately added to scope
1500 else
1502 ! First, a barrier between the actor and the ancestor. The actor
1503 ! can only be in a sequence of enterable objects, and only closed
1504 ! containers form a barrier.
1506 if (actor ~= ancestor) {
1507 i = parent(actor);
1508 while (i ~= ancestor) {
1509 if (i has container && i hasnt open) {
1510 if (flag1) rtrue;
1511 return L__M(##Take, 9, i, noun);
1513 i = parent(i);
1517 ! Second, a barrier between the item and the ancestor. The item can
1518 ! be carried by someone, part of a piece of machinery, in or on top
1519 ! of something and so on.
1521 i = parent(item);
1522 if (item ~= ancestor && i ~= player) {
1523 while (i ~= ancestor) {
1524 if (flag2 && i hasnt container && i hasnt supporter) {
1525 if (i has animate) {
1526 if (flag1) rtrue;
1527 return L__M(##Take, 6, i, noun);
1529 if (i has transparent) {
1530 if (flag1) rtrue;
1531 return L__M(##Take, 7, i, noun);
1533 if (flag1) rtrue;
1534 return L__M(##Take, 8, item, noun);
1536 if (i has container && i hasnt open) {
1537 if (flag1) rtrue;
1538 return L__M(##Take, 9, i, noun);
1540 i = parent(i);
1543 rfalse;
1546 [ AttemptToTakeObject item
1547 ancestor after_recipient i k;
1548 ! Try to transfer the given item to the actor: return false
1549 ! if successful, true if unsuccessful, printing a suitable message
1550 ! in the latter case.
1551 ! People cannot ordinarily be taken.
1552 if (item == actor) return L__M(##Take, 2, noun);
1553 if (item has animate) return L__M(##Take, 3, item);
1555 ancestor = CommonAncestor(actor, item);
1557 if (ancestor == 0) {
1558 i = ObjectScopedBySomething(item);
1559 if (i) ancestor = CommonAncestor(actor, i);
1562 ! Is the actor indirectly inside the item?
1563 if (ancestor == item) return L__M(##Take, 4, item);
1565 ! Does the actor already directly contain the item?
1566 if (item in actor) return L__M(##Take, 5, item);
1568 ! Can the actor touch the item, or is there (e.g.) a closed container
1569 ! in the way?
1570 if (ObjectIsUntouchable(item, false, true)) rtrue;
1572 ! The item is now known to be accessible.
1574 ! Consult the immediate possessor of the item, if it's in a container
1575 ! which the actor is not in.
1577 i = parent(item);
1578 if (i && i ~= ancestor && (i has container or supporter)) {
1579 after_recipient = i;
1580 k = action; action = ##LetGo;
1581 if (RunRoutines(i, before)) { action = k; rtrue; }
1582 action = k;
1585 if (item has scenery) return L__M(##Take, 10, item);
1586 if (item has static) return L__M(##Take, 11, item);
1588 ! The item is now known to be available for taking. Is the player
1589 ! carrying too much? If so, possibly juggle items into the rucksack
1590 ! to make room.
1592 if (ObjectDoesNotFit(item, actor) ||
1593 LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, item, actor)) return;
1594 if (AtFullCapacity(item, actor)) return L__M(##Take, 12, item);
1596 ! Transfer the item.
1598 move item to actor; give item ~worn;
1600 ! Send "after" message to the object letting go of the item, if any.
1602 if (after_recipient) {
1603 k = action; action = ##LetGo;
1604 if (RunRoutines(after_recipient, after)) { action = k; rtrue; }
1605 action = k;
1607 rfalse;
1610 [ AtFullCapacity n s
1611 obj k;
1612 n = n; ! suppress compiler warning
1613 if (s == actor) {
1614 objectloop (obj in s)
1615 if (obj hasnt worn) k++;
1616 } else
1617 k = children(s);
1619 if (k < RunRoutines(s, capacity) || (s == player && RoomInSack())) rfalse;
1622 [ RoomInSack
1623 obj ks;
1624 if (SACK_OBJECT && SACK_OBJECT in player) {
1625 ks = keep_silent; keep_silent = 2;
1626 for (obj=youngest(player) : obj : obj=elder(obj))
1627 if (obj ~= SACK_OBJECT && obj hasnt worn or light) {
1628 <Insert obj SACK_OBJECT>;
1629 if (obj in SACK_OBJECT) {
1630 keep_silent = ks;
1631 return L__M(##Take, 13, obj, SACK_OBJECT);
1634 keep_silent = ks;
1636 rfalse;
1639 ! ----------------------------------------------------------------------------
1640 ! Support for implicit actions
1641 ! ----------------------------------------------------------------------------
1643 [ CheckImplicitAction act o1 o2
1644 sav_act sav_noun sav_sec res;
1645 if (o1 provides before_implicit) {
1646 sav_act = action; action = act;
1647 sav_noun = noun; noun = o1;
1648 if (o2) { sav_sec = second; second = o2; }
1649 res = RunRoutines(o1, before_implicit);
1650 action = sav_act; noun = sav_noun;
1651 if (sav_sec) second = sav_sec;
1653 else {
1654 if (no_implicit_actions)
1655 res = 2;
1656 else
1657 res = 0;
1659 return res;
1662 [ ImplicitTake obj
1663 res ks supcon;
1664 switch (metaclass(obj)) { Class, String, Routine, nothing: rfalse; }
1665 if (obj in actor) rfalse;
1666 if (action_to_be == ##Drop && ~~IndirectlyContains(actor, obj)) rfalse;
1667 res = CheckImplicitAction(##Take, obj);
1668 ! 0 = Take object, Tell the user (normal default)
1669 ! 1 = Take object, don't Tell
1670 ! 2 = don't Take object continue (default with no_implicit_actions)
1671 ! 3 = don't Take object, don't continue
1672 if (res >= 2) rtrue;
1673 if (parent(obj) && parent(obj) has container or supporter) supcon = parent(obj);
1674 ks = keep_silent; keep_silent = 2; AttemptToTakeObject(obj); keep_silent = ks;
1675 if (obj notin actor) rtrue;
1676 if (res == 0 && ~~keep_silent)
1677 if (supcon) L__M(##Miscellany, 58, obj, supcon);
1678 else L__M(##Miscellany, 26, obj);
1679 rfalse;
1682 [ ImplicitExit obj
1683 res ks;
1684 if (parent(obj) == nothing) rfalse;
1685 res = CheckImplicitAction(##Exit, obj);
1686 ! 0 = Exit object, Tell the user (normal default)
1687 ! 1 = Exit object, don't Tell
1688 ! 2 = don't Take object continue (default with no_implicit_actions)
1689 ! 3 = don't Take object, don't continue
1690 if (res >= 2) rtrue;
1691 ks = keep_silent; keep_silent = 2; <Exit obj, actor>; keep_silent = ks;
1692 if (parent(actor) == obj) rtrue;
1693 if (res == 0 && ~~keep_silent) L__M(##Exit, 5, obj);
1694 rfalse;
1697 [ ImplicitClose obj
1698 res ks;
1699 if (obj hasnt open) rfalse;
1700 res = CheckImplicitAction(##Close, obj);
1701 ! 0 = Close object, Tell the user (normal default)
1702 ! 1 = Close object, don't Tell
1703 ! 2 = don't Take object continue (default with no_implicit_actions)
1704 ! 3 = don't Take object, don't continue
1705 if (res >= 2) rtrue;
1706 ks = keep_silent; keep_silent = 2; <Close obj, actor>; keep_silent = ks;
1707 if (obj has open) rtrue;
1708 if (res == 0 && ~~keep_silent) L__M(##Close, 4, obj);
1709 rfalse;
1712 [ ImplicitOpen obj
1713 res temp;
1714 if (obj has open) rfalse;
1715 res = CheckImplicitAction(##Open, obj);
1716 ! 0 = Open object, Tell the user (normal default)
1717 ! 1 = Open object, don't Tell
1718 ! 2 = don't Take object continue (default with no_implicit_actions)
1719 ! 3 = don't Take object, don't continue
1720 if (res >= 2) rtrue;
1721 if (obj has locked) rtrue;
1722 temp = keep_silent; keep_silent = 2; <Open obj, actor>; keep_silent = temp;
1723 if (obj hasnt open) rtrue;
1724 if (res == 0 && ~~keep_silent) L__M(##Open, 6, obj);
1725 temp = action; action = ##Open; AfterRoutines(); action = temp;
1726 rfalse;
1729 [ ImplicitUnlock obj;
1730 if (obj has locked) rtrue;
1731 rfalse;
1734 [ ImplicitDisrobe obj
1735 res ks;
1736 if (obj hasnt worn) rfalse;
1737 res = CheckImplicitAction(##Disrobe, obj);
1738 ! 0 = Take off object, Tell the user (normal default)
1739 ! 1 = Take off object, don't Tell
1740 ! 2 = don't Take object continue (default with no_implicit_actions)
1741 ! 3 = don't Take object, don't continue
1742 if (res >= 2) rtrue;
1743 ks = keep_silent; keep_silent = 1; <Disrobe obj, actor>; keep_silent = ks;
1744 if (obj has worn && obj in actor) rtrue;
1745 if (res == 0 && ~~keep_silent) L__M(##Drop, 3, obj);
1746 rfalse;
1750 ! ----------------------------------------------------------------------------
1751 ! Object movement verbs
1752 ! ----------------------------------------------------------------------------
1754 [ TakeSub;
1755 if (onotheld_mode == 0 || noun notin actor)
1756 if (AttemptToTakeObject(noun)) return;
1757 if (AfterRoutines()) return;
1758 notheld_mode = onotheld_mode;
1759 if (notheld_mode == 1 || keep_silent) return;
1760 L__M(##Take, 1, noun);
1763 [ RemoveSub i;
1764 i = parent(noun);
1765 if (i && i has container && i hasnt open && ImplicitOpen(i)) return L__M(##Remove, 1, i);
1766 if (i ~= second) return L__M(##Remove, 2, noun);
1767 if (i has animate) return L__M(##Take, 6, i, noun);
1769 if (AttemptToTakeObject(noun)) rtrue;
1771 action = ##Remove; if (AfterRoutines()) return;
1772 action = ##Take; if (AfterRoutines()) return;
1773 if (keep_silent) return;
1774 L__M(##Remove, 3, noun);
1777 [ DropSub;
1778 if (noun == actor) return L__M(##PutOn, 4, noun);
1779 if (noun in parent(actor)) return L__M(##Drop, 1, noun);
1780 if (noun notin actor && ~~ImplicitTake(noun)) return L__M(##Drop, 2, noun);
1781 if (noun has worn && ImplicitDisrobe(noun)) return;
1782 move noun to parent(actor);
1783 if (AfterRoutines() || keep_silent) return;
1784 L__M(##Drop, 4, noun);
1787 [ PutOnSub ancestor;
1788 receive_action = ##PutOn;
1789 if (second == d_obj || actor in second) <<Drop noun, actor>>;
1790 if (parent(noun) == second) return L__M(##Drop, 1, noun);
1791 if (noun notin actor && ImplicitTake(noun)) return L__M(##PutOn, 1, noun);
1793 ancestor = CommonAncestor(noun, second);
1794 if (ancestor == noun) return L__M(##PutOn, 2, noun);
1795 if (ObjectIsUntouchable(second)) return;
1797 if (second ~= ancestor) {
1798 action = ##Receive;
1799 if (RunRoutines(second, before)) { action = ##PutOn; return; }
1800 action = ##PutOn;
1802 if (second hasnt supporter) return L__M(##PutOn, 3, second);
1803 if (ancestor == actor) return L__M(##PutOn, 4, second);
1804 if (noun has worn && ImplicitDisrobe(noun)) return;
1806 if (ObjectDoesNotFit(noun, second) ||
1807 LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, noun, second)) return;
1808 if (AtFullCapacity(noun, second)) return L__M(##PutOn, 6, second);
1810 move noun to second;
1812 if (AfterRoutines()) return;
1814 if (second ~= ancestor) {
1815 action = ##Receive;
1816 if (RunRoutines(second, after)) { action = ##PutOn; return; }
1817 action = ##PutOn;
1819 if (keep_silent) return;
1820 if (multiflag) return L__M(##PutOn, 7);
1821 L__M(##PutOn, 8, noun, second);
1824 [ InsertSub ancestor;
1825 receive_action = ##Insert;
1826 if (second == d_obj || actor in second) <<Drop noun, actor>>;
1827 if (parent(noun) == second) return L__M(##Drop, 1, noun);
1828 if (noun notin actor && ImplicitTake(noun)) return L__M(##Insert, 1, noun);
1829 ancestor = CommonAncestor(noun, second);
1830 if (ancestor == noun) return L__M(##Insert, 5, noun);
1831 if (ObjectIsUntouchable(second)) return;
1832 if (second ~= ancestor) {
1833 action = ##Receive;
1834 if (RunRoutines(second,before)) { action = ##Insert; rtrue; }
1835 action = ##Insert;
1836 if (second has container && second hasnt open && ImplicitOpen(second))
1837 return L__M(##Insert, 3, second);
1839 if (second hasnt container) return L__M(##Insert, 2, second);
1840 if (noun has worn && ImplicitDisrobe(noun)) return;
1842 if (ObjectDoesNotFit(noun, second) ||
1843 LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, noun, second)) return;
1844 if (AtFullCapacity(noun, second)) return L__M(##Insert, 7, second);
1846 move noun to second;
1848 if (AfterRoutines()) rtrue;
1850 if (second ~= ancestor) {
1851 action = ##Receive;
1852 if (RunRoutines(second, after)) { action = ##Insert; rtrue; }
1853 action = ##Insert;
1855 if (keep_silent) rtrue;
1856 if (multiflag) return L__M(##Insert, 8, noun);
1857 L__M(##Insert, 9, noun, second);
1860 ! ----------------------------------------------------------------------------
1861 ! Empties and transfers are routed through the actions above
1862 ! ----------------------------------------------------------------------------
1864 [ TransferSub;
1865 if (noun notin actor && AttemptToTakeObject(noun)) return;
1866 if (second has supporter) <<PutOn noun second, actor>>;
1867 if (second == d_obj) <<Drop noun, actor>>;
1868 <<Insert noun second, actor>>;
1871 [ EmptySub; second = d_obj; EmptyTSub(); ];
1873 [ EmptyTSub i j k flag;
1874 if (noun == second) return L__M(##EmptyT, 4, noun);
1875 if (ObjectIsUntouchable(noun)) return;
1876 if (noun hasnt container) return L__M(##EmptyT, 1, noun);
1877 if (noun hasnt open && ImplicitOpen(noun)) return L__M(##EmptyT, 2, noun);
1878 if (second ~= d_obj) {
1879 if (second hasnt supporter) {
1880 if (second hasnt container) return L__M(##EmptyT, 1, second);
1881 if (second hasnt open && ImplicitOpen(second))
1882 return L__M(##EmptyT, 2, second);
1885 i = child(noun); k = children(noun);
1886 if (i == 0) return L__M(##EmptyT, 3, noun);
1887 while (i) {
1888 j = sibling(i);
1889 flag = false;
1890 if (ObjectIsUntouchable(noun)) flag = true;
1891 if (noun hasnt container) flag = true;
1892 if (noun hasnt open) flag = true;
1893 if (second ~= d_obj) {
1894 if (second hasnt supporter) {
1895 if (second hasnt container) flag = true;
1896 if (second hasnt open) flag = true;
1899 if (k-- == 0) flag = 1;
1900 if (flag) break;
1901 if (keep_silent == 0) print (name) i, (string) COLON__TX;
1902 <Transfer i second, actor>;
1903 i = j;
1907 ! ----------------------------------------------------------------------------
1908 ! Gifts
1909 ! ----------------------------------------------------------------------------
1911 [ GiveSub;
1912 if (noun notin actor && ImplicitTake(noun)) return L__M(##Give, 1, noun);
1913 if (second == actor) return L__M(##Give, 2, noun);
1914 if (noun has worn && ImplicitDisrobe(noun)) return;
1915 if (second == player) {
1916 move noun to player;
1917 return L__M(##Give, 4, noun);
1920 if (RunLife(second, ##Give)) return;
1921 L__M(##Give, 3, second);
1924 [ GiveRSub; <Give second noun, actor>; ];
1926 [ ShowSub;
1927 if (noun notin actor && ImplicitTake(noun)) return L__M(##Show, 1, noun);
1928 if (second == player) <<Examine noun, actor>>;
1929 if (RunLife(second, ##Show)) return;
1930 L__M(##Show, 2, second);
1933 [ ShowRSub; <Show second noun, actor>; ];
1935 ! ----------------------------------------------------------------------------
1936 ! Travelling around verbs
1937 ! ----------------------------------------------------------------------------
1939 [ EnterSub ancestor j ks;
1940 if (noun has door || noun in compass) <<Go noun, actor>>;
1941 if (actor in noun) return L__M(##Enter, 1, noun);
1942 if (noun hasnt enterable) return L__M(##Enter, 2, noun, verb_word);
1944 if (parent(actor) ~= parent(noun)) {
1945 ancestor = CommonAncestor(actor, noun);
1946 if (ancestor == actor or 0) return L__M(##Enter, 4, noun);
1947 while (actor notin ancestor) {
1948 j = parent(actor);
1949 ks = keep_silent;
1950 if (parent(j) ~= ancestor || noun ~= ancestor) {
1951 L__M(##Enter, 6, j);
1952 keep_silent = 1;
1954 <Exit, actor>;
1955 keep_silent = ks;
1956 if (actor in j) return;
1958 if (actor in noun) return;
1959 if (noun notin ancestor) {
1960 j = parent(noun);
1961 while (parent(j) ~= ancestor) j = parent(j);
1962 L__M(##Enter, 7, j);
1963 ks = keep_silent; keep_silent = 1;
1964 <Enter j, actor>;
1965 keep_silent = ks;
1966 if (actor notin j) return;
1967 <<Enter noun, actor>>;
1971 if (noun has container && noun hasnt open && ImplicitOpen(noun)) return L__M(##Enter, 3, noun);
1972 move actor to noun;
1974 if (AfterRoutines() || keep_silent) return;
1975 L__M(##Enter, 5, noun);
1976 if (actor == player) Locale(noun);
1979 [ GetOffSub;
1980 if (parent(actor) == noun) <<Exit, actor>>;
1981 L__M(##GetOff, 1, noun);
1984 [ ExitSub p;
1985 p = parent(actor);
1986 if (noun ~= nothing && noun ~= p) return L__M(##Exit, 4 ,noun);
1987 if (p == location || (location == thedark && p == real_location)) {
1988 if (actor provides posture && actor.posture) {
1989 actor.posture = 0;
1990 return L__M(##Exit, 6);
1992 if ((location.out_to) || (location == thedark && real_location.out_to))
1993 <<Go out_obj, actor>>;
1994 return L__M(##Exit, 1);
1996 if (p has container && p hasnt open && ImplicitOpen(p))
1997 return L__M(##Exit, 2, p);
1999 if (noun == nothing) {
2000 inp1 = p;
2001 if (RunRoutines(p, before)) return;
2004 move actor to parent(p);
2005 if (player provides posture) player.posture = 0;
2007 if (AfterRoutines() || keep_silent) return;
2008 L__M(##Exit, 3, p);
2009 if (actor == player && p has container) LookSub(1);
2012 [ VagueGoSub; L__M(##VagueGo); ];
2014 [ GoInSub; <<Go in_obj, actor>>; ];
2016 [ GoSub i j k movewith thedir next_loc;
2018 ! first, check if any PushDir object is touchable
2019 if (second && second notin Compass && ObjectIsUntouchable(second)) return;
2021 movewith = 0;
2022 i = parent(actor);
2023 if ((location ~= thedark && i ~= location) || (location == thedark && i ~= real_location)) {
2024 j = location;
2025 if (location == thedark) location = real_location;
2026 k = RunRoutines(i, before); if (k ~= 3) location = j;
2027 if (k == 1) {
2028 movewith = i; i = parent(i);
2030 else {
2031 if (k) rtrue;
2032 if (ImplicitExit(i)) return L__M(##Go, 1, i);
2033 i = parent(actor);
2037 thedir = noun.door_dir;
2038 if (metaclass(thedir) == Routine) thedir = RunRoutines(noun, door_dir);
2040 next_loc = i.thedir; k = metaclass(next_loc);
2041 if (k == String) { print (string) next_loc; new_line; rfalse; }
2042 if (k == Routine) {
2043 next_loc = RunRoutines(i, thedir);
2044 if (next_loc == 1) rtrue;
2047 if (k == nothing || next_loc == 0) {
2048 if (i.cant_go ~= 0 or CANTGO__TX) PrintOrRun(i, cant_go);
2049 else L__M(##Go, 2);
2050 rfalse;
2052 if (next_loc has door) {
2053 if (next_loc has concealed) return L__M(##Go, 2);
2054 if (next_loc hasnt open && ImplicitOpen(next_loc)) {
2055 if (noun == u_obj) return L__M(##Go, 3, next_loc);
2056 if (noun == d_obj) return L__M(##Go, 4, next_loc);
2057 return L__M(##Go, 5, next_loc);
2059 k = RunRoutines(next_loc, door_to);
2060 if (k == 0) return L__M(##Go, 6, next_loc);
2061 if (k == 1) rtrue;
2062 next_loc = k;
2065 action = ##Going;
2066 if (RunRoutines(next_loc, before)) { action = ##Go; return; }
2067 action = ##Go;
2069 if (movewith == 0) move actor to next_loc; else move movewith to next_loc;
2070 if (actor ~= player) return L__M(##Go, 7);
2072 k = location; location = next_loc;
2073 MoveFloatingObjects();
2074 if (OffersLight(location))
2075 lightflag = true;
2076 else {
2077 lightflag = false;
2078 if (k == thedark) {
2079 if(DarkToDark() == false) ! From real_location To location
2080 LibraryExtensions.RunAll(ext_darktodark);
2081 if (deadflag) rtrue;
2083 location = thedark;
2085 NoteDeparture(); real_location = next_loc;
2086 action = ##Going;
2087 if (RunRoutines(prev_location, after)) { action = ##Go; return; }
2088 action = ##Go;
2089 if (AfterRoutines() || keep_silent) return;
2090 LookSub(1);
2093 ! ----------------------------------------------------------------------------
2094 ! Describing the world. SayWhatsOn(object) does just that (producing
2095 ! no text if nothing except possibly "scenery" and "concealed" items are).
2096 ! Locale(object) runs through the "tail end" of a Look-style room
2097 ! description for the contents of the object, printing up suitable
2098 ! descriptions as it goes.
2099 ! ----------------------------------------------------------------------------
2101 [ SayWhatsOn descon j f;
2102 if (descon == parent(player)) rfalse;
2103 objectloop (j in descon)
2104 if (j hasnt concealed && j hasnt scenery) f = 1;
2105 if (f == 0) rfalse;
2106 L__M(##Look, 4, descon);
2109 [ NotSupportingThePlayer o i;
2110 i = parent(player);
2111 while (i && i ~= visibility_ceiling) {
2112 if (i == o) rfalse;
2113 i = parent(i);
2114 if (i && i hasnt supporter) rtrue;
2116 rtrue;
2118 ! modified with the fix for L61122
2119 [ Locale descin text_without_ALSO text_with_ALSO
2120 o p num_objs must_print_ALSO;
2121 objectloop (o in descin) give o ~workflag;
2122 num_objs = 0;
2123 objectloop (o in descin)
2124 if (o hasnt concealed && NotSupportingThePlayer(o)) {
2125 #Ifndef MANUAL_PRONOUNS;
2126 PronounNotice(o);
2127 #Endif;
2128 if (o has scenery) {
2129 if (o has supporter && child(o)) SayWhatsOn(o);
2131 else {
2132 give o workflag; num_objs++;
2133 p = initial;
2134 if ((o has door or container) && o has open && o provides when_open) {
2135 p = when_open; jump Prop_Chosen;
2137 if ((o has door or container) && o hasnt open && o provides when_closed) {
2138 p = when_closed; jump Prop_Chosen;
2140 if (o has switchable && o has on && o provides when_on) {
2141 p = when_on; jump Prop_Chosen;
2143 if (o has switchable && o hasnt on && o provides when_off) {
2144 p = when_off;
2147 .Prop_Chosen;
2149 if (o.&describe && RunRoutines(o, describe)) {
2150 must_print_ALSO = true;
2151 give o ~workflag; num_objs--;
2152 continue;
2154 if (o.p && (o hasnt moved || p ~= initial)) {
2155 new_line;
2156 PrintOrRun(o, p);
2157 must_print_ALSO = true;
2158 give o ~workflag; num_objs--;
2159 if (o has supporter && child(o)) SayWhatsOn(o);
2164 if (num_objs == 0) return 0;
2166 if (actor ~= player) give actor concealed;
2167 if (text_without_ALSO) {
2168 new_line;
2169 if (must_print_ALSO) print (string) text_with_ALSO, " ";
2170 else print (string) text_without_ALSO, " ";
2171 WriteListFrom(child(descin),
2172 ENGLISH_BIT+RECURSE_BIT+PARTINV_BIT+TERSE_BIT+CONCEAL_BIT+WORKFLAG_BIT);
2174 else {
2175 if (must_print_ALSO) L__M(##Look, 5, descin);
2176 else L__M(##Look, 6, descin);
2178 if (actor ~= player) give actor ~concealed;
2179 return num_objs;
2182 ! ----------------------------------------------------------------------------
2183 ! Looking. LookSub(1) is allowed to abbreviate long descriptions, but
2184 ! LookSub(0) (which is what happens when the Look action is generated)
2185 ! isn't. (Except that these are over-ridden by the player-set lookmode.)
2186 ! ----------------------------------------------------------------------------
2188 [ LMode1Sub; lookmode=1; print (string) Story; L__M(##LMode1); ]; ! Brief
2190 [ LMode2Sub; lookmode=2; print (string) Story; L__M(##LMode2); ]; ! Verbose
2192 [ LMode3Sub; lookmode=3; print (string) Story; L__M(##LMode3); ]; ! Superbrief
2194 [ LModeNormalSub; ! 'normal' value: the default, or as set in Initialise()
2195 switch (initial_lookmode) {
2196 1: <<LMode1>>;
2197 3: <<LMode3>>;
2198 default: <<LMode2>>;
2202 [ NoteArrival descin;
2203 if (location ~= lastdesc) {
2204 if (location.initial) PrintOrRun(location, initial);
2205 if (location == thedark) { lastdesc = thedark; return; }
2206 descin = location;
2207 if(NewRoom() == false) LibraryExtensions.RunAll(ext_newroom);
2208 lastdesc = descin;
2212 [ NoteDeparture;
2213 prev_location = real_location;
2216 [ ScoreArrival;
2217 if (location hasnt visited) {
2218 give location visited;
2219 if (location has scored) {
2220 score = score + ROOM_SCORE;
2221 places_score = places_score + ROOM_SCORE;
2226 [ FindVisibilityLevels visibility_levels;
2227 visibility_levels = 1;
2228 visibility_ceiling = parent(player);
2229 while ((parent(visibility_ceiling)) &&
2230 (visibility_ceiling hasnt container || visibility_ceiling has open or transparent)) {
2231 visibility_ceiling = parent(visibility_ceiling);
2232 visibility_levels++;
2234 return visibility_levels;
2237 [ LookSub allow_abbrev visibility_levels i j k nl_flag;
2238 if (parent(player) == 0) return RunTimeError(10);
2240 .MovedByInitial;
2242 if (location == thedark) { visibility_ceiling = thedark; NoteArrival(); }
2243 else {
2244 visibility_levels = FindVisibilityLevels();
2245 if (visibility_ceiling == location) {
2246 NoteArrival();
2247 if (visibility_ceiling ~= location) jump MovedByInitial;
2250 ! Printing the top line: e.g.
2251 ! Octagonal Room (on the table) (as Frodo)
2252 new_line;
2253 #Ifdef TARGET_ZCODE;
2254 style bold;
2255 #Ifnot; ! TARGET_GLULX;
2256 glk_set_style(style_Subheader);
2257 #Endif; ! TARGET_
2258 if (visibility_levels == 0) print (name) thedark;
2259 else {
2260 if (visibility_ceiling ~= location) print (The) visibility_ceiling;
2261 else print (name) visibility_ceiling;
2263 #Ifdef TARGET_ZCODE;
2264 style roman;
2265 #Ifnot; ! TARGET_GLULX;
2266 glk_set_style(style_Normal);
2267 #Endif; ! TARGET_
2269 for (j=1,i=parent(player) : j<visibility_levels : j++,i=parent(i))
2270 if (i has supporter) L__M(##Look, 1, i);
2271 else L__M(##Look, 2, i);
2273 if (print_player_flag == 1) L__M(##Look, 3, player);
2274 new_line;
2276 ! The room description (if visible)
2278 if (lookmode < 3 && visibility_ceiling == location) {
2279 if ((allow_abbrev ~= 1) || (lookmode == 2) || (location hasnt visited)) {
2280 if (location.&describe) RunRoutines(location, describe);
2281 else {
2282 if (location.description == 0) RunTimeError(11, location, description);
2283 else PrintOrRun(location, description);
2288 if (visibility_ceiling == location) nl_flag = 1;
2290 if (visibility_levels == 0) Locale(thedark);
2291 else {
2292 for (i=player,j=visibility_levels : j>0 : j--,i=parent(i)) give i workflag;
2294 for (j=visibility_levels : j>0 : j--) {
2295 for (i=player,k=0 : k<j : k++) i=parent(i);
2296 if (i.inside_description) {
2297 if (nl_flag) new_line; else nl_flag = 1;
2298 PrintOrRun(i,inside_description);
2300 if (Locale(i)) nl_flag=1;
2304 if(LookRoutine() == false) LibraryExtensions.RunAll(ext_lookroutine);
2305 ScoreArrival();
2306 action = ##Look;
2307 AfterRoutines();
2310 [ ExamineSub i;
2311 if (location == thedark) return L__M(##Examine, 1, noun);
2312 i = noun.description;
2313 if (i == 0) {
2314 if (noun has container)
2315 if (noun has open or transparent) <<Search noun, actor>>;
2316 else return L__M(##Search, 5, noun);
2317 if (noun has switchable) { L__M(##Examine, 3, noun); rfalse; }
2318 return L__M(##Examine, 2, noun);
2320 i = PrintOrRun(noun, description);
2321 if (i < 2 && noun has switchable) L__M(##Examine, 3, noun);
2322 AfterRoutines();
2325 [ LookUnderSub;
2326 if (location == thedark) return L__M(##LookUnder, 1, noun);
2327 L__M(##LookUnder, 2);
2330 [ VisibleContents o i f;
2331 objectloop (i in o) if (i hasnt concealed or scenery) f++;
2332 return f;
2335 [ SearchSub f;
2336 if (location == thedark) return L__M(##Search, 1, noun);
2337 if (ObjectIsUntouchable(noun)) return;
2338 f = VisibleContents(noun);
2339 if (noun has supporter) {
2340 if (f == 0) return L__M(##Search, 2, noun);
2341 return L__M(##Search, 3, noun);
2343 if (noun hasnt container) return L__M(##Search, 4, noun);
2344 if (noun hasnt transparent or open && ImplicitOpen(noun)) return L__M(##Search, 5, noun);
2345 if (AfterRoutines()) return;
2347 if (f == 0) return L__M(##Search, 6, noun);
2348 L__M(##Search, 7, noun);
2351 ! ----------------------------------------------------------------------------
2352 ! Verbs which change the state of objects without moving them
2353 ! ----------------------------------------------------------------------------
2355 [ UnlockSub;
2356 if (ObjectIsUntouchable(noun)) return;
2357 if (noun hasnt lockable) return L__M(##Unlock, 1, noun);
2358 if (noun hasnt locked) return L__M(##Unlock, 2, noun);
2359 if (noun.with_key ~= second) return L__M(##Unlock, 3, second);
2361 give noun ~locked;
2363 if (AfterRoutines() || keep_silent) return;
2364 L__M(##Unlock, 4, noun);
2367 [ LockSub;
2368 if (ObjectIsUntouchable(noun)) return;
2369 if (noun hasnt lockable) return L__M(##Lock, 1, noun);
2370 if (noun has locked) return L__M(##Lock, 2 ,noun);
2371 if (noun has open && ImplicitClose(noun)) return L__M(##Lock, 3, noun);
2372 if (noun.with_key ~= second) return L__M(##Lock, 4, second);
2374 give noun locked;
2375 if (AfterRoutines() || keep_silent) return;
2376 L__M(##Lock, 5, noun);
2379 [ SwitchonSub;
2380 if (ObjectIsUntouchable(noun)) return;
2381 if (noun hasnt switchable) return L__M(##SwitchOn, 1, noun);
2382 if (noun has on) return L__M(##SwitchOn, 2, noun);
2384 give noun on;
2385 if (AfterRoutines() || keep_silent) return;
2386 L__M(##SwitchOn, 3, noun);
2389 [ SwitchoffSub;
2390 if (ObjectIsUntouchable(noun)) return;
2391 if (noun hasnt switchable) return L__M(##SwitchOff, 1, noun);
2392 if (noun hasnt on) return L__M(##SwitchOff, 2, noun);
2394 give noun ~on;
2395 if (AfterRoutines() || keep_silent) return;
2396 L__M(##SwitchOff, 3, noun);
2399 [ OpenSub;
2400 if (ObjectIsUntouchable(noun)) return;
2401 if (noun hasnt openable) return L__M(##Open, 1, noun);
2402 if (noun has locked && ImplicitUnlock(noun)) return L__M(##Open, 2, noun);
2403 if (noun has open) return L__M(##Open, 3, noun);
2404 give noun open;
2406 if (keep_silent || AfterRoutines()) return;
2408 if (noun hasnt container)
2409 return L__M(##Open, 5, noun);
2411 if ((noun has container && location ~= thedark && VisibleContents(noun)
2412 && IndirectlyContains(noun, player)) == 0) {
2413 if (noun hasnt transparent && noun hasnt door) return L__M(##Open, 4, noun);
2415 L__M(##Open, 5, noun);
2418 [ CloseSub;
2419 if (ObjectIsUntouchable(noun)) return;
2420 if (noun hasnt openable) return L__M(##Close, 1, noun);
2421 if (noun hasnt open) return L__M(##Close, 2, noun);
2423 give noun ~open;
2424 if (AfterRoutines() || keep_silent) return;
2425 L__M(##Close, 3, noun);
2428 [ DisrobeSub;
2429 if (ObjectIsUntouchable(noun)) return;
2430 if (noun hasnt worn) return L__M(##Disrobe, 1, noun);
2432 give noun ~worn;
2433 if (AfterRoutines() || keep_silent) return;
2434 L__M(##Disrobe, 2, noun);
2437 [ WearSub;
2438 if (ObjectIsUntouchable(noun)) return;
2439 if (noun hasnt clothing) return L__M(##Wear, 1, noun);
2440 if (noun notin actor && ImplicitTake(noun)) return L__M(##Wear, 2, noun);
2441 if (noun has worn) return L__M(##Wear, 3, noun);
2443 give noun worn;
2444 if (AfterRoutines() || keep_silent) return;
2445 L__M(##Wear, 4, noun);
2448 [ EatSub;
2449 if (ObjectIsUntouchable(noun)) return;
2450 if (noun hasnt edible) return L__M(##Eat, 1, noun);
2451 if (noun has worn && ImplicitDisrobe(noun)) return;
2453 remove noun;
2454 if (AfterRoutines() || keep_silent) return;
2455 L__M(##Eat, 2, noun);
2458 ! ----------------------------------------------------------------------------
2459 ! Verbs which are really just stubs (anything which happens for these
2460 ! actions must happen in before rules)
2461 ! ----------------------------------------------------------------------------
2463 [ AllowPushDir i;
2464 if (parent(second) ~= compass) return L__M(##PushDir, 2, noun);
2465 if (second == u_obj or d_obj) return L__M(##PushDir, 3, noun);
2466 AfterRoutines(); i = noun; move i to actor;
2467 <Go second, actor>;
2468 if (location == thedark) move i to real_location;
2469 else move i to location;
2472 [ AnswerSub;
2473 if (second && RunLife(second,##Answer)) rfalse;
2474 L__M(##Answer, 1, noun);
2477 [ AskSub;
2478 if (RunLife(noun,##Ask)) rfalse;
2479 L__M(##Ask, 1, noun);
2482 [ AskForSub;
2483 if (noun == player) <<Inv, actor>>;
2484 L__M(##Order, 1, noun);
2487 [ AskToSub; L__M(##Order, 1, noun); ];
2489 [ AttackSub;
2490 if (ObjectIsUntouchable(noun)) return;
2491 if (noun has animate && RunLife(noun, ##Attack)) rfalse;
2492 L__M(##Attack, 1, noun);
2495 [ BlowSub; L__M(##Blow, 1, noun); ];
2497 [ BurnSub;
2498 if (noun has animate) return L__M(##Burn, 2, noun);
2499 L__M(##Burn, 1, noun);
2502 [ BuySub; L__M(##Buy, 1, noun); ];
2504 [ ClimbSub;
2505 if (noun has animate) return L__M(##Climb, 2, noun);
2506 L__M(##Climb, 1, noun);
2509 [ ConsultSub; L__M(##Consult, 1, noun); ];
2511 [ CutSub;
2512 if (noun has animate) return L__M(##Cut, 2, noun);
2513 L__M(##Cut, 1, noun);
2516 [ DigSub; L__M(##Dig, 1, noun); ];
2518 [ DrinkSub; L__M(##Drink, 1, noun); ];
2520 [ FillSub;
2521 if (second == nothing) return L__M(##Fill, 1, noun);
2522 L__M(##Fill, 2, noun, second);
2525 [ JumpSub; L__M(##Jump, 1, noun); ];
2527 [ JumpInSub;
2528 if (noun has animate) return L__M(##JumpIn, 2, noun);
2529 if (noun has enterable) <<Enter noun>>;
2530 L__M(##JumpOn, 1, noun);
2533 [ JumpOnSub;
2534 if (noun has animate) return L__M(##JumpOn, 2, noun);
2535 if (noun has enterable && noun has supporter) <<Enter noun>>;
2536 L__M(##JumpOn, 1, noun);
2539 [ JumpOverSub;
2540 if (noun has animate) return L__M(##JumpOver, 2, noun);
2541 L__M(##JumpOver, 1, noun);
2544 [ KissSub;
2545 if (ObjectIsUntouchable(noun)) return;
2546 if (RunLife(noun, ##Kiss)) return;
2547 if (noun == actor) return L__M(##Touch, 3, noun);
2548 L__M(##Kiss, 1, noun);
2551 [ ListenSub; L__M(##Listen, 1, noun); ];
2553 [ MildSub; L__M(##Mild, 1, noun); ];
2555 [ NoSub; L__M(##No); ];
2557 [ PraySub; L__M(##Pray, 1, noun); ];
2559 [ PullSub;
2560 if (ObjectIsUntouchable(noun)) return;
2561 if (noun == player) return L__M(##Pull, 1, noun);
2562 if (noun == actor) return L__M(##Pull, 6, noun);
2563 if (noun has static) return L__M(##Pull, 2, noun);
2564 if (noun has scenery) return L__M(##Pull, 3, noun);
2565 if (noun has animate) return L__M(##Pull, 5, noun);
2566 L__M(##Pull, 4, noun);
2569 [ PushSub;
2570 if (ObjectIsUntouchable(noun)) return;
2571 if (noun == player) return L__M(##Push, 1, noun);
2572 if (noun == actor) return L__M(##Push, 5, noun);
2573 if (noun has static) return L__M(##Push, 2, noun);
2574 if (noun has scenery) return L__M(##Push, 3, noun);
2575 if (noun has animate) return L__M(##Push, 5, noun);
2576 L__M(##Push, 4, noun);
2579 [ PushDirSub; L__M(##PushDir, 1, noun); ];
2581 [ RubSub;
2582 if (ObjectIsUntouchable(noun)) return;
2583 if (noun has animate) return L__M(##Rub, 2, noun);
2584 L__M(##Rub, 1, noun);
2587 [ SetSub; L__M(##Set, 1, noun); ];
2589 [ SetToSub; L__M(##SetTo, 1, noun); ];
2591 [ SingSub; L__M(##Sing, 1, noun); ];
2593 [ SleepSub; L__M(##Sleep, 1, noun); ];
2595 [ SmellSub;
2596 if (noun ~= nothing && noun has animate) return L__M(##Smell, 2, noun);
2597 L__M(##Smell, 1, noun);
2600 [ SorrySub; L__M(##Sorry, 1, noun); ];
2602 [ SqueezeSub;
2603 if (ObjectIsUntouchable(noun)) return;
2604 if (noun has animate && noun ~= player) return L__M(##Squeeze, 1, noun);
2605 L__M(##Squeeze, 2, noun);
2608 [ StrongSub; L__M(##Strong, 1, noun); ];
2610 [ SwimSub; L__M(##Swim, 1, noun); ];
2612 [ SwingSub; L__M(##Swing, 1, noun); ];
2614 [ TasteSub;
2615 if (ObjectIsUntouchable(noun)) return;
2616 if (noun has animate) return L__M(##Taste, 2, noun);
2617 L__M(##Taste, 1, noun);
2620 [ TellSub;
2621 if (noun == actor) return L__M(##Tell, 1, noun);
2622 if (RunLife(noun, ##Tell)) return;
2623 L__M(##Tell, 2, noun);
2626 [ ThinkSub; L__M(##Think, 1, noun); ];
2628 [ ThrowAtSub;
2629 if (ObjectIsUntouchable(noun)) return;
2630 if (second > 1) {
2631 action = ##ThrownAt;
2632 if (RunRoutines(second, before)) { action = ##ThrowAt; rtrue; }
2633 action = ##ThrowAt;
2635 if (noun has worn && ImplicitDisrobe(noun)) return;
2636 if (second hasnt animate) return L__M(##ThrowAt, 1, noun);
2637 if (RunLife(second, ##ThrowAt)) return;
2638 L__M(##ThrowAt, 2, noun);
2641 [ TieSub;
2642 if (noun has animate) return L__M(##Tie, 2, noun);
2643 L__M(##Tie, 1, noun);
2646 [ TouchSub;
2647 if (noun == actor) return L__M(##Touch, 3, noun);
2648 if (ObjectIsUntouchable(noun)) return;
2649 if (noun has animate) return L__M(##Touch, 1, noun);
2650 L__M(##Touch, 2,noun);
2653 [ TurnSub;
2654 if (ObjectIsUntouchable(noun)) return;
2655 if (noun == player) return L__M(##Turn, 1, noun);
2656 if (noun == actor) return L__M(##Turn, 5, noun);
2657 if (noun has static) return L__M(##Turn, 2, noun);
2658 if (noun has scenery) return L__M(##Turn, 3, noun);
2659 if (noun has animate) return L__M(##Turn, 5, noun);
2660 L__M(##Turn, 4, noun);
2663 [ WaitSub;
2664 if (AfterRoutines()) rtrue;
2665 L__M(##Wait, 1, noun);
2668 [ WakeSub; L__M(##Wake, 1, noun); ];
2670 [ WakeOtherSub;
2671 if (ObjectIsUntouchable(noun)) return;
2672 if (RunLife(noun, ##WakeOther)) return;
2673 L__M(##WakeOther, 1, noun);
2676 [ WaveSub;
2677 if (noun == player) return L__M(##Wave, 2 ,noun, second);
2678 if (noun == actor) return L__M(##Wave, 3, noun, second);
2679 if (noun notin actor && ImplicitTake(noun)) return L__M(##Wave, 1, noun);
2680 L__M(##Wave, 2, noun, second);
2683 [ WaveHandsSub;
2684 if (noun) return L__M(##WaveHands, 2, noun);
2685 L__M(##WaveHands, 1, noun); ];
2687 [ YesSub; L__M(##Yes); ];
2689 ! ----------------------------------------------------------------------------
2690 ! Debugging verbs
2691 ! ----------------------------------------------------------------------------
2693 #Ifdef DEBUG;
2695 [ TraceOnSub; parser_trace = 1; "[Trace on.]"; ];
2697 [ TraceLevelSub;
2698 parser_trace = noun;
2699 print "[Parser tracing set to level ", parser_trace, ".]^";
2702 [ TraceOffSub; parser_trace = 0; "Trace off."; ];
2704 [ RoutinesOnSub;
2705 debug_flag = debug_flag | DEBUG_MESSAGES;
2706 "[Message listing on.]";
2709 [ RoutinesOffSub;
2710 debug_flag = debug_flag & ~DEBUG_MESSAGES;
2711 "[Message listing off.]";
2714 [ RoutinesVerboseSub;
2715 debug_flag = debug_flag | (DEBUG_VERBOSE|DEBUG_MESSAGES);
2716 "[Verbose message listing on.]";
2719 [ ActionsOnSub;
2720 debug_flag = debug_flag | DEBUG_ACTIONS;
2721 "[Action listing on.]";
2724 [ ActionsOffSub;
2725 debug_flag = debug_flag & ~DEBUG_ACTIONS;
2726 "[Action listing off.]";
2729 [ TimersOnSub;
2730 debug_flag = debug_flag | DEBUG_TIMERS;
2731 "[Timers listing on.]";
2734 [ TimersOffSub;
2735 debug_flag = debug_flag & ~DEBUG_TIMERS;
2736 "[Timers listing off.]";
2739 #Ifdef VN_1610;
2741 [ ChangesOnSub; debug_flag = debug_flag | DEBUG_CHANGES; "[Changes listing on.]"; ];
2742 [ ChangesOffSub; debug_flag = debug_flag & ~DEBUG_CHANGES; "[Changes listing off.]"; ];
2744 #Ifnot;
2746 [ ChangesOnSub; "[Changes listing available only from Inform 6.2 onwards.]"; ];
2748 [ ChangesOffSub; "[Changes listing available only from Inform 6.2 onwards.]"; ];
2750 #Endif; ! VN_1610
2752 #Ifdef TARGET_ZCODE;
2754 [ PredictableSub i;
2755 i = random(-100);
2756 "[Random number generator now predictable.]";
2759 #Ifnot; ! TARGET_GLULX;
2761 [ PredictableSub;
2762 @setrandom 100;
2763 "[Random number generator now predictable.]";
2766 #Endif; ! TARGET_;
2768 [ XTestMove obj dest;
2769 if (~~obj ofclass Object) "[Not an object.]";
2770 if (~~dest ofclass Object) "[Destination not an object.]";
2771 if ((obj <= InformLibrary) || (obj == LibraryMessages) || (obj in 1))
2772 "[Can't move ", (name) obj, ": it's a system object.]";
2773 while (dest) {
2774 if (dest == obj) "[Can't move ", (name) obj, ": it would contain itself.]";
2775 dest = parent(dest);
2777 rfalse;
2780 [ XPurloinSub;
2781 if (XTestMove(noun, player)) return;
2782 move noun to player; give noun moved ~concealed;
2783 "[Purloined.]";
2786 [ XAbstractSub;
2787 if (XTestMove(noun, second)) return;
2788 move noun to second;
2789 "[Abstracted.]";
2792 [ XObj obj f;
2793 if (parent(obj) == 0) print (name) obj; else print (a) obj;
2794 print " (", obj, ") ";
2795 if (f && parent(obj))
2796 print "in ~", (name) parent(obj), "~ (", parent(obj), ")";
2797 new_line;
2798 if (child(obj) == 0) rtrue;
2799 if (obj == Class) ! ???
2800 WriteListFrom(child(obj), NEWLINE_BIT+INDENT_BIT+ALWAYS_BIT+ID_BIT+NOARTICLE_BIT, 1);
2801 else
2802 WriteListFrom(child(obj), NEWLINE_BIT+INDENT_BIT+ALWAYS_BIT+ID_BIT+FULLINV_BIT, 1);
2805 [ XTreeSub i;
2806 if (noun && ~~noun ofclass Object) "[Not an object.]";
2807 if (noun == 0) {
2808 objectloop (i)
2809 if (i ofclass Object && parent(i) == 0) XObj(i);
2811 else XObj(noun, true);
2814 [ GotoSub;
2815 if ((~~noun ofclass Object) || parent(noun)) "[Not a safe place.]";
2816 PlayerTo(noun);
2819 [ GoNearSub x;
2820 if (~~noun ofclass Object) "[Not a safe place.]";
2821 x = noun;
2822 while (parent(x)) x = parent(x);
2823 PlayerTo(x);
2826 [ Print_ScL obj; print_ret ++x_scope_count, ": ", (a) obj, " (", obj, ")"; ];
2828 [ ScopeSub;
2829 if (noun && ~~noun ofclass Object) "[Not an object.]";
2830 x_scope_count = 0;
2831 LoopOverScope(Print_ScL, noun);
2832 if (x_scope_count == 0) "Nothing is in scope.";
2835 #Ifdef TARGET_GLULX;
2837 [ GlkListSub id val;
2838 id = glk_window_iterate(0, gg_arguments);
2839 while (id) {
2840 print "Window ", id, " (", gg_arguments-->0, "): ";
2841 val = glk_window_get_type(id);
2842 switch (val) {
2843 1: print "pair";
2844 2: print "blank";
2845 3: print "textbuffer";
2846 4: print "textgrid";
2847 5: print "graphics";
2848 default: print "unknown";
2850 val = glk_window_get_parent(id);
2851 if (val) print ", parent is window ", val;
2852 else print ", no parent (root)";
2853 val = glk_window_get_stream(id);
2854 print ", stream ", val;
2855 val = glk_window_get_echo_stream(id);
2856 if (val) print ", echo stream ", val;
2857 print "^";
2858 id = glk_window_iterate(id, gg_arguments);
2860 id = glk_stream_iterate(0, gg_arguments);
2861 while (id) {
2862 print "Stream ", id, " (", gg_arguments-->0, ")^";
2863 id = glk_stream_iterate(id, gg_arguments);
2865 id = glk_fileref_iterate(0, gg_arguments);
2866 while (id) {
2867 print "Fileref ", id, " (", gg_arguments-->0, ")^";
2868 id = glk_fileref_iterate(id, gg_arguments);
2870 val = glk_gestalt(gestalt_Sound, 0);
2871 if (val) {
2872 id = glk_schannel_iterate(0, gg_arguments);
2873 while (id) {
2874 print "Soundchannel ", id, " (", gg_arguments-->0, ")^";
2875 id = glk_schannel_iterate(id, gg_arguments);
2880 #Endif; ! TARGET_;
2882 #Endif; ! DEBUG
2884 ! ----------------------------------------------------------------------------
2885 ! Finally: the mechanism for library text (the text is in the language defn)
2886 ! ----------------------------------------------------------------------------
2888 [ L__M act n x1 x2 s;
2889 if (keep_silent == 2) return;
2890 s = sw__var;
2891 sw__var = act;
2892 if (n == 0) n = 1;
2893 L___M(n, x1, x2);
2894 sw__var = s;
2897 [ L___M n x1 x2 s;
2898 s = action;
2899 lm_n = n;
2900 lm_o = x1;
2901 lm_s = x2;
2902 action = sw__var;
2903 if (RunRoutines(LibraryMessages, before)) { action = s; rfalse; }
2904 if (LibraryExtensions.RunWhile(ext_messages, false )) { action = s; rfalse; }
2905 action = s;
2906 LanguageLM(n, x1, x2);
2909 ! ==============================================================================