home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume16 / nethack31 / part71 < 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: v16i079:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part71/108
  5. Message-ID: <4442@master.CNA.TEK.COM>
  6. Date: 5 Feb 93 19:19:36 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2040
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1630
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 79
  14. Archive-name: nethack31/Part71
  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 71 (of 108)."
  27. # Contents:  doc/tmac.n src/mkmaze.c
  28. # Wrapped by billr@saab on Wed Jan 27 16:09:15 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'doc/tmac.n' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'doc/tmac.n'\"
  32. else
  33. echo shar: Extracting \"'doc/tmac.n'\" \(25079 characters\)
  34. sed "s/^X//" >'doc/tmac.n' <<'END_OF_FILE'
  35. X\" @(#)$Id: tmac.n,v 3.0 89/06/21 21:44:28 syd Exp $
  36. X.\" The News macro package
  37. X.\"
  38. X.\" This  is  the macro package that is used to format news documents.  It
  39. X.\" was written because many sites do not have one of the -mm or -ms pack-
  40. X.\" ages that the documents use.   This is NOT compatible with EITHER, but
  41. X.\" (I hope) will become the standard for all news  documents  (man  pages
  42. X.\" excepted, since everyone seems to have -man.)
  43. X.\"
  44. X.\" This package was written using  only  the  "NROFF/TROFF Users' Guide",
  45. X.\" and  therefore  if  you  can run NROFF/TROFF, you can legitimately use
  46. X.\" this package.  However, because NROFF/TROFF are proprietary  programs,
  47. X.\" I  cannot  place  this  package in the public domain.  This should not
  48. X.\" matter, because if you legitimately have  NROFF/TROFF,  you  have  the
  49. X.\" documentation; if not, you can't run off the documentation anyway.
  50. X.\"
  51. X.\" This  package may be circulated freely with the news documentation; it
  52. X.\" may not be sold, but is to be distributed with  the  unformatted  news
  53. X.\" documents.  However,  the name of the author and the place at which it
  54. X.\" was written (in the author's own  time,  of  course)  are  not  to  be
  55. X.\" removed  from the package regardless of how it is modified or altered.
  56. X.\" Further, please do not distribute this package if you make any changes
  57. X.\" because  I  don't want to get bug reports of macros I haven't written;
  58. X.\" if you have a goodie you want me to add, send it to me and we'll talk.
  59. X.\" (I really do like feedback!)  I'd really appreciate your cooperation.
  60. X.\"
  61. X.\" Author:    Matt Bishop
  62. X.\"        Research Institute for Advanced Computer Science
  63. X.\"        Mail Stop 230-5
  64. X.\"         NASA Ames Research Center
  65. X.\"        Moffett Field, CA  94035
  66. X.\"
  67. X.\" version 1.0        September 28, 1985    mab@riacs.arpa
  68. X.\"     initial version
  69. X.\" version 1.1        October 25, 1985    mab@riacs.arpa
  70. X.\"    fixed an incredibly obscure footnote bug (that occurred twice in
  71. X.\"    the news documentation!) which put footnoted words on  one  page
  72. X.\"    and the footnote on the next if the word was in the next-to-last
  73. X.\"    or last line; commented it, and generally cleaned up
  74. X.\" Version 1.2        October 27, 1985    mab@riacs.arpa
  75. X.\"    Added a few more comments and a check to keep footnotes lined up
  76. X.\"    with the bottom margin.
  77. X.\" Version 1.3        February 12, 1986    mab@riacs.arpa
  78. X.\"    Added an error check to catch unmatched ef's and ed's
  79. X.\" Version 1.4        December 29, 1986    mab@riacs.edu
  80. X.\"    Changed footnote for ux, pd, and vx macros and  added  a  string
  81. X.\"    for rg ("Registered Trademark")
  82. X.\" Version 1.5        January 2, 1989        Matt.Bishop@dartmouth.edu
  83. X.\"    Minor modifications for nroff compatibility
  84. X.\" Version 1.6        March 15, 1989        Matt.Bishop@dartmouth.edu
  85. X.\"                        ..!bear.dartmouth.edu!bishop
  86. X.\"    Fixed a bug in footnote handling (again, sigh ...)  This one
  87. X.\"    occurred when the the "fo" trap position was reset just beneath
  88. X.\"    the current line; the footnote overflow trap would kick in and
  89. X.\"    never be closed.
  90. X.\"
  91. X.\"
  92. X.\" **********
  93. X.\" these preserve and restore various things
  94. X.\" they are used to shorten other macros
  95. X.de yf                    \" restore fonts
  96. X.ft \\n(f2                \" previous font
  97. X.ft \\n(f1                \" current font
  98. X..
  99. X.de yi                    \" restore indents
  100. X'in \\n(i2u                \" previous indent
  101. X'in \\n(i1u                \" current indent
  102. X..
  103. X.de ys                    \" restore point sizes
  104. X.ps \\n(s2                \" previous point size
  105. X.ps \\n(s1                \" current point size
  106. X..
  107. X.de yv                    \" restore vertical spacings
  108. X.vs \\n(v2u                \" previous vertical spacing
  109. X.vs \\n(v1u                \" current vertical spacing
  110. X..
  111. X.de ya                    \" restore everything
  112. X.yf                    \" restore fonts
  113. X.yi                    \" restore indents
  114. X.ys                    \" restore point sizes
  115. X.yv                    \" restore vertical spacing
  116. X..
  117. X.de zf                    \" preserve fonts
  118. X.nr f1 \\n(.f                \" current font
  119. X.ft                    \" switch to previous font
  120. X.nr f2 \\n(.f                \" previous font
  121. X.ft                    \" back to current font
  122. X..
  123. X.de zi                    \" preserve indents
  124. X.nr i1 \\n(.iu                \" current indent
  125. X'in                    \" switch to previous indent
  126. X.nr i2 \\n(.iu                \" previous indent
  127. X'in                    \" back to current indent
  128. X..
  129. X.de zs                    \" preserve point sizes
  130. X.nr s1 \\n(.su                \" current point size
  131. X.ps                    \" switch to previous point size
  132. X.nr s2 \\n(.su                \" previous point size
  133. X.ps                    \" back to current point size
  134. X..
  135. X.de zv                    \" preserve vertical spacings
  136. X.nr v1 \\n(.vu                \" current vertical spacing
  137. X.vs                    \" switch to previous vertical spacing
  138. X.nr v2 \\n(.vu                \" previous vertical spacing
  139. X.vs                    \" back to current vertical spacing
  140. X..
  141. X.de za                    \" save everything
  142. X.zf                    \" save fonts
  143. X.zi                    \" save indents
  144. X.zs                    \" save point sizes
  145. X.zv                    \" save vertical spacings
  146. X..
  147. X.\" **********
  148. X.\" these actually print the header and footer titles
  149. X.\" they are defined separately from the "hd" and "fo" macros
  150. X.\" to make user redefinition easy
  151. X.de pt                    \" print header title
  152. X.                    \" omit header on first page
  153. X.if \\n%>1 \{\
  154. X'    sp |\\$1u            \" move to proper position
  155. X.    ft 1                \" change to default font
  156. X.    ps \\n(ps            \" change to default point size
  157. X.    vs \\n(vs            \" change to default spacing
  158. X.    tl '\\*(h0'\\*(h1'\\*(h2'    \" center title
  159. X.    vs                \" restore current vertical spacing
  160. X.    ps                \" restore current point size
  161. X.    ft                \" restore current font
  162. X.\}
  163. X..
  164. X.de pf                    \" print footer title
  165. X.ft 1                    \" change to default font
  166. X.ps \\n(ps                \" change to default point size
  167. X.vs \\n(vs                \" change to default spacing
  168. X.ie \\n%=1 .tl '\\*(h0'\\*(h1'\\*(h2'    \" on first page, print the header here
  169. X.el        .tl '\\*(f0'\\*(f1'\\*(f2'    \" on other pages, print the footer
  170. X.vs                    \" restore current vertical spacing
  171. X.ps                    \" restore current point size
  172. X.ft                    \" restore current font
  173. X..
  174. X.\" **********
  175. X.\" these are the top of page (header) and bottom of page (footer) macros
  176. X.\" they don't actually print anything, just call the right macros
  177. X.de hd                    \" header -- do top of page processing
  178. X.if t .if \\n(cm .tl '\(rn'''        \" drop cut mark if needed
  179. X.pt \\n(ttu                \" print header
  180. X.nr fc 0 1                \" init footnote count
  181. X.nr fs \\n(.pu-\\n(bmu-1u        \" if any footnotes, start print here
  182. X.nr fp 0-\\n(bmu            \" reset current footer place
  183. X.ch fo -\\n(bmu                \" reset footer trap
  184. X.if \\n(dn .fz                \" put leftover footnotes st bottom
  185. X.ya                    \" restore font, etc.
  186. X'sp |\\n(tmu                \" move to top of body
  187. X.ns                    \" don't allow any more space
  188. X..
  189. X.de fo                    \" footer -- do bottom of page processing
  190. X.za                    \" save font, etc.
  191. X.rs                    \" you want motions here
  192. X.nr dn 0                \" clobber diversion size register
  193. X.if \\n(fc .fd                \" now print the footnotes, if any
  194. X'bp                    \" force out page
  195. X..
  196. X.\" **********
  197. X.\" these are the footnote macros
  198. X.\" here's an overview:
  199. X.\"    Footnotes are processed in environment #1, which is  initialized
  200. X.\"    at the bottom of this package.  When "fn" is called, nroff/troff
  201. X.\"    switches to this environment.  The body of the footnote is saved
  202. X.\"    in  the  diversion  "tf" (for "temporary footnote"), so you will
  203. X.\"    NEVER spring a trap during the first reading of a footnote. When
  204. X.\"    "ef" ("end footnote") is called,  the diversion  is  closed.  If
  205. X.\"    this  is the first footnote on the page (ie, the number register
  206. X.\"    "fc" is 1), and the footnote height (plus the height of 1  line)
  207. X.\"    crosses  the  bottom  margin,  you get the footnoted word on one
  208. X.\"    page and the footnote on the other.  In this case we  just  call
  209. X.\"    "fo"  manually  (taking case it cannot be re-invoked on the same
  210. X.\"    page!)  If this situation does not occur,  we  just  adjust  the
  211. X.\"    footer  trap's  position upwards (we'll get to how far in a min-
  212. X.\"    ute); if this puts the trap above the current line,  we  reposi-
  213. X.\"    tion  the trap just beneath the current line to be sure of trig-
  214. X.\"    triggering it once the current line is forced out.
  215. X.\"     To reposition the footer trap, we proceed as  follows.  Because
  216. X.\"    the  trap  may be sprung in the middle of a line, it is possible
  217. X.\"    that the footnote will not fit on the page (regardless of  where
  218. X.\"    on the page the footnoted word occurs -- really!) if we move the
  219. X.\"    trap up by the size of  the  footnote  diversion  "tf".  So,  we
  220. X.\"    fudge things a little bit -- for the first footnote on each page
  221. X.\"    we move the footer trap up 1 extra line ("line" being 1v in env-
  222. X.\"    ironment  #0).   Unless  the point size and vertical spacing are
  223. X.\"    increased between the first footnote and the footer trap's being
  224. X.\"    sprung,  this  will  keep  the footnotes on the same page as the
  225. X.\"    footnoted word.  But as there may be now as much as 1v of  space
  226. X.\"    between the footnote and the bottom margin, which looks HIDEOUS,
  227. X.\"    we use the number register "fs" to mark where  the  footer  trap
  228. X.\"    would  REALLY go, and just space to it when it comes time to put
  229. X.\"    out the footnotes.
  230. X.de fd                    \" dump footnotes
  231. X.nr gs 1v                \" get a measure of 1 line in env #0
  232. X.ev 1                    \" switch to footnote environment
  233. X.nr gs +2v                \" min of 2 lines of footnotes
  234. X.                    \" if the number register ns > 0,
  235. X.                    \" the last text line may contain a
  236. X.                    \" footnote that is too big to fit;
  237. X.                    \" this checks for such a note and
  238. X.                    \" if so, forces the footnote into
  239. X.                    \" the "fy" diversion that carries
  240. X.                    \" it onto the next text page
  241. X.ie (\\n(nsu>0)&(\\n(gsu>=\\n(.tu) 'sp \\n(gsu    \" be sure you can get it down
  242. X.el .if \\n(fsu>\\n(nlu 'sp \\n(fsu-\\n(nlu    \" move to footnote start position
  243. X'nf                    \" don't reprocess footnotes
  244. X'in 0                    \" don't indent them any more either
  245. X.tf                    \" drop text of footnotes
  246. X.rm tf
  247. X.if '\\n(.z'fy' .di            \" end overflow diversion, if any
  248. X.nr fc 0                \" re-init footnote count
  249. X.ev                    \" return to usual environment
  250. X..
  251. X.de fn                    \" start footnote
  252. X.                    \" look for nested footnotes -- ILLEGAL
  253. X.ie \\n(if>0 .er "footnote within footnote"
  254. X.el .da tf                \" append footnote to footnote diversion
  255. X.nr if +1                \" increment level of footnoting
  256. X.nr fc +1                \" one more footnote on this page
  257. X.if \\n(fc=1 .nr fp -1v            \" The reason for this "fudge factor"
  258. X.                    \" is that there is no way to force
  259. X.                    \" NROFF/TROFF to invoke a macro at
  260. X.                    \" the end of each line.  At times,
  261. X.                    \" the trap boundary will not match up
  262. X.                    \" with the bottom of a line, so the
  263. X.                    \" "fo" trap which is set at 2320 may
  264. X.                    \" not be triggered until 2340 -- and
  265. X.                    \" then the footnote won't fit.  This
  266. X.                    \" gives some slack so the footnote is
  267. X.                    \" more likely to fit. *sigh*
  268. X.ev 1                    \" enter footnote environment
  269. X.if \\n(fc=1 .fs            \" drop separator if first footnote
  270. X.br                    \" flush out any previous line in footnote
  271. X.fi                    \" process footnote in fill mode
  272. X..
  273. X.de ef                    \" end footnote
  274. X.br                    \" flush out the line in footnote
  275. X.ie \\n(if<=0 .er "end footnote has no corresponding begin footnote"
  276. X.el \{\
  277. X.    nr if -1            \" decrement level of footnoting
  278. X.    nr fg 2v            \" remember this for repositioning fo
  279. X.    ev                \" back to usual environment
  280. X.    if \\n(if=0 \{\
  281. X.        di            \" end of footnote proper
  282. X.        nr fp -\\n(dnu        \" "fo" will be moved at least up this far
  283. X.        nr fs -\\n(dnu        \" increase size of footnote
  284. X.        ch fo \\n(fpu        \" reposition "fo" trap (first guess)
  285. X.                    \" the first part of the "ie" clause
  286. X.                    \" is taken in the special case
  287. X.                    \" described above
  288. X.        ie (\\n(fc=1)&((\\n(nlu+1v+\\n(fgu)>=(\\n(.pu-\\n(bmu)) \{\
  289. X.            nr ns \\n(dnu    \" suppress footnote separator
  290. X.                    \" since this footnote contains it
  291. X.                    \" keep "fo" from being invoked twice
  292. X.            ch fo \\n(.pu+1i
  293. X.            fo        \" force the page out AT ONCE
  294. X.            nr ns 0        \" re-enable footnote separator
  295. X.        \}
  296. X.                    \" footnote won't fit completely
  297. X.                    \" invoke the footer trap but
  298. X.                    \" don't worry about the footnote
  299. X.                    \" separator (it's already there)
  300. X.        el .if (\\n(nlu+1v)>=(\\n(.pu+\\n(fpu) \{\
  301. X.                    \" as before we must reposition the
  302. X.                    \" "fo" trap to prevent "fo" from
  303. X.                    \" being invoked twice
  304. X.            ch fo \\n(.pu+1i
  305. X.            fo        \" force the page out AT ONCE
  306. X.        \}
  307. X.    \}
  308. X.\}
  309. X..
  310. X.de fs                    \" drop footnote separator
  311. X.                    \" only if not already dropped
  312. X.if \\n(ns=0 \l'1i'
  313. X.nr ns 0                \" in case footnotes are over 1 page long
  314. X..
  315. X.de fx                    \" process footnote overflow
  316. X.if \\n(fc .di fy            \" stuff them in the right place
  317. X..
  318. X.de fz                    \" deposit footnote overflow
  319. X.fn                    \" treat it as a footnote
  320. X.nf                    \" it's already been processed
  321. X.in 0                    \"   and indented
  322. X.fy                    \" "fx" put it here
  323. X.ef                    \" end the footnote
  324. X..
  325. X.\" **********
  326. X.\" the ones after here are user-invoked (like "fn" and "ef" above)
  327. X.\" title, author, etc.
  328. X.de mt                    \" main title
  329. X\&
  330. X.sp |\\n(mtu                \" space
  331. X.ft 3                    \" in bold
  332. X.ps \\n(ps+2p                \" large point size and
  333. X.vs \\n(vs+2p                \" vertical spacing
  334. X.ce 1000                \" center the title
  335. X.nr t2 1                \" space it
  336. X..
  337. X.de au                    \" author
  338. X.nr t2 0                \" spacing here
  339. X.sp 2v                    \" space
  340. X.ft 2                    \" in italics
  341. X.ps \\n(ps                \" usual point size and
  342. X.vs \\n(vs                \" vertical spacing
  343. X.ce 1000                \" center the name(s)
  344. X..
  345. X.de ai                    \" author's institution
  346. X.if \\n(t2 .sp 2v            \" space after a title
  347. X.nr t2 0                \" institution
  348. X.ft 2                    \" in italics
  349. X.ps \\n(ps                \" usual point size and
  350. X.vs \\n(vs                \" vertical spacing
  351. X.ce 1000                \" center the name(s)
  352. X..
  353. X.de bt                    \" begin text macro
  354. X.nr t2 0                \" hold it here
  355. X.nr it +1                \" mark as called
  356. X.ce 0                    \" end any centering
  357. X.sn 3v                    \" a little bit of space
  358. X..
  359. X.\" paragraph
  360. X.de si                    \" start indented section
  361. X.nr lo \\n(lm                \" remember the current level
  362. X.nr lm +1                \" go to the next level
  363. X.ie '\\$1'' .nr l\\n(lm \\n(l\\n(lo+5n    \" if no arg, indent 5n
  364. X.el         .nr l\\n(lm \\$1n        \" otherwise, indent that much
  365. X..
  366. X.de ei                    \" end indent
  367. X.nr lm -1                \" down one level
  368. X.if \\n(lm<0 .nr lm 0            \" make sure you don't go too far
  369. X..
  370. X.de pg                    \" plain old paragraph
  371. X.if !\\n(it .bt                \" end the title and such
  372. X.sn \\n(pdu                \" inter-paragraph spacing
  373. X.ft 1                    \" reset a few things (paranoia)
  374. X.                    \" these ONLY if not in footnote
  375. X.ie \\n(if=0 \{\
  376. X.    ps \\n(ps            \" reset point size
  377. X.    vs \\n(vs            \" reset vertical spacing
  378. X.    ne 1v+\\n(.Vu            \" slightly more than 1 line
  379. X.\}
  380. X.el \{\
  381. X.    ps \\n(ps-2p            \" reset point size
  382. X.    vs \\n(vs-2p            \" reset vertical spacing
  383. X.\}
  384. X.in \\n(l\\n(lmu            \" stop any indenting
  385. X.ce 0                    \" stop any centering
  386. X.if !'\\$1'L' .if !'\\$1'l' .ti +\\n(piu    \" indent the sucker
  387. X..
  388. X.de lp                    \" labelled paragraph
  389. X.pg l                    \" reset paragraph
  390. X.if \\n(.$>1 .nr li \\$2n        \" if indent given use it
  391. X.in +\\n(liu                \" indent for paragraph
  392. X.ti -\\n(liu                \" force first line NOT to indent
  393. X.ta +\\n(liu                \" for the label
  394. X\&\\$1\t\c
  395. X.if \\w'\\$1'u>=(\\n(l\\n(lmu+\\n(liu) .br    \" don't overwrite
  396. X..
  397. X.\" The following two macros (hu & hn) have been modified for ELM usage.
  398. X.\" If the macros have text as part of the macro call, the text will be
  399. X.\" increased in size by two points.  After printing the text, the font
  400. X.\" will be returned to normal, otherwise the font will be left bold.
  401. X.\"
  402. X.\" section
  403. X.de hu                    \" header, unnumbered
  404. X.                    \" format: .hu [text]
  405. X.if !\\n(it .bt                \" end the title and such
  406. X.br                    \" force out previous line
  407. X.b
  408. X.ie \\n(hP .ps \\n(hP
  409. X.el        .ps \\n(ps
  410. X.ie \\n(hv .vs \\n(hv
  411. X.el        .vs \\n(vs
  412. X.in \\n(l\\n(lmu            \" stop any indenting
  413. X.sn \\n(hsu                \" inter-section spacing
  414. X.ne 3v+\\n(.Vu                \" slightly more than 3 lines
  415. X.fi                    \" process the text, too
  416. X.if \\n(.$>=1 \{\
  417. X.ps +2
  418. X\\$1
  419. X.\}
  420. X.if \\n(.$>=2 \\$2
  421. X.if \\n(.$>=3 \\$3
  422. X.if \\n(.$>=4 \\$4
  423. X.if \\n(.$>=5 \\$5
  424. X.if \\n(.$>=6 \\$6
  425. X.if \\n(.$>=7 \\$7
  426. X.if \\n(.$>=8 \\$8
  427. X.if \\n(.$=9 \\$9
  428. X.if \\n(.$>=1 \{\
  429. X.ps -2
  430. X.br
  431. X.ft 1
  432. X.\}
  433. X..
  434. X.de hn                    \" header, numbered
  435. X.                    \" format: .hn [level] [text]
  436. X.if !\\n(it .bt                \" end the title and such
  437. X.br                    \" force out previous line
  438. X.b
  439. X.ie \\n(hP .ps \\n(hP
  440. X.el        .ps \\n(ps
  441. X.ie \\n(hv .vs \\n(hv
  442. X.el        .vs \\n(vs
  443. X.in \\n(l\\n(lmu            \" stop any indenting
  444. X.sn \\n(hsu                \" inter-section spacing
  445. X.ne 3v+\\n(.Vu                \" slightly more than 3 lines
  446. X.fi                    \" process the text, too
  447. X.ie !'\\$1'' .nr hn \\$1
  448. X.el          .nr hn 1
  449. X.ie \\n(hn>0 .nr hn -1
  450. X.el          .nr hn 0
  451. X.ie \\n(hn=0 \{\
  452. X.    nr h0 +1            \" add 1 to main section header
  453. X.    nr h1 0                \" zap remaining section numbers
  454. X.    nr h2 0                \" zap remaining section numbers
  455. X.    nr h3 0                \" zap remaining section numbers
  456. X.ie \\n(.$>=2 \{\
  457. X.ps +2
  458. X\\n(h0.
  459. X.ps -2
  460. X.\}
  461. X.el \\n(h0.
  462. X.\}
  463. X.el .ie \\n(hn=1 \{\
  464. X.    nr h1 +1            \" add 1 to the section header
  465. X.    nr h2 0                \" zap remaining section numbers
  466. X.    nr h3 0                \" zap remaining section numbers
  467. X.ie \\n(.$>=2 \{\
  468. X.ps +2
  469. X\\n(h0.\\n(h1.
  470. X.ps -2
  471. X.\}
  472. X.el \\n(h0.\\n(h1.
  473. X.\}
  474. X.el .ie \\n(hn=2 \{\
  475. X.    nr h2 +1            \" add 1 to the section header
  476. X.    nr h3 0                \" zap remaining section numbers
  477. X.ie \\n(.$>=2 \{\
  478. X.ps +2
  479. X\\n(h0.\\n(h1.\\n(h2.
  480. X.ps -2
  481. X.\}
  482. X.el \\n(h0.\\n(h1.\\n(h2.
  483. X.\}
  484. X.el \{\
  485. X.    nr h3 +1            \" add 1 to the section number
  486. X.ie \\n(.$>=2 \{\
  487. X.ps +2
  488. X\\n(h0.\\n(h1.\\n(h2.\\n(h3.
  489. X.ps -2
  490. X.\}
  491. X.el \\n(h0.\\n(h1.\\n(h2.\\n(h3.
  492. X.\}
  493. X.if \\n(.$>=2 \{\
  494. X.ps +2
  495. X\\$2
  496. X.\}
  497. X.if \\n(.$>=3 \\$3
  498. X.if \\n(.$>=4 \\$4
  499. X.if \\n(.$>=5 \\$5
  500. X.if \\n(.$>=6 \\$6
  501. X.if \\n(.$>=7 \\$7
  502. X.if \\n(.$>=8 \\$8
  503. X.if \\n(.$>=9 \\$9
  504. X.if \\n(.$>=2 \{\
  505. X.br
  506. X.ft 1
  507. X.ps -2
  508. X.\}
  509. X..
  510. X.\" displays (no floats, thank God!)
  511. X.de sd                    \" start display
  512. X.                    \" look for nested displays -- ILLEGAL
  513. X.ie \\n(id>0 .er "display within display"
  514. X.el \{\
  515. X.    ie '\\$1'c' .nr sf 1        \" center the sucker
  516. X.    el          .nr sf 0        \" don't center it
  517. X.\}
  518. X.sn \\n(pdu                \" a little bit of space
  519. X.ev 2                    \" switch to display environment
  520. X.nf                    \" what you type is what you get
  521. X.if \\n(id=0 .di dd            \" start saving text
  522. X.rs                    \" don't eat leading space
  523. X.nr id +1                \" increment level of display
  524. X..
  525. X.de ed                    \" end display
  526. X.br                    \" flush line
  527. X.ie \\n(id<=0 .er "end display has no corresponding begin display"
  528. X.el \{\
  529. X.    nr id -1            \" decrement level of display
  530. X.    if \\n(id=0 \{\
  531. X.        di            \" end diversion
  532. X.        fi            \" resume filling
  533. X.        in -\\n(piu        \" dedent
  534. X.        ev            \" pop environment
  535. X.        ne \\n(dnu        \" be sure you have room
  536. X.        nf            \" don't reprocess display
  537. X.        rs            \" don't eat leading space
  538. X.        zi            \" save indents
  539. X.        ie \\n(sf .in (\\n(llu-\\n(dlu)/2u    \" center on the line length
  540. X.        el .in +\\n(piu        \" indent the sucker
  541. X.        dd            \" drop display
  542. X.        yi            \" restore indents
  543. X.    \}
  544. X.\}
  545. X.fi                    \" resume filling
  546. X.sn \\n(pdu                \" a little bit of space
  547. X..
  548. X.\" **********
  549. X.\" fonts -- if argument(s), apply only to first
  550. X.de b                    \" bold (font 3)
  551. X.ie \\n(.$>0 \\&\\$3\\f3\\$1\\fP\\$2
  552. X.el .ft 3
  553. X..
  554. X.de i                    \" italics (font 2)
  555. X.ie \\n(.$>0 \\&\\$3\\f2\\$1\\fP\\$2
  556. X.el .ft 2
  557. X..
  558. X.de r                    \" roman (font 1)
  559. X.ft 1                    \" just restore it
  560. X..
  561. X.de bi                    \" bold italics (embolden font 2)
  562. X\\&\\$3\c
  563. X\\kb\\f2\\$1\\fP\\h'|\\nbu+2u'\\f2\\$1\\fP\\$2
  564. X..
  565. X.\" **********
  566. X.\" point sizes -- if argument(s), apply only to first
  567. X.de sm                    \" reduce point size by 2
  568. X.ie \\n(.$>0 \\&\\$3\\s-2\\$1\\s0\\$2
  569. X.el .ps -2
  570. X..
  571. X.de is                    \" increase point size by 2
  572. X.ie \\n(.$>0 \\&\\$3\\s+2\\$1\\s0\\$2
  573. X.el .ps +2
  574. X..
  575. X.de nl                    \" return to normal size
  576. X.ps \\n(ps                \" just reset the point size
  577. X..
  578. X.\" **********
  579. X.\" handy force space/inhibit more space macros
  580. X.de sn                    \" space, then turn on nospace mode
  581. X.sp \\$1                \" space
  582. X.ns                    \" ignore any more space requests
  583. X..
  584. X.de sr                    \" force out space
  585. X.rs                    \" turn on spacing mode
  586. X.sp \\$1                \" space
  587. X..
  588. X.\" **********
  589. X.\" end of text and error macros
  590. X.de et                    \" end of text macro
  591. X.                    \" this: (1) flushes rest of line
  592. X.                    \" (2) trips the footer, taking
  593. X.                    \" care of footnotes
  594. X.sp \\n(.pu
  595. X.                    \" check for open displays or footnotes
  596. X.if \\n(id>0 .er "unfinished display"
  597. X.if \\n(if>0 .er "unfinished footnote"
  598. X.                    \" this one means an -mn bug (*sigh*)
  599. X.if !'\\n(.z'' .er "diversion \\n(.z not closed"
  600. X..
  601. X.de er                    \" print error message
  602. X.                    \" flag it as an error
  603. X.ds ws "** ERROR **
  604. X.                    \" if you have it, give the file name
  605. X.if !'\\*(.f'' .as ws " file \\*(.f,
  606. X.                    \" put out the line number
  607. X.as ws " line \\n(.c
  608. X.                    \" and finally the error message
  609. X.tm \\*(ws: \\$1
  610. X..
  611. X.\" **********
  612. X.\" macros in this section are VERY specific to the news documentation
  613. X.de pa                    \" protocol appellation (darn names!)
  614. X\\&\\$3\\f2\\$1\\fP\\$2
  615. X..
  616. X.de ng                    \" news group name
  617. X\\&\\$3\\f3\\$1\\fP\\$2
  618. X..
  619. X.de cn                    \" computer name
  620. X\\&\\$3\\f2\\$1\\fP\\$2
  621. X..
  622. X.de hf                    \" header field
  623. X\\&\\$3\\*(lq\\$1\\*(rq\\$2
  624. X..
  625. X.de cf                    \" contents of field
  626. X\\&\\$3\\*(lq\\$1\\*(rq\\$2
  627. X..
  628. X.de qc                    \" quote control char (command)
  629. X\\&\\$3\\f3<\\s-2\\$1\\s0>\\fP\\$2
  630. X..
  631. X.de qp                    \" quote printing char (command)
  632. X\\&\\$3\\f3\\$1\\fP\\$2
  633. X..
  634. X.de op                    \" option
  635. X\\&\\$3\\f3\\$1\\fP\\$2
  636. X..
  637. X.\" **********
  638. X.\" trademarked names
  639. X.de pd                    \" print "PDP-11"
  640. X.ie \\n(p1 \\&\\$2\\s-1PDP\\s0-11\\$1
  641. X.el \{\
  642. X.    nr p1 +1            \" mark footnote as dropped
  643. X\\&\\$2\\s-1PDP\\s0-11\\*(rg\\$1
  644. X.    fn                \" put out the footnote
  645. X\\&\\*(rgPDP-11 is a registered trademark of Digital Equipment Corporation.
  646. X.    ef                \" short and sweet ...
  647. X.\}
  648. X..
  649. X.de ux                    \" print "UNIX"
  650. X.ie \\n(ux \\&\\$2\\s-1UNIX\\s0\\$1
  651. X.el \{\
  652. X.    nr ux +1            \" mark footnote as dropped
  653. X\\&\\$2\\s-1UNIX\\s0\\*(rg\\$1
  654. X.    fn                \" put out the footnote
  655. X\\&\\*(rgUNIX is a registered trademark of AT&T.
  656. X.    ef                \" short and sweet ...
  657. X.\}
  658. X..
  659. X.de vx                    \" print "VAX"
  660. X.ie \\n(vx \\&\\$2\\s-1VAX\\s0\\$1
  661. X.el \{\
  662. X.    nr vx +1            \" mark footnote as dropped
  663. X\\&\\$2\\s-1VAX\\s0\\*(rg\\$1
  664. X.    fn                \" put out the footnote
  665. X\\&\\*(rgVAX is a trademark of Digital Equipment Corporation.
  666. X.    ef                \" short and sweet ...
  667. X.\}
  668. X..
  669. X.\" **********
  670. X.\" set up string and number registers
  671. X.                    \" set up for the date
  672. X.if \n(mo=1  .ds mo January
  673. X.if \n(mo=2  .ds mo February
  674. X.if \n(mo=3  .ds mo March
  675. X.if \n(mo=4  .ds mo April
  676. X.if \n(mo=5  .ds mo May
  677. X.if \n(mo=6  .ds mo June
  678. X.if \n(mo=7  .ds mo July
  679. X.if \n(mo=8  .ds mo August
  680. X.if \n(mo=9  .ds mo September
  681. X.if \n(mo=10 .ds mo October
  682. X.if \n(mo=11 .ds mo November
  683. X.if \n(mo=12 .ds mo December
  684. X.ds dy "\*(mo \n(dy, 19\n(yr
  685. X.if \n(dw=1  .ds dw Sunday
  686. X.if \n(dw=2  .ds dw Monday
  687. X.if \n(dw=3  .ds dw Tuesday
  688. X.if \n(dw=4  .ds dw Wednesday
  689. X.if \n(dw=5  .ds dw Thursday
  690. X.if \n(dw=6  .ds dw Friday
  691. X.if \n(dw=7  .ds dw Saturday
  692. X.                    \" NROFF dependencies
  693. X.if n \{\
  694. X.                    \" string registers
  695. X.    ds rg (R)
  696. X.    ds lq ""
  697. X.    ds rq ""
  698. X.    ds f1 "\*(dy
  699. X.                    \" number registers
  700. X.    nr hs 1v            \" space before section header
  701. X.    nr pd 1v            \" inter-paragraph spacing
  702. X.    nr bm 1.0i            \" height of bottom margin
  703. X.\}
  704. X.                    \" NROFF dependencies
  705. X.if t \{\
  706. X.                    \" string registers
  707. X.    ds rg \\u\\s-2\\(rg\\s0\\d
  708. X.    ds lq ``
  709. X.    ds rq ''
  710. X.                    \" number registers
  711. X.    nr hs 1v            \" space before section header
  712. X.    nr pd 0.3v            \" inter-paragraph spacing
  713. X.    nr bm 1.0i+1v            \" height of bottom margin (wacky laser)
  714. X.\}
  715. X.                    \" these are the same for [NT]ROFF
  716. X.ds dg \(dg
  717. X.ds vr "News Version B2.11
  718. X.ds pv "News macros 1.5
  719. X.ds h1 - % -
  720. X.nr bt 0.5i+1v                \" bottom of page to footer
  721. X.nr cm 0                \" no cut marks
  722. X.nr fc 0 1                \" init footnote count
  723. X.nr fl 5.5i                \" footnote line length
  724. X.nr fp 0-\n(bmu                \" fo macro trap location
  725. X.nr h0 0                \" init section header level 0
  726. X.nr h1 0                \" init section header level 1
  727. X.nr h2 0                \" init section header level 2
  728. X.nr h3 0                \" init section header level 3
  729. X.nr id 0                \" 1 in display
  730. X.nr if 0                \" 1 in keep
  731. X.nr it 0                \" 1 when beyond title, etc.
  732. X.nr li 5n                \" indent for labelled paragraph
  733. X.nr ll 6.5i                \" line length
  734. X.nr lm 0                \" left margin
  735. X.nr l0 0                \" first indent level
  736. X.nr mt 1.5i+1v                \" title goes down this far
  737. X.nr pi 5n                \" regular paragraph indent
  738. X.nr po 1.0i                \" page offset
  739. X.nr ps 10                \" point size
  740. X.nr tm 1.0i                \" height of top margin
  741. X.nr tt 0.5i-0.5v            \" top of page to header
  742. X.nr p1 0                \" no PDP-TM message yet
  743. X.nr ux 0                \" no UNIX-TM message yet
  744. X.nr vx 0                \" no VAX-TM message yet
  745. X.nr vs 12                \" vertical spacing
  746. X.\" set things up
  747. X.\" DSINC changes for XROFF
  748. X.nr f1 1
  749. X.nr f2 1
  750. X.nr s1 10
  751. X.nr s2 10
  752. X.nr v1 12
  753. X.nr v2 12
  754. X.ps 10
  755. X.vs 12
  756. X.\" DSINC end changes for XROFF
  757. X.po \n(pou                \" set page offset
  758. X.ps \n(ps                \" set previous, current
  759. X.ps \n(ps                \"   point sizes
  760. X.vs \n(vs                \" set previous, current
  761. X.vs \n(vs                \"   vertical spacings
  762. X.ll \n(llu                \" set line length
  763. X.lt \n(llu                \" set title line length
  764. X.ev 1                    \" *** footnote environment
  765. X.ps \n(ps-2p                \" set previous, current
  766. X.ps \n(ps-2p                \"   point sizes
  767. X.vs \n(vs-2p                \" set previous, current
  768. X.vs \n(vs-2p                \"   vertical spacings
  769. X.ll \n(flu                \" set line length
  770. X.lt \n(flu                \" set title line length
  771. X.ev                    \" *** pop environment
  772. X.ev 2                    \" *** footnote environment
  773. X.ps \n(ps                \" set previous, current
  774. X.ps \n(ps                \"   point sizes
  775. X.vs \n(vs                \" set previous, current
  776. X.vs \n(vs                \"   vertical spacings
  777. X.ll \n(llu                \" set line length
  778. X.lt \n(llu                \" set title line length
  779. X.ev                    \" *** pop environment
  780. X.\" now set internal registers (for the first header section)
  781. X.nr f1 \n(.f                \" saved font #1
  782. X.nr f2 \n(.f                \" saved font #2
  783. X.nr s1 \n(.s                \" saved point size #1
  784. X.nr s2 \n(.s                \" saved point size #2
  785. X.nr v1 \n(.v                \" saved vertical spacing #1
  786. X.nr v2 \n(.v                \" saved vertical spacing #2
  787. X.\" install traps
  788. X.wh 0i hd                \" position header trap
  789. X.wh -\n(bmu fo                \" position footer trap
  790. X.wh \n(.pu+1i fx            \" put footnote overflow trap here
  791. X.ch fx -\n(bmu                \" move it over fo
  792. X.wh -\n(btu pf                \" print the bottom margin here
  793. X.em et                    \" at end of file, call et
  794. X.\" couple of miscellaneous requests
  795. X.bd S 3 3                \" embolden special font chars if B
  796. X.hy 2                    \" don't hyphenate last lines
  797. X
  798. END_OF_FILE
  799. if test 25079 -ne `wc -c <'doc/tmac.n'`; then
  800.     echo shar: \"'doc/tmac.n'\" unpacked with wrong size!
  801. fi
  802. # end of 'doc/tmac.n'
  803. fi
  804. if test -f 'src/mkmaze.c' -a "${1}" != "-c" ; then 
  805.   echo shar: Will not clobber existing file \"'src/mkmaze.c'\"
  806. else
  807. echo shar: Extracting \"'src/mkmaze.c'\" \(29353 characters\)
  808. sed "s/^X//" >'src/mkmaze.c' <<'END_OF_FILE'
  809. X/*    SCCS Id: @(#)mkmaze.c    3.1    93/01/17    */
  810. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  811. X/* NetHack may be freely redistributed.  See license for details. */
  812. X
  813. X#include "hack.h"
  814. X#include "sp_lev.h"
  815. X
  816. X#define    UP    1
  817. X#define DOWN    0
  818. X
  819. X/* from sp_lev.c, for fixup_special() */
  820. Xextern char *lev_message;
  821. Xextern lev_region *lregions;
  822. Xextern int num_lregions;
  823. X
  824. Xstatic int FDECL(iswall,(int,int));
  825. Xstatic boolean FDECL(okay,(int,int,int));
  826. Xstatic void FDECL(maze0xy,(coord *));
  827. Xstatic boolean FDECL(put_lregion_here,(XCHAR_P,XCHAR_P,XCHAR_P,
  828. X    XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P,BOOLEAN_P,d_level *));
  829. Xstatic void NDECL(fixup_special);
  830. Xstatic void NDECL(setup_waterlevel);
  831. Xstatic void NDECL(unsetup_waterlevel);
  832. X
  833. Xstatic int
  834. Xiswall(x,y)
  835. Xint x,y;
  836. X{
  837. X    if (x<=0 || y<0 || x>COLNO-1 || y>ROWNO-1)
  838. X        return 0;
  839. X    return (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)
  840. X        || levl[x][y].typ == SDOOR);
  841. X}
  842. X
  843. Xvoid
  844. Xwallification(x1, y1, x2, y2)
  845. Xint x1, y1, x2, y2;
  846. X{
  847. X    uchar type;
  848. X    short x,y;
  849. X    register struct rm *lev;
  850. X
  851. X    if (x1 < 0) x1 = 0;
  852. X    if (x2 < x1) x2 = x1;
  853. X    if (x2 > COLNO-1) x2 = COLNO-1;
  854. X    if (x1 > x2) x1 = x2;
  855. X    if (y1 < 0) y1 = 0;
  856. X    if (y2 < y1) y2 = y1;
  857. X    if (y2 > ROWNO-1) y2 = ROWNO-1;
  858. X    if (y1 > y2) y1 = y2;
  859. X    for(x = x1; x <= x2; x++)
  860. X        for(y = y1; y <= y2; y++) {
  861. X        lev = &levl[x][y];
  862. X        type = lev->typ;
  863. X        if (iswall(x,y)) {
  864. X          if (IS_DOOR(type) || type == SDOOR || type == DBWALL)
  865. X            continue;
  866. X          else
  867. X            if (iswall(x,y-1))
  868. X            if (iswall(x,y+1))
  869. X                if (iswall(x-1,y))
  870. X                if (iswall(x+1,y))
  871. X                    lev->typ = CROSSWALL;
  872. X                else
  873. X                    lev->typ = TLWALL;
  874. X                else
  875. X                if (iswall(x+1,y))
  876. X                    lev->typ = TRWALL;
  877. X                else
  878. X                    lev->typ = VWALL;
  879. X            else
  880. X                if (iswall(x-1,y))
  881. X                if (iswall(x+1,y))
  882. X                    lev->typ = TUWALL;
  883. X                else
  884. X                    lev->typ = BRCORNER;
  885. X                else
  886. X                if (iswall(x+1,y))
  887. X                    lev->typ = BLCORNER;
  888. X                else
  889. X                    lev->typ = VWALL;
  890. X            else
  891. X            if (iswall(x,y+1))
  892. X                if (iswall(x-1,y))
  893. X                if (iswall(x+1,y))
  894. X                    lev->typ = TDWALL;
  895. X                else
  896. X                    lev->typ = TRCORNER;
  897. X                else
  898. X                if (iswall(x+1,y))
  899. X                    lev->typ = TLCORNER;
  900. X                else
  901. X                    lev->typ = VWALL;
  902. X            else
  903. X                lev->typ = HWALL;
  904. X        }
  905. X        }
  906. X}
  907. X
  908. Xstatic boolean
  909. Xokay(x,y,dir)
  910. Xint x,y;
  911. Xregister int dir;
  912. X{
  913. X    move(&x,&y,dir);
  914. X    move(&x,&y,dir);
  915. X    if(x<3 || y<3 || x>x_maze_max || y>y_maze_max || levl[x][y].typ != 0)
  916. X        return(FALSE);
  917. X    return(TRUE);
  918. X}
  919. X
  920. Xstatic void
  921. Xmaze0xy(cc)    /* find random starting point for maze generation */
  922. X    coord    *cc;
  923. X{
  924. X    cc->x = 3 + 2*rn2((x_maze_max>>1) - 1);
  925. X    cc->y = 3 + 2*rn2((y_maze_max>>1) - 1);
  926. X    return;
  927. X}
  928. X
  929. X/*
  930. X * Bad if:
  931. X *    pos is occupied OR
  932. X *    pos is inside restricted region (lx,ly,hx,hy) OR
  933. X *    NOT (pos is corridor and a maze level OR pos is a room OR pos is air)
  934. X */
  935. Xboolean
  936. Xbad_location(x, y, lx, ly, hx, hy)
  937. X    xchar x, y;
  938. X    xchar lx, ly, hx, hy;
  939. X{
  940. X    return(occupied(x, y) ||
  941. X       ((x >= lx) && (x <= hx) && (y >= ly) && (y <= hy)) ||
  942. X       !((levl[x][y].typ == CORR && level.flags.is_maze_lev) ||
  943. X           levl[x][y].typ == ROOM || levl[x][y].typ == AIR));
  944. X}
  945. X
  946. X/* pick a location in area (lx, ly, hx, hy) but not in (nlx, nly, nhx, nhy) */
  947. X/* and place something (based on rtype) in that region */
  948. Xvoid
  949. Xplace_lregion(lx, ly, hx, hy, nlx, nly, nhx, nhy, rtype, lev)
  950. X    xchar    lx, ly, hx, hy;
  951. X    xchar    nlx, nly, nhx, nhy;
  952. X    xchar    rtype;
  953. X    d_level    *lev;
  954. X{
  955. X    int trycnt;
  956. X    boolean oneshot;
  957. X    xchar x, y;
  958. X
  959. X    if(!lx) { /* default to whole level */
  960. X    /*
  961. X     * if there are rooms and this a branch, let place_branch choose
  962. X     * the branch location (to avoid putting branches in corridors).
  963. X     */
  964. X    if(rtype == LR_BRANCH && nroom) {
  965. X        place_branch(Is_branchlev(&u.uz), 0, 0);
  966. X        return;
  967. X    }
  968. X
  969. X    lx = 1; hx = COLNO-1;
  970. X    ly = 1; hy = ROWNO-1;
  971. X    }
  972. X
  973. X    /* first a probabilistic approach */
  974. X
  975. X    oneshot = (lx == hx && ly == hy);
  976. X    for(trycnt = 0; trycnt < 100; trycnt ++) {
  977. X
  978. X    x = rn1((hx - lx) + 1, lx);
  979. X    y = rn1((hy - ly) + 1, ly);
  980. X
  981. X    if (put_lregion_here(x,y,nlx,nly,nhx,nhy,rtype,oneshot,lev))
  982. X        return;
  983. X    }
  984. X
  985. X    /* then a deterministic one */
  986. X
  987. X    oneshot = TRUE;
  988. X    for (x = lx; x <= hx; x++)
  989. X    for (y = ly; y <= hy; y++)
  990. X        if (put_lregion_here(x,y,nlx,nly,nhx,nhy,rtype,oneshot,lev))
  991. X        return;
  992. X
  993. X    impossible("Couldn't place lregion type %d!", rtype);
  994. X}
  995. X
  996. Xstatic boolean
  997. Xput_lregion_here(x,y,nlx,nly,nhx,nhy,rtype,oneshot,lev)
  998. Xxchar x, y;
  999. Xxchar nlx, nly, nhx, nhy;
  1000. Xxchar rtype;
  1001. Xboolean oneshot;
  1002. Xd_level *lev;
  1003. X{
  1004. X    if(oneshot) {
  1005. X    /* must make due with the only location possible */
  1006. X    /* avoid failure due to a misplaced trap */
  1007. X    /* it might still fail if there's a dungeon feature here */
  1008. X    struct trap *t = t_at(x,y);
  1009. X    if (t) deltrap(t);
  1010. X    }
  1011. X    if(bad_location(x, y, nlx, nly, nhx, nhy)) return(FALSE);
  1012. X    switch (rtype) {
  1013. X    case LR_TELE:
  1014. X    case LR_UPTELE:
  1015. X    case LR_DOWNTELE:
  1016. X    /* "something" means the player in this case */
  1017. X    if(MON_AT(x, y)) {
  1018. X        /* move the monster if no choice, or just try again */
  1019. X        if(oneshot) rloc(m_at(x,y));
  1020. X        else return(FALSE);
  1021. X    }
  1022. X    u.ux = x; u.uy = y;
  1023. X    break;
  1024. X    case LR_PORTAL:
  1025. X    mkportal(x, y, lev->dnum, lev->dlevel);
  1026. X    break;
  1027. X    case LR_DOWNSTAIR:
  1028. X    case LR_UPSTAIR:
  1029. X    mkstairs(x, y, (char)rtype, (struct mkroom *)0);
  1030. X    break;
  1031. X    case LR_BRANCH:
  1032. X    place_branch(Is_branchlev(&u.uz), x, y);
  1033. X    break;
  1034. X    }
  1035. X    return(TRUE);
  1036. X}
  1037. X
  1038. Xstatic boolean was_waterlevel; /* ugh... this shouldn't be needed */
  1039. X
  1040. X/* this is special stuff that the level compiler cannot (yet) handle */
  1041. Xstatic void
  1042. Xfixup_special()
  1043. X{
  1044. X    register lev_region *r = lregions;
  1045. X    struct d_level lev;
  1046. X    register int x, y;
  1047. X    struct mkroom *croom;
  1048. X    boolean added_branch = FALSE;
  1049. X
  1050. X    if (was_waterlevel) {
  1051. X    was_waterlevel = FALSE;
  1052. X    u.uinwater = 0;
  1053. X    unsetup_waterlevel();
  1054. X    } else if (Is_waterlevel(&u.uz)) {
  1055. X    level.flags.hero_memory = 0;
  1056. X    was_waterlevel = TRUE;
  1057. X    /* water level is an odd beast - it has to be set up
  1058. X       before calling place_lregions etc. */
  1059. X    setup_waterlevel();
  1060. X    }
  1061. X    for(x = 0; x < num_lregions; x++, r++) {
  1062. X    switch(r->rtype) {
  1063. X    case LR_BRANCH:
  1064. X        added_branch = TRUE;
  1065. X        goto place_it;
  1066. X
  1067. X    case LR_PORTAL:
  1068. X        if(*r->rname >= '0' && *r->rname <= '9') {
  1069. X        /* "chutes and ladders" */
  1070. X        lev = u.uz;
  1071. X        lev.dlevel = atoi(r->rname);
  1072. X        } else
  1073. X        lev = find_level(r->rname)->dlevel;
  1074. X        /* fall into... */
  1075. X
  1076. X    case LR_UPSTAIR:
  1077. X    case LR_DOWNSTAIR:
  1078. X    place_it:
  1079. X        place_lregion(r->inarea.x1, r->inarea.y1,
  1080. X              r->inarea.x2, r->inarea.y2,
  1081. X              r->delarea.x1, r->delarea.y1,
  1082. X              r->delarea.x2, r->delarea.y2,
  1083. X              r->rtype, &lev);
  1084. X        break;
  1085. X
  1086. X    case LR_TELE:
  1087. X    case LR_UPTELE:
  1088. X    case LR_DOWNTELE:
  1089. X        /* save the region outlines for goto_level() */
  1090. X        if(r->rtype == LR_TELE || r->rtype == LR_UPTELE) {
  1091. X            updest.lx = r->inarea.x1; updest.ly = r->inarea.y1;
  1092. X            updest.hx = r->inarea.x2; updest.hy = r->inarea.y2;
  1093. X            updest.nlx = r->delarea.x1; updest.nly = r->delarea.y1;
  1094. X            updest.nhx = r->delarea.x2; updest.nhy = r->delarea.y2;
  1095. X        }
  1096. X        if(r->rtype == LR_TELE || r->rtype == LR_DOWNTELE) {
  1097. X            dndest.lx = r->inarea.x1; dndest.ly = r->inarea.y1;
  1098. X            dndest.hx = r->inarea.x2; dndest.hy = r->inarea.y2;
  1099. X            dndest.nlx = r->delarea.x1; dndest.nly = r->delarea.y1;
  1100. X            dndest.nhx = r->delarea.x2; dndest.nhy = r->delarea.y2;
  1101. X        }
  1102. X        /* place_lregion gets called from goto_level() */
  1103. X        break;
  1104. X    }
  1105. X    }
  1106. X
  1107. X    /* place dungeon branch if not placed above */
  1108. X    if (!added_branch && Is_branchlev(&u.uz)) {
  1109. X    place_lregion(0,0,0,0,0,0,0,0,LR_BRANCH,(d_level *)0);
  1110. X    }
  1111. X
  1112. X    /* Still need to add some stuff to level file */
  1113. X    if (Is_medusa_level(&u.uz)) {
  1114. X    struct obj *otmp;
  1115. X    int tryct;
  1116. X
  1117. X    croom = &rooms[0]; /* only one room on the medusa level */
  1118. X    for (tryct = rn1(1,3); tryct; tryct--) {
  1119. X        x = somex(croom); y = somey(croom);
  1120. X        if (goodpos(x, y, (struct monst *)0, (struct permonst *)0)) {
  1121. X        otmp = mk_tt_object(STATUE, x, y);
  1122. X        while (otmp && (poly_when_stoned(&mons[otmp->corpsenm]) ||
  1123. X                resists_ston(&mons[otmp->corpsenm]))) {
  1124. X            otmp->corpsenm = rndmonnum();
  1125. X            otmp->owt = weight(otmp);
  1126. X        }
  1127. X        }
  1128. X    }
  1129. X
  1130. X    if (rn2(2))
  1131. X        otmp = mk_tt_object(STATUE, somex(croom), somey(croom));
  1132. X    else /* Medusa statues don't contain books */
  1133. X        otmp = mkcorpstat(STATUE, (struct permonst *)0,
  1134. X                  somex(croom), somey(croom), FALSE);
  1135. X    if (otmp) {
  1136. X        while (resists_ston(&mons[otmp->corpsenm])
  1137. X           || poly_when_stoned(&mons[otmp->corpsenm])) {
  1138. X        otmp->corpsenm = rndmonnum();
  1139. X        otmp->owt = weight(otmp);
  1140. X        }
  1141. X    }
  1142. X    } else if(Is_wiz1_level(&u.uz)) {
  1143. X    croom = search_special(MORGUE);
  1144. X
  1145. X    create_secret_door(croom, W_SOUTH|W_EAST|W_WEST);
  1146. X#ifdef MULDGN
  1147. X    } else if(Is_knox(&u.uz)) {
  1148. X    /* using an unfilled morgue for rm id */
  1149. X    croom = search_special(MORGUE);
  1150. X    /* stock the main vault */
  1151. X    for(x = croom->lx; x <= croom->hx; x++)
  1152. X        for(y = croom->ly; y <= croom->hy; y++) {
  1153. X        mkgold((long) rn1(300, 600), x, y);
  1154. X        if(!rn2(3) && !is_pool(x,y)) (void)maketrap(x, y, LANDMINE);
  1155. X        }
  1156. X#endif
  1157. X    } else if(Is_sanctum(&u.uz)) {
  1158. X    croom = search_special(TEMPLE);
  1159. X
  1160. X    create_secret_door(croom, W_ANY);
  1161. X    } else if(on_level(&u.uz, &orcus_level)) {
  1162. X       register struct monst *mtmp, *mtmp2;
  1163. X
  1164. X       /* it's a ghost town, get rid of shopkeepers */
  1165. X        for(mtmp = fmon; mtmp; mtmp = mtmp2) {
  1166. X            mtmp2 = mtmp->nmon;
  1167. X            if(mtmp->isshk) mongone(mtmp);
  1168. X        }
  1169. X    }
  1170. X
  1171. X    if(lev_message) {
  1172. X    char *str, *nl;
  1173. X    for(str = lev_message; (nl = index(str, '\n')) != 0; str = nl+1) {
  1174. X        *nl = '\0';
  1175. X        pline("%s", str);
  1176. X    }
  1177. X    if(*str)
  1178. X        pline("%s", str);
  1179. X    free((genericptr_t)lev_message);
  1180. X    lev_message = 0;
  1181. X    }
  1182. X}
  1183. X
  1184. Xvoid
  1185. Xmakemaz(s)
  1186. Xregister const char *s;
  1187. X{
  1188. X    int x,y;
  1189. X    char protofile[20];
  1190. X    s_level    *sp = Is_special(&u.uz);
  1191. X    coord mm;
  1192. X
  1193. X    if(*s) {
  1194. X        if(sp && sp->rndlevs) Sprintf(protofile, "%s-%d", s,
  1195. X                        rnd((int) sp->rndlevs));
  1196. X        else         Strcpy(protofile, s);
  1197. X    } else if(*(dungeons[u.uz.dnum].proto)) {
  1198. X        if(dunlevs_in_dungeon(&u.uz) > 1) {
  1199. X        if(sp && sp->rndlevs)
  1200. X             Sprintf(protofile, "%s%d-%d", dungeons[u.uz.dnum].proto,
  1201. X                        dunlev(&u.uz),
  1202. X                        rnd((int) sp->rndlevs));
  1203. X        else Sprintf(protofile, "%s%d", dungeons[u.uz.dnum].proto,
  1204. X                        dunlev(&u.uz));
  1205. X        } else if(sp && sp->rndlevs) {
  1206. X             Sprintf(protofile, "%s-%d", dungeons[u.uz.dnum].proto,
  1207. X                        rnd((int) sp->rndlevs));
  1208. X        } else Strcpy(protofile, dungeons[u.uz.dnum].proto);
  1209. X
  1210. X    } else Strcpy(protofile, "");
  1211. X
  1212. X    if(*protofile) {
  1213. X        Strcat(protofile, LEV_EXT);
  1214. X        if(load_special(protofile)) {
  1215. X        fixup_special();
  1216. X        return;    /* no mazification right now */
  1217. X        }
  1218. X        impossible("Couldn't load '%s' - making a maze.", protofile);
  1219. X    }
  1220. X
  1221. X    level.flags.is_maze_lev = TRUE;
  1222. X
  1223. X#ifndef WALLIFIED_MAZE
  1224. X    for(x = 2; x < x_maze_max; x++)
  1225. X        for(y = 2; y < y_maze_max; y++)
  1226. X            levl[x][y].typ = STONE;
  1227. X#else
  1228. X    for(x = 2; x <= x_maze_max; x++)
  1229. X        for(y = 2; y <= y_maze_max; y++)
  1230. X            levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
  1231. X#endif
  1232. X
  1233. X    maze0xy(&mm);
  1234. X    walkfrom((int) mm.x, (int) mm.y);
  1235. X    /* put a boulder at the maze center */
  1236. X    (void) mksobj_at(BOULDER, (int) mm.x, (int) mm.y, TRUE);
  1237. X
  1238. X#ifdef WALLIFIED_MAZE
  1239. X    wallification(2, 2, x_maze_max, y_maze_max);
  1240. X#else
  1241. X    for(x = 2; x < x_maze_max; x++)
  1242. X        for(y = 2; y < y_maze_max; y++)
  1243. X            levl[x][y].seen = 1;    /* start out seen */
  1244. X#endif
  1245. X    if(Invocation_lev(&u.uz)) {
  1246. X        place_lregion(0,0,0,0, 30, 0, 46, ROWNO, UP, (d_level *)0);
  1247. X        do {
  1248. X            if(xupstair < 30)
  1249. X                x = rn1(COLNO-16-xupstair, xupstair+7);
  1250. X            else
  1251. X                x = rn1(xupstair-16, 9);
  1252. X            y = rn1(7, 8);
  1253. X        } while((levl[x][y].typ != CORR && levl[x][y].typ != ROOM)
  1254. X            || occupied(x,y));
  1255. X        inv_pos.x = x;
  1256. X        inv_pos.y = y;
  1257. X    } else {
  1258. X        /* no regular up stairs on the first level of a dungeon) */
  1259. X        if(u.uz.dlevel != 1) {
  1260. X        mazexy(&mm);
  1261. X        mkstairs(mm.x, mm.y, UP, (struct mkroom *)0);
  1262. X        }
  1263. X
  1264. X        /* no regular down stairs on the last level of a dungeon */
  1265. X        if(dunlev(&u.uz) != dunlevs_in_dungeon(&u.uz)) {
  1266. X        mazexy(&mm);
  1267. X        mkstairs(mm.x, mm.y, DOWN, (struct mkroom *)0);
  1268. X        }
  1269. X    }
  1270. X
  1271. X    /* place branch stair or portal */
  1272. X    place_branch(Is_branchlev(&u.uz), 0, 0);
  1273. X
  1274. X    for(x = rn1(8,11); x; x--) {
  1275. X        mazexy(&mm);
  1276. X        (void) mkobj_at(rn2(2) ? GEM_CLASS : 0, mm.x, mm.y, TRUE);
  1277. X    }
  1278. X    for(x = rn1(10,2); x; x--) {
  1279. X        mazexy(&mm);
  1280. X        (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE);
  1281. X    }
  1282. X    mazexy(&mm);
  1283. X    (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y);
  1284. X    for(x = rn1(5,7); x; x--) {
  1285. X        mazexy(&mm);
  1286. X        (void) makemon((struct permonst *) 0, mm.x, mm.y);
  1287. X    }
  1288. X    for(x = rn1(6,7); x; x--) {
  1289. X        mazexy(&mm);
  1290. X        mkgold(0L,mm.x,mm.y);
  1291. X    }
  1292. X    for(x = rn1(6,7); x; x--)
  1293. X        mktrap(0,1,(struct mkroom *) 0, (coord*) 0);
  1294. X}
  1295. X
  1296. X#ifdef MICRO
  1297. X/* Make the mazewalk iterative by faking a stack.  This is needed to
  1298. X * ensure the mazewalk is successful in the limited stack space of
  1299. X * the program.  This iterative version uses the minimum amount of stack
  1300. X * that is totally safe.
  1301. X */
  1302. Xvoid
  1303. Xwalkfrom(x,y)
  1304. Xint x,y;
  1305. X{
  1306. X#define CELLS (ROWNO * COLNO) / 4        /* a maze cell is 4 squares */
  1307. X    char mazex[CELLS + 1], mazey[CELLS + 1];    /* char's are OK */
  1308. X    int q, a, dir, pos;
  1309. X    int dirs[4];
  1310. X
  1311. X    pos = 1;
  1312. X    mazex[pos] = (char) x;
  1313. X    mazey[pos] = (char) y;
  1314. X    while (pos) {
  1315. X        x = (int) mazex[pos];
  1316. X        y = (int) mazey[pos];
  1317. X        if(!IS_DOOR(levl[x][y].typ)) {
  1318. X            /* might still be on edge of MAP, so don't overwrite */
  1319. X#ifndef WALLIFIED_MAZE
  1320. X            levl[x][y].typ = CORR;
  1321. X#else
  1322. X            levl[x][y].typ = ROOM;
  1323. X#endif
  1324. X            levl[x][y].flags = 0;
  1325. X        }
  1326. X        q = 0;
  1327. X        for (a = 0; a < 4; a++)
  1328. X            if(okay(x, y, a)) dirs[q++]= a;
  1329. X        if (!q)
  1330. X            pos--;
  1331. X        else {
  1332. X            dir = dirs[rn2(q)];
  1333. X            move(&x, &y, dir);
  1334. X#ifndef WALLIFIED_MAZE
  1335. X            levl[x][y].typ = CORR;
  1336. X#else
  1337. X            levl[x][y].typ = ROOM;
  1338. X#endif
  1339. X            move(&x, &y, dir);
  1340. X            pos++;
  1341. X            if (pos > CELLS)
  1342. X                panic("Overflow in walkfrom");
  1343. X            mazex[pos] = (char) x;
  1344. X            mazey[pos] = (char) y;
  1345. X        }
  1346. X    }
  1347. X}
  1348. X#else
  1349. X
  1350. Xvoid
  1351. Xwalkfrom(x,y)
  1352. Xint x,y;
  1353. X{
  1354. X    register int q,a,dir;
  1355. X    int dirs[4];
  1356. X
  1357. X    if(!IS_DOOR(levl[x][y].typ)) {
  1358. X        /* might still be on edge of MAP, so don't overwrite */
  1359. X#ifndef WALLIFIED_MAZE
  1360. X        levl[x][y].typ = CORR;
  1361. X#else
  1362. X        levl[x][y].typ = ROOM;
  1363. X#endif
  1364. X        levl[x][y].flags = 0;
  1365. X    }
  1366. X
  1367. X    while(1) {
  1368. X        q = 0;
  1369. X        for(a = 0; a < 4; a++)
  1370. X            if(okay(x,y,a)) dirs[q++]= a;
  1371. X        if(!q) return;
  1372. X        dir = dirs[rn2(q)];
  1373. X        move(&x,&y,dir);
  1374. X#ifndef WALLIFIED_MAZE
  1375. X        levl[x][y].typ = CORR;
  1376. X#else
  1377. X        levl[x][y].typ = ROOM;
  1378. X#endif
  1379. X        move(&x,&y,dir);
  1380. X        walkfrom(x,y);
  1381. X    }
  1382. X}
  1383. X#endif /* MICRO */
  1384. X
  1385. Xvoid
  1386. Xmove(x,y,dir)
  1387. Xregister int *x, *y;
  1388. Xregister int dir;
  1389. X{
  1390. X    switch(dir){
  1391. X        case 0: --(*y); break;
  1392. X        case 1: (*x)++; break;
  1393. X        case 2: (*y)++; break;
  1394. X        case 3: --(*x); break;
  1395. X    }
  1396. X}
  1397. X
  1398. Xvoid
  1399. Xmazexy(cc)    /* find random point in generated corridors,
  1400. X           so we don't create items in moats, bunkers, or walls */
  1401. X    coord    *cc;
  1402. X{
  1403. X    int cpt=0;
  1404. X
  1405. X    do {
  1406. X        cc->x = 3 + 2*rn2((x_maze_max>>1) - 1);
  1407. X        cc->y = 3 + 2*rn2((y_maze_max>>1) - 1);
  1408. X        cpt++;
  1409. X    } while (cpt < 100 && levl[cc->x][cc->y].typ !=
  1410. X#ifndef WALLIFIED_MAZE
  1411. X         CORR
  1412. X#else
  1413. X         ROOM
  1414. X#endif
  1415. X        );
  1416. X    if (cpt >= 100) {
  1417. X        register int x, y;
  1418. X        /* last try */
  1419. X        for (x = 0; x < (x_maze_max>>1) - 1; x++)
  1420. X            for (y = 0; y < (y_maze_max>>1) - 1; y++) {
  1421. X            cc->x = 3 + 2 * x;
  1422. X            cc->y = 3 + 2 * y;
  1423. X            if (levl[cc->x][cc->y].typ ==
  1424. X#ifndef WALLIFIED_MAZE
  1425. X                CORR
  1426. X#else
  1427. X                ROOM
  1428. X#endif
  1429. X               ) return;
  1430. X            }
  1431. X        panic("mazexy: can't find a place!");
  1432. X    }
  1433. X    return;
  1434. X}
  1435. X
  1436. Xvoid
  1437. Xbound_digging()
  1438. X/* put a non-diggable boundary around the initial portion of a level map.
  1439. X * assumes that no level will initially put things beyond the isok() range.
  1440. X *
  1441. X * we can't bound unconditionally on the last line with something in it,
  1442. X * because that something might be a niche which was already reachable,
  1443. X * so the boundary would be breached
  1444. X *
  1445. X * we can't bound unconditionally on one beyond the last line, because
  1446. X * that provides a window of abuse for WALLIFIED_MAZE special levels
  1447. X */
  1448. X{
  1449. X    register int x,y;
  1450. X    register unsigned typ;
  1451. X    register struct rm *lev;
  1452. X    boolean found, nonwall;
  1453. X    int xmin,xmax,ymin,ymax;
  1454. X
  1455. X    if(Is_earthlevel(&u.uz)) return; /* everything diggable here */
  1456. X
  1457. X    found = nonwall = FALSE;
  1458. X    for(xmin=0; !found; xmin++) {
  1459. X        lev = &levl[xmin][0];
  1460. X        for(y=0; y<=ROWNO-1; y++, lev++) {
  1461. X            typ = lev->typ;
  1462. X            if(typ != STONE) {
  1463. X                found = TRUE;
  1464. X                if(!IS_WALL(typ)) nonwall = TRUE;
  1465. X            }
  1466. X        }
  1467. X    }
  1468. X    xmin -= (nonwall || !level.flags.is_maze_lev) ? 2 : 1;
  1469. X    if (xmin < 0) xmin = 0;
  1470. X
  1471. X    found = nonwall = FALSE;
  1472. X    for(xmax=COLNO-1; !found; xmax--) {
  1473. X        lev = &levl[xmax][0];
  1474. X        for(y=0; y<=ROWNO-1; y++, lev++) {
  1475. X            typ = lev->typ;
  1476. X            if(typ != STONE) {
  1477. X                found = TRUE;
  1478. X                if(!IS_WALL(typ)) nonwall = TRUE;
  1479. X            }
  1480. X        }
  1481. X    }
  1482. X    xmax += (nonwall || !level.flags.is_maze_lev) ? 2 : 1;
  1483. X    if (xmax >= COLNO) xmax = COLNO-1;
  1484. X
  1485. X    found = nonwall = FALSE;
  1486. X    for(ymin=0; !found; ymin++) {
  1487. X        lev = &levl[xmin][ymin];
  1488. X        for(x=xmin; x<=xmax; x++, lev += ROWNO) {
  1489. X            typ = lev->typ;
  1490. X            if(typ != STONE) {
  1491. X                found = TRUE;
  1492. X                if(!IS_WALL(typ)) nonwall = TRUE;
  1493. X            }
  1494. X        }
  1495. X    }
  1496. X    ymin -= (nonwall || !level.flags.is_maze_lev) ? 2 : 1;
  1497. X
  1498. X    found = nonwall = FALSE;
  1499. X    for(ymax=ROWNO-1; !found; ymax--) {
  1500. X        lev = &levl[xmin][ymax];
  1501. X        for(x=xmin; x<=xmax; x++, lev += ROWNO) {
  1502. X            typ = lev->typ;
  1503. X            if(typ != STONE) {
  1504. X                found = TRUE;
  1505. X                if(!IS_WALL(typ)) nonwall = TRUE;
  1506. X            }
  1507. X        }
  1508. X    }
  1509. X    ymax += (nonwall || !level.flags.is_maze_lev) ? 2 : 1;
  1510. X
  1511. X    if(ymin >= 0)
  1512. X        for(x=xmin; x<=xmax; x++) levl[x][ymin].diggable = W_NONDIGGABLE;
  1513. X    if(ymax < ROWNO)
  1514. X        for(x=xmin; x<=xmax; x++) levl[x][ymax].diggable = W_NONDIGGABLE;
  1515. X
  1516. X    /* Don't bound these until _after_ the previous loops to avoid "ice" */
  1517. X    /* Normal rooms become ice by setting W_NONDIGGABLE -dlc */
  1518. X    if (ymin < 0) ymin = 0;
  1519. X    if (ymax >= ROWNO) ymax = ROWNO-1;
  1520. X
  1521. X    for(y=ymin; y<=ymax; y++) {
  1522. X        levl[xmin][y].diggable = W_NONDIGGABLE;
  1523. X        levl[xmax][y].diggable = W_NONDIGGABLE;
  1524. X    }
  1525. X}
  1526. X
  1527. Xvoid
  1528. Xmkportal(x, y, todnum, todlevel)
  1529. Xregister xchar x, y, todnum, todlevel;
  1530. X{
  1531. X    /* a portal "trap" must be matched by a */
  1532. X    /* portal in the destination dungeon/dlevel */
  1533. X    register struct trap *ttmp = maketrap(x, y, MAGIC_PORTAL);
  1534. X
  1535. X#ifdef DEBUG
  1536. X    pline("mkportal: at (%d,%d), to %s, level %d",
  1537. X        x, y, dungeons[todnum].dname, todlevel);
  1538. X#endif
  1539. X    ttmp->dst.dnum = todnum;
  1540. X    ttmp->dst.dlevel = todlevel;
  1541. X    return;
  1542. X}
  1543. X
  1544. X/*
  1545. X * Special waterlevel stuff in endgame (TH).
  1546. X *
  1547. X * Some of these functions would probably logically belong to some
  1548. X * other source files, but they are all so nicely encapsulated here.
  1549. X */
  1550. X
  1551. X/* to ease the work of debuggers at this stage */
  1552. X#define register
  1553. X
  1554. Xstruct container {
  1555. X    struct container *next;
  1556. X    xchar x, y;
  1557. X    short what;
  1558. X    genericptr_t list;
  1559. X};
  1560. X#define CONS_OBJ   0
  1561. X#define CONS_MON   1
  1562. X#define CONS_HERO  2
  1563. X#define CONS_TRAP  3
  1564. X
  1565. Xstatic struct bubble {
  1566. X    xchar x, y;    /* coordinates of the upper left corner */
  1567. X    schar dx, dy;    /* the general direction of the bubble's movement */
  1568. X    uchar *bm;    /* pointer to the bubble bit mask */
  1569. X    struct bubble *prev, *next; /* need to traverse the list up and down */
  1570. X    struct container *cons;
  1571. X} *bbubbles, *ebubbles;
  1572. X
  1573. Xstatic struct trap *wportal;
  1574. Xstatic int xmin, ymin, xmax, ymax;    /* level boundaries */
  1575. X/* bubble movement boundaries */
  1576. X#define bxmin (xmin + 1)
  1577. X#define bymin (ymin + 1)
  1578. X#define bxmax (xmax - 1)
  1579. X#define bymax (ymax - 1)
  1580. X
  1581. Xstatic void NDECL(set_wportal);
  1582. Xstatic void FDECL(mk_bubble, (int,int,int));
  1583. Xstatic void FDECL(mv_bubble, (struct bubble *,int,int,BOOLEAN_P));
  1584. X
  1585. Xvoid
  1586. Xmovebubbles()
  1587. X{
  1588. X    static boolean up;
  1589. X    register struct bubble *b;
  1590. X    register int x, y, i, j;
  1591. X    struct trap *btrap;
  1592. X    static const struct rm water_pos =
  1593. X        { cmap_to_glyph(S_water), WATER, 0, 0, 0, 0, 0, 0, 0 };
  1594. X
  1595. X    /* set up the portal the first time bubbles are moved */
  1596. X    if (!wportal) set_wportal();
  1597. X
  1598. X    vision_recalc(2);
  1599. X
  1600. X    /*
  1601. X     * Pick up everything inside of a bubble then fill all bubble
  1602. X     * locations.
  1603. X     */
  1604. X
  1605. X    for (b = up ? bbubbles : ebubbles; b; b = up ? b->next : b->prev) {
  1606. X        if (b->cons) panic("movebubbles: cons != null");
  1607. X        for (i = 0, x = b->x; i < (int) b->bm[0]; i++, x++)
  1608. X        for (j = 0, y = b->y; j < (int) b->bm[1]; j++, y++)
  1609. X            if (b->bm[j + 2] & (1 << i)) {
  1610. X            if (!isok(x,y)) {
  1611. X                impossible("movebubbles: bad pos (%d,%d)", x,y);
  1612. X                continue;
  1613. X            }
  1614. X
  1615. X            /* pick up objects, monsters, hero, and traps */
  1616. X            if (OBJ_AT(x,y)) {
  1617. X                struct obj *olist = (struct obj *) 0, *otmp;
  1618. X                struct container *cons = (struct container *)
  1619. X                alloc(sizeof(struct container));
  1620. X
  1621. X                while ((otmp = level.objects[x][y]) != 0) {
  1622. X                remove_object(otmp);
  1623. X                otmp->ox = otmp->oy = 0;
  1624. X                otmp->nexthere = olist;
  1625. X                olist = otmp;
  1626. X                }
  1627. X
  1628. X                cons->x = x;
  1629. X                cons->y = y;
  1630. X                cons->what = CONS_OBJ;
  1631. X                cons->list = (genericptr_t) olist;
  1632. X                cons->next = b->cons;
  1633. X                b->cons = cons;
  1634. X            }
  1635. X            if (MON_AT(x,y)) {
  1636. X                struct monst *mon = m_at(x,y);
  1637. X                struct container *cons = (struct container *)
  1638. X                alloc(sizeof(struct container));
  1639. X
  1640. X                cons->x = x;
  1641. X                cons->y = y;
  1642. X                cons->what = CONS_MON;
  1643. X                cons->list = (genericptr_t) mon;
  1644. X
  1645. X                cons->next = b->cons;
  1646. X                b->cons = cons;
  1647. X
  1648. X                if(mon->wormno)
  1649. X                remove_worm(mon);
  1650. X                else
  1651. X                remove_monster(x, y);
  1652. X
  1653. X                newsym(x,y);    /* clean up old position */
  1654. X                mon->mx = mon->my = 0;
  1655. X            }
  1656. X            if (!u.uswallow && x == u.ux && y == u.uy) {
  1657. X                struct container *cons = (struct container *)
  1658. X                alloc(sizeof(struct container));
  1659. X
  1660. X                cons->x = x;
  1661. X                cons->y = y;
  1662. X                cons->what = CONS_HERO;
  1663. X                cons->list = (genericptr_t) 0;
  1664. X
  1665. X                cons->next = b->cons;
  1666. X                b->cons = cons;
  1667. X            }
  1668. X            if ((btrap = t_at(x,y)) != 0) {
  1669. X                struct container *cons = (struct container *)
  1670. X                alloc(sizeof(struct container));
  1671. X
  1672. X                cons->x = x;
  1673. X                cons->y = y;
  1674. X                cons->what = CONS_TRAP;
  1675. X                cons->list = (genericptr_t) btrap;
  1676. X
  1677. X                cons->next = b->cons;
  1678. X                b->cons = cons;
  1679. X            }
  1680. X
  1681. X            levl[x][y] = water_pos;
  1682. X            block_point(x,y);
  1683. X            }
  1684. X    }
  1685. X
  1686. X    /*
  1687. X     * Every second time traverse down.  This is because otherwise
  1688. X     * all the junk that changes owners when bubbles overlap
  1689. X     * would eventually end up in the last bubble in the chain.
  1690. X     */
  1691. X
  1692. X    up = !up;
  1693. X    for (b = up ? bbubbles : ebubbles; b; b = up ? b->next : b->prev) {
  1694. X        register int rx = rn2(3), ry = rn2(3);
  1695. X
  1696. X        mv_bubble(b,b->dx + 1 - (!b->dx ? rx : (rx ? 1 : 0)),
  1697. X                b->dy + 1 - (!b->dy ? ry : (ry ? 1 : 0)),
  1698. X                FALSE);
  1699. X    }
  1700. X
  1701. X    vision_full_recalc = 1;
  1702. X}
  1703. X
  1704. Xvoid
  1705. Xwater_friction()
  1706. X{
  1707. X    register boolean eff = FALSE;
  1708. X
  1709. X    if (u.dx && !rn2(3)) {
  1710. X        eff = TRUE;
  1711. X        u.dx = 0;
  1712. X    }
  1713. X    if (u.dy && !rn2(3)) {
  1714. X        eff = TRUE;
  1715. X        u.dy = 0;
  1716. X    }
  1717. X    if (eff) pline("Water turbulence affects your movements.");
  1718. X}
  1719. X
  1720. Xvoid
  1721. Xsave_waterlevel(fd)
  1722. Xregister int fd;
  1723. X{
  1724. X    register struct bubble *b;
  1725. X    int n;
  1726. X
  1727. X    if (!Is_waterlevel(&u.uz)) return;
  1728. X
  1729. X    for (b = bbubbles, n = 0; b; b = b->next, n++) ;
  1730. X    bwrite(fd,(genericptr_t)&n,sizeof(int));
  1731. X    bwrite(fd,(genericptr_t)&xmin,sizeof(int));
  1732. X    bwrite(fd,(genericptr_t)&ymin,sizeof(int));
  1733. X    bwrite(fd,(genericptr_t)&xmax,sizeof(int));
  1734. X    bwrite(fd,(genericptr_t)&ymax,sizeof(int));
  1735. X    for (b = bbubbles; b; b = b->next)
  1736. X        bwrite(fd,(genericptr_t)b,sizeof(struct bubble));
  1737. X}
  1738. X
  1739. Xvoid
  1740. Xrestore_waterlevel(fd)
  1741. Xregister int fd;
  1742. X{
  1743. X    register struct bubble *b = (struct bubble *)0, *btmp;
  1744. X    register int i;
  1745. X    int n;
  1746. X
  1747. X    if (!Is_waterlevel(&u.uz)) return;
  1748. X
  1749. X    set_wportal();
  1750. X    mread(fd,(genericptr_t)&n,sizeof(int));
  1751. X    mread(fd,(genericptr_t)&xmin,sizeof(int));
  1752. X    mread(fd,(genericptr_t)&ymin,sizeof(int));
  1753. X    mread(fd,(genericptr_t)&xmax,sizeof(int));
  1754. X    mread(fd,(genericptr_t)&ymax,sizeof(int));
  1755. X    for (i = 0; i < n; i++) {
  1756. X        btmp = b;
  1757. X        b = (struct bubble *)alloc(sizeof(struct bubble));
  1758. X        mread(fd,(genericptr_t)b,sizeof(struct bubble));
  1759. X        if (bbubbles) {
  1760. X            btmp->next = b;
  1761. X            b->prev = btmp;
  1762. X        } else {
  1763. X            bbubbles = b;
  1764. X            b->prev = (struct bubble *)0;
  1765. X        }
  1766. X        mv_bubble(b,0,0,TRUE);
  1767. X    }
  1768. X    ebubbles = b;
  1769. X    b->next = (struct bubble *)0;
  1770. X    was_waterlevel = TRUE;
  1771. X}
  1772. X
  1773. Xstatic void
  1774. Xset_wportal()
  1775. X{
  1776. X    /* there better be only one magic portal on water level... */
  1777. X    for (wportal = ftrap; wportal; wportal = wportal->ntrap)
  1778. X        if (wportal->ttyp == MAGIC_PORTAL) return;
  1779. X    impossible("set_wportal(): no portal!");
  1780. X}
  1781. X
  1782. Xstatic void
  1783. Xsetup_waterlevel()
  1784. X{
  1785. X    register int x, y;
  1786. X    register int xskip, yskip;
  1787. X    register int water_glyph = cmap_to_glyph(S_water);
  1788. X
  1789. X    /* ouch, hardcoded... */
  1790. X
  1791. X    xmin = 3;
  1792. X    ymin = 1;
  1793. X    xmax = 78;
  1794. X    ymax = 20;
  1795. X
  1796. X    /* set hero's memory to water */
  1797. X
  1798. X    for (x = xmin; x <= xmax; x++)
  1799. X        for (y = ymin; y <= ymax; y++)
  1800. X            levl[x][y].glyph = water_glyph;
  1801. X
  1802. X    /* make bubbles */
  1803. X
  1804. X    xskip = 10 + rn2(10);
  1805. X    yskip = 4 + rn2(4);
  1806. X    for (x = bxmin; x <= bxmax; x += xskip)
  1807. X        for (y = bymin; y <= bymax; y += yskip)
  1808. X            mk_bubble(x,y,rn2(7));
  1809. X}
  1810. X
  1811. Xstatic void
  1812. Xunsetup_waterlevel()
  1813. X{
  1814. X    register struct bubble *b, *bb;
  1815. X
  1816. X    /* free bubbles */
  1817. X
  1818. X    for (b = bbubbles; b; b = bb) {
  1819. X        bb = b->next;
  1820. X        free((genericptr_t)b);
  1821. X    }
  1822. X    bbubbles = ebubbles = (struct bubble *)0;
  1823. X}
  1824. X
  1825. Xstatic void
  1826. Xmk_bubble(x,y,n)
  1827. Xregister int x, y, n;
  1828. X{
  1829. X    /*
  1830. X     * These bit masks make visually pleasing bubbles on a normal aspect
  1831. X     * 25x80 terminal, which naturally results in them being mathematically
  1832. X     * anything but symmetric.  For this reason they cannot be computed
  1833. X     * in situ, either.  The first two elements tell the dimensions of
  1834. X     * the bubble's bounding box.
  1835. X     */
  1836. X    static uchar
  1837. X        bm2[] = {2,1,0x3},
  1838. X        bm3[] = {3,2,0x7,0x7},
  1839. X        bm4[] = {4,3,0x6,0xf,0x6},
  1840. X        bm5[] = {5,3,0xe,0x1f,0xe},
  1841. X        bm6[] = {6,4,0x1e,0x3f,0x3f,0x1e},
  1842. X        bm7[] = {7,4,0x3e,0x7f,0x7f,0x3e},
  1843. X        bm8[] = {8,4,0x7e,0xff,0xff,0x7e},
  1844. X        *bmask[] = {bm2,bm3,bm4,bm5,bm6,bm7,bm8};
  1845. X
  1846. X    register struct bubble *b;
  1847. X
  1848. X    if (x >= bxmax || y >= bymax) return;
  1849. X    if (n >= SIZE(bmask)) {
  1850. X        impossible("n too large (mk_bubble)");
  1851. X        n = SIZE(bmask) - 1;
  1852. X    }
  1853. X    b = (struct bubble *)alloc(sizeof(struct bubble));
  1854. X    if ((x + (int) bmask[n][0] - 1) > bxmax) x = bxmax - bmask[n][0] + 1;
  1855. X    if ((y + (int) bmask[n][1] - 1) > bymax) y = bymax - bmask[n][1] + 1;
  1856. X    b->x = x;
  1857. X    b->y = y;
  1858. X    b->dx = 1 - rn2(3);
  1859. X    b->dy = 1 - rn2(3);
  1860. X    b->bm = bmask[n];
  1861. X    b->cons = 0;
  1862. X    if (!bbubbles) bbubbles = b;
  1863. X    if (ebubbles) {
  1864. X        ebubbles->next = b;
  1865. X        b->prev = ebubbles;
  1866. X    }
  1867. X    else
  1868. X        b->prev = (struct bubble *)0;
  1869. X    b->next =  (struct bubble *)0;
  1870. X    ebubbles = b;
  1871. X    mv_bubble(b,0,0,TRUE);
  1872. X}
  1873. X
  1874. X/*
  1875. X * The player, the portal and all other objects and monsters
  1876. X * float along with their associated bubbles.  Bubbles may overlap
  1877. X * freely, and the contents may get associated with other bubbles in
  1878. X * the process.  Bubbles are "sticky", meaning that if the player is
  1879. X * in the immediate neighborhood of one, he/she may get sucked inside.
  1880. X * This property also makes leaving a bubble slightly difficult.
  1881. X */
  1882. Xstatic void
  1883. Xmv_bubble(b,dx,dy,ini)
  1884. Xregister struct bubble *b;
  1885. Xregister int dx, dy;
  1886. Xregister boolean ini;
  1887. X{
  1888. X    register int x, y, i, j, colli = 0;
  1889. X    struct bubble ob;
  1890. X    struct container *cons, *ctemp;
  1891. X
  1892. X    /* some old data for reference */
  1893. X
  1894. X    ob.x = b->x;
  1895. X    ob.y = b->y;
  1896. X    ob.bm = b->bm;
  1897. X
  1898. X    /* move bubble */
  1899. X    if (dx < -1 || dx > 1 || dy < -1 || dy > 1) {
  1900. X        /* pline("mv_bubble: dx = %d, dy = %d", dx, dy); */
  1901. X        dx = sgn(dx);
  1902. X        dy = sgn(dy);
  1903. X    }
  1904. X
  1905. X    /*
  1906. X     * collision with level borders?
  1907. X     *    1 = horizontal border, 2 = vertical, 3 = corner
  1908. X     */
  1909. X    if (b->x <= bxmin) colli |= 2;
  1910. X    if (b->y <= bymin) colli |= 1;
  1911. X    if ((int) (b->x + b->bm[0] - 1) >= bxmax) colli |= 2;
  1912. X    if ((int) (b->y + b->bm[1] - 1) >= bymax) colli |= 1;
  1913. X
  1914. X    if (b->x < bxmin) {
  1915. X        pline("bubble xmin: x = %d, xmin = %d", b->x, bxmin);
  1916. X        b->x = bxmin;
  1917. X    }
  1918. X    if (b->y < bymin) {
  1919. X        pline("bubble ymin: y = %d, ymin = %d", b->y, bymin);
  1920. X        b->y = bymin;
  1921. X    }
  1922. X    if ((int) (b->x + b->bm[0] - 1) > bxmax) {
  1923. X        pline("bubble xmax: x = %d, xmax = %d",
  1924. X            b->x + b->bm[0] - 1, bxmax);
  1925. X        b->x = bxmax - b->bm[0] + 1;
  1926. X    }
  1927. X    if ((int) (b->y + b->bm[1] - 1) > bymax) {
  1928. X        pline("bubble ymax: y = %d, ymax = %d",
  1929. X            b->y + b->bm[1] - 1, bymax);
  1930. X        b->y = bymax - b->bm[1] + 1;
  1931. X    }
  1932. X
  1933. X    /* bounce if we're trying to move off the border */
  1934. X    if (b->x == bxmin && dx < 0) dx = -dx;
  1935. X    if (b->x + b->bm[0] - 1 == bxmax && dx > 0) dx = -dx;
  1936. X    if (b->y == bymin && dy < 0) dy = -dy;
  1937. X    if (b->y + b->bm[1] - 1 == bymax && dy > 0) dy = -dy;
  1938. X
  1939. X    b->x += dx;
  1940. X    b->y += dy;
  1941. X
  1942. X    /* void positions inside bubble */
  1943. X
  1944. X    for (i = 0, x = b->x; i < (int) b->bm[0]; i++, x++)
  1945. X        for (j = 0, y = b->y; j < (int) b->bm[1]; j++, y++)
  1946. X        if (b->bm[j + 2] & (1 << i)) {
  1947. X            levl[x][y].typ = AIR;
  1948. X            levl[x][y].lit = 1;
  1949. X            unblock_point(x,y);
  1950. X        }
  1951. X
  1952. X    /* replace contents of bubble */
  1953. X    for (cons = b->cons; cons; cons = ctemp) {
  1954. X        ctemp = cons->next;
  1955. X        cons->x += dx;
  1956. X        cons->y += dy;
  1957. X
  1958. X        switch(cons->what) {
  1959. X        case CONS_OBJ: {
  1960. X            struct obj *olist, *otmp;
  1961. X
  1962. X            for (olist=(struct obj *)cons->list; olist; olist=otmp) {
  1963. X            otmp = olist->nexthere;
  1964. X            place_object(olist, cons->x, cons->y);
  1965. X            }
  1966. X            break;
  1967. X        }
  1968. X
  1969. X        case CONS_MON: {
  1970. X            struct monst *mon = (struct monst *) cons->list;
  1971. X            (void) mnearto(mon, cons->x, cons->y, TRUE);
  1972. X            break;
  1973. X        }
  1974. X
  1975. X        case CONS_HERO: {
  1976. X            int ux0 = u.ux, uy0 = u.uy;
  1977. X
  1978. X            /* change u.ux0 and u.uy0? */
  1979. X            u.ux = cons->x;
  1980. X            u.uy = cons->y;
  1981. X            newsym(ux0, uy0);    /* clean up old position */
  1982. X
  1983. X            if (MON_AT(cons->x, cons->y)) {
  1984. X                mnexto(m_at(cons->x,cons->y));
  1985. X            }
  1986. X            if (Punished) placebc();    /* do this for now */
  1987. X            break;
  1988. X        }
  1989. X
  1990. X        case CONS_TRAP: {
  1991. X            struct trap *btrap = (struct trap *) cons->list;
  1992. X            btrap->tx = cons->x;
  1993. X            btrap->ty = cons->y;
  1994. X            break;
  1995. X        }
  1996. X
  1997. X        default:
  1998. X            impossible("mv_bubble: unknown bubble contents");
  1999. X            break;
  2000. X        }
  2001. X        free((genericptr_t)cons);
  2002. X    }
  2003. X    b->cons = 0;
  2004. X
  2005. X    /* boing? */
  2006. X
  2007. X    switch (colli) {
  2008. X        case 1: b->dy = -b->dy;    break;
  2009. X        case 3: b->dy = -b->dy;    /* fall through */
  2010. X        case 2: b->dx = -b->dx;    break;
  2011. X        default:
  2012. X        /* sometimes alter direction for fun anyway
  2013. X           (higher probability for stationary bubbles) */
  2014. X        if (!ini && ((b->dx || b->dy) ? !rn2(20) : !rn2(5))) {
  2015. X            b->dx = 1 - rn2(3);
  2016. X            b->dy = 1 - rn2(3);
  2017. X        }
  2018. X    }
  2019. X}
  2020. X
  2021. X
  2022. X/*mkmaze.c*/
  2023. END_OF_FILE
  2024. if test 29353 -ne `wc -c <'src/mkmaze.c'`; then
  2025.     echo shar: \"'src/mkmaze.c'\" unpacked with wrong size!
  2026. fi
  2027. # end of 'src/mkmaze.c'
  2028. fi
  2029. echo shar: End of archive 71 \(of 108\).
  2030. cp /dev/null ark71isdone
  2031. MISSING=""
  2032. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2033. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2034. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2035. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2036. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2037. 101 102 103 104 105 106 107 108 ; do
  2038.     if test ! -f ark${I}isdone ; then
  2039.     MISSING="${MISSING} ${I}"
  2040.     fi
  2041. done
  2042. if test "${MISSING}" = "" ; then
  2043.     echo You have unpacked all 108 archives.
  2044.     echo "Now execute 'rebuild.sh'"
  2045.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2046. else
  2047.     echo You still need to unpack the following archives:
  2048.     echo "        " ${MISSING}
  2049. fi
  2050. ##  End of shell archive.
  2051. exit 0
  2052.