1 ! ==============================================================================
2 ! VERBLIB: Front end to standard verbs library.
4 ! Supplied for use with Inform 6 -- Release 6.12.5 -- Serial number 210605
6 ! Copyright Graham Nelson 1993-2004 and David Griffith 2012-2021
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 ! In your game file, Include three library files in this order:
26 ! ==============================================================================
31 #Iffalse LIBRARY_STAGE >= AFTER_VERBLIB; ! if not already included
32 #Iftrue LIBRARY_STAGE == AFTER_PARSER; ! if okay to include it
34 ! ------------------------------------------------------------------------------
36 Default AMUSING_PROVIDED 1;
37 Default MAX_CARRIED 100;
39 Default NUMBER_TASKS 1;
40 Default OBJECT_SCORE 4;
42 Default SACK_OBJECT 0;
43 Default TASKS_PROVIDED 1;
46 Array task_scores -> 0 0 0 0;
49 Array task_done -> NUMBER_TASKS;
51 #Ifndef LibraryMessages;
52 Object LibraryMessages;
56 [ ObjectsSub; Objects1Sub(); ];
57 [ ObjectsTallSub; Objects1TallSub(); ];
58 [ ObjectsWideSub; Objects1WideSub(); ];
59 [ PlacesSub; Places1Sub(); ];
60 [ PlacesTallSub; Places1TallSub(); ];
61 [ PlacesWideSub; Places1WideSub(); ];
64 ! ------------------------------------------------------------------------------
65 ! Banner(), VersionSub(), and RunTimeError() are preempted by LanguageBanner(),
66 ! LanguageVersionSub(), and LanguageError() respectfully. When converting
67 ! this library to support a different natural language, these three latter
68 ! functions should be created rather than editing this file.
69 ! ------------------------------------------------------------------------------
72 #Ifdef LanguageBanner;
74 i = 0; ! suppress warning
78 #IfV5; style bold; #Endif;
79 print "^", (string) Story;
80 #IfV5; style roman; #Endif;
81 #Ifnot; ! TARGET_GLULX;
82 glk_set_style(style_Header);
83 print "^", (string) Story;
84 glk_set_style(style_Normal);
89 if (Headline) print (string) Headline;
94 print (string) RELEASE__TX, (HDR_GAMERELEASE-->0) & $03ff, " / ", (string) SERNUM__TX;
95 for (i=0 : i<6 : i++) print (char) HDR_GAMESERIAL->i;
96 #Ifnot; ! TARGET_GLULX;
97 print (string) RELEASE__TX;
98 @aloads ROM_GAMERELEASE 0 i;
100 print " / ", (string) SERNUM__TX;
101 for (i=0 : i<6 : i++) print (char) ROM_GAMESERIAL->i;
104 #Endif; ! LanguageBanner
108 #Ifdef LanguageVersionSub;
109 LanguageVersionSub();
110 ix = 0; ! suppress warning
114 ix = 0; ! shut up compiler warning
115 if (standard_interpreter > 0) {
116 print (string) STDTERP__TX, standard_interpreter/256, ".", standard_interpreter%256,
117 " (", HDR_TERPNUMBER->0;
118 #Iftrue (#version_number == 6);
119 print (char) '.', HDR_TERPVERSION->0;
121 print (char) HDR_TERPVERSION->0;
126 print (string) TERP__TX, HDR_TERPNUMBER->0, (string) VER__TX;
127 #Iftrue (#version_number == 6);
128 print HDR_TERPVERSION->0;
130 print (char) HDR_TERPVERSION->0;
135 #Ifnot; ! TARGET_GLULX;
137 print (string) TERPVER__TX, ix / $10000, ".", (ix & $FF00) / $100,
138 ".", ix & $FF, " / ";
140 print (string) VM__TX, ix / $10000, ".", (ix & $FF00) / $100, ".", ix & $FF, " / ";
142 print (string) LIBSER__TX, (string) LibSerial, "^";
143 #Ifdef LanguageVersion;
144 print (string) LanguageVersion, "^";
145 #Endif; ! LanguageVersion
146 #Endif; ! LanguageVersionSub
149 [ RunTimeError n p1 p2;
150 #Ifdef LanguageError;
151 LanguageError(n, p1, p2);
154 print "** ", (string) LIBERROR__TX, n, " (", p1, ", ", p2, ") **";
156 L__M(##RunTimeError, n, p1, p2);
160 #Endif; ! LanguageError
163 ! ----------------------------------------------------------------------------
164 ! The WriteListFrom routine, a flexible object-lister taking care of
165 ! plurals, inventory information, various formats and so on. This is used
166 ! by everything in the library which ever wants to list anything.
168 ! If there were no objects to list, it prints nothing and returns false;
169 ! otherwise it returns true.
171 ! o is the object, and style is a bitmap, whose bits are given by:
172 ! ----------------------------------------------------------------------------
175 Constant NEWLINE_BIT $0001; ! New-line after each entry
176 Constant INDENT_BIT $0002; ! Indent each entry by depth
177 Constant FULLINV_BIT $0004; ! Full inventory information after entry
178 Constant ENGLISH_BIT $0008; ! English sentence style, with commas and and
179 Constant RECURSE_BIT $0010; ! Recurse downwards with usual rules
180 Constant ALWAYS_BIT $0020; ! Always recurse downwards
181 Constant TERSE_BIT $0040; ! More terse English style
182 Constant PARTINV_BIT $0080; ! Only brief inventory information after entry
183 Constant DEFART_BIT $0100; ! Use the definite article in list
184 Constant WORKFLAG_BIT $0200; ! At top level (only), only list objects
185 ! which have the "workflag" attribute
186 Constant ISARE_BIT $0400; ! Print " is" or " are" before list
187 Constant CONCEAL_BIT $0800; ! Omit objects with "concealed" or "scenery":
188 ! if WORKFLAG_BIT also set, then does _not_
189 ! apply at top level, but does lower down
190 Constant NOARTICLE_BIT $1000; ! Print no articles, definite or not
191 Constant ID_BIT $2000; ! Print object id after each entry
193 [ NextEntry o odepth;
196 if (o == 0) return 0;
197 if (lt_value && o.list_together ~= lt_value) continue;
198 if (c_style & WORKFLAG_BIT && odepth==0 && o hasnt workflag) continue;
199 if (c_style & CONCEAL_BIT && (o has concealed || o has scenery)) continue;
205 if (c_style & ALWAYS_BIT) rtrue;
206 if (c_style & RECURSE_BIT == 0) rfalse;
207 if ((o has transparent or supporter) || (o has container && o has open)) rtrue;
212 if (child(o1) && WillRecurs(o1)) rfalse;
213 if (child(o2) && WillRecurs(o2)) rfalse;
214 if (c_style & (FULLINV_BIT + PARTINV_BIT)) {
215 if ((o1 hasnt worn && o2 has worn) || (o2 hasnt worn && o1 has worn)) rfalse;
216 if ((o1 hasnt light && o2 has light) || (o2 hasnt light && o1 has light)) rfalse;
217 if (o1 has container) {
218 if (o2 hasnt container) rfalse;
219 if ((o1 has open && o2 hasnt open) || (o2 has open && o1 hasnt open))
222 else if (o2 has container)
225 return Identical(o1, o2);
228 [ SortTogether obj value;
229 ! print "Sorting together possessions of ", (object) obj, " by value ", value, "^";
230 ! for (x=child(obj) : x : x=sibling(x))
231 ! print (the) x, " no: ", x, " lt: ", x.list_together, "^";
233 if (child(obj).list_together ~= value) move child(obj) to out_obj;
234 else move child(obj) to in_obj;
236 while (child(in_obj)) move child(in_obj) to obj;
237 while (child(out_obj)) move child(out_obj) to obj;
240 [ SortOutList obj i k l;
241 ! print "^^Sorting out list from ", (name) obj, "^ ";
242 ! for (i=child(location) : i : i=sibling(i))
243 ! print (name) i, " --> ";
248 for (i=obj : i : i=sibling(i)) {
251 ! print "Scanning ", (name) i, " with lt=", k, "^";
252 for (i=sibling(i) : i && i.list_together == k :) i = sibling(i);
254 ! print "First not in block is ", (name) i, " with lt=", i.list_together, "^";
255 for (l=sibling(i) : l : l=sibling(l))
256 if (l.list_together == k) {
257 SortTogether(parent(obj), k);
258 ! print "^^After ST:^ ";
259 ! for (i=child(location) : i : i=sibling(i))
260 ! print (name) i, " --> ";
262 obj = child(parent(obj));
271 [ Print__Spaces n; ! To avoid a bug occurring in Inform 6.01 to 6.10
276 #Ifnot; ! TARGET_GLULX;
287 [ WriteListFrom o style depth
290 if (o == nothing) return 0;
292 s1 = c_style; s2 = lt_value; s3 = listing_together;
293 s4 = listing_size; s5 = wlf_indent; s6 = inventory_stage;
295 if (o == child(parent(o))) {
297 o = child(parent(o));
301 if (WriteListR(o, depth) == 0) return 0;
303 c_style = s1; lt_value = s2; listing_together = s3;
304 listing_size = s4; wlf_indent = s5; inventory_stage = s6;
308 [ WriteListR o depth stack_pointer classes_p sizes_p i j k k2 l m n q senc mr;
309 if (depth > 0 && o == child(parent(o))) {
311 o = child(parent(o));
315 if (c_style & WORKFLAG_BIT && depth==0 && o hasnt workflag) {
319 if (c_style & CONCEAL_BIT && (o has concealed || o has scenery)) {
325 classes_p = match_classes + stack_pointer;
326 sizes_p = match_list + stack_pointer;
328 for (i=o,j=0 : i && (j+stack_pointer)<128 : i=NextEntry(i,depth),j++) {
333 if (c_style & ISARE_BIT) {
334 if (j == 1 && o hasnt pluralname) Tense(IS__TX, WAS__TX);
335 else Tense(ARE__TX, WERE__TX);
336 if (c_style & NEWLINE_BIT) print (string) COLON__TX, "^";
337 else print (char) ' ';
338 c_style = c_style - ISARE_BIT;
341 stack_pointer = stack_pointer+j+1;
343 if (k < 2) jump EconomyVersion; ! It takes two to plural
345 for (i=o,k=0 : k<j : i=NextEntry(i,depth),k++)
346 if (classes_p->k == 0) {
347 classes_p->k = n; sizes_p->n = 1;
348 for (l=NextEntry(i,depth),m=k+1 : l && m<j : l=NextEntry(l,depth),m++)
349 if (classes_p->m == 0 && i.plural && l.plural ~= 0) {
350 if (ListEqual(i, l) == 1) {
351 sizes_p->n = sizes_p->n + 1;
359 for (i=1,j=o,k=0 : i<=n : i++,senc++) {
360 while (((classes_p->k) ~= i) && ((classes_p->k) ~= -i)) {
361 k++; j=NextEntry(j, depth);
366 if (j.list_together ~= 0 or lt_value && metaclass(j.list_together) == Routine or String &&
367 j.list_together == mr) senc--;
368 mr = j.list_together;
373 for (i=1,j=o,k=0,mr=0 : senc>=0 : i++,senc--) {
374 while (((classes_p->k) ~= i) && ((classes_p->k) ~= -i)) {
375 k++; j=NextEntry(j, depth);
377 if (j.list_together ~= 0 or lt_value) {
378 if (j.list_together == mr) {
382 k2 = NextEntry(j, depth);
383 if (k2 == 0 || k2.list_together ~= j.list_together) jump Omit_WL2;
384 k2 = metaclass(j.list_together);
385 if (k2 == Routine or String) {
386 q = j; listing_size = 1; l = k; m = i;
387 while (m < n && q.list_together == j.list_together) {
389 while (((classes_p->l) ~= m) && ((classes_p->l) ~= -m)) {
390 l++; q = NextEntry(q, depth);
392 if (q.list_together == j.list_together) listing_size++;
394 ! print " [", listing_size, "] ";
395 if (listing_size == 1) jump Omit_WL2;
396 if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
399 for (l=0 : l<listing_size : l++) q = q+sizes_p->(l+i);
400 EnglishNumber(q); print " ";
401 print (string) j.list_together;
402 if (c_style & ENGLISH_BIT) print " (";
403 if (c_style & INDENT_BIT) print (string) COLON__TX, "^";
408 parser_one = j; parser_two = depth+wlf_indent;
409 if (RunRoutines(j, list_together) == 1) jump Omit__Sublist2;
413 @push lt_value; @push listing_together; @push listing_size;
414 #Ifnot; ! TARGET_GLULX;
415 @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
418 lt_value = j.list_together; listing_together = j; wlf_indent++;
419 WriteListR(j, depth, stack_pointer); wlf_indent--;
422 @pull listing_size; @pull listing_together; @pull lt_value;
423 #Ifnot; ! TARGET_GLULX;
424 @copy sp listing_size;
425 @copy sp listing_together;
430 if (q & ENGLISH_BIT) print ")";
434 parser_one = j; parser_two = depth+wlf_indent;
435 RunRoutines(j, list_together);
440 if (q & NEWLINE_BIT && c_style & NEWLINE_BIT == 0) new_line;
442 mr = j.list_together;
449 if (WriteBeforeEntry(j, depth, 0, senc) == 1) jump Omit_FL2;
450 if (sizes_p->i == 1) {
451 if (c_style & NOARTICLE_BIT) print (name) j;
453 if (c_style & DEFART_BIT) print (the) j;
456 if (c_style & ID_BIT) print " (", j, ")";
459 if (c_style & DEFART_BIT) PrefaceByArticle(j, 1, sizes_p->i);
460 print (number) sizes_p->i, " ";
461 PrintOrRun(j, plural, 1);
463 if (sizes_p->i > 1 && j hasnt pluralname) {
465 WriteAfterEntry(j, depth, stack_pointer);
469 WriteAfterEntry(j,depth,stack_pointer);
473 if (c_style & ENGLISH_BIT) {
474 if (senc == 1) print (SerialComma) i+senc, (string) AND__TX;
475 if (senc > 1) print (string) COMMA__TX;
484 for (i=1,j=o : i<=n : j=NextEntry(j,depth),i++,senc++) {
485 if (j.list_together ~= 0 or lt_value && metaclass(j.list_together) == Routine or String &&
486 j.list_together==mr) senc--;
487 mr = j.list_together;
490 for (i=1,j=o,mr=0 : i<=senc : j=NextEntry(j,depth),i++) {
491 if (j.list_together ~= 0 or lt_value) {
492 if (j.list_together == mr) {
496 k = NextEntry(j, depth);
497 if (k == 0 || k.list_together ~= j.list_together) jump Omit_WL;
498 k = metaclass(j.list_together);
499 if (k == Routine or String) {
500 if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
504 q = NextEntry(q, depth); l++;
505 } until (q == 0 || q.list_together ~= j.list_together);
506 EnglishNumber(l); print " ";
507 print (string) j.list_together;
508 if (c_style & ENGLISH_BIT) print " (";
509 if (c_style & INDENT_BIT) print (string) COLON__TX, "^";
514 parser_one = j; parser_two = depth+wlf_indent;
515 if (RunRoutines(j, list_together) == 1) jump Omit__Sublist;
519 @push lt_value; @push listing_together; @push listing_size;
520 #Ifnot; ! TARGET_GLULX;
521 @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
524 lt_value = j.list_together; listing_together = j; wlf_indent++;
525 WriteListR(j, depth, stack_pointer); wlf_indent--;
528 @pull listing_size; @pull listing_together; @pull lt_value;
529 #Ifnot; ! TARGET_GLULX;
530 @copy sp listing_size; @copy sp listing_together; @copy sp lt_value;
534 if (q & ENGLISH_BIT) print ")";
538 parser_one = j; parser_two = depth+wlf_indent;
539 RunRoutines(j, list_together);
544 if (q & NEWLINE_BIT && c_style & NEWLINE_BIT == 0) new_line;
546 mr = j.list_together;
553 if (WriteBeforeEntry(j, depth, i, senc) == 1) jump Omit_FL;
554 if (c_style & NOARTICLE_BIT) print (name) j;
556 if (c_style & DEFART_BIT) print (the) j;
559 if (c_style & ID_BIT) print " (", j, ")";
560 WriteAfterEntry(j, depth, stack_pointer);
564 if (c_style & ENGLISH_BIT) {
565 if (i == senc-1) print (SerialComma) senc, (string) AND__TX;
566 if (i < senc-1) print (string) COMMA__TX;
572 ]; ! end of WriteListR
574 [ WriteBeforeEntry o depth ipos sentencepos
578 if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
579 if (o.invent && (c_style & (PARTINV_BIT|FULLINV_BIT))) {
580 flag = PrintOrRun(o, invent, 1);
582 if (c_style & ENGLISH_BIT) {
583 if (ipos == sentencepos-1)
584 print (SerialComma) sentencepos, (string) AND__TX;
585 if (ipos < sentencepos-1)
586 print (string) COMMA__TX;
588 if (c_style & NEWLINE_BIT) new_line;
594 [ WriteAfterEntry o depth stack_p
595 p recurse_flag parenth_flag eldest_child child_count combo i j;
598 if (c_style & PARTINV_BIT) {
599 if (o.invent && RunRoutines(o, invent))
600 if (c_style & NEWLINE_BIT) ""; else rtrue;
603 if (o has light && location hasnt light) combo=combo+1;
604 if (o has container && o hasnt open) combo=combo+2;
605 if ((o has container && (o has open || o has transparent))) {
607 if (i hasnt concealed && i hasnt scenery) {
611 if (~~j) combo=combo+4;
613 if (combo) L__M(##ListMiscellany, combo, o);
614 } ! end of PARTINV_BIT processing
616 if (c_style & FULLINV_BIT) {
617 if (o.invent && RunRoutines(o, invent))
618 if (c_style & NEWLINE_BIT) ""; else rtrue;
620 if (o has light && o has worn) { L__M(##ListMiscellany, 8, o); parenth_flag = true; }
622 if (o has light) { L__M(##ListMiscellany, 9, o); parenth_flag = true; }
623 if (o has worn) { L__M(##ListMiscellany, 10, o); parenth_flag = true; }
627 if (o has openable) {
628 if (parenth_flag) print (string) AND__TX;
629 else L__M(##ListMiscellany, 11, o);
631 if (child(o)) L__M(##ListMiscellany, 12, o);
632 else L__M(##ListMiscellany, 13, o);
634 if (o has lockable && o has locked) L__M(##ListMiscellany, 15, o);
635 else L__M(##ListMiscellany, 14, o);
639 if (child(o)==0 && o has transparent)
640 if (parenth_flag) L__M(##ListMiscellany, 16, o);
641 else L__M(##ListMiscellany, 17, o);
643 if (parenth_flag) print ")";
644 } ! end of FULLINV_BIT processing
646 if (c_style & CONCEAL_BIT) {
649 if (p hasnt concealed && p hasnt scenery) { child_count++; eldest_child = p; }
651 else { child_count = children(o); eldest_child = child(o); }
653 if (child_count && (c_style & ALWAYS_BIT)) {
654 if (c_style & ENGLISH_BIT) L__M(##ListMiscellany, 18, o);
658 if (child_count && (c_style & RECURSE_BIT)) {
659 if (o has supporter) {
660 if (c_style & ENGLISH_BIT) {
661 if (c_style & TERSE_BIT) L__M(##ListMiscellany, 19, o);
662 else L__M(##ListMiscellany, 20, o);
663 if (o has animate) print (string) WHOM__TX;
664 else print (string) WHICH__TX;
668 if (o has container && (o has open || o has transparent)) {
669 if (c_style & ENGLISH_BIT) {
670 if (c_style & TERSE_BIT) L__M(##ListMiscellany, 21, o);
671 else L__M(##ListMiscellany, 22, o);
672 if (o has animate) print (string) WHOM__TX;
673 else print (string) WHICH__TX;
679 if (recurse_flag && (c_style & ENGLISH_BIT))
680 if (child_count > 1 || eldest_child has pluralname) Tense(ARE2__TX, WERE2__TX);
681 else Tense(IS2__TX, WAS2__TX);
683 if (c_style & NEWLINE_BIT) new_line;
688 @push lt_value; @push listing_together; @push listing_size;
689 #Ifnot; ! TARGET_GLULX;
690 @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
692 lt_value = 0; listing_together = 0; listing_size = 0;
693 WriteListR(o, depth+1, stack_p);
695 @pull listing_size; @pull listing_together; @pull lt_value;
696 #Ifnot; ! TARGET_GLULX;
697 @copy sp listing_size; @copy sp listing_together; @copy sp lt_value;
699 if (c_style & TERSE_BIT) print ")";
703 ! ----------------------------------------------------------------------------
704 ! LoopWithinObject(rtn,obj,arg)
706 ! rtn is the address of a user-supplied routine.
707 ! obj is an optional parent object whose dependents are to be processed; the
708 ! default is the current actor (normally the player).
709 ! arg is an optional argument passed to the rtn; this can be a single variable
710 ! or constant, or the address of an array (which enables multiple values to be
711 ! passed and returned).
713 ! For each object o which is a child, grandchild, great-grandchild, etc, of the
714 ! original obj, LoopWithinObject() calls rtn(o,arg).
716 ! The rtn should perform any appropriate testing or processing on each object o,
717 ! using the optional arg value if necessary. If the rtn returns true (or any
718 ! positive value), the children of o, if any, are also tested; those children
719 ! are skipped if rtn returns false. To terminate the loop before all objects
720 ! have been processed, rtn should return a large negative number (eg -99).
722 ! To deal with supporters and open containers, so that objects are processed
723 ! only if they are accessible to the player, rtn might end with these
725 ! if ((o has transparent or supporter) || (o has container && o has open)) rtrue;
727 ! or alternatively with:
728 ! c_style = RECURSE_BIT; return WillRecurs(o);
730 ! LoopWithinObject() returns the number of objects which have been processed.
731 ! ----------------------------------------------------------------------------
733 [ LoopWithinObject rtn obj arg
735 if (obj == 0) obj = actor;
739 x = rtn(o, arg); ! user-supplied routine returning x.
740 ! if x < 0: skip up to next parent
741 ! if x = 0: jump across to next sibling
742 ! if x > 0: continue down to child objects
743 if (y ~= parent(o)) { RunTimeError(15, o); rfalse; }
744 if (x > 0 && child(o)) o = child(o);
747 if (++x > 0 && sibling(o)) { o = sibling(o); break; }
749 if (o == obj) return n;
755 ! ----------------------------------------------------------------------------
756 ! Much better menus can be created using one of the optional library
757 ! extensions. These are provided for compatibility with previous practice:
758 ! ----------------------------------------------------------------------------
760 [ LowKey_Menu menu_choices EntryR ChoiceR lines main_title i j;
767 main_title = item_name;
769 print "--- "; print (string) main_title; print " ---^^";
771 if (menu_choices ofclass Routine) menu_choices();
772 else print (string) menu_choices;
775 L__M(##Miscellany, 52, lines);
782 read buffer parse DrawStatusLine;
784 j = parse->1; ! number of words
785 #Ifnot; ! TARGET_GLULX;
786 KeyboardPrimitive(buffer, parse);
787 j = parse-->0; ! number of words
791 if (j == 0 || (i == QUIT1__WD or QUIT2__WD)) {
792 menu_nesting--; if (menu_nesting > 0) rfalse;
793 if (deadflag == 0) <<Look>>;
797 if (i == 0) jump LKRD;
798 if (i < 1 || i > lines) continue;
801 if (j == 2) jump LKRD;
810 [ DoMenu menu_choices EntryR ChoiceR; LowKey_Menu(menu_choices, EntryR, ChoiceR); ];
816 [ DoMenu menu_choices EntryR ChoiceR
817 lines main_title main_wid cl i j oldcl pkey ch cw y x;
818 if (pretty_flag == 0) return LowKey_Menu(menu_choices, EntryR, ChoiceR);
822 main_title = item_name; main_wid = item_width;
829 #Iftrue (#version_number == 6);
831 ch = HDR_FONTWUNITS->0;
837 i = HDR_SCREENWCHARS->0;
842 #Iftrue (#version_number == 6);
844 cw = HDR_FONTHUNITS->0;
850 spaces(i); j=1+(i/2-main_wid)*cw;
852 print (string) main_title;
853 y=1+ch; @set_cursor y 1; spaces(i);
854 x=1+cw; @set_cursor y x; print (string) NKEY__TX;
855 j=1+(i-13)*cw; @set_cursor y j; print (string) PKEY__TX;
856 y=y+ch; @set_cursor y 1; spaces(i);
857 @set_cursor y x; print (string) RKEY__TX;
858 j=1+(i-18)*cw; @set_cursor y j;
860 if (menu_nesting == 1) print (string) QKEY1__TX;
861 else print (string) QKEY2__TX;
864 @set_cursor y x; font off;
866 if (menu_choices ofclass String) print (string) menu_choices;
873 y=1+(oldcl-1)*ch; @set_cursor y x; print " ";
875 y=1+(cl-1)*ch; @set_cursor y x; print ">";
879 @read_char 1 -> pkey;
880 if (pkey == NKEY1__KY or NKEY2__KY or 130) {
881 cl++; if (cl == 7+lines) cl = 7; continue;
883 if (pkey == PKEY1__KY or PKEY2__KY or 129) {
884 cl--; if (cl == 6) cl = 6+lines; continue;
886 if (pkey == QKEY1__KY or QKEY2__KY or 27 or 131) break;
887 if (pkey == 10 or 13 or 132) {
888 @set_window 0; font on;
889 new_line; new_line; new_line;
896 i = HDR_SCREENWCHARS->0; if ( i== 0) i = 80;
897 @set_window 1; @set_cursor 1 1; style reverse; spaces(i);
898 j=1+(i/2-item_width)*cw;
900 print (string) item_name;
901 style roman; @set_window 0; new_line;
904 if (i == 2) jump ReDisplay;
907 L__M(##Miscellany, 53);
908 @read_char 1 -> pkey; jump ReDisplay;
912 menu_nesting--; if (menu_nesting > 0) rfalse;
913 font on; @set_cursor 1 1;
914 @erase_window $ffff; @set_window 0;
915 #Iftrue (#version_number == 6);
918 new_line; new_line; new_line;
919 if (deadflag == 0) <<Look>>;
924 #Ifnot; ! TARGET_GLULX
926 [ DoMenu menu_choices EntryR ChoiceR
927 winwid winhgt lines main_title main_wid cl i oldcl pkey;
929 if (pretty_flag == 0 || gg_statuswin == 0) return LowKey_Menu(menu_choices, EntryR, ChoiceR);
934 main_title = item_name;
935 main_wid = item_width;
939 ! If we printed "hit arrow keys" here, it would be appropriate to
940 ! check for the availability of Glk input keys. But we actually
941 ! print "hit N/P/Q". So it's reasonable to silently accept Glk
942 ! arrow key codes as secondary options.
946 glk_window_clear(gg_statuswin);
947 glk_window_clear(gg_mainwin);
948 glk_set_window(gg_statuswin);
949 StatusLineHeight(lines+7);
950 glk_window_get_size(gg_statuswin, gg_arguments, gg_arguments+4);
951 winwid = gg_arguments-->0;
952 winhgt = gg_arguments-->1;
953 glk_set_style(style_Subheader);
954 glk_window_move_cursor(gg_statuswin, winwid/2-main_wid, 0);
955 print (string) main_title;
956 glk_window_move_cursor(gg_statuswin, 1, 1);
957 print (string) NKEY__TX;
958 glk_window_move_cursor(gg_statuswin, winwid-13, 1);
959 print (string) PKEY__TX;
960 glk_window_move_cursor(gg_statuswin, 1, 2);
961 print (string) RKEY__TX;
962 glk_window_move_cursor(gg_statuswin, winwid-18, 2);
963 if (menu_nesting == 1) print (string) QKEY1__TX;
964 else print (string) QKEY2__TX;
965 glk_set_style(style_Normal);
966 glk_window_move_cursor(gg_statuswin, 1, 4);
967 if (menu_choices ofclass String) print (string) menu_choices;
974 if (cl < 0 || cl >= lines) cl = 0;
976 glk_window_move_cursor(gg_statuswin, 3, oldcl+6);
980 glk_window_move_cursor(gg_statuswin, 3, oldcl+6);
983 pkey = KeyCharPrimitive(gg_statuswin, true);
984 if (pkey == $80000000) jump ReDisplay;
985 if (pkey == NKEY1__KY or NKEY2__KY or $fffffffb) {
987 if (cl >= lines) cl = 0;
990 if (pkey == PKEY1__KY or PKEY2__KY or $fffffffc) {
992 if (cl < 0) cl = lines-1;
995 if (pkey == QKEY1__KY or QKEY2__KY or $fffffff8 or $fffffffe) break;
996 if (pkey == $fffffffa or $fffffffd) {
997 glk_set_window(gg_mainwin);
998 new_line; new_line; new_line;
1001 glk_window_clear(gg_statuswin);
1002 glk_window_clear(gg_mainwin);
1003 glk_set_window(gg_statuswin);
1004 StatusLineHeight(1);
1005 glk_window_get_size(gg_statuswin, gg_arguments, gg_arguments+4);
1006 winwid = gg_arguments-->0;
1007 winhgt = gg_arguments-->1;
1008 glk_set_style(style_Subheader);
1009 glk_window_move_cursor(gg_statuswin, winwid/2-item_width, 0);
1010 print (string) item_name;
1011 glk_set_style(style_Normal);
1012 glk_set_window(gg_mainwin);
1015 if (i == 2) jump ReDisplay;
1017 L__M(##Miscellany, 53);
1018 pkey = KeyCharPrimitive(gg_mainwin, 1);
1023 ! done with this menu...
1025 if (menu_nesting > 0) rfalse;
1026 glk_set_window(gg_mainwin);
1027 glk_window_clear(gg_mainwin);
1028 new_line; new_line; new_line;
1029 if (deadflag == 0) <<Look>>;
1034 ! ----------------------------------------------------------------------------
1035 ! A cunning routine (which could have been a daemon, but isn't, for the
1036 ! sake of efficiency) to move objects which could be in many rooms about
1037 ! so that the player never catches one not in place
1038 ! ----------------------------------------------------------------------------
1040 [ MoveFloatingObjects i k l m address flag;
1041 if (location == player or nothing) return;
1043 address = i.&found_in;
1044 if (address && i hasnt non_floating && ~~IndirectlyContains(player, i)) {
1045 if (metaclass(address-->0) == Routine)
1046 flag = i.found_in();
1049 k = i.#found_in/WORDSIZE;
1050 for (l=0 : l<k : l++) {
1052 if ((m in Class && location ofclass m) ||
1053 m == location || m in location) {
1060 if (i notin location) move i to location;
1062 if (parent(i)) remove i;
1068 ! ----------------------------------------------------------------------------
1069 ! Two little routines for moving the player safely.
1070 ! ----------------------------------------------------------------------------
1072 [ PlayerTo newplace flag;
1074 move player to newplace;
1075 while (parent(newplace)) newplace = parent(newplace);
1076 location = real_location = newplace;
1077 MoveFloatingObjects(); AdjustLight(1);
1080 1: NoteArrival(); ScoreArrival();
1085 [ MovePlayer direc; <Go direc>; <Look>; ];
1087 ! ----------------------------------------------------------------------------
1088 ! The handy YesOrNo routine, and some "meta" verbs
1089 ! ----------------------------------------------------------------------------
1091 [ YesOrNo noStatusRedraw
1094 #Ifdef TARGET_ZCODE;
1095 if (location == nothing || parent(player) == nothing || noStatusRedraw)
1097 else read buffer parse DrawStatusLine;
1099 #Ifnot; ! TARGET_GLULX;
1100 noStatusRedraw = 0; ! suppress warning
1101 KeyboardPrimitive(buffer, parse);
1104 if (j) { ! at least one word entered
1106 if (i == YES1__WD or YES2__WD or YES3__WD) rtrue;
1107 if (i == NO1__WD or NO2__WD or NO3__WD) rfalse;
1109 L__M(##Quit, 1); print "> ";
1113 #Ifdef TARGET_ZCODE;
1117 if (YesOrNo()) quit;
1122 if (YesOrNo()) { @restart; L__M(##Restart, 2); }
1127 return L__M(##Restore, 1);
1129 if (AfterRestore() == 1)
1130 LibraryExtensions.RunAll(ext_afterrestore);
1141 if (AfterSave() == 1)
1142 LibraryExtensions.RunAll(ext_aftersave);
1147 if (AfterRestore() == 1)
1148 LibraryExtensions.RunAll(ext_afterrestore);
1154 return L__M(##Save, 1);
1156 if (AfterSave() == 1)
1157 LibraryExtensions.RunAll(ext_aftersave);
1167 return L__M(##Verify, 1);
1173 transcript_mode = ((HDR_GAMEFLAGS-->0) & 1);
1174 if (transcript_mode) return L__M(##ScriptOn, 1);
1176 if (((HDR_GAMEFLAGS-->0) & 1) == 0) return L__M(##ScriptOn, 3);
1177 L__M(##ScriptOn, 2);
1178 transcript_mode = true;
1182 transcript_mode = ((HDR_GAMEFLAGS-->0) & 1);
1183 if (transcript_mode == false) return L__M(##ScriptOff, 1);
1184 L__M(##ScriptOff, 2);
1186 if ((HDR_GAMEFLAGS-->0) & 1) return L__M(##ScriptOff, 3);
1187 transcript_mode = false;
1193 L__M(##CommandsOn, 1);
1197 if (xcommsdir == 1) @output_stream -4;
1199 L__M(##CommandsOff, 1);
1205 L__M(##CommandsRead, 1);
1208 #Ifnot; ! TARGET_GLULX;
1212 if (YesOrNo()) quit;
1217 if (YesOrNo()) { @restart; L__M(##Restart, 2); }
1220 [ RestoreSub res fref;
1221 fref = glk_fileref_create_by_prompt($01, $02, 0);
1222 if (fref == 0) jump RFailed;
1223 gg_savestr = glk_stream_open_file(fref, $02, GG_SAVESTR_ROCK);
1224 glk_fileref_destroy(fref);
1225 if (gg_savestr == 0) jump RFailed;
1226 @restore gg_savestr res;
1227 glk_stream_close(gg_savestr, 0);
1233 [ SaveSub res fref retval;
1234 fref = glk_fileref_create_by_prompt($01, $01, 0);
1235 if (fref == 0) jump SFailed;
1236 gg_savestr = glk_stream_open_file(fref, $01, GG_SAVESTR_ROCK);
1237 glk_fileref_destroy(fref);
1238 if (gg_savestr == 0) jump SFailed;
1239 @save gg_savestr res;
1241 ! The player actually just typed "restore". We're going to print
1242 ! L__M(##Restore,2); the Z-Code Inform library does this correctly
1243 ! now. But first, we have to recover all the Glk objects; the values
1244 ! in our global variables are all wrong.
1246 glk_stream_close(gg_savestr, 0);
1248 if (AfterRestore() == 1)
1249 return LibraryExtensions.RunAll(ext_afterrestore);
1251 return L__M(##Restore, 2);
1254 glk_stream_close(gg_savestr, 0);
1257 if (AfterSave() == 1)
1258 return LibraryExtensions.RunAll(ext_aftersave);
1260 return L__M(##Save, 2);
1268 if (res == 0) return L__M(##Verify, 1);
1273 if (gg_scriptstr) return L__M(##ScriptOn, 1);
1274 if (gg_scriptfref == 0) {
1275 gg_scriptfref = glk_fileref_create_by_prompt($102, $05, GG_SCRIPTFREF_ROCK);
1276 if (gg_scriptfref == 0) jump S1Failed;
1278 gg_scriptstr = glk_stream_open_file(gg_scriptfref, $05, GG_SCRIPTSTR_ROCK);
1279 if (gg_scriptstr == 0) jump S1Failed;
1280 glk_window_set_echo_stream(gg_mainwin, gg_scriptstr);
1281 L__M(##ScriptOn, 2);
1284 L__M(##ScriptOn, 3);
1288 if (gg_scriptstr == 0) return L__M(##ScriptOff,1);
1289 L__M(##ScriptOff, 2);
1290 glk_stream_close(gg_scriptstr, 0);
1294 [ CommandsOnSub fref;
1295 if (gg_commandstr) {
1296 if (gg_command_reading) return L__M(##CommandsOn, 2);
1297 else return L__M(##CommandsOn, 3);
1299 fref = glk_fileref_create_by_prompt($103, $01, 0);
1300 if (fref == 0) return L__M(##CommandsOn, 4);
1301 gg_command_reading = false;
1302 gg_commandstr = glk_stream_open_file(fref, $01, GG_COMMANDWSTR_ROCK);
1303 glk_fileref_destroy(fref);
1304 if (gg_commandstr == 0) return L__M(##CommandsOn, 4);
1305 L__M(##CommandsOn, 1);
1309 if (gg_commandstr == 0) return L__M(##CommandsOff, 2);
1310 if (gg_command_reading) return L__M(##CommandsRead, 5);
1311 glk_stream_close(gg_commandstr, 0);
1313 gg_command_reading = false;
1314 L__M(##CommandsOff, 1);
1317 [ CommandsReadSub fref;
1318 if (gg_commandstr) {
1319 if (gg_command_reading) return L__M(##CommandsRead, 2);
1320 else return L__M(##CommandsRead, 3);
1322 fref = glk_fileref_create_by_prompt($103, $02, 0);
1323 if (fref == 0) return L__M(##CommandsRead, 4);
1324 gg_command_reading = true;
1325 gg_commandstr = glk_stream_open_file(fref, $02, GG_COMMANDRSTR_ROCK);
1326 glk_fileref_destroy(fref);
1327 if (gg_commandstr == 0) return L__M(##CommandsRead, 4);
1328 L__M(##CommandsRead, 1);
1333 [ NotifyOnSub; notify_mode = true; L__M(##NotifyOn); ];
1334 [ NotifyOffSub; notify_mode = false; L__M(##NotifyOff); ];
1337 places_style = NEWLINE_BIT+INDENT_BIT+FULLINV_BIT;
1342 places_style = ENGLISH_BIT+FULLINV_BIT;
1347 objectloop (i has visited) j++;
1349 return L__M(##Places, 3);
1352 if (places_style & INDENT_BIT) print (string) COLON__TX, "^";
1355 objectloop (i has visited) {
1356 if (places_style & INDENT_BIT) Print__Spaces(2);
1357 print (name) i; k++;
1359 if (places_style & INDENT_BIT)
1363 return L__M(##Places, 2);
1365 print (SerialComma) j, (string) AND__TX;
1367 print (string) COMMA__TX;
1373 objects_style = NEWLINE_BIT+INDENT_BIT+FULLINV_BIT;
1378 objects_style = ENGLISH_BIT+FULLINV_BIT;
1382 [ Objects1Sub i j f object_count;
1384 objectloop (i has moved) {
1387 if (object_count == 0)
1388 return L__M(##Objects, 2);
1391 if (objects_style & INDENT_BIT) print (string) COLON__TX, "^";
1394 objectloop (i has moved) {
1396 if (objects_style & INDENT_BIT) Print__Spaces(2);
1401 if (i has worn) L__M(##Objects, 3, j, i);
1402 else L__M(##Objects, 4, j, i);
1405 if (j has animate) { L__M(##Objects, 5, j, i); jump Obj__Ptd; }
1406 if (j has visited) { L__M(##Objects, 6, j, i); jump Obj__Ptd; }
1407 if (j has container) { L__M(##Objects, 8, j, i); jump Obj__Ptd; }
1408 if (j has supporter) { L__M(##Objects, 9, j, i); jump Obj__Ptd; }
1409 if (j has enterable) { L__M(##Objects, 7, j, i); jump Obj__Ptd; }
1411 L__M(##Objects, 10, j, i);
1415 if ((object_count - f) >= 1) {
1416 if (objects_style & INDENT_BIT) {
1420 if ((object_count - f) == 1) {
1421 SerialComma(object_count);
1422 print " ", (address) AND1__WD, " ";
1423 } else if (object_count > 2)
1424 print (string) COMMA__TX;
1429 if ((objects_style & INDENT_BIT) == 0)
1435 ! ----------------------------------------------------------------------------
1436 ! The scoring system
1437 ! ----------------------------------------------------------------------------
1441 if (deadflag == 0) L__M(##Score, 2);
1443 if (deadflag) new_line;
1445 if(PrintRank() == false) LibraryExtensions.RunAll(ext_printrank);
1451 return task_scores->i;
1456 if (task_done->num == 0) {
1458 score = score + TaskScore(num);
1465 if (n < 0) { n = -m; n = n*10; }
1466 if (n < 10) { print " "; jump Panuml; }
1467 if (n < 100) { print " "; jump Panuml; }
1468 if (n < 1000) { print " "; }
1477 if (score == 0 || TASKS_PROVIDED == 1) rfalse;
1479 L__M(##FullScore, 1);
1480 for (i=0 : i<NUMBER_TASKS : i++)
1481 if (task_done->i == 1) {
1482 PANum(TaskScore(i));
1483 if(PrintTaskName(i) == false)
1484 LibraryExtensions.RunAll(ext_printtaskname,i);
1487 PANum(things_score);
1488 L__M(##FullScore, 2);
1491 PANum(places_score);
1492 L__M(##FullScore, 3);
1494 new_line; PANum(score); L__M(##FullScore, 4);
1497 ! ----------------------------------------------------------------------------
1498 ! Real verbs start here: Inventory
1499 ! ----------------------------------------------------------------------------
1502 if (actor == player)
1503 inventory_style = ENGLISH_BIT+FULLINV_BIT+RECURSE_BIT;
1505 inventory_style = ENGLISH_BIT+PARTINV_BIT;
1510 if (actor == player)
1511 inventory_style = NEWLINE_BIT+INDENT_BIT+FULLINV_BIT+RECURSE_BIT;
1513 inventory_style = NEWLINE_BIT+INDENT_BIT+PARTINV_BIT;
1518 if (child(actor) == 0) return L__M(##Inv, 1);
1519 if (inventory_style == 0)
1520 if (actor == player) return InvTallSub();
1521 else return InvWideSub();
1523 if (inventory_style & NEWLINE_BIT) L__M(##Inv, 3); else print " ";
1525 WriteListFrom(child(actor), inventory_style, 1);
1526 if (inventory_style & ENGLISH_BIT) L__M(##Inv, 4);
1528 #Ifndef MANUAL_PRONOUNS;
1529 objectloop (x in player) PronounNotice(x);
1531 x = 0; ! To prevent a "not used" error
1535 ! ----------------------------------------------------------------------------
1536 ! The object tree and determining the possibility of moves
1537 ! ----------------------------------------------------------------------------
1539 [ CommonAncestor o1 o2 i j;
1540 ! Find the nearest object indirectly containing o1 and o2,
1541 ! or return 0 if there is no common ancestor.
1546 if (j == i) return i;
1554 [ IndirectlyContains o1 o2;
1555 ! Does o1 indirectly contain o2? (Same as testing if their common ancestor is o1.)
1557 if (o1 == o2) rtrue;
1558 if (o2 ofclass Class) rfalse;
1564 [ ObjectScopedBySomething item i j k l m;
1566 objectloop (j .& add_to_scope) {
1567 l = j.&add_to_scope;
1568 k = (j.#add_to_scope)/WORDSIZE;
1569 if (l-->0 ofclass Routine) continue;
1570 for (m=0 : m<k : m++)
1571 if (l-->m == i) return j;
1576 [ ObjectIsUntouchable item flag1 flag2 ancestor i;
1577 ! Determine if there's any barrier preventing the actor from moving
1578 ! things to "item". Return false if no barrier; otherwise print a
1579 ! suitable message and return true.
1580 ! If flag1 is set, do not print any message.
1581 ! If flag2 is set, also apply Take/Remove restrictions.
1583 ! If the item has been added to scope by something, it's first necessary
1584 ! for that something to be touchable.
1586 ancestor = CommonAncestor(actor, item);
1587 if (ancestor == 0) {
1589 while (ancestor && (i = ObjectScopedBySomething(ancestor)) == 0)
1590 ancestor = parent(ancestor);
1592 if (ObjectIsUntouchable(i, flag1, flag2)) return;
1593 ! An item immediately added to scope
1598 ! First, a barrier between the actor and the ancestor. The actor
1599 ! can only be in a sequence of enterable objects, and only closed
1600 ! containers form a barrier.
1602 if (actor ~= ancestor) {
1604 while (i ~= ancestor) {
1605 if (i has container && i hasnt open) {
1607 return L__M(##Take, 9, i, noun);
1613 ! Second, a barrier between the item and the ancestor. The item can
1614 ! be carried by someone, part of a piece of machinery, in or on top
1615 ! of something and so on.
1618 if (item ~= ancestor && i ~= player) {
1619 while (i ~= ancestor) {
1620 if (flag2 && i hasnt container && i hasnt supporter) {
1621 if (i has animate) {
1623 return L__M(##Take, 6, i, noun);
1625 if (i has transparent) {
1627 return L__M(##Take, 7, i, noun);
1630 return L__M(##Take, 8, item, noun);
1632 if (i has container && i hasnt open) {
1634 return L__M(##Take, 9, i, noun);
1642 [ AttemptToTakeObject item
1643 ancestor after_recipient i k;
1644 ! Try to transfer the given item to the actor: return false
1645 ! if successful, true if unsuccessful, printing a suitable message
1646 ! in the latter case.
1647 ! People cannot ordinarily be taken.
1648 if (item == actor) return L__M(##Take, 2, noun);
1649 if (item has animate) return L__M(##Take, 3, item);
1651 ancestor = CommonAncestor(actor, item);
1653 if (ancestor == 0) {
1654 i = ObjectScopedBySomething(item);
1655 if (i) ancestor = CommonAncestor(actor, i);
1658 ! Is the actor indirectly inside the item?
1659 if (ancestor == item) return L__M(##Take, 4, item);
1661 ! Does the actor already directly contain the item?
1662 if (item in actor) return L__M(##Take, 5, item);
1664 ! Can the actor touch the item, or is there (e.g.) a closed container
1666 if (ObjectIsUntouchable(item, false, true)) rtrue;
1668 ! The item is now known to be accessible.
1670 ! Consult the immediate possessor of the item, if it's in a container
1671 ! which the actor is not in.
1674 if (i && i ~= ancestor && (i has container or supporter)) {
1675 after_recipient = i;
1676 k = action; action = ##LetGo;
1677 if (RunRoutines(i, before)) { action = k; rtrue; }
1681 if (item has static) return L__M(##Take, 11, item);
1682 if (item has scenery) return L__M(##Take, 10, item);
1684 ! The item is now known to be available for taking. Is the player
1685 ! carrying too much? If so, possibly juggle items into the rucksack
1688 if (ObjectDoesNotFit(item, actor) ||
1689 LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, item, actor)) return;
1690 if (AtFullCapacity(item, actor)) return L__M(##Take, 12, item);
1692 ! Transfer the item.
1694 move item to actor; give item ~worn;
1696 ! Send "after" message to the object letting go of the item, if any.
1698 if (after_recipient) {
1699 k = action; action = ##LetGo;
1700 if (RunRoutines(after_recipient, after)) { action = k; rtrue; }
1706 [ AtFullCapacity n s
1708 n = n; ! suppress compiler warning
1710 objectloop (obj in s)
1711 if (obj hasnt worn) k++;
1715 if (k < RunRoutines(s, capacity) || (s == player && RoomInSack())) rfalse;
1720 if (SACK_OBJECT && SACK_OBJECT in player) {
1721 ks = keep_silent; keep_silent = 2;
1722 for (obj=youngest(player) : obj : obj=elder(obj))
1723 if (obj ~= SACK_OBJECT && obj hasnt worn or light) {
1724 <Insert obj SACK_OBJECT>;
1725 if (obj in SACK_OBJECT) {
1727 return L__M(##Take, 13, obj, SACK_OBJECT);
1735 ! ----------------------------------------------------------------------------
1736 ! Support for implicit actions
1737 ! ----------------------------------------------------------------------------
1739 [ CheckImplicitAction act o1 o2
1740 sav_act sav_noun sav_sec res;
1741 if (o1 provides before_implicit) {
1742 sav_act = action; action = act;
1743 sav_noun = noun; noun = o1;
1744 if (o2) { sav_sec = second; second = o2; }
1745 res = RunRoutines(o1, before_implicit);
1746 action = sav_act; noun = sav_noun;
1747 if (sav_sec) second = sav_sec;
1750 if (no_implicit_actions)
1760 switch (metaclass(obj)) { Class, String, Routine, nothing: rfalse; }
1761 if (obj in actor) rfalse;
1762 if (action_to_be == ##Drop && ~~IndirectlyContains(actor, obj)) rfalse;
1763 res = CheckImplicitAction(##Take, obj);
1764 ! 0 = Take object, Tell the user (normal default)
1765 ! 1 = Take object, don't Tell
1766 ! 2 = don't Take object continue (default with no_implicit_actions)
1767 ! 3 = don't Take object, don't continue
1768 if (res >= 2) rtrue;
1769 if (parent(obj) && parent(obj) has container or supporter) supcon = parent(obj);
1770 ks = keep_silent; keep_silent = 2; AttemptToTakeObject(obj); keep_silent = ks;
1771 if (obj notin actor) rtrue;
1772 if (res == 0 && ~~keep_silent)
1773 if (supcon) return L__M(##Miscellany, 58, obj, supcon);
1774 else return L__M(##Miscellany, 26, obj);
1780 if (parent(obj) == nothing) rfalse;
1781 res = CheckImplicitAction(##Exit, obj);
1782 ! 0 = Exit object, Tell the user (normal default)
1783 ! 1 = Exit object, don't Tell
1784 ! 2 = don't Exit object continue (default with no_implicit_actions)
1785 ! 3 = don't Exit object, don't continue
1786 if (res >= 2) rtrue;
1787 ks = keep_silent; keep_silent = 2; <Exit obj, actor>; keep_silent = ks;
1788 if (parent(actor) == obj) rtrue;
1789 if (res == 0 && ~~keep_silent) L__M(##Exit, 5, obj);
1795 if (obj hasnt open) rfalse;
1796 res = CheckImplicitAction(##Close, obj);
1797 ! 0 = Close object, Tell the user (normal default)
1798 ! 1 = Close object, don't Tell
1799 ! 2 = don't Close object continue (default with no_implicit_actions)
1800 ! 3 = don't Close object, don't continue
1801 if (res >= 2) rtrue;
1802 ks = keep_silent; keep_silent = 2; <Close obj, actor>; keep_silent = ks;
1803 if (obj has open) rtrue;
1804 if (res == 0 && ~~keep_silent) L__M(##Close, 4, obj);
1810 if (obj has open) rfalse;
1811 res = CheckImplicitAction(##Open, obj);
1812 ! 0 = Open object, Tell the user (normal default)
1813 ! 1 = Open object, don't Tell
1814 ! 2 = don't Open object continue (default with no_implicit_actions)
1815 ! 3 = don't Open object, don't continue
1816 if (res >= 2) rtrue;
1817 if (obj has locked) rtrue;
1818 temp = keep_silent; keep_silent = 2; <Open obj, actor>; keep_silent = temp;
1819 if (obj hasnt open) rtrue;
1820 if (res == 0 && ~~keep_silent) L__M(##Open, 6, obj);
1821 temp = action; action = ##Open;
1822 inp1temp = inp1; inp1 = obj;
1824 inp1 = inp1temp; action = temp;
1828 [ ImplicitUnlock obj;
1829 if (obj has locked) rtrue;
1833 [ ImplicitDisrobe obj
1835 if (obj hasnt worn) rfalse;
1836 res = CheckImplicitAction(##Disrobe, obj);
1837 ! 0 = Take off object, Tell the user (normal default)
1838 ! 1 = Take off object, don't Tell
1839 ! 2 = don't Take off object continue (default with no_implicit_actions)
1840 ! 3 = don't Take off object, don't continue
1841 if (res >= 2) rtrue;
1842 ks = keep_silent; keep_silent = 1; <Disrobe obj, actor>; keep_silent = ks;
1843 if (obj has worn && obj in actor) rtrue;
1844 if (res == 0 && ~~keep_silent) L__M(##Disrobe, 3, obj);
1849 ! ----------------------------------------------------------------------------
1850 ! Object movement verbs
1851 ! ----------------------------------------------------------------------------
1854 if (noun in actor && noun has worn) <<Disrobe noun, actor>>;
1855 if (onotheld_mode == 0 || noun notin actor)
1856 if (AttemptToTakeObject(noun)) return;
1857 if (AfterRoutines()) return;
1858 notheld_mode = onotheld_mode;
1859 if (notheld_mode == 1 || keep_silent) return;
1860 L__M(##Take, 1, noun);
1865 if (i && i has container && i hasnt open && ImplicitOpen(i)) return L__M(##Remove, 1, i);
1866 if (noun has clothing) {
1867 if (noun has worn) <<Disrobe noun, actor>>;
1868 if (i && i has container or supporter)
1871 if (i == actor) return L__M(##Disrobe, 1, noun);
1873 if (i hasnt container && i hasnt supporter) return L__M(##Remove, 4, noun);
1874 if (i ~= second && second ~= nothing) return L__M(##Remove, 2, noun);
1875 if (i has animate) return L__M(##Take, 6, i, noun);
1878 if (AttemptToTakeObject(noun)) rtrue;
1879 action = ##Remove; if (AfterRoutines()) return;
1880 action = ##Take; if (AfterRoutines()) return;
1881 if (keep_silent) return;
1882 L__M(##Remove, 3, noun);
1886 if (noun == actor) return L__M(##PutOn, 4, noun);
1887 if (noun in parent(actor)) return L__M(##Drop, 1, noun);
1888 if (noun has worn && no_implicit_actions) return L__M(##Disrobe, 4, noun);
1889 if (noun has worn && ImplicitDisrobe(noun)) return;
1890 if (noun notin actor) {
1891 if (no_implicit_actions) return L__M(##Drop, 4, noun, parent(noun));
1892 L__M(##Miscellany, 58, noun, parent(noun));
1895 move noun to parent(actor);
1896 if (AfterRoutines() || keep_silent) return;
1897 L__M(##Drop, 3, noun);
1900 [ PutOnSub ancestor;
1901 receive_action = ##PutOn;
1902 if (second == d_obj || actor in second) <<Drop noun, actor>>;
1903 if (parent(noun) == second) return L__M(##Drop, 1, noun);
1904 if (ImplicitTake(noun) && noun notin actor) return L__M(##PutOn, 1, noun);
1906 ancestor = CommonAncestor(noun, second);
1907 if (ancestor == noun) return L__M(##PutOn, 2, noun);
1908 if (ObjectIsUntouchable(second)) return;
1910 if (second ~= ancestor) {
1912 if (RunRoutines(second, before)) { action = ##PutOn; return; }
1915 if (second hasnt supporter) return L__M(##PutOn, 3, second);
1917 if (noun has worn && no_implicit_actions) return L__M(##Disrobe, 4, noun);
1918 if (noun has worn && ImplicitDisrobe(noun)) return;
1920 if (ObjectDoesNotFit(noun, second) ||
1921 LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, noun, second)) return;
1922 if (AtFullCapacity(noun, second)) return L__M(##PutOn, 6, second);
1924 move noun to second;
1926 if (AfterRoutines()) return;
1928 if (second ~= ancestor) {
1930 if (RunRoutines(second, after)) { action = ##PutOn; return; }
1933 if (keep_silent) return;
1934 if (multiflag) return L__M(##PutOn, 7);
1935 L__M(##PutOn, 8, noun, second);
1938 [ InsertSub ancestor;
1939 receive_action = ##Insert;
1940 if (second == d_obj || actor in second) <<Drop noun, actor>>;
1941 if (parent(noun) == second) return L__M(##Drop, 1, noun);
1942 if (ImplicitTake(noun) && noun notin actor) return L__M(##Insert, 1, noun);
1943 ancestor = CommonAncestor(noun, second);
1944 if (ancestor == noun) return L__M(##Insert, 5, noun);
1945 if (ObjectIsUntouchable(second)) return;
1946 if (second ~= ancestor) {
1948 if (RunRoutines(second,before)) { action = ##Insert; rtrue; }
1950 if (second has container && second hasnt open && ImplicitOpen(second))
1951 return L__M(##Insert, 3, second);
1953 if (second hasnt container) return L__M(##Insert, 2, second);
1954 if (noun has worn && no_implicit_actions) return L__M(##Disrobe, 4, noun);
1955 if (noun has worn && ImplicitDisrobe(noun)) return;
1957 if (ObjectDoesNotFit(noun, second) ||
1958 LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, noun, second)) return;
1959 if (AtFullCapacity(noun, second)) return L__M(##Insert, 7, second);
1961 move noun to second;
1963 if (AfterRoutines()) rtrue;
1965 if (second ~= ancestor) {
1967 if (RunRoutines(second, after)) { action = ##Insert; rtrue; }
1970 if (keep_silent) rtrue;
1971 if (multiflag) return L__M(##Insert, 8, noun);
1972 L__M(##Insert, 9, noun, second);
1975 ! ----------------------------------------------------------------------------
1976 ! Empties and transfers are routed through the actions above
1977 ! ----------------------------------------------------------------------------
1980 if (noun notin actor && AttemptToTakeObject(noun)) return;
1981 if (second has supporter) <<PutOn noun second, actor>>;
1982 if (second == d_obj) <<Drop noun, actor>>;
1983 <<Insert noun second, actor>>;
1986 [ EmptySub; second = d_obj; EmptyTSub(); ];
1988 [ EmptyTSub i j k flag;
1989 if (noun == second) return L__M(##EmptyT, 4, noun);
1990 if (ObjectIsUntouchable(noun)) return;
1991 if (noun hasnt container) return L__M(##EmptyT, 1, noun);
1992 if (noun hasnt open && ImplicitOpen(noun)) return L__M(##EmptyT, 2, noun);
1993 if (second ~= d_obj) {
1994 if (second hasnt supporter) {
1995 if (second hasnt container) return L__M(##EmptyT, 1, second);
1996 if (second hasnt open && ImplicitOpen(second))
1997 return L__M(##EmptyT, 2, second);
2000 i = child(noun); k = children(noun);
2001 if (i == 0) return L__M(##EmptyT, 3, noun);
2005 if (ObjectIsUntouchable(noun)) flag = true;
2006 if (noun hasnt container) flag = true;
2007 if (noun hasnt open) flag = true;
2008 if (second ~= d_obj) {
2009 if (second hasnt supporter) {
2010 if (second hasnt container) flag = true;
2011 if (second hasnt open) flag = true;
2014 if (k-- == 0) flag = 1;
2016 if (keep_silent == 0) print (name) i, (string) COLON__TX, " ";
2017 <Transfer i second, actor>;
2022 ! ----------------------------------------------------------------------------
2024 ! ----------------------------------------------------------------------------
2027 if (noun notin actor && ImplicitTake(noun)) return L__M(##Give, 1, noun);
2028 if (second == actor) return L__M(##Give, 2, noun);
2029 if (noun has worn && ImplicitDisrobe(noun)) return;
2030 if (second == player) {
2031 move noun to player;
2032 return L__M(##Give, 4, noun);
2035 if (RunLife(second, ##Give)) return;
2036 L__M(##Give, 3, second);
2039 [ GiveRSub; <Give second noun, actor>; ];
2042 if (noun notin actor && ImplicitTake(noun)) return L__M(##Show, 1, noun);
2043 if (second == player) <<Examine noun, actor>>;
2044 if (RunLife(second, ##Show)) return;
2045 L__M(##Show, 2, second);
2048 [ ShowRSub; <Show second noun, actor>; ];
2050 ! ----------------------------------------------------------------------------
2051 ! Travelling around verbs
2052 ! ----------------------------------------------------------------------------
2054 [ EnterSub ancestor j ks;
2055 if (noun has door || noun in Compass) {
2056 if (verb_word == STAND__TX or SIT__TX or LIE__TX)
2057 return L__M(##Enter, 2, noun, verb_word);
2061 if (actor in noun) return L__M(##Enter, 1, noun);
2062 if (noun hasnt enterable) return L__M(##Enter, 2, noun, verb_word);
2064 if (parent(actor) ~= parent(noun)) {
2065 ancestor = CommonAncestor(actor, noun);
2066 if (ancestor == actor or 0) return L__M(##Enter, 4, noun);
2067 while (actor notin ancestor) {
2070 if (parent(j) ~= ancestor || noun ~= ancestor) {
2071 L__M(##Enter, 6, j);
2076 if (actor in j) return;
2078 if (actor in noun) return;
2079 if (noun notin ancestor) {
2081 while (parent(j) ~= ancestor) j = parent(j);
2082 L__M(##Enter, 7, j);
2083 ks = keep_silent; keep_silent = 1;
2086 if (actor notin j) return;
2087 <<Enter noun, actor>>;
2091 if (noun has container && noun hasnt open && ImplicitOpen(noun)) return L__M(##Enter, 3, noun);
2094 if (AfterRoutines() || keep_silent) return;
2095 L__M(##Enter, 5, noun);
2096 if (actor == player) Locale(noun);
2100 if (parent(actor) == noun) <<Exit, actor>>;
2101 L__M(##GetOff, 1, noun);
2106 if (noun ~= nothing && noun ~= p) return L__M(##Exit, 4 ,noun);
2107 if (p == location || (location == thedark && p == real_location)) {
2108 if (actor provides posture && actor.posture) {
2110 return L__M(##Exit, 6);
2112 if ((location.out_to) || (location == thedark && real_location.out_to))
2113 <<Go out_obj, actor>>;
2114 return L__M(##Exit, 1);
2116 if (p has container && p hasnt open && ImplicitOpen(p))
2117 return L__M(##Exit, 2, p);
2119 if (noun == nothing) {
2121 if (RunRoutines(p, before)) return;
2124 move actor to parent(p);
2125 if (player provides posture) player.posture = 0;
2127 if (AfterRoutines() || keep_silent) return;
2129 if (actor == player && p has container) LookSub(1);
2132 [ VagueGoSub; L__M(##VagueGo); ];
2134 [ GoInSub; <<Go in_obj, actor>>; ];
2136 [ GoSub i j k movewith thedir next_loc;
2138 ! first, check if any PushDir object is touchable
2139 if (second && second notin Compass && ObjectIsUntouchable(second)) return;
2143 if ((location ~= thedark && i ~= location) || (location == thedark && i ~= real_location)) {
2145 if (location == thedark) location = real_location;
2146 k = RunRoutines(i, before); if (k ~= 3) location = j;
2148 movewith = i; i = parent(i);
2152 if (ImplicitExit(i)) return L__M(##Go, 1, i);
2157 if (noun.door_dir ~= nothing) {
2158 thedir = noun.door_dir;
2159 if (metaclass(thedir) == Routine)
2160 thedir = RunRoutines(noun, door_dir);
2161 next_loc = i.thedir;
2165 k = metaclass(next_loc);
2168 print (string) next_loc;
2173 next_loc = RunRoutines(i, thedir);
2174 if (next_loc == 1) rtrue;
2177 if (k == nothing || next_loc == 0) {
2178 if (i.cant_go ~= 0 or CANTGO__TX) PrintOrRun(i, cant_go);
2183 if (next_loc has door) {
2184 if (next_loc has concealed) return L__M(##Go, 2);
2185 if (next_loc hasnt open && ImplicitOpen(next_loc)) {
2186 if (noun == u_obj) return L__M(##Go, 3, next_loc);
2187 if (noun == d_obj) return L__M(##Go, 4, next_loc);
2188 return L__M(##Go, 5, next_loc);
2190 k = RunRoutines(next_loc, door_to);
2191 if (k == 0) return L__M(##Go, 6, next_loc);
2197 if (RunRoutines(next_loc, before)) { action = ##Go; return; }
2200 if (movewith == 0) move actor to next_loc; else move movewith to next_loc;
2201 if (actor ~= player) return L__M(##Go, 7);
2203 k = location; location = next_loc;
2204 MoveFloatingObjects();
2205 if (OffersLight(location))
2210 if(DarkToDark() == false) ! From real_location To location
2211 LibraryExtensions.RunAll(ext_darktodark);
2212 if (deadflag) rtrue;
2216 NoteDeparture(); real_location = next_loc;
2218 if (RunRoutines(prev_location, after)) { action = ##Go; return; }
2220 if (AfterRoutines() || keep_silent) return;
2226 ! ----------------------------------------------------------------------------
2227 ! Describing the world. SayWhatsOn(object) does just that (producing
2228 ! no text if nothing except possibly "scenery" and "concealed" items are).
2229 ! Locale(object) runs through the "tail end" of a Look-style room
2230 ! description for the contents of the object, printing up suitable
2231 ! descriptions as it goes.
2232 ! ----------------------------------------------------------------------------
2235 [ SayWhatsOn descon j f;
2236 if (descon == parent(player)) rfalse;
2237 objectloop (j in descon)
2238 if (j hasnt concealed && j hasnt scenery) f = 1;
2240 L__M(##Look, 4, descon);
2244 [ NotSupportingThePlayer o i;
2246 while (i && i ~= visibility_ceiling) {
2249 if (i && i hasnt supporter) rtrue;
2255 ! Determine if something is casually visible. Includes things on
2256 ! supporters or in open/transparent containers that are scenery. Static
2257 ! objects are not included.
2258 [ Locale descin text_without_ALSO text_with_ALSO
2259 o p num_objs must_print_ALSO x flag;
2261 objectloop (o in descin) {
2262 if (o has scenery && (o has supporter || (o has container && o has open or transparent)) && children(o) > 0) {
2264 objectloop (x in o) {
2265 if (x hasnt scenery && x hasnt concealed)
2274 if (o has supporter)
2275 print "On ", (the) o;
2277 print "In ", (the) o;
2279 WriteListFrom(child(o), ENGLISH_BIT+TERSE_BIT+CONCEAL_BIT+ISARE_BIT);
2289 objectloop (o in descin)
2292 objectloop (o in descin) {
2293 if (o hasnt concealed && NotSupportingThePlayer(o)) {
2294 #Ifndef MANUAL_PRONOUNS;
2297 if (o hasnt scenery) {
2301 if ((o has door or container) && o has open && o provides when_open) {
2305 if ((o has door or container) && o hasnt open && o provides when_closed) {
2309 if (o has switchable && o has on && o provides when_on) {
2313 if (o has switchable && o hasnt on && o provides when_off)
2316 if (o.&describe && RunRoutines(o, describe)) {
2317 must_print_ALSO = true;
2322 if (o.p && (o hasnt moved || p ~= initial)) {
2325 must_print_ALSO = true;
2328 if (o has supporter && child(o))
2337 if (actor ~= player)
2338 give actor concealed;
2339 if (text_without_ALSO) {
2341 if (must_print_ALSO)
2342 print (string) text_with_ALSO, " ";
2344 print (string) text_without_ALSO, " ";
2346 WriteListFrom(child(descin), ENGLISH_BIT+RECURSE_BIT+PARTINV_BIT+TERSE_BIT+CONCEAL_BIT+WORKFLAG_BIT);
2348 if (must_print_ALSO)
2349 L__M(##Look, 5, descin);
2351 L__M(##Look, 6, descin);
2353 if (actor ~= player)
2354 give actor ~concealed;
2360 ! ----------------------------------------------------------------------------
2361 ! Looking. LookSub(1) is allowed to abbreviate long descriptions, but
2362 ! LookSub(0) (which is what happens when the Look action is generated)
2363 ! isn't. (Except that these are over-ridden by the player-set lookmode.)
2364 ! ----------------------------------------------------------------------------
2366 [ LMode1Sub; lookmode=1; L__M(##LMode1); ]; ! Brief
2368 [ LMode2Sub; lookmode=2; L__M(##LMode2); ]; ! Verbose
2370 [ LMode3Sub; lookmode=3; L__M(##LMode3); ]; ! Superbrief
2372 [ LModeNormalSub; ! 'normal' value: the default, or as set in Initialise()
2373 switch (initial_lookmode) {
2376 default: <<LMode2>>;
2380 [ NoteArrival descin;
2381 if (location ~= lastdesc) {
2382 if (location.initial) PrintOrRun(location, initial);
2383 if (location == thedark) { lastdesc = thedark; return; }
2385 if(NewRoom() == false) LibraryExtensions.RunAll(ext_newroom);
2391 prev_location = real_location;
2395 if (location hasnt visited) {
2396 give location visited;
2397 if (location has scored) {
2398 score = score + ROOM_SCORE;
2399 places_score = places_score + ROOM_SCORE;
2404 [ FindVisibilityLevels visibility_levels;
2405 visibility_levels = 1;
2406 visibility_ceiling = parent(player);
2407 while ((parent(visibility_ceiling)) &&
2408 (visibility_ceiling hasnt container || visibility_ceiling has open or transparent)) {
2409 visibility_ceiling = parent(visibility_ceiling);
2410 visibility_levels++;
2412 return visibility_levels;
2415 [ LookSub allow_abbrev visibility_levels i j k nl_flag;
2416 if (parent(player) == 0) return RunTimeError(10);
2420 if (location == thedark) { visibility_ceiling = thedark; NoteArrival(); }
2422 visibility_levels = FindVisibilityLevels();
2423 if (visibility_ceiling == location) {
2425 if (visibility_ceiling ~= location) jump MovedByInitial;
2428 ! Printing the top line: e.g.
2429 ! Octagonal Room (on the table) (as Frodo)
2431 #Ifdef TARGET_ZCODE;
2433 #Ifnot; ! TARGET_GLULX;
2434 glk_set_style(style_Subheader);
2436 if (visibility_levels == 0) print (name) thedark;
2438 if (visibility_ceiling ~= location) print (The) visibility_ceiling;
2439 else print (name) visibility_ceiling;
2441 #Ifdef TARGET_ZCODE;
2443 #Ifnot; ! TARGET_GLULX;
2444 glk_set_style(style_Normal);
2447 for (j=1,i=parent(player) : j<visibility_levels : j++,i=parent(i))
2448 if (i has supporter) L__M(##Look, 1, i);
2449 else L__M(##Look, 2, i);
2451 if (print_player_flag == 1) L__M(##Look, 3, player);
2454 ! The room description (if visible)
2456 if (lookmode < 3 && visibility_ceiling == location) {
2457 if ((allow_abbrev ~= 1) || (lookmode == 2) || (location hasnt visited)) {
2458 if (location.&describe) RunRoutines(location, describe);
2460 if (location.description == 0) RunTimeError(11, location, description);
2461 else PrintOrRun(location, description);
2466 if (visibility_ceiling == location) nl_flag = 1;
2468 if (visibility_levels == 0) Locale(thedark);
2470 for (i=player,j=visibility_levels : j>0 : j--,i=parent(i)) give i workflag;
2472 for (j=visibility_levels : j>0 : j--) {
2473 for (i=player,k=0 : k<j : k++) i=parent(i);
2474 if (i.inside_description) {
2475 if (nl_flag) new_line; else nl_flag = 1;
2476 PrintOrRun(i,inside_description);
2478 if (Locale(i)) nl_flag=1;
2482 if(LookRoutine() == false) LibraryExtensions.RunAll(ext_lookroutine);
2489 if (location == thedark) return L__M(##Examine, 1, noun);
2490 i = noun.description;
2492 if (noun has container)
2493 if (noun has open or transparent) <<Search noun, actor>>;
2494 else return L__M(##Search, 5, noun);
2495 if (noun has switchable) { L__M(##Examine, 3, noun); rfalse; }
2496 return L__M(##Examine, 2, noun);
2498 i = PrintOrRun(noun, description);
2499 if (i == 0 && noun has switchable) L__M(##Examine, 3, noun);
2504 if (location == thedark) return L__M(##LookUnder, 1, noun);
2505 L__M(##LookUnder, 2);
2508 [ VisibleContents o i f;
2509 objectloop (i in o) if (i hasnt concealed or scenery) f++;
2514 if (location == thedark) return L__M(##Search, 1, noun);
2515 if (ObjectIsUntouchable(noun)) return;
2516 f = VisibleContents(noun);
2517 if (noun has supporter) {
2518 if (f == 0) return L__M(##Search, 2, noun);
2519 return L__M(##Search, 3, noun);
2521 if (noun hasnt container) return L__M(##Search, 4, noun);
2522 if (noun hasnt transparent or open && ImplicitOpen(noun)) return L__M(##Search, 5, noun);
2523 if (AfterRoutines()) return;
2525 if (f == 0) return L__M(##Search, 6, noun);
2526 L__M(##Search, 7, noun);
2529 ! ----------------------------------------------------------------------------
2530 ! Verbs which change the state of objects without moving them
2531 ! ----------------------------------------------------------------------------
2534 if (ObjectIsUntouchable(noun)) return;
2535 if (noun hasnt lockable) return L__M(##Unlock, 1, noun);
2536 if (noun hasnt locked) return L__M(##Unlock, 2, noun);
2537 if ((noun.with_key ofclass Object && noun.with_key ~= second) ||
2538 (noun.with_key ofclass Routine && noun.with_key() ~= second) ||
2539 noun.with_key == nothing)
2540 return L__M(##Unlock, 3, second);
2544 if (AfterRoutines() || keep_silent) return;
2545 L__M(##Unlock, 4, noun);
2549 if (ObjectIsUntouchable(noun)) return;
2550 if (noun hasnt lockable) return L__M(##Lock, 1, noun);
2551 if (noun has locked) return L__M(##Lock, 2 ,noun);
2552 if (noun has open && ImplicitClose(noun)) return L__M(##Lock, 3, noun);
2553 if ((noun.with_key ofclass Object && noun.with_key ~= second) ||
2554 (noun.with_key ofclass Routine && noun.with_key() ~= second) ||
2555 noun.with_key == nothing)
2556 return L__M(##Lock, 4, second);
2559 if (AfterRoutines() || keep_silent) return;
2560 L__M(##Lock, 5, noun);
2564 if (ObjectIsUntouchable(noun)) return;
2565 if (noun hasnt switchable) return L__M(##SwitchOn, 1, noun);
2566 if (noun has on) return L__M(##SwitchOn, 2, noun);
2569 if (AfterRoutines() || keep_silent) return;
2570 L__M(##SwitchOn, 3, noun);
2574 if (ObjectIsUntouchable(noun)) return;
2575 if (noun hasnt switchable) return L__M(##SwitchOff, 1, noun);
2576 if (noun hasnt on) return L__M(##SwitchOff, 2, noun);
2579 if (AfterRoutines() || keep_silent) return;
2580 L__M(##SwitchOff, 3, noun);
2584 if (ObjectIsUntouchable(noun)) return;
2585 if (noun hasnt openable) return L__M(##Open, 1, noun);
2586 if (noun has locked && ImplicitUnlock(noun)) return L__M(##Open, 2, noun);
2587 if (noun has open) return L__M(##Open, 3, noun);
2590 if (keep_silent || AfterRoutines()) return;
2592 if (noun hasnt container)
2593 return L__M(##Open, 5, noun);
2595 if ((noun has container && location ~= thedark && VisibleContents(noun)
2596 && IndirectlyContains(noun, player)) == 0) {
2597 if (noun hasnt transparent && noun hasnt door) return L__M(##Open, 4, noun);
2599 L__M(##Open, 5, noun);
2603 if (ObjectIsUntouchable(noun)) return;
2604 if (noun hasnt openable) return L__M(##Close, 1, noun);
2605 if (noun hasnt open) return L__M(##Close, 2, noun);
2608 if (AfterRoutines() || keep_silent) return;
2609 L__M(##Close, 3, noun);
2613 if (ObjectIsUntouchable(noun)) return;
2614 if (noun hasnt clothing) return L__M(##Disrobe,1, noun);
2615 if (noun hasnt worn && noun has clothing) return L__M(##Disrobe, 1, noun);
2618 if (AfterRoutines() || keep_silent) return;
2619 L__M(##Disrobe, 2, noun);
2623 if (ObjectIsUntouchable(noun)) return;
2624 if (noun hasnt clothing) return L__M(##Wear, 1, noun);
2626 if (noun notin actor && noun hasnt worn) {
2627 if (IndirectlyContains(actor, noun) || parent(noun) has container or supporter) {
2628 if (no_implicit_actions) return L__M(##Wear, 5, noun, parent(noun));
2629 L__M(##Miscellany, 58, noun, parent(noun));
2630 AttemptToTakeObject(noun);
2632 return L__M(##Wear, 2, noun, parent(noun));
2634 if (noun has worn) return L__M(##Wear, 3, noun);
2637 if (AfterRoutines() || keep_silent) return;
2638 L__M(##Wear, 4, noun);
2642 if (ObjectIsUntouchable(noun)) return;
2643 if (noun hasnt edible) return L__M(##Eat, 1, noun);
2644 if (noun has worn && ImplicitDisrobe(noun)) return;
2647 if (AfterRoutines() || keep_silent) return;
2648 L__M(##Eat, 2, noun);
2651 ! ----------------------------------------------------------------------------
2652 ! Verbs which are really just stubs (anything which happens for these
2653 ! actions must happen in before rules)
2654 ! ----------------------------------------------------------------------------
2657 if (parent(second) ~= Compass) return L__M(##PushDir, 2, noun);
2658 if (second == u_obj or d_obj) return L__M(##PushDir, 3, noun);
2659 AfterRoutines(); i = noun; move i to actor;
2661 if (location == thedark) move i to real_location;
2662 else move i to location;
2666 if (second && RunLife(second,##Answer)) rfalse;
2667 L__M(##Answer, 1, noun);
2671 if (RunLife(noun,##Ask)) rfalse;
2672 L__M(##Ask, 1, noun);
2676 if (noun == player) <<Inv, actor>>;
2677 L__M(##Order, 1, noun);
2680 [ AskToSub; L__M(##Order, 1, noun); ];
2683 if (ObjectIsUntouchable(noun)) return;
2684 if (noun has animate && RunLife(noun, ##Attack)) rfalse;
2685 L__M(##Attack, 1, noun);
2688 [ BlowSub; L__M(##Blow, 1, noun); ];
2691 if (noun has animate) return L__M(##Burn, 2, noun);
2692 L__M(##Burn, 1, noun);
2695 [ BuySub; L__M(##Buy, 1, noun); ];
2698 if (noun has animate) return L__M(##Climb, 2, noun);
2699 L__M(##Climb, 1, noun);
2702 [ ConsultSub; L__M(##Consult, 1, noun); ];
2705 if (noun has animate) return L__M(##Cut, 2, noun);
2706 L__M(##Cut, 1, noun);
2709 [ DigSub; L__M(##Dig, 1, noun); ];
2711 [ DrinkSub; L__M(##Drink, 1, noun); ];
2714 if (second == nothing) return L__M(##Fill, 1, noun);
2715 L__M(##Fill, 2, noun, second);
2718 [ JumpSub; L__M(##Jump, 1, noun); ];
2721 if (noun has animate) return L__M(##JumpIn, 2, noun);
2722 if (noun has enterable) <<Enter noun>>;
2723 L__M(##JumpIn, 1, noun);
2727 if (noun has animate) return L__M(##JumpOn, 2, noun);
2728 if (noun has enterable && noun has supporter) <<Enter noun>>;
2729 L__M(##JumpOn, 1, noun);
2733 if (noun has animate) return L__M(##JumpOver, 2, noun);
2734 L__M(##JumpOver, 1, noun);
2738 if (ObjectIsUntouchable(noun)) return;
2739 if (RunLife(noun, ##Kiss)) return;
2740 if (noun == actor) return L__M(##Touch, 3, noun);
2741 L__M(##Kiss, 1, noun);
2744 [ ListenSub; L__M(##Listen, 1, noun); ];
2746 [ MildSub; L__M(##Mild, 1, noun); ];
2748 [ NoSub; L__M(##No); ];
2750 [ PraySub; L__M(##Pray, 1, noun); ];
2753 if (ObjectIsUntouchable(noun)) return;
2754 if (noun == player) return L__M(##Pull, 1, noun);
2755 if (noun == actor) return L__M(##Pull, 6, noun);
2756 if (noun has static) return L__M(##Pull, 2, noun);
2757 if (noun has scenery) return L__M(##Pull, 3, noun);
2758 if (noun has animate) return L__M(##Pull, 5, noun);
2759 L__M(##Pull, 4, noun);
2763 if (ObjectIsUntouchable(noun)) return;
2764 if (noun == player) return L__M(##Push, 1, noun);
2765 if (noun == actor) return L__M(##Push, 5, noun);
2766 if (noun has static) return L__M(##Push, 2, noun);
2767 if (noun has scenery) return L__M(##Push, 3, noun);
2768 if (noun has animate) return L__M(##Push, 5, noun);
2769 L__M(##Push, 4, noun);
2772 [ PushDirSub; L__M(##PushDir, 1, noun); ];
2775 if (ObjectIsUntouchable(noun)) return;
2776 if (noun has animate) return L__M(##Rub, 2, noun);
2777 L__M(##Rub, 1, noun);
2780 [ SetSub; L__M(##Set, 1, noun); ];
2782 [ SetToSub; L__M(##SetTo, 1, noun); ];
2784 [ SingSub; L__M(##Sing, 1, noun); ];
2786 [ SleepSub; L__M(##Sleep, 1, noun); ];
2789 if (noun ~= nothing && noun has animate) return L__M(##Smell, 2, noun);
2790 L__M(##Smell, 1, noun);
2793 [ SorrySub; L__M(##Sorry, 1, noun); ];
2796 if (ObjectIsUntouchable(noun)) return;
2797 if (noun has animate && noun ~= player) return L__M(##Squeeze, 1, noun);
2798 L__M(##Squeeze, 2, noun);
2801 [ StrongSub; L__M(##Strong, 1, noun); ];
2803 [ SwimSub; L__M(##Swim, 1, noun); ];
2805 [ SwingSub; L__M(##Swing, 1, noun); ];
2808 if (ObjectIsUntouchable(noun)) return;
2809 if (noun has animate) return L__M(##Taste, 2, noun);
2810 L__M(##Taste, 1, noun);
2814 if (noun == actor) return L__M(##Tell, 1, noun);
2815 if (RunLife(noun, ##Tell)) return;
2816 L__M(##Tell, 2, noun);
2819 [ ThinkSub; L__M(##Think, 1, noun); ];
2822 if (ObjectIsUntouchable(noun)) return;
2823 if (second == nothing) return L__M(##ThrowAt, 1, noun);
2825 action = ##ThrownAt;
2826 if (RunRoutines(second, before)) { action = ##ThrowAt; rtrue; }
2829 if (noun has worn && ImplicitDisrobe(noun)) return;
2830 if (second hasnt animate) return L__M(##ThrowAt, 1, noun);
2831 if (RunLife(second, ##ThrowAt)) return;
2832 L__M(##ThrowAt, 2, noun);
2836 if (noun has animate) return L__M(##Tie, 2, noun);
2837 L__M(##Tie, 1, noun);
2841 if (noun == actor) return L__M(##Touch, 3, noun);
2842 if (ObjectIsUntouchable(noun)) return;
2843 if (noun has animate) return L__M(##Touch, 1, noun);
2844 L__M(##Touch, 2,noun);
2848 if (ObjectIsUntouchable(noun)) return;
2849 if (noun == player) return L__M(##Turn, 1, noun);
2850 if (noun == actor) return L__M(##Turn, 5, noun);
2851 if (noun has static) return L__M(##Turn, 2, noun);
2852 if (noun has scenery) return L__M(##Turn, 3, noun);
2853 if (noun has animate) return L__M(##Turn, 5, noun);
2854 L__M(##Turn, 4, noun);
2858 if (AfterRoutines()) rtrue;
2859 L__M(##Wait, 1, noun);
2862 [ WakeSub; L__M(##Wake, 1, noun); ];
2865 if (ObjectIsUntouchable(noun)) return;
2866 if (RunLife(noun, ##WakeOther)) return;
2867 L__M(##WakeOther, 1, noun);
2871 if (noun == player) return L__M(##Wave, 2 ,noun, second);
2872 if (noun == actor) return L__M(##Wave, 3, noun, second);
2873 if (ImplicitTake(noun) && noun notin actor) return L__M(##Wave, 1, noun);
2874 L__M(##Wave, 2, noun, second);
2878 if (noun) return L__M(##WaveHands, 2, noun);
2879 L__M(##WaveHands, 1, noun); ];
2881 [ YesSub; L__M(##Yes); ];
2883 ! ----------------------------------------------------------------------------
2885 ! ----------------------------------------------------------------------------
2889 [ TraceOnSub; parser_trace = 1; "[Trace on.]"; ];
2892 parser_trace = noun;
2893 print "[Parser tracing set to level ", parser_trace, ".]^";
2896 [ TraceOffSub; parser_trace = 0; "Trace off."; ];
2899 debug_flag = debug_flag | DEBUG_MESSAGES;
2900 "[Message listing on.]";
2904 debug_flag = debug_flag & ~DEBUG_MESSAGES;
2905 "[Message listing off.]";
2908 [ RoutinesVerboseSub;
2909 debug_flag = debug_flag | (DEBUG_VERBOSE|DEBUG_MESSAGES);
2910 "[Verbose message listing on.]";
2914 debug_flag = debug_flag | DEBUG_ACTIONS;
2915 "[Action listing on.]";
2919 debug_flag = debug_flag & ~DEBUG_ACTIONS;
2920 "[Action listing off.]";
2924 debug_flag = debug_flag | DEBUG_TIMERS;
2925 "[Timers listing on.]";
2929 debug_flag = debug_flag & ~DEBUG_TIMERS;
2930 "[Timers listing off.]";
2935 [ ChangesOnSub; debug_flag = debug_flag | DEBUG_CHANGES; "[Changes listing on.]"; ];
2936 [ ChangesOffSub; debug_flag = debug_flag & ~DEBUG_CHANGES; "[Changes listing off.]"; ];
2940 [ ChangesOnSub; "[Changes listing available only from Inform 6.2 onwards.]"; ];
2942 [ ChangesOffSub; "[Changes listing available only from Inform 6.2 onwards.]"; ];
2946 #Ifdef TARGET_ZCODE;
2950 "[Random number generator now predictable.]";
2953 #Ifnot; ! TARGET_GLULX;
2957 "[Random number generator now predictable.]";
2962 [ XTestMove obj dest;
2963 if (~~obj ofclass Object) "[Not an object.]";
2964 if (~~dest ofclass Object) "[Destination not an object.]";
2965 if ((obj <= InformLibrary) || (obj == LibraryMessages) || (obj in 1))
2966 "[Can't move ", (name) obj, ": it's a system object.]";
2968 if (dest == obj) "[Can't move ", (name) obj, ": it would contain itself.]";
2969 dest = parent(dest);
2975 if (XTestMove(noun, player)) return;
2976 move noun to player; give noun moved ~concealed;
2981 if (XTestMove(noun, second)) return;
2982 move noun to second;
2987 if (parent(obj) == 0) print (name) obj; else print (a) obj;
2988 print " (", obj, ") ";
2989 if (f && parent(obj))
2990 print "in ~", (name) parent(obj), "~ (", parent(obj), ")";
2992 if (child(obj) == 0) rtrue;
2993 if (obj == Class) ! ???
2994 WriteListFrom(child(obj), NEWLINE_BIT+INDENT_BIT+ALWAYS_BIT+ID_BIT+NOARTICLE_BIT, 1);
2996 WriteListFrom(child(obj), NEWLINE_BIT+INDENT_BIT+ALWAYS_BIT+ID_BIT+FULLINV_BIT, 1);
3000 if (noun && ~~noun ofclass Object) "[Not an object.]";
3003 if (i ofclass Object && parent(i) == 0) XObj(i);
3005 else XObj(noun, true);
3009 if ((~~noun ofclass Object) || parent(noun)) "[Not a safe place.]";
3014 if (~~noun ofclass Object) "[Not a safe place.]";
3016 while (parent(x)) x = parent(x);
3020 [ Print_ScL obj; print_ret ++x_scope_count, ": ", (a) obj, " (", obj, ")"; ];
3023 if (noun && ~~noun ofclass Object) "[Not an object.]";
3025 LoopOverScope(Print_ScL, noun);
3026 if (x_scope_count == 0) "Nothing is in scope.";
3029 #Ifdef TARGET_GLULX;
3031 [ GlkListSub id val;
3032 id = glk_window_iterate(0, gg_arguments);
3034 print "Window ", id, " (", gg_arguments-->0, "): ";
3035 val = glk_window_get_type(id);
3039 3: print "textbuffer";
3040 4: print "textgrid";
3041 5: print "graphics";
3042 default: print "unknown";
3044 val = glk_window_get_parent(id);
3045 if (val) print ", parent is window ", val;
3046 else print ", no parent (root)";
3047 val = glk_window_get_stream(id);
3048 print ", stream ", val;
3049 val = glk_window_get_echo_stream(id);
3050 if (val) print ", echo stream ", val;
3052 id = glk_window_iterate(id, gg_arguments);
3054 id = glk_stream_iterate(0, gg_arguments);
3056 print "Stream ", id, " (", gg_arguments-->0, ")^";
3057 id = glk_stream_iterate(id, gg_arguments);
3059 id = glk_fileref_iterate(0, gg_arguments);
3061 print "Fileref ", id, " (", gg_arguments-->0, ")^";
3062 id = glk_fileref_iterate(id, gg_arguments);
3064 val = glk_gestalt(gestalt_Sound, 0);
3066 id = glk_schannel_iterate(0, gg_arguments);
3068 print "Soundchannel ", id, " (", gg_arguments-->0, ")^";
3069 id = glk_schannel_iterate(id, gg_arguments);
3078 ! ----------------------------------------------------------------------------
3079 ! Finally: the mechanism for library text (the text is in the language defn)
3080 ! ----------------------------------------------------------------------------
3082 [ L__M act n x1 x2 s;
3083 if (keep_silent == 2) return;
3097 if (RunRoutines(LibraryMessages, before)) { action = s; rfalse; }
3098 if (LibraryExtensions.RunWhile(ext_messages, false )) { action = s; rfalse; }
3100 LanguageLM(n, x1, x2);
3103 ! ==============================================================================
3105 Undef LIBRARY_STAGE; Constant LIBRARY_STAGE = AFTER_VERBLIB;
3107 #Ifnot; ! LIBRARY_STAGE < AFTER_VERBLIB but ~= AFTER_PARSER
3108 ! (this shouldn't happen because if 'parser' isn't there, LIBRARY_STAGE isn't defined)
3109 Message "Error: 'parser' needs to be correctly included before including 'verblib'. This will cause a big number of errors!";
3112 #Ifnot; ! LIBRARY_STAGE >= AFTER_VERBLIB: already included
3113 Message "Warning: 'verblib' included twice; ignoring second inclusion. (Ignore this if this is on purpose.)";
3116 #Ifnot; ! LIBRARY_STAGE is not defined (likely, 'parser' hasn't been included)
3117 Message "Error: 'parser' needs to be correctly included before including 'verblib'. This will cause a big number of errors!";
3120 ! ==============================================================================