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 file is free software: you can redistribute it and/or modify
9 ! it under the terms of the GNU Affero General Public License as
10 ! published by the Free Software Foundation, either version 3 of the
11 ! License, or (at your option) any later version.
13 ! This file is distributed in the hope that it will be useful, but
14 ! WITHOUT ANY WARRANTY; without even the implied warranty of
15 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ! Affero General Public License for more details.
18 ! You should have received a copy of the GNU Affero General Public
19 ! License along with this program. If not, see
20 ! https://gnu.org/licenses/
22 ! This file is automatically Included in your game file by "verblib".
23 ! ==============================================================================
29 Constant Grammar__Version 2;
34 ! ------------------------------------------------------------------------------
37 #Ifdef LanguageBanner;
39 i = 0; ! suppress warning
43 #IfV5; style bold; #Endif;
44 print "^", (string) Story;
45 #IfV5; style roman; #Endif;
46 #Ifnot; ! TARGET_GLULX;
47 glk_set_style(style_Header);
48 print "^", (string) Story;
49 glk_set_style(style_Normal);
52 if (Headline) print (string) Headline;
54 print "Release ", (HDR_GAMERELEASE-->0) & $03ff, " / Serial number ";
55 for (i=0 : i<6 : i++) print (char) HDR_GAMESERIAL->i;
56 #Ifnot; ! TARGET_GLULX;
58 @aloads ROM_GAMERELEASE 0 i;
60 print " / Serial number ";
61 for (i=0 : i<6 : i++) print (char) ROM_GAMESERIAL->i;
71 #Endif; ! LanguageBanner
75 #Ifdef LanguageVersionSub;
77 ix = 0; ! suppress warning
81 ix = 0; ! shut up compiler warning
82 if (standard_interpreter > 0) {
83 print "Standard interpreter ", standard_interpreter/256, ".", standard_interpreter%256,
84 " (", HDR_TERPNUMBER->0;
85 #Iftrue (#version_number == 6);
86 print (char) '.', HDR_TERPVERSION->0;
88 print (char) HDR_TERPVERSION->0;
93 print "Interpreter ", HDR_TERPNUMBER->0, " Version ";
94 #Iftrue (#version_number == 6);
95 print HDR_TERPVERSION->0;
97 print (char) HDR_TERPVERSION->0;
102 #Ifnot; ! TARGET_GLULX;
104 print "Interpreter version ", ix / $10000, ".", (ix & $FF00) / $100,
105 ".", ix & $FF, " / ";
107 print "VM ", ix / $10000, ".", (ix & $FF00) / $100, ".", ix & $FF, " / ";
109 print "Library serial number ", (string) LibSerial, "^";
110 #Ifdef LanguageVersion;
111 print (string) LanguageVersion, "^";
112 #Endif; ! LanguageVersion
113 #Endif; ! LanguageVersionSub
116 [ RunTimeError n p1 p2;
117 #Ifdef LanguageError;
118 LanguageError(n, p1, p2);
121 print "** Library error ", n, " (", p1, ", ", p2, ") **^** ";
123 1: print "preposition not found (this should not occur)";
124 2: print "Property value not routine or string: ~", (property) p2, "~ of ~", (name) p1,
126 3: print "Entry in property list not routine or string: ~", (property) p2, "~ list of ~",
127 (name) p1, "~ (", p1, ")";
128 4: print "Too many timers/daemons are active simultaneously.
129 The limit is the library constant MAX_TIMERS
130 (currently ", MAX_TIMERS, ") and should be increased";
131 5: print "Object ~", (name) p1, "~ has no ~", (property) p2, "~ property";
132 7: print "The object ~", (name) p1, "~ can only be used as a player object if it has
133 the ~number~ property";
134 8: print "Attempt to take random entry from an empty table array";
135 9: print p1, " is not a valid direction property number";
136 10: print "The player-object is outside the object tree";
137 11: print "The room ~", (name) p1, "~ has no ~", (property) p2, "~ property";
138 12: print "Tried to set a non-existent pronoun using SetPronoun";
139 13: print "A 'topic' token can only be followed by a preposition";
140 14: print "Overflowed buffer limit of ", p1, " using '@@64output_stream 3' ", (string) p2;
141 15: print "LoopWithinObject broken because the object ", (name) p1, " was moved while the loop passed through it.";
142 16: print "Attempt to use illegal narrative_voice of ", p1, ".";
144 print "(unexplained)";
148 "** Library error ", n, " (", p1, ", ", p2, ") **";
150 #Endif; ! LanguageError
153 ! ----------------------------------------------------------------------------
154 ! The WriteListFrom routine, a flexible object-lister taking care of
155 ! plurals, inventory information, various formats and so on. This is used
156 ! by everything in the library which ever wants to list anything.
158 ! If there were no objects to list, it prints nothing and returns false;
159 ! otherwise it returns true.
161 ! o is the object, and style is a bitmap, whose bits are given by:
162 ! ----------------------------------------------------------------------------
165 Constant NEWLINE_BIT $0001; ! New-line after each entry
166 Constant INDENT_BIT $0002; ! Indent each entry by depth
167 Constant FULLINV_BIT $0004; ! Full inventory information after entry
168 Constant ENGLISH_BIT $0008; ! English sentence style, with commas and and
169 Constant RECURSE_BIT $0010; ! Recurse downwards with usual rules
170 Constant ALWAYS_BIT $0020; ! Always recurse downwards
171 Constant TERSE_BIT $0040; ! More terse English style
172 Constant PARTINV_BIT $0080; ! Only brief inventory information after entry
173 Constant DEFART_BIT $0100; ! Use the definite article in list
174 Constant WORKFLAG_BIT $0200; ! At top level (only), only list objects
175 ! which have the "workflag" attribute
176 Constant ISARE_BIT $0400; ! Print " is" or " are" before list
177 Constant CONCEAL_BIT $0800; ! Omit objects with "concealed" or "scenery":
178 ! if WORKFLAG_BIT also set, then does _not_
179 ! apply at top level, but does lower down
180 Constant NOARTICLE_BIT $1000; ! Print no articles, definite or not
181 Constant ID_BIT $2000; ! Print object id after each entry
183 [ NextEntry o odepth;
186 if (o == 0) return 0;
187 if (lt_value && o.list_together ~= lt_value) continue;
188 if (c_style & WORKFLAG_BIT && odepth==0 && o hasnt workflag) continue;
189 if (c_style & CONCEAL_BIT && (o has concealed || o has scenery)) continue;
195 if (c_style & ALWAYS_BIT) rtrue;
196 if (c_style & RECURSE_BIT == 0) rfalse;
197 if ((o has transparent or supporter) || (o has container && o has open)) rtrue;
202 if (child(o1) && WillRecurs(o1)) rfalse;
203 if (child(o2) && WillRecurs(o2)) rfalse;
204 if (c_style & (FULLINV_BIT + PARTINV_BIT)) {
205 if ((o1 hasnt worn && o2 has worn) || (o2 hasnt worn && o1 has worn)) rfalse;
206 if ((o1 hasnt light && o2 has light) || (o2 hasnt light && o1 has light)) rfalse;
207 if (o1 has container) {
208 if (o2 hasnt container) rfalse;
209 if ((o1 has open && o2 hasnt open) || (o2 has open && o1 hasnt open))
212 else if (o2 has container)
215 return Identical(o1, o2);
218 [ SortTogether obj value;
219 ! print "Sorting together possessions of ", (object) obj, " by value ", value, "^";
220 ! for (x=child(obj) : x : x=sibling(x))
221 ! print (the) x, " no: ", x, " lt: ", x.list_together, "^";
223 if (child(obj).list_together ~= value) move child(obj) to out_obj;
224 else move child(obj) to in_obj;
226 while (child(in_obj)) move child(in_obj) to obj;
227 while (child(out_obj)) move child(out_obj) to obj;
230 [ SortOutList obj i k l;
231 ! print "^^Sorting out list from ", (name) obj, "^ ";
232 ! for (i=child(location) : i : i=sibling(i))
233 ! print (name) i, " --> ";
238 for (i=obj : i : i=sibling(i)) {
241 ! print "Scanning ", (name) i, " with lt=", k, "^";
242 for (i=sibling(i) : i && i.list_together == k :) i = sibling(i);
244 ! print "First not in block is ", (name) i, " with lt=", i.list_together, "^";
245 for (l=sibling(i) : l : l=sibling(l))
246 if (l.list_together == k) {
247 SortTogether(parent(obj), k);
248 ! print "^^After ST:^ ";
249 ! for (i=child(location) : i : i=sibling(i))
250 ! print (name) i, " --> ";
252 obj = child(parent(obj));
261 [ Print__Spaces n; ! To avoid a bug occurring in Inform 6.01 to 6.10
266 #Ifnot; ! TARGET_GLULX;
277 [ WriteListFrom o style depth
280 if (o == nothing) return 0;
282 s1 = c_style; s2 = lt_value; s3 = listing_together;
283 s4 = listing_size; s5 = wlf_indent; s6 = inventory_stage;
285 if (o == child(parent(o))) {
287 o = child(parent(o));
291 if (WriteListR(o, depth) == 0) return 0;
293 c_style = s1; lt_value = s2; listing_together = s3;
294 listing_size = s4; wlf_indent = s5; inventory_stage = s6;
298 [ WriteListR o depth stack_pointer classes_p sizes_p i j k k2 l m n q senc mr;
299 if (depth > 0 && o == child(parent(o))) {
301 o = child(parent(o));
305 if (c_style & WORKFLAG_BIT && depth==0 && o hasnt workflag) {
309 if (c_style & CONCEAL_BIT && (o has concealed || o has scenery)) {
315 classes_p = match_classes + stack_pointer;
316 sizes_p = match_list + stack_pointer;
318 for (i=o,j=0 : i && (j+stack_pointer)<128 : i=NextEntry(i,depth),j++) {
323 if (c_style & ISARE_BIT) {
324 if (j == 1 && o hasnt pluralname) Tense(IS__TX, WAS__TX);
325 else Tense(ARE__TX, WERE__TX);
326 if (c_style & NEWLINE_BIT) print ":^";
327 else print (char) ' ';
328 c_style = c_style - ISARE_BIT;
331 stack_pointer = stack_pointer+j+1;
333 if (k < 2) jump EconomyVersion; ! It takes two to plural
335 for (i=o,k=0 : k<j : i=NextEntry(i,depth),k++)
336 if (classes_p->k == 0) {
337 classes_p->k = n; sizes_p->n = 1;
338 for (l=NextEntry(i,depth),m=k+1 : l && m<j : l=NextEntry(l,depth),m++)
339 if (classes_p->m == 0 && i.plural && l.plural ~= 0) {
340 if (ListEqual(i, l) == 1) {
341 sizes_p->n = sizes_p->n + 1;
349 for (i=1,j=o,k=0 : i<=n : i++,senc++) {
350 while (((classes_p->k) ~= i) && ((classes_p->k) ~= -i)) {
351 k++; j=NextEntry(j, depth);
356 if (j.list_together ~= 0 or lt_value && metaclass(j.list_together) == Routine or String &&
357 j.list_together == mr) senc--;
358 mr = j.list_together;
363 for (i=1,j=o,k=0,mr=0 : senc>=0 : i++,senc--) {
364 while (((classes_p->k) ~= i) && ((classes_p->k) ~= -i)) {
365 k++; j=NextEntry(j, depth);
367 if (j.list_together ~= 0 or lt_value) {
368 if (j.list_together == mr) {
372 k2 = NextEntry(j, depth);
373 if (k2 == 0 || k2.list_together ~= j.list_together) jump Omit_WL2;
374 k2 = metaclass(j.list_together);
375 if (k2 == Routine or String) {
376 q = j; listing_size = 1; l = k; m = i;
377 while (m < n && q.list_together == j.list_together) {
379 while (((classes_p->l) ~= m) && ((classes_p->l) ~= -m)) {
380 l++; q = NextEntry(q, depth);
382 if (q.list_together == j.list_together) listing_size++;
384 ! print " [", listing_size, "] ";
385 if (listing_size == 1) jump Omit_WL2;
386 if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
389 for (l=0 : l<listing_size : l++) q = q+sizes_p->(l+i);
390 EnglishNumber(q); print " ";
391 print (string) j.list_together;
392 if (c_style & ENGLISH_BIT) print " (";
393 if (c_style & INDENT_BIT) print ":^";
398 parser_one = j; parser_two = depth+wlf_indent;
399 if (RunRoutines(j, list_together) == 1) jump Omit__Sublist2;
403 @push lt_value; @push listing_together; @push listing_size;
404 #Ifnot; ! TARGET_GLULX;
405 @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
408 lt_value = j.list_together; listing_together = j; wlf_indent++;
409 WriteListR(j, depth, stack_pointer); wlf_indent--;
412 @pull listing_size; @pull listing_together; @pull lt_value;
413 #Ifnot; ! TARGET_GLULX;
414 @copy sp listing_size;
415 @copy sp listing_together;
420 if (q & ENGLISH_BIT) print ")";
424 parser_one = j; parser_two = depth+wlf_indent;
425 RunRoutines(j, list_together);
430 if (q & NEWLINE_BIT && c_style & NEWLINE_BIT == 0) new_line;
432 mr = j.list_together;
439 if (WriteBeforeEntry(j, depth, 0, senc) == 1) jump Omit_FL2;
440 if (sizes_p->i == 1) {
441 if (c_style & NOARTICLE_BIT) print (name) j;
443 if (c_style & DEFART_BIT) print (the) j;
446 if (c_style & ID_BIT) print " (", j, ")";
449 if (c_style & DEFART_BIT) PrefaceByArticle(j, 1, sizes_p->i);
450 print (number) sizes_p->i, " ";
451 PrintOrRun(j, plural, 1);
453 if (sizes_p->i > 1 && j hasnt pluralname) {
455 WriteAfterEntry(j, depth, stack_pointer);
459 WriteAfterEntry(j,depth,stack_pointer);
463 if (c_style & ENGLISH_BIT) {
464 if (senc == 1) print (SerialComma) i+senc, (string) AND__TX;
465 if (senc > 1) print (string) COMMA__TX;
474 for (i=1,j=o : i<=n : j=NextEntry(j,depth),i++,senc++) {
475 if (j.list_together ~= 0 or lt_value && metaclass(j.list_together) == Routine or String &&
476 j.list_together==mr) senc--;
477 mr = j.list_together;
480 for (i=1,j=o,mr=0 : i<=senc : j=NextEntry(j,depth),i++) {
481 if (j.list_together ~= 0 or lt_value) {
482 if (j.list_together == mr) {
486 k = NextEntry(j, depth);
487 if (k == 0 || k.list_together ~= j.list_together) jump Omit_WL;
488 k = metaclass(j.list_together);
489 if (k == Routine or String) {
490 if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
494 q = NextEntry(q, depth); l++;
495 } until (q == 0 || q.list_together ~= j.list_together);
496 EnglishNumber(l); print " ";
497 print (string) j.list_together;
498 if (c_style & ENGLISH_BIT) print " (";
499 if (c_style & INDENT_BIT) print ":^";
504 parser_one = j; parser_two = depth+wlf_indent;
505 if (RunRoutines(j, list_together) == 1) jump Omit__Sublist;
509 @push lt_value; @push listing_together; @push listing_size;
510 #Ifnot; ! TARGET_GLULX;
511 @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
514 lt_value = j.list_together; listing_together = j; wlf_indent++;
515 WriteListR(j, depth, stack_pointer); wlf_indent--;
518 @pull listing_size; @pull listing_together; @pull lt_value;
519 #Ifnot; ! TARGET_GLULX;
520 @copy sp listing_size; @copy sp listing_together; @copy sp lt_value;
524 if (q & ENGLISH_BIT) print ")";
528 parser_one = j; parser_two = depth+wlf_indent;
529 RunRoutines(j, list_together);
534 if (q & NEWLINE_BIT && c_style & NEWLINE_BIT == 0) new_line;
536 mr = j.list_together;
543 if (WriteBeforeEntry(j, depth, i, senc) == 1) jump Omit_FL;
544 if (c_style & NOARTICLE_BIT) print (name) j;
546 if (c_style & DEFART_BIT) print (the) j;
549 if (c_style & ID_BIT) print " (", j, ")";
550 WriteAfterEntry(j, depth, stack_pointer);
554 if (c_style & ENGLISH_BIT) {
555 if (i == senc-1) print (SerialComma) senc, (string) AND__TX;
556 if (i < senc-1) print (string) COMMA__TX;
562 ]; ! end of WriteListR
564 [ WriteBeforeEntry o depth ipos sentencepos
568 if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
569 if (o.invent && (c_style & (PARTINV_BIT|FULLINV_BIT))) {
570 flag = PrintOrRun(o, invent, 1);
572 if (c_style & ENGLISH_BIT) {
573 if (ipos == sentencepos-1)
574 print (SerialComma) sentencepos, (string) AND__TX;
575 if (ipos < sentencepos-1)
576 print (string) COMMA__TX;
578 if (c_style & NEWLINE_BIT) new_line;
584 [ WriteAfterEntry o depth stack_p
585 p recurse_flag parenth_flag eldest_child child_count combo i j;
588 if (c_style & PARTINV_BIT) {
589 if (o.invent && RunRoutines(o, invent))
590 if (c_style & NEWLINE_BIT) ""; else rtrue;
593 if (o has light && location hasnt light) combo=combo+1;
594 if (o has container && o hasnt open) combo=combo+2;
595 if ((o has container && (o has open || o has transparent))) {
597 if (i hasnt concealed && i hasnt scenery) {
601 if (~~j) combo=combo+4;
603 if (combo) L__M(##ListMiscellany, combo, o);
604 } ! end of PARTINV_BIT processing
606 if (c_style & FULLINV_BIT) {
607 if (o.invent && RunRoutines(o, invent))
608 if (c_style & NEWLINE_BIT) ""; else rtrue;
610 if (o has light && o has worn) { L__M(##ListMiscellany, 8, o); parenth_flag = true; }
612 if (o has light) { L__M(##ListMiscellany, 9, o); parenth_flag = true; }
613 if (o has worn) { L__M(##ListMiscellany, 10, o); parenth_flag = true; }
617 if (o has openable) {
618 if (parenth_flag) print (string) AND__TX;
619 else L__M(##ListMiscellany, 11, o);
621 if (child(o)) L__M(##ListMiscellany, 12, o);
622 else L__M(##ListMiscellany, 13, o);
624 if (o has lockable && o has locked) L__M(##ListMiscellany, 15, o);
625 else L__M(##ListMiscellany, 14, o);
629 if (child(o)==0 && o has transparent)
630 if (parenth_flag) L__M(##ListMiscellany, 16, o);
631 else L__M(##ListMiscellany, 17, o);
633 if (parenth_flag) print ")";
634 } ! end of FULLINV_BIT processing
636 if (c_style & CONCEAL_BIT) {
639 if (p hasnt concealed && p hasnt scenery) { child_count++; eldest_child = p; }
641 else { child_count = children(o); eldest_child = child(o); }
643 if (child_count && (c_style & ALWAYS_BIT)) {
644 if (c_style & ENGLISH_BIT) L__M(##ListMiscellany, 18, o);
648 if (child_count && (c_style & RECURSE_BIT)) {
649 if (o has supporter) {
650 if (c_style & ENGLISH_BIT) {
651 if (c_style & TERSE_BIT) L__M(##ListMiscellany, 19, o);
652 else L__M(##ListMiscellany, 20, o);
653 if (o has animate) print (string) WHOM__TX;
654 else print (string) WHICH__TX;
658 if (o has container && (o has open || o has transparent)) {
659 if (c_style & ENGLISH_BIT) {
660 if (c_style & TERSE_BIT) L__M(##ListMiscellany, 21, o);
661 else L__M(##ListMiscellany, 22, o);
662 if (o has animate) print (string) WHOM__TX;
663 else print (string) WHICH__TX;
669 if (recurse_flag && (c_style & ENGLISH_BIT))
670 if (child_count > 1 || eldest_child has pluralname) Tense(ARE2__TX, WERE2__TX);
671 else Tense(IS2__TX, WAS2__TX);
673 if (c_style & NEWLINE_BIT) new_line;
678 @push lt_value; @push listing_together; @push listing_size;
679 #Ifnot; ! TARGET_GLULX;
680 @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
682 lt_value = 0; listing_together = 0; listing_size = 0;
683 WriteListR(o, depth+1, stack_p);
685 @pull listing_size; @pull listing_together; @pull lt_value;
686 #Ifnot; ! TARGET_GLULX;
687 @copy sp listing_size; @copy sp listing_together; @copy sp lt_value;
689 if (c_style & TERSE_BIT) print ")";
693 ! ----------------------------------------------------------------------------
694 ! LoopWithinObject(rtn,obj,arg)
696 ! rtn is the address of a user-supplied routine.
697 ! obj is an optional parent object whose dependents are to be processed; the
698 ! default is the current actor (normally the player).
699 ! arg is an optional argument passed to the rtn; this can be a single variable
700 ! or constant, or the address of an array (which enables multiple values to be
701 ! passed and returned).
703 ! For each object o which is a child, grandchild, great-grandchild, etc, of the
704 ! original obj, LoopWithinObject() calls rtn(o,arg).
706 ! The rtn should perform any appropriate testing or processing on each object o,
707 ! using the optional arg value if necessary. If the rtn returns true (or any
708 ! positive value), the children of o, if any, are also tested; those children
709 ! are skipped if rtn returns false. To terminate the loop before all objects
710 ! have been processed, rtn should return a large negative number (eg -99).
712 ! To deal with supporters and open containers, so that objects are processed
713 ! only if they are accessible to the player, rtn might end with these
715 ! if ((o has transparent or supporter) || (o has container && o has open)) rtrue;
717 ! or alternatively with:
718 ! c_style = RECURSE_BIT; return WillRecurs(o);
720 ! LoopWithinObject() returns the number of objects which have been processed.
721 ! ----------------------------------------------------------------------------
723 [ LoopWithinObject rtn obj arg
725 if (obj == 0) obj = actor;
729 x = rtn(o, arg); ! user-supplied routine returning x.
730 ! if x < 0: skip up to next parent
731 ! if x = 0: jump across to next sibling
732 ! if x > 0: continue down to child objects
733 if (y ~= parent(o)) { RunTimeError(15, o); rfalse; }
734 if (x > 0 && child(o)) o = child(o);
737 if (++x > 0 && sibling(o)) { o = sibling(o); break; }
739 if (o == obj) return n;
745 ! ----------------------------------------------------------------------------
746 ! Much better menus can be created using one of the optional library
747 ! extensions. These are provided for compatibility with previous practice:
748 ! ----------------------------------------------------------------------------
750 [ LowKey_Menu menu_choices EntryR ChoiceR lines main_title i j;
757 main_title = item_name;
759 print "--- "; print (string) main_title; print " ---^^";
761 if (menu_choices ofclass Routine) menu_choices();
762 else print (string) menu_choices;
765 L__M(##Miscellany, 52, lines);
772 read buffer parse DrawStatusLine;
774 j = parse->1; ! number of words
775 #Ifnot; ! TARGET_GLULX;
776 KeyboardPrimitive(buffer, parse);
777 j = parse-->0; ! number of words
781 if (j == 0 || (i == QUIT1__WD or QUIT2__WD)) {
782 menu_nesting--; if (menu_nesting > 0) rfalse;
783 if (deadflag == 0) <<Look>>;
787 if (i == 0) jump LKRD;
788 if (i < 1 || i > lines) continue;
791 if (j == 2) jump LKRD;
800 [ DoMenu menu_choices EntryR ChoiceR; LowKey_Menu(menu_choices, EntryR, ChoiceR); ];
806 [ DoMenu menu_choices EntryR ChoiceR
807 lines main_title main_wid cl i j oldcl pkey ch cw y x;
808 if (pretty_flag == 0) return LowKey_Menu(menu_choices, EntryR, ChoiceR);
812 main_title = item_name; main_wid = item_width;
819 #Iftrue (#version_number == 6);
821 ch = HDR_FONTWUNITS->0;
827 i = HDR_SCREENWCHARS->0;
832 #Iftrue (#version_number == 6);
834 cw = HDR_FONTHUNITS->0;
840 spaces(i); j=1+(i/2-main_wid)*cw;
842 print (string) main_title;
843 y=1+ch; @set_cursor y 1; spaces(i);
844 x=1+cw; @set_cursor y x; print (string) NKEY__TX;
845 j=1+(i-13)*cw; @set_cursor y j; print (string) PKEY__TX;
846 y=y+ch; @set_cursor y 1; spaces(i);
847 @set_cursor y x; print (string) RKEY__TX;
848 j=1+(i-18)*cw; @set_cursor y j;
850 if (menu_nesting == 1) print (string) QKEY1__TX;
851 else print (string) QKEY2__TX;
854 @set_cursor y x; font off;
856 if (menu_choices ofclass String) print (string) menu_choices;
863 y=1+(oldcl-1)*ch; @set_cursor y x; print " ";
865 y=1+(cl-1)*ch; @set_cursor y x; print ">";
869 @read_char 1 -> pkey;
870 if (pkey == NKEY1__KY or NKEY2__KY or 130) {
871 cl++; if (cl == 7+lines) cl = 7; continue;
873 if (pkey == PKEY1__KY or PKEY2__KY or 129) {
874 cl--; if (cl == 6) cl = 6+lines; continue;
876 if (pkey == QKEY1__KY or QKEY2__KY or 27 or 131) break;
877 if (pkey == 10 or 13 or 132) {
878 @set_window 0; font on;
879 new_line; new_line; new_line;
886 i = HDR_SCREENWCHARS->0; if ( i== 0) i = 80;
887 @set_window 1; @set_cursor 1 1; style reverse; spaces(i);
888 j=1+(i/2-item_width)*cw;
890 print (string) item_name;
891 style roman; @set_window 0; new_line;
894 if (i == 2) jump ReDisplay;
897 L__M(##Miscellany, 53);
898 @read_char 1 -> pkey; jump ReDisplay;
902 menu_nesting--; if (menu_nesting > 0) rfalse;
903 font on; @set_cursor 1 1;
904 @erase_window $ffff; @set_window 0;
905 #Iftrue (#version_number == 6);
908 new_line; new_line; new_line;
909 if (deadflag == 0) <<Look>>;
914 #Ifnot; ! TARGET_GLULX
916 [ DoMenu menu_choices EntryR ChoiceR
917 winwid winhgt lines main_title main_wid cl i oldcl pkey;
919 if (pretty_flag == 0 || gg_statuswin == 0) return LowKey_Menu(menu_choices, EntryR, ChoiceR);
924 main_title = item_name;
925 main_wid = item_width;
929 ! If we printed "hit arrow keys" here, it would be appropriate to
930 ! check for the availability of Glk input keys. But we actually
931 ! print "hit N/P/Q". So it's reasonable to silently accept Glk
932 ! arrow key codes as secondary options.
936 glk_window_clear(gg_statuswin);
937 glk_window_clear(gg_mainwin);
938 glk_set_window(gg_statuswin);
939 StatusLineHeight(lines+7);
940 glk_window_get_size(gg_statuswin, gg_arguments, gg_arguments+4);
941 winwid = gg_arguments-->0;
942 winhgt = gg_arguments-->1;
943 glk_set_style(style_Subheader);
944 glk_window_move_cursor(gg_statuswin, winwid/2-main_wid, 0);
945 print (string) main_title;
946 glk_window_move_cursor(gg_statuswin, 1, 1);
947 print (string) NKEY__TX;
948 glk_window_move_cursor(gg_statuswin, winwid-13, 1);
949 print (string) PKEY__TX;
950 glk_window_move_cursor(gg_statuswin, 1, 2);
951 print (string) RKEY__TX;
952 glk_window_move_cursor(gg_statuswin, winwid-18, 2);
953 if (menu_nesting == 1) print (string) QKEY1__TX;
954 else print (string) QKEY2__TX;
955 glk_set_style(style_Normal);
956 glk_window_move_cursor(gg_statuswin, 1, 4);
957 if (menu_choices ofclass String) print (string) menu_choices;
964 if (cl < 0 || cl >= lines) cl = 0;
966 glk_window_move_cursor(gg_statuswin, 3, oldcl+6);
970 glk_window_move_cursor(gg_statuswin, 3, oldcl+6);
973 pkey = KeyCharPrimitive(gg_statuswin, true);
974 if (pkey == $80000000) jump ReDisplay;
975 if (pkey == NKEY1__KY or NKEY2__KY or $fffffffb) {
977 if (cl >= lines) cl = 0;
980 if (pkey == PKEY1__KY or PKEY2__KY or $fffffffc) {
982 if (cl < 0) cl = lines-1;
985 if (pkey == QKEY1__KY or QKEY2__KY or $fffffff8 or $fffffffe) break;
986 if (pkey == $fffffffa or $fffffffd) {
987 glk_set_window(gg_mainwin);
988 new_line; new_line; new_line;
991 glk_window_clear(gg_statuswin);
992 glk_window_clear(gg_mainwin);
993 glk_set_window(gg_statuswin);
995 glk_window_get_size(gg_statuswin, gg_arguments, gg_arguments+4);
996 winwid = gg_arguments-->0;
997 winhgt = gg_arguments-->1;
998 glk_set_style(style_Subheader);
999 glk_window_move_cursor(gg_statuswin, winwid/2-item_width, 0);
1000 print (string) item_name;
1001 glk_set_style(style_Normal);
1002 glk_set_window(gg_mainwin);
1005 if (i == 2) jump ReDisplay;
1007 L__M(##Miscellany, 53);
1008 pkey = KeyCharPrimitive(gg_mainwin, 1);
1013 ! done with this menu...
1015 if (menu_nesting > 0) rfalse;
1016 glk_set_window(gg_mainwin);
1017 glk_window_clear(gg_mainwin);
1018 new_line; new_line; new_line;
1019 if (deadflag == 0) <<Look>>;
1024 ! ----------------------------------------------------------------------------
1025 ! A cunning routine (which could have been a daemon, but isn't, for the
1026 ! sake of efficiency) to move objects which could be in many rooms about
1027 ! so that the player never catches one not in place
1028 ! ----------------------------------------------------------------------------
1030 [ MoveFloatingObjects i k l m address flag;
1031 if (location == player or nothing) return;
1033 address = i.&found_in;
1034 if (address && i hasnt non_floating && ~~IndirectlyContains(player, i)) {
1035 if (metaclass(address-->0) == Routine)
1036 flag = i.found_in();
1039 k = i.#found_in/WORDSIZE;
1040 for (l=0 : l<k : l++) {
1042 if ((m in Class && location ofclass m) ||
1043 m == location || m in location) {
1050 if (i notin location) move i to location;
1052 if (parent(i)) remove i;
1058 ! ----------------------------------------------------------------------------
1059 ! Two little routines for moving the player safely.
1060 ! ----------------------------------------------------------------------------
1062 [ PlayerTo newplace flag;
1064 move player to newplace;
1065 while (parent(newplace)) newplace = parent(newplace);
1066 location = real_location = newplace;
1067 MoveFloatingObjects(); AdjustLight(1);
1070 1: NoteArrival(); ScoreArrival();
1075 [ MovePlayer direc; <Go direc>; <Look>; ];
1077 ! ----------------------------------------------------------------------------
1078 ! The handy YesOrNo routine, and some "meta" verbs
1079 ! ----------------------------------------------------------------------------
1081 [ YesOrNo noStatusRedraw
1084 #Ifdef TARGET_ZCODE;
1085 if (location == nothing || parent(player) == nothing || noStatusRedraw)
1087 else read buffer parse DrawStatusLine;
1089 #Ifnot; ! TARGET_GLULX;
1090 noStatusRedraw = 0; ! suppress warning
1091 KeyboardPrimitive(buffer, parse);
1094 if (j) { ! at least one word entered
1096 if (i == YES1__WD or YES2__WD or YES3__WD) rtrue;
1097 if (i == NO1__WD or NO2__WD or NO3__WD) rfalse;
1099 L__M(##Quit, 1); print "> ";
1103 #Ifdef TARGET_ZCODE;
1107 if (YesOrNo()) quit;
1112 if (YesOrNo()) { @restart; L__M(##Restart, 2); }
1117 return L__M(##Restore, 1);
1134 return L__M(##Save, 1);
1144 return L__M(##Verify, 1);
1150 transcript_mode = ((HDR_GAMEFLAGS-->0) & 1);
1151 if (transcript_mode) return L__M(##ScriptOn, 1);
1153 if (((HDR_GAMEFLAGS-->0) & 1) == 0) return L__M(##ScriptOn, 3);
1154 L__M(##ScriptOn, 2); VersionSub();
1155 transcript_mode = true;
1159 transcript_mode = ((HDR_GAMEFLAGS-->0) & 1);
1160 if (transcript_mode == false) return L__M(##ScriptOff, 1);
1161 L__M(##ScriptOff, 2);
1163 if ((HDR_GAMEFLAGS-->0) & 1) return L__M(##ScriptOff, 3);
1164 transcript_mode = false;
1170 L__M(##CommandsOn, 1);
1174 if (xcommsdir == 1) @output_stream -4;
1176 L__M(##CommandsOff, 1);
1182 L__M(##CommandsRead, 1);
1185 #Ifnot; ! TARGET_GLULX;
1189 if (YesOrNo()) quit;
1194 if (YesOrNo()) { @restart; L__M(##Restart, 2); }
1197 [ RestoreSub res fref;
1198 fref = glk_fileref_create_by_prompt($01, $02, 0);
1199 if (fref == 0) jump RFailed;
1200 gg_savestr = glk_stream_open_file(fref, $02, GG_SAVESTR_ROCK);
1201 glk_fileref_destroy(fref);
1202 if (gg_savestr == 0) jump RFailed;
1203 @restore gg_savestr res;
1204 glk_stream_close(gg_savestr, 0);
1211 fref = glk_fileref_create_by_prompt($01, $01, 0);
1212 if (fref == 0) jump SFailed;
1213 gg_savestr = glk_stream_open_file(fref, $01, GG_SAVESTR_ROCK);
1214 glk_fileref_destroy(fref);
1215 if (gg_savestr == 0) jump SFailed;
1216 @save gg_savestr res;
1218 ! The player actually just typed "restore". We're going to print
1219 ! L__M(##Restore,2); the Z-Code Inform library does this correctly
1220 ! now. But first, we have to recover all the Glk objects; the values
1221 ! in our global variables are all wrong.
1223 glk_stream_close(gg_savestr, 0);
1225 return L__M(##Restore, 2);
1227 glk_stream_close(gg_savestr, 0);
1229 if (res == 0) return L__M(##Save, 2);
1236 if (res == 0) return L__M(##Verify, 1);
1241 if (gg_scriptstr) return L__M(##ScriptOn, 1);
1242 if (gg_scriptfref == 0) {
1243 gg_scriptfref = glk_fileref_create_by_prompt($102, $05, GG_SCRIPTFREF_ROCK);
1244 if (gg_scriptfref == 0) jump S1Failed;
1246 gg_scriptstr = glk_stream_open_file(gg_scriptfref, $05, GG_SCRIPTSTR_ROCK);
1247 if (gg_scriptstr == 0) jump S1Failed;
1248 glk_window_set_echo_stream(gg_mainwin, gg_scriptstr);
1249 L__M(##ScriptOn, 2);
1253 L__M(##ScriptOn, 3);
1257 if (gg_scriptstr == 0) return L__M(##ScriptOff,1);
1258 L__M(##ScriptOff, 2);
1259 glk_stream_close(gg_scriptstr, 0);
1263 [ CommandsOnSub fref;
1264 if (gg_commandstr) {
1265 if (gg_command_reading) return L__M(##CommandsOn, 2);
1266 else return L__M(##CommandsOn, 3);
1268 fref = glk_fileref_create_by_prompt($103, $01, 0);
1269 if (fref == 0) return L__M(##CommandsOn, 4);
1270 gg_command_reading = false;
1271 gg_commandstr = glk_stream_open_file(fref, $01, GG_COMMANDWSTR_ROCK);
1272 glk_fileref_destroy(fref);
1273 if (gg_commandstr == 0) return L__M(##CommandsOn, 4);
1274 L__M(##CommandsOn, 1);
1278 if (gg_commandstr == 0) return L__M(##CommandsOff, 2);
1279 if (gg_command_reading) return L__M(##CommandsRead, 5);
1280 glk_stream_close(gg_commandstr, 0);
1282 gg_command_reading = false;
1283 L__M(##CommandsOff, 1);
1286 [ CommandsReadSub fref;
1287 if (gg_commandstr) {
1288 if (gg_command_reading) return L__M(##CommandsRead, 2);
1289 else return L__M(##CommandsRead, 3);
1291 fref = glk_fileref_create_by_prompt($103, $02, 0);
1292 if (fref == 0) return L__M(##CommandsRead, 4);
1293 gg_command_reading = true;
1294 gg_commandstr = glk_stream_open_file(fref, $02, GG_COMMANDRSTR_ROCK);
1295 glk_fileref_destroy(fref);
1296 if (gg_commandstr == 0) return L__M(##CommandsRead, 4);
1297 L__M(##CommandsRead, 1);
1302 [ NotifyOnSub; notify_mode = true; L__M(##NotifyOn); ];
1303 [ NotifyOffSub; notify_mode = false; L__M(##NotifyOff); ];
1307 objectloop (i has visited) j++;
1308 objectloop (i has visited) {
1309 print (name) i; k++;
1310 if (k == j) return L__M(##Places, 2);
1311 if (k == j-1) print (SerialComma) j, (string) AND__TX;
1312 else print (string) COMMA__TX;
1316 [ Objects1Sub i j f;
1318 objectloop (i has moved) {
1319 f = 1; print (the) i; j = parent(i);
1322 if (i has worn) L__M(##Objects, 3, j, i);
1323 else L__M(##Objects, 4, j, i);
1326 if (j has animate) { L__M(##Objects, 5, j, i); jump Obj__Ptd; }
1327 if (j has visited) { L__M(##Objects, 6, j, i); jump Obj__Ptd; }
1328 if (j has container) { L__M(##Objects, 8, j, i); jump Obj__Ptd; }
1329 if (j has supporter) { L__M(##Objects, 9, j, i); jump Obj__Ptd; }
1330 if (j has enterable) { L__M(##Objects, 7, j, i); jump Obj__Ptd; }
1332 L__M(##Objects, 10, j, i);
1338 if (f == 0) L__M(##Objects, 2);
1341 ! ----------------------------------------------------------------------------
1342 ! The scoring system
1343 ! ----------------------------------------------------------------------------
1347 if (deadflag == 0) L__M(##Score, 2);
1349 if (deadflag) new_line;
1351 if(PrintRank() == false) LibraryExtensions.RunAll(ext_printrank);
1357 return task_scores->i;
1362 if (task_done->num == 0) {
1364 score = score + TaskScore(num);
1371 if (n < 0) { n = -m; n = n*10; }
1372 if (n < 10) { print " "; jump Panuml; }
1373 if (n < 100) { print " "; jump Panuml; }
1374 if (n < 1000) { print " "; }
1383 if (score == 0 || TASKS_PROVIDED == 1) rfalse;
1385 L__M(##FullScore, 1);
1386 for (i=0 : i<NUMBER_TASKS : i++)
1387 if (task_done->i == 1) {
1388 PANum(TaskScore(i));
1389 if(PrintTaskName(i) == false)
1390 LibraryExtensions.RunAll(ext_printtaskname,i);
1393 PANum(things_score);
1394 L__M(##FullScore, 2);
1397 PANum(places_score);
1398 L__M(##FullScore, 3);
1400 new_line; PANum(score); L__M(##FullScore, 4);
1403 ! ----------------------------------------------------------------------------
1404 ! Real verbs start here: Inventory
1405 ! ----------------------------------------------------------------------------
1408 if (actor == player)
1409 inventory_style = ENGLISH_BIT+FULLINV_BIT+RECURSE_BIT;
1411 inventory_style = ENGLISH_BIT+PARTINV_BIT;
1413 inventory_style = 0;
1417 if (actor == player)
1418 inventory_style = NEWLINE_BIT+INDENT_BIT+FULLINV_BIT+RECURSE_BIT;
1420 inventory_style = NEWLINE_BIT+INDENT_BIT+PARTINV_BIT;
1422 inventory_style = 0;
1426 if (child(actor) == 0) return L__M(##Inv, 1);
1427 if (inventory_style == 0)
1428 if (actor == player) return InvTallSub();
1429 else return InvWideSub();
1431 if (inventory_style & NEWLINE_BIT) L__M(##Inv, 3); else print " ";
1433 WriteListFrom(child(actor), inventory_style, 1);
1434 if (inventory_style & ENGLISH_BIT) L__M(##Inv, 4);
1436 #Ifndef MANUAL_PRONOUNS;
1437 objectloop (x in player) PronounNotice(x);
1439 x = 0; ! To prevent a "not used" error
1443 ! ----------------------------------------------------------------------------
1444 ! The object tree and determining the possibility of moves
1445 ! ----------------------------------------------------------------------------
1447 [ CommonAncestor o1 o2 i j;
1448 ! Find the nearest object indirectly containing o1 and o2,
1449 ! or return 0 if there is no common ancestor.
1454 if (j == i) return i;
1462 [ IndirectlyContains o1 o2;
1463 ! Does o1 indirectly contain o2? (Same as testing if their common ancestor is o1.)
1465 if (o1 == o2) rtrue;
1466 if (o2 ofclass Class) rfalse;
1472 [ ObjectScopedBySomething item i j k l m;
1474 objectloop (j .& add_to_scope) {
1475 l = j.&add_to_scope;
1476 k = (j.#add_to_scope)/WORDSIZE;
1477 if (l-->0 ofclass Routine) continue;
1478 for (m=0 : m<k : m++)
1479 if (l-->m == i) return j;
1484 [ ObjectIsUntouchable item flag1 flag2 ancestor i;
1485 ! Determine if there's any barrier preventing the actor from moving
1486 ! things to "item". Return false if no barrier; otherwise print a
1487 ! suitable message and return true.
1488 ! If flag1 is set, do not print any message.
1489 ! If flag2 is set, also apply Take/Remove restrictions.
1491 ! If the item has been added to scope by something, it's first necessary
1492 ! for that something to be touchable.
1494 ancestor = CommonAncestor(actor, item);
1495 if (ancestor == 0) {
1497 while (ancestor && (i = ObjectScopedBySomething(ancestor)) == 0)
1498 ancestor = parent(ancestor);
1500 if (ObjectIsUntouchable(i, flag1, flag2)) return;
1501 ! An item immediately added to scope
1506 ! First, a barrier between the actor and the ancestor. The actor
1507 ! can only be in a sequence of enterable objects, and only closed
1508 ! containers form a barrier.
1510 if (actor ~= ancestor) {
1512 while (i ~= ancestor) {
1513 if (i has container && i hasnt open) {
1515 return L__M(##Take, 9, i, noun);
1521 ! Second, a barrier between the item and the ancestor. The item can
1522 ! be carried by someone, part of a piece of machinery, in or on top
1523 ! of something and so on.
1526 if (item ~= ancestor && i ~= player) {
1527 while (i ~= ancestor) {
1528 if (flag2 && i hasnt container && i hasnt supporter) {
1529 if (i has animate) {
1531 return L__M(##Take, 6, i, noun);
1533 if (i has transparent) {
1535 return L__M(##Take, 7, i, noun);
1538 return L__M(##Take, 8, item, noun);
1540 if (i has container && i hasnt open) {
1542 return L__M(##Take, 9, i, noun);
1550 [ AttemptToTakeObject item
1551 ancestor after_recipient i k;
1552 ! Try to transfer the given item to the actor: return false
1553 ! if successful, true if unsuccessful, printing a suitable message
1554 ! in the latter case.
1555 ! People cannot ordinarily be taken.
1556 if (item == actor) return L__M(##Take, 2, noun);
1557 if (item has animate) return L__M(##Take, 3, item);
1559 ancestor = CommonAncestor(actor, item);
1561 if (ancestor == 0) {
1562 i = ObjectScopedBySomething(item);
1563 if (i) ancestor = CommonAncestor(actor, i);
1566 ! Is the actor indirectly inside the item?
1567 if (ancestor == item) return L__M(##Take, 4, item);
1569 ! Does the actor already directly contain the item?
1570 if (item in actor) return L__M(##Take, 5, item);
1572 ! Can the actor touch the item, or is there (e.g.) a closed container
1574 if (ObjectIsUntouchable(item, false, true)) rtrue;
1576 ! The item is now known to be accessible.
1578 ! Consult the immediate possessor of the item, if it's in a container
1579 ! which the actor is not in.
1582 if (i && i ~= ancestor && (i has container or supporter)) {
1583 after_recipient = i;
1584 k = action; action = ##LetGo;
1585 if (RunRoutines(i, before)) { action = k; rtrue; }
1589 if (item has scenery) return L__M(##Take, 10, item);
1590 if (item has static) return L__M(##Take, 11, item);
1592 ! The item is now known to be available for taking. Is the player
1593 ! carrying too much? If so, possibly juggle items into the rucksack
1596 if (ObjectDoesNotFit(item, actor) ||
1597 LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, item, actor)) return;
1598 if (AtFullCapacity(item, actor)) return L__M(##Take, 12, item);
1600 ! Transfer the item.
1602 move item to actor; give item ~worn;
1604 ! Send "after" message to the object letting go of the item, if any.
1606 if (after_recipient) {
1607 k = action; action = ##LetGo;
1608 if (RunRoutines(after_recipient, after)) { action = k; rtrue; }
1614 [ AtFullCapacity n s
1616 n = n; ! suppress compiler warning
1618 objectloop (obj in s)
1619 if (obj hasnt worn) k++;
1623 if (k < RunRoutines(s, capacity) || (s == player && RoomInSack())) rfalse;
1628 if (SACK_OBJECT && SACK_OBJECT in player) {
1629 ks = keep_silent; keep_silent = 2;
1630 for (obj=youngest(player) : obj : obj=elder(obj))
1631 if (obj ~= SACK_OBJECT && obj hasnt worn or light) {
1632 <Insert obj SACK_OBJECT>;
1633 if (obj in SACK_OBJECT) {
1635 return L__M(##Take, 13, obj, SACK_OBJECT);
1643 ! ----------------------------------------------------------------------------
1644 ! Support for implicit actions
1645 ! ----------------------------------------------------------------------------
1647 [ CheckImplicitAction act o1 o2
1648 sav_act sav_noun sav_sec res;
1649 if (o1 provides before_implicit) {
1650 sav_act = action; action = act;
1651 sav_noun = noun; noun = o1;
1652 if (o2) { sav_sec = second; second = o2; }
1653 res = RunRoutines(o1, before_implicit);
1654 action = sav_act; noun = sav_noun;
1655 if (sav_sec) second = sav_sec;
1658 if (no_implicit_actions)
1668 switch (metaclass(obj)) { Class, String, Routine, nothing: rfalse; }
1669 if (obj in actor) rfalse;
1670 if (action_to_be == ##Drop && ~~IndirectlyContains(actor, obj)) rfalse;
1671 res = CheckImplicitAction(##Take, obj);
1672 ! 0 = Take object, Tell the user (normal default)
1673 ! 1 = Take object, don't Tell
1674 ! 2 = don't Take object continue (default with no_implicit_actions)
1675 ! 3 = don't Take object, don't continue
1676 if (res >= 2) rtrue;
1677 if (parent(obj) && parent(obj) has container or supporter) supcon = parent(obj);
1678 ks = keep_silent; keep_silent = 2; AttemptToTakeObject(obj); keep_silent = ks;
1679 if (obj notin actor) rtrue;
1680 if (res == 0 && ~~keep_silent)
1681 if (supcon) L__M(##Miscellany, 58, obj, supcon);
1682 else L__M(##Miscellany, 26, obj);
1688 if (parent(obj) == nothing) rfalse;
1689 res = CheckImplicitAction(##Exit, obj);
1690 ! 0 = Exit object, Tell the user (normal default)
1691 ! 1 = Exit object, don't Tell
1692 ! 2 = don't Take object continue (default with no_implicit_actions)
1693 ! 3 = don't Take object, don't continue
1694 if (res >= 2) rtrue;
1695 ks = keep_silent; keep_silent = 2; <Exit obj, actor>; keep_silent = ks;
1696 if (parent(actor) == obj) rtrue;
1697 if (res == 0 && ~~keep_silent) L__M(##Exit, 5, obj);
1703 if (obj hasnt open) rfalse;
1704 res = CheckImplicitAction(##Close, obj);
1705 ! 0 = Close object, Tell the user (normal default)
1706 ! 1 = Close object, don't Tell
1707 ! 2 = don't Take object continue (default with no_implicit_actions)
1708 ! 3 = don't Take object, don't continue
1709 if (res >= 2) rtrue;
1710 ks = keep_silent; keep_silent = 2; <Close obj, actor>; keep_silent = ks;
1711 if (obj has open) rtrue;
1712 if (res == 0 && ~~keep_silent) L__M(##Close, 4, obj);
1718 if (obj has open) rfalse;
1719 res = CheckImplicitAction(##Open, obj);
1720 ! 0 = Open object, Tell the user (normal default)
1721 ! 1 = Open object, don't Tell
1722 ! 2 = don't Take object continue (default with no_implicit_actions)
1723 ! 3 = don't Take object, don't continue
1724 if (res >= 2) rtrue;
1725 if (obj has locked) rtrue;
1726 temp = keep_silent; keep_silent = 2; <Open obj, actor>; keep_silent = temp;
1727 if (obj hasnt open) rtrue;
1728 if (res == 0 && ~~keep_silent) L__M(##Open, 6, obj);
1729 temp = action; action = ##Open; AfterRoutines(); action = temp;
1733 [ ImplicitUnlock obj;
1734 if (obj has locked) rtrue;
1738 [ ImplicitDisrobe obj
1740 if (obj hasnt worn) rfalse;
1741 res = CheckImplicitAction(##Disrobe, obj);
1742 ! 0 = Take off object, Tell the user (normal default)
1743 ! 1 = Take off object, don't Tell
1744 ! 2 = don't Take object continue (default with no_implicit_actions)
1745 ! 3 = don't Take object, don't continue
1746 if (res >= 2) rtrue;
1747 ks = keep_silent; keep_silent = 1; <Disrobe obj, actor>; keep_silent = ks;
1748 if (obj has worn && obj in actor) rtrue;
1749 if (res == 0 && ~~keep_silent) L__M(##Drop, 3, obj);
1754 ! ----------------------------------------------------------------------------
1755 ! Object movement verbs
1756 ! ----------------------------------------------------------------------------
1759 if (onotheld_mode == 0 || noun notin actor)
1760 if (AttemptToTakeObject(noun)) return;
1761 if (AfterRoutines()) return;
1762 notheld_mode = onotheld_mode;
1763 if (notheld_mode == 1 || keep_silent) return;
1764 L__M(##Take, 1, noun);
1769 if (i && i has container && i hasnt open && ImplicitOpen(i)) return L__M(##Remove, 1, i);
1770 if (i ~= second) return L__M(##Remove, 2, noun);
1771 if (i has animate) return L__M(##Take, 6, i, noun);
1773 if (AttemptToTakeObject(noun)) rtrue;
1775 action = ##Remove; if (AfterRoutines()) return;
1776 action = ##Take; if (AfterRoutines()) return;
1777 if (keep_silent) return;
1778 L__M(##Remove, 3, noun);
1782 if (noun == actor) return L__M(##PutOn, 4, noun);
1783 if (noun in parent(actor)) return L__M(##Drop, 1, noun);
1784 if (noun notin actor && ~~ImplicitTake(noun)) return L__M(##Drop, 2, noun);
1785 if (noun has worn && ImplicitDisrobe(noun)) return;
1786 move noun to parent(actor);
1787 if (AfterRoutines() || keep_silent) return;
1788 L__M(##Drop, 4, noun);
1791 [ PutOnSub ancestor;
1792 receive_action = ##PutOn;
1793 if (second == d_obj || actor in second) <<Drop noun, actor>>;
1794 if (parent(noun) == second) return L__M(##Drop, 1, noun);
1795 if (noun notin actor && ImplicitTake(noun)) return L__M(##PutOn, 1, noun);
1797 ancestor = CommonAncestor(noun, second);
1798 if (ancestor == noun) return L__M(##PutOn, 2, noun);
1799 if (ObjectIsUntouchable(second)) return;
1801 if (second ~= ancestor) {
1803 if (RunRoutines(second, before)) { action = ##PutOn; return; }
1806 if (second hasnt supporter) return L__M(##PutOn, 3, second);
1807 if (ancestor == actor) return L__M(##PutOn, 4, second);
1808 if (noun has worn && ImplicitDisrobe(noun)) return;
1810 if (ObjectDoesNotFit(noun, second) ||
1811 LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, noun, second)) return;
1812 if (AtFullCapacity(noun, second)) return L__M(##PutOn, 6, second);
1814 move noun to second;
1816 if (AfterRoutines()) return;
1818 if (second ~= ancestor) {
1820 if (RunRoutines(second, after)) { action = ##PutOn; return; }
1823 if (keep_silent) return;
1824 if (multiflag) return L__M(##PutOn, 7);
1825 L__M(##PutOn, 8, noun, second);
1828 [ InsertSub ancestor;
1829 receive_action = ##Insert;
1830 if (second == d_obj || actor in second) <<Drop noun, actor>>;
1831 if (parent(noun) == second) return L__M(##Drop, 1, noun);
1832 if (noun notin actor && ImplicitTake(noun)) return L__M(##Insert, 1, noun);
1833 ancestor = CommonAncestor(noun, second);
1834 if (ancestor == noun) return L__M(##Insert, 5, noun);
1835 if (ObjectIsUntouchable(second)) return;
1836 if (second ~= ancestor) {
1838 if (RunRoutines(second,before)) { action = ##Insert; rtrue; }
1840 if (second has container && second hasnt open && ImplicitOpen(second))
1841 return L__M(##Insert, 3, second);
1843 if (second hasnt container) return L__M(##Insert, 2, second);
1844 if (noun has worn && ImplicitDisrobe(noun)) return;
1846 if (ObjectDoesNotFit(noun, second) ||
1847 LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, noun, second)) return;
1848 if (AtFullCapacity(noun, second)) return L__M(##Insert, 7, second);
1850 move noun to second;
1852 if (AfterRoutines()) rtrue;
1854 if (second ~= ancestor) {
1856 if (RunRoutines(second, after)) { action = ##Insert; rtrue; }
1859 if (keep_silent) rtrue;
1860 if (multiflag) return L__M(##Insert, 8, noun);
1861 L__M(##Insert, 9, noun, second);
1864 ! ----------------------------------------------------------------------------
1865 ! Empties and transfers are routed through the actions above
1866 ! ----------------------------------------------------------------------------
1869 if (noun notin actor && AttemptToTakeObject(noun)) return;
1870 if (second has supporter) <<PutOn noun second, actor>>;
1871 if (second == d_obj) <<Drop noun, actor>>;
1872 <<Insert noun second, actor>>;
1875 [ EmptySub; second = d_obj; EmptyTSub(); ];
1877 [ EmptyTSub i j k flag;
1878 if (noun == second) return L__M(##EmptyT, 4, noun);
1879 if (ObjectIsUntouchable(noun)) return;
1880 if (noun hasnt container) return L__M(##EmptyT, 1, noun);
1881 if (noun hasnt open && ImplicitOpen(noun)) return L__M(##EmptyT, 2, noun);
1882 if (second ~= d_obj) {
1883 if (second hasnt supporter) {
1884 if (second hasnt container) return L__M(##EmptyT, 1, second);
1885 if (second hasnt open && ImplicitOpen(second))
1886 return L__M(##EmptyT, 2, second);
1889 i = child(noun); k = children(noun);
1890 if (i == 0) return L__M(##EmptyT, 3, noun);
1894 if (ObjectIsUntouchable(noun)) flag = true;
1895 if (noun hasnt container) flag = true;
1896 if (noun hasnt open) flag = true;
1897 if (second ~= d_obj) {
1898 if (second hasnt supporter) {
1899 if (second hasnt container) flag = true;
1900 if (second hasnt open) flag = true;
1903 if (k-- == 0) flag = 1;
1905 if (keep_silent == 0) print (name) i, (string) COLON__TX;
1906 <Transfer i second, actor>;
1911 ! ----------------------------------------------------------------------------
1913 ! ----------------------------------------------------------------------------
1916 if (noun notin actor && ImplicitTake(noun)) return L__M(##Give, 1, noun);
1917 if (second == actor) return L__M(##Give, 2, noun);
1918 if (noun has worn && ImplicitDisrobe(noun)) return;
1919 if (second == player) {
1920 move noun to player;
1921 return L__M(##Give, 4, noun);
1924 if (RunLife(second, ##Give)) return;
1925 L__M(##Give, 3, second);
1928 [ GiveRSub; <Give second noun, actor>; ];
1931 if (noun notin actor && ImplicitTake(noun)) return L__M(##Show, 1, noun);
1932 if (second == player) <<Examine noun, actor>>;
1933 if (RunLife(second, ##Show)) return;
1934 L__M(##Show, 2, second);
1937 [ ShowRSub; <Show second noun, actor>; ];
1939 ! ----------------------------------------------------------------------------
1940 ! Travelling around verbs
1941 ! ----------------------------------------------------------------------------
1943 [ EnterSub ancestor j ks;
1944 if (noun has door || noun in compass) <<Go noun, actor>>;
1945 if (actor in noun) return L__M(##Enter, 1, noun);
1946 if (noun hasnt enterable) return L__M(##Enter, 2, noun, verb_word);
1948 if (parent(actor) ~= parent(noun)) {
1949 ancestor = CommonAncestor(actor, noun);
1950 if (ancestor == actor or 0) return L__M(##Enter, 4, noun);
1951 while (actor notin ancestor) {
1954 if (parent(j) ~= ancestor || noun ~= ancestor) {
1955 L__M(##Enter, 6, j);
1960 if (actor in j) return;
1962 if (actor in noun) return;
1963 if (noun notin ancestor) {
1965 while (parent(j) ~= ancestor) j = parent(j);
1966 L__M(##Enter, 7, j);
1967 ks = keep_silent; keep_silent = 1;
1970 if (actor notin j) return;
1971 <<Enter noun, actor>>;
1975 if (noun has container && noun hasnt open && ImplicitOpen(noun)) return L__M(##Enter, 3, noun);
1978 if (AfterRoutines() || keep_silent) return;
1979 L__M(##Enter, 5, noun);
1980 if (actor == player) Locale(noun);
1984 if (parent(actor) == noun) <<Exit, actor>>;
1985 L__M(##GetOff, 1, noun);
1990 if (noun ~= nothing && noun ~= p) return L__M(##Exit, 4 ,noun);
1991 if (p == location || (location == thedark && p == real_location)) {
1992 if (actor provides posture && actor.posture) {
1994 return L__M(##Exit, 6);
1996 if ((location.out_to) || (location == thedark && real_location.out_to))
1997 <<Go out_obj, actor>>;
1998 return L__M(##Exit, 1);
2000 if (p has container && p hasnt open && ImplicitOpen(p))
2001 return L__M(##Exit, 2, p);
2003 if (noun == nothing) {
2005 if (RunRoutines(p, before)) return;
2008 move actor to parent(p);
2009 if (player provides posture) player.posture = 0;
2011 if (AfterRoutines() || keep_silent) return;
2013 if (actor == player && p has container) LookSub(1);
2016 [ VagueGoSub; L__M(##VagueGo); ];
2018 [ GoInSub; <<Go in_obj, actor>>; ];
2020 [ GoSub i j k movewith thedir next_loc;
2022 ! first, check if any PushDir object is touchable
2023 if (second && second notin Compass && ObjectIsUntouchable(second)) return;
2027 if ((location ~= thedark && i ~= location) || (location == thedark && i ~= real_location)) {
2029 if (location == thedark) location = real_location;
2030 k = RunRoutines(i, before); if (k ~= 3) location = j;
2032 movewith = i; i = parent(i);
2036 if (ImplicitExit(i)) return L__M(##Go, 1, i);
2041 thedir = noun.door_dir;
2042 if (metaclass(thedir) == Routine) thedir = RunRoutines(noun, door_dir);
2044 next_loc = i.thedir; k = metaclass(next_loc);
2045 if (k == String) { print (string) next_loc; new_line; rfalse; }
2047 next_loc = RunRoutines(i, thedir);
2048 if (next_loc == 1) rtrue;
2051 if (k == nothing || next_loc == 0) {
2052 if (i.cant_go ~= 0 or CANTGO__TX) PrintOrRun(i, cant_go);
2056 if (next_loc has door) {
2057 if (next_loc has concealed) return L__M(##Go, 2);
2058 if (next_loc hasnt open && ImplicitOpen(next_loc)) {
2059 if (noun == u_obj) return L__M(##Go, 3, next_loc);
2060 if (noun == d_obj) return L__M(##Go, 4, next_loc);
2061 return L__M(##Go, 5, next_loc);
2063 k = RunRoutines(next_loc, door_to);
2064 if (k == 0) return L__M(##Go, 6, next_loc);
2070 if (RunRoutines(next_loc, before)) { action = ##Go; return; }
2073 if (movewith == 0) move actor to next_loc; else move movewith to next_loc;
2074 if (actor ~= player) return L__M(##Go, 7);
2076 k = location; location = next_loc;
2077 MoveFloatingObjects();
2078 if (OffersLight(location))
2083 if(DarkToDark() == false) ! From real_location To location
2084 LibraryExtensions.RunAll(ext_darktodark);
2085 if (deadflag) rtrue;
2089 NoteDeparture(); real_location = next_loc;
2091 if (RunRoutines(prev_location, after)) { action = ##Go; return; }
2093 if (AfterRoutines() || keep_silent) return;
2097 ! ----------------------------------------------------------------------------
2098 ! Describing the world. SayWhatsOn(object) does just that (producing
2099 ! no text if nothing except possibly "scenery" and "concealed" items are).
2100 ! Locale(object) runs through the "tail end" of a Look-style room
2101 ! description for the contents of the object, printing up suitable
2102 ! descriptions as it goes.
2103 ! ----------------------------------------------------------------------------
2105 [ SayWhatsOn descon j f;
2106 if (descon == parent(player)) rfalse;
2107 objectloop (j in descon)
2108 if (j hasnt concealed && j hasnt scenery) f = 1;
2110 L__M(##Look, 4, descon);
2113 [ NotSupportingThePlayer o i;
2115 while (i && i ~= visibility_ceiling) {
2118 if (i && i hasnt supporter) rtrue;
2122 ! modified with the fix for L61122
2123 [ Locale descin text_without_ALSO text_with_ALSO
2124 o p num_objs must_print_ALSO;
2125 objectloop (o in descin) give o ~workflag;
2127 objectloop (o in descin)
2128 if (o hasnt concealed && NotSupportingThePlayer(o)) {
2129 #Ifndef MANUAL_PRONOUNS;
2132 if (o has scenery) {
2133 if (o has supporter && child(o)) SayWhatsOn(o);
2136 give o workflag; num_objs++;
2138 if ((o has door or container) && o has open && o provides when_open) {
2139 p = when_open; jump Prop_Chosen;
2141 if ((o has door or container) && o hasnt open && o provides when_closed) {
2142 p = when_closed; jump Prop_Chosen;
2144 if (o has switchable && o has on && o provides when_on) {
2145 p = when_on; jump Prop_Chosen;
2147 if (o has switchable && o hasnt on && o provides when_off) {
2153 if (o.&describe && RunRoutines(o, describe)) {
2154 must_print_ALSO = true;
2155 give o ~workflag; num_objs--;
2158 if (o.p && (o hasnt moved || p ~= initial)) {
2161 must_print_ALSO = true;
2162 give o ~workflag; num_objs--;
2163 if (o has supporter && child(o)) SayWhatsOn(o);
2168 if (num_objs == 0) return 0;
2170 if (actor ~= player) give actor concealed;
2171 if (text_without_ALSO) {
2173 if (must_print_ALSO) print (string) text_with_ALSO, " ";
2174 else print (string) text_without_ALSO, " ";
2175 WriteListFrom(child(descin),
2176 ENGLISH_BIT+RECURSE_BIT+PARTINV_BIT+TERSE_BIT+CONCEAL_BIT+WORKFLAG_BIT);
2179 if (must_print_ALSO) L__M(##Look, 5, descin);
2180 else L__M(##Look, 6, descin);
2182 if (actor ~= player) give actor ~concealed;
2186 ! ----------------------------------------------------------------------------
2187 ! Looking. LookSub(1) is allowed to abbreviate long descriptions, but
2188 ! LookSub(0) (which is what happens when the Look action is generated)
2189 ! isn't. (Except that these are over-ridden by the player-set lookmode.)
2190 ! ----------------------------------------------------------------------------
2192 [ LMode1Sub; lookmode=1; print (string) Story; L__M(##LMode1); ]; ! Brief
2194 [ LMode2Sub; lookmode=2; print (string) Story; L__M(##LMode2); ]; ! Verbose
2196 [ LMode3Sub; lookmode=3; print (string) Story; L__M(##LMode3); ]; ! Superbrief
2198 [ LModeNormalSub; ! 'normal' value: the default, or as set in Initialise()
2199 switch (initial_lookmode) {
2202 default: <<LMode2>>;
2206 [ NoteArrival descin;
2207 if (location ~= lastdesc) {
2208 if (location.initial) PrintOrRun(location, initial);
2209 if (location == thedark) { lastdesc = thedark; return; }
2211 if(NewRoom() == false) LibraryExtensions.RunAll(ext_newroom);
2217 prev_location = real_location;
2221 if (location hasnt visited) {
2222 give location visited;
2223 if (location has scored) {
2224 score = score + ROOM_SCORE;
2225 places_score = places_score + ROOM_SCORE;
2230 [ FindVisibilityLevels visibility_levels;
2231 visibility_levels = 1;
2232 visibility_ceiling = parent(player);
2233 while ((parent(visibility_ceiling)) &&
2234 (visibility_ceiling hasnt container || visibility_ceiling has open or transparent)) {
2235 visibility_ceiling = parent(visibility_ceiling);
2236 visibility_levels++;
2238 return visibility_levels;
2241 [ LookSub allow_abbrev visibility_levels i j k nl_flag;
2242 if (parent(player) == 0) return RunTimeError(10);
2246 if (location == thedark) { visibility_ceiling = thedark; NoteArrival(); }
2248 visibility_levels = FindVisibilityLevels();
2249 if (visibility_ceiling == location) {
2251 if (visibility_ceiling ~= location) jump MovedByInitial;
2254 ! Printing the top line: e.g.
2255 ! Octagonal Room (on the table) (as Frodo)
2257 #Ifdef TARGET_ZCODE;
2259 #Ifnot; ! TARGET_GLULX;
2260 glk_set_style(style_Subheader);
2262 if (visibility_levels == 0) print (name) thedark;
2264 if (visibility_ceiling ~= location) print (The) visibility_ceiling;
2265 else print (name) visibility_ceiling;
2267 #Ifdef TARGET_ZCODE;
2269 #Ifnot; ! TARGET_GLULX;
2270 glk_set_style(style_Normal);
2273 for (j=1,i=parent(player) : j<visibility_levels : j++,i=parent(i))
2274 if (i has supporter) L__M(##Look, 1, i);
2275 else L__M(##Look, 2, i);
2277 if (print_player_flag == 1) L__M(##Look, 3, player);
2280 ! The room description (if visible)
2282 if (lookmode < 3 && visibility_ceiling == location) {
2283 if ((allow_abbrev ~= 1) || (lookmode == 2) || (location hasnt visited)) {
2284 if (location.&describe) RunRoutines(location, describe);
2286 if (location.description == 0) RunTimeError(11, location, description);
2287 else PrintOrRun(location, description);
2292 if (visibility_ceiling == location) nl_flag = 1;
2294 if (visibility_levels == 0) Locale(thedark);
2296 for (i=player,j=visibility_levels : j>0 : j--,i=parent(i)) give i workflag;
2298 for (j=visibility_levels : j>0 : j--) {
2299 for (i=player,k=0 : k<j : k++) i=parent(i);
2300 if (i.inside_description) {
2301 if (nl_flag) new_line; else nl_flag = 1;
2302 PrintOrRun(i,inside_description);
2304 if (Locale(i)) nl_flag=1;
2308 if(LookRoutine() == false) LibraryExtensions.RunAll(ext_lookroutine);
2315 if (location == thedark) return L__M(##Examine, 1, noun);
2316 i = noun.description;
2318 if (noun has container)
2319 if (noun has open or transparent) <<Search noun, actor>>;
2320 else return L__M(##Search, 5, noun);
2321 if (noun has switchable) { L__M(##Examine, 3, noun); rfalse; }
2322 return L__M(##Examine, 2, noun);
2324 i = PrintOrRun(noun, description);
2325 if (i < 2 && noun has switchable) L__M(##Examine, 3, noun);
2330 if (location == thedark) return L__M(##LookUnder, 1, noun);
2331 L__M(##LookUnder, 2);
2334 [ VisibleContents o i f;
2335 objectloop (i in o) if (i hasnt concealed or scenery) f++;
2340 if (location == thedark) return L__M(##Search, 1, noun);
2341 if (ObjectIsUntouchable(noun)) return;
2342 f = VisibleContents(noun);
2343 if (noun has supporter) {
2344 if (f == 0) return L__M(##Search, 2, noun);
2345 return L__M(##Search, 3, noun);
2347 if (noun hasnt container) return L__M(##Search, 4, noun);
2348 if (noun hasnt transparent or open && ImplicitOpen(noun)) return L__M(##Search, 5, noun);
2349 if (AfterRoutines()) return;
2351 if (f == 0) return L__M(##Search, 6, noun);
2352 L__M(##Search, 7, noun);
2355 ! ----------------------------------------------------------------------------
2356 ! Verbs which change the state of objects without moving them
2357 ! ----------------------------------------------------------------------------
2360 if (ObjectIsUntouchable(noun)) return;
2361 if (noun hasnt lockable) return L__M(##Unlock, 1, noun);
2362 if (noun hasnt locked) return L__M(##Unlock, 2, noun);
2363 if (noun.with_key ~= second) return L__M(##Unlock, 3, second);
2367 if (AfterRoutines() || keep_silent) return;
2368 L__M(##Unlock, 4, noun);
2372 if (ObjectIsUntouchable(noun)) return;
2373 if (noun hasnt lockable) return L__M(##Lock, 1, noun);
2374 if (noun has locked) return L__M(##Lock, 2 ,noun);
2375 if (noun has open && ImplicitClose(noun)) return L__M(##Lock, 3, noun);
2376 if (noun.with_key ~= second) return L__M(##Lock, 4, second);
2379 if (AfterRoutines() || keep_silent) return;
2380 L__M(##Lock, 5, noun);
2384 if (ObjectIsUntouchable(noun)) return;
2385 if (noun hasnt switchable) return L__M(##SwitchOn, 1, noun);
2386 if (noun has on) return L__M(##SwitchOn, 2, noun);
2389 if (AfterRoutines() || keep_silent) return;
2390 L__M(##SwitchOn, 3, noun);
2394 if (ObjectIsUntouchable(noun)) return;
2395 if (noun hasnt switchable) return L__M(##SwitchOff, 1, noun);
2396 if (noun hasnt on) return L__M(##SwitchOff, 2, noun);
2399 if (AfterRoutines() || keep_silent) return;
2400 L__M(##SwitchOff, 3, noun);
2404 if (ObjectIsUntouchable(noun)) return;
2405 if (noun hasnt openable) return L__M(##Open, 1, noun);
2406 if (noun has locked && ImplicitUnlock(noun)) return L__M(##Open, 2, noun);
2407 if (noun has open) return L__M(##Open, 3, noun);
2410 if (keep_silent || AfterRoutines()) return;
2412 if (noun hasnt container)
2413 return L__M(##Open, 5, noun);
2415 if ((noun has container && location ~= thedark && VisibleContents(noun)
2416 && IndirectlyContains(noun, player)) == 0) {
2417 if (noun hasnt transparent && noun hasnt door) return L__M(##Open, 4, noun);
2419 L__M(##Open, 5, noun);
2423 if (ObjectIsUntouchable(noun)) return;
2424 if (noun hasnt openable) return L__M(##Close, 1, noun);
2425 if (noun hasnt open) return L__M(##Close, 2, noun);
2428 if (AfterRoutines() || keep_silent) return;
2429 L__M(##Close, 3, noun);
2433 if (ObjectIsUntouchable(noun)) return;
2434 if (noun hasnt worn) return L__M(##Disrobe, 1, noun);
2437 if (AfterRoutines() || keep_silent) return;
2438 L__M(##Disrobe, 2, noun);
2442 if (ObjectIsUntouchable(noun)) return;
2443 if (noun hasnt clothing) return L__M(##Wear, 1, noun);
2444 if (noun notin actor && ImplicitTake(noun)) return L__M(##Wear, 2, noun);
2445 if (noun has worn) return L__M(##Wear, 3, noun);
2448 if (AfterRoutines() || keep_silent) return;
2449 L__M(##Wear, 4, noun);
2453 if (ObjectIsUntouchable(noun)) return;
2454 if (noun hasnt edible) return L__M(##Eat, 1, noun);
2455 if (noun has worn && ImplicitDisrobe(noun)) return;
2458 if (AfterRoutines() || keep_silent) return;
2459 L__M(##Eat, 2, noun);
2462 ! ----------------------------------------------------------------------------
2463 ! Verbs which are really just stubs (anything which happens for these
2464 ! actions must happen in before rules)
2465 ! ----------------------------------------------------------------------------
2468 if (parent(second) ~= compass) return L__M(##PushDir, 2, noun);
2469 if (second == u_obj or d_obj) return L__M(##PushDir, 3, noun);
2470 AfterRoutines(); i = noun; move i to actor;
2472 if (location == thedark) move i to real_location;
2473 else move i to location;
2477 if (second && RunLife(second,##Answer)) rfalse;
2478 L__M(##Answer, 1, noun);
2482 if (RunLife(noun,##Ask)) rfalse;
2483 L__M(##Ask, 1, noun);
2487 if (noun == player) <<Inv, actor>>;
2488 L__M(##Order, 1, noun);
2491 [ AskToSub; L__M(##Order, 1, noun); ];
2494 if (ObjectIsUntouchable(noun)) return;
2495 if (noun has animate && RunLife(noun, ##Attack)) rfalse;
2496 L__M(##Attack, 1, noun);
2499 [ BlowSub; L__M(##Blow, 1, noun); ];
2502 if (noun has animate) return L__M(##Burn, 2, noun);
2503 L__M(##Burn, 1, noun);
2506 [ BuySub; L__M(##Buy, 1, noun); ];
2509 if (noun has animate) return L__M(##Climb, 2, noun);
2510 L__M(##Climb, 1, noun);
2513 [ ConsultSub; L__M(##Consult, 1, noun); ];
2516 if (noun has animate) return L__M(##Cut, 2, noun);
2517 L__M(##Cut, 1, noun);
2520 [ DigSub; L__M(##Dig, 1, noun); ];
2522 [ DrinkSub; L__M(##Drink, 1, noun); ];
2525 if (second == nothing) return L__M(##Fill, 1, noun);
2526 L__M(##Fill, 2, noun, second);
2529 [ JumpSub; L__M(##Jump, 1, noun); ];
2532 if (noun has animate) return L__M(##JumpIn, 2, noun);
2533 if (noun has enterable) <<Enter noun>>;
2534 L__M(##JumpOn, 1, noun);
2538 if (noun has animate) return L__M(##JumpOn, 2, noun);
2539 if (noun has enterable && noun has supporter) <<Enter noun>>;
2540 L__M(##JumpOn, 1, noun);
2544 if (noun has animate) return L__M(##JumpOver, 2, noun);
2545 L__M(##JumpOver, 1, noun);
2549 if (ObjectIsUntouchable(noun)) return;
2550 if (RunLife(noun, ##Kiss)) return;
2551 if (noun == actor) return L__M(##Touch, 3, noun);
2552 L__M(##Kiss, 1, noun);
2555 [ ListenSub; L__M(##Listen, 1, noun); ];
2557 [ MildSub; L__M(##Mild, 1, noun); ];
2559 [ NoSub; L__M(##No); ];
2561 [ PraySub; L__M(##Pray, 1, noun); ];
2564 if (ObjectIsUntouchable(noun)) return;
2565 if (noun == player) return L__M(##Pull, 1, noun);
2566 if (noun == actor) return L__M(##Pull, 6, noun);
2567 if (noun has static) return L__M(##Pull, 2, noun);
2568 if (noun has scenery) return L__M(##Pull, 3, noun);
2569 if (noun has animate) return L__M(##Pull, 5, noun);
2570 L__M(##Pull, 4, noun);
2574 if (ObjectIsUntouchable(noun)) return;
2575 if (noun == player) return L__M(##Push, 1, noun);
2576 if (noun == actor) return L__M(##Push, 5, noun);
2577 if (noun has static) return L__M(##Push, 2, noun);
2578 if (noun has scenery) return L__M(##Push, 3, noun);
2579 if (noun has animate) return L__M(##Push, 5, noun);
2580 L__M(##Push, 4, noun);
2583 [ PushDirSub; L__M(##PushDir, 1, noun); ];
2586 if (ObjectIsUntouchable(noun)) return;
2587 if (noun has animate) return L__M(##Rub, 2, noun);
2588 L__M(##Rub, 1, noun);
2591 [ SetSub; L__M(##Set, 1, noun); ];
2593 [ SetToSub; L__M(##SetTo, 1, noun); ];
2595 [ SingSub; L__M(##Sing, 1, noun); ];
2597 [ SleepSub; L__M(##Sleep, 1, noun); ];
2600 if (noun ~= nothing && noun has animate) return L__M(##Smell, 2, noun);
2601 L__M(##Smell, 1, noun);
2604 [ SorrySub; L__M(##Sorry, 1, noun); ];
2607 if (ObjectIsUntouchable(noun)) return;
2608 if (noun has animate && noun ~= player) return L__M(##Squeeze, 1, noun);
2609 L__M(##Squeeze, 2, noun);
2612 [ StrongSub; L__M(##Strong, 1, noun); ];
2614 [ SwimSub; L__M(##Swim, 1, noun); ];
2616 [ SwingSub; L__M(##Swing, 1, noun); ];
2619 if (ObjectIsUntouchable(noun)) return;
2620 if (noun has animate) return L__M(##Taste, 2, noun);
2621 L__M(##Taste, 1, noun);
2625 if (noun == actor) return L__M(##Tell, 1, noun);
2626 if (RunLife(noun, ##Tell)) return;
2627 L__M(##Tell, 2, noun);
2630 [ ThinkSub; L__M(##Think, 1, noun); ];
2633 if (ObjectIsUntouchable(noun)) return;
2635 action = ##ThrownAt;
2636 if (RunRoutines(second, before)) { action = ##ThrowAt; rtrue; }
2639 if (noun has worn && ImplicitDisrobe(noun)) return;
2640 if (second hasnt animate) return L__M(##ThrowAt, 1, noun);
2641 if (RunLife(second, ##ThrowAt)) return;
2642 L__M(##ThrowAt, 2, noun);
2646 if (noun has animate) return L__M(##Tie, 2, noun);
2647 L__M(##Tie, 1, noun);
2651 if (noun == actor) return L__M(##Touch, 3, noun);
2652 if (ObjectIsUntouchable(noun)) return;
2653 if (noun has animate) return L__M(##Touch, 1, noun);
2654 L__M(##Touch, 2,noun);
2658 if (ObjectIsUntouchable(noun)) return;
2659 if (noun == player) return L__M(##Turn, 1, noun);
2660 if (noun == actor) return L__M(##Turn, 5, noun);
2661 if (noun has static) return L__M(##Turn, 2, noun);
2662 if (noun has scenery) return L__M(##Turn, 3, noun);
2663 if (noun has animate) return L__M(##Turn, 5, noun);
2664 L__M(##Turn, 4, noun);
2668 if (AfterRoutines()) rtrue;
2669 L__M(##Wait, 1, noun);
2672 [ WakeSub; L__M(##Wake, 1, noun); ];
2675 if (ObjectIsUntouchable(noun)) return;
2676 if (RunLife(noun, ##WakeOther)) return;
2677 L__M(##WakeOther, 1, noun);
2681 if (noun == player) return L__M(##Wave, 2 ,noun, second);
2682 if (noun == actor) return L__M(##Wave, 3, noun, second);
2683 if (noun notin actor && ImplicitTake(noun)) return L__M(##Wave, 1, noun);
2684 L__M(##Wave, 2, noun, second);
2688 if (noun) return L__M(##WaveHands, 2, noun);
2689 L__M(##WaveHands, 1, noun); ];
2691 [ YesSub; L__M(##Yes); ];
2693 ! ----------------------------------------------------------------------------
2695 ! ----------------------------------------------------------------------------
2699 [ TraceOnSub; parser_trace = 1; "[Trace on.]"; ];
2702 parser_trace = noun;
2703 print "[Parser tracing set to level ", parser_trace, ".]^";
2706 [ TraceOffSub; parser_trace = 0; "Trace off."; ];
2709 debug_flag = debug_flag | DEBUG_MESSAGES;
2710 "[Message listing on.]";
2714 debug_flag = debug_flag & ~DEBUG_MESSAGES;
2715 "[Message listing off.]";
2718 [ RoutinesVerboseSub;
2719 debug_flag = debug_flag | (DEBUG_VERBOSE|DEBUG_MESSAGES);
2720 "[Verbose message listing on.]";
2724 debug_flag = debug_flag | DEBUG_ACTIONS;
2725 "[Action listing on.]";
2729 debug_flag = debug_flag & ~DEBUG_ACTIONS;
2730 "[Action listing off.]";
2734 debug_flag = debug_flag | DEBUG_TIMERS;
2735 "[Timers listing on.]";
2739 debug_flag = debug_flag & ~DEBUG_TIMERS;
2740 "[Timers listing off.]";
2745 [ ChangesOnSub; debug_flag = debug_flag | DEBUG_CHANGES; "[Changes listing on.]"; ];
2746 [ ChangesOffSub; debug_flag = debug_flag & ~DEBUG_CHANGES; "[Changes listing off.]"; ];
2750 [ ChangesOnSub; "[Changes listing available only from Inform 6.2 onwards.]"; ];
2752 [ ChangesOffSub; "[Changes listing available only from Inform 6.2 onwards.]"; ];
2756 #Ifdef TARGET_ZCODE;
2760 "[Random number generator now predictable.]";
2763 #Ifnot; ! TARGET_GLULX;
2767 "[Random number generator now predictable.]";
2772 [ XTestMove obj dest;
2773 if (~~obj ofclass Object) "[Not an object.]";
2774 if (~~dest ofclass Object) "[Destination not an object.]";
2775 if ((obj <= InformLibrary) || (obj == LibraryMessages) || (obj in 1))
2776 "[Can't move ", (name) obj, ": it's a system object.]";
2778 if (dest == obj) "[Can't move ", (name) obj, ": it would contain itself.]";
2779 dest = parent(dest);
2785 if (XTestMove(noun, player)) return;
2786 move noun to player; give noun moved ~concealed;
2791 if (XTestMove(noun, second)) return;
2792 move noun to second;
2797 if (parent(obj) == 0) print (name) obj; else print (a) obj;
2798 print " (", obj, ") ";
2799 if (f && parent(obj))
2800 print "in ~", (name) parent(obj), "~ (", parent(obj), ")";
2802 if (child(obj) == 0) rtrue;
2803 if (obj == Class) ! ???
2804 WriteListFrom(child(obj), NEWLINE_BIT+INDENT_BIT+ALWAYS_BIT+ID_BIT+NOARTICLE_BIT, 1);
2806 WriteListFrom(child(obj), NEWLINE_BIT+INDENT_BIT+ALWAYS_BIT+ID_BIT+FULLINV_BIT, 1);
2810 if (noun && ~~noun ofclass Object) "[Not an object.]";
2813 if (i ofclass Object && parent(i) == 0) XObj(i);
2815 else XObj(noun, true);
2819 if ((~~noun ofclass Object) || parent(noun)) "[Not a safe place.]";
2824 if (~~noun ofclass Object) "[Not a safe place.]";
2826 while (parent(x)) x = parent(x);
2830 [ Print_ScL obj; print_ret ++x_scope_count, ": ", (a) obj, " (", obj, ")"; ];
2833 if (noun && ~~noun ofclass Object) "[Not an object.]";
2835 LoopOverScope(Print_ScL, noun);
2836 if (x_scope_count == 0) "Nothing is in scope.";
2839 #Ifdef TARGET_GLULX;
2841 [ GlkListSub id val;
2842 id = glk_window_iterate(0, gg_arguments);
2844 print "Window ", id, " (", gg_arguments-->0, "): ";
2845 val = glk_window_get_type(id);
2849 3: print "textbuffer";
2850 4: print "textgrid";
2851 5: print "graphics";
2852 default: print "unknown";
2854 val = glk_window_get_parent(id);
2855 if (val) print ", parent is window ", val;
2856 else print ", no parent (root)";
2857 val = glk_window_get_stream(id);
2858 print ", stream ", val;
2859 val = glk_window_get_echo_stream(id);
2860 if (val) print ", echo stream ", val;
2862 id = glk_window_iterate(id, gg_arguments);
2864 id = glk_stream_iterate(0, gg_arguments);
2866 print "Stream ", id, " (", gg_arguments-->0, ")^";
2867 id = glk_stream_iterate(id, gg_arguments);
2869 id = glk_fileref_iterate(0, gg_arguments);
2871 print "Fileref ", id, " (", gg_arguments-->0, ")^";
2872 id = glk_fileref_iterate(id, gg_arguments);
2874 val = glk_gestalt(gestalt_Sound, 0);
2876 id = glk_schannel_iterate(0, gg_arguments);
2878 print "Soundchannel ", id, " (", gg_arguments-->0, ")^";
2879 id = glk_schannel_iterate(id, gg_arguments);
2888 ! ----------------------------------------------------------------------------
2889 ! Finally: the mechanism for library text (the text is in the language defn)
2890 ! ----------------------------------------------------------------------------
2892 [ L__M act n x1 x2 s;
2893 if (keep_silent == 2) return;
2907 if (RunRoutines(LibraryMessages, before)) { action = s; rfalse; }
2908 if (LibraryExtensions.RunWhile(ext_messages, false )) { action = s; rfalse; }
2910 LanguageLM(n, x1, x2);
2913 ! ==============================================================================