verblibm.h 91 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915
  1. ! ==============================================================================
  2. ! VERBLIBM: Core of standard verbs library.
  3. !
  4. ! Supplied for use with Inform 6 -- Release 6/12 -- Serial number 151220
  5. !
  6. ! Copyright Graham Nelson 1993-2004 and David Griffith 2012-2015
  7. !
  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/
  12. !
  13. ! This file is automatically Included in your game file by "VerbLib".
  14. ! ==============================================================================
  15. System_file;
  16. #Ifdef MODULE_MODE;
  17. Constant DEBUG;
  18. Constant Grammar__Version 2;
  19. Include "linklpa";
  20. Include "linklv";
  21. #Endif; ! MODULE_MODE
  22. ! ------------------------------------------------------------------------------
  23. [ Banner i;
  24. #Ifdef LanguageBanner;
  25. LanguageBanner();
  26. i = 0; ! suppress warning
  27. #Ifnot;
  28. if (Story) {
  29. #Ifdef TARGET_ZCODE;
  30. #IfV5; style bold; #Endif;
  31. print "^", (string) Story;
  32. #IfV5; style roman; #Endif;
  33. #Ifnot; ! TARGET_GLULX;
  34. glk($0086, 3); ! set header style
  35. print (string) Story;
  36. glk($0086, 0); ! set normal style
  37. #Endif; ! TARGET_
  38. }
  39. if (Headline) print (string) Headline;
  40. #Ifdef TARGET_ZCODE;
  41. print "Release ", (HDR_GAMERELEASE-->0) & $03ff, " / Serial number ";
  42. for (i=0 : i<6 : i++) print (char) HDR_GAMESERIAL->i;
  43. #Ifnot; ! TARGET_GLULX;
  44. print "Release ";
  45. @aloads ROM_GAMERELEASE 0 i;
  46. print i;
  47. print " / Serial number ";
  48. for (i=0 : i<6 : i++) print (char) ROM_GAMESERIAL->i;
  49. #Endif; ! TARGET_
  50. print " / Inform v"; inversion;
  51. print " Library ", (string) LibRelease, " ";
  52. #Ifdef STRICT_MODE;
  53. print "S";
  54. #Endif; ! STRICT_MODE
  55. #Ifdef INFIX;
  56. print "X";
  57. #Ifnot;
  58. #Ifdef DEBUG;
  59. print "D";
  60. #Endif; ! DEBUG
  61. #Endif; ! INFIX
  62. new_line;
  63. #Endif; ! LanguageBanner
  64. ];
  65. [ VersionSub ix;
  66. #Ifdef LanguageVersionSub;
  67. LanguageVersionSub();
  68. ix = 0; ! suppress warning
  69. #Ifnot;
  70. Banner();
  71. #Ifdef TARGET_ZCODE;
  72. ix = 0; ! shut up compiler warning
  73. if (standard_interpreter > 0) {
  74. print "Standard interpreter ", standard_interpreter/256, ".", standard_interpreter%256,
  75. " (", HDR_TERPNUMBER->0;
  76. #Iftrue (#version_number == 6);
  77. print (char) '.', HDR_TERPVERSION->0;
  78. #Ifnot;
  79. print (char) HDR_TERPVERSION->0;
  80. #Endif;
  81. print ") / ";
  82. }
  83. else {
  84. print "Interpreter ", HDR_TERPNUMBER->0, " Version ";
  85. #Iftrue (#version_number == 6);
  86. print HDR_TERPVERSION->0;
  87. #Ifnot;
  88. print (char) HDR_TERPVERSION->0;
  89. #Endif;
  90. print " / ";
  91. }
  92. #Ifnot; ! TARGET_GLULX;
  93. @gestalt 1 0 ix;
  94. print "Interpreter version ", ix / $10000, ".", (ix & $FF00) / $100,
  95. ".", ix & $FF, " / ";
  96. @gestalt 0 0 ix;
  97. print "VM ", ix / $10000, ".", (ix & $FF00) / $100, ".", ix & $FF, " / ";
  98. #Endif; ! TARGET_;
  99. print "Library serial number ", (string) LibSerial, "^";
  100. #Ifdef LanguageVersion;
  101. print (string) LanguageVersion, "^";
  102. #Endif; ! LanguageVersion
  103. #Endif; ! LanguageVersionSub
  104. ];
  105. [ RunTimeError n p1 p2;
  106. #Ifdef LanguageError;
  107. LanguageError(n, p1, p2);
  108. #Ifnot;
  109. #Ifdef DEBUG;
  110. print "** Library error ", n, " (", p1, ", ", p2, ") **^** ";
  111. switch (n) {
  112. 1: print "preposition not found (this should not occur)";
  113. 2: print "Property value not routine or string: ~", (property) p2, "~ of ~", (name) p1,
  114. "~ (", p1, ")";
  115. 3: print "Entry in property list not routine or string: ~", (property) p2, "~ list of ~",
  116. (name) p1, "~ (", p1, ")";
  117. 4: print "Too many timers/daemons are active simultaneously.
  118. The limit is the library constant MAX_TIMERS
  119. (currently ", MAX_TIMERS, ") and should be increased";
  120. 5: print "Object ~", (name) p1, "~ has no ~", (property) p2, "~ property";
  121. 7: print "The object ~", (name) p1, "~ can only be used as a player object if it has
  122. the ~number~ property";
  123. 8: print "Attempt to take random entry from an empty table array";
  124. 9: print p1, " is not a valid direction property number";
  125. 10: print "The player-object is outside the object tree";
  126. 11: print "The room ~", (name) p1, "~ has no ~", (property) p2, "~ property";
  127. 12: print "Tried to set a non-existent pronoun using SetPronoun";
  128. 13: print "A 'topic' token can only be followed by a preposition";
  129. 14: print "Overflowed buffer limit of ", p1, " using '@@64output_stream 3' ", (string) p2;
  130. 15: print "LoopWithinObject broken because the object ", (name) p1, " was moved while the loop passed through it.";
  131. 16: print "Attempt to use illegal narrative_voice of ", p1, ".";
  132. default:
  133. print "(unexplained)";
  134. }
  135. " **";
  136. #Ifnot;
  137. "** Library error ", n, " (", p1, ", ", p2, ") **";
  138. #Endif; ! DEBUG
  139. #Endif; ! LanguageError
  140. ];
  141. ! ----------------------------------------------------------------------------
  142. ! The WriteListFrom routine, a flexible object-lister taking care of
  143. ! plurals, inventory information, various formats and so on. This is used
  144. ! by everything in the library which ever wants to list anything.
  145. !
  146. ! If there were no objects to list, it prints nothing and returns false;
  147. ! otherwise it returns true.
  148. !
  149. ! o is the object, and style is a bitmap, whose bits are given by:
  150. ! ----------------------------------------------------------------------------
  151. Constant NEWLINE_BIT $0001; ! New-line after each entry
  152. Constant INDENT_BIT $0002; ! Indent each entry by depth
  153. Constant FULLINV_BIT $0004; ! Full inventory information after entry
  154. Constant ENGLISH_BIT $0008; ! English sentence style, with commas and and
  155. Constant RECURSE_BIT $0010; ! Recurse downwards with usual rules
  156. Constant ALWAYS_BIT $0020; ! Always recurse downwards
  157. Constant TERSE_BIT $0040; ! More terse English style
  158. Constant PARTINV_BIT $0080; ! Only brief inventory information after entry
  159. Constant DEFART_BIT $0100; ! Use the definite article in list
  160. Constant WORKFLAG_BIT $0200; ! At top level (only), only list objects
  161. ! which have the "workflag" attribute
  162. Constant ISARE_BIT $0400; ! Print " is" or " are" before list
  163. Constant CONCEAL_BIT $0800; ! Omit objects with "concealed" or "scenery":
  164. ! if WORKFLAG_BIT also set, then does _not_
  165. ! apply at top level, but does lower down
  166. Constant NOARTICLE_BIT $1000; ! Print no articles, definite or not
  167. Constant ID_BIT $2000; ! Print object id after each entry
  168. [ NextEntry o odepth;
  169. for (::) {
  170. o = sibling(o);
  171. if (o == 0) return 0;
  172. if (lt_value && o.list_together ~= lt_value) continue;
  173. if (c_style & WORKFLAG_BIT && odepth==0 && o hasnt workflag) continue;
  174. if (c_style & CONCEAL_BIT && (o has concealed || o has scenery)) continue;
  175. return o;
  176. }
  177. ];
  178. [ WillRecurs o;
  179. if (c_style & ALWAYS_BIT) rtrue;
  180. if (c_style & RECURSE_BIT == 0) rfalse;
  181. if ((o has transparent or supporter) || (o has container && o has open)) rtrue;
  182. rfalse;
  183. ];
  184. [ ListEqual o1 o2;
  185. if (child(o1) && WillRecurs(o1)) rfalse;
  186. if (child(o2) && WillRecurs(o2)) rfalse;
  187. if (c_style & (FULLINV_BIT + PARTINV_BIT)) {
  188. if ((o1 hasnt worn && o2 has worn) || (o2 hasnt worn && o1 has worn)) rfalse;
  189. if ((o1 hasnt light && o2 has light) || (o2 hasnt light && o1 has light)) rfalse;
  190. if (o1 has container) {
  191. if (o2 hasnt container) rfalse;
  192. if ((o1 has open && o2 hasnt open) || (o2 has open && o1 hasnt open))
  193. rfalse;
  194. }
  195. else if (o2 has container)
  196. rfalse;
  197. }
  198. return Identical(o1, o2);
  199. ];
  200. [ SortTogether obj value;
  201. ! print "Sorting together possessions of ", (object) obj, " by value ", value, "^";
  202. ! for (x=child(obj) : x : x=sibling(x))
  203. ! print (the) x, " no: ", x, " lt: ", x.list_together, "^";
  204. while (child(obj)) {
  205. if (child(obj).list_together ~= value) move child(obj) to out_obj;
  206. else move child(obj) to in_obj;
  207. }
  208. while (child(in_obj)) move child(in_obj) to obj;
  209. while (child(out_obj)) move child(out_obj) to obj;
  210. ];
  211. [ SortOutList obj i k l;
  212. ! print "^^Sorting out list from ", (name) obj, "^ ";
  213. ! for (i=child(location) : i : i=sibling(i))
  214. ! print (name) i, " --> ";
  215. ! new_line;
  216. .AP_SOL;
  217. for (i=obj : i : i=sibling(i)) {
  218. k = i.list_together;
  219. if (k ~= 0) {
  220. ! print "Scanning ", (name) i, " with lt=", k, "^";
  221. for (i=sibling(i) : i && i.list_together == k :) i = sibling(i);
  222. if (i == 0) rfalse;
  223. ! print "First not in block is ", (name) i, " with lt=", i.list_together, "^";
  224. for (l=sibling(i) : l : l=sibling(l))
  225. if (l.list_together == k) {
  226. SortTogether(parent(obj), k);
  227. ! print "^^After ST:^ ";
  228. ! for (i=child(location) : i : i=sibling(i))
  229. ! print (name) i, " --> ";
  230. ! new_line;
  231. obj = child(parent(obj));
  232. jump AP_SOL;
  233. }
  234. }
  235. }
  236. ];
  237. #Ifdef TARGET_ZCODE;
  238. [ Print__Spaces n; ! To avoid a bug occurring in Inform 6.01 to 6.10
  239. if (n == 0) return;
  240. spaces n;
  241. ];
  242. #Ifnot; ! TARGET_GLULX;
  243. [ Print__Spaces n;
  244. while (n > 0) {
  245. @streamchar ' ';
  246. n = n - 1;
  247. }
  248. ];
  249. #Endif; ! TARGET_
  250. [ WriteListFrom o style depth
  251. s1 s2 s3 s4 s5 s6;
  252. if (o == nothing) return 0;
  253. s1 = c_style; s2 = lt_value; s3 = listing_together;
  254. s4 = listing_size; s5 = wlf_indent; s6 = inventory_stage;
  255. if (o == child(parent(o))) {
  256. SortOutList(o);
  257. o = child(parent(o));
  258. }
  259. c_style = style;
  260. wlf_indent = 0;
  261. if (WriteListR(o, depth) == 0) return 0;
  262. c_style = s1; lt_value = s2; listing_together = s3;
  263. listing_size = s4; wlf_indent = s5; inventory_stage = s6;
  264. rtrue;
  265. ];
  266. [ WriteListR o depth stack_pointer classes_p sizes_p i j k k2 l m n q senc mr;
  267. if (depth > 0 && o == child(parent(o))) {
  268. SortOutList(o);
  269. o = child(parent(o));
  270. }
  271. for (::) {
  272. if (o == 0) rfalse;
  273. if (c_style & WORKFLAG_BIT && depth==0 && o hasnt workflag) {
  274. o = sibling(o);
  275. continue;
  276. }
  277. if (c_style & CONCEAL_BIT && (o has concealed || o has scenery)) {
  278. o = sibling(o);
  279. continue;
  280. }
  281. break;
  282. }
  283. classes_p = match_classes + stack_pointer;
  284. sizes_p = match_list + stack_pointer;
  285. for (i=o,j=0 : i && (j+stack_pointer)<128 : i=NextEntry(i,depth),j++) {
  286. classes_p->j = 0;
  287. if (i.plural) k++;
  288. }
  289. if (c_style & ISARE_BIT) {
  290. if (j == 1 && o hasnt pluralname) Tense(IS__TX, WAS__TX);
  291. else Tense(ARE__TX, WERE__TX);
  292. if (c_style & NEWLINE_BIT) print ":^";
  293. else print (char) ' ';
  294. c_style = c_style - ISARE_BIT;
  295. }
  296. stack_pointer = stack_pointer+j+1;
  297. if (k < 2) jump EconomyVersion; ! It takes two to plural
  298. n = 1;
  299. for (i=o,k=0 : k<j : i=NextEntry(i,depth),k++)
  300. if (classes_p->k == 0) {
  301. classes_p->k = n; sizes_p->n = 1;
  302. for (l=NextEntry(i,depth),m=k+1 : l && m<j : l=NextEntry(l,depth),m++)
  303. if (classes_p->m == 0 && i.plural && l.plural ~= 0) {
  304. if (ListEqual(i, l) == 1) {
  305. sizes_p->n = sizes_p->n + 1;
  306. classes_p->m = n;
  307. }
  308. }
  309. n++;
  310. }
  311. n--;
  312. for (i=1,j=o,k=0 : i<=n : i++,senc++) {
  313. while (((classes_p->k) ~= i) && ((classes_p->k) ~= -i)) {
  314. k++; j=NextEntry(j, depth);
  315. }
  316. m = sizes_p->i;
  317. if (j == 0) mr = 0;
  318. else {
  319. if (j.list_together ~= 0 or lt_value && ZRegion(j.list_together) == Routine or String &&
  320. j.list_together == mr) senc--;
  321. mr = j.list_together;
  322. }
  323. }
  324. senc--;
  325. for (i=1,j=o,k=0,mr=0 : senc>=0 : i++,senc--) {
  326. while (((classes_p->k) ~= i) && ((classes_p->k) ~= -i)) {
  327. k++; j=NextEntry(j, depth);
  328. }
  329. if (j.list_together ~= 0 or lt_value) {
  330. if (j.list_together == mr) {
  331. senc++;
  332. jump Omit_FL2;
  333. }
  334. k2 = NextEntry(j, depth);
  335. if (k2 == 0 || k2.list_together ~= j.list_together) jump Omit_WL2;
  336. k2 = metaclass(j.list_together);
  337. if (k2 == Routine or String) {
  338. q = j; listing_size = 1; l = k; m = i;
  339. while (m < n && q.list_together == j.list_together) {
  340. m++;
  341. while (((classes_p->l) ~= m) && ((classes_p->l) ~= -m)) {
  342. l++; q = NextEntry(q, depth);
  343. }
  344. if (q.list_together == j.list_together) listing_size++;
  345. }
  346. ! print " [", listing_size, "] ";
  347. if (listing_size == 1) jump Omit_WL2;
  348. if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
  349. if (k2 == String) {
  350. q = 0;
  351. for (l=0 : l<listing_size : l++) q = q+sizes_p->(l+i);
  352. EnglishNumber(q); print " ";
  353. print (string) j.list_together;
  354. if (c_style & ENGLISH_BIT) print " (";
  355. if (c_style & INDENT_BIT) print ":^";
  356. }
  357. q = c_style;
  358. if (k2 ~= String) {
  359. inventory_stage = 1;
  360. parser_one = j; parser_two = depth+wlf_indent;
  361. if (RunRoutines(j, list_together) == 1) jump Omit__Sublist2;
  362. }
  363. #Ifdef TARGET_ZCODE;
  364. @push lt_value; @push listing_together; @push listing_size;
  365. #Ifnot; ! TARGET_GLULX;
  366. @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
  367. #Endif; ! TARGET_;
  368. lt_value = j.list_together; listing_together = j; wlf_indent++;
  369. WriteListR(j, depth, stack_pointer); wlf_indent--;
  370. #Ifdef TARGET_ZCODE;
  371. @pull listing_size; @pull listing_together; @pull lt_value;
  372. #Ifnot; ! TARGET_GLULX;
  373. @copy sp listing_size;
  374. @copy sp listing_together;
  375. @copy sp lt_value;
  376. #Endif; ! TARGET_;
  377. if (k2 == String) {
  378. if (q & ENGLISH_BIT) print ")";
  379. }
  380. else {
  381. inventory_stage = 2;
  382. parser_one = j; parser_two = depth+wlf_indent;
  383. RunRoutines(j, list_together);
  384. }
  385. .Omit__Sublist2;
  386. if (q & NEWLINE_BIT && c_style & NEWLINE_BIT == 0) new_line;
  387. c_style = q;
  388. mr = j.list_together;
  389. jump Omit_EL2;
  390. }
  391. }
  392. .Omit_WL2;
  393. if (WriteBeforeEntry(j, depth, 0, senc) == 1) jump Omit_FL2;
  394. if (sizes_p->i == 1) {
  395. if (c_style & NOARTICLE_BIT) print (name) j;
  396. else {
  397. if (c_style & DEFART_BIT) print (the) j;
  398. else print (a) j;
  399. }
  400. if (c_style & ID_BIT) print " (", j, ")";
  401. }
  402. else {
  403. if (c_style & DEFART_BIT) PrefaceByArticle(j, 1, sizes_p->i);
  404. print (number) sizes_p->i, " ";
  405. PrintOrRun(j, plural, 1);
  406. }
  407. if (sizes_p->i > 1 && j hasnt pluralname) {
  408. give j pluralname;
  409. WriteAfterEntry(j, depth, stack_pointer);
  410. give j ~pluralname;
  411. }
  412. else {
  413. WriteAfterEntry(j,depth,stack_pointer);
  414. }
  415. .Omit_EL2;
  416. if (c_style & ENGLISH_BIT) {
  417. if (senc == 1) print (SerialComma) i+senc, (string) AND__TX;
  418. if (senc > 1) print (string) COMMA__TX;
  419. }
  420. .Omit_FL2;
  421. }
  422. rtrue;
  423. .EconomyVersion;
  424. n = j;
  425. for (i=1,j=o : i<=n : j=NextEntry(j,depth),i++,senc++) {
  426. if (j.list_together ~= 0 or lt_value && ZRegion(j.list_together) == 2 or 3 &&
  427. j.list_together==mr) senc--;
  428. mr = j.list_together;
  429. }
  430. for (i=1,j=o,mr=0 : i<=senc : j=NextEntry(j,depth),i++) {
  431. if (j.list_together ~= 0 or lt_value) {
  432. if (j.list_together == mr) {
  433. i--;
  434. jump Omit_FL;
  435. }
  436. k = NextEntry(j, depth);
  437. if (k == 0 || k.list_together ~= j.list_together) jump Omit_WL;
  438. k = metaclass(j.list_together);
  439. if (k == Routine or String) {
  440. if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
  441. if (k == String) {
  442. q = j; l = 0;
  443. do {
  444. q = NextEntry(q, depth); l++;
  445. } until (q == 0 || q.list_together ~= j.list_together);
  446. EnglishNumber(l); print " ";
  447. print (string) j.list_together;
  448. if (c_style & ENGLISH_BIT) print " (";
  449. if (c_style & INDENT_BIT) print ":^";
  450. }
  451. q = c_style;
  452. if (k ~= String) {
  453. inventory_stage = 1;
  454. parser_one = j; parser_two = depth+wlf_indent;
  455. if (RunRoutines(j, list_together) == 1) jump Omit__Sublist;
  456. }
  457. #Ifdef TARGET_ZCODE;
  458. @push lt_value; @push listing_together; @push listing_size;
  459. #Ifnot; ! TARGET_GLULX;
  460. @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
  461. #Endif; ! TARGET_;
  462. lt_value = j.list_together; listing_together = j; wlf_indent++;
  463. WriteListR(j, depth, stack_pointer); wlf_indent--;
  464. #Ifdef TARGET_ZCODE;
  465. @pull listing_size; @pull listing_together; @pull lt_value;
  466. #Ifnot; ! TARGET_GLULX;
  467. @copy sp listing_size; @copy sp listing_together; @copy sp lt_value;
  468. #Endif; ! TARGET_;
  469. if (k == String) {
  470. if (q & ENGLISH_BIT) print ")";
  471. }
  472. else {
  473. inventory_stage = 2;
  474. parser_one = j; parser_two = depth+wlf_indent;
  475. RunRoutines(j, list_together);
  476. }
  477. .Omit__Sublist;
  478. if (q & NEWLINE_BIT && c_style & NEWLINE_BIT == 0) new_line;
  479. c_style = q;
  480. mr = j.list_together;
  481. jump Omit_EL;
  482. }
  483. }
  484. .Omit_WL;
  485. if (WriteBeforeEntry(j, depth, i, senc) == 1) jump Omit_FL;
  486. if (c_style & NOARTICLE_BIT) print (name) j;
  487. else {
  488. if (c_style & DEFART_BIT) print (the) j;
  489. else print (a) j;
  490. }
  491. if (c_style & ID_BIT) print " (", j, ")";
  492. WriteAfterEntry(j, depth, stack_pointer);
  493. .Omit_EL;
  494. if (c_style & ENGLISH_BIT) {
  495. if (i == senc-1) print (SerialComma) senc, (string) AND__TX;
  496. if (i < senc-1) print (string) COMMA__TX;
  497. }
  498. .Omit_FL;
  499. }
  500. ]; ! end of WriteListR
  501. [ WriteBeforeEntry o depth ipos sentencepos
  502. flag;
  503. inventory_stage = 1;
  504. if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
  505. if (o.invent && (c_style & (PARTINV_BIT|FULLINV_BIT))) {
  506. flag = PrintOrRun(o, invent, 1);
  507. if (flag) {
  508. if (c_style & ENGLISH_BIT) {
  509. if (ipos == sentencepos-1)
  510. print (SerialComma) sentencepos, (string) AND__TX;
  511. if (ipos < sentencepos-1)
  512. print (string) COMMA__TX;
  513. }
  514. if (c_style & NEWLINE_BIT) new_line;
  515. }
  516. }
  517. return flag;
  518. ];
  519. [ WriteAfterEntry o depth stack_p
  520. p recurse_flag parenth_flag eldest_child child_count combo i j;
  521. inventory_stage = 2;
  522. if (c_style & PARTINV_BIT) {
  523. if (o.invent && RunRoutines(o, invent))
  524. if (c_style & NEWLINE_BIT) ""; else rtrue;
  525. combo = 0;
  526. if (o has light && location hasnt light) combo=combo+1;
  527. if (o has container && o hasnt open) combo=combo+2;
  528. if ((o has container && (o has open || o has transparent))) {
  529. objectloop(i in o) {
  530. if (i has concealed or scenery) j = false;
  531. if (i hasnt concealed && i hasnt scenery) j = true;
  532. }
  533. if (~~j) combo=combo+4;
  534. }
  535. if (combo) L__M(##ListMiscellany, combo, o);
  536. } ! end of PARTINV_BIT processing
  537. if (c_style & FULLINV_BIT) {
  538. if (o.invent && RunRoutines(o, invent))
  539. if (c_style & NEWLINE_BIT) ""; else rtrue;
  540. if (o has light && o has worn) { L__M(##ListMiscellany, 8, o); parenth_flag = true; }
  541. else {
  542. if (o has light) { L__M(##ListMiscellany, 9, o); parenth_flag = true; }
  543. if (o has worn) { L__M(##ListMiscellany, 10, o); parenth_flag = true; }
  544. }
  545. if (o has container)
  546. if (o has openable) {
  547. if (parenth_flag) print (string) AND__TX;
  548. else L__M(##ListMiscellany, 11, o);
  549. if (o has open)
  550. if (child(o)) L__M(##ListMiscellany, 12, o);
  551. else L__M(##ListMiscellany, 13, o);
  552. else
  553. if (o has lockable && o has locked) L__M(##ListMiscellany, 15, o);
  554. else L__M(##ListMiscellany, 14, o);
  555. parenth_flag = true;
  556. }
  557. else
  558. if (child(o)==0 && o has transparent)
  559. if (parenth_flag) L__M(##ListMiscellany, 16, o);
  560. else L__M(##ListMiscellany, 17, o);
  561. if (parenth_flag) print ")";
  562. } ! end of FULLINV_BIT processing
  563. if (c_style & CONCEAL_BIT) {
  564. child_count = 0;
  565. objectloop (p in o)
  566. if (p hasnt concealed && p hasnt scenery) { child_count++; eldest_child = p; }
  567. }
  568. else { child_count = children(o); eldest_child = child(o); }
  569. if (child_count && (c_style & ALWAYS_BIT)) {
  570. if (c_style & ENGLISH_BIT) L__M(##ListMiscellany, 18, o);
  571. recurse_flag = true;
  572. }
  573. if (child_count && (c_style & RECURSE_BIT)) {
  574. if (o has supporter) {
  575. if (c_style & ENGLISH_BIT) {
  576. if (c_style & TERSE_BIT) L__M(##ListMiscellany, 19, o);
  577. else L__M(##ListMiscellany, 20, o);
  578. if (o has animate) print (string) WHOM__TX;
  579. else print (string) WHICH__TX;
  580. }
  581. recurse_flag = true;
  582. }
  583. if (o has container && (o has open || o has transparent)) {
  584. if (c_style & ENGLISH_BIT) {
  585. if (c_style & TERSE_BIT) L__M(##ListMiscellany, 21, o);
  586. else L__M(##ListMiscellany, 22, o);
  587. if (o has animate) print (string) WHOM__TX;
  588. else print (string) WHICH__TX;
  589. }
  590. recurse_flag = true;
  591. }
  592. }
  593. if (recurse_flag && (c_style & ENGLISH_BIT))
  594. if (child_count > 1 || eldest_child has pluralname) Tense(ARE2__TX, WERE2__TX);
  595. else Tense(IS2__TX, WAS2__TX);
  596. if (c_style & NEWLINE_BIT) new_line;
  597. if (recurse_flag) {
  598. o = child(o);
  599. #Ifdef TARGET_ZCODE;
  600. @push lt_value; @push listing_together; @push listing_size;
  601. #Ifnot; ! TARGET_GLULX;
  602. @copy lt_value sp; @copy listing_together sp; @copy listing_size sp;
  603. #Endif;
  604. lt_value = 0; listing_together = 0; listing_size = 0;
  605. WriteListR(o, depth+1, stack_p);
  606. #Ifdef TARGET_ZCODE;
  607. @pull listing_size; @pull listing_together; @pull lt_value;
  608. #Ifnot; ! TARGET_GLULX;
  609. @copy sp listing_size; @copy sp listing_together; @copy sp lt_value;
  610. #Endif;
  611. if (c_style & TERSE_BIT) print ")";
  612. }
  613. ];
  614. ! ----------------------------------------------------------------------------
  615. ! LoopWithinObject(rtn,obj,arg)
  616. !
  617. ! rtn is the address of a user-supplied routine.
  618. ! obj is an optional parent object whose dependents are to be processed; the
  619. ! default is the current actor (normally the player).
  620. ! arg is an optional argument passed to the rtn; this can be a single variable
  621. ! or constant, or the address of an array (which enables multiple values to be
  622. ! passed and returned).
  623. !
  624. ! For each object o which is a child, grandchild, great-grandchild, etc, of the
  625. ! original obj, LoopWithinObject() calls rtn(o,arg).
  626. !
  627. ! The rtn should perform any appropriate testing or processing on each object o,
  628. ! using the optional arg value if necessary. If the rtn returns true (or any
  629. ! positive value), the children of o, if any, are also tested; those children
  630. ! are skipped if rtn returns false. To terminate the loop before all objects
  631. ! have been processed, rtn should return a large negative number (eg -99).
  632. !
  633. ! To deal with supporters and open containers, so that objects are processed
  634. ! only if they are accessible to the player, rtn might end with these
  635. ! statements:
  636. ! if ((o has transparent or supporter) || (o has container && o has open)) rtrue;
  637. ! rfalse;
  638. ! or alternatively with:
  639. ! c_style = RECURSE_BIT; return WillRecurs(o);
  640. !
  641. ! LoopWithinObject() returns the number of objects which have been processed.
  642. ! ----------------------------------------------------------------------------
  643. [ LoopWithinObject rtn obj arg
  644. n o x y;
  645. if (obj == 0) obj = actor;
  646. o = child(obj);
  647. while (o) {
  648. y = parent(o); n++;
  649. x = rtn(o, arg); ! user-supplied routine returning x.
  650. ! if x < 0: skip up to next parent
  651. ! if x = 0: jump across to next sibling
  652. ! if x > 0: continue down to child objects
  653. if (y ~= parent(o)) { RunTimeError(15, o); rfalse; }
  654. if (x > 0 && child(o)) o = child(o);
  655. else
  656. while (o) {
  657. if (++x > 0 && sibling(o)) { o = sibling(o); break; }
  658. o = parent(o);
  659. if (o == obj) return n;
  660. }
  661. }
  662. ];
  663. ! ----------------------------------------------------------------------------
  664. ! Much better menus can be created using one of the optional library
  665. ! extensions. These are provided for compatibility with previous practice:
  666. ! ----------------------------------------------------------------------------
  667. [ LowKey_Menu menu_choices EntryR ChoiceR lines main_title i j;
  668. menu_nesting++;
  669. .LKRD;
  670. menu_item = 0;
  671. lines = EntryR();
  672. main_title = item_name;
  673. print "--- "; print (string) main_title; print " ---^^";
  674. if (menu_choices ofclass Routine) menu_choices();
  675. else print (string) menu_choices;
  676. for (::) {
  677. L__M(##Miscellany, 52, lines);
  678. print "> ";
  679. #Ifdef TARGET_ZCODE;
  680. #IfV3;
  681. read buffer parse;
  682. #Ifnot;
  683. read buffer parse DrawStatusLine;
  684. #Endif; ! V3
  685. j = parse->1; ! number of words
  686. #Ifnot; ! TARGET_GLULX;
  687. KeyboardPrimitive(buffer, parse);
  688. j = parse-->0; ! number of words
  689. #Endif; ! TARGET_
  690. i = parse-->1;
  691. if (j == 0 || (i == QUIT1__WD or QUIT2__WD)) {
  692. menu_nesting--; if (menu_nesting > 0) rfalse;
  693. if (deadflag == 0) <<Look>>;
  694. rfalse;
  695. }
  696. i = TryNumber(1);
  697. if (i == 0) jump LKRD;
  698. if (i < 1 || i > lines) continue;
  699. menu_item = i;
  700. j = ChoiceR();
  701. if (j == 2) jump LKRD;
  702. if (j == 3) rfalse;
  703. }
  704. ];
  705. #Ifdef TARGET_ZCODE;
  706. #IfV3;
  707. [ DoMenu menu_choices EntryR ChoiceR; LowKey_Menu(menu_choices, EntryR, ChoiceR); ];
  708. #Endif; ! V3
  709. #IfV5;
  710. [ DoMenu menu_choices EntryR ChoiceR
  711. lines main_title main_wid cl i j oldcl pkey ch cw y x;
  712. if (pretty_flag == 0) return LowKey_Menu(menu_choices, EntryR, ChoiceR);
  713. menu_nesting++;
  714. menu_item = 0;
  715. lines = EntryR();
  716. main_title = item_name; main_wid = item_width;
  717. cl = 7;
  718. .ReDisplay;
  719. oldcl = 0;
  720. @erase_window $ffff;
  721. #Iftrue (#version_number == 6);
  722. @set_cursor -1;
  723. ch = HDR_FONTWUNITS->0;
  724. #Ifnot;
  725. ch = 1;
  726. #Endif;
  727. i = ch * (lines+7);
  728. @split_window i;
  729. i = HDR_SCREENWCHARS->0;
  730. if (i == 0) i = 80;
  731. @set_window 1;
  732. @set_cursor 1 1;
  733. #Iftrue (#version_number == 6);
  734. @set_font 4 -> cw;
  735. cw = HDR_FONTHUNITS->0;
  736. #Ifnot;
  737. cw = 1;
  738. #Endif;
  739. style reverse;
  740. spaces(i); j=1+(i/2-main_wid)*cw;
  741. @set_cursor 1 j;
  742. print (string) main_title;
  743. y=1+ch; @set_cursor y 1; spaces(i);
  744. x=1+cw; @set_cursor y x; print (string) NKEY__TX;
  745. j=1+(i-13)*cw; @set_cursor y j; print (string) PKEY__TX;
  746. y=y+ch; @set_cursor y 1; spaces(i);
  747. @set_cursor y x; print (string) RKEY__TX;
  748. j=1+(i-18)*cw; @set_cursor y j;
  749. if (menu_nesting == 1) print (string) QKEY1__TX;
  750. else print (string) QKEY2__TX;
  751. style roman;
  752. y = y+2*ch;
  753. @set_cursor y x; font off;
  754. if (menu_choices ofclass String) print (string) menu_choices;
  755. else menu_choices();
  756. x = 1+3*cw;
  757. for (::) {
  758. if (cl ~= oldcl) {
  759. if (oldcl>0) {
  760. y=1+(oldcl-1)*ch; @set_cursor y x; print " ";
  761. }
  762. y=1+(cl-1)*ch; @set_cursor y x; print ">";
  763. }
  764. oldcl = cl;
  765. @read_char 1 -> pkey;
  766. if (pkey == NKEY1__KY or NKEY2__KY or 130) {
  767. cl++; if (cl == 7+lines) cl = 7; continue;
  768. }
  769. if (pkey == PKEY1__KY or PKEY2__KY or 129) {
  770. cl--; if (cl == 6) cl = 6+lines; continue;
  771. }
  772. if (pkey == QKEY1__KY or QKEY2__KY or 27 or 131) break;
  773. if (pkey == 10 or 13 or 132) {
  774. @set_window 0; font on;
  775. new_line; new_line; new_line;
  776. menu_item = cl-6;
  777. EntryR();
  778. @erase_window $ffff;
  779. @split_window ch;
  780. i = HDR_SCREENWCHARS->0; if ( i== 0) i = 80;
  781. @set_window 1; @set_cursor 1 1; style reverse; spaces(i);
  782. j=1+(i/2-item_width)*cw;
  783. @set_cursor 1 j;
  784. print (string) item_name;
  785. style roman; @set_window 0; new_line;
  786. i = ChoiceR();
  787. if (i == 2) jump ReDisplay;
  788. if (i == 3) break;
  789. L__M(##Miscellany, 53);
  790. @read_char 1 -> pkey; jump ReDisplay;
  791. }
  792. }
  793. menu_nesting--; if (menu_nesting > 0) rfalse;
  794. font on; @set_cursor 1 1;
  795. @erase_window $ffff; @set_window 0;
  796. #Iftrue (#version_number == 6);
  797. @set_cursor -2;
  798. #Endif;
  799. new_line; new_line; new_line;
  800. if (deadflag == 0) <<Look>>;
  801. ];
  802. #Endif; ! V5
  803. #Ifnot; ! TARGET_GLULX
  804. [ DoMenu menu_choices EntryR ChoiceR
  805. winwid winhgt lines main_title main_wid cl i oldcl pkey;
  806. if (pretty_flag == 0 || gg_statuswin == 0) return LowKey_Menu(menu_choices, EntryR, ChoiceR);
  807. menu_nesting++;
  808. menu_item = 0;
  809. lines = EntryR();
  810. main_title = item_name;
  811. main_wid = item_width;
  812. cl = 0;
  813. ! If we printed "hit arrow keys" here, it would be appropriate to
  814. ! check for the availability of Glk input keys. But we actually
  815. ! print "hit N/P/Q". So it's reasonable to silently accept Glk
  816. ! arrow key codes as secondary options.
  817. .ReDisplay;
  818. glk($002A, gg_statuswin); ! window_clear
  819. glk($002A, gg_mainwin); ! window_clear
  820. glk($002F, gg_statuswin); ! set_window
  821. StatusLineHeight(lines+7);
  822. glk($0025, gg_statuswin, gg_arguments, gg_arguments+4); ! window_get_size
  823. winwid = gg_arguments-->0;
  824. winhgt = gg_arguments-->1;
  825. glk($0086, 4); ! set subheader style
  826. glk($002B, gg_statuswin, winwid/2-main_wid, 0); ! window_move_cursor
  827. print (string) main_title;
  828. glk($002B, gg_statuswin, 1, 1); ! window_move_cursor
  829. print (string) NKEY__TX;
  830. glk($002B, gg_statuswin, winwid-13, 1); ! window_move_cursor
  831. print (string) PKEY__TX;
  832. glk($002B, gg_statuswin, 1, 2); ! window_move_cursor
  833. print (string) RKEY__TX;
  834. glk($002B, gg_statuswin, winwid-18, 2); ! window_move_cursor
  835. if (menu_nesting == 1) print (string) QKEY1__TX;
  836. else print (string) QKEY2__TX;
  837. glk($0086, 0); ! set normal style
  838. glk($002B, gg_statuswin, 1, 4); ! window_move_cursor
  839. if (menu_choices ofclass String) print (string) menu_choices;
  840. else menu_choices();
  841. oldcl = -1;
  842. for (::) {
  843. if (cl ~= oldcl) {
  844. if (cl < 0 || cl >= lines) cl = 0;
  845. if (oldcl >= 0) {
  846. glk($002B, gg_statuswin, 3, oldcl+6);
  847. print (char) ' ';
  848. }
  849. oldcl = cl;
  850. glk($002B, gg_statuswin, 3, oldcl+6);
  851. print (char) '>';
  852. }
  853. pkey = KeyCharPrimitive(gg_statuswin, true);
  854. if (pkey == $80000000) jump ReDisplay;
  855. if (pkey == NKEY1__KY or NKEY2__KY or $fffffffb) {
  856. cl++;
  857. if (cl >= lines) cl = 0;
  858. continue;
  859. }
  860. if (pkey == PKEY1__KY or PKEY2__KY or $fffffffc) {
  861. cl--;
  862. if (cl < 0) cl = lines-1;
  863. continue;
  864. }
  865. if (pkey == QKEY1__KY or QKEY2__KY or $fffffff8 or $fffffffe) break;
  866. if (pkey == $fffffffa or $fffffffd) {
  867. glk($002F, gg_mainwin); ! set_window
  868. new_line; new_line; new_line;
  869. menu_item = cl+1;
  870. EntryR();
  871. glk($002A, gg_statuswin); ! window_clear
  872. glk($002A, gg_mainwin); ! window_clear
  873. glk($002F, gg_statuswin); ! set_window
  874. StatusLineHeight(1);
  875. glk($0025, gg_statuswin, gg_arguments, gg_arguments+4); ! window_get_size
  876. winwid = gg_arguments-->0;
  877. winhgt = gg_arguments-->1;
  878. glk($0086, 4); ! set subheader style
  879. glk($002B, gg_statuswin, winwid/2-item_width, 0); ! window_move_cursor
  880. print (string) item_name;
  881. glk($0086, 0); ! set normal style
  882. glk($002F, gg_mainwin); ! set_window
  883. new_line;
  884. i = ChoiceR();
  885. if (i == 2) jump ReDisplay;
  886. if (i == 3) break;
  887. L__M(##Miscellany, 53);
  888. pkey = KeyCharPrimitive(gg_mainwin, 1);
  889. jump ReDisplay;
  890. }
  891. }
  892. ! done with this menu...
  893. menu_nesting--;
  894. if (menu_nesting > 0) rfalse;
  895. glk($002F, gg_mainwin); ! set_window
  896. glk($002A, gg_mainwin); ! window_clear
  897. new_line; new_line; new_line;
  898. if (deadflag == 0) <<Look>>;
  899. ];
  900. #Endif; ! TARGET_
  901. ! ----------------------------------------------------------------------------
  902. ! A cunning routine (which could have been a daemon, but isn't, for the
  903. ! sake of efficiency) to move objects which could be in many rooms about
  904. ! so that the player never catches one not in place
  905. ! ----------------------------------------------------------------------------
  906. [ MoveFloatingObjects i k l m address flag;
  907. if (location == player or nothing) return;
  908. objectloop (i) {
  909. address = i.&found_in;
  910. if (address && i hasnt non_floating && ~~IndirectlyContains(player, i)) {
  911. if (metaclass(address-->0) == Routine)
  912. flag = i.found_in();
  913. else {
  914. flag = false;
  915. k = i.#found_in/WORDSIZE;
  916. for (l=0 : l<k : l++) {
  917. m = address-->l;
  918. if ((m in Class && location ofclass m) ||
  919. m == location || m in location) {
  920. flag = true;
  921. break;
  922. }
  923. }
  924. }
  925. if (flag) {
  926. if (i notin location) move i to location;
  927. } else {
  928. if (parent(i)) remove i;
  929. }
  930. }
  931. }
  932. ];
  933. ! ----------------------------------------------------------------------------
  934. ! Two little routines for moving the player safely.
  935. ! ----------------------------------------------------------------------------
  936. [ PlayerTo newplace flag;
  937. NoteDeparture();
  938. move player to newplace;
  939. while (parent(newplace)) newplace = parent(newplace);
  940. location = real_location = newplace;
  941. MoveFloatingObjects(); AdjustLight(1);
  942. switch (flag) {
  943. 0: <Look>;
  944. 1: NoteArrival(); ScoreArrival();
  945. 2: LookSub(1);
  946. }
  947. ];
  948. [ MovePlayer direc; <Go direc>; <Look>; ];
  949. ! ----------------------------------------------------------------------------
  950. ! The handy YesOrNo routine, and some "meta" verbs
  951. ! ----------------------------------------------------------------------------
  952. [ YesOrNo noStatusRedraw
  953. i j;
  954. for (::) {
  955. #Ifdef TARGET_ZCODE;
  956. if (location == nothing || parent(player) == nothing || noStatusRedraw)
  957. read buffer parse;
  958. else read buffer parse DrawStatusLine;
  959. j = parse->1;
  960. #Ifnot; ! TARGET_GLULX;
  961. noStatusRedraw = 0; ! suppress warning
  962. KeyboardPrimitive(buffer, parse);
  963. j = parse-->0;
  964. #Endif; ! TARGET_
  965. if (j) { ! at least one word entered
  966. i = parse-->1;
  967. if (i == YES1__WD or YES2__WD or YES3__WD) rtrue;
  968. if (i == NO1__WD or NO2__WD or NO3__WD) rfalse;
  969. }
  970. L__M(##Quit, 1); print "> ";
  971. }
  972. ];
  973. #Ifdef TARGET_ZCODE;
  974. [ QuitSub;
  975. L__M(##Quit, 2);
  976. if (YesOrNo()) quit;
  977. ];
  978. [ RestartSub;
  979. L__M(##Restart, 1);
  980. if (YesOrNo()) { @restart; L__M(##Restart, 2); }
  981. ];
  982. [ RestoreSub;
  983. restore Rmaybe;
  984. return L__M(##Restore, 1);
  985. .RMaybe;
  986. L__M(##Restore, 2);
  987. ];
  988. [ SaveSub flag;
  989. #IfV5;
  990. @save -> flag;
  991. switch (flag) {
  992. 0: L__M(##Save, 1);
  993. 1: L__M(##Save, 2);
  994. 2:
  995. RestoreColours();
  996. L__M(##Restore, 2);
  997. }
  998. #Ifnot;
  999. save Smaybe;
  1000. return L__M(##Save, 1);
  1001. .SMaybe;
  1002. L__M(##Save, 2);
  1003. #Endif; ! V5
  1004. ];
  1005. [ VerifySub;
  1006. @verify ?Vmaybe;
  1007. jump Vwrong;
  1008. .Vmaybe;
  1009. return L__M(##Verify, 1);
  1010. .Vwrong;
  1011. L__M(##Verify, 2);
  1012. ];
  1013. [ ScriptOnSub;
  1014. transcript_mode = ((HDR_GAMEFLAGS-->0) & 1);
  1015. if (transcript_mode) return L__M(##ScriptOn, 1);
  1016. @output_stream 2;
  1017. if (((HDR_GAMEFLAGS-->0) & 1) == 0) return L__M(##ScriptOn, 3);
  1018. L__M(##ScriptOn, 2); VersionSub();
  1019. transcript_mode = true;
  1020. ];
  1021. [ ScriptOffSub;
  1022. transcript_mode = ((HDR_GAMEFLAGS-->0) & 1);
  1023. if (transcript_mode == false) return L__M(##ScriptOff, 1);
  1024. L__M(##ScriptOff, 2);
  1025. @output_stream -2;
  1026. if ((HDR_GAMEFLAGS-->0) & 1) return L__M(##ScriptOff, 3);
  1027. transcript_mode = false;
  1028. ];
  1029. [ CommandsOnSub;
  1030. @output_stream 4;
  1031. xcommsdir = 1;
  1032. L__M(##CommandsOn, 1);
  1033. ];
  1034. [ CommandsOffSub;
  1035. if (xcommsdir == 1) @output_stream -4;
  1036. xcommsdir = 0;
  1037. L__M(##CommandsOff, 1);
  1038. ];
  1039. [ CommandsReadSub;
  1040. @input_stream 1;
  1041. xcommsdir = 2;
  1042. L__M(##CommandsRead, 1);
  1043. ];
  1044. #Ifnot; ! TARGET_GLULX;
  1045. [ QuitSub;
  1046. L__M(##Quit, 2);
  1047. if (YesOrNo()) quit;
  1048. ];
  1049. [ RestartSub;
  1050. L__M(##Restart,1);
  1051. if (YesOrNo()) { @restart; L__M(##Restart, 2); }
  1052. ];
  1053. [ RestoreSub res fref;
  1054. fref = glk($0062, $01, $02, 0); ! fileref_create_by_prompt
  1055. if (fref == 0) jump RFailed;
  1056. gg_savestr = glk($0042, fref, $02, GG_SAVESTR_ROCK); ! stream_open_file
  1057. glk($0063, fref); ! fileref_destroy
  1058. if (gg_savestr == 0) jump RFailed;
  1059. @restore gg_savestr res;
  1060. glk($0044, gg_savestr, 0); ! stream_close
  1061. gg_savestr = 0;
  1062. .RFailed;
  1063. L__M(##Restore, 1);
  1064. ];
  1065. [ SaveSub res fref;
  1066. fref = glk($0062, $01, $01, 0); ! fileref_create_by_prompt
  1067. if (fref == 0) jump SFailed;
  1068. gg_savestr = glk($0042, fref, $01, GG_SAVESTR_ROCK); ! stream_open_file
  1069. glk($0063, fref); ! fileref_destroy
  1070. if (gg_savestr == 0) jump SFailed;
  1071. @save gg_savestr res;
  1072. if (res == -1) {
  1073. ! The player actually just typed "restore". We're going to print
  1074. ! L__M(##Restore,2); the Z-Code Inform library does this correctly
  1075. ! now. But first, we have to recover all the Glk objects; the values
  1076. ! in our global variables are all wrong.
  1077. GGRecoverObjects();
  1078. glk($0044, gg_savestr, 0); ! stream_close
  1079. gg_savestr = 0;
  1080. return L__M(##Restore, 2);
  1081. }
  1082. glk($0044, gg_savestr, 0); ! stream_close
  1083. gg_savestr = 0;
  1084. if (res == 0) return L__M(##Save, 2);
  1085. .SFailed;
  1086. L__M(##Save, 1);
  1087. ];
  1088. [ VerifySub res;
  1089. @verify res;
  1090. if (res == 0) return L__M(##Verify, 1);
  1091. L__M(##Verify, 2);
  1092. ];
  1093. [ ScriptOnSub;
  1094. if (gg_scriptstr) return L__M(##ScriptOn, 1);
  1095. if (gg_scriptfref == 0) {
  1096. ! fileref_create_by_prompt
  1097. gg_scriptfref = glk($0062, $102, $05, GG_SCRIPTFREF_ROCK);
  1098. if (gg_scriptfref == 0) jump S1Failed;
  1099. }
  1100. ! stream_open_file
  1101. gg_scriptstr = glk($0042, gg_scriptfref, $05, GG_SCRIPTSTR_ROCK);
  1102. if (gg_scriptstr == 0) jump S1Failed;
  1103. glk($002D, gg_mainwin, gg_scriptstr); ! window_set_echo_stream
  1104. L__M(##ScriptOn, 2);
  1105. VersionSub();
  1106. return;
  1107. .S1Failed;
  1108. L__M(##ScriptOn, 3);
  1109. ];
  1110. [ ScriptOffSub;
  1111. if (gg_scriptstr == 0) return L__M(##ScriptOff,1);
  1112. L__M(##ScriptOff, 2);
  1113. glk($0044, gg_scriptstr, 0); ! stream_close
  1114. gg_scriptstr = 0;
  1115. ];
  1116. [ CommandsOnSub fref;
  1117. if (gg_commandstr) {
  1118. if (gg_command_reading) return L__M(##CommandsOn, 2);
  1119. else return L__M(##CommandsOn, 3);
  1120. }
  1121. ! fileref_create_by_prompt
  1122. fref = glk($0062, $103, $01, 0);
  1123. if (fref == 0) return L__M(##CommandsOn, 4);
  1124. gg_command_reading = false;
  1125. ! stream_open_file
  1126. gg_commandstr = glk($0042, fref, $01, GG_COMMANDWSTR_ROCK);
  1127. glk($0063, fref); ! fileref_destroy
  1128. if (gg_commandstr == 0) return L__M(##CommandsOn, 4);
  1129. L__M(##CommandsOn, 1);
  1130. ];
  1131. [ CommandsOffSub;
  1132. if (gg_commandstr == 0) return L__M(##CommandsOff, 2);
  1133. if (gg_command_reading) return L__M(##CommandsRead, 5);
  1134. glk($0044, gg_commandstr, 0); ! stream_close
  1135. gg_commandstr = 0;
  1136. gg_command_reading = false;
  1137. L__M(##CommandsOff, 1);
  1138. ];
  1139. [ CommandsReadSub fref;
  1140. if (gg_commandstr) {
  1141. if (gg_command_reading) return L__M(##CommandsRead, 2);
  1142. else return L__M(##CommandsRead, 3);
  1143. }
  1144. ! fileref_create_by_prompt
  1145. fref = glk($0062, $103, $02, 0);
  1146. if (fref == 0) return L__M(##CommandsRead, 4);
  1147. gg_command_reading = true;
  1148. ! stream_open_file
  1149. gg_commandstr = glk($0042, fref, $02, GG_COMMANDRSTR_ROCK);
  1150. glk($0063, fref); ! fileref_destroy
  1151. if (gg_commandstr == 0) return L__M(##CommandsRead, 4);
  1152. L__M(##CommandsRead, 1);
  1153. ];
  1154. #Endif; ! TARGET_;
  1155. [ NotifyOnSub; notify_mode = true; L__M(##NotifyOn); ];
  1156. [ NotifyOffSub; notify_mode = false; L__M(##NotifyOff); ];
  1157. [ Places1Sub i j k;
  1158. L__M(##Places, 1);
  1159. objectloop (i has visited) j++;
  1160. objectloop (i has visited) {
  1161. print (name) i; k++;
  1162. if (k == j) return L__M(##Places, 2);
  1163. if (k == j-1) print (SerialComma) j, (string) AND__TX;
  1164. else print (string) COMMA__TX;
  1165. }
  1166. ];
  1167. [ Objects1Sub i j f;
  1168. L__M(##Objects, 1);
  1169. objectloop (i has moved) {
  1170. f = 1; print (the) i; j = parent(i);
  1171. if (j) {
  1172. if (j == player) {
  1173. if (i has worn) L__M(##Objects, 3, j, i);
  1174. else L__M(##Objects, 4, j, i);
  1175. jump Obj__Ptd;
  1176. }
  1177. if (j has animate) { L__M(##Objects, 5, j, i); jump Obj__Ptd; }
  1178. if (j has visited) { L__M(##Objects, 6, j, i); jump Obj__Ptd; }
  1179. if (j has container) { L__M(##Objects, 8, j, i); jump Obj__Ptd; }
  1180. if (j has supporter) { L__M(##Objects, 9, j, i); jump Obj__Ptd; }
  1181. if (j has enterable) { L__M(##Objects, 7, j, i); jump Obj__Ptd; }
  1182. }
  1183. L__M(##Objects, 10, j, i);
  1184. .Obj__Ptd;
  1185. new_line;
  1186. }
  1187. if (f == 0) L__M(##Objects, 2);
  1188. ];
  1189. ! ----------------------------------------------------------------------------
  1190. ! The scoring system
  1191. ! ----------------------------------------------------------------------------
  1192. [ ScoreSub;
  1193. #Ifdef NO_SCORE;
  1194. if (deadflag == 0) L__M(##Score, 2);
  1195. #Ifnot;
  1196. if (deadflag) new_line;
  1197. L__M(##Score, 1);
  1198. if(PrintRank() == false) LibraryExtensions.RunAll(ext_printrank);
  1199. #Endif; ! NO_SCORE
  1200. ];
  1201. #Ifndef TaskScore;
  1202. [ TaskScore i;
  1203. return task_scores->i;
  1204. ];
  1205. #Endif;
  1206. [ Achieved num;
  1207. if (task_done->num == 0) {
  1208. task_done->num = 1;
  1209. score = score + TaskScore(num);
  1210. }
  1211. ];
  1212. [ PANum m n;
  1213. print " ";
  1214. n = m;
  1215. if (n < 0) { n = -m; n = n*10; }
  1216. if (n < 10) { print " "; jump Panuml; }
  1217. if (n < 100) { print " "; jump Panuml; }
  1218. if (n < 1000) { print " "; }
  1219. .Panuml;
  1220. print m, " ";
  1221. ];
  1222. [ FullScoreSub i;
  1223. ScoreSub();
  1224. if (score == 0 || TASKS_PROVIDED == 1) rfalse;
  1225. new_line;
  1226. L__M(##FullScore, 1);
  1227. for (i=0 : i<NUMBER_TASKS : i++)
  1228. if (task_done->i == 1) {
  1229. PANum(TaskScore(i));
  1230. if(PrintTaskName(i) == false)
  1231. LibraryExtensions.RunAll(ext_printtaskname,i);
  1232. }
  1233. if (things_score) {
  1234. PANum(things_score);
  1235. L__M(##FullScore, 2);
  1236. }
  1237. if (places_score) {
  1238. PANum(places_score);
  1239. L__M(##FullScore, 3);
  1240. }
  1241. new_line; PANum(score); L__M(##FullScore, 4);
  1242. ];
  1243. ! ----------------------------------------------------------------------------
  1244. ! Real verbs start here: Inventory
  1245. ! ----------------------------------------------------------------------------
  1246. [ InvWideSub;
  1247. if (actor == player)
  1248. inventory_style = ENGLISH_BIT+FULLINV_BIT+RECURSE_BIT;
  1249. else
  1250. inventory_style = ENGLISH_BIT+PARTINV_BIT;
  1251. <Inv, actor>;
  1252. inventory_style = 0;
  1253. ];
  1254. [ InvTallSub;
  1255. if (actor == player)
  1256. inventory_style = NEWLINE_BIT+INDENT_BIT+FULLINV_BIT+RECURSE_BIT;
  1257. else
  1258. inventory_style = NEWLINE_BIT+INDENT_BIT+PARTINV_BIT;
  1259. <Inv, actor>;
  1260. inventory_style = 0;
  1261. ];
  1262. [ InvSub x;
  1263. if (child(actor) == 0) return L__M(##Inv, 1);
  1264. if (inventory_style == 0)
  1265. if (actor == player) return InvTallSub();
  1266. else return InvWideSub();
  1267. L__M(##Inv, 2);
  1268. if (inventory_style & NEWLINE_BIT) L__M(##Inv, 3); else print " ";
  1269. WriteListFrom(child(actor), inventory_style, 1);
  1270. if (inventory_style & ENGLISH_BIT) L__M(##Inv, 4);
  1271. #Ifndef MANUAL_PRONOUNS;
  1272. objectloop (x in player) PronounNotice(x);
  1273. #Endif;
  1274. x = 0; ! To prevent a "not used" error
  1275. AfterRoutines();
  1276. ];
  1277. ! ----------------------------------------------------------------------------
  1278. ! The object tree and determining the possibility of moves
  1279. ! ----------------------------------------------------------------------------
  1280. [ CommonAncestor o1 o2 i j;
  1281. ! Find the nearest object indirectly containing o1 and o2,
  1282. ! or return 0 if there is no common ancestor.
  1283. i = o1;
  1284. while (i) {
  1285. j = o2;
  1286. while (j) {
  1287. if (j == i) return i;
  1288. j = parent(j);
  1289. }
  1290. i = parent(i);
  1291. }
  1292. return 0;
  1293. ];
  1294. [ IndirectlyContains o1 o2;
  1295. ! Does o1 indirectly contain o2? (Same as testing if their common ancestor is o1.)
  1296. while (o2) {
  1297. if (o1 == o2) rtrue;
  1298. if (o2 ofclass Class) rfalse;
  1299. o2 = parent(o2);
  1300. }
  1301. rfalse;
  1302. ];
  1303. [ ObjectScopedBySomething item i j k l m;
  1304. i = item;
  1305. objectloop (j .& add_to_scope) {
  1306. l = j.&add_to_scope;
  1307. k = (j.#add_to_scope)/WORDSIZE;
  1308. if (l-->0 ofclass Routine) continue;
  1309. for (m=0 : m<k : m++)
  1310. if (l-->m == i) return j;
  1311. }
  1312. rfalse;
  1313. ];
  1314. [ ObjectIsUntouchable item flag1 flag2 ancestor i;
  1315. ! Determine if there's any barrier preventing the actor from moving
  1316. ! things to "item". Return false if no barrier; otherwise print a
  1317. ! suitable message and return true.
  1318. ! If flag1 is set, do not print any message.
  1319. ! If flag2 is set, also apply Take/Remove restrictions.
  1320. ! If the item has been added to scope by something, it's first necessary
  1321. ! for that something to be touchable.
  1322. ancestor = CommonAncestor(actor, item);
  1323. if (ancestor == 0) {
  1324. ancestor = item;
  1325. while (ancestor && (i = ObjectScopedBySomething(ancestor)) == 0)
  1326. ancestor = parent(ancestor);
  1327. if (i) {
  1328. if (ObjectIsUntouchable(i, flag1, flag2)) return;
  1329. ! An item immediately added to scope
  1330. }
  1331. }
  1332. else
  1333. ! First, a barrier between the actor and the ancestor. The actor
  1334. ! can only be in a sequence of enterable objects, and only closed
  1335. ! containers form a barrier.
  1336. if (actor ~= ancestor) {
  1337. i = parent(actor);
  1338. while (i ~= ancestor) {
  1339. if (i has container && i hasnt open) {
  1340. if (flag1) rtrue;
  1341. return L__M(##Take, 9, i, noun);
  1342. }
  1343. i = parent(i);
  1344. }
  1345. }
  1346. ! Second, a barrier between the item and the ancestor. The item can
  1347. ! be carried by someone, part of a piece of machinery, in or on top
  1348. ! of something and so on.
  1349. i = parent(item);
  1350. if (item ~= ancestor && i ~= player) {
  1351. while (i ~= ancestor) {
  1352. if (flag2 && i hasnt container && i hasnt supporter) {
  1353. if (i has animate) {
  1354. if (flag1) rtrue;
  1355. return L__M(##Take, 6, i, noun);
  1356. }
  1357. if (i has transparent) {
  1358. if (flag1) rtrue;
  1359. return L__M(##Take, 7, i, noun);
  1360. }
  1361. if (flag1) rtrue;
  1362. return L__M(##Take, 8, item, noun);
  1363. }
  1364. if (i has container && i hasnt open) {
  1365. if (flag1) rtrue;
  1366. return L__M(##Take, 9, i, noun);
  1367. }
  1368. i = parent(i);
  1369. }
  1370. }
  1371. rfalse;
  1372. ];
  1373. [ AttemptToTakeObject item
  1374. ancestor after_recipient i k;
  1375. ! Try to transfer the given item to the actor: return false
  1376. ! if successful, true if unsuccessful, printing a suitable message
  1377. ! in the latter case.
  1378. ! People cannot ordinarily be taken.
  1379. if (item == actor) return L__M(##Take, 2, noun);
  1380. if (item has animate) return L__M(##Take, 3, item);
  1381. ancestor = CommonAncestor(actor, item);
  1382. if (ancestor == 0) {
  1383. i = ObjectScopedBySomething(item);
  1384. if (i) ancestor = CommonAncestor(actor, i);
  1385. }
  1386. ! Is the actor indirectly inside the item?
  1387. if (ancestor == item) return L__M(##Take, 4, item);
  1388. ! Does the actor already directly contain the item?
  1389. if (item in actor) return L__M(##Take, 5, item);
  1390. ! Can the actor touch the item, or is there (e.g.) a closed container
  1391. ! in the way?
  1392. if (ObjectIsUntouchable(item, false, true)) rtrue;
  1393. ! The item is now known to be accessible.
  1394. ! Consult the immediate possessor of the item, if it's in a container
  1395. ! which the actor is not in.
  1396. i = parent(item);
  1397. if (i && i ~= ancestor && (i has container or supporter)) {
  1398. after_recipient = i;
  1399. k = action; action = ##LetGo;
  1400. if (RunRoutines(i, before)) { action = k; rtrue; }
  1401. action = k;
  1402. }
  1403. if (item has scenery) return L__M(##Take, 10, item);
  1404. if (item has static) return L__M(##Take, 11, item);
  1405. ! The item is now known to be available for taking. Is the player
  1406. ! carrying too much? If so, possibly juggle items into the rucksack
  1407. ! to make room.
  1408. if (ObjectDoesNotFit(item, actor) ||
  1409. LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, item, actor)) return;
  1410. if (AtFullCapacity(item, actor)) return L__M(##Take, 12, item);
  1411. ! Transfer the item.
  1412. move item to actor; give item ~worn;
  1413. ! Send "after" message to the object letting go of the item, if any.
  1414. if (after_recipient) {
  1415. k = action; action = ##LetGo;
  1416. if (RunRoutines(after_recipient, after)) { action = k; rtrue; }
  1417. action = k;
  1418. }
  1419. rfalse;
  1420. ];
  1421. [ AtFullCapacity n s
  1422. obj k;
  1423. n = n; ! suppress compiler warning
  1424. if (s == actor) {
  1425. objectloop (obj in s)
  1426. if (obj hasnt worn) k++;
  1427. } else
  1428. k = children(s);
  1429. if (k < RunRoutines(s, capacity) || (s == player && RoomInSack())) rfalse;
  1430. ];
  1431. [ RoomInSack
  1432. obj ks;
  1433. if (SACK_OBJECT && SACK_OBJECT in player) {
  1434. ks = keep_silent; keep_silent = 2;
  1435. for (obj=youngest(player) : obj : obj=elder(obj))
  1436. if (obj ~= SACK_OBJECT && obj hasnt worn or light) {
  1437. <Insert obj SACK_OBJECT>;
  1438. if (obj in SACK_OBJECT) {
  1439. keep_silent = ks;
  1440. return L__M(##Take, 13, obj, SACK_OBJECT);
  1441. }
  1442. }
  1443. keep_silent = ks;
  1444. }
  1445. rfalse;
  1446. ];
  1447. ! ----------------------------------------------------------------------------
  1448. ! Support for implicit actions
  1449. ! ----------------------------------------------------------------------------
  1450. [ CheckImplicitAction act o1 o2
  1451. sav_act sav_noun sav_sec res;
  1452. if (o1 provides before_implicit) {
  1453. sav_act = action; action = act;
  1454. sav_noun = noun; noun = o1;
  1455. if (o2) { sav_sec = second; second = o2; }
  1456. res = RunRoutines(o1, before_implicit);
  1457. action = sav_act; noun = sav_noun;
  1458. if (sav_sec) second = sav_sec;
  1459. }
  1460. else {
  1461. if (no_implicit_actions)
  1462. res = 2;
  1463. else
  1464. res = 0;
  1465. }
  1466. return res;
  1467. ];
  1468. [ ImplicitTake obj
  1469. res ks supcon;
  1470. switch (metaclass(obj)) { Class, String, Routine, nothing: rfalse; }
  1471. if (obj in actor) rfalse;
  1472. if (action_to_be == ##Drop) rfalse;
  1473. res = CheckImplicitAction(##Take, obj);
  1474. ! 0 = Take object, Tell the user (normal default)
  1475. ! 1 = Take object, don't Tell
  1476. ! 2 = don't Take object continue (default with no_implicit_actions)
  1477. ! 3 = don't Take object, don't continue
  1478. if (res >= 2) rtrue;
  1479. if (parent(obj) && parent(obj) has container or supporter) supcon = parent(obj);
  1480. ks = keep_silent; keep_silent = 2; AttemptToTakeObject(obj); keep_silent = ks;
  1481. if (obj notin actor) rtrue;
  1482. if (res == 0 && ~~keep_silent)
  1483. if (supcon) L__M(##Miscellany, 58, obj, supcon);
  1484. else L__M(##Miscellany, 26, obj);
  1485. rfalse;
  1486. ];
  1487. [ ImplicitExit obj
  1488. res ks;
  1489. if (parent(obj) == nothing) rfalse;
  1490. res = CheckImplicitAction(##Exit, obj);
  1491. ! 0 = Exit object, Tell the user (normal default)
  1492. ! 1 = Exit object, don't Tell
  1493. ! 2 = don't Take object continue (default with no_implicit_actions)
  1494. ! 3 = don't Take object, don't continue
  1495. if (res >= 2) rtrue;
  1496. ks = keep_silent; keep_silent = 2; <Exit obj, actor>; keep_silent = ks;
  1497. if (parent(actor) == obj) rtrue;
  1498. if (res == 0 && ~~keep_silent) L__M(##Exit, 5, obj);
  1499. rfalse;
  1500. ];
  1501. [ ImplicitClose obj
  1502. res ks;
  1503. if (obj hasnt open) rfalse;
  1504. res = CheckImplicitAction(##Close, obj);
  1505. ! 0 = Close object, Tell the user (normal default)
  1506. ! 1 = Close object, don't Tell
  1507. ! 2 = don't Take object continue (default with no_implicit_actions)
  1508. ! 3 = don't Take object, don't continue
  1509. if (res >= 2) rtrue;
  1510. ks = keep_silent; keep_silent = 2; <Close obj, actor>; keep_silent = ks;
  1511. if (obj has open) rtrue;
  1512. if (res == 0 && ~~keep_silent) L__M(##Close, 4, obj);
  1513. rfalse;
  1514. ];
  1515. [ ImplicitOpen obj
  1516. res ks;
  1517. if (obj has open) rfalse;
  1518. res = CheckImplicitAction(##Open, obj);
  1519. ! 0 = Open object, Tell the user (normal default)
  1520. ! 1 = Open object, don't Tell
  1521. ! 2 = don't Take object continue (default with no_implicit_actions)
  1522. ! 3 = don't Take object, don't continue
  1523. if (res >= 2) rtrue;
  1524. if (obj has locked) rtrue;
  1525. ks = keep_silent; keep_silent = 2; <Open obj, actor>; keep_silent = ks;
  1526. if (obj hasnt open) rtrue;
  1527. if (res == 0 && ~~keep_silent) L__M(##Open, 6, obj);
  1528. rfalse;
  1529. ];
  1530. [ ImplicitUnlock obj;
  1531. if (obj has locked) rtrue;
  1532. rfalse;
  1533. ];
  1534. [ ImplicitDisrobe obj
  1535. res ks;
  1536. if (obj hasnt worn) rfalse;
  1537. res = CheckImplicitAction(##Disrobe, obj);
  1538. ! 0 = Take off object, Tell the user (normal default)
  1539. ! 1 = Take off object, don't Tell
  1540. ! 2 = don't Take object continue (default with no_implicit_actions)
  1541. ! 3 = don't Take object, don't continue
  1542. if (res >= 2) rtrue;
  1543. ks = keep_silent; keep_silent = 1; <Disrobe obj, actor>; keep_silent = ks;
  1544. if (obj has worn && obj in actor) rtrue;
  1545. if (res == 0 && ~~keep_silent) L__M(##Drop, 3, noun);
  1546. rfalse;
  1547. ];
  1548. ! ----------------------------------------------------------------------------
  1549. ! Object movement verbs
  1550. ! ----------------------------------------------------------------------------
  1551. [ TakeSub;
  1552. if (onotheld_mode == 0 || noun notin actor)
  1553. if (AttemptToTakeObject(noun)) return;
  1554. if (AfterRoutines()) return;
  1555. notheld_mode = onotheld_mode;
  1556. if (notheld_mode == 1 || keep_silent) return;
  1557. L__M(##Take, 1, noun);
  1558. ];
  1559. [ RemoveSub i;
  1560. i = parent(noun);
  1561. if (i && i has container && i hasnt open && ImplicitOpen(i)) return L__M(##Remove, 1, noun);
  1562. if (i ~= second) return L__M(##Remove, 2, noun);
  1563. if (i has animate) return L__M(##Take, 6, i, noun);
  1564. if (AttemptToTakeObject(noun)) rtrue;
  1565. action = ##Remove; if (AfterRoutines()) return;
  1566. action = ##Take; if (AfterRoutines()) return;
  1567. if (keep_silent) return;
  1568. L__M(##Remove, 3, noun);
  1569. ];
  1570. [ DropSub;
  1571. if (noun == actor) return L__M(##PutOn, 4, noun);
  1572. if (noun in parent(actor)) return L__M(##Drop, 1, noun);
  1573. if (noun notin actor && ~~ImplicitTake(noun)) return L__M(##Drop, 2, noun);
  1574. if (noun has worn && ImplicitDisrobe(noun)) return;
  1575. move noun to parent(actor);
  1576. if (AfterRoutines() || keep_silent) return;
  1577. L__M(##Drop, 4, noun);
  1578. ];
  1579. [ PutOnSub ancestor;
  1580. receive_action = ##PutOn;
  1581. if (second == d_obj || actor in second) <<Drop noun, actor>>;
  1582. if (parent(noun) == second) return L__M(##Drop, 1, noun);
  1583. if (noun notin actor && ImplicitTake(noun)) return L__M(##PutOn, 1, noun);
  1584. ancestor = CommonAncestor(noun, second);
  1585. if (ancestor == noun) return L__M(##PutOn, 2, noun);
  1586. if (ObjectIsUntouchable(second)) return;
  1587. if (second ~= ancestor) {
  1588. action = ##Receive;
  1589. if (RunRoutines(second, before)) { action = ##PutOn; return; }
  1590. action = ##PutOn;
  1591. }
  1592. if (second hasnt supporter) return L__M(##PutOn, 3, second);
  1593. if (ancestor == actor) return L__M(##PutOn, 4, second);
  1594. if (noun has worn && ImplicitDisrobe(noun)) return;
  1595. if (ObjectDoesNotFit(noun, second) ||
  1596. LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, noun, second)) return;
  1597. if (AtFullCapacity(noun, second)) return L__M(##PutOn, 6, second);
  1598. move noun to second;
  1599. if (AfterRoutines()) return;
  1600. if (second ~= ancestor) {
  1601. action = ##Receive;
  1602. if (RunRoutines(second, after)) { action = ##PutOn; return; }
  1603. action = ##PutOn;
  1604. }
  1605. if (keep_silent) return;
  1606. if (multiflag) return L__M(##PutOn, 7);
  1607. L__M(##PutOn, 8, noun, second);
  1608. ];
  1609. [ InsertSub ancestor;
  1610. receive_action = ##Insert;
  1611. if (second == d_obj || actor in second) <<Drop noun, actor>>;
  1612. if (parent(noun) == second) return L__M(##Drop, 1, noun);
  1613. if (noun notin actor && ImplicitTake(noun)) return L__M(##Insert, 1, noun);
  1614. ancestor = CommonAncestor(noun, second);
  1615. if (ancestor == noun) return L__M(##Insert, 5, noun);
  1616. if (ObjectIsUntouchable(second)) return;
  1617. if (second ~= ancestor) {
  1618. action = ##Receive;
  1619. if (RunRoutines(second,before)) { action = ##Insert; rtrue; }
  1620. action = ##Insert;
  1621. if (second has container && second hasnt open && ImplicitOpen(second))
  1622. return L__M(##Insert, 3, second);
  1623. }
  1624. if (second hasnt container) return L__M(##Insert, 2, second);
  1625. if (noun has worn && ImplicitDisrobe(noun)) return;
  1626. if (ObjectDoesNotFit(noun, second) ||
  1627. LibraryExtensions.RunWhile(ext_objectdoesnotfit, false, noun, second)) return;
  1628. if (AtFullCapacity(noun, second)) return L__M(##Insert, 7, second);
  1629. move noun to second;
  1630. if (second ~= ancestor) {
  1631. action = ##Receive;
  1632. if (RunRoutines(second, after)) { action = ##Insert; rtrue; }
  1633. action = ##Insert;
  1634. }
  1635. if (keep_silent) rtrue;
  1636. if (multiflag) return L__M(##Insert, 8, noun);
  1637. L__M(##Insert, 9, noun, second);
  1638. ];
  1639. ! ----------------------------------------------------------------------------
  1640. ! Empties and transfers are routed through the actions above
  1641. ! ----------------------------------------------------------------------------
  1642. [ TransferSub;
  1643. if (noun notin actor && AttemptToTakeObject(noun)) return;
  1644. if (second has supporter) <<PutOn noun second, actor>>;
  1645. if (second == d_obj) <<Drop noun, actor>>;
  1646. <<Insert noun second, actor>>;
  1647. ];
  1648. [ EmptySub; second = d_obj; EmptyTSub(); ];
  1649. [ EmptyTSub i j k flag;
  1650. if (noun == second) return L__M(##EmptyT, 4, noun);
  1651. if (ObjectIsUntouchable(noun)) return;
  1652. if (noun hasnt container) return L__M(##EmptyT, 1, noun);
  1653. if (noun hasnt open && ImplicitOpen(noun)) return L__M(##EmptyT, 2, noun);
  1654. if (second ~= d_obj) {
  1655. if (second hasnt supporter) {
  1656. if (second hasnt container) return L__M(##EmptyT, 1, second);
  1657. if (second hasnt open && ImplicitOpen(second))
  1658. return L__M(##EmptyT, 2, second);
  1659. }
  1660. }
  1661. i = child(noun); k = children(noun);
  1662. if (i == 0) return L__M(##EmptyT, 3, noun);
  1663. while (i) {
  1664. j = sibling(i);
  1665. flag = false;
  1666. if (ObjectIsUntouchable(noun)) flag = true;
  1667. if (noun hasnt container) flag = true;
  1668. if (noun hasnt open) flag = true;
  1669. if (second ~= d_obj) {
  1670. if (second hasnt supporter) {
  1671. if (second hasnt container) flag = true;
  1672. if (second hasnt open) flag = true;
  1673. }
  1674. }
  1675. if (k-- == 0) flag = 1;
  1676. if (flag) break;
  1677. if (keep_silent == 0) print (name) i, (string) COLON__TX;
  1678. <Transfer i second, actor>;
  1679. i = j;
  1680. }
  1681. ];
  1682. ! ----------------------------------------------------------------------------
  1683. ! Gifts
  1684. ! ----------------------------------------------------------------------------
  1685. [ GiveSub;
  1686. if (noun notin actor && ImplicitTake(noun)) return L__M(##Give, 1, noun);
  1687. if (second == actor) return L__M(##Give, 2, noun);
  1688. if (noun has worn && ImplicitDisrobe(noun)) return;
  1689. if (second == player) {
  1690. move noun to player;
  1691. return L__M(##Give, 4, noun);
  1692. }
  1693. if (RunLife(second, ##Give)) return;
  1694. L__M(##Give, 3, second);
  1695. ];
  1696. [ GiveRSub; <Give second noun, actor>; ];
  1697. [ ShowSub;
  1698. if (noun notin actor && ImplicitTake(noun)) return L__M(##Show, 1, noun);
  1699. if (second == player) <<Examine noun, actor>>;
  1700. if (RunLife(second, ##Show)) return;
  1701. L__M(##Show, 2, second);
  1702. ];
  1703. [ ShowRSub; <Show second noun, actor>; ];
  1704. ! ----------------------------------------------------------------------------
  1705. ! Travelling around verbs
  1706. ! ----------------------------------------------------------------------------
  1707. [ EnterSub ancestor j ks;
  1708. if (noun has door || noun in compass) <<Go noun, actor>>;
  1709. if (actor in noun) return L__M(##Enter, 1, noun);
  1710. if (noun hasnt enterable) return L__M(##Enter, 2, noun, verb_word);
  1711. if (parent(actor) ~= parent(noun)) {
  1712. ancestor = CommonAncestor(actor, noun);
  1713. if (ancestor == actor or 0) return L__M(##Enter, 4, noun);
  1714. while (actor notin ancestor) {
  1715. j = parent(actor);
  1716. ks = keep_silent;
  1717. if (parent(j) ~= ancestor || noun ~= ancestor) {
  1718. L__M(##Enter, 6, j);
  1719. keep_silent = 1;
  1720. }
  1721. <Exit, actor>;
  1722. keep_silent = ks;
  1723. if (actor in j) return;
  1724. }
  1725. if (actor in noun) return;
  1726. if (noun notin ancestor) {
  1727. j = parent(noun);
  1728. while (parent(j) ~= ancestor) j = parent(j);
  1729. L__M(##Enter, 7, j);
  1730. ks = keep_silent; keep_silent = 1;
  1731. <Enter j, actor>;
  1732. keep_silent = ks;
  1733. if (actor notin j) return;
  1734. <<Enter noun, actor>>;
  1735. }
  1736. }
  1737. if (noun has container && noun hasnt open && ImplicitOpen(noun)) return L__M(##Enter, 3, noun);
  1738. move actor to noun;
  1739. if (AfterRoutines() || keep_silent) return;
  1740. L__M(##Enter, 5, noun);
  1741. if (actor == player) Locale(noun);
  1742. ];
  1743. [ GetOffSub;
  1744. if (parent(actor) == noun) <<Exit, actor>>;
  1745. L__M(##GetOff, 1, noun);
  1746. ];
  1747. [ ExitSub p;
  1748. p = parent(actor);
  1749. if (noun ~= nothing && noun ~= p) return L__M(##Exit, 4 ,noun);
  1750. if (p == location || (location == thedark && p == real_location)) {
  1751. if (actor provides posture && actor.posture) {
  1752. actor.posture = 0;
  1753. return L__M(##Exit, 6);
  1754. }
  1755. if ((location.out_to) || (location == thedark && real_location.out_to))
  1756. <<Go out_obj, actor>>;
  1757. return L__M(##Exit, 1);
  1758. }
  1759. if (p has container && p hasnt open && ImplicitOpen(p))
  1760. return L__M(##Exit, 2, p);
  1761. if (noun == nothing) {
  1762. inp1 = p;
  1763. if (RunRoutines(p, before)) return;
  1764. }
  1765. move actor to parent(p);
  1766. if (player provides posture) player.posture = 0;
  1767. if (AfterRoutines() || keep_silent) return;
  1768. L__M(##Exit, 3, p);
  1769. if (actor == player && p has container) LookSub(1);
  1770. ];
  1771. [ VagueGoSub; L__M(##VagueGo); ];
  1772. [ GoInSub; <<Go in_obj, actor>>; ];
  1773. [ GoSub i j k movewith thedir next_loc;
  1774. ! first, check if any PushDir object is touchable
  1775. if (second && second notin Compass && ObjectIsUntouchable(second)) return;
  1776. movewith = 0;
  1777. i = parent(actor);
  1778. if ((location ~= thedark && i ~= location) || (location == thedark && i ~= real_location)) {
  1779. j = location;
  1780. if (location == thedark) location = real_location;
  1781. k = RunRoutines(i, before); if (k ~= 3) location = j;
  1782. if (k == 1) {
  1783. movewith = i; i = parent(i);
  1784. }
  1785. else {
  1786. if (k) rtrue;
  1787. if (ImplicitExit(i)) return L__M(##Go, 1, i);
  1788. i = parent(actor);
  1789. }
  1790. }
  1791. thedir = noun.door_dir;
  1792. if (metaclass(thedir) == Routine) thedir = RunRoutines(noun, door_dir);
  1793. next_loc = i.thedir; k = metaclass(next_loc);
  1794. if (k == String) { print (string) next_loc; new_line; rfalse; }
  1795. if (k == Routine) {
  1796. next_loc = RunRoutines(i, thedir);
  1797. if (next_loc == 1) rtrue;
  1798. }
  1799. if (k == nothing || next_loc == 0) {
  1800. if (i.cant_go ~= 0 or CANTGO__TX) PrintOrRun(i, cant_go);
  1801. else L__M(##Go, 2);
  1802. rfalse;
  1803. }
  1804. if (next_loc has door) {
  1805. if (next_loc has concealed) return L__M(##Go, 2);
  1806. if (next_loc hasnt open && ImplicitOpen(next_loc)) {
  1807. if (noun == u_obj) return L__M(##Go, 3, next_loc);
  1808. if (noun == d_obj) return L__M(##Go, 4, next_loc);
  1809. return L__M(##Go, 5, next_loc);
  1810. }
  1811. k = RunRoutines(next_loc, door_to);
  1812. if (k == 0) return L__M(##Go, 6, next_loc);
  1813. if (k == 1) rtrue;
  1814. next_loc = k;
  1815. }
  1816. action = ##Going;
  1817. if (RunRoutines(next_loc, before)) { action = ##Go; return; }
  1818. action = ##Go;
  1819. if (movewith == 0) move actor to next_loc; else move movewith to next_loc;
  1820. if (actor ~= player) return L__M(##Go, 7);
  1821. k = location; location = next_loc;
  1822. MoveFloatingObjects();
  1823. if (OffersLight(location))
  1824. lightflag = true;
  1825. else {
  1826. lightflag = false;
  1827. if (k == thedark) {
  1828. if(DarkToDark() == false) ! From real_location To location
  1829. LibraryExtensions.RunAll(ext_darktodark);
  1830. if (deadflag) rtrue;
  1831. }
  1832. location = thedark;
  1833. }
  1834. NoteDeparture(); real_location = next_loc;
  1835. action = ##Going;
  1836. if (RunRoutines(prev_location, after)) { action = ##Go; return; }
  1837. action = ##Go;
  1838. if (AfterRoutines() || keep_silent) return;
  1839. LookSub(1);
  1840. ];
  1841. ! ----------------------------------------------------------------------------
  1842. ! Describing the world. SayWhatsOn(object) does just that (producing
  1843. ! no text if nothing except possibly "scenery" and "concealed" items are).
  1844. ! Locale(object) runs through the "tail end" of a Look-style room
  1845. ! description for the contents of the object, printing up suitable
  1846. ! descriptions as it goes.
  1847. ! ----------------------------------------------------------------------------
  1848. [ SayWhatsOn descon j f;
  1849. if (descon == parent(player)) rfalse;
  1850. objectloop (j in descon)
  1851. if (j hasnt concealed && j hasnt scenery) f = 1;
  1852. if (f == 0) rfalse;
  1853. L__M(##Look, 4, descon);
  1854. ];
  1855. [ NotSupportingThePlayer o i;
  1856. i = parent(player);
  1857. while (i && i ~= visibility_ceiling) {
  1858. if (i == o) rfalse;
  1859. i = parent(i);
  1860. if (i && i hasnt supporter) rtrue;
  1861. }
  1862. rtrue;
  1863. ];
  1864. ! modified with the fix for L61122
  1865. [ Locale descin text_without_ALSO text_with_ALSO
  1866. o p num_objs must_print_ALSO;
  1867. objectloop (o in descin) give o ~workflag;
  1868. num_objs = 0;
  1869. objectloop (o in descin)
  1870. if (o hasnt concealed && NotSupportingThePlayer(o)) {
  1871. #Ifndef MANUAL_PRONOUNS;
  1872. PronounNotice(o);
  1873. #Endif;
  1874. if (o has scenery) {
  1875. if (o has supporter && child(o)) SayWhatsOn(o);
  1876. }
  1877. else {
  1878. give o workflag; num_objs++;
  1879. p = initial;
  1880. if ((o has door or container) && o has open && o provides when_open) {
  1881. p = when_open; jump Prop_Chosen;
  1882. }
  1883. if ((o has door or container) && o hasnt open && o provides when_closed) {
  1884. p = when_closed; jump Prop_Chosen;
  1885. }
  1886. if (o has switchable && o has on && o provides when_on) {
  1887. p = when_on; jump Prop_Chosen;
  1888. }
  1889. if (o has switchable && o hasnt on && o provides when_off) {
  1890. p = when_off;
  1891. }
  1892. .Prop_Chosen;
  1893. if (o.&describe && RunRoutines(o, describe)) {
  1894. must_print_ALSO = true;
  1895. give o ~workflag; num_objs--;
  1896. continue;
  1897. }
  1898. if (o.p && (o hasnt moved || p ~= initial)) {
  1899. new_line;
  1900. PrintOrRun(o, p);
  1901. must_print_ALSO = true;
  1902. give o ~workflag; num_objs--;
  1903. if (o has supporter && child(o)) SayWhatsOn(o);
  1904. }
  1905. }
  1906. }
  1907. if (num_objs == 0) return 0;
  1908. if (actor ~= player) give actor concealed;
  1909. if (text_without_ALSO) {
  1910. new_line;
  1911. if (must_print_ALSO) print (string) text_with_ALSO, " ";
  1912. else print (string) text_without_ALSO, " ";
  1913. WriteListFrom(child(descin),
  1914. ENGLISH_BIT+RECURSE_BIT+PARTINV_BIT+TERSE_BIT+CONCEAL_BIT+WORKFLAG_BIT);
  1915. }
  1916. else {
  1917. if (must_print_ALSO) L__M(##Look, 5, descin);
  1918. else L__M(##Look, 6, descin);
  1919. }
  1920. if (actor ~= player) give actor ~concealed;
  1921. return num_objs;
  1922. ];
  1923. ! ----------------------------------------------------------------------------
  1924. ! Looking. LookSub(1) is allowed to abbreviate long descriptions, but
  1925. ! LookSub(0) (which is what happens when the Look action is generated)
  1926. ! isn't. (Except that these are over-ridden by the player-set lookmode.)
  1927. ! ----------------------------------------------------------------------------
  1928. [ LMode1Sub; lookmode=1; print (string) Story; L__M(##LMode1); ]; ! Brief
  1929. [ LMode2Sub; lookmode=2; print (string) Story; L__M(##LMode2); ]; ! Verbose
  1930. [ LMode3Sub; lookmode=3; print (string) Story; L__M(##LMode3); ]; ! Superbrief
  1931. [ LModeNormalSub; ! 'normal' value: the default, or as set in Initialise()
  1932. switch (initial_lookmode) {
  1933. 1: <<LMode1>>;
  1934. 3: <<LMode3>>;
  1935. default: <<LMode2>>;
  1936. }
  1937. ];
  1938. [ NoteArrival descin;
  1939. if (location ~= lastdesc) {
  1940. if (location.initial) PrintOrRun(location, initial);
  1941. if (location == thedark) { lastdesc = thedark; return; }
  1942. descin = location;
  1943. if(NewRoom() == false) LibraryExtensions.RunAll(ext_newroom);
  1944. lastdesc = descin;
  1945. }
  1946. ];
  1947. [ NoteDeparture;
  1948. prev_location = real_location;
  1949. ];
  1950. [ ScoreArrival;
  1951. if (location hasnt visited) {
  1952. give location visited;
  1953. if (location has scored) {
  1954. score = score + ROOM_SCORE;
  1955. places_score = places_score + ROOM_SCORE;
  1956. }
  1957. }
  1958. ];
  1959. [ FindVisibilityLevels visibility_levels;
  1960. visibility_levels = 1;
  1961. visibility_ceiling = parent(player);
  1962. while ((parent(visibility_ceiling)) &&
  1963. (visibility_ceiling hasnt container || visibility_ceiling has open or transparent)) {
  1964. visibility_ceiling = parent(visibility_ceiling);
  1965. visibility_levels++;
  1966. }
  1967. return visibility_levels;
  1968. ];
  1969. [ LookSub allow_abbrev visibility_levels i j k nl_flag;
  1970. if (parent(player) == 0) return RunTimeError(10);
  1971. .MovedByInitial;
  1972. if (location == thedark) { visibility_ceiling = thedark; NoteArrival(); }
  1973. else {
  1974. visibility_levels = FindVisibilityLevels();
  1975. if (visibility_ceiling == location) {
  1976. NoteArrival();
  1977. if (visibility_ceiling ~= location) jump MovedByInitial;
  1978. }
  1979. }
  1980. ! Printing the top line: e.g.
  1981. ! Octagonal Room (on the table) (as Frodo)
  1982. new_line;
  1983. #Ifdef TARGET_ZCODE;
  1984. style bold;
  1985. #Ifnot; ! TARGET_GLULX;
  1986. glk($0086, 4); ! set subheader style
  1987. #Endif; ! TARGET_
  1988. if (visibility_levels == 0) print (name) thedark;
  1989. else {
  1990. if (visibility_ceiling ~= location) print (The) visibility_ceiling;
  1991. else print (name) visibility_ceiling;
  1992. }
  1993. #Ifdef TARGET_ZCODE;
  1994. style roman;
  1995. #Ifnot; ! TARGET_GLULX;
  1996. glk($0086, 0); ! set normal style
  1997. #Endif; ! TARGET_
  1998. for (j=1,i=parent(player) : j<visibility_levels : j++,i=parent(i))
  1999. if (i has supporter) L__M(##Look, 1, i);
  2000. else L__M(##Look, 2, i);
  2001. if (print_player_flag == 1) L__M(##Look, 3, player);
  2002. new_line;
  2003. ! The room description (if visible)
  2004. if (lookmode < 3 && visibility_ceiling == location) {
  2005. if ((allow_abbrev ~= 1) || (lookmode == 2) || (location hasnt visited)) {
  2006. if (location.&describe) RunRoutines(location, describe);
  2007. else {
  2008. if (location.description == 0) RunTimeError(11, location, description);
  2009. else PrintOrRun(location, description);
  2010. }
  2011. }
  2012. }
  2013. if (visibility_ceiling == location) nl_flag = 1;
  2014. if (visibility_levels == 0) Locale(thedark);
  2015. else {
  2016. for (i=player,j=visibility_levels : j>0 : j--,i=parent(i)) give i workflag;
  2017. for (j=visibility_levels : j>0 : j--) {
  2018. for (i=player,k=0 : k<j : k++) i=parent(i);
  2019. if (i.inside_description) {
  2020. if (nl_flag) new_line; else nl_flag = 1;
  2021. PrintOrRun(i,inside_description);
  2022. }
  2023. if (Locale(i)) nl_flag=1;
  2024. }
  2025. }
  2026. if(LookRoutine() == false) LibraryExtensions.RunAll(ext_lookroutine);
  2027. ScoreArrival();
  2028. action = ##Look;
  2029. AfterRoutines();
  2030. ];
  2031. [ ExamineSub i;
  2032. if (location == thedark) return L__M(##Examine, 1, noun);
  2033. i = noun.description;
  2034. if (i == 0) {
  2035. if (noun has container)
  2036. if (noun has open) <<Search noun, actor>>;
  2037. else return L__M(##Search, 5, noun);
  2038. if (noun has switchable) { L__M(##Examine, 3, noun); rfalse; }
  2039. return L__M(##Examine, 2, noun);
  2040. }
  2041. i = PrintOrRun(noun, description);
  2042. if (i < 2 && noun has switchable) L__M(##Examine, 3, noun);
  2043. AfterRoutines();
  2044. ];
  2045. [ LookUnderSub;
  2046. if (location == thedark) return L__M(##LookUnder, 1, noun);
  2047. L__M(##LookUnder, 2);
  2048. ];
  2049. [ VisibleContents o i f;
  2050. objectloop (i in o) if (i hasnt concealed or scenery) f++;
  2051. return f;
  2052. ];
  2053. [ SearchSub f;
  2054. if (location == thedark) return L__M(##Search, 1, noun);
  2055. if (ObjectIsUntouchable(noun)) return;
  2056. f = VisibleContents(noun);
  2057. if (noun has supporter) {
  2058. if (f == 0) return L__M(##Search, 2, noun);
  2059. return L__M(##Search, 3, noun);
  2060. }
  2061. if (noun hasnt container) return L__M(##Search, 4, noun);
  2062. if (noun hasnt transparent or open && ImplicitOpen(noun)) return L__M(##Search, 5, noun);
  2063. if (AfterRoutines()) return;
  2064. if (f == 0) return L__M(##Search, 6, noun);
  2065. L__M(##Search, 7, noun);
  2066. ];
  2067. ! ----------------------------------------------------------------------------
  2068. ! Verbs which change the state of objects without moving them
  2069. ! ----------------------------------------------------------------------------
  2070. [ UnlockSub;
  2071. if (ObjectIsUntouchable(noun)) return;
  2072. if (noun hasnt lockable) return L__M(##Unlock, 1, noun);
  2073. if (noun hasnt locked) return L__M(##Unlock, 2, noun);
  2074. if (noun.with_key ~= second) return L__M(##Unlock, 3, second);
  2075. give noun ~locked;
  2076. if (AfterRoutines() || keep_silent) return;
  2077. L__M(##Unlock, 4, noun);
  2078. ];
  2079. [ LockSub;
  2080. if (ObjectIsUntouchable(noun)) return;
  2081. if (noun hasnt lockable) return L__M(##Lock, 1, noun);
  2082. if (noun has locked) return L__M(##Lock, 2 ,noun);
  2083. if (noun has open && ImplicitClose(noun)) return L__M(##Lock, 3, noun);
  2084. if (noun.with_key ~= second) return L__M(##Lock, 4, second);
  2085. give noun locked;
  2086. if (AfterRoutines() || keep_silent) return;
  2087. L__M(##Lock, 5, noun);
  2088. ];
  2089. [ SwitchonSub;
  2090. if (ObjectIsUntouchable(noun)) return;
  2091. if (noun hasnt switchable) return L__M(##SwitchOn, 1, noun);
  2092. if (noun has on) return L__M(##SwitchOn, 2, noun);
  2093. give noun on;
  2094. if (AfterRoutines() || keep_silent) return;
  2095. L__M(##SwitchOn, 3, noun);
  2096. ];
  2097. [ SwitchoffSub;
  2098. if (ObjectIsUntouchable(noun)) return;
  2099. if (noun hasnt switchable) return L__M(##SwitchOff, 1, noun);
  2100. if (noun hasnt on) return L__M(##SwitchOff, 2, noun);
  2101. give noun ~on;
  2102. if (AfterRoutines() || keep_silent) return;
  2103. L__M(##SwitchOff, 3, noun);
  2104. ];
  2105. [ OpenSub;
  2106. if (ObjectIsUntouchable(noun)) return;
  2107. if (noun hasnt openable) return L__M(##Open, 1, noun);
  2108. if (noun has locked && ImplicitUnlock(noun)) return L__M(##Open, 2, noun);
  2109. if (noun has open) return L__M(##Open, 3, noun);
  2110. give noun open;
  2111. if (AfterRoutines() || keep_silent) return;
  2112. if (noun hasnt container)
  2113. return L__M(##Open, 5, noun);
  2114. if ((noun has container && location ~= thedark && VisibleContents(noun)
  2115. && IndirectlyContains(noun, player)) == 0) {
  2116. if (noun hasnt transparent && noun hasnt door) return L__M(##Open, 4, noun);
  2117. }
  2118. L__M(##Open, 5, noun);
  2119. ];
  2120. [ CloseSub;
  2121. if (ObjectIsUntouchable(noun)) return;
  2122. if (noun hasnt openable) return L__M(##Close, 1, noun);
  2123. if (noun hasnt open) return L__M(##Close, 2, noun);
  2124. give noun ~open;
  2125. if (AfterRoutines() || keep_silent) return;
  2126. L__M(##Close, 3, noun);
  2127. ];
  2128. [ DisrobeSub;
  2129. if (ObjectIsUntouchable(noun)) return;
  2130. if (noun hasnt worn) return L__M(##Disrobe, 1, noun);
  2131. give noun ~worn;
  2132. if (AfterRoutines() || keep_silent) return;
  2133. L__M(##Disrobe, 2, noun);
  2134. ];
  2135. [ WearSub;
  2136. if (ObjectIsUntouchable(noun)) return;
  2137. if (noun hasnt clothing) return L__M(##Wear, 1, noun);
  2138. if (noun notin actor && ImplicitTake(noun)) return L__M(##Wear, 2, noun);
  2139. if (noun has worn) return L__M(##Wear, 3, noun);
  2140. give noun worn;
  2141. if (AfterRoutines() || keep_silent) return;
  2142. L__M(##Wear, 4, noun);
  2143. ];
  2144. [ EatSub;
  2145. if (ObjectIsUntouchable(noun)) return;
  2146. if (noun hasnt edible) return L__M(##Eat, 1, noun);
  2147. if (noun has worn && ImplicitDisrobe(noun)) return;
  2148. remove noun;
  2149. if (AfterRoutines() || keep_silent) return;
  2150. L__M(##Eat, 2, noun);
  2151. ];
  2152. ! ----------------------------------------------------------------------------
  2153. ! Verbs which are really just stubs (anything which happens for these
  2154. ! actions must happen in before rules)
  2155. ! ----------------------------------------------------------------------------
  2156. [ AllowPushDir i;
  2157. if (parent(second) ~= compass) return L__M(##PushDir, 2, noun);
  2158. if (second == u_obj or d_obj) return L__M(##PushDir, 3, noun);
  2159. AfterRoutines(); i = noun; move i to actor;
  2160. <Go second, actor>;
  2161. if (location == thedark) move i to real_location;
  2162. else move i to location;
  2163. ];
  2164. [ AnswerSub;
  2165. if (second && RunLife(second,##Answer)) rfalse;
  2166. L__M(##Answer, 1, noun);
  2167. ];
  2168. [ AskSub;
  2169. if (RunLife(noun,##Ask)) rfalse;
  2170. L__M(##Ask, 1, noun);
  2171. ];
  2172. [ AskForSub;
  2173. if (noun == player) <<Inv, actor>>;
  2174. L__M(##Order, 1, noun);
  2175. ];
  2176. [ AskToSub; L__M(##Order, 1, noun); ];
  2177. [ AttackSub;
  2178. if (ObjectIsUntouchable(noun)) return;
  2179. if (noun has animate && RunLife(noun, ##Attack)) rfalse;
  2180. L__M(##Attack, 1, noun);
  2181. ];
  2182. [ BlowSub; L__M(##Blow, 1, noun); ];
  2183. [ BurnSub;
  2184. if (noun has animate) return L__M(##Burn, 2, noun);
  2185. L__M(##Burn, 1, noun);
  2186. ];
  2187. [ BuySub; L__M(##Buy, 1, noun); ];
  2188. [ ClimbSub;
  2189. if (noun has animate) return L__M(##Climb, 2, noun);
  2190. L__M(##Climb, 1, noun);
  2191. ];
  2192. [ ConsultSub; L__M(##Consult, 1, noun); ];
  2193. [ CutSub;
  2194. if (noun has animate) return L__M(##Cut, 2, noun);
  2195. L__M(##Cut, 1, noun);
  2196. ];
  2197. [ DigSub; L__M(##Dig, 1, noun); ];
  2198. [ DrinkSub; L__M(##Drink, 1, noun); ];
  2199. [ FillSub;
  2200. if (second == nothing) return L__M(##Fill, 1, noun);
  2201. L__M(##Fill, 2, noun, second);
  2202. ];
  2203. [ JumpSub; L__M(##Jump, 1, noun); ];
  2204. [ JumpInSub;
  2205. if (noun has animate) return L__M(##JumpIn, 2, noun);
  2206. if (noun has enterable) <<Enter noun>>;
  2207. L__M(##JumpOn, 1, noun);
  2208. ];
  2209. [ JumpOnSub;
  2210. if (noun has animate) return L__M(##JumpOn, 2, noun);
  2211. if (noun has enterable && noun has supporter) <<Enter noun>>;
  2212. L__M(##JumpOn, 1, noun);
  2213. ];
  2214. [ JumpOverSub;
  2215. if (noun has animate) return L__M(##JumpOver, 2, noun);
  2216. L__M(##JumpOver, 1, noun);
  2217. ];
  2218. [ KissSub;
  2219. if (ObjectIsUntouchable(noun)) return;
  2220. if (RunLife(noun, ##Kiss)) return;
  2221. if (noun == actor) return L__M(##Touch, 3, noun);
  2222. L__M(##Kiss, 1, noun);
  2223. ];
  2224. [ ListenSub; L__M(##Listen, 1, noun); ];
  2225. [ MildSub; L__M(##Mild, 1, noun); ];
  2226. [ NoSub; L__M(##No); ];
  2227. [ PraySub; L__M(##Pray, 1, noun); ];
  2228. [ PullSub;
  2229. if (ObjectIsUntouchable(noun)) return;
  2230. if (noun == player) return L__M(##Pull, 1, noun);
  2231. if (noun == actor) return L__M(##Pull, 6, noun);
  2232. if (noun has static) return L__M(##Pull, 2, noun);
  2233. if (noun has scenery) return L__M(##Pull, 3, noun);
  2234. if (noun has animate) return L__M(##Pull, 5, noun);
  2235. L__M(##Pull, 4, noun);
  2236. ];
  2237. [ PushSub;
  2238. if (ObjectIsUntouchable(noun)) return;
  2239. if (noun == player) return L__M(##Push, 1, noun);
  2240. if (noun == actor) return L__M(##Push, 5, noun);
  2241. if (noun has static) return L__M(##Push, 2, noun);
  2242. if (noun has scenery) return L__M(##Push, 3, noun);
  2243. if (noun has animate) return L__M(##Push, 5, noun);
  2244. L__M(##Push, 4, noun);
  2245. ];
  2246. [ PushDirSub; L__M(##PushDir, 1, noun); ];
  2247. [ RubSub;
  2248. if (ObjectIsUntouchable(noun)) return;
  2249. if (noun has animate) return L__M(##Rub, 2, noun);
  2250. L__M(##Rub, 1, noun);
  2251. ];
  2252. [ SetSub; L__M(##Set, 1, noun); ];
  2253. [ SetToSub; L__M(##SetTo, 1, noun); ];
  2254. [ SingSub; L__M(##Sing, 1, noun); ];
  2255. [ SleepSub; L__M(##Sleep, 1, noun); ];
  2256. [ SmellSub;
  2257. if (noun ~= nothing && noun has animate) return L__M(##Smell, 2, noun);
  2258. L__M(##Smell, 1, noun);
  2259. ];
  2260. [ SorrySub; L__M(##Sorry, 1, noun); ];
  2261. [ SqueezeSub;
  2262. if (ObjectIsUntouchable(noun)) return;
  2263. if (noun has animate && noun ~= player) return L__M(##Squeeze, 1, noun);
  2264. L__M(##Squeeze, 2, noun);
  2265. ];
  2266. [ StrongSub; L__M(##Strong, 1, noun); ];
  2267. [ SwimSub; L__M(##Swim, 1, noun); ];
  2268. [ SwingSub; L__M(##Swing, 1, noun); ];
  2269. [ TasteSub;
  2270. if (ObjectIsUntouchable(noun)) return;
  2271. if (noun has animate) return L__M(##Taste, 2, noun);
  2272. L__M(##Taste, 1, noun);
  2273. ];
  2274. [ TellSub;
  2275. if (noun == actor) return L__M(##Tell, 1, noun);
  2276. if (RunLife(noun, ##Tell)) return;
  2277. L__M(##Tell, 2, noun);
  2278. ];
  2279. [ ThinkSub; L__M(##Think, 1, noun); ];
  2280. [ ThrowAtSub;
  2281. if (ObjectIsUntouchable(noun)) return;
  2282. if (second > 1) {
  2283. action = ##ThrownAt;
  2284. if (RunRoutines(second, before)) { action = ##ThrowAt; rtrue; }
  2285. action = ##ThrowAt;
  2286. }
  2287. if (noun has worn && ImplicitDisrobe(noun)) return;
  2288. if (second hasnt animate) return L__M(##ThrowAt, 1, noun);
  2289. if (RunLife(second, ##ThrowAt)) return;
  2290. L__M(##ThrowAt, 2, noun);
  2291. ];
  2292. [ TieSub;
  2293. if (noun has animate) return L__M(##Tie, 2, noun);
  2294. L__M(##Tie, 1, noun);
  2295. ];
  2296. [ TouchSub;
  2297. if (noun == actor) return L__M(##Touch, 3, noun);
  2298. if (ObjectIsUntouchable(noun)) return;
  2299. if (noun has animate) return L__M(##Touch, 1, noun);
  2300. L__M(##Touch, 2,noun);
  2301. ];
  2302. [ TurnSub;
  2303. if (ObjectIsUntouchable(noun)) return;
  2304. if (noun == player) return L__M(##Turn, 1, noun);
  2305. if (noun == actor) return L__M(##Turn, 5, noun);
  2306. if (noun has static) return L__M(##Turn, 2, noun);
  2307. if (noun has scenery) return L__M(##Turn, 3, noun);
  2308. if (noun has animate) return L__M(##Turn, 5, noun);
  2309. L__M(##Turn, 4, noun);
  2310. ];
  2311. [ WaitSub;
  2312. if (AfterRoutines()) rtrue;
  2313. L__M(##Wait, 1, noun);
  2314. ];
  2315. [ WakeSub; L__M(##Wake, 1, noun); ];
  2316. [ WakeOtherSub;
  2317. if (ObjectIsUntouchable(noun)) return;
  2318. if (RunLife(noun, ##WakeOther)) return;
  2319. L__M(##WakeOther, 1, noun);
  2320. ];
  2321. [ WaveSub;
  2322. if (noun == player) return L__M(##Wave, 2 ,noun, second);
  2323. if (noun == actor) return L__M(##Wave, 3, noun, second);
  2324. if (noun notin actor && ImplicitTake(noun)) return L__M(##Wave, 1, noun);
  2325. L__M(##Wave, 2, noun, second);
  2326. ];
  2327. [ WaveHandsSub;
  2328. if (noun) return L__M(##WaveHands, 2, noun);
  2329. L__M(##WaveHands, 1, noun); ];
  2330. [ YesSub; L__M(##Yes); ];
  2331. ! ----------------------------------------------------------------------------
  2332. ! Debugging verbs
  2333. ! ----------------------------------------------------------------------------
  2334. #Ifdef DEBUG;
  2335. [ TraceOnSub; parser_trace = 1; "[Trace on.]"; ];
  2336. [ TraceLevelSub;
  2337. parser_trace = noun;
  2338. print "[Parser tracing set to level ", parser_trace, ".]^";
  2339. ];
  2340. [ TraceOffSub; parser_trace = 0; "Trace off."; ];
  2341. [ RoutinesOnSub;
  2342. debug_flag = debug_flag | DEBUG_MESSAGES;
  2343. "[Message listing on.]";
  2344. ];
  2345. [ RoutinesOffSub;
  2346. debug_flag = debug_flag & ~DEBUG_MESSAGES;
  2347. "[Message listing off.]";
  2348. ];
  2349. [ RoutinesVerboseSub;
  2350. debug_flag = debug_flag | (DEBUG_VERBOSE|DEBUG_MESSAGES);
  2351. "[Verbose message listing on.]";
  2352. ];
  2353. [ ActionsOnSub;
  2354. debug_flag = debug_flag | DEBUG_ACTIONS;
  2355. "[Action listing on.]";
  2356. ];
  2357. [ ActionsOffSub;
  2358. debug_flag = debug_flag & ~DEBUG_ACTIONS;
  2359. "[Action listing off.]";
  2360. ];
  2361. [ TimersOnSub;
  2362. debug_flag = debug_flag | DEBUG_TIMERS;
  2363. "[Timers listing on.]";
  2364. ];
  2365. [ TimersOffSub;
  2366. debug_flag = debug_flag & ~DEBUG_TIMERS;
  2367. "[Timers listing off.]";
  2368. ];
  2369. #Ifdef VN_1610;
  2370. [ ChangesOnSub; debug_flag = debug_flag | DEBUG_CHANGES; "[Changes listing on.]"; ];
  2371. [ ChangesOffSub; debug_flag = debug_flag & ~DEBUG_CHANGES; "[Changes listing off.]"; ];
  2372. #Ifnot;
  2373. [ ChangesOnSub; "[Changes listing available only from Inform 6.2 onwards.]"; ];
  2374. [ ChangesOffSub; "[Changes listing available only from Inform 6.2 onwards.]"; ];
  2375. #Endif; ! VN_1610
  2376. #Ifdef TARGET_ZCODE;
  2377. [ PredictableSub i;
  2378. i = random(-100);
  2379. "[Random number generator now predictable.]";
  2380. ];
  2381. #Ifnot; ! TARGET_GLULX;
  2382. [ PredictableSub;
  2383. @setrandom 100;
  2384. "[Random number generator now predictable.]";
  2385. ];
  2386. #Endif; ! TARGET_;
  2387. [ XTestMove obj dest;
  2388. if (~~obj ofclass Object) "[Not an object.]";
  2389. if (~~dest ofclass Object) "[Destination not an object.]";
  2390. if ((obj <= InformLibrary) || (obj == LibraryMessages) || (obj in 1))
  2391. "[Can't move ", (name) obj, ": it's a system object.]";
  2392. while (dest) {
  2393. if (dest == obj) "[Can't move ", (name) obj, ": it would contain itself.]";
  2394. dest = parent(dest);
  2395. }
  2396. rfalse;
  2397. ];
  2398. [ XPurloinSub;
  2399. if (XTestMove(noun, player)) return;
  2400. move noun to player; give noun moved ~concealed;
  2401. "[Purloined.]";
  2402. ];
  2403. [ XAbstractSub;
  2404. if (XTestMove(noun, second)) return;
  2405. move noun to second;
  2406. "[Abstracted.]";
  2407. ];
  2408. [ XObj obj f;
  2409. if (parent(obj) == 0) print (name) obj; else print (a) obj;
  2410. print " (", obj, ") ";
  2411. if (f && parent(obj))
  2412. print "in ~", (name) parent(obj), "~ (", parent(obj), ")";
  2413. new_line;
  2414. if (child(obj) == 0) rtrue;
  2415. if (obj == Class) ! ???
  2416. WriteListFrom(child(obj), NEWLINE_BIT+INDENT_BIT+ALWAYS_BIT+ID_BIT+NOARTICLE_BIT, 1);
  2417. else
  2418. WriteListFrom(child(obj), NEWLINE_BIT+INDENT_BIT+ALWAYS_BIT+ID_BIT+FULLINV_BIT, 1);
  2419. ];
  2420. [ XTreeSub i;
  2421. if (noun && ~~noun ofclass Object) "[Not an object.]";
  2422. if (noun == 0) {
  2423. objectloop (i)
  2424. if (i ofclass Object && parent(i) == 0) XObj(i);
  2425. }
  2426. else XObj(noun, true);
  2427. ];
  2428. [ GotoSub;
  2429. if ((~~noun ofclass Object) || parent(noun)) "[Not a safe place.]";
  2430. PlayerTo(noun);
  2431. ];
  2432. [ GoNearSub x;
  2433. if (~~noun ofclass Object) "[Not a safe place.]";
  2434. x = noun;
  2435. while (parent(x)) x = parent(x);
  2436. PlayerTo(x);
  2437. ];
  2438. [ Print_ScL obj; print_ret ++x_scope_count, ": ", (a) obj, " (", obj, ")"; ];
  2439. [ ScopeSub;
  2440. if (noun && ~~noun ofclass Object) "[Not an object.]";
  2441. x_scope_count = 0;
  2442. LoopOverScope(Print_ScL, noun);
  2443. if (x_scope_count == 0) "Nothing is in scope.";
  2444. ];
  2445. #Ifdef TARGET_GLULX;
  2446. [ GlkListSub id val;
  2447. id = glk($0020, 0, gg_arguments); ! window_iterate
  2448. while (id) {
  2449. print "Window ", id, " (", gg_arguments-->0, "): ";
  2450. val = glk($0028, id); ! window_get_type
  2451. switch (val) {
  2452. 1: print "pair";
  2453. 2: print "blank";
  2454. 3: print "textbuffer";
  2455. 4: print "textgrid";
  2456. 5: print "graphics";
  2457. default: print "unknown";
  2458. }
  2459. val = glk($0029, id); ! window_get_parent
  2460. if (val) print ", parent is window ", val;
  2461. else print ", no parent (root)";
  2462. val = glk($002C, id); ! window_get_stream
  2463. print ", stream ", val;
  2464. val = glk($002E, id); ! window_get_echo_stream
  2465. if (val) print ", echo stream ", val;
  2466. print "^";
  2467. id = glk($0020, id, gg_arguments); ! window_iterate
  2468. }
  2469. id = glk($0040, 0, gg_arguments); ! stream_iterate
  2470. while (id) {
  2471. print "Stream ", id, " (", gg_arguments-->0, ")^";
  2472. id = glk($0040, id, gg_arguments); ! stream_iterate
  2473. }
  2474. id = glk($0064, 0, gg_arguments); ! fileref_iterate
  2475. while (id) {
  2476. print "Fileref ", id, " (", gg_arguments-->0, ")^";
  2477. id = glk($0064, id, gg_arguments); ! fileref_iterate
  2478. }
  2479. val = glk($0004, 8, 0); ! gestalt, Sound
  2480. if (val) {
  2481. id = glk($00F0, 0, gg_arguments); ! schannel_iterate
  2482. while (id) {
  2483. print "Soundchannel ", id, " (", gg_arguments-->0, ")^";
  2484. id = glk($00F0, id, gg_arguments); ! schannel_iterate
  2485. }
  2486. }
  2487. ];
  2488. #Endif; ! TARGET_;
  2489. #Endif; ! DEBUG
  2490. ! ----------------------------------------------------------------------------
  2491. ! Finally: the mechanism for library text (the text is in the language defn)
  2492. ! ----------------------------------------------------------------------------
  2493. [ L__M act n x1 x2 s;
  2494. if (keep_silent == 2) return;
  2495. s = sw__var;
  2496. sw__var = act;
  2497. if (n == 0) n = 1;
  2498. L___M(n, x1, x2);
  2499. sw__var = s;
  2500. ];
  2501. [ L___M n x1 x2 s;
  2502. s = action;
  2503. lm_n = n;
  2504. lm_o = x1;
  2505. lm_s = x2;
  2506. action = sw__var;
  2507. if (RunRoutines(LibraryMessages, before)) { action = s; rfalse; }
  2508. if (LibraryExtensions.RunWhile(ext_messages, false )) { action = s; rfalse; }
  2509. action = s;
  2510. LanguageLM(n, x1, x2);
  2511. ];
  2512. ! ==============================================================================