1 ! ==============================================================================
2 ! VERBLIBM
: Core of standard verbs library
.
4 ! Supplied
for use with Inform
6 -- Release
6.12.1 -- Serial number
160605
6 ! Copyright Graham Nelson
1993-2004 and David Griffith
2012-2016
8 ! This code is licensed under either the traditional Inform license as
9 ! described by the DM4
or the Artistic License version
2.0. See the
10 ! file COPYING in the distribution archive
or at
11 ! https
://github.com/DavidGriffith/inform6lib/
13 ! This file is automatically Included in your game file by
"VerbLib".
14 ! ==============================================================================
20 Constant Grammar__Version
2;
25 ! ------------------------------------------------------------------------------
28 #Ifdef LanguageBanner;
30 i
= 0; ! suppress warning
34 #IfV5; style bold; #Endif;
35 print
"^", (string
) Story
;
36 #IfV5; style roman; #Endif;
37 #Ifnot; ! TARGET_GLULX;
38 glk_set_style(style_Header
);
39 print
"^", (string
) Story
;
40 glk_set_style(style_Normal
);
43 if (Headline
) print (string
) Headline
;
45 print
"Release ", (HDR_GAMERELEASE
-->0) & $
03ff
, " / Serial number ";
46 for (i
=0 : i
<6 : i
++) print (char) HDR_GAMESERIAL
->i
;
47 #Ifnot; ! TARGET_GLULX;
49 @aloads ROM_GAMERELEASE
0 i
;
51 print
" / Serial number ";
52 for (i
=0 : i
<6 : i
++) print (char) ROM_GAMESERIAL
->i
;
54 print
" / Inform v"; inversion
;
55 print
" Library v", (string
) LibRelease
, " ";
67 #Endif; ! LanguageBanner
71 #Ifdef LanguageVersionSub;
73 ix
= 0; ! suppress warning
77 ix
= 0; ! shut up compiler warning
78 if (standard_interpreter
> 0) {
79 print
"Standard interpreter ", standard_interpreter
/256, ".", standard_interpreter
%256,
80 " (", HDR_TERPNUMBER
->0;
81 #Iftrue (#version_number == 6);
82 print (char) '.', HDR_TERPVERSION
->0;
84 print (char) HDR_TERPVERSION
->0;
89 print
"Interpreter ", HDR_TERPNUMBER
->0, " Version ";
90 #Iftrue (#version_number == 6);
91 print HDR_TERPVERSION
->0;
93 print (char) HDR_TERPVERSION
->0;
98 #Ifnot; ! TARGET_GLULX;
100 print
"Interpreter version ", ix
/ $
10000, ".", (ix
& $FF00
) / $
100,
101 ".", ix
& $FF
, " / ";
103 print
"VM ", ix
/ $
10000, ".", (ix
& $FF00
) / $
100, ".", ix
& $FF
, " / ";
105 print
"Library serial number ", (string
) LibSerial
, "^";
106 #Ifdef LanguageVersion;
107 print (string
) LanguageVersion
, "^";
108 #Endif; ! LanguageVersion
109 #Endif; ! LanguageVersionSub
112 [ RunTimeError n p1 p2
;
113 #Ifdef LanguageError;
114 LanguageError(n
, p1
, p2
);
117 print
"** Library error ", n
, " (", p1
, ", ", p2
, ") **^** ";
119 1: print
"preposition not found (this should not occur)";
120 2: print
"Property value not routine or string: ~", (property
) p2
, "~ of ~", (name
) p1
,
122 3: print
"Entry in property list not routine or string: ~", (property
) p2
, "~ list of ~",
123 (name
) p1
, "~ (", p1
, ")";
124 4: print
"Too many timers/daemons are active simultaneously.
125 The limit is the library constant MAX_TIMERS
126 (currently ", MAX_TIMERS
, ") and should be increased";
127 5: print
"Object ~", (name
) p1
, "~ has no ~", (property
) p2
, "~ property";
128 7: print
"The object ~", (name
) p1
, "~ can only be used as a player object if it has
129 the ~number~ property";
130 8: print
"Attempt to take random entry from an empty table array";
131 9: print p1
, " is not a valid direction property number";
132 10: print
"The player-object is outside the object tree";
133 11: print
"The room ~", (name
) p1
, "~ has no ~", (property
) p2
, "~ property";
134 12: print
"Tried to set a non-existent pronoun using SetPronoun";
135 13: print
"A 'topic' token can only be followed by a preposition";
136 14: print
"Overflowed buffer limit of ", p1
, " using '@@64output_stream 3' ", (string
) p2
;
137 15: print
"LoopWithinObject broken because the object ", (name
) p1
, " was moved while the loop passed through it.";
138 16: print
"Attempt to use illegal narrative_voice of ", p1
, ".";
140 print
"(unexplained)";
144 "** Library error ", n
, " (", p1
, ", ", p2
, ") **";
146 #Endif; ! LanguageError
149 ! ----------------------------------------------------------------------------
150 ! The WriteListFrom routine
, a flexible object
-lister taking care of
151 ! plurals
, inventory information
, various formats
and so on
. This is used
152 ! by everything in the library which ever wants to list anything
.
154 ! If there were no objects to list
, it prints nothing
and returns
false;
155 ! otherwise it returns
true.
157 ! o is the object
, and style is a bitmap
, whose bits are given by
:
158 ! ----------------------------------------------------------------------------
161 Constant NEWLINE_BIT $
0001; ! New
-line after each entry
162 Constant INDENT_BIT $
0002; ! Indent each entry by depth
163 Constant FULLINV_BIT $
0004; ! Full inventory information after entry
164 Constant ENGLISH_BIT $
0008; ! English sentence style
, with commas
and and
165 Constant RECURSE_BIT $
0010; ! Recurse downwards with usual rules
166 Constant ALWAYS_BIT $
0020; ! Always recurse downwards
167 Constant TERSE_BIT $
0040; ! More terse English style
168 Constant PARTINV_BIT $
0080; ! Only brief inventory information after entry
169 Constant DEFART_BIT $
0100; ! Use the definite article in list
170 Constant WORKFLAG_BIT $
0200; ! At top
level (only
), only list objects
171 ! which have the
"workflag" attribute
172 Constant ISARE_BIT $
0400; ! Print
" is" or " are" before list
173 Constant CONCEAL_BIT $
0800; ! Omit objects with
"concealed" or "scenery":
174 ! if WORKFLAG_BIT also set
, then does _not_
175 ! apply at top level
, but does lower down
176 Constant NOARTICLE_BIT $
1000; ! Print no articles
, definite
or not
177 Constant ID_BIT $
2000; ! Print object id after each entry
179 [ NextEntry o odepth
;
182 if (o
== 0) return 0;
183 if (lt_value
&& o
.list_together
~= lt_value
) continue;
184 if (c_style
& WORKFLAG_BIT
&& odepth
==0 && o hasnt workflag
) continue;
185 if (c_style
& CONCEAL_BIT
&& (o has concealed
|| o has scenery
)) continue;
191 if (c_style
& ALWAYS_BIT
) rtrue
;
192 if (c_style
& RECURSE_BIT
== 0) rfalse
;
193 if ((o has transparent
or supporter
) || (o has container
&& o has open
)) rtrue
;
198 if (child(o1
) && WillRecurs(o1
)) rfalse
;
199 if (child(o2
) && WillRecurs(o2
)) rfalse
;
200 if (c_style
& (FULLINV_BIT
+ PARTINV_BIT
)) {
201 if ((o1 hasnt worn
&& o2 has worn
) || (o2 hasnt worn
&& o1 has worn
)) rfalse
;
202 if ((o1 hasnt light
&& o2 has light
) || (o2 hasnt light
&& o1 has light
)) rfalse
;
203 if (o1 has container
) {
204 if (o2 hasnt container
) rfalse
;
205 if ((o1 has open
&& o2 hasnt open
) || (o2 has open
&& o1 hasnt open
))
208 else if (o2 has container
)
211 return Identical(o1
, o2
);
214 [ SortTogether obj value
;
215 ! print
"Sorting together possessions of ", (object
) obj
, " by value ", value
, "^";
216 ! for (x
=child(obj
) : x
: x
=sibling(x
))
217 ! print (the
) x
, " no: ", x
, " lt: ", x
.list_together
, "^";
219 if (child(obj
).list_together
~= value
) move
child(obj
) to out_obj
;
220 else move
child(obj
) to in_obj
;
222 while (child(in_obj
)) move
child(in_obj
) to obj
;
223 while (child(out_obj
)) move
child(out_obj
) to obj
;
226 [ SortOutList obj i k l
;
227 ! print
"^^Sorting out list from ", (name
) obj
, "^ ";
228 ! for (i
=child(location
) : i
: i
=sibling(i
))
229 ! print (name
) i
, " --> ";
234 for (i
=obj
: i
: i
=sibling(i
)) {
237 ! print
"Scanning ", (name
) i
, " with lt=", k
, "^";
238 for (i
=sibling(i
) : i
&& i
.list_together
== k
:) i
= sibling(i
);
240 ! print
"First not in block is ", (name
) i
, " with lt=", i
.list_together
, "^";
241 for (l
=sibling(i
) : l
: l
=sibling(l
))
242 if (l
.list_together
== k
) {
243 SortTogether(parent(obj
), k
);
244 ! print
"^^After ST:^ ";
245 ! for (i
=child(location
) : i
: i
=sibling(i
))
246 ! print (name
) i
, " --> ";
248 obj
= child(parent(obj
));
257 [ Print__Spaces n
; ! To avoid a bug occurring in Inform
6.01 to
6.10
262 #Ifnot; ! TARGET_GLULX;
273 [ WriteListFrom o style depth
276 if (o
== nothing
) return 0;
278 s1
= c_style
; s2
= lt_value
; s3
= listing_together
;
279 s4
= listing_size
; s5
= wlf_indent
; s6
= inventory_stage
;
281 if (o
== child(parent(o
))) {
283 o
= child(parent(o
));
287 if (WriteListR(o
, depth
) == 0) return 0;
289 c_style
= s1
; lt_value
= s2
; listing_together
= s3
;
290 listing_size
= s4
; wlf_indent
= s5
; inventory_stage
= s6
;
294 [ WriteListR o depth stack_pointer classes_p sizes_p i j k k2 l m n q senc mr
;
295 if (depth
> 0 && o
== child(parent(o
))) {
297 o
= child(parent(o
));
301 if (c_style
& WORKFLAG_BIT
&& depth
==0 && o hasnt workflag
) {
305 if (c_style
& CONCEAL_BIT
&& (o has concealed
|| o has scenery
)) {
311 classes_p
= match_classes
+ stack_pointer
;
312 sizes_p
= match_list
+ stack_pointer
;
314 for (i
=o
,j
=0 : i
&& (j
+stack_pointer
)<128 : i
=NextEntry(i
,depth
),j
++) {
319 if (c_style
& ISARE_BIT
) {
320 if (j
== 1 && o hasnt pluralname
) Tense(IS__TX
, WAS__TX
);
321 else Tense(ARE__TX
, WERE__TX
);
322 if (c_style
& NEWLINE_BIT
) print
":^";
323 else print (char) ' ';
324 c_style
= c_style
- ISARE_BIT
;
327 stack_pointer
= stack_pointer
+j
+1;
329 if (k
< 2) jump EconomyVersion
; ! It takes two to plural
331 for (i
=o
,k
=0 : k
<j
: i
=NextEntry(i
,depth
),k
++)
332 if (classes_p
->k
== 0) {
333 classes_p
->k
= n
; sizes_p
->n
= 1;
334 for (l
=NextEntry(i
,depth
),m
=k
+1 : l
&& m
<j
: l
=NextEntry(l
,depth
),m
++)
335 if (classes_p
->m
== 0 && i
.plural
&& l
.plural
~= 0) {
336 if (ListEqual(i
, l
) == 1) {
337 sizes_p
->n
= sizes_p
->n
+ 1;
345 for (i
=1,j
=o
,k
=0 : i
<=n
: i
++,senc
++) {
346 while (((classes_p
->k
) ~= i
) && ((classes_p
->k
) ~= -i
)) {
347 k
++; j
=NextEntry(j
, depth
);
352 if (j
.list_together
~= 0 or lt_value
&& metaclass(j
.list_together
) == Routine
or String
&&
353 j
.list_together
== mr
) senc
--;
354 mr
= j
.list_together
;
359 for (i
=1,j
=o
,k
=0,mr
=0 : senc
>=0 : i
++,senc
--) {
360 while (((classes_p
->k
) ~= i
) && ((classes_p
->k
) ~= -i
)) {
361 k
++; j
=NextEntry(j
, depth
);
363 if (j
.list_together
~= 0 or lt_value
) {
364 if (j
.list_together
== mr
) {
368 k2
= NextEntry(j
, depth
);
369 if (k2
== 0 || k2
.list_together
~= j
.list_together
) jump Omit_WL2
;
370 k2
= metaclass(j
.list_together
);
371 if (k2
== Routine
or String
) {
372 q
= j
; listing_size
= 1; l
= k
; m
= i
;
373 while (m
< n
&& q
.list_together
== j
.list_together
) {
375 while (((classes_p
->l
) ~= m
) && ((classes_p
->l
) ~= -m
)) {
376 l
++; q
= NextEntry(q
, depth
);
378 if (q
.list_together
== j
.list_together
) listing_size
++;
380 ! print
" [", listing_size
, "] ";
381 if (listing_size
== 1) jump Omit_WL2
;
382 if (c_style
& INDENT_BIT
) Print__Spaces(2*(depth
+wlf_indent
));
385 for (l
=0 : l
<listing_size
: l
++) q
= q
+sizes_p
->(l
+i
);
386 EnglishNumber(q
); print
" ";
387 print (string
) j
.list_together
;
388 if (c_style
& ENGLISH_BIT
) print
" (";
389 if (c_style
& INDENT_BIT
) print
":^";
394 parser_one
= j
; parser_two
= depth
+wlf_indent
;
395 if (RunRoutines(j
, list_together
) == 1) jump Omit__Sublist2
;
399 @push lt_value
; @push listing_together
; @push listing_size
;
400 #Ifnot; ! TARGET_GLULX;
401 @copy lt_value sp
; @copy listing_together sp
; @copy listing_size sp
;
404 lt_value
= j
.list_together
; listing_together
= j
; wlf_indent
++;
405 WriteListR(j
, depth
, stack_pointer
); wlf_indent
--;
408 @pull listing_size
; @pull listing_together
; @pull lt_value
;
409 #Ifnot; ! TARGET_GLULX;
410 @copy sp listing_size
;
411 @copy sp listing_together
;
416 if (q
& ENGLISH_BIT
) print
")";
420 parser_one
= j
; parser_two
= depth
+wlf_indent
;
421 RunRoutines(j
, list_together
);
426 if (q
& NEWLINE_BIT
&& c_style
& NEWLINE_BIT
== 0) new_line
;
428 mr
= j
.list_together
;
435 if (WriteBeforeEntry(j
, depth
, 0, senc
) == 1) jump Omit_FL2
;
436 if (sizes_p
->i
== 1) {
437 if (c_style
& NOARTICLE_BIT
) print (name
) j
;
439 if (c_style
& DEFART_BIT
) print (the
) j
;
442 if (c_style
& ID_BIT
) print
" (", j
, ")";
445 if (c_style
& DEFART_BIT
) PrefaceByArticle(j
, 1, sizes_p
->i
);
446 print (number
) sizes_p
->i
, " ";
447 PrintOrRun(j
, plural
, 1);
449 if (sizes_p
->i
> 1 && j hasnt pluralname
) {
451 WriteAfterEntry(j
, depth
, stack_pointer
);
455 WriteAfterEntry(j
,depth
,stack_pointer
);
459 if (c_style
& ENGLISH_BIT
) {
460 if (senc
== 1) print (SerialComma
) i
+senc
, (string
) AND__TX
;
461 if (senc
> 1) print (string
) COMMA__TX
;
470 for (i
=1,j
=o
: i
<=n
: j
=NextEntry(j
,depth
),i
++,senc
++) {
471 if (j
.list_together
~= 0 or lt_value
&& metaclass(j
.list_together
) == Routine
or String
&&
472 j
.list_together
==mr
) senc
--;
473 mr
= j
.list_together
;
476 for (i
=1,j
=o
,mr
=0 : i
<=senc
: j
=NextEntry(j
,depth
),i
++) {
477 if (j
.list_together
~= 0 or lt_value
) {
478 if (j
.list_together
== mr
) {
482 k
= NextEntry(j
, depth
);
483 if (k
== 0 || k
.list_together
~= j
.list_together
) jump Omit_WL
;
484 k
= metaclass(j
.list_together
);
485 if (k
== Routine
or String
) {
486 if (c_style
& INDENT_BIT
) Print__Spaces(2*(depth
+wlf_indent
));
490 q
= NextEntry(q
, depth
); l
++;
491 } until (q
== 0 || q
.list_together
~= j
.list_together
);
492 EnglishNumber(l
); print
" ";
493 print (string
) j
.list_together
;
494 if (c_style
& ENGLISH_BIT
) print
" (";
495 if (c_style
& INDENT_BIT
) print
":^";
500 parser_one
= j
; parser_two
= depth
+wlf_indent
;
501 if (RunRoutines(j
, list_together
) == 1) jump Omit__Sublist
;
505 @push lt_value
; @push listing_together
; @push listing_size
;
506 #Ifnot; ! TARGET_GLULX;
507 @copy lt_value sp
; @copy listing_together sp
; @copy listing_size sp
;
510 lt_value
= j
.list_together
; listing_together
= j
; wlf_indent
++;
511 WriteListR(j
, depth
, stack_pointer
); wlf_indent
--;
514 @pull listing_size
; @pull listing_together
; @pull lt_value
;
515 #Ifnot; ! TARGET_GLULX;
516 @copy sp listing_size
; @copy sp listing_together
; @copy sp lt_value
;
520 if (q
& ENGLISH_BIT
) print
")";
524 parser_one
= j
; parser_two
= depth
+wlf_indent
;
525 RunRoutines(j
, list_together
);
530 if (q
& NEWLINE_BIT
&& c_style
& NEWLINE_BIT
== 0) new_line
;
532 mr
= j
.list_together
;
539 if (WriteBeforeEntry(j
, depth
, i
, senc
) == 1) jump Omit_FL
;
540 if (c_style
& NOARTICLE_BIT
) print (name
) j
;
542 if (c_style
& DEFART_BIT
) print (the
) j
;
545 if (c_style
& ID_BIT
) print
" (", j
, ")";
546 WriteAfterEntry(j
, depth
, stack_pointer
);
550 if (c_style
& ENGLISH_BIT
) {
551 if (i
== senc
-1) print (SerialComma
) senc
, (string
) AND__TX
;
552 if (i
< senc
-1) print (string
) COMMA__TX
;
558 ]; ! end of WriteListR
560 [ WriteBeforeEntry o depth ipos sentencepos
564 if (c_style
& INDENT_BIT
) Print__Spaces(2*(depth
+wlf_indent
));
565 if (o
.invent
&& (c_style
& (PARTINV_BIT
|FULLINV_BIT
))) {
566 flag
= PrintOrRun(o
, invent
, 1);
568 if (c_style
& ENGLISH_BIT
) {
569 if (ipos
== sentencepos
-1)
570 print (SerialComma
) sentencepos
, (string
) AND__TX
;
571 if (ipos
< sentencepos
-1)
572 print (string
) COMMA__TX
;
574 if (c_style
& NEWLINE_BIT
) new_line
;
580 [ WriteAfterEntry o depth stack_p
581 p recurse_flag parenth_flag eldest_child child_count combo i j
;
584 if (c_style
& PARTINV_BIT
) {
585 if (o
.invent
&& RunRoutines(o
, invent
))
586 if (c_style
& NEWLINE_BIT
) ""; else rtrue
;
589 if (o has light
&& location hasnt light
) combo
=combo
+1;
590 if (o has container
&& o hasnt open
) combo
=combo
+2;
591 if ((o has container
&& (o has open
|| o has transparent
))) {
593 if (i hasnt concealed
&& i hasnt scenery
) {
597 if (~~j
) combo
=combo
+4;
599 if (combo
) L__M(##ListMiscellany, combo, o);
600 } ! end of PARTINV_BIT processing
602 if (c_style
& FULLINV_BIT
) {
603 if (o
.invent
&& RunRoutines(o
, invent
))
604 if (c_style
& NEWLINE_BIT
) ""; else rtrue
;
606 if (o has light
&& o has worn
) { L__M(##ListMiscellany, 8, o); parenth_flag = true; }
608 if (o has light
) { L__M(##ListMiscellany, 9, o); parenth_flag = true; }
609 if (o has worn
) { L__M(##ListMiscellany, 10, o); parenth_flag = true; }
613 if (o has openable
) {
614 if (parenth_flag
) print (string
) AND__TX
;
615 else L__M(##ListMiscellany, 11, o);
617 if (child(o
)) L__M(##ListMiscellany, 12, o);
618 else L__M(##ListMiscellany, 13, o);
620 if (o has lockable
&& o has locked
) L__M(##ListMiscellany, 15, o);
621 else L__M(##ListMiscellany, 14, o);
625 if (child(o
)==0 && o has transparent
)
626 if (parenth_flag
) L__M(##ListMiscellany, 16, o);
627 else L__M(##ListMiscellany, 17, o);
629 if (parenth_flag
) print
")";
630 } ! end of FULLINV_BIT processing
632 if (c_style
& CONCEAL_BIT
) {
635 if (p hasnt concealed
&& p hasnt scenery
) { child_count
++; eldest_child
= p
; }
637 else { child_count
= children(o
); eldest_child
= child(o
); }
639 if (child_count
&& (c_style
& ALWAYS_BIT
)) {
640 if (c_style
& ENGLISH_BIT
) L__M(##ListMiscellany, 18, o);
644 if (child_count
&& (c_style
& RECURSE_BIT
)) {
645 if (o has supporter
) {
646 if (c_style
& ENGLISH_BIT
) {
647 if (c_style
& TERSE_BIT
) L__M(##ListMiscellany, 19, o);
648 else L__M(##ListMiscellany, 20, o);
649 if (o has animate
) print (string
) WHOM__TX
;
650 else print (string
) WHICH__TX
;
654 if (o has container
&& (o has open
|| o has transparent
)) {
655 if (c_style
& ENGLISH_BIT
) {
656 if (c_style
& TERSE_BIT
) L__M(##ListMiscellany, 21, o);
657 else L__M(##ListMiscellany, 22, o);
658 if (o has animate
) print (string
) WHOM__TX
;
659 else print (string
) WHICH__TX
;
665 if (recurse_flag
&& (c_style
& ENGLISH_BIT
))
666 if (child_count
> 1 || eldest_child has pluralname
) Tense(ARE2__TX
, WERE2__TX
);
667 else Tense(IS2__TX
, WAS2__TX
);
669 if (c_style
& NEWLINE_BIT
) new_line
;
674 @push lt_value
; @push listing_together
; @push listing_size
;
675 #Ifnot; ! TARGET_GLULX;
676 @copy lt_value sp
; @copy listing_together sp
; @copy listing_size sp
;
678 lt_value
= 0; listing_together
= 0; listing_size
= 0;
679 WriteListR(o
, depth
+1, stack_p
);
681 @pull listing_size
; @pull listing_together
; @pull lt_value
;
682 #Ifnot; ! TARGET_GLULX;
683 @copy sp listing_size
; @copy sp listing_together
; @copy sp lt_value
;
685 if (c_style
& TERSE_BIT
) print
")";
689 ! ----------------------------------------------------------------------------
690 ! LoopWithinObject(rtn
,obj
,arg
)
692 ! rtn is the address of a user
-supplied routine
.
693 ! obj is an optional parent object whose dependents are to be processed
; the
694 ! default is the current
actor (normally the player
).
695 ! arg is an optional argument passed to the rtn
; this can be a single variable
696 ! or constant
, or the address of an
array (which enables multiple values to be
697 ! passed
and returned
).
699 ! For each object o which is a child
, grandchild
, great
-grandchild
, etc
, of the
700 ! original obj
, LoopWithinObject() calls
rtn(o
,arg
).
702 ! The rtn should perform any appropriate testing
or processing on each object o
,
703 ! using the optional arg value
if necessary
. If the rtn returns
true (or any
704 ! positive value
), the children of o
, if any
, are also tested
; those children
705 ! are skipped
if rtn returns
false. To terminate the loop before all objects
706 ! have been processed
, rtn should
return a large negative
number (eg
-99).
708 ! To deal with supporters
and open containers
, so that objects are processed
709 ! only
if they are accessible to the player
, rtn might end with these
711 ! if ((o has transparent
or supporter
) || (o has container
&& o has open
)) rtrue
;
713 ! or alternatively with
:
714 ! c_style
= RECURSE_BIT
; return WillRecurs(o
);
716 ! LoopWithinObject() returns the number of objects which have been processed
.
717 ! ----------------------------------------------------------------------------
719 [ LoopWithinObject rtn obj arg
721 if (obj
== 0) obj
= actor
;
725 x
= rtn(o
, arg
); ! user
-supplied routine returning x
.
726 ! if x
< 0: skip up to next parent
727 ! if x
= 0: jump across to next sibling
728 ! if x
> 0: continue down to child objects
729 if (y
~= parent(o
)) { RunTimeError(15, o
); rfalse
; }
730 if (x
> 0 && child(o
)) o
= child(o
);
733 if (++x
> 0 && sibling(o
)) { o
= sibling(o
); break; }
735 if (o
== obj
) return n
;
741 ! ----------------------------------------------------------------------------
742 ! Much better menus can be created
using one of the optional library
743 ! extensions
. These are provided
for compatibility with previous practice
:
744 ! ----------------------------------------------------------------------------
746 [ LowKey_Menu menu_choices EntryR ChoiceR lines main_title i j
;
753 main_title
= item_name
;
755 print
"--- "; print (string
) main_title
; print
" ---^^";
757 if (menu_choices ofclass Routine
) menu_choices();
758 else print (string
) menu_choices
;
761 L__M(##Miscellany, 52, lines);
768 read buffer parse DrawStatusLine
;
770 j
= parse
->1; ! number of words
771 #Ifnot; ! TARGET_GLULX;
772 KeyboardPrimitive(buffer
, parse
);
773 j
= parse
-->0; ! number of words
777 if (j
== 0 || (i
== QUIT1__WD
or QUIT2__WD
)) {
778 menu_nesting
--; if (menu_nesting
> 0) rfalse
;
779 if (deadflag
== 0) <<Look
>>;
783 if (i
== 0) jump LKRD
;
784 if (i
< 1 || i
> lines
) continue;
787 if (j
== 2) jump LKRD
;
796 [ DoMenu menu_choices EntryR ChoiceR
; LowKey_Menu(menu_choices
, EntryR
, ChoiceR
); ];
802 [ DoMenu menu_choices EntryR ChoiceR
803 lines main_title main_wid cl i j oldcl pkey ch cw y x
;
804 if (pretty_flag
== 0) return LowKey_Menu(menu_choices
, EntryR
, ChoiceR
);
808 main_title
= item_name
; main_wid
= item_width
;
815 #Iftrue (#version_number == 6);
817 ch
= HDR_FONTWUNITS
->0;
823 i
= HDR_SCREENWCHARS
->0;
828 #Iftrue (#version_number == 6);
830 cw
= HDR_FONTHUNITS
->0;
836 spaces(i
); j
=1+(i
/2-main_wid
)*cw
;
838 print (string
) main_title
;
839 y
=1+ch
; @set_cursor y
1; spaces(i
);
840 x
=1+cw
; @set_cursor y x
; print (string
) NKEY__TX
;
841 j
=1+(i
-13)*cw
; @set_cursor y j
; print (string
) PKEY__TX
;
842 y
=y
+ch
; @set_cursor y
1; spaces(i
);
843 @set_cursor y x
; print (string
) RKEY__TX
;
844 j
=1+(i
-18)*cw
; @set_cursor y j
;
846 if (menu_nesting
== 1) print (string
) QKEY1__TX
;
847 else print (string
) QKEY2__TX
;
850 @set_cursor y x
; font off
;
852 if (menu_choices ofclass String
) print (string
) menu_choices
;
859 y
=1+(oldcl
-1)*ch
; @set_cursor y x
; print
" ";
861 y
=1+(cl
-1)*ch
; @set_cursor y x
; print
">";
865 @read_char
1 -> pkey
;
866 if (pkey
== NKEY1__KY
or NKEY2__KY
or 130) {
867 cl
++; if (cl
== 7+lines
) cl
= 7; continue;
869 if (pkey
== PKEY1__KY
or PKEY2__KY
or 129) {
870 cl
--; if (cl
== 6) cl
= 6+lines
; continue;
872 if (pkey
== QKEY1__KY
or QKEY2__KY
or 27 or 131) break;
873 if (pkey
== 10 or 13 or 132) {
874 @set_window
0; font on
;
875 new_line
; new_line
; new_line
;
882 i
= HDR_SCREENWCHARS
->0; if ( i
== 0) i
= 80;
883 @set_window
1; @set_cursor
1 1; style reverse
; spaces(i
);
884 j
=1+(i
/2-item_width
)*cw
;
886 print (string
) item_name
;
887 style roman
; @set_window
0; new_line
;
890 if (i
== 2) jump ReDisplay
;
893 L__M(##Miscellany, 53);
894 @read_char
1 -> pkey
; jump ReDisplay
;
898 menu_nesting
--; if (menu_nesting
> 0) rfalse
;
899 font on
; @set_cursor
1 1;
900 @erase_window $ffff
; @set_window
0;
901 #Iftrue (#version_number == 6);
904 new_line
; new_line
; new_line
;
905 if (deadflag
== 0) <<Look
>>;
910 #Ifnot; ! TARGET_GLULX
912 [ DoMenu menu_choices EntryR ChoiceR
913 winwid winhgt lines main_title main_wid cl i oldcl pkey
;
915 if (pretty_flag
== 0 || gg_statuswin
== 0) return LowKey_Menu(menu_choices
, EntryR
, ChoiceR
);
920 main_title
= item_name
;
921 main_wid
= item_width
;
925 ! If we printed
"hit arrow keys" here
, it would be appropriate to
926 ! check
for the availability of Glk input keys
. But we actually
927 ! print
"hit N/P/Q". So it
's reasonable to silently accept Glk
928 ! arrow key codes as secondary options.
932 glk_window_clear(gg_statuswin);
933 glk_window_clear(gg_mainwin);
934 glk_set_window(gg_statuswin);
935 StatusLineHeight(lines+7);
936 glk_window_get_size(gg_statuswin, gg_arguments, gg_arguments+4);
937 winwid = gg_arguments-->0;
938 winhgt = gg_arguments-->1;
939 glk_set_style(style_Subheader);
940 glk_window_move_cursor(gg_statuswin, winwid/2-main_wid, 0);
941 print (string) main_title;
942 glk_window_move_cursor(gg_statuswin, 1, 1);
943 print (string) NKEY__TX;
944 glk_window_move_cursor(gg_statuswin, winwid-13, 1);
945 print (string) PKEY__TX;
946 glk_window_move_cursor(gg_statuswin, 1, 2);
947 print (string) RKEY__TX;
948 glk_window_move_cursor(gg_statuswin, winwid-18, 2);
949 if (menu_nesting == 1) print (string) QKEY1__TX;
950 else print (string) QKEY2__TX;
951 glk_set_style(style_Normal);
952 glk_window_move_cursor(gg_statuswin, 1, 4);
953 if (menu_choices ofclass String) print (string) menu_choices;
960 if (cl < 0 || cl >= lines) cl = 0;
962 glk_window_move_cursor(gg_statuswin, 3, oldcl+6);
966 glk_window_move_cursor(gg_statuswin, 3, oldcl+6);
969 pkey = KeyCharPrimitive(gg_statuswin, true);
970 if (pkey == $80000000) jump ReDisplay;
971 if (pkey == NKEY1__KY or NKEY2__KY or $fffffffb) {
973 if (cl >= lines) cl = 0;
976 if (pkey == PKEY1__KY or PKEY2__KY or $fffffffc) {
978 if (cl < 0) cl = lines-1;
981 if (pkey == QKEY1__KY or QKEY2__KY or $fffffff8 or $fffffffe) break;
982 if (pkey == $fffffffa or $fffffffd) {
983 glk_set_window(gg_mainwin);
984 new_line; new_line; new_line;
987 glk_window_clear(gg_statuswin);
988 glk_window_clear(gg_mainwin);
989 glk_set_window(gg_statuswin);
991 glk_window_get_size(gg_statuswin, gg_arguments, gg_arguments+4);
992 winwid = gg_arguments-->0;
993 winhgt = gg_arguments-->1;
994 glk_set_style(style_Subheader);
995 glk_window_move_cursor(gg_statuswin, winwid/2-item_width, 0);
996 print (string) item_name;
997 glk_set_style(style_Normal);
998 glk_set_window(gg_mainwin);
1001 if (i == 2) jump ReDisplay;
1003 L__M(##Miscellany, 53);
1004 pkey = KeyCharPrimitive(gg_mainwin, 1);
1009 ! done with this menu...
1011 if (menu_nesting > 0) rfalse;
1012 glk_set_window(gg_mainwin);
1013 glk_window_clear(gg_mainwin);
1014 new_line; new_line; new_line;
1015 if (deadflag == 0) <<Look>>;
1020 ! ----------------------------------------------------------------------------
1021 ! A cunning routine (which could have been a daemon, but isn't
, for the
1022 ! sake of efficiency
) to move objects which could be in many rooms about
1023 ! so that the player never catches one
not in place
1024 ! ----------------------------------------------------------------------------
1026 [ MoveFloatingObjects i k l m address flag
;
1027 if (location
== player
or nothing
) return;
1029 address
= i
.&found_in
;
1030 if (address
&& i hasnt non_floating
&& ~~IndirectlyContains(player
, i
)) {
1031 if (metaclass(address
-->0) == Routine
)
1032 flag
= i
.found_in();
1035 k
= i
.#found_in/WORDSIZE;
1036 for (l
=0 : l
<k
: l
++) {
1038 if ((m in Class
&& location ofclass m
) ||
1039 m
== location
|| m in location
) {
1046 if (i notin location
) move i to location
;
1048 if (parent(i
)) remove i
;
1054 ! ----------------------------------------------------------------------------
1055 ! Two little routines
for moving the player safely
.
1056 ! ----------------------------------------------------------------------------
1058 [ PlayerTo newplace flag
;
1060 move player to newplace
;
1061 while (parent(newplace
)) newplace
= parent(newplace
);
1062 location
= real_location
= newplace
;
1063 MoveFloatingObjects(); AdjustLight(1);
1066 1: NoteArrival(); ScoreArrival();
1071 [ MovePlayer direc
; <Go direc
>; <Look
>; ];
1073 ! ----------------------------------------------------------------------------
1074 ! The handy YesOrNo routine
, and some
"meta" verbs
1075 ! ----------------------------------------------------------------------------
1077 [ YesOrNo noStatusRedraw
1080 #Ifdef TARGET_ZCODE;
1081 if (location
== nothing
|| parent(player
) == nothing
|| noStatusRedraw
)
1083 else read buffer parse DrawStatusLine
;
1085 #Ifnot; ! TARGET_GLULX;
1086 noStatusRedraw
= 0; ! suppress warning
1087 KeyboardPrimitive(buffer
, parse
);
1090 if (j
) { ! at least one word entered
1092 if (i
== YES1__WD
or YES2__WD
or YES3__WD
) rtrue
;
1093 if (i
== NO1__WD
or NO2__WD
or NO3__WD
) rfalse
;
1095 L__M(##Quit, 1); print "> ";
1099 #Ifdef TARGET_ZCODE;
1103 if (YesOrNo()) quit
;
1108 if (YesOrNo()) { @restart
; L__M(##Restart, 2); }
1113 return L__M(##Restore, 1);
1130 return L__M(##Save, 1);
1140 return L__M(##Verify, 1);
1146 transcript_mode
= ((HDR_GAMEFLAGS
-->0) & 1);
1147 if (transcript_mode
) return L__M(##ScriptOn, 1);
1149 if (((HDR_GAMEFLAGS
-->0) & 1) == 0) return L__M(##ScriptOn, 3);
1150 L__M(##ScriptOn, 2); VersionSub();
1151 transcript_mode
= true;
1155 transcript_mode
= ((HDR_GAMEFLAGS
-->0) & 1);
1156 if (transcript_mode
== false) return L__M(##ScriptOff, 1);
1157 L__M(##ScriptOff, 2);
1159 if ((HDR_GAMEFLAGS
-->0) & 1) return L__M(##ScriptOff, 3);
1160 transcript_mode
= false;
1166 L__M(##CommandsOn, 1);
1170 if (xcommsdir
== 1) @output_stream
-4;
1172 L__M(##CommandsOff, 1);
1178 L__M(##CommandsRead, 1);
1181 #Ifnot; ! TARGET_GLULX;
1185 if (YesOrNo()) quit
;
1190 if (YesOrNo()) { @restart
; L__M(##Restart, 2); }
1193 [ RestoreSub res fref
;
1194 fref
= glk_fileref_create_by_prompt($
01, $
02, 0);
1195 if (fref
== 0) jump RFailed
;
1196 gg_savestr
= glk_stream_open_file(fref
, $
02, GG_SAVESTR_ROCK
);
1197 glk_fileref_destroy(fref
);
1198 if (gg_savestr
== 0) jump RFailed
;
1199 @restore gg_savestr res
;
1200 glk_stream_close(gg_savestr
, 0);
1207 fref
= glk_fileref_create_by_prompt($
01, $
01, 0);
1208 if (fref
== 0) jump SFailed
;
1209 gg_savestr
= glk_stream_open_file(fref
, $
01, GG_SAVESTR_ROCK
);
1210 glk_fileref_destroy(fref
);
1211 if (gg_savestr
== 0) jump SFailed
;
1212 @save gg_savestr res
;
1214 ! The player actually just typed
"restore". We
're going to print
1215 ! L__M(##Restore,2); the Z-Code Inform library does this correctly
1216 ! now. But first, we have to recover all the Glk objects; the values
1217 ! in our global variables are all wrong.
1219 glk_stream_close(gg_savestr, 0);
1221 return L__M(##Restore, 2);
1223 glk_stream_close(gg_savestr, 0);
1225 if (res == 0) return L__M(##Save, 2);
1232 if (res == 0) return L__M(##Verify, 1);
1237 if (gg_scriptstr) return L__M(##ScriptOn, 1);
1238 if (gg_scriptfref == 0) {
1239 gg_scriptfref = glk_fileref_create_by_prompt($102, $05, GG_SCRIPTFREF_ROCK);
1240 if (gg_scriptfref == 0) jump S1Failed;
1242 gg_scriptstr = glk_stream_open_file(gg_scriptfref, $05, GG_SCRIPTSTR_ROCK);
1243 if (gg_scriptstr == 0) jump S1Failed;
1244 glk_window_set_echo_stream(gg_mainwin, gg_scriptstr);
1245 L__M(##ScriptOn, 2);
1249 L__M(##ScriptOn, 3);
1253 if (gg_scriptstr == 0) return L__M(##ScriptOff,1);
1254 L__M(##ScriptOff, 2);
1255 glk_stream_close(gg_scriptstr, 0);
1259 [ CommandsOnSub fref;
1260 if (gg_commandstr) {
1261 if (gg_command_reading) return L__M(##CommandsOn, 2);
1262 else return L__M(##CommandsOn, 3);
1264 fref = glk_fileref_create_by_prompt($103, $01, 0);
1265 if (fref == 0) return L__M(##CommandsOn, 4);
1266 gg_command_reading = false;
1267 gg_commandstr = glk_stream_open_file(fref, $01, GG_COMMANDWSTR_ROCK);
1268 glk_fileref_destroy(fref);
1269 if (gg_commandstr == 0) return L__M(##CommandsOn, 4);
1270 L__M(##CommandsOn, 1);
1274 if (gg_commandstr == 0) return L__M(##CommandsOff, 2);
1275 if (gg_command_reading) return L__M(##CommandsRead, 5);
1276 glk_stream_close(gg_commandstr, 0);
1278 gg_command_reading = false;
1279 L__M(##CommandsOff, 1);
1282 [ CommandsReadSub fref;
1283 if (gg_commandstr) {
1284 if (gg_command_reading) return L__M(##CommandsRead, 2);
1285 else return L__M(##CommandsRead, 3);
1287 fref = glk_fileref_create_by_prompt($103, $02, 0);
1288 if (fref == 0) return L__M(##CommandsRead, 4);
1289 gg_command_reading = true;
1290 gg_commandstr = glk_stream_open_file(fref, $02, GG_COMMANDRSTR_ROCK);
1291 glk_fileref_destroy(fref);
1292 if (gg_commandstr == 0) return L__M(##CommandsRead, 4);
1293 L__M(##CommandsRead, 1);
1298 [ NotifyOnSub; notify_mode = true; L__M(##NotifyOn); ];
1299 [ NotifyOffSub; notify_mode = false; L__M(##NotifyOff); ];
1303 objectloop (i has visited) j++;
1304 objectloop (i has visited) {
1305 print (name) i; k++;
1306 if (k == j) return L__M(##Places, 2);
1307 if (k == j-1) print (SerialComma) j, (string) AND__TX;
1308 else print (string) COMMA__TX;
1312 [ Objects1Sub i j f;
1314 objectloop (i has moved) {
1315 f = 1; print (the) i; j = parent(i);
1318 if (i has worn) L__M(##Objects, 3, j, i);
1319 else L__M(##Objects, 4, j, i);
1322 if (j has animate) { L__M(##Objects, 5, j, i); jump Obj__Ptd; }
1323 if (j has visited) { L__M(##Objects, 6, j, i); jump Obj__Ptd; }
1324 if (j has container) { L__M(##Objects, 8, j, i); jump Obj__Ptd; }
1325 if (j has supporter) { L__M(##Objects, 9, j, i); jump Obj__Ptd; }
1326 if (j has enterable) { L__M(##Objects, 7, j, i); jump Obj__Ptd; }
1328 L__M(##Objects, 10, j, i);
1334 if (f == 0) L__M(##Objects, 2);
1337 ! ----------------------------------------------------------------------------
1338 ! The scoring system
1339 ! ----------------------------------------------------------------------------
1343 if (deadflag == 0) L__M(##Score, 2);
1345 if (deadflag) new_line;
1347 if(PrintRank() == false) LibraryExtensions.RunAll(ext_printrank);
1353 return task_scores->i;
1358 if (task_done->num == 0) {
1360 score = score + TaskScore(num);
1367 if (n < 0) { n = -m; n = n*10; }
1368 if (n < 10) { print " "; jump Panuml; }
1369 if (n < 100) { print " "; jump Panuml; }
1370 if (n < 1000) { print " "; }
1379 if (score == 0 || TASKS_PROVIDED == 1) rfalse;
1381 L__M(##FullScore, 1);
1382 for (i=0 : i<NUMBER_TASKS : i++)
1383 if (task_done->i == 1) {
1384 PANum(TaskScore(i));
1385 if(PrintTaskName(i) == false)
1386 LibraryExtensions.RunAll(ext_printtaskname,i);
1389 PANum(things_score);
1390 L__M(##FullScore, 2);
1393 PANum(places_score);
1394 L__M(##FullScore, 3);
1396 new_line; PANum(score); L__M(##FullScore, 4);
1399 ! ----------------------------------------------------------------------------
1400 ! Real verbs start here: Inventory
1401 ! ----------------------------------------------------------------------------
1404 if (actor == player)
1405 inventory_style = ENGLISH_BIT+FULLINV_BIT+RECURSE_BIT;
1407 inventory_style = ENGLISH_BIT+PARTINV_BIT;
1409 inventory_style = 0;
1413 if (actor == player)
1414 inventory_style = NEWLINE_BIT+INDENT_BIT+FULLINV_BIT+RECURSE_BIT;
1416 inventory_style = NEWLINE_BIT+INDENT_BIT+PARTINV_BIT;
1418 inventory_style = 0;
1422 if (child(actor) == 0) return L__M(##Inv, 1);
1423 if (inventory_style == 0)
1424 if (actor == player) return InvTallSub();
1425 else return InvWideSub();
1427 if (inventory_style & NEWLINE_BIT) L__M(##Inv, 3); else print " ";
1429 WriteListFrom(child(actor), inventory_style, 1);
1430 if (inventory_style & ENGLISH_BIT) L__M(##Inv, 4);
1432 #Ifndef MANUAL_PRONOUNS;
1433 objectloop (x in player) PronounNotice(x);
1435 x = 0; ! To prevent a "not used" error
1439 ! ----------------------------------------------------------------------------
1440 ! The object tree and determining the possibility of moves
1441 ! ----------------------------------------------------------------------------
1443 [ CommonAncestor o1 o2 i j;
1444 ! Find the nearest object indirectly containing o1 and o2,
1445 ! or return 0 if there is no common ancestor.
1450 if (j == i) return i;
1458 [ IndirectlyContains o1 o2;
1459 ! Does o1 indirectly contain o2? (Same as testing if their common ancestor is o1.)
1461 if (o1 == o2) rtrue;
1462 if (o2 ofclass Class) rfalse;
1468 [ ObjectScopedBySomething item i j k l m;
1470 objectloop (j .& add_to_scope) {
1471 l = j.&add_to_scope;
1472 k = (j.#add_to_scope)/WORDSIZE;
1473 if (l-->0 ofclass Routine) continue;
1474 for (m=0 : m<k : m++)
1475 if (l-->m == i) return j;
1480 [ ObjectIsUntouchable item flag1 flag2 ancestor i;
1481 ! Determine if there's any barrier preventing the actor from moving
1482 ! things to
"item". Return
false if no barrier
; otherwise print a
1483 ! suitable message
and return true.
1484 ! If flag1 is set
, do not print any message
.
1485 ! If flag2 is set
, also apply Take
/Remove restrictions
.
1487 ! If the item has been added to scope by something
, it
's first necessary
1488 ! for that something to be touchable.
1490 ancestor = CommonAncestor(actor, item);
1491 if (ancestor == 0) {
1493 while (ancestor && (i = ObjectScopedBySomething(ancestor)) == 0)
1494 ancestor = parent(ancestor);
1496 if (ObjectIsUntouchable(i, flag1, flag2)) return;
1497 ! An item immediately added to scope
1502 ! First, a barrier between the actor and the ancestor. The actor
1503 ! can only be in a sequence of enterable objects, and only closed
1504 ! containers form a barrier.
1506 if (actor ~= ancestor) {
1508 while (i ~= ancestor) {
1509 if (i has container && i hasnt open) {
1511 return L__M(##Take, 9, i, noun);
1517 ! Second, a barrier between the item and the ancestor. The item can
1518 ! be carried by someone, part of a piece of machinery, in or on top
1519 ! of something and so on.
1522 if (item ~= ancestor && i ~= player) {
1523 while (i ~= ancestor) {
1524 if (flag2 && i hasnt container && i hasnt supporter) {
1525 if (i has animate) {
1527 return L__M(##Take, 6, i, noun);
1529 if (i has transparent) {
1531 return L__M(##Take, 7, i, noun);
1534 return L__M(##Take, 8, item, noun);
1536 if (i has container && i hasnt open) {
1538 return L__M(##Take, 9, i, noun);
1546 [ AttemptToTakeObject item
1547 ancestor after_recipient i k;
1548 ! Try to transfer the given item to the actor: return false
1549 ! if successful, true if unsuccessful, printing a suitable message
1550 ! in the latter case.
1551 ! People cannot ordinarily be taken.
1552 if (item == actor) return L__M(##Take, 2, noun);
1553 if (item has animate) return L__M(##Take, 3, item);
1555 ancestor = CommonAncestor(actor, item);
1557 if (ancestor == 0) {
1558 i = ObjectScopedBySomething(item);
1559 if (i) ancestor = CommonAncestor(actor, i);
1562 ! Is the actor indirectly inside the item?
1563 if (ancestor == item) return L__M(##Take, 4, item);
1565 ! Does the actor already directly contain the item?
1566 if (item in actor) return L__M(##Take, 5, item);
1568 ! Can the actor touch the item, or is there (e.g.) a closed container
1570 if (ObjectIsUntouchable(item, false, true)) rtrue;
1572 ! The item is now known to be accessible.
1574 ! Consult the immediate possessor of the item, if it's in a container
1575 ! which the actor is
not in
.
1578 if (i
&& i
~= ancestor
&& (i has container
or supporter
)) {
1579 after_recipient
= i
;
1580 k
= action
; action
= ##LetGo;
1581 if (RunRoutines(i
, before
)) { action
= k
; rtrue
; }
1585 if (item has scenery
) return L__M(##Take, 10, item);
1586 if (item has
static) return L__M(##Take, 11, item);
1588 ! The item is now known to be available
for taking
. Is the player
1589 ! carrying too much
? If so
, possibly juggle items into the rucksack
1592 if (ObjectDoesNotFit(item
, actor
) ||
1593 LibraryExtensions
.RunWhile(ext_objectdoesnotfit
, false, item
, actor
)) return;
1594 if (AtFullCapacity(item
, actor
)) return L__M(##Take, 12, item);
1596 ! Transfer the item
.
1598 move item to actor
; give item
~worn
;
1600 ! Send
"after" message to the object letting go of the item
, if any
.
1602 if (after_recipient
) {
1603 k
= action
; action
= ##LetGo;
1604 if (RunRoutines(after_recipient
, after
)) { action
= k
; rtrue
; }
1610 [ AtFullCapacity n s
1612 n
= n
; ! suppress compiler warning
1614 objectloop (obj in s
)
1615 if (obj hasnt worn
) k
++;
1619 if (k
< RunRoutines(s
, capacity
) || (s
== player
&& RoomInSack())) rfalse
;
1624 if (SACK_OBJECT
&& SACK_OBJECT in player
) {
1625 ks
= keep_silent
; keep_silent
= 2;
1626 for (obj
=youngest(player
) : obj
: obj
=elder(obj
))
1627 if (obj
~= SACK_OBJECT
&& obj hasnt worn
or light
) {
1628 <Insert obj SACK_OBJECT
>;
1629 if (obj in SACK_OBJECT
) {
1631 return L__M(##Take, 13, obj, SACK_OBJECT);
1639 ! ----------------------------------------------------------------------------
1640 ! Support
for implicit actions
1641 ! ----------------------------------------------------------------------------
1643 [ CheckImplicitAction act o1 o2
1644 sav_act sav_noun sav_sec res
;
1645 if (o1 provides before_implicit
) {
1646 sav_act
= action
; action
= act
;
1647 sav_noun
= noun
; noun
= o1
;
1648 if (o2
) { sav_sec
= second
; second
= o2
; }
1649 res
= RunRoutines(o1
, before_implicit
);
1650 action
= sav_act
; noun
= sav_noun
;
1651 if (sav_sec
) second
= sav_sec
;
1654 if (no_implicit_actions
)
1664 switch (metaclass(obj
)) { Class
, String
, Routine
, nothing
: rfalse
; }
1665 if (obj in actor
) rfalse
;
1666 if (action_to_be
== ##Drop && ~~IndirectlyContains(actor, obj)) rfalse;
1667 res
= CheckImplicitAction(##Take, obj);
1668 ! 0 = Take object
, Tell the
user (normal
default)
1669 ! 1 = Take object
, don
't Tell
1670 ! 2 = don't Take object
continue (default with no_implicit_actions
)
1671 ! 3 = don
't Take object, don't
continue
1672 if (res
>= 2) rtrue
;
1673 if (parent(obj
) && parent(obj
) has container
or supporter
) supcon
= parent(obj
);
1674 ks
= keep_silent
; keep_silent
= 2; AttemptToTakeObject(obj
); keep_silent
= ks
;
1675 if (obj notin actor
) rtrue
;
1676 if (res
== 0 && ~~keep_silent
)
1677 if (supcon
) L__M(##Miscellany, 58, obj, supcon);
1678 else L__M(##Miscellany, 26, obj);
1684 if (parent(obj
) == nothing
) rfalse
;
1685 res
= CheckImplicitAction(##Exit, obj);
1686 ! 0 = Exit object
, Tell the
user (normal
default)
1687 ! 1 = Exit object
, don
't Tell
1688 ! 2 = don't Take object
continue (default with no_implicit_actions
)
1689 ! 3 = don
't Take object, don't
continue
1690 if (res
>= 2) rtrue
;
1691 ks
= keep_silent
; keep_silent
= 2; <Exit obj
, actor
>; keep_silent
= ks
;
1692 if (parent(actor
) == obj
) rtrue
;
1693 if (res
== 0 && ~~keep_silent
) L__M(##Exit, 5, obj);
1699 if (obj hasnt open
) rfalse
;
1700 res
= CheckImplicitAction(##Close, obj);
1701 ! 0 = Close object
, Tell the
user (normal
default)
1702 ! 1 = Close object
, don
't Tell
1703 ! 2 = don't Take object
continue (default with no_implicit_actions
)
1704 ! 3 = don
't Take object, don't
continue
1705 if (res
>= 2) rtrue
;
1706 ks
= keep_silent
; keep_silent
= 2; <Close obj
, actor
>; keep_silent
= ks
;
1707 if (obj has open
) rtrue
;
1708 if (res
== 0 && ~~keep_silent
) L__M(##Close, 4, obj);
1714 if (obj has open
) rfalse
;
1715 res
= CheckImplicitAction(##Open, obj);
1716 ! 0 = Open object
, Tell the
user (normal
default)
1717 ! 1 = Open object
, don
't Tell
1718 ! 2 = don't Take object
continue (default with no_implicit_actions
)
1719 ! 3 = don
't Take object, don't
continue
1720 if (res
>= 2) rtrue
;
1721 if (obj has locked
) rtrue
;
1722 temp
= keep_silent
; keep_silent
= 2; <Open obj
, actor
>; keep_silent
= temp
;
1723 if (obj hasnt open
) rtrue
;
1724 if (res
== 0 && ~~keep_silent
) L__M(##Open, 6, obj);
1725 temp
= action
; action
= ##Open; AfterRoutines(); action = temp;
1729 [ ImplicitUnlock obj
;
1730 if (obj has locked
) rtrue
;
1734 [ ImplicitDisrobe obj
1736 if (obj hasnt worn
) rfalse
;
1737 res
= CheckImplicitAction(##Disrobe, obj);
1738 ! 0 = Take off object
, Tell the
user (normal
default)
1739 ! 1 = Take off object
, don
't Tell
1740 ! 2 = don't Take object
continue (default with no_implicit_actions
)
1741 ! 3 = don
't Take object, don't
continue
1742 if (res
>= 2) rtrue
;
1743 ks
= keep_silent
; keep_silent
= 1; <Disrobe obj
, actor
>; keep_silent
= ks
;
1744 if (obj has worn
&& obj in actor
) rtrue
;
1745 if (res
== 0 && ~~keep_silent
) L__M(##Drop, 3, obj);
1750 ! ----------------------------------------------------------------------------
1751 ! Object movement verbs
1752 ! ----------------------------------------------------------------------------
1755 if (onotheld_mode
== 0 || noun notin actor
)
1756 if (AttemptToTakeObject(noun
)) return;
1757 if (AfterRoutines()) return;
1758 notheld_mode
= onotheld_mode
;
1759 if (notheld_mode
== 1 || keep_silent
) return;
1760 L__M(##Take, 1, noun);
1765 if (i
&& i has container
&& i hasnt open
&& ImplicitOpen(i
)) return L__M(##Remove, 1, i);
1766 if (i
~= second
) return L__M(##Remove, 2, noun);
1767 if (i has animate
) return L__M(##Take, 6, i, noun);
1769 if (AttemptToTakeObject(noun
)) rtrue
;
1771 action
= ##Remove; if (AfterRoutines()) return;
1772 action
= ##Take; if (AfterRoutines()) return;
1773 if (keep_silent
) return;
1774 L__M(##Remove, 3, noun);
1778 if (noun
== actor
) return L__M(##PutOn, 4, noun);
1779 if (noun in
parent(actor
)) return L__M(##Drop, 1, noun);
1780 if (noun notin actor
&& ~~ImplicitTake(noun
)) return L__M(##Drop, 2, noun);
1781 if (noun has worn
&& ImplicitDisrobe(noun
)) return;
1782 move noun to
parent(actor
);
1783 if (AfterRoutines() || keep_silent
) return;
1784 L__M(##Drop, 4, noun);
1787 [ PutOnSub ancestor
;
1788 receive_action
= ##PutOn;
1789 if (second
== d_obj
|| actor in second
) <<Drop noun
, actor
>>;
1790 if (parent(noun
) == second
) return L__M(##Drop, 1, noun);
1791 if (noun notin actor
&& ImplicitTake(noun
)) return L__M(##PutOn, 1, noun);
1793 ancestor
= CommonAncestor(noun
, second
);
1794 if (ancestor
== noun
) return L__M(##PutOn, 2, noun);
1795 if (ObjectIsUntouchable(second
)) return;
1797 if (second
~= ancestor
) {
1799 if (RunRoutines(second
, before
)) { action
= ##PutOn; return; }
1802 if (second hasnt supporter
) return L__M(##PutOn, 3, second);
1803 if (ancestor
== actor
) return L__M(##PutOn, 4, second);
1804 if (noun has worn
&& ImplicitDisrobe(noun
)) return;
1806 if (ObjectDoesNotFit(noun
, second
) ||
1807 LibraryExtensions
.RunWhile(ext_objectdoesnotfit
, false, noun
, second
)) return;
1808 if (AtFullCapacity(noun
, second
)) return L__M(##PutOn, 6, second);
1810 move noun to second
;
1812 if (AfterRoutines()) return;
1814 if (second
~= ancestor
) {
1816 if (RunRoutines(second
, after
)) { action
= ##PutOn; return; }
1819 if (keep_silent
) return;
1820 if (multiflag
) return L__M(##PutOn, 7);
1821 L__M(##PutOn, 8, noun, second);
1824 [ InsertSub ancestor
;
1825 receive_action
= ##Insert;
1826 if (second
== d_obj
|| actor in second
) <<Drop noun
, actor
>>;
1827 if (parent(noun
) == second
) return L__M(##Drop, 1, noun);
1828 if (noun notin actor
&& ImplicitTake(noun
)) return L__M(##Insert, 1, noun);
1829 ancestor
= CommonAncestor(noun
, second
);
1830 if (ancestor
== noun
) return L__M(##Insert, 5, noun);
1831 if (ObjectIsUntouchable(second
)) return;
1832 if (second
~= ancestor
) {
1834 if (RunRoutines(second
,before
)) { action
= ##Insert; rtrue; }
1836 if (second has container
&& second hasnt open
&& ImplicitOpen(second
))
1837 return L__M(##Insert, 3, second);
1839 if (second hasnt container
) return L__M(##Insert, 2, second);
1840 if (noun has worn
&& ImplicitDisrobe(noun
)) return;
1842 if (ObjectDoesNotFit(noun
, second
) ||
1843 LibraryExtensions
.RunWhile(ext_objectdoesnotfit
, false, noun
, second
)) return;
1844 if (AtFullCapacity(noun
, second
)) return L__M(##Insert, 7, second);
1846 move noun to second
;
1848 if (AfterRoutines()) rtrue
;
1850 if (second
~= ancestor
) {
1852 if (RunRoutines(second
, after
)) { action
= ##Insert; rtrue; }
1855 if (keep_silent
) rtrue
;
1856 if (multiflag
) return L__M(##Insert, 8, noun);
1857 L__M(##Insert, 9, noun, second);
1860 ! ----------------------------------------------------------------------------
1861 ! Empties
and transfers are routed through the actions above
1862 ! ----------------------------------------------------------------------------
1865 if (noun notin actor
&& AttemptToTakeObject(noun
)) return;
1866 if (second has supporter
) <<PutOn noun second
, actor
>>;
1867 if (second
== d_obj
) <<Drop noun
, actor
>>;
1868 <<Insert noun second
, actor
>>;
1871 [ EmptySub
; second
= d_obj
; EmptyTSub(); ];
1873 [ EmptyTSub i j k flag
;
1874 if (noun
== second
) return L__M(##EmptyT, 4, noun);
1875 if (ObjectIsUntouchable(noun
)) return;
1876 if (noun hasnt container
) return L__M(##EmptyT, 1, noun);
1877 if (noun hasnt open
&& ImplicitOpen(noun
)) return L__M(##EmptyT, 2, noun);
1878 if (second
~= d_obj
) {
1879 if (second hasnt supporter
) {
1880 if (second hasnt container
) return L__M(##EmptyT, 1, second);
1881 if (second hasnt open
&& ImplicitOpen(second
))
1882 return L__M(##EmptyT, 2, second);
1885 i
= child(noun
); k
= children(noun
);
1886 if (i
== 0) return L__M(##EmptyT, 3, noun);
1890 if (ObjectIsUntouchable(noun
)) flag
= true;
1891 if (noun hasnt container
) flag
= true;
1892 if (noun hasnt open
) flag
= true;
1893 if (second
~= d_obj
) {
1894 if (second hasnt supporter
) {
1895 if (second hasnt container
) flag
= true;
1896 if (second hasnt open
) flag
= true;
1899 if (k
-- == 0) flag
= 1;
1901 if (keep_silent
== 0) print (name
) i
, (string
) COLON__TX
;
1902 <Transfer i second
, actor
>;
1907 ! ----------------------------------------------------------------------------
1909 ! ----------------------------------------------------------------------------
1912 if (noun notin actor
&& ImplicitTake(noun
)) return L__M(##Give, 1, noun);
1913 if (second
== actor
) return L__M(##Give, 2, noun);
1914 if (noun has worn
&& ImplicitDisrobe(noun
)) return;
1915 if (second
== player
) {
1916 move noun to player
;
1917 return L__M(##Give, 4, noun);
1920 if (RunLife(second
, ##Give)) return;
1921 L__M(##Give, 3, second);
1924 [ GiveRSub
; <Give second noun
, actor
>; ];
1927 if (noun notin actor
&& ImplicitTake(noun
)) return L__M(##Show, 1, noun);
1928 if (second
== player
) <<Examine noun
, actor
>>;
1929 if (RunLife(second
, ##Show)) return;
1930 L__M(##Show, 2, second);
1933 [ ShowRSub
; <Show second noun
, actor
>; ];
1935 ! ----------------------------------------------------------------------------
1936 ! Travelling around verbs
1937 ! ----------------------------------------------------------------------------
1939 [ EnterSub ancestor j ks
;
1940 if (noun has door
|| noun in compass
) <<Go noun
, actor
>>;
1941 if (actor in noun
) return L__M(##Enter, 1, noun);
1942 if (noun hasnt enterable
) return L__M(##Enter, 2, noun, verb_word);
1944 if (parent(actor
) ~= parent(noun
)) {
1945 ancestor
= CommonAncestor(actor
, noun
);
1946 if (ancestor
== actor
or 0) return L__M(##Enter, 4, noun);
1947 while (actor notin ancestor
) {
1950 if (parent(j
) ~= ancestor
|| noun
~= ancestor
) {
1951 L__M(##Enter, 6, j);
1956 if (actor in j
) return;
1958 if (actor in noun
) return;
1959 if (noun notin ancestor
) {
1961 while (parent(j
) ~= ancestor
) j
= parent(j
);
1962 L__M(##Enter, 7, j);
1963 ks
= keep_silent
; keep_silent
= 1;
1966 if (actor notin j
) return;
1967 <<Enter noun
, actor
>>;
1971 if (noun has container
&& noun hasnt open
&& ImplicitOpen(noun
)) return L__M(##Enter, 3, noun);
1974 if (AfterRoutines() || keep_silent
) return;
1975 L__M(##Enter, 5, noun);
1976 if (actor
== player
) Locale(noun
);
1980 if (parent(actor
) == noun
) <<Exit
, actor
>>;
1981 L__M(##GetOff, 1, noun);
1986 if (noun
~= nothing
&& noun
~= p
) return L__M(##Exit, 4 ,noun);
1987 if (p
== location
|| (location
== thedark
&& p
== real_location
)) {
1988 if (actor provides posture
&& actor
.posture
) {
1990 return L__M(##Exit, 6);
1992 if ((location
.out_to
) || (location
== thedark
&& real_location
.out_to
))
1993 <<Go out_obj
, actor
>>;
1994 return L__M(##Exit, 1);
1996 if (p has container
&& p hasnt open
&& ImplicitOpen(p
))
1997 return L__M(##Exit, 2, p);
1999 if (noun
== nothing
) {
2001 if (RunRoutines(p
, before
)) return;
2004 move actor to
parent(p
);
2005 if (player provides posture
) player
.posture
= 0;
2007 if (AfterRoutines() || keep_silent
) return;
2009 if (actor
== player
&& p has container
) LookSub(1);
2012 [ VagueGoSub
; L__M(##VagueGo); ];
2014 [ GoInSub
; <<Go in_obj
, actor
>>; ];
2016 [ GoSub i j k movewith thedir next_loc
;
2018 ! first
, check
if any PushDir object is touchable
2019 if (second
&& second notin Compass
&& ObjectIsUntouchable(second
)) return;
2023 if ((location
~= thedark
&& i
~= location
) || (location
== thedark
&& i
~= real_location
)) {
2025 if (location
== thedark
) location
= real_location
;
2026 k
= RunRoutines(i
, before
); if (k
~= 3) location
= j
;
2028 movewith
= i
; i
= parent(i
);
2032 if (ImplicitExit(i
)) return L__M(##Go, 1, i);
2037 thedir
= noun
.door_dir
;
2038 if (metaclass(thedir
) == Routine
) thedir
= RunRoutines(noun
, door_dir
);
2040 next_loc
= i
.thedir
; k
= metaclass(next_loc
);
2041 if (k
== String
) { print (string
) next_loc
; new_line
; rfalse
; }
2043 next_loc
= RunRoutines(i
, thedir
);
2044 if (next_loc
== 1) rtrue
;
2047 if (k
== nothing
|| next_loc
== 0) {
2048 if (i
.cant_go
~= 0 or CANTGO__TX
) PrintOrRun(i
, cant_go
);
2052 if (next_loc has door
) {
2053 if (next_loc has concealed
) return L__M(##Go, 2);
2054 if (next_loc hasnt open
&& ImplicitOpen(next_loc
)) {
2055 if (noun
== u_obj
) return L__M(##Go, 3, next_loc);
2056 if (noun
== d_obj
) return L__M(##Go, 4, next_loc);
2057 return L__M(##Go, 5, next_loc);
2059 k
= RunRoutines(next_loc
, door_to
);
2060 if (k
== 0) return L__M(##Go, 6, next_loc);
2066 if (RunRoutines(next_loc
, before
)) { action
= ##Go; return; }
2069 if (movewith
== 0) move actor to next_loc
; else move movewith to next_loc
;
2070 if (actor
~= player
) return L__M(##Go, 7);
2072 k
= location
; location
= next_loc
;
2073 MoveFloatingObjects();
2074 if (OffersLight(location
))
2079 if(DarkToDark() == false) ! From real_location To location
2080 LibraryExtensions
.RunAll(ext_darktodark
);
2081 if (deadflag
) rtrue
;
2085 NoteDeparture(); real_location
= next_loc
;
2087 if (RunRoutines(prev_location
, after
)) { action
= ##Go; return; }
2089 if (AfterRoutines() || keep_silent
) return;
2093 ! ----------------------------------------------------------------------------
2094 ! Describing the world
. SayWhatsOn(object
) does just
that (producing
2095 ! no text
if nothing except possibly
"scenery" and "concealed" items are
).
2096 ! Locale(object
) runs through the
"tail end" of a Look
-style room
2097 ! description
for the contents of the object
, printing up suitable
2098 ! descriptions as it goes
.
2099 ! ----------------------------------------------------------------------------
2101 [ SayWhatsOn descon j f
;
2102 if (descon
== parent(player
)) rfalse
;
2103 objectloop (j in descon
)
2104 if (j hasnt concealed
&& j hasnt scenery
) f
= 1;
2106 L__M(##Look, 4, descon);
2109 [ NotSupportingThePlayer o i
;
2111 while (i
&& i
~= visibility_ceiling
) {
2114 if (i
&& i hasnt supporter
) rtrue
;
2118 ! modified with the fix
for L61122
2119 [ Locale descin text_without_ALSO text_with_ALSO
2120 o p num_objs must_print_ALSO
;
2121 objectloop (o in descin
) give o
~workflag
;
2123 objectloop (o in descin
)
2124 if (o hasnt concealed
&& NotSupportingThePlayer(o
)) {
2125 #Ifndef MANUAL_PRONOUNS;
2128 if (o has scenery
) {
2129 if (o has supporter
&& child(o
)) SayWhatsOn(o
);
2132 give o workflag
; num_objs
++;
2134 if ((o has door
or container
) && o has open
&& o provides when_open
) {
2135 p
= when_open
; jump Prop_Chosen
;
2137 if ((o has door
or container
) && o hasnt open
&& o provides when_closed
) {
2138 p
= when_closed
; jump Prop_Chosen
;
2140 if (o has switchable
&& o has on
&& o provides when_on
) {
2141 p
= when_on
; jump Prop_Chosen
;
2143 if (o has switchable
&& o hasnt on
&& o provides when_off
) {
2149 if (o
.&describe
&& RunRoutines(o
, describe
)) {
2150 must_print_ALSO
= true;
2151 give o
~workflag
; num_objs
--;
2154 if (o
.p
&& (o hasnt moved
|| p
~= initial
)) {
2157 must_print_ALSO
= true;
2158 give o
~workflag
; num_objs
--;
2159 if (o has supporter
&& child(o
)) SayWhatsOn(o
);
2164 if (num_objs
== 0) return 0;
2166 if (actor
~= player
) give actor concealed
;
2167 if (text_without_ALSO
) {
2169 if (must_print_ALSO
) print (string
) text_with_ALSO
, " ";
2170 else print (string
) text_without_ALSO
, " ";
2171 WriteListFrom(child(descin
),
2172 ENGLISH_BIT
+RECURSE_BIT
+PARTINV_BIT
+TERSE_BIT
+CONCEAL_BIT
+WORKFLAG_BIT
);
2175 if (must_print_ALSO
) L__M(##Look, 5, descin);
2176 else L__M(##Look, 6, descin);
2178 if (actor
~= player
) give actor
~concealed
;
2182 ! ----------------------------------------------------------------------------
2183 ! Looking
. LookSub(1) is allowed to abbreviate
long descriptions
, but
2184 ! LookSub(0) (which is what happens when the Look action is generated
)
2185 ! isn
't. (Except that these are over-ridden by the player-set lookmode.)
2186 ! ----------------------------------------------------------------------------
2188 [ LMode1Sub; lookmode=1; print (string) Story; L__M(##LMode1); ]; ! Brief
2190 [ LMode2Sub; lookmode=2; print (string) Story; L__M(##LMode2); ]; ! Verbose
2192 [ LMode3Sub; lookmode=3; print (string) Story; L__M(##LMode3); ]; ! Superbrief
2194 [ LModeNormalSub; ! 'normal
' value: the default, or as set in Initialise()
2195 switch (initial_lookmode) {
2198 default: <<LMode2>>;
2202 [ NoteArrival descin;
2203 if (location ~= lastdesc) {
2204 if (location.initial) PrintOrRun(location, initial);
2205 if (location == thedark) { lastdesc = thedark; return; }
2207 if(NewRoom() == false) LibraryExtensions.RunAll(ext_newroom);
2213 prev_location = real_location;
2217 if (location hasnt visited) {
2218 give location visited;
2219 if (location has scored) {
2220 score = score + ROOM_SCORE;
2221 places_score = places_score + ROOM_SCORE;
2226 [ FindVisibilityLevels visibility_levels;
2227 visibility_levels = 1;
2228 visibility_ceiling = parent(player);
2229 while ((parent(visibility_ceiling)) &&
2230 (visibility_ceiling hasnt container || visibility_ceiling has open or transparent)) {
2231 visibility_ceiling = parent(visibility_ceiling);
2232 visibility_levels++;
2234 return visibility_levels;
2237 [ LookSub allow_abbrev visibility_levels i j k nl_flag;
2238 if (parent(player) == 0) return RunTimeError(10);
2242 if (location == thedark) { visibility_ceiling = thedark; NoteArrival(); }
2244 visibility_levels = FindVisibilityLevels();
2245 if (visibility_ceiling == location) {
2247 if (visibility_ceiling ~= location) jump MovedByInitial;
2250 ! Printing the top line: e.g.
2251 ! Octagonal Room (on the table) (as Frodo)
2253 #Ifdef TARGET_ZCODE;
2255 #Ifnot; ! TARGET_GLULX;
2256 glk_set_style(style_Subheader);
2258 if (visibility_levels == 0) print (name) thedark;
2260 if (visibility_ceiling ~= location) print (The) visibility_ceiling;
2261 else print (name) visibility_ceiling;
2263 #Ifdef TARGET_ZCODE;
2265 #Ifnot; ! TARGET_GLULX;
2266 glk_set_style(style_Normal);
2269 for (j=1,i=parent(player) : j<visibility_levels : j++,i=parent(i))
2270 if (i has supporter) L__M(##Look, 1, i);
2271 else L__M(##Look, 2, i);
2273 if (print_player_flag == 1) L__M(##Look, 3, player);
2276 ! The room description (if visible)
2278 if (lookmode < 3 && visibility_ceiling == location) {
2279 if ((allow_abbrev ~= 1) || (lookmode == 2) || (location hasnt visited)) {
2280 if (location.&describe) RunRoutines(location, describe);
2282 if (location.description == 0) RunTimeError(11, location, description);
2283 else PrintOrRun(location, description);
2288 if (visibility_ceiling == location) nl_flag = 1;
2290 if (visibility_levels == 0) Locale(thedark);
2292 for (i=player,j=visibility_levels : j>0 : j--,i=parent(i)) give i workflag;
2294 for (j=visibility_levels : j>0 : j--) {
2295 for (i=player,k=0 : k<j : k++) i=parent(i);
2296 if (i.inside_description) {
2297 if (nl_flag) new_line; else nl_flag = 1;
2298 PrintOrRun(i,inside_description);
2300 if (Locale(i)) nl_flag=1;
2304 if(LookRoutine() == false) LibraryExtensions.RunAll(ext_lookroutine);
2311 if (location == thedark) return L__M(##Examine, 1, noun);
2312 i = noun.description;
2314 if (noun has container)
2315 if (noun has open or transparent) <<Search noun, actor>>;
2316 else return L__M(##Search, 5, noun);
2317 if (noun has switchable) { L__M(##Examine, 3, noun); rfalse; }
2318 return L__M(##Examine, 2, noun);
2320 i = PrintOrRun(noun, description);
2321 if (i < 2 && noun has switchable) L__M(##Examine, 3, noun);
2326 if (location == thedark) return L__M(##LookUnder, 1, noun);
2327 L__M(##LookUnder, 2);
2330 [ VisibleContents o i f;
2331 objectloop (i in o) if (i hasnt concealed or scenery) f++;
2336 if (location == thedark) return L__M(##Search, 1, noun);
2337 if (ObjectIsUntouchable(noun)) return;
2338 f = VisibleContents(noun);
2339 if (noun has supporter) {
2340 if (f == 0) return L__M(##Search, 2, noun);
2341 return L__M(##Search, 3, noun);
2343 if (noun hasnt container) return L__M(##Search, 4, noun);
2344 if (noun hasnt transparent or open && ImplicitOpen(noun)) return L__M(##Search, 5, noun);
2345 if (AfterRoutines()) return;
2347 if (f == 0) return L__M(##Search, 6, noun);
2348 L__M(##Search, 7, noun);
2351 ! ----------------------------------------------------------------------------
2352 ! Verbs which change the state of objects without moving them
2353 ! ----------------------------------------------------------------------------
2356 if (ObjectIsUntouchable(noun)) return;
2357 if (noun hasnt lockable) return L__M(##Unlock, 1, noun);
2358 if (noun hasnt locked) return L__M(##Unlock, 2, noun);
2359 if (noun.with_key ~= second) return L__M(##Unlock, 3, second);
2363 if (AfterRoutines() || keep_silent) return;
2364 L__M(##Unlock, 4, noun);
2368 if (ObjectIsUntouchable(noun)) return;
2369 if (noun hasnt lockable) return L__M(##Lock, 1, noun);
2370 if (noun has locked) return L__M(##Lock, 2 ,noun);
2371 if (noun has open && ImplicitClose(noun)) return L__M(##Lock, 3, noun);
2372 if (noun.with_key ~= second) return L__M(##Lock, 4, second);
2375 if (AfterRoutines() || keep_silent) return;
2376 L__M(##Lock, 5, noun);
2380 if (ObjectIsUntouchable(noun)) return;
2381 if (noun hasnt switchable) return L__M(##SwitchOn, 1, noun);
2382 if (noun has on) return L__M(##SwitchOn, 2, noun);
2385 if (AfterRoutines() || keep_silent) return;
2386 L__M(##SwitchOn, 3, noun);
2390 if (ObjectIsUntouchable(noun)) return;
2391 if (noun hasnt switchable) return L__M(##SwitchOff, 1, noun);
2392 if (noun hasnt on) return L__M(##SwitchOff, 2, noun);
2395 if (AfterRoutines() || keep_silent) return;
2396 L__M(##SwitchOff, 3, noun);
2400 if (ObjectIsUntouchable(noun)) return;
2401 if (noun hasnt openable) return L__M(##Open, 1, noun);
2402 if (noun has locked && ImplicitUnlock(noun)) return L__M(##Open, 2, noun);
2403 if (noun has open) return L__M(##Open, 3, noun);
2406 if (keep_silent || AfterRoutines()) return;
2408 if (noun hasnt container)
2409 return L__M(##Open, 5, noun);
2411 if ((noun has container && location ~= thedark && VisibleContents(noun)
2412 && IndirectlyContains(noun, player)) == 0) {
2413 if (noun hasnt transparent && noun hasnt door) return L__M(##Open, 4, noun);
2415 L__M(##Open, 5, noun);
2419 if (ObjectIsUntouchable(noun)) return;
2420 if (noun hasnt openable) return L__M(##Close, 1, noun);
2421 if (noun hasnt open) return L__M(##Close, 2, noun);
2424 if (AfterRoutines() || keep_silent) return;
2425 L__M(##Close, 3, noun);
2429 if (ObjectIsUntouchable(noun)) return;
2430 if (noun hasnt worn) return L__M(##Disrobe, 1, noun);
2433 if (AfterRoutines() || keep_silent) return;
2434 L__M(##Disrobe, 2, noun);
2438 if (ObjectIsUntouchable(noun)) return;
2439 if (noun hasnt clothing) return L__M(##Wear, 1, noun);
2440 if (noun notin actor && ImplicitTake(noun)) return L__M(##Wear, 2, noun);
2441 if (noun has worn) return L__M(##Wear, 3, noun);
2444 if (AfterRoutines() || keep_silent) return;
2445 L__M(##Wear, 4, noun);
2449 if (ObjectIsUntouchable(noun)) return;
2450 if (noun hasnt edible) return L__M(##Eat, 1, noun);
2451 if (noun has worn && ImplicitDisrobe(noun)) return;
2454 if (AfterRoutines() || keep_silent) return;
2455 L__M(##Eat, 2, noun);
2458 ! ----------------------------------------------------------------------------
2459 ! Verbs which are really just stubs (anything which happens for these
2460 ! actions must happen in before rules)
2461 ! ----------------------------------------------------------------------------
2464 if (parent(second) ~= compass) return L__M(##PushDir, 2, noun);
2465 if (second == u_obj or d_obj) return L__M(##PushDir, 3, noun);
2466 AfterRoutines(); i = noun; move i to actor;
2468 if (location == thedark) move i to real_location;
2469 else move i to location;
2473 if (second && RunLife(second,##Answer)) rfalse;
2474 L__M(##Answer, 1, noun);
2478 if (RunLife(noun,##Ask)) rfalse;
2479 L__M(##Ask, 1, noun);
2483 if (noun == player) <<Inv, actor>>;
2484 L__M(##Order, 1, noun);
2487 [ AskToSub; L__M(##Order, 1, noun); ];
2490 if (ObjectIsUntouchable(noun)) return;
2491 if (noun has animate && RunLife(noun, ##Attack)) rfalse;
2492 L__M(##Attack, 1, noun);
2495 [ BlowSub; L__M(##Blow, 1, noun); ];
2498 if (noun has animate) return L__M(##Burn, 2, noun);
2499 L__M(##Burn, 1, noun);
2502 [ BuySub; L__M(##Buy, 1, noun); ];
2505 if (noun has animate) return L__M(##Climb, 2, noun);
2506 L__M(##Climb, 1, noun);
2509 [ ConsultSub; L__M(##Consult, 1, noun); ];
2512 if (noun has animate) return L__M(##Cut, 2, noun);
2513 L__M(##Cut, 1, noun);
2516 [ DigSub; L__M(##Dig, 1, noun); ];
2518 [ DrinkSub; L__M(##Drink, 1, noun); ];
2521 if (second == nothing) return L__M(##Fill, 1, noun);
2522 L__M(##Fill, 2, noun, second);
2525 [ JumpSub; L__M(##Jump, 1, noun); ];
2528 if (noun has animate) return L__M(##JumpIn, 2, noun);
2529 if (noun has enterable) <<Enter noun>>;
2530 L__M(##JumpOn, 1, noun);
2534 if (noun has animate) return L__M(##JumpOn, 2, noun);
2535 if (noun has enterable && noun has supporter) <<Enter noun>>;
2536 L__M(##JumpOn, 1, noun);
2540 if (noun has animate) return L__M(##JumpOver, 2, noun);
2541 L__M(##JumpOver, 1, noun);
2545 if (ObjectIsUntouchable(noun)) return;
2546 if (RunLife(noun, ##Kiss)) return;
2547 if (noun == actor) return L__M(##Touch, 3, noun);
2548 L__M(##Kiss, 1, noun);
2551 [ ListenSub; L__M(##Listen, 1, noun); ];
2553 [ MildSub; L__M(##Mild, 1, noun); ];
2555 [ NoSub; L__M(##No); ];
2557 [ PraySub; L__M(##Pray, 1, noun); ];
2560 if (ObjectIsUntouchable(noun)) return;
2561 if (noun == player) return L__M(##Pull, 1, noun);
2562 if (noun == actor) return L__M(##Pull, 6, noun);
2563 if (noun has static) return L__M(##Pull, 2, noun);
2564 if (noun has scenery) return L__M(##Pull, 3, noun);
2565 if (noun has animate) return L__M(##Pull, 5, noun);
2566 L__M(##Pull, 4, noun);
2570 if (ObjectIsUntouchable(noun)) return;
2571 if (noun == player) return L__M(##Push, 1, noun);
2572 if (noun == actor) return L__M(##Push, 5, noun);
2573 if (noun has static) return L__M(##Push, 2, noun);
2574 if (noun has scenery) return L__M(##Push, 3, noun);
2575 if (noun has animate) return L__M(##Push, 5, noun);
2576 L__M(##Push, 4, noun);
2579 [ PushDirSub; L__M(##PushDir, 1, noun); ];
2582 if (ObjectIsUntouchable(noun)) return;
2583 if (noun has animate) return L__M(##Rub, 2, noun);
2584 L__M(##Rub, 1, noun);
2587 [ SetSub; L__M(##Set, 1, noun); ];
2589 [ SetToSub; L__M(##SetTo, 1, noun); ];
2591 [ SingSub; L__M(##Sing, 1, noun); ];
2593 [ SleepSub; L__M(##Sleep, 1, noun); ];
2596 if (noun ~= nothing && noun has animate) return L__M(##Smell, 2, noun);
2597 L__M(##Smell, 1, noun);
2600 [ SorrySub; L__M(##Sorry, 1, noun); ];
2603 if (ObjectIsUntouchable(noun)) return;
2604 if (noun has animate && noun ~= player) return L__M(##Squeeze, 1, noun);
2605 L__M(##Squeeze, 2, noun);
2608 [ StrongSub; L__M(##Strong, 1, noun); ];
2610 [ SwimSub; L__M(##Swim, 1, noun); ];
2612 [ SwingSub; L__M(##Swing, 1, noun); ];
2615 if (ObjectIsUntouchable(noun)) return;
2616 if (noun has animate) return L__M(##Taste, 2, noun);
2617 L__M(##Taste, 1, noun);
2621 if (noun == actor) return L__M(##Tell, 1, noun);
2622 if (RunLife(noun, ##Tell)) return;
2623 L__M(##Tell, 2, noun);
2626 [ ThinkSub; L__M(##Think, 1, noun); ];
2629 if (ObjectIsUntouchable(noun)) return;
2631 action = ##ThrownAt;
2632 if (RunRoutines(second, before)) { action = ##ThrowAt; rtrue; }
2635 if (noun has worn && ImplicitDisrobe(noun)) return;
2636 if (second hasnt animate) return L__M(##ThrowAt, 1, noun);
2637 if (RunLife(second, ##ThrowAt)) return;
2638 L__M(##ThrowAt, 2, noun);
2642 if (noun has animate) return L__M(##Tie, 2, noun);
2643 L__M(##Tie, 1, noun);
2647 if (noun == actor) return L__M(##Touch, 3, noun);
2648 if (ObjectIsUntouchable(noun)) return;
2649 if (noun has animate) return L__M(##Touch, 1, noun);
2650 L__M(##Touch, 2,noun);
2654 if (ObjectIsUntouchable(noun)) return;
2655 if (noun == player) return L__M(##Turn, 1, noun);
2656 if (noun == actor) return L__M(##Turn, 5, noun);
2657 if (noun has static) return L__M(##Turn, 2, noun);
2658 if (noun has scenery) return L__M(##Turn, 3, noun);
2659 if (noun has animate) return L__M(##Turn, 5, noun);
2660 L__M(##Turn, 4, noun);
2664 if (AfterRoutines()) rtrue;
2665 L__M(##Wait, 1, noun);
2668 [ WakeSub; L__M(##Wake, 1, noun); ];
2671 if (ObjectIsUntouchable(noun)) return;
2672 if (RunLife(noun, ##WakeOther)) return;
2673 L__M(##WakeOther, 1, noun);
2677 if (noun == player) return L__M(##Wave, 2 ,noun, second);
2678 if (noun == actor) return L__M(##Wave, 3, noun, second);
2679 if (noun notin actor && ImplicitTake(noun)) return L__M(##Wave, 1, noun);
2680 L__M(##Wave, 2, noun, second);
2684 if (noun) return L__M(##WaveHands, 2, noun);
2685 L__M(##WaveHands, 1, noun); ];
2687 [ YesSub; L__M(##Yes); ];
2689 ! ----------------------------------------------------------------------------
2691 ! ----------------------------------------------------------------------------
2695 [ TraceOnSub; parser_trace = 1; "[Trace on.]"; ];
2698 parser_trace = noun;
2699 print "[Parser tracing set to level ", parser_trace, ".]^";
2702 [ TraceOffSub; parser_trace = 0; "Trace off."; ];
2705 debug_flag = debug_flag | DEBUG_MESSAGES;
2706 "[Message listing on.]";
2710 debug_flag = debug_flag & ~DEBUG_MESSAGES;
2711 "[Message listing off.]";
2714 [ RoutinesVerboseSub;
2715 debug_flag = debug_flag | (DEBUG_VERBOSE|DEBUG_MESSAGES);
2716 "[Verbose message listing on.]";
2720 debug_flag = debug_flag | DEBUG_ACTIONS;
2721 "[Action listing on.]";
2725 debug_flag = debug_flag & ~DEBUG_ACTIONS;
2726 "[Action listing off.]";
2730 debug_flag = debug_flag | DEBUG_TIMERS;
2731 "[Timers listing on.]";
2735 debug_flag = debug_flag & ~DEBUG_TIMERS;
2736 "[Timers listing off.]";
2741 [ ChangesOnSub; debug_flag = debug_flag | DEBUG_CHANGES; "[Changes listing on.]"; ];
2742 [ ChangesOffSub; debug_flag = debug_flag & ~DEBUG_CHANGES; "[Changes listing off.]"; ];
2746 [ ChangesOnSub; "[Changes listing available only from Inform 6.2 onwards.]"; ];
2748 [ ChangesOffSub; "[Changes listing available only from Inform 6.2 onwards.]"; ];
2752 #Ifdef TARGET_ZCODE;
2756 "[Random number generator now predictable.]";
2759 #Ifnot; ! TARGET_GLULX;
2763 "[Random number generator now predictable.]";
2768 [ XTestMove obj dest;
2769 if (~~obj ofclass Object) "[Not an object.]";
2770 if (~~dest ofclass Object) "[Destination not an object.]";
2771 if ((obj <= InformLibrary) || (obj == LibraryMessages) || (obj in 1))
2772 "[Can't move
", (name) obj, ": it
's a system object.]";
2774 if (dest == obj) "[Can't move
", (name) obj, ": it would contain itself
.]";
2775 dest = parent(dest);
2781 if (XTestMove(noun, player)) return;
2782 move noun to player; give noun moved ~concealed;
2787 if (XTestMove(noun, second)) return;
2788 move noun to second;
2793 if (parent(obj) == 0) print (name) obj; else print (a) obj;
2794 print " (", obj, ") ";
2795 if (f && parent(obj))
2796 print "in
~", (name) parent(obj), "~ (", parent(obj), ")";
2798 if (child(obj) == 0) rtrue;
2799 if (obj == Class) ! ???
2800 WriteListFrom(child(obj), NEWLINE_BIT+INDENT_BIT+ALWAYS_BIT+ID_BIT+NOARTICLE_BIT, 1);
2802 WriteListFrom(child(obj), NEWLINE_BIT+INDENT_BIT+ALWAYS_BIT+ID_BIT+FULLINV_BIT, 1);
2806 if (noun && ~~noun ofclass Object) "[Not an object
.]";
2809 if (i ofclass Object && parent(i) == 0) XObj(i);
2811 else XObj(noun, true);
2815 if ((~~noun ofclass Object) || parent(noun)) "[Not a safe place
.]";
2820 if (~~noun ofclass Object) "[Not a safe place
.]";
2822 while (parent(x)) x = parent(x);
2826 [ Print_ScL obj; print_ret ++x_scope_count, ": ", (a) obj, " (", obj, ")"; ];
2829 if (noun && ~~noun ofclass Object) "[Not an object
.]";
2831 LoopOverScope(Print_ScL, noun);
2832 if (x_scope_count == 0) "Nothing is in scope
.";
2835 #Ifdef TARGET_GLULX;
2837 [ GlkListSub id val;
2838 id = glk_window_iterate(0, gg_arguments);
2840 print "Window
", id, " (", gg_arguments-->0, "): ";
2841 val = glk_window_get_type(id);
2845 3: print "textbuffer
";
2846 4: print "textgrid
";
2847 5: print "graphics
";
2848 default: print "unknown
";
2850 val = glk_window_get_parent(id);
2851 if (val) print ", parent is window
", val;
2852 else print ", no
parent (root
)";
2853 val = glk_window_get_stream(id);
2854 print ", stream
", val;
2855 val = glk_window_get_echo_stream(id);
2856 if (val) print ", echo stream
", val;
2858 id = glk_window_iterate(id, gg_arguments);
2860 id = glk_stream_iterate(0, gg_arguments);
2862 print "Stream
", id, " (", gg_arguments-->0, ")^";
2863 id = glk_stream_iterate(id, gg_arguments);
2865 id = glk_fileref_iterate(0, gg_arguments);
2867 print "Fileref
", id, " (", gg_arguments-->0, ")^";
2868 id = glk_fileref_iterate(id, gg_arguments);
2870 val = glk_gestalt(gestalt_Sound, 0);
2872 id = glk_schannel_iterate(0, gg_arguments);
2874 print "Soundchannel
", id, " (", gg_arguments-->0, ")^";
2875 id = glk_schannel_iterate(id, gg_arguments);
2884 ! ----------------------------------------------------------------------------
2885 ! Finally: the mechanism for library text (the text is in the language defn)
2886 ! ----------------------------------------------------------------------------
2888 [ L__M act n x1 x2 s;
2889 if (keep_silent == 2) return;
2903 if (RunRoutines(LibraryMessages, before)) { action = s; rfalse; }
2904 if (LibraryExtensions.RunWhile(ext_messages, false )) { action = s; rfalse; }
2906 LanguageLM(n, x1, x2);
2909 ! ==============================================================================