home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume16 / nethack31 / part87 < prev    next >
Internet Message Format  |  1993-02-06  |  59KB

  1. Path: uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v16i095:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part87/108
  5. Message-ID: <4458@master.CNA.TEK.COM>
  6. Date: 5 Feb 93 19:22:05 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 1783
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1646
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 95
  14. Archive-name: nethack31/Part87
  15. Supersedes: nethack3p9: Volume 10, Issue 46-102
  16. Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
  17.  
  18.  
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 87 (of 108)."
  27. # Contents:  dat/Wizard.des src/quest.c sys/vms/vmsmail.c
  28. #   sys/vms/vmstty.c
  29. # Wrapped by billr@saab on Wed Jan 27 16:09:21 1993
  30. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  31. if test -f 'dat/Wizard.des' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'dat/Wizard.des'\"
  33. else
  34. echo shar: Extracting \"'dat/Wizard.des'\" \(14707 characters\)
  35. sed "s/^X//" >'dat/Wizard.des' <<'END_OF_FILE'
  36. X#    SCCS Id: @(#)Wizard.des    3.1    92/07/11
  37. X#    Copyright (c) 1992 by David Cohrs
  38. X# NetHack may be freely redistributed.  See license for details.
  39. X#
  40. X#    The "start" level for the quest.
  41. X#
  42. X#    Here you meet your (besieged) class leader, the Wizard of Balance
  43. X#    and receive your quest assignment.
  44. X#
  45. XMAZE: "W-start",' '
  46. XFLAGS: noteleport,hardfloor
  47. XGEOMETRY:center,center
  48. XMAP
  49. X............................................................................
  50. X.....................C....CC.C........................C.....................
  51. X..........CCC.....................CCC.......................................
  52. X........CC........-----------.......C.C...C...C....C........................
  53. X.......C.....---------------------...C..C..C..C.............................
  54. X......C..C...------....\....------....C.....C...............................
  55. X........C...||....|.........|....||.........................................
  56. X.......C....||....|.........+....||.........................................
  57. X.......C...||---+--.........|....|||........................................
  58. X......C....||...............|--S--||........................................
  59. X...........||--+--|++----|---|..|.SS..........C......C......................
  60. X........C..||.....|..|...|...|--|.||..CC..C.....C..........C................
  61. X.......C...||.....|..|.--|.|.|....||.................C..C...................
  62. X.....C......||....|..|.....|.|.--||..C..C..........C...........}}}..........
  63. X......C.C...||....|..-----.|.....||...C.C.C..............C....}}}}}}........
  64. X.........C...------........|------....C..C.....C..CC.C......}}}}}}}}}}}.....
  65. X.........CC..---------------------...C.C..C.....CCCCC.C.......}}}}}}}}......
  66. X.........C........-----------..........C.C.......CCC.........}}}}}}}}}......
  67. X..........C.C.........................C............C...........}}}}}........
  68. X......................CCC.C.................................................
  69. XENDMAP
  70. X# Random Monsters
  71. XRANDOM_MONSTERS: 'B', 'i'
  72. X# Dungeon Description
  73. XREGION:(00,00,75,19),lit,"ordinary"
  74. XREGION:(35,00,49,03),unlit,"ordinary"
  75. XREGION:(43,12,49,16),unlit,"ordinary"
  76. XREGION:(19,11,33,15),unlit,"ordinary",unfilled,true
  77. XREGION:(30,10,31,10),unlit,"ordinary"
  78. X# Stairs
  79. XSTAIR:(30,10),down
  80. X# Portal arrival point
  81. XBRANCH:(63,06,63,06),(0,0,0,0)
  82. X# Doors
  83. XDOOR:closed,(31,09)
  84. XDOOR:closed,(16,08)
  85. XDOOR:closed,(28,07)
  86. XDOOR:locked,(34,10)
  87. XDOOR:locked,(35,10)
  88. XDOOR:closed,(15,10)
  89. XDOOR:locked,(19,10)
  90. XDOOR:locked,(20,10)
  91. X# Wizard of Balance
  92. XMONSTER:'@',"Wizard of Balance",(23,05)
  93. X# The treasure of Wizard of Balance
  94. XOBJECT:'(',"chest",(24,05)
  95. X# apprentice guards for the audience chamber
  96. XMONSTER:'@',"apprentice",(30,07)
  97. XMONSTER:'@',"apprentice",(24,06)
  98. XMONSTER:'@',"apprentice",(15,06)
  99. XMONSTER:'@',"apprentice",(15,12)
  100. XMONSTER:'@',"apprentice",(26,11)
  101. XMONSTER:'@',"apprentice",(27,11)
  102. XMONSTER:'@',"apprentice",(19,09)
  103. XMONSTER:'@',"apprentice",(20,09)
  104. X# Eels in the pond
  105. XMONSTER:';',"giant eel",(62,14)
  106. XMONSTER:';',"giant eel",(69,15)
  107. XMONSTER:';',"giant eel",(67,17)
  108. X# Non diggable walls
  109. XNON_DIGGABLE:(00,00,75,19)
  110. X# Random traps
  111. XTRAP:random,random
  112. XTRAP:random,random
  113. XTRAP:random,random
  114. XTRAP:random,random
  115. XTRAP:random,random
  116. XTRAP:random,random
  117. X# Monsters on siege duty.
  118. XMONSTER: 'B',random,(60,09),hostile
  119. XMONSTER: 'W',random,(60,10),hostile
  120. XMONSTER: 'B',random,(60,11),hostile
  121. XMONSTER: 'B',random,(60,12),hostile
  122. XMONSTER: 'i',random,(60,13),hostile
  123. XMONSTER: 'B',random,(61,10),hostile
  124. XMONSTER: 'B',random,(61,11),hostile
  125. XMONSTER: 'B',random,(61,12),hostile
  126. XMONSTER: 'B',random,(35,03),hostile
  127. XMONSTER: 'i',random,(35,17),hostile
  128. XMONSTER: 'B',random,(36,17),hostile
  129. XMONSTER: 'B',random,(34,16),hostile
  130. XMONSTER: 'i',random,(34,17),hostile
  131. XMONSTER: 'W',random,(67,02),hostile
  132. XMONSTER: 'B',random,(10,19),hostile
  133. X#
  134. X#    The "locate" level for the quest.
  135. X#
  136. X#    Here you have to find the Entrance to the Tower of Darkness to go
  137. X#    further towards your assigned quest.
  138. X#
  139. X
  140. XMAZE: "W-locate",' '
  141. XFLAGS: hardfloor
  142. XGEOMETRY:center,center
  143. XMAP
  144. X.............        .......................................................
  145. X..............       .............}}}}}}}.}}}}}}}}}}}}}}}}}}}.}}}}}}}.......
  146. X..............      ..............}.................................}.......
  147. X..............      ..............}.---------S---------------------.}.......
  148. X...............     .........C....}.|.............................|.}.......
  149. X...............    ..........C....}.|.---------------------------.|.}.......
  150. X...............    .........CCC.....|.|.........................|.|.........
  151. X................   ....C....CCC...}.|.|.---S-------------------.|.|.}.......
  152. X.......C..C.....  .....C....CCC...}.|.|.|......+.......+......|.|.|.}.......
  153. X.............C..CC.....C....CCC...}.|.|.|......|-------|......|.|.|.}.......
  154. X................   ....C....CCC...}.|.|.|......|.......S......|.|.|.}.......
  155. X......C..C.....    ....C....CCC...}.|.|.|......|-------|......|.|.|.}.......
  156. X............C..     ...C....CCC...}.|.|.|......+.......+......|.|.|.}.......
  157. X........C......    ....C....CCC...}.|.|.-----------------------.|.|.}.......
  158. X....C......C...     ........CCC.....|.|.........................|.|.........
  159. X......C..C....      .........C....}.|.--------------------S------.|.}.......
  160. X..............      .........C....}.|.............................|.}.......
  161. X.............       ..............}.-------------------------------.}.......
  162. X.............        .............}.................................}.......
  163. X.............        .............}}}}}}}.}}}}}}}}}}}}}}}}}}}.}}}}}}}.......
  164. X.............        .......................................................
  165. XENDMAP
  166. X# Random Monsters
  167. XRANDOM_MONSTERS: 'B', 'X'
  168. X# Dungeon Description
  169. XREGION:(00,00,75,20),lit,"ordinary"
  170. XREGION:(37,04,65,16),unlit,"ordinary"
  171. XREGION:(41,08,46,12),lit,"ordinary"
  172. XREGION:(56,08,61,12),lit,"ordinary"
  173. XREGION:(48,08,54,08),unlit,"ordinary"
  174. XREGION:(48,12,54,12),unlit,"ordinary"
  175. XREGION:(48,10,54,10),unlit,"ordinary"
  176. X
  177. X# Doors
  178. XDOOR:locked,(45,03)
  179. XDOOR:locked,(43,07)
  180. XDOOR:locked,(58,15)
  181. XDOOR:locked,(55,10)
  182. XDOOR:locked,(55,08)
  183. XDOOR:locked,(55,12)
  184. XDOOR:locked,(47,08)
  185. XDOOR:locked,(47,12)
  186. X# Stairs
  187. XSTAIR:(03,17),up
  188. XSTAIR:(48,10),down
  189. X# Non diggable walls
  190. XNON_DIGGABLE:(00,00,75,20)
  191. X# Objects
  192. XOBJECT:random,random,random
  193. XOBJECT:random,random,random
  194. XOBJECT:random,random,random
  195. XOBJECT:random,random,random
  196. XOBJECT:random,random,random
  197. XOBJECT:random,random,random
  198. XOBJECT:random,random,random
  199. XOBJECT:random,random,random
  200. XOBJECT:random,random,random
  201. XOBJECT:random,random,random
  202. XOBJECT:random,random,random
  203. XOBJECT:random,random,random
  204. XOBJECT:random,random,random
  205. XOBJECT:random,random,random
  206. XOBJECT:random,random,random
  207. X# Random traps
  208. XTRAP:"spiked pit",(24,02)
  209. XTRAP:"spiked pit",(07,10)
  210. XTRAP:"spiked pit",(23,05)
  211. XTRAP:"spiked pit",(26,19)
  212. XTRAP:"spiked pit",(72,02)
  213. XTRAP:"spiked pit",(72,12)
  214. XTRAP:"falling rock",(45,16)
  215. XTRAP:"falling rock",(65,13)
  216. XTRAP:"falling rock",(55,06)
  217. XTRAP:"falling rock",(39,11)
  218. XTRAP:"falling rock",(57,09)
  219. XTRAP:"magic",random
  220. XTRAP:"statue",random
  221. XTRAP:"statue",random
  222. XTRAP:"polymorph",random
  223. XTRAP:"anti magic",(53,10)
  224. XTRAP:"sleep gas",random
  225. XTRAP:"sleep gas",random
  226. XTRAP:"dart",random
  227. XTRAP:"dart",random
  228. XTRAP:"dart",random
  229. X# Random monsters.
  230. XMONSTER:'B',random,random,hostile
  231. XMONSTER:'B',random,random,hostile
  232. XMONSTER:'B',random,random,hostile
  233. XMONSTER:'B',random,random,hostile
  234. XMONSTER:'B',random,random,hostile
  235. XMONSTER:'B',random,random,hostile
  236. XMONSTER:'B',random,random,hostile
  237. XMONSTER:'B',random,random,hostile
  238. XMONSTER:'B',random,random,hostile
  239. XMONSTER:'B',random,random,hostile
  240. XMONSTER:'B',random,random,hostile
  241. XMONSTER:'B',random,random,hostile
  242. XMONSTER:'i',random,random,hostile
  243. XMONSTER:'i',random,random,hostile
  244. XMONSTER:'i',random,random,hostile
  245. XMONSTER:'i',random,random,hostile
  246. XMONSTER:'i',random,random,hostile
  247. XMONSTER:'i',random,random,hostile
  248. XMONSTER:'i',random,random,hostile
  249. XMONSTER:'B',"vampire bat",random
  250. XMONSTER:'B',"vampire bat",random
  251. XMONSTER:'B',"vampire bat",random
  252. XMONSTER:'B',"vampire bat",random
  253. XMONSTER:'B',"vampire bat",random
  254. XMONSTER:'B',"vampire bat",random
  255. XMONSTER:'B',"vampire bat",random
  256. XMONSTER:'i',random,random,hostile
  257. X
  258. X#
  259. X#    The "goal" level for the quest.
  260. X#
  261. X#    Here you meet the Dark One, your nemesis monster.  You have to
  262. X#    defeat the Dark One in combat to gain the artifact you have
  263. X#    been assigned to retrieve.
  264. X#
  265. X
  266. XMAZE: "W-goal", ' '
  267. XGEOMETRY:center,center
  268. XMAP
  269. X                                                                            
  270. X
  271. X
  272. X                   -------------                 -------------
  273. X                   |...........|                 |...........|
  274. X            -------|...........-------------------...........|
  275. X            |......S...........|..|..|..|..|..|..|...........|
  276. X            |......|...........|..|..|..|..|..|..|...........|
  277. X            |......|...........--+--+--+--+--+--+-...........|
  278. X            --S----|...........S.................+...........|
  279. X            |......|...........--+--+--+--+--+--+-...........|
  280. X            |......|...........|..|..|..|..|..|..|...........|
  281. X            |......|...........|..|..|..|..|..|..|...........|
  282. X            -------|...........-------------------...........|
  283. X                   |...........|                 |...........|
  284. X                   -------------                 -------------
  285. X
  286. X
  287. X
  288. X                                                                            
  289. XENDMAP
  290. X# Random Monsters
  291. XRANDOM_MONSTERS: 'B', 'X'
  292. X# Dungeon Description
  293. XREGION:(13,10,18,12),unlit,"temple"
  294. XREGION:(13,06,18,08),lit,"ordinary"
  295. XREGION:(20,04,30,14),unlit,"ordinary"
  296. XREGION:(32,06,33,07),unlit,"ordinary"
  297. XREGION:(35,06,36,07),unlit,"ordinary"
  298. XREGION:(38,06,39,07),unlit,"ordinary"
  299. XREGION:(41,06,42,07),unlit,"ordinary"
  300. XREGION:(44,06,45,07),unlit,"ordinary"
  301. XREGION:(47,06,48,07),unlit,"ordinary"
  302. XREGION:(32,09,48,09),unlit,"ordinary"
  303. XREGION:(32,11,33,12),unlit,"ordinary"
  304. XREGION:(35,11,36,12),unlit,"ordinary"
  305. XREGION:(38,11,39,12),unlit,"ordinary"
  306. XREGION:(41,11,42,12),unlit,"ordinary"
  307. XREGION:(44,11,45,12),unlit,"ordinary"
  308. XREGION:(47,11,48,12),unlit,"ordinary"
  309. XREGION:(50,04,60,14),lit,"ordinary"
  310. X# Doors
  311. XDOOR:locked,(19,06)
  312. XDOOR:locked,(14,09)
  313. XDOOR:locked,(31,09)
  314. XDOOR:locked,(33,08)
  315. XDOOR:locked,(36,08)
  316. XDOOR:locked,(39,08)
  317. XDOOR:locked,(42,08)
  318. XDOOR:locked,(45,08)
  319. XDOOR:locked,(48,08)
  320. XDOOR:locked,(33,10)
  321. XDOOR:locked,(36,10)
  322. XDOOR:locked,(39,10)
  323. XDOOR:locked,(42,10)
  324. XDOOR:locked,(45,10)
  325. XDOOR:locked,(48,10)
  326. XDOOR:locked,(49,09)
  327. X# Stairs
  328. XSTAIR:(55,05),up
  329. X# Non diggable walls
  330. XNON_DIGGABLE:(00,00,75,19)
  331. X# The altar of Anhur.  This is not a shrine.
  332. XALTAR:(16,11),chaos,altar
  333. X# Objects
  334. XOBJECT:'"',"amulet of ESP",(16,11),blessed,0,"The Eye of the Aethiopica"
  335. XOBJECT:random,random,random
  336. XOBJECT:random,random,random
  337. XOBJECT:random,random,random
  338. XOBJECT:random,random,random
  339. XOBJECT:random,random,random
  340. XOBJECT:random,random,random
  341. XOBJECT:random,random,random
  342. XOBJECT:random,random,random
  343. XOBJECT:random,random,random
  344. XOBJECT:random,random,random
  345. XOBJECT:random,random,random
  346. XOBJECT:random,random,random
  347. XOBJECT:random,random,random
  348. XOBJECT:random,random,random
  349. X# Random traps
  350. XTRAP:random,random
  351. XTRAP:random,random
  352. XTRAP:random,random
  353. XTRAP:random,random
  354. XTRAP:random,random
  355. XTRAP:random,random
  356. X# Random monsters.
  357. XMONSTER:'@',"Dark One",(16,11)
  358. XMONSTER:'B',random,random,hostile
  359. XMONSTER:'B',random,random,hostile
  360. XMONSTER:'B',random,random,hostile
  361. XMONSTER:'B',random,random,hostile
  362. XMONSTER:'B',random,random,hostile
  363. XMONSTER:'B',random,random,hostile
  364. XMONSTER:'B',random,random,hostile
  365. XMONSTER:'B',random,random,hostile
  366. XMONSTER:'B',random,random,hostile
  367. XMONSTER:'B',random,random,hostile
  368. XMONSTER:'B',random,random,hostile
  369. XMONSTER:'i',random,random,hostile
  370. XMONSTER:'i',random,random,hostile
  371. XMONSTER:'i',random,random,hostile
  372. XMONSTER:'i',random,random,hostile
  373. XMONSTER:'i',random,random,hostile
  374. XMONSTER:'i',random,random,hostile
  375. XMONSTER:'i',random,random,hostile
  376. XMONSTER:'B',"vampire bat",random
  377. XMONSTER:'B',"vampire bat",random
  378. XMONSTER:'B',"vampire bat",random
  379. XMONSTER:'B',"vampire bat",random
  380. XMONSTER:'B',"vampire bat",random
  381. XMONSTER:'B',"vampire bat",random
  382. XMONSTER:'B',"vampire bat",random
  383. XMONSTER:'B',"vampire bat",random
  384. XMONSTER:'i',random,random,hostile
  385. X# Captive Monsters in the dungeon
  386. XMONSTER:'@',"rogue",(35,06),peaceful,"Pug"
  387. XMONSTER:'Y',"owlbear",(47,06),peaceful,asleep
  388. XMONSTER:'@',"wizard",(32,11),peaceful,asleep,"Newt"
  389. XMONSTER:'@',"Grey-elf",(44,11),peaceful
  390. XMONSTER:'H',"hill giant",(47,11),peaceful,asleep
  391. XMONSTER:'G',"gnomish wizard",(38,06),peaceful
  392. X
  393. X#
  394. X#    The "fill" levels for the quest.
  395. X#
  396. X#    These levels are used to fill out any levels not occupied by specific
  397. X#    levels as defined above. "filla" is the upper filler, between the
  398. X#    start and locate levels, and "fillb" the lower between the locate
  399. X#    and goal levels.
  400. X#
  401. X
  402. XLEVEL: "W-filla"
  403. X# Random Monsters
  404. XRANDOM_MONSTERS: 'B', 'X'
  405. X#
  406. XROOM: "ordinary" , random, random, random, random
  407. XSTAIR: random, up
  408. XOBJECT: random,random,random
  409. XMONSTER: 'i', random, random, hostile
  410. X
  411. XROOM: "ordinary" , random, random, random, random
  412. XOBJECT: random, random, random
  413. XOBJECT: random,random,random
  414. XMONSTER: 'i', random, random, hostile
  415. X
  416. XROOM: "ordinary" , random, random, random, random
  417. XOBJECT: random, random, random
  418. XTRAP: random, random
  419. XOBJECT: random,random,random
  420. XMONSTER: 'B', "vampire bat", random
  421. XMONSTER: 'B', "vampire bat", random
  422. X
  423. XROOM: "ordinary" , random, random, random, random
  424. XSTAIR: random, down
  425. XOBJECT: random, random, random
  426. XTRAP: random, random
  427. XMONSTER: 'i', random, random, hostile
  428. XMONSTER: 'B', "vampire bat", random
  429. X
  430. XROOM: "ordinary" , random, random, random, random
  431. XOBJECT: random, random, random
  432. XOBJECT: random, random, random
  433. XTRAP: random, random
  434. XMONSTER: 'i', random, random, hostile
  435. X
  436. XROOM: "ordinary" , random, random, random, random
  437. XOBJECT: random, random, random
  438. XTRAP: random, random
  439. XMONSTER: 'B', "vampire bat", random
  440. X
  441. XRANDOM_CORRIDORS
  442. X
  443. XLEVEL: "W-fillb"
  444. X# Random Monsters
  445. XRANDOM_MONSTERS: 'B', 'X'
  446. X#
  447. XROOM: "ordinary" , random, random, random, random
  448. XSTAIR: random, up
  449. XOBJECT: random,random,random
  450. XMONSTER: 'X', random, random, hostile
  451. X
  452. XROOM: "ordinary" , random, random, random, random
  453. XOBJECT: random, random, random
  454. XOBJECT: random,random,random
  455. XMONSTER: 'i', random, random, hostile
  456. X
  457. XROOM: "ordinary" , random, random, random, random
  458. XOBJECT: random, random, random
  459. XTRAP: random, random
  460. XOBJECT: random,random,random
  461. XMONSTER: 'X', random, random, hostile
  462. X
  463. XROOM: "ordinary" , random, random, random, random
  464. XSTAIR: random, down
  465. XOBJECT: random, random, random
  466. XTRAP: random, random
  467. XMONSTER: 'i', random, random, hostile
  468. XMONSTER: 'B', "vampire bat", random
  469. X
  470. XROOM: "ordinary" , random, random, random, random
  471. XOBJECT: random, random, random
  472. XOBJECT: random, random, random
  473. XTRAP: random, random
  474. XMONSTER: 'i', random, random, hostile
  475. X
  476. XROOM: "ordinary" , random, random, random, random
  477. XOBJECT: random, random, random
  478. XTRAP: random, random
  479. XMONSTER: 'B', "vampire bat", random
  480. X
  481. XRANDOM_CORRIDORS
  482. END_OF_FILE
  483. if test 14707 -ne `wc -c <'dat/Wizard.des'`; then
  484.     echo shar: \"'dat/Wizard.des'\" unpacked with wrong size!
  485. fi
  486. # end of 'dat/Wizard.des'
  487. fi
  488. if test -f 'src/quest.c' -a "${1}" != "-c" ; then 
  489.   echo shar: Will not clobber existing file \"'src/quest.c'\"
  490. else
  491. echo shar: Extracting \"'src/quest.c'\" \(8083 characters\)
  492. sed "s/^X//" >'src/quest.c' <<'END_OF_FILE'
  493. X/*    SCCS Id: @(#)quest.c    3.1    92/11/13    */
  494. X/*    Copyright 1991, M. Stephenson          */
  495. X/* NetHack may be freely redistributed.  See license for details. */
  496. X
  497. X#include "hack.h"
  498. X
  499. X#ifdef MULDGN
  500. X/*  quest dungeon branch routines. */
  501. X
  502. X#include "quest.h"
  503. X#include "qtext.h"
  504. X
  505. X#define Not_firsttime    (on_level(&u.uz0, &u.uz))
  506. X#define Qstat(x)    (quest_status.x)
  507. X
  508. Xstatic void NDECL(on_start);
  509. Xstatic void NDECL(on_locate);
  510. Xstatic void NDECL(on_goal);
  511. Xstatic boolean NDECL(not_capable);
  512. Xstatic boolean NDECL(not_pure);
  513. Xstatic void FDECL(expulsion, (BOOLEAN_P));
  514. Xstatic void NDECL(chat_with_leader);
  515. Xstatic void NDECL(chat_with_nemesis);
  516. Xstatic void NDECL(chat_with_guardian);
  517. X
  518. Xstatic void
  519. Xon_start() {
  520. X  if(!Qstat(first_start)) {
  521. X    qt_pager(QT_FIRSTTIME);
  522. X    Qstat(first_start) = TRUE;
  523. X  } else if((u.uz0.dnum != u.uz.dnum) || (u.uz0.dlevel < u.uz.dlevel)) {
  524. X    if(Qstat(not_ready) <= 2) qt_pager(QT_NEXTTIME);
  525. X    else    qt_pager(QT_OTHERTIME);
  526. X  }
  527. X}
  528. X
  529. Xstatic void
  530. Xon_locate() {
  531. X  if(!Qstat(first_locate)) {
  532. X    qt_pager(QT_FIRSTLOCATE);
  533. X    Qstat(first_locate) = TRUE;
  534. X  } else if(u.uz0.dlevel < u.uz.dlevel)
  535. X    qt_pager(QT_NEXTLOCATE);
  536. X}
  537. X
  538. Xstatic void
  539. Xon_goal() {
  540. X  if(!Qstat(made_goal)) {
  541. X    qt_pager(QT_FIRSTGOAL);
  542. X    Qstat(made_goal) = 1;
  543. X  } else {
  544. X    qt_pager(QT_NEXTGOAL);
  545. X    if(Qstat(made_goal) < 7) Qstat(made_goal)++;
  546. X  }
  547. X}
  548. X
  549. Xvoid
  550. Xquest_init() {
  551. X/*
  552. X *    Special setup modifications here:
  553. X *
  554. X *    Unfortunately, this is going to have to be done on each level,
  555. X *    on start-up, and on entry, since you lose the permonst mods
  556. X *    across a save/restore :-)
  557. X *
  558. X *    1 - The Rogue Leader is the Tourist Nemesis.
  559. X *    1 - Elves can have one of two different leaders, work it out here.
  560. X *    2 - Priests start with a random alignment - convert the leader and
  561. X *        guardians here.
  562. X */
  563. X#ifdef TOURIST
  564. X    if(pl_character[0] == 'T' && Is_nemesis(&u.uz)) {
  565. X    register struct monst *mtmp;
  566. X    mons[PM_MASTER_OF_THIEVES].msound = MS_NEMESIS;
  567. X    mons[PM_MASTER_OF_THIEVES].mflags2 &= ~(M2_PEACEFUL);
  568. X    mons[PM_MASTER_OF_THIEVES].mflags2 |= (M2_NASTY|M2_STALK|M2_HOSTILE);
  569. X    mons[PM_MASTER_OF_THIEVES].mflags3 = M3_WANTSARTI | M3_WAITFORU;
  570. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) /* find the leader... */
  571. X        if(mtmp->data->msound == MS_NEMESIS) {
  572. X        set_malign(mtmp); /* changed M2_PEACEFUL */
  573. X        break;
  574. X        }
  575. X    } else
  576. X#endif
  577. X    if(pl_character[0] == 'E' && flags.female && Is_qstart(&u.uz)) {
  578. X    register struct monst *mtmp;
  579. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) /* find the leader... */
  580. X        if(mtmp->data->msound == MS_LEADER) {
  581. X        mtmp->data = &mons[PM_ELWING]; /* sex-change */
  582. X        break;
  583. X        }
  584. X    } else if(pl_character[0] == 'P' && Is_qstart(&u.uz)) {
  585. X
  586. X    register struct monst *mtmp;
  587. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) /* find leader & guards */
  588. X       if(mtmp->data->msound == MS_LEADER ||
  589. X          mtmp->data->msound == MS_GUARDIAN) {
  590. X           /* use game-start alignment for reference */
  591. X        mtmp->data->maligntyp = u.ualignbase[1]*3;
  592. X        mtmp->mpeaceful = TRUE;
  593. X        set_malign(mtmp); /* mpeaceful may have changed */
  594. X       }
  595. X    }
  596. X}
  597. X
  598. Xvoid
  599. Xonquest() {
  600. X
  601. X    if(Not_firsttime)    return;
  602. X    if(!Is_special(&u.uz)) return;
  603. X
  604. X    if(Is_qstart(&u.uz)) on_start();
  605. X    else if(Is_qlocate(&u.uz) && u.uz.dlevel > u.uz0.dlevel) on_locate();
  606. X    else if(Is_nemesis(&u.uz)) on_goal();
  607. X    return;
  608. X}
  609. X
  610. Xvoid
  611. Xnemdead() {
  612. X    if(!Qstat(killed_nemesis)) {
  613. X        Qstat(killed_nemesis) = TRUE;
  614. X        qt_pager(QT_KILLEDNEM);
  615. X    }
  616. X}
  617. X
  618. Xvoid
  619. Xartitouch() {
  620. X    if(!Qstat(touched_artifact)) {
  621. X        Qstat(touched_artifact) = TRUE;
  622. X        qt_pager(QT_GOTIT);
  623. X        exercise(A_WIS, TRUE);
  624. X    }
  625. X}
  626. X
  627. X/* external hook for do.c (level change check) */
  628. Xboolean
  629. Xok_to_quest() {
  630. X
  631. X    return(Qstat(got_quest));
  632. X}
  633. X
  634. Xstatic boolean
  635. Xnot_capable() {
  636. X  return(u.ulevel < MIN_QUEST_LEVEL);
  637. X}
  638. X
  639. X/* TODO:    This one needs tuning. */
  640. Xstatic boolean
  641. Xnot_pure() {
  642. X#ifdef WIZARD
  643. X    if(wizard && (u.ualign.record < MIN_QUEST_ALIGN)) {
  644. X
  645. X       You("are currently %d and require %d.",
  646. X         u.ualign.record, MIN_QUEST_ALIGN);
  647. X       if(yn_function("adjust?", NULL, 'y') == 'y')
  648. X        u.ualign.record = MIN_QUEST_ALIGN;
  649. X    }
  650. X#endif
  651. X  return(u.ualign.record < MIN_QUEST_ALIGN);
  652. X}
  653. X
  654. X/*
  655. X * Expell the player to the stairs on the parent of the quest dungeon.
  656. X *
  657. X * This assumes that the hero is currently _in_ the quest dungeon and that
  658. X * there is a single branch to and from it.
  659. X */
  660. Xstatic void
  661. Xexpulsion(seal)
  662. Xboolean seal;
  663. X{
  664. X  branch *br;
  665. X  d_level *dest;
  666. X
  667. X  br = dungeon_branch("The Quest");
  668. X  dest = (br->end1.dnum == u.uz.dnum) ? &br->end2 : &br->end1;
  669. X  assign_level(&u.utolev, dest);
  670. X  u.utotype = 1; /* portal */
  671. X  if (seal) {    /* remove the portal to the quest - sealing it off */
  672. X    u.utotype |= 0200;
  673. X    u.uevent.qexpelled = 1;
  674. X  }
  675. X}
  676. X
  677. Xstatic void
  678. Xchat_with_leader()
  679. X{
  680. X/*    Rule 0:    Cheater checks.                    */
  681. X    if(u.uhave.questart && !Qstat(met_nemesis))
  682. X        Qstat(cheater) = TRUE;
  683. X
  684. X/*    It is possible for you to get the amulet without completing
  685. X *    the quest.  If so, try to induce the player to quest.
  686. X */
  687. X    if(Qstat(got_thanks)) {
  688. X/*    Rule 1:    You've gone back with/whithout the amulet.    */
  689. X            if(u.uhave.amulet)    qt_pager(QT_HASAMULET);
  690. X
  691. X/*    Rule 2:    You've gone back before going for the amulet.    */
  692. X        else        qt_pager(QT_POSTHANKS);
  693. X    }
  694. X
  695. X/*    Rule 3: You've got the artifact and are back to return it. */
  696. X      else if(u.uhave.questart) {
  697. X        if(u.uhave.amulet)    qt_pager(QT_HASAMULET);
  698. X        else        qt_pager(QT_OFFEREDIT);
  699. X        Qstat(got_thanks) = TRUE;
  700. X        u.uevent.qcompleted = 1;    /* you did it! */
  701. X
  702. X/*    Rule 4: You haven't got the artifact yet.    */
  703. X    } else if(Qstat(got_quest)) qt_pager(rn1(10, QT_ENCOURAGE));
  704. X
  705. X/*    Rule 5: You aren't yet acceptable - or are you? */
  706. X    else {
  707. X      if(!Qstat(met_leader)) {
  708. X        qt_pager(QT_FIRSTLEADER);
  709. X        Qstat(met_leader) = TRUE;
  710. X        Qstat(not_ready) = 0;
  711. X      } else qt_pager(QT_NEXTLEADER);
  712. X
  713. X      if(not_capable()) {
  714. X        qt_pager(QT_BADLEVEL);
  715. X        exercise(A_WIS, TRUE);
  716. X        expulsion(FALSE);
  717. X      } else if(not_pure()) {
  718. X        qt_pager(QT_BADALIGN);
  719. X        if(Qstat(not_ready) == MAX_QUEST_TRIES) {
  720. X          qt_pager(QT_LASTLEADER);
  721. X          expulsion(TRUE);
  722. X        } else {
  723. X          Qstat(not_ready)++;
  724. X          exercise(A_WIS, TRUE);
  725. X          expulsion(FALSE);
  726. X        }
  727. X      } else {    /* You are worthy! */
  728. X        qt_pager(QT_ASSIGNQUEST);
  729. X        exercise(A_WIS, TRUE);
  730. X        Qstat(got_quest) = TRUE;
  731. X      }
  732. X    }
  733. X}
  734. X
  735. Xvoid
  736. Xleader_speaks(mtmp)
  737. X
  738. X    register struct monst *mtmp;
  739. X{
  740. X    /* maybe you attacked leader? */
  741. X    if(!mtmp->mpeaceful) {
  742. X        Qstat(pissed_off) = TRUE;
  743. X        mtmp->data->mflags3 = 0;    /* end the inaction */
  744. X    }
  745. X
  746. X        if(Qstat(pissed_off)) {
  747. X      qt_pager(QT_LASTLEADER);
  748. X      expulsion(TRUE);
  749. X    } else chat_with_leader();
  750. X
  751. X}
  752. X
  753. Xstatic void
  754. Xchat_with_nemesis()
  755. X{
  756. X/*    The nemesis will do most of the talking, but... */
  757. X        qt_pager(rn1(10, QT_DISCOURAGE));
  758. X    if(!Qstat(met_nemesis)) Qstat(met_nemesis++);
  759. X}
  760. X
  761. Xvoid
  762. Xnemesis_speaks()
  763. X{
  764. X    if(!Qstat(in_battle)) {
  765. X      if(u.uhave.questart) qt_pager(QT_NEMWANTSIT);
  766. X      else if(!Qstat(made_goal)) qt_pager(QT_FIRSTNEMESIS);
  767. X      else if(Qstat(made_goal) < 3) qt_pager(QT_NEXTNEMESIS);
  768. X      else if(Qstat(made_goal) < 7) qt_pager(QT_OTHERNEMESIS);
  769. X      else if(!rn2(5))    qt_pager(rn1(10, QT_DISCOURAGE));
  770. X      if(Qstat(made_goal) < 7) Qstat(made_goal)++;
  771. X       Qstat(met_nemesis) = TRUE;
  772. X    } else /* he will spit out random maledictions */
  773. X      if(!rn2(5))    qt_pager(rn1(10, QT_DISCOURAGE));
  774. X}
  775. X
  776. Xstatic void
  777. Xchat_with_guardian()
  778. X{
  779. X/*    These guys/gals really don't have much to say... */
  780. X        qt_pager(rn1(5, QT_GUARDTALK));
  781. X}
  782. X
  783. Xvoid
  784. Xquest_chat(mtmp)
  785. X
  786. X    register struct monst *mtmp;
  787. X{
  788. X
  789. X    switch(mtmp->data->msound) {
  790. X        case MS_LEADER:    chat_with_leader(); break;
  791. X        case MS_NEMESIS:    chat_with_nemesis(); break;
  792. X        case MS_GUARDIAN:    chat_with_guardian(); break;
  793. X        default:    impossible("quest_chat: Unknown quest character %s.",
  794. X                   mon_nam(mtmp));
  795. X    }
  796. X}
  797. X
  798. Xvoid
  799. Xquest_talk(mtmp)
  800. X
  801. X    register struct monst *mtmp;
  802. X{
  803. X    switch(mtmp->data->msound) {
  804. X        case MS_LEADER:    leader_speaks(mtmp); break;
  805. X        case MS_NEMESIS:    nemesis_speaks(); break;
  806. X        default:        break;
  807. X    }
  808. X}
  809. X
  810. Xvoid
  811. Xquest_stat_check(mtmp)
  812. X
  813. X    struct monst *mtmp;
  814. X{
  815. X    if(mtmp->data->msound == MS_NEMESIS)
  816. X    Qstat(in_battle) = 
  817. X        (mtmp->mcanmove && !mtmp->msleep && monnear(mtmp, u.ux, u.uy));
  818. X}
  819. X
  820. X#endif /* MULDGN */
  821. X
  822. X/*quest.c*/
  823. END_OF_FILE
  824. if test 8083 -ne `wc -c <'src/quest.c'`; then
  825.     echo shar: \"'src/quest.c'\" unpacked with wrong size!
  826. fi
  827. # end of 'src/quest.c'
  828. fi
  829. if test -f 'sys/vms/vmsmail.c' -a "${1}" != "-c" ; then 
  830.   echo shar: Will not clobber existing file \"'sys/vms/vmsmail.c'\"
  831. else
  832. echo shar: Extracting \"'sys/vms/vmsmail.c'\" \(16224 characters\)
  833. sed "s/^X//" >'sys/vms/vmsmail.c' <<'END_OF_FILE'
  834. X/*    SCCS Id: @(#)vmsmail.c    3.1    92/12/16    */
  835. X/* Copyright (c) Robert Patrick Rankin, 1991.              */
  836. X/* NetHack may be freely redistributed.  See license for details. */
  837. X
  838. X#define EXTERN_H    /* don't need all those prototypes */
  839. X#include "config.h"
  840. X
  841. X#ifdef MAIL
  842. X#include "winprocs.h"
  843. X#include "mail.h"
  844. X#include <ctype.h>
  845. X#include <descrip.h>
  846. X#include <errno.h>
  847. X# ifndef __GNUC__
  848. X#include <msgdef.h>
  849. X# else
  850. X#  define MSG$_TRMHANGUP  6
  851. X#  define MSG$_TRMBRDCST 83
  852. X# endif /*__GNUC__*/
  853. X#include <signal.h>
  854. X/* #include <string.h> */
  855. X# define vms_ok(sts) ((sts)&1)
  856. X
  857. Xstatic struct mail_info *FDECL(parse_brdcst, (char *));
  858. Xstatic void FDECL(filter_brdcst, (char *));
  859. Xstatic void NDECL(flush_broadcasts);
  860. Xstatic void FDECL(broadcast_ast, (int));
  861. Xextern char *strcpy(), *strcat(), *strrchr(), *strstri(), *eos();
  862. Xextern int strspn(), strncmpi();
  863. X#ifndef __DECC
  864. Xextern int VDECL(sscanf, (const char *,const char *,...));
  865. X#endif
  866. Xextern unsigned long
  867. X    SMG$CREATE_PASTEBOARD(),
  868. X    SMG$GET_BROADCAST_MESSAGE(),
  869. X    SMG$SET_BROADCAST_TRAPPING(),
  870. X    SMG$DISABLE_BROADCAST_TRAPPING();
  871. X
  872. Xextern volatile int broadcasts;        /* defining declaration in mail.c */
  873. X
  874. Xstatic long pasteboard_id = 0;        /* SMG's magic cookie */
  875. X
  876. X/*
  877. X * Mail (et al) overview:
  878. X *
  879. X *    When a broadcast is asynchronously captured, a volatile counter
  880. X * ('broadcasts') is incremented.  Each player turn, ckmailstatus() polls
  881. X * the counter and calls parse_next_broadcast() if it's positive; this
  882. X * returns some display text, object name, and response command, which is
  883. X * passed to newmail().  Routine newmail() generates a mail-daemon monster
  884. X * who approaches the character, "speaks" the display text, and delivers
  885. X * a scroll of mail pre-named to the object name; the response command is
  886. X * initially appended to the name, so that the object is tagged with both
  887. X * of them; a NUL is inserted to terminate the ordinary name and hide the
  888. X * command.  (If the player renames such a scroll, the hidden command will
  889. X * be lost; who cares?)  Unrecognized broadcasts result in the mail-daemon
  890. X * arriving and announcing the display text, but no scroll being created.
  891. X * If SHELL is undefined, then all broadcasts are treated as 'other'; since
  892. X * no subproceses are allowed, there'd be no way to respond to the scroll.
  893. X *
  894. X *    When a scroll of mail is read by the character, readmail() extracts
  895. X * the hidden command string and uses it for the default when prompting the
  896. X * player for a system command to spawn.  The player may enter any command
  897. X * he or she chooses, or just <return> to accept the default or <escape> to
  898. X * avoid executing any command.  If the command is "SPAWN", a regular shell
  899. X * escape to DCL is performed; otherwise, the indicated single command is
  900. X * spawned.  Either way, NetHack resumes play when the subprocess terminates
  901. X * or explicitly reattaches to its parent.
  902. X *
  903. X * Broadcast parsing:
  904. X *
  905. X *    The following broadcast messages are [attempted to be] recognized:
  906. X *    text fragment          name for scroll          default command
  907. X *    New mail        VMSmail            MAIL
  908. X *    New ALL-IN-1 MAIL    A1mail            A1M
  909. X *    Software Tools mail    STmail            MSG [+folder]
  910. X *    MM mail            MMmail            MM
  911. X *    WPmail: New mail    WPmail            OFFICE/MAIL
  912. X *    **M400 mail        M400mail        M400
  913. X *    " mail", ^"mail "    unknown mail        SPAWN
  914. X *    " phoning"        Phone call        PHONE ANSWER
  915. X *    talk-daemon...by...foo    Talk request        TALK[/OLD] foo@bar
  916. X *    (node)user -        Bitnet noise        XYZZY user@node
  917. X * Anything else results in just the message text being passed along, no
  918. X * scroll of mail so consequently no command to execute when scroll read.
  919. X * The user can set up ``$ XYZZY :== SEND'' prior to invoking NetHack if
  920. X * vanilla JNET responses to Bitnet messages are prefered.
  921. X *
  922. X *    Static return buffers are used because only one broadcast gets
  923. X * processed at a time, and the essential information in each one is
  924. X * either displayed and discarded or copied into a scroll-of-mail object.
  925. X *
  926. X *    The test driver code below can be used to check out potential new
  927. X * entries without rebuilding NetHack itself.  CC/DEFINE="TEST_DRIVER"
  928. X * Link it with hacklib.obj or nethack.olb/incl=hacklib (not nethack/lib).
  929. X */
  930. X
  931. Xstatic struct mail_info msg;    /* parse_*()'s return buffer */
  932. Xstatic char nam_cmd_buf[63],    /* maximum onamelth, size of ONAME(object) */
  933. X        txt_buf[255+1];    /* same size as used for message buf[] */
  934. X
  935. X/* try to decipher and categorize broadcast message text
  936. X*/
  937. Xstatic struct mail_info *
  938. Xparse_brdcst(buf)        /* called by parse_next_broadcast() */
  939. Xchar *buf;            /* input: filtered broadcast text */
  940. X{
  941. X    int typ;
  942. X    char *txt, *nam, *cmd;
  943. X# ifdef SHELL        /* only parse if spawned commands are enabled */
  944. X    register char *p, *q;
  945. X    boolean is_jnet_send;
  946. X    char cmd_buf[127+1], user[127+1], node[127+1], sentinel;
  947. X
  948. X    /* Check these first; otherwise, their arbitrary text would enable
  949. X    easy spoofing of some other message patterns.  Unfortunately,
  950. X    any home-grown broadcast delivery program poses a similar risk. */
  951. X    if (!strncmpi(buf, "reply received", 14)) goto other;
  952. X    is_jnet_send = (sscanf(buf, "(%[^)])%s -%c", node, user, &sentinel) == 3);
  953. X    if (is_jnet_send) goto jnet_send;
  954. X
  955. X    /* scan the text more or less by brute force */
  956. X    if ((q = strstri(buf, " mail")) != 0 ||    /* all known mail broadcasts */
  957. X    !strncmpi(q = buf, "mail ", 5)) {    /* unexpected alternative */
  958. X    typ = MSG_MAIL;
  959. X    p = strstri(q, " from");
  960. X    txt = p ? strcat(strcpy(txt_buf, "Mail for you"), p) : (char *) 0;
  961. X
  962. X    if (!strncmpi(buf, "new mail", 8)) {
  963. X/*
  964. XNew mail [on node FOO] from [SPAM::]BAR [\"personal_name\"] [\(HH:MM:SS\)]
  965. X*/
  966. X        nam = "VMSmail";        /* assume VMSmail */
  967. X        cmd = "MAIL";
  968. X        if (txt && (p = strrchr(txt, '(')) > txt && /* discard time */
  969. X        (--p, strspn(p, "0123456789( :.)") == strlen(p))) *p = '\0';
  970. X    } else if (!strncmpi(buf, "new all-in-1", 12)) {
  971. X        int i;
  972. X/*
  973. XNew ALL-IN-1 MAIL message [on node FOO] from Personal Name \(BAR@SPAM\) [\(DD-MMM-YYYY HH:MM:SS\)]
  974. X*/
  975. X        nam = "A1mail";
  976. X        cmd = "A1M";
  977. X        if (txt && (p = strrchr(txt, '(')) > txt && /* discard date+time */
  978. X        sscanf(p-1," (%*d-%*[^-]-%*d %*d:%*d:%d) %c",&i,&sentinel) == 1)
  979. X        *--p = '\0';
  980. X    } else if (!strncmpi(buf, "software tools", 14)) {
  981. X/*
  982. XSoftware Tools mail has arrived on FOO from \'BAR\' [in SPAM]
  983. X*/
  984. X        nam = "STmail";
  985. X        cmd = "MSG";
  986. X        if (txt && (p = strstri(p, " in ")) != 0)    /* specific folder */
  987. X        cmd = strcat(strcpy(cmd_buf, "MSG +"), p + 4);
  988. X    } else if (q - 2 >= buf && !strncmpi(q - 2, "mm", 2)) {
  989. X/*
  990. X{MultiNet\ |PMDF\/}MM mail has arrived on FOO from BAR\n
  991. X[Subject: subject_text] (PMDF only)
  992. X*/
  993. X        nam = "MMmail";        /* MultiNet's version of MM */
  994. X        cmd = "MM";            /*{ perhaps "MM READ"? }*/
  995. X    } else if (!strncmpi(buf, "wpmail:", 7)) {
  996. X/*
  997. XWPmail: New mail from BAR.  subject_text
  998. X*/
  999. X        nam = "WPmail";        /* WordPerfect [sic] Office */
  1000. X        cmd = "OFFICE/MAIL";
  1001. X    } else if (!strncmpi(buf, "**m400 mail", 7)) {
  1002. X/*
  1003. X**M400 mail waiting**
  1004. X*/
  1005. X        nam = "M400mail";        /* Messenger 400 [not seen] */
  1006. X        cmd = "M400";
  1007. X    } else {
  1008. X        /* not recognized, but presumed to be mail */
  1009. X        nam = "unknown mail";
  1010. X        cmd = "SPAWN";        /* generic escape back to DCL */
  1011. X        txt = (char *) 0;        /* don't rely on "from" info here */
  1012. X    }
  1013. X
  1014. X    if (!txt) txt = strcat(strcpy(txt_buf, "Mail for you: "), buf);
  1015. X    /*
  1016. X     :    end of mail recognition; now check for call-type interruptions...
  1017. X     */
  1018. X    } else if ((q = strstri(buf, " phoning")) != 0) {
  1019. X/*
  1020. XBAR is phoning you [on FOO] \(HH:MM:SS\)
  1021. X*/
  1022. X    typ = MSG_CALL;
  1023. X    nam = "Phone call";
  1024. X    cmd = "PHONE ANSWER";
  1025. X    if (!strncmpi(q + 8, " you", 4)) q += (8 + 4), *q = '\0';
  1026. X    txt = strcat(strcpy(txt_buf, "Do you hear ringing?  "), buf);
  1027. X    } else if ((q = strstri(buf, " talk-daemon")) != 0 ||
  1028. X           (q = strstri(buf, " talk_daemon")) != 0) {
  1029. X/*
  1030. XMessage from TALK-DAEMON@FOO at HH:MM:SS\n
  1031. XConnection request by BAR@SPAM\n
  1032. X\[Respond with: TALK[/OLD] BAR@SPAM\]
  1033. X*/
  1034. X    typ = MSG_CALL;
  1035. X    nam = "Talk request";        /* MultiNet's TALK and/or TALK/OLD */
  1036. X    cmd = "TALK";
  1037. X    if ((p = strstri(q, " by ")) != 0) {
  1038. X        txt = strcat(strcpy(txt_buf, "Talk request from"), p + 3);
  1039. X        if ((p = strstri(p, "respond with")) != 0) {
  1040. X        if (*(p-1) == '[') *(p-1) = '\0'; else *p = '\0'; /* terminate */
  1041. X        p += (sizeof "respond with" - sizeof "");
  1042. X        if (*p == ':') p++;
  1043. X        if (*p == ' ') p++;
  1044. X        cmd = strcpy(cmd_buf, p);    /* "TALK[/OLD] bar@spam" */
  1045. X        p = eos(cmd);
  1046. X        if (*--p == ']') *p = '\0';
  1047. X        }
  1048. X    } else
  1049. X        txt = strcat(strcpy(txt_buf, "Pardon the interruption: "), buf);
  1050. X    } else if (is_jnet_send) {    /* sscanf(,"(%[^)])%s -%c",,,)==3 */
  1051. Xjnet_send:
  1052. X/*
  1053. X\(SPAM\)BAR - arbitrary_message_text (from BAR@SPAM)
  1054. X*/
  1055. X    typ = MSG_CALL;
  1056. X    nam = "Bitnet noise";        /* RSCS/NJE message received via JNET */
  1057. X    Sprintf(cmd = cmd_buf, "XYZZY %s@%s", user, node);
  1058. X    /*{ perhaps just vanilla SEND instead of XYZZY? }*/
  1059. X    Sprintf(txt = txt_buf, "Message from %s@%s:%s", user, node,
  1060. X        &buf[1+strlen(node)+1+strlen(user)+2-1]);  /* "(node)user -" */
  1061. X    /*
  1062. X     :    end of call recognition; anything else is none-of-the-above...
  1063. X     */
  1064. X    } else {
  1065. Xother:
  1066. X# endif /* SHELL */
  1067. X/* arbitrary broadcast: batch job completed, system shutdown imminent, &c */
  1068. X    typ = MSG_OTHER;
  1069. X    nam = (char *) 0; /*"captured broadcast message"*/
  1070. X    cmd = (char *) 0;
  1071. X    txt = strcat(strcpy(txt_buf, "Message for you: "), buf);
  1072. X# ifdef SHELL
  1073. X    }
  1074. X    /* Daemon in newmail() will append period when the text is displayed */
  1075. X    if ((p = eos(txt)) > txt && *--p == '.') *p = '\0';
  1076. X
  1077. X    /* newmail() and readmail() assume that nam and cmd are concatenated */
  1078. X    if (nam) {        /* object name to attach to scroll of mail */
  1079. X    nam = strcpy(nam_cmd_buf, nam);
  1080. X    if (cmd) {    /* append command to name; readmail() requires it */
  1081. X        int len = sizeof nam_cmd_buf - sizeof "" - (strlen(nam) + 1);
  1082. X        cmd_buf[len] = '\0';    /* possibly truncate */
  1083. X        (void) strcat(nam, " ");
  1084. X        cmd = strcpy(eos(nam), cmd);
  1085. X    }
  1086. X    }
  1087. X# endif /* SHELL */
  1088. X    msg.message_typ  = typ;    /* simple index */
  1089. X    msg.display_txt  = txt;    /* text for daemon to pline() */
  1090. X    msg.object_nam   = nam;    /* 'name' for mail scroll */
  1091. X    msg.response_cmd = cmd;    /* command to spawn when scroll read */
  1092. X    return &msg;
  1093. X}
  1094. X
  1095. X/* filter out non-printable characters and redundant noise
  1096. X*/
  1097. Xstatic void
  1098. Xfilter_brdcst(buf)        /* called by parse_next_broadcast() */
  1099. Xregister char *buf;        /* in: original text; out: filtered text */
  1100. X{
  1101. X    register char c, *p, *buf_p;
  1102. X
  1103. X    /* filter the text; restrict consecutive spaces or dots to just two */
  1104. X    for (p = buf_p = buf; *buf_p; buf_p++) {
  1105. X    c = *buf_p & '\177';
  1106. X    if (c == ' ' || c == '\t' || c == '\n')
  1107. X        if (p == buf ||        /* ignore leading whitespace */
  1108. X        (p >= buf+2 && *(p-1) == ' ' && *(p-2) == ' ')) continue;
  1109. X        else c = ' ';
  1110. X    else if (c == '.' || c < ' ' || c == '\177')
  1111. X        if (p == buf ||        /* skip leading beeps & such */
  1112. X        (p >= buf+2 && *(p-1) == '.' && *(p-2) == '.')) continue;
  1113. X        else c = '.';
  1114. X    else if (c == '%' &&        /* trim %%% OPCOM verbosity %%% */
  1115. X        p >= buf+2 && *(p-1) == '%' && *(p-2) == '%') continue;
  1116. X    *p++ = c;
  1117. X    }
  1118. X    *p = '\0';            /* terminate, then strip trailing junk */
  1119. X    while (p > buf && (*--p == ' ' || *p == '.')) *p = '\0';
  1120. X    return;
  1121. X}
  1122. X
  1123. X/* fetch the text of a captured broadcast, then mangle and decipher it
  1124. X*/
  1125. Xstruct mail_info *
  1126. Xparse_next_broadcast()        /* called by ckmailstatus(mail.c) */
  1127. X{
  1128. X    short length, msg_type;
  1129. X    $DESCRIPTOR(message, "");    /* string descriptor for buf[] */
  1130. X    struct mail_info *result = 0;
  1131. X    /* messages could actually be longer; let long ones be truncated */
  1132. X    char buf[255+1];
  1133. X
  1134. X    message.dsc$a_pointer = buf,  message.dsc$w_length = sizeof buf - 1;
  1135. X    msg_type = length = 0;
  1136. X    SMG$GET_BROADCAST_MESSAGE(&pasteboard_id, &message, &length, &msg_type);
  1137. X    if (msg_type == MSG$_TRMBRDCST) {
  1138. X    buf[length] = '\0';
  1139. X    filter_brdcst(buf);        /* mask non-printable characters */
  1140. X    result = parse_brdcst(buf);    /* do the real work */
  1141. X    } else if (msg_type == MSG$_TRMHANGUP) {
  1142. X    (void) gsignal(SIGHUP);
  1143. X    }
  1144. X    return result;
  1145. X}
  1146. X
  1147. X/* spit out any pending broadcast messages whenever we leave
  1148. X*/
  1149. Xstatic void
  1150. Xflush_broadcasts()    /* called from disable_broadcast_trapping() */
  1151. X{
  1152. X    if (broadcasts > 0) {
  1153. X    short len, typ;
  1154. X    $DESCRIPTOR(msg, "");
  1155. X    char buf[512+1];
  1156. X
  1157. X    msg.dsc$a_pointer = buf,  msg.dsc$w_length = sizeof buf - 1;
  1158. X    raw_print("");        /* print at least one line for wait_synch() */
  1159. X    do {
  1160. X        typ = len = 0;
  1161. X        SMG$GET_BROADCAST_MESSAGE(&pasteboard_id, &msg, &len, &typ);
  1162. X        if (typ == MSG$_TRMBRDCST) buf[len] = '\0',  raw_print(buf);
  1163. X    } while (--broadcasts);
  1164. X    wait_synch();        /* prompt with "Hit return to continue: " */
  1165. X    }
  1166. X}
  1167. X
  1168. X/* AST routine called when the terminal's associated mailbox receives a message
  1169. X*/
  1170. Xstatic void
  1171. Xbroadcast_ast(dummy)        /* called asynchronously by terminal driver */
  1172. Xint dummy;    /* not used */
  1173. X{
  1174. X    broadcasts++;
  1175. X}
  1176. X
  1177. X/* initialize the broadcast manipulation code; SMG makes this easy
  1178. X*/
  1179. Xunsigned long init_broadcast_trapping()   /* called by setftty() [once only] */
  1180. X{
  1181. X    unsigned long sts, preserve_screen_flag = 1;
  1182. X
  1183. X    /* we need a pasteboard to pass to the broadcast setup/teardown routines */
  1184. X    sts = SMG$CREATE_PASTEBOARD(&pasteboard_id, 0, 0, 0, &preserve_screen_flag);
  1185. X    if (!vms_ok(sts)) {
  1186. X    errno = EVMSERR,  vaxc$errno = sts;
  1187. X    raw_print("");
  1188. X    perror("?can't create SMG pasteboard for broadcast trapping");
  1189. X    wait_synch();
  1190. X    broadcasts = -1;    /* flag that trapping is currently broken */
  1191. X    }
  1192. X    return sts;
  1193. X}
  1194. X
  1195. X/* set up the terminal driver to deliver $brkthru data to a mailbox device
  1196. X*/
  1197. Xunsigned long enable_broadcast_trapping()    /* called by setftty() */
  1198. X{
  1199. X    unsigned long sts = 1;
  1200. X
  1201. X    if (broadcasts >= 0) {    /* (-1 => no pasteboard, so don't even try) */
  1202. X    /* register callback routine to be triggered when broadcasts arrive */
  1203. X    /* Note side effect:  also intercepts hangup notification. */
  1204. X    /* Another note:  TMPMBX privilege is required. */
  1205. X    sts = SMG$SET_BROADCAST_TRAPPING(&pasteboard_id, broadcast_ast, 0);
  1206. X    if (!vms_ok(sts)) {
  1207. X        errno = EVMSERR,  vaxc$errno = sts;
  1208. X        raw_print("");
  1209. X        perror("?can't enable broadcast trapping");
  1210. X        wait_synch();
  1211. X    }
  1212. X    }
  1213. X    return sts;
  1214. X}
  1215. X
  1216. X/* return to 'normal'; $brkthru data goes straight to the terminal
  1217. X*/
  1218. Xunsigned long disable_broadcast_trapping()    /* called by settty() */
  1219. X{
  1220. X    unsigned long sts = 1;
  1221. X
  1222. X    if (broadcasts >= 0) {
  1223. X    /* disable trapping; releases associated MBX so that SPAWN can work */
  1224. X    sts = SMG$DISABLE_BROADCAST_TRAPPING(&pasteboard_id);
  1225. X    if (!vms_ok(sts)) errno = EVMSERR,  vaxc$errno = sts;
  1226. X    flush_broadcasts();    /* don't hold on to any buffered ones */
  1227. X    }
  1228. X    return sts;
  1229. X}
  1230. X#else    /* MAIL */
  1231. X    /* simple stubs for non-mail configuration */
  1232. Xunsigned long init_broadcast_trapping() { return 1; }
  1233. Xunsigned long enable_broadcast_trapping() { return 1; }
  1234. Xunsigned long disable_broadcast_trapping() { return 1; }
  1235. X#endif    /* MAIL */
  1236. X
  1237. X/*----------------------------------------------------------------------*/
  1238. X
  1239. X#ifdef TEST_DRIVER
  1240. X    /* (Take parse_next_broadcast for a spin. :-) */
  1241. X
  1242. Xvolatile int broadcasts = 0;
  1243. X
  1244. Xvoid newmail(foo)
  1245. Xstruct mail_info *foo;
  1246. X{
  1247. X# define STRING(s) ((s) ? (s) : "<null>")
  1248. X    printf("\n\
  1249. X  message type = %d\n\
  1250. X  display text = \"%s\"\n\
  1251. X  object name  = \"%.*s\"\n\
  1252. X  response cmd = \"%s\"\n\
  1253. X",      foo->message_typ, STRING(foo->display_txt),
  1254. X    (foo->object_nam && foo->response_cmd) ?
  1255. X        (foo->response_cmd - foo->object_nam - 1) :
  1256. X        strlen(STRING(foo->object_nam)),
  1257. X    STRING(foo->object_nam), STRING(foo->response_cmd));
  1258. X# undef STRING
  1259. X}
  1260. X
  1261. Xvoid ckmailstatus()
  1262. X{
  1263. X    struct mail_info *brdcst, *parse_next_broadcast();
  1264. X
  1265. X    while (broadcasts > 0) {    /* process all trapped broadcasts [until] */
  1266. X    broadcasts--;
  1267. X    if ((brdcst = parse_next_broadcast()) != 0) {
  1268. X        newmail(brdcst);
  1269. X        break;        /* only handle one real message at a time */
  1270. X    } else
  1271. X        printf("\n--< non-broadcast encountered >--\n");
  1272. X    }
  1273. X}
  1274. X
  1275. Xint main()
  1276. X{
  1277. X    char dummy[BUFSIZ];
  1278. X
  1279. X    init_broadcast_trapping();
  1280. X    enable_broadcast_trapping();
  1281. X    for (;;) {
  1282. X    ckmailstatus();
  1283. X    printf("> "), fflush(stdout);    /* issue a prompt */
  1284. X    if (!gets(dummy)) break;    /* wait for a response */
  1285. X    }
  1286. X    disable_broadcast_trapping();
  1287. X    return 1;
  1288. X}
  1289. X
  1290. Xvoid panic(s) char *s; { raw_print(s); exit(1); }
  1291. X
  1292. Xvoid raw_print(s) char *s; { puts(s); fflush(stdout); }
  1293. X
  1294. Xvoid wait_synch() { char dummy[BUFSIZ];
  1295. X  printf("\nPress <return> to continue: "); fflush(stdout); (void) gets(dummy);
  1296. X}
  1297. X#endif    /* TEST_DRIVER */
  1298. X
  1299. X/*vmsmail.c*/
  1300. END_OF_FILE
  1301. if test 16224 -ne `wc -c <'sys/vms/vmsmail.c'`; then
  1302.     echo shar: \"'sys/vms/vmsmail.c'\" unpacked with wrong size!
  1303. fi
  1304. # end of 'sys/vms/vmsmail.c'
  1305. fi
  1306. if test -f 'sys/vms/vmstty.c' -a "${1}" != "-c" ; then 
  1307.   echo shar: Will not clobber existing file \"'sys/vms/vmstty.c'\"
  1308. else
  1309. echo shar: Extracting \"'sys/vms/vmstty.c'\" \(14490 characters\)
  1310. sed "s/^X//" >'sys/vms/vmstty.c' <<'END_OF_FILE'
  1311. X/*    SCCS Id: @(#)vmstty.c    3.1    92/11/24    */
  1312. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  1313. X/* NetHack may be freely redistributed.  See license for details. */
  1314. X/* tty.c - (VMS) version */
  1315. X
  1316. X#define NEED_VARARGS
  1317. X#include "hack.h"
  1318. X#include "wintty.h"
  1319. X#include "termcap.h"
  1320. X
  1321. X#include <descrip.h>
  1322. X#include <iodef.h>
  1323. X#ifndef __GNUC__
  1324. X#include <smgdef.h>
  1325. X#include <ttdef.h>
  1326. X#include <tt2def.h>
  1327. X#else    /* values needed from missing include files */
  1328. X# define SMG$K_TRM_UP     274
  1329. X# define SMG$K_TRM_DOWN  275
  1330. X# define SMG$K_TRM_LEFT  276
  1331. X# define SMG$K_TRM_RIGHT 277
  1332. X# define TT$M_MECHTAB     0x00000100    /* hardware tab support */
  1333. X# define TT$M_MECHFORM     0x00080000    /* hardware form-feed support */
  1334. X# define TT$M_NOBRDCST     0x00020000    /* disable broadcast messages, but  */
  1335. X# define TT2$M_BRDCSTMBX 0x00000010    /* catch them in associated mailbox */
  1336. X#endif /* __GNUC__ */
  1337. X#ifdef USE_QIO_INPUT
  1338. X#include <ssdef.h>
  1339. X#endif
  1340. X#include <errno.h>
  1341. X#include <signal.h>
  1342. X
  1343. Xunsigned long LIB$DISABLE_CTRL(), LIB$ENABLE_CTRL();
  1344. Xunsigned long SYS$ASSIGN(), SYS$DASSGN(), SYS$QIOW();
  1345. X#ifndef USE_QIO_INPUT
  1346. Xunsigned long SMG$CREATE_VIRTUAL_KEYBOARD(), SMG$DELETE_VIRTUAL_KEYBOARD(),
  1347. X          SMG$READ_KEYSTROKE(), SMG$CANCEL_INPUT();
  1348. X#else
  1349. Xstatic short FDECL(parse_function_key, (int));
  1350. X#endif
  1351. Xstatic void NDECL(setctty);
  1352. Xstatic void NDECL(resettty);
  1353. X
  1354. X#define vms_ok(sts) ((sts)&1)
  1355. X#define META(c)  ((c)|0x80)    /* 8th bit */
  1356. X#define CTRL(c)  ((c)&0x1F)
  1357. X#define CMASK(c) (1<<CTRL(c))
  1358. X#define LIB$M_CLI_CTRLT CMASK('T')    /* 0x00100000 */
  1359. X#define LIB$M_CLI_CTRLY CMASK('Y')    /* 0x02000000 */
  1360. X#define ESC '\033'
  1361. X#define CSI META(ESC)        /* '\233' */
  1362. X#define SS3 META(CTRL('O'))    /* '\217' */
  1363. X
  1364. Xextern short ospeed;
  1365. Xchar erase_char, intr_char, kill_char;
  1366. Xstatic boolean settty_needed = FALSE,  bombing = FALSE;
  1367. Xstatic unsigned long kb = 0;
  1368. X#ifdef USE_QIO_INPUT
  1369. Xstatic char inputbuf[15+1], *inp = 0;
  1370. Xstatic int  inc = 0;
  1371. X#endif
  1372. X
  1373. X#define QIO_FUNC    IO$_TTYREADALL|IO$M_NOECHO|IO$M_TRMNOECHO
  1374. X#ifdef MAIL
  1375. X#define TT_SPECIAL_HANDLING  (TT$M_MECHTAB|TT$M_MECHFORM|TT$M_NOBRDCST)
  1376. X#define TT2_SPECIAL_HANDLING (TT2$M_BRDCSTMBX)
  1377. X#else
  1378. X#define TT_SPECIAL_HANDLING  (TT$M_MECHTAB|TT$M_MECHFORM)
  1379. X#define TT2_SPECIAL_HANDLING (0)
  1380. X#endif
  1381. X#define Uword unsigned short
  1382. X#define Ubyte unsigned char
  1383. Xstruct _rd_iosb {        /* i/o status block for read */
  1384. X    Uword    status,  trm_offset;
  1385. X    Uword    terminator,  trm_siz;
  1386. X};
  1387. Xstruct _wr_iosb {        /* i/o status block for write */
  1388. X    Uword    status,  byte_cnt;
  1389. X    unsigned   : 32;
  1390. X};
  1391. Xstruct _sm_iosb {        /* i/o status block for sense-mode qio */
  1392. X    Uword      status;
  1393. X    Ubyte      xmt_speed,  rcv_speed;
  1394. X    Ubyte      cr_fill,  lf_fill,  parity;
  1395. X    unsigned   : 8;
  1396. X};
  1397. Xstruct _sm_bufr {        /* sense-mode characteristics buffer */
  1398. X    Ubyte      class,  type;        /* class==DC$_TERM, type==(various) */
  1399. X    Uword      buf_siz;        /* aka page width */
  1400. X#define page_width buf_siz        /* number of columns */
  1401. X          unsigned  tt_char    : 24;    /* primary characteristics */
  1402. X          unsigned  page_length    :  8;    /* number of lines */
  1403. X          unsigned  tt2_char    : 32;    /* secondary characteristics */
  1404. X};
  1405. Xstatic struct {
  1406. X    struct _sm_iosb io;
  1407. X    struct _sm_bufr sm;
  1408. X} sg = {{0},{0}};
  1409. Xstatic unsigned short tt_chan = 0;
  1410. Xstatic unsigned long  tt_char_restore = 0, tt_char_active = 0,
  1411. X              tt2_char_restore = 0, tt2_char_active = 0;
  1412. Xstatic unsigned long  ctrl_mask = 0;
  1413. X
  1414. Xint
  1415. Xvms_getchar()
  1416. X{
  1417. X    short key;
  1418. X
  1419. X#ifdef USE_QIO_INPUT
  1420. X    struct _rd_iosb iosb;
  1421. X    unsigned long sts;
  1422. X    unsigned char kb_buf;
  1423. X
  1424. X    if (inc > 0) {
  1425. X    /* we have buffered character(s) from previous read */
  1426. X    kb_buf = *inp++;
  1427. X    --inc;
  1428. X    sts = SS$_NORMAL;
  1429. X    } else {
  1430. X    sts = SYS$QIOW(0, tt_chan, QIO_FUNC, &iosb, (void(*)())0, 0,
  1431. X               &kb_buf, sizeof kb_buf, 0, 0, 0, 0);
  1432. X    }
  1433. X    if (vms_ok(sts)) {
  1434. X    if (kb_buf == CTRL('C')) {
  1435. X        if (intr_char) gsignal(SIGINT);
  1436. X        key = (short)kb_buf;
  1437. X    } else if (kb_buf == '\r') {    /* <return> */
  1438. X        key = (short)'\n';
  1439. X    } else if (kb_buf == ESC || kb_buf == CSI || kb_buf == SS3) {
  1440. X        switch(parse_function_key((int)kb_buf)) {
  1441. X          case SMG$K_TRM_UP:    key = flags.num_pad ? '8' : 'k';  break;
  1442. X          case SMG$K_TRM_DOWN:  key = flags.num_pad ? '2' : 'j';  break;
  1443. X          case SMG$K_TRM_LEFT:  key = flags.num_pad ? '4' : 'h';  break;
  1444. X          case SMG$K_TRM_RIGHT: key = flags.num_pad ? '6' : 'l';  break;
  1445. X          default:            key = ESC;    break;
  1446. X        }
  1447. X    } else {
  1448. X        key = (short)kb_buf;
  1449. X    }
  1450. X    } else if (sts == SS$_HANGUP || iosb.status == SS$_HANGUP) {
  1451. X    gsignal(SIGHUP);
  1452. X    key = ESC;
  1453. X    } else            /*(this should never happen)*/
  1454. X    key = getchar();
  1455. X
  1456. X#else   /*!USE_QIO_INPUT*/
  1457. X    static volatile int recurse = 0;    /* SMG is not AST re-entrant! */
  1458. X
  1459. X    if (recurse++ == 0 && kb != 0) {
  1460. X    SMG$READ_KEYSTROKE(&kb, &key);
  1461. X    switch (key) {
  1462. X      case SMG$K_TRM_UP:    flags.num_pad ? '8' : key = 'k';  break;
  1463. X      case SMG$K_TRM_DOWN:    flags.num_pad ? '2' : key = 'j';  break;
  1464. X      case SMG$K_TRM_LEFT:    flags.num_pad ? '4' : key = 'h';  break;
  1465. X      case SMG$K_TRM_RIGHT: flags.num_pad ? '6' : key = 'l';  break;
  1466. X      case '\r':        key = '\n'; break;
  1467. X      default:        if (key > 255)    key = ESC;
  1468. X                break;
  1469. X    }
  1470. X    } else {
  1471. X    /* abnormal input--either SMG didn't initialize properly or
  1472. X       vms_getchar() has been called recursively (via SIGINT handler).
  1473. X     */
  1474. X    if (kb != 0)            /* must have been a recursive call */
  1475. X        SMG$CANCEL_INPUT(&kb);    /*  from an interrupt handler       */
  1476. X    key = getchar();
  1477. X    }
  1478. X    --recurse;
  1479. X#endif    /* USE_QIO_INPUT */
  1480. X
  1481. X    return (int)key;
  1482. X}
  1483. X
  1484. X#ifdef USE_QIO_INPUT
  1485. X       /*
  1486. X    * We've just gotten an <escape> character.  Do a timed read to
  1487. X    * get any other characters, then try to parse them as an escape
  1488. X    * sequence.  This isn't perfect, since there's no guarantee
  1489. X    * that a full escape sequence will be available, or even if one
  1490. X    * is, it might actually by regular input from a fast typist or
  1491. X    * a stalled input connection.  {For packetized environments,
  1492. X    * cross plural(body_part(FINGER)) and hope for best. :-}
  1493. X    *
  1494. X    * This is needed to preserve compatability with SMG interface
  1495. X    * for two reasons:
  1496. X    *    1) retain support for arrow keys, and
  1497. X    *    2) treat other VTxxx function keys as <esc> for aborting
  1498. X    *    various NetHack prompts.
  1499. X    * The second reason is compelling; otherwise remaining chars of
  1500. X    * an escape sequence get treated as inappropriate user commands.
  1501. X    *
  1502. X    * SMG code values for these key sequences fall in the range of
  1503. X    * 256 thru 3xx.  The assignments are not particularly intuitive.
  1504. X    */
  1505. X/*=
  1506. X     -- Summary of VTxxx-style keyboards and transmitted escape sequences. --
  1507. XKeypad codes are prefixed by 7 bit (\033 O) or 8 bit SS3:
  1508. X    keypad:  PF1 PF2 PF3 PF4       codes:    P   Q    R   S
  1509. X          7   8   9   -            w   x    y   m
  1510. X          4   5   6   .            t   u    v   n
  1511. X          1   2   3  :en-:        q   r    s  : :
  1512. X         ...0...  ,  :ter:           ...p...    l  :M:
  1513. XArrows are prefixed by either SS3 or CSI (either 7 or 8 bit), depending on
  1514. Xwhether the terminal is in application or numeric mode (ditto for PF keys):
  1515. X    arrows: <up> <dwn> <lft> <rgt>        A   B    D   C
  1516. XAdditional function keys (vk201/vk401) generate CSI nn ~ (nn is 1 or 2 digits):
  1517. X    vk201 keys:  F6 F7 F8 F9 F10   F11 F12 F13 F14  Help Do   F17 F18 F19 F20
  1518. X   'nn' digits:  17 18 19 20 21    23  24  25  26    28  29   31  32  33  34
  1519. X     alternate:  ^C           ^[  ^H  ^J        (when in VT100 mode)
  1520. X   edit keypad: <fnd> <ins> <rmv>     digits:    1   2    3
  1521. X        <sel> <prv> <nxt>        4   5    6
  1522. XVT52 mode:  arrows and PF keys send ESCx where x is in A-D or P-S.
  1523. X=*/
  1524. X
  1525. Xstatic const char *arrow_or_PF = "ABCDPQRS",    /* suffix char */
  1526. X          *smg_keypad_codes = "PQRSpqrstuvwxyMmlnABDC";
  1527. X    /* PF1..PF4,KP0..KP9,enter,dash,comma,dot,up-arrow,down,left,right */
  1528. X    /* Ultimate return value is (index into smg_keypad_codes[] + 256). */
  1529. X
  1530. Xstatic short
  1531. Xparse_function_key(c)
  1532. Xregister int c;
  1533. X{
  1534. X    struct _rd_iosb iosb;
  1535. X    unsigned long sts;
  1536. X    char seq_buf[15+1];        /* plenty room for escape sequence + slop */
  1537. X    short result = ESC;        /* translate to <escape> by default */
  1538. X
  1539. X    /*
  1540. X     * Read whatever we can from type-ahead buffer (1 second timeout).
  1541. X     * If the user typed an actual <escape> to deliberately abort
  1542. X     * something, he or she should be able to tolerate the necessary
  1543. X     * restriction of a negligible pause before typing anything else.
  1544. X     * We might already have [at least some of] an escape sequence from a
  1545. X     * previous read, particularly if user holds down the arrow keys...
  1546. X     */
  1547. X    if (inc > 0) strncpy(seq_buf, inp, inc);
  1548. X    if (inc < sizeof seq_buf - 1) {
  1549. X    sts = SYS$QIOW(0, tt_chan, QIO_FUNC|IO$M_TIMED, &iosb, (void(*)())0, 0,
  1550. X               seq_buf + inc, sizeof seq_buf - 1 - inc, 1, 0, 0, 0);
  1551. X    if (vms_ok(sts))  sts = iosb.status;
  1552. X    } else
  1553. X    sts = SS$_NORMAL;
  1554. X    if (vms_ok(sts) || sts == SS$_TIMEOUT) {
  1555. X    register int cnt = iosb.trm_offset + iosb.trm_siz + inc;
  1556. X    register char *p = seq_buf;
  1557. X    if (c == ESC)    /* check for 7-bit vt100/ANSI, or vt52 */
  1558. X        if (*p == '[' || *p == 'O') c = META(CTRL(*p++)),  cnt--;
  1559. X        else if (strchr(arrow_or_PF, *p)) c = SS3; /*CSI*/
  1560. X    if (cnt > 0 && (c == SS3 || (c == CSI && strchr(arrow_or_PF, *p)))) {
  1561. X        register char *q = strchr(smg_keypad_codes, *p);
  1562. X        if (q) result = 256 + (q - smg_keypad_codes);
  1563. X        p++,  --cnt;    /* one more char consumed */
  1564. X    } else if (cnt > 1 && c == CSI) {
  1565. X        static short    /* "CSI nn ~" -> F_keys[nn] */
  1566. X        F_keys[35] = {    ESC,                /*(filler)*/
  1567. X                311, 312, 313, 314, 315, 316,    /* E1-E6 */
  1568. X                ESC, ESC, ESC, ESC,       /*(more filler)*/
  1569. X                281, 282, 283, 284, 285, ESC,    /* F1-F5 */
  1570. X                286, 287, 288, 289, 290, ESC,    /* F6-F10*/
  1571. X                291, 292, 293, 294, ESC,    /*F11-F14*/
  1572. X                295, 296, ESC, /*<help>,<do>, aka F15,F16*/
  1573. X                297, 298, 299, 300        /*F17-F20*/
  1574. X        };  /* note: there are several missing nn in CSI nn ~ values */
  1575. X        int nn;  char *q;
  1576. X        *(p + cnt) = '\0';    /* terminate string */
  1577. X        q = strchr(p, '~');
  1578. X        if (q && sscanf(p, "%d~", &nn) == 1) {
  1579. X        if (nn > 0 && nn < SIZE(F_keys)) result = F_keys[nn];
  1580. X        cnt -= (++q - p);
  1581. X        p = q;
  1582. X        }
  1583. X    }
  1584. X    if (cnt > 0) strncpy((inp = inputbuf), p, (inc = cnt));
  1585. X    else         inc = 0,  inp = 0;
  1586. X    }
  1587. X    return result;
  1588. X}
  1589. X#endif    /* USE_QIO_INPUT */
  1590. X
  1591. Xstatic void
  1592. Xsetctty()
  1593. X{
  1594. X    struct _sm_iosb iosb;
  1595. X    unsigned long status;
  1596. X
  1597. X    status = SYS$QIOW(0, tt_chan, IO$_SETMODE, &iosb, (void(*)())0, 0,
  1598. X              &sg.sm, sizeof sg.sm, 0, 0, 0, 0);
  1599. X    if (vms_ok(status))  status = iosb.status;
  1600. X    if (!vms_ok(status)) {
  1601. X    raw_print("");
  1602. X    errno = EVMSERR,  vaxc$errno = status;
  1603. X    perror("NetHack(setctty: setmode)");
  1604. X    wait_synch();
  1605. X    }
  1606. X}
  1607. X
  1608. Xstatic void
  1609. Xresettty(){            /* atexit() routine */
  1610. X    if (settty_needed) {
  1611. X    bombing = TRUE;     /* don't clear screen; preserve traceback info */
  1612. X    settty((char *)NULL);
  1613. X    }
  1614. X    (void) SYS$DASSGN(tt_chan),  tt_chan = 0;
  1615. X}
  1616. X
  1617. X/*
  1618. X * Get initial state of terminal, set ospeed (for termcap routines)
  1619. X * and switch off tab expansion if necessary.
  1620. X * Called by init_nhwindows() and resume_nhwindows() in wintty.c
  1621. X * (for initial startup and for returning from '!' or ^Z).
  1622. X */
  1623. Xvoid
  1624. Xgettty()
  1625. X{
  1626. X    static $DESCRIPTOR(tty_dsc, "TT:");
  1627. X    int err = 0;
  1628. X    unsigned long status, zero = 0;
  1629. X
  1630. X    if (tt_chan == 0) {        /* do this stuff once only */
  1631. X    flags.cbreak = OFF,  flags.echo = ON;    /* until setup is complete */
  1632. X    status = SYS$ASSIGN(&tty_dsc, &tt_chan, 0, 0);
  1633. X    if (!vms_ok(status)) {
  1634. X        raw_print(""),  err++;
  1635. X        errno = EVMSERR,  vaxc$errno = status;
  1636. X        perror("NetHack(gettty: $assign)");
  1637. X    }
  1638. X    atexit(resettty);   /* register an exit handler to reset things */
  1639. X    }
  1640. X    status = SYS$QIOW(0, tt_chan, IO$_SENSEMODE, &sg.io, (void(*)())0, 0,
  1641. X              &sg.sm, sizeof sg.sm, 0, 0, 0, 0);
  1642. X    if (vms_ok(status))  status = sg.io.status;
  1643. X    if (!vms_ok(status)) {
  1644. X    raw_print(""),  err++;
  1645. X    errno = EVMSERR,  vaxc$errno = status;
  1646. X    perror("NetHack(gettty: sensemode)");
  1647. X    }
  1648. X    ospeed = sg.io.xmt_speed;
  1649. X    erase_char = '\177';    /* <rubout>, aka <delete> */
  1650. X    kill_char = CTRL('U');
  1651. X    intr_char = CTRL('C');
  1652. X    (void) LIB$ENABLE_CTRL(&zero, &ctrl_mask);
  1653. X    /* Use the systems's values for lines and columns if it has any idea. */
  1654. X    if (sg.sm.page_length)
  1655. X    LI = sg.sm.page_length;
  1656. X    if (sg.sm.page_width)
  1657. X    CO = sg.sm.page_width;
  1658. X    /* Determine whether TTDRIVER is doing tab and/or form-feed expansion;
  1659. X       if so, we want to suppress that but also restore it at final exit. */
  1660. X    if ((sg.sm.tt_char & TT_SPECIAL_HANDLING) != TT_SPECIAL_HANDLING
  1661. X     && (sg.sm.tt2_char & TT2_SPECIAL_HANDLING) != TT2_SPECIAL_HANDLING) {
  1662. X    tt_char_restore  = sg.sm.tt_char;
  1663. X    tt_char_active     = sg.sm.tt_char |= TT_SPECIAL_HANDLING;
  1664. X    tt2_char_restore = sg.sm.tt2_char;
  1665. X    tt2_char_active  = sg.sm.tt2_char |= TT2_SPECIAL_HANDLING;
  1666. X#if 0        /*[ defer until setftty() ]*/
  1667. X    setctty();
  1668. X#endif
  1669. X    } else    /* no need to take any action */
  1670. X    tt_char_restore = tt_char_active = 0,
  1671. X    tt2_char_restore = tt2_char_active = 0;
  1672. X    if (err) wait_synch();
  1673. X}
  1674. X
  1675. X/* reset terminal to original state */
  1676. Xvoid
  1677. Xsettty(s)
  1678. Xconst char *s;
  1679. X{
  1680. X    if (!bombing) {
  1681. X        end_screen();
  1682. X        if (s) raw_print(s);
  1683. X    }
  1684. X    disable_broadcast_trapping();
  1685. X#if 0        /* let SMG's exit handler do the cleanup (as per doc) */
  1686. X/* #ifndef USE_QIO_INPUT */
  1687. X    if (kb)  SMG$DELETE_VIRTUAL_KEYBOARD(&kb),  kb = 0;
  1688. X#endif    /* 0 (!USE_QIO_INPUT) */
  1689. X    if (ctrl_mask)
  1690. X        (void) LIB$ENABLE_CTRL(&ctrl_mask, 0);
  1691. X    flags.echo = ON;
  1692. X    flags.cbreak = OFF;
  1693. X    if (tt_char_restore != 0 || tt2_char_restore != 0) {
  1694. X        sg.sm.tt_char  = tt_char_restore;
  1695. X        sg.sm.tt2_char = tt2_char_restore;
  1696. X        setctty();
  1697. X    }
  1698. X    settty_needed = FALSE;
  1699. X}
  1700. X
  1701. X/* same as settty, with no clearing of the screen */
  1702. Xvoid
  1703. Xshuttty(s)
  1704. Xconst char *s;
  1705. X{
  1706. X    if(s) raw_print(s);
  1707. X    bombing = TRUE;
  1708. X    settty(s);
  1709. X    bombing = FALSE;
  1710. X}
  1711. X
  1712. Xvoid
  1713. Xsetftty()
  1714. X{
  1715. X    unsigned long mask = LIB$M_CLI_CTRLT | LIB$M_CLI_CTRLY;
  1716. X
  1717. X    (void) LIB$DISABLE_CTRL(&mask, 0);
  1718. X    if (kb == 0) {        /* do this stuff once only */
  1719. X#ifdef USE_QIO_INPUT
  1720. X        kb = tt_chan;
  1721. X#else   /*!USE_QIO_INPUT*/
  1722. X        SMG$CREATE_VIRTUAL_KEYBOARD(&kb);
  1723. X#endif  /*USE_QIO_INPUT*/
  1724. X        init_broadcast_trapping();
  1725. X    }
  1726. X    enable_broadcast_trapping();    /* no-op if !defined(MAIL) */
  1727. X    flags.cbreak = (kb != 0) ? ON : OFF;
  1728. X    flags.echo   = (kb != 0) ? OFF : ON;
  1729. X    /* disable tab & form-feed expansion */
  1730. X    if (tt_char_active != 0 || tt2_char_active != 0) {
  1731. X        sg.sm.tt_char  = tt_char_active;
  1732. X        sg.sm.tt2_char = tt2_char_active;
  1733. X        setctty();
  1734. X    }
  1735. X    start_screen();
  1736. X    settty_needed = TRUE;
  1737. X}
  1738. X
  1739. Xvoid
  1740. Xintron()        /* enable kbd interupts if enabled when game started */
  1741. X{
  1742. X    intr_char = CTRL('C');
  1743. X}
  1744. X
  1745. Xvoid
  1746. Xintroff()        /* disable kbd interrupts if required*/
  1747. X{
  1748. X    intr_char = 0;
  1749. X}
  1750. X
  1751. X
  1752. X/* fatal error */
  1753. X/*VARARGS1*/
  1754. Xvoid
  1755. Xerror VA_DECL(const char *,s)
  1756. X    VA_START(s);
  1757. X    VA_INIT(s, const char *);
  1758. X    if(settty_needed)
  1759. X        settty(NULL);
  1760. X    Vprintf(s,VA_ARGS);
  1761. X    (void) putchar('\n');
  1762. X    VA_END();
  1763. X    exit(1);
  1764. X}
  1765. END_OF_FILE
  1766. if test 14490 -ne `wc -c <'sys/vms/vmstty.c'`; then
  1767.     echo shar: \"'sys/vms/vmstty.c'\" unpacked with wrong size!
  1768. fi
  1769. # end of 'sys/vms/vmstty.c'
  1770. fi
  1771. echo shar: End of archive 87 \(of 108\).
  1772. cp /dev/null ark87isdone
  1773. MISSING=""
  1774. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  1775. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  1776. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  1777. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  1778. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  1779. 101 102 103 104 105 106 107 108 ; do
  1780.     if test ! -f ark${I}isdone ; then
  1781.     MISSING="${MISSING} ${I}"
  1782.     fi
  1783. done
  1784. if test "${MISSING}" = "" ; then
  1785.     echo You have unpacked all 108 archives.
  1786.     echo "Now execute 'rebuild.sh'"
  1787.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  1788. else
  1789.     echo You still need to unpack the following archives:
  1790.     echo "        " ${MISSING}
  1791. fi
  1792. ##  End of shell archive.
  1793. exit 0
  1794.