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

  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: v16i069:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part61/108
  5. Message-ID: <4372@master.CNA.TEK.COM>
  6. Date: 1 Feb 93 19:49:45 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2382
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1619
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 69
  14. Archive-name: nethack31/Part61
  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 61 (of 108)."
  27. # Contents:  src/files.c src/zap.c2
  28. # Wrapped by billr@saab on Wed Jan 27 16:09:10 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'src/files.c' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'src/files.c'\"
  32. else
  33. echo shar: Extracting \"'src/files.c'\" \(21581 characters\)
  34. sed "s/^X//" >'src/files.c' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)files.c    3.1    92/12/07    */
  36. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  37. X/* NetHack may be freely redistributed.  See license for details. */
  38. X
  39. X#include "hack.h"
  40. X
  41. X#include <ctype.h>
  42. X
  43. X#if !defined(MAC) && !defined(O_WRONLY) && !defined(AZTEC_C)
  44. X#include <fcntl.h>
  45. X#endif
  46. X#if defined(UNIX) || defined(VMS)
  47. X#include <errno.h>
  48. X# ifndef SKIP_ERRNO
  49. Xextern int errno;
  50. X# endif
  51. X#include <signal.h>
  52. X#endif
  53. X
  54. X#if defined(MSDOS) || defined(OS2) || defined(TOS)
  55. X# ifndef GNUDOS
  56. X#include <sys\stat.h>
  57. X# else
  58. X#include <sys/stat.h>
  59. X# endif
  60. X#endif
  61. X#ifndef O_BINARY    /* used for micros, no-op for others */
  62. X# define O_BINARY 0
  63. X#endif
  64. X
  65. X#ifdef MFLOPPY
  66. Xchar bones[FILENAME];        /* pathname of bones files */
  67. Xchar lock[FILENAME];        /* pathname of level files */
  68. X#else
  69. Xstatic char bones[] = "bonesnn.xxxx";
  70. X# ifdef VMS
  71. Xchar lock[PL_NSIZ+17] = "1lock"; /* long enough for _uid+name+.99;1 */
  72. X# else
  73. Xchar lock[PL_NSIZ+14] = "1lock"; /* long enough for uid+name+.99 */
  74. X# endif
  75. X#endif
  76. X
  77. X#ifdef MAC
  78. X#include <files.h>
  79. XMacDirs theDirs ;
  80. X#endif
  81. X
  82. X#ifdef UNIX
  83. X#define SAVESIZE    (PL_NSIZ + 13)    /* save/99999player.e */
  84. X#else
  85. X# ifdef VMS
  86. X#define SAVESIZE    (PL_NSIZ + 22)    /* [.save]<uid>player.e;1 */
  87. X# else
  88. X#define SAVESIZE    FILENAME    /* from macconf.h or pcconf.h */
  89. X# endif
  90. X#endif
  91. X
  92. Xchar SAVEF[SAVESIZE];    /* holds relative path of save file from playground */
  93. X#ifdef MICRO
  94. Xchar SAVEP[SAVESIZE];    /* holds path of directory for save file */
  95. X#endif
  96. X#ifdef AMIGA
  97. Xextern char PATH[];    /* see sys/amiga/amidos.c */
  98. X#endif
  99. X
  100. Xstatic char * FDECL(set_bonesfile_name, (char *,d_level*));
  101. X
  102. X/* fopen a file, with OS-dependent bells and whistles */
  103. XFILE *
  104. Xfopen_datafile(filename, mode)
  105. Xconst char *filename, *mode;
  106. X{
  107. X    FILE *fp;
  108. X#ifdef AMIGA
  109. X    fp = fopenp(filename, mode);
  110. X#else
  111. X# ifdef VMS    /* essential to have punctuation, to avoid logical names */
  112. X    char tmp[BUFSIZ];
  113. X
  114. X    if (!index(filename, '.') && !index(filename, ';'))
  115. X        filename = strcat(strcpy(tmp, filename), ";0");
  116. X    fp = fopen(filename, mode, "mbc=16");
  117. X# else
  118. X    fp = fopen(filename, mode);
  119. X# endif
  120. X#endif
  121. X    return fp;
  122. X}
  123. X
  124. X
  125. X/* ----------  BEGIN LEVEL FILE HANDLING ----------- */
  126. X
  127. X#ifdef MFLOPPY
  128. X/* Set names for bones[] and lock[] */
  129. Xvoid
  130. Xset_lock_and_bones()
  131. X{
  132. X    if (!ramdisk) {
  133. X        Strcpy(levels, permbones);
  134. X        Strcpy(bones, permbones);
  135. X    }
  136. X    append_slash(permbones);
  137. X    append_slash(levels);
  138. X    append_slash(bones);
  139. X    Strcat(bones, "bonesnn.*");
  140. X    Strcpy(lock, levels);
  141. X    Strcat(lock, alllevels);
  142. X    return;
  143. X}
  144. X#endif /* MFLOPPY */
  145. X
  146. X
  147. X/* Construct a file name for a level-type file, which is of the form
  148. X * something.level (with any old level stripped off).
  149. X * This assumes there is space on the end of 'file' to append
  150. X * a two digit number.  This is true for 'level'
  151. X * but be careful if you use it for other things -dgk
  152. X */
  153. Xvoid
  154. Xset_levelfile_name(file, lev)
  155. Xchar *file;
  156. Xint lev;
  157. X{
  158. X    char *tf;
  159. X
  160. X    tf = rindex(file, '.');
  161. X    if (!tf) tf = eos(file);
  162. X    Sprintf(tf, ".%d", lev);
  163. X#ifdef VMS
  164. X    Strcat(tf, ";1");
  165. X#endif
  166. X    return;
  167. X}
  168. X
  169. Xint
  170. Xcreate_levelfile(lev)
  171. Xint lev;
  172. X{
  173. X    int fd;
  174. X
  175. X    set_levelfile_name(lock, lev);
  176. X
  177. X#if defined(MICRO)
  178. X    /* Use O_TRUNC to force the file to be shortened if it already
  179. X     * exists and is currently longer.
  180. X     */
  181. X    fd = open(lock, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK);
  182. X#else
  183. X#ifdef MAC
  184. X    fd = maccreat ( lock , LEVL_TYPE ) ;
  185. X#else /* MAC */
  186. X    fd = creat(lock, FCMASK);
  187. X#endif /* MAC */
  188. X#endif /* MICRO */
  189. X
  190. X    return fd;
  191. X}
  192. X
  193. X
  194. Xint
  195. Xopen_levelfile(lev)
  196. Xint lev;
  197. X{
  198. X    int fd;
  199. X
  200. X    set_levelfile_name(lock, lev);
  201. X#ifdef MFLOPPY
  202. X    /* If not currently accessible, swap it in. */
  203. X    if (fileinfo[lev].where != ACTIVE)
  204. X        swapin_file(lev);
  205. X#endif
  206. X# ifdef MAC
  207. X    fd = macopen ( lock , O_RDONLY | O_BINARY , LEVL_TYPE ) ;
  208. X# else /* MAC */
  209. X    fd = open(lock, O_RDONLY | O_BINARY, 0);
  210. X# endif /* MAC */
  211. X    return fd;
  212. X}
  213. X
  214. X
  215. Xvoid
  216. Xdelete_levelfile(lev)
  217. Xint lev;
  218. X{
  219. X    set_levelfile_name(lock, lev);
  220. X    (void) unlink(lock);
  221. X}
  222. X
  223. X
  224. Xvoid
  225. Xclearlocks()
  226. X{
  227. X#ifdef MFLOPPY
  228. X    eraseall(levels, alllevels);
  229. X# ifndef AMIGA
  230. X    if (ramdisk)
  231. X        eraseall(permbones, alllevels);
  232. X# endif
  233. X#else
  234. X    register int x;
  235. X
  236. X# if defined(UNIX) || defined(VMS)
  237. X    (void) signal(SIGHUP, SIG_IGN);
  238. X# endif
  239. X    for (x = maxledgerno(); x >= 0; x--)
  240. X        delete_levelfile(x);    /* not all levels need be present */
  241. X#endif
  242. X}
  243. X
  244. X/* ----------  END LEVEL FILE HANDLING ----------- */
  245. X
  246. X
  247. X/* ----------  BEGIN BONES FILE HANDLING ----------- */
  248. X
  249. Xstatic char *
  250. Xset_bonesfile_name(file, lev)
  251. Xchar *file;
  252. Xd_level *lev;
  253. X{
  254. X    char *dptr = rindex(file, '.');
  255. X    s_level *sptr;
  256. X
  257. X    if (!dptr) dptr = eos(file);
  258. X    *(dptr-2) = dungeons[lev->dnum].boneid;
  259. X#ifdef MULDGN
  260. X    *(dptr-1) = In_quest(lev) ? pl_character[0] : '0';
  261. X#else
  262. X    *(dptr-1) = '0';
  263. X#endif
  264. X    if ((sptr = Is_special(lev)) != 0)
  265. X        Sprintf(dptr, ".%c", sptr->boneid);
  266. X    else
  267. X        Sprintf(dptr, ".%d", lev->dlevel);
  268. X#ifdef VMS
  269. X    Strcat(dptr, ";1");
  270. X#endif
  271. X    return(dptr-2);
  272. X}
  273. X
  274. Xint
  275. Xcreate_bonesfile(lev, bonesid)
  276. Xd_level *lev;
  277. Xchar **bonesid;
  278. X{
  279. X    int fd;
  280. X
  281. X    *bonesid = set_bonesfile_name(bones, lev);
  282. X
  283. X#ifdef MICRO
  284. X    /* Use O_TRUNC to force the file to be shortened if it already
  285. X     * exists and is currently longer.
  286. X     */
  287. X    fd = open(bones, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK);
  288. X#else
  289. X# ifdef MAC
  290. X    fd = maccreat ( bones , BONE_TYPE ) ;
  291. X# else /* MAC */
  292. X    fd = creat(bones, FCMASK);
  293. X# endif /* MAC */
  294. X#  if defined(VMS) && !defined(SECURE)
  295. X    /*
  296. X       Re-protect bones file with world:read+write+execute+delete access.
  297. X       umask() doesn't seem very reliable; also, vaxcrtl won't let us set
  298. X       delete access without write access, which is what's really wanted.
  299. X       Can't simply create it with the desired protection because creat
  300. X       ANDs the mask with the user's default protection, which usually
  301. X       denies some or all access to world.
  302. X     */
  303. X    (void) chmod(bones, FCMASK | 007);  /* allow other users full access */
  304. X#  endif /* VMS && !SECURE */
  305. X#endif /* MICRO */
  306. X
  307. X    return fd;
  308. X}
  309. X
  310. X
  311. Xint
  312. Xopen_bonesfile(lev, bonesid)
  313. Xd_level *lev;
  314. Xchar **bonesid;
  315. X{
  316. X    int fd;
  317. X
  318. X    *bonesid = set_bonesfile_name(bones, lev);
  319. X    uncompress(bones);    /* no effect if nonexistent */
  320. X#ifdef MAC
  321. X    fd = macopen ( bones , O_RDONLY | O_BINARY , BONE_TYPE ) ;
  322. X#else
  323. X    fd = open(bones, O_RDONLY | O_BINARY, 0);
  324. X#endif
  325. X    return fd;
  326. X}
  327. X
  328. X
  329. Xint
  330. Xdelete_bonesfile(lev)
  331. Xd_level *lev;
  332. X{
  333. X    (void) set_bonesfile_name(bones, lev);
  334. X    return !(unlink(bones) < 0);
  335. X}
  336. X
  337. X
  338. X/* assume we're compressing the recently read or created bonesfile, so the
  339. X * file name is already set properly */
  340. Xvoid
  341. Xcompress_bonesfile()
  342. X{
  343. X    compress(bones);
  344. X}
  345. X
  346. X/* ----------  END BONES FILE HANDLING ----------- */
  347. X
  348. X
  349. X/* ----------  BEGIN SAVE FILE HANDLING ----------- */
  350. X
  351. X/* set savefile name in OS-dependent manner from pre-existing plname,
  352. X * avoiding troublesome characters */
  353. Xvoid
  354. Xset_savefile_name()
  355. X{
  356. X#ifdef VMS
  357. X    Sprintf(SAVEF, "[.save]%d%s", getuid(), plname);
  358. X    regularize(SAVEF+7);
  359. X    Strcat(SAVEF, ";1");
  360. X#else
  361. X# ifdef MICRO
  362. X    Strcpy(SAVEF, SAVEP);
  363. X    {
  364. X        int i = strlen(SAVEP);
  365. X#  ifdef AMIGA
  366. X        /* plname has to share space with SAVEP and ".sav" */
  367. X        (void)strncat(SAVEF, plname, FILENAME - i - 4);
  368. X#  else
  369. X        (void)strncat(SAVEF, plname, 8);
  370. X#  endif
  371. X        regularize(SAVEF+i);
  372. X    }
  373. X    Strcat(SAVEF, ".sav");
  374. X# else
  375. X    Sprintf(SAVEF, "save/%d%s", (int)getuid(), plname);
  376. X    regularize(SAVEF+5);    /* avoid . or / in name */
  377. X# endif
  378. X#endif
  379. X}
  380. X
  381. X#ifdef INSURANCE
  382. Xvoid
  383. Xsave_savefile_name(fd)
  384. Xint fd;
  385. X{
  386. X    (void) write(fd, (genericptr_t) SAVEF, sizeof(SAVEF));
  387. X}
  388. X#endif
  389. X
  390. X
  391. X#if defined(WIZARD) && !defined(MICRO)
  392. X/* change pre-existing savefile name to indicate an error savefile */
  393. Xvoid
  394. Xset_error_savefile()
  395. X{
  396. X# ifdef VMS
  397. X      {
  398. X    char *semi_colon = rindex(SAVEF, ';');
  399. X    if (semi_colon) *semi_colon = '\0';
  400. X      }
  401. X    Strcat(SAVEF, ".e;1");
  402. X# else
  403. X#ifdef MAC
  404. X    Strcat(SAVEF, "-e");
  405. X#else
  406. X    Strcat(SAVEF, ".e");
  407. X#endif
  408. X# endif
  409. X}
  410. X#endif
  411. X
  412. X
  413. X/* create save file, overwriting one if it already exists */
  414. Xint
  415. Xcreate_savefile()
  416. X{
  417. X    int fd;
  418. X# ifdef AMIGA
  419. X    fd = ami_wbench_getsave(O_WRONLY | O_CREAT | O_TRUNC);
  420. X# else
  421. X#  ifdef MICRO
  422. X    fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
  423. X#  else
  424. X#   ifdef MAC
  425. X    fd = creat(SAVEF, SAVE_TYPE);
  426. X#   else /* MAC */
  427. X    fd = creat(SAVEF, FCMASK);
  428. X#   endif /* MAC */
  429. X#   if defined(VMS) && !defined(SECURE)
  430. X    /*
  431. X       Make sure the save file is owned by the current process.  That's
  432. X       the default for non-privileged users, but for priv'd users the
  433. X       file will be owned by the directory's owner instead of the user.
  434. X     */
  435. X#    ifdef getuid    /*(see vmsunix.c)*/
  436. X#     undef getuid
  437. X#    endif
  438. X    (void) chown(SAVEF, getuid(), getgid());
  439. X#   endif /* VMS && !SECURE */
  440. X#  endif
  441. X# endif
  442. X
  443. X    return fd;
  444. X}
  445. X
  446. X
  447. X/* open savefile for reading */
  448. Xint
  449. Xopen_savefile()
  450. X{
  451. X    int fd;
  452. X
  453. X#ifdef AMIGA
  454. X    fd = ami_wbench_getsave(O_RDONLY);
  455. X#else
  456. X# ifdef MAC
  457. X    fd = macopen ( SAVEF , O_RDONLY , SAVE_TYPE ) ;
  458. X# else /* MAC */
  459. X    fd = open(SAVEF, O_RDONLY, 0);
  460. X# endif /* MAC */
  461. X#endif /* AMIGA */
  462. X    return fd;
  463. X}
  464. X
  465. X
  466. X/* delete savefile */
  467. Xint
  468. Xdelete_savefile()
  469. X{
  470. X#ifdef AMIGA
  471. X    ami_wbench_unlink(SAVEF);
  472. X#endif
  473. X    (void) unlink(SAVEF);
  474. X    return 0;    /* for xxxmain.c test */
  475. X}
  476. X
  477. X
  478. X/* ----------  END SAVE FILE HANDLING ----------- */
  479. X
  480. X
  481. X/* ----------  BEGIN FILE COMPRESSION HANDLING ----------- */
  482. X
  483. X/* compress file */
  484. Xvoid
  485. Xcompress(filename)
  486. Xconst char *filename;
  487. X{
  488. X#ifdef COMPRESS
  489. X    char cmd[80];
  490. X
  491. X    Strcpy(cmd, COMPRESS);
  492. X    Strcat(cmd, " ");
  493. X# ifdef COMPRESS_OPTIONS
  494. X    Strcat(cmd, COMPRESS_OPTIONS);
  495. X    Strcat(cmd, " ");
  496. X# endif
  497. X    Strcat(cmd,filename);
  498. X    (void) system(cmd);
  499. X#endif
  500. X}
  501. X
  502. X
  503. X/* uncompress file if it exists */
  504. Xvoid
  505. Xuncompress(filename)
  506. Xconst char *filename;
  507. X{
  508. X#ifdef COMPRESS
  509. X    char cmd[80], cfn[80];
  510. X    int fd;
  511. X
  512. X    Strcpy(cfn,filename);
  513. X    Strcat(cfn,".Z");
  514. X    if((fd = open(cfn,O_RDONLY)) >= 0) {
  515. X        (void) close(fd);
  516. X        Strcpy(cmd, COMPRESS);
  517. X        Strcat(cmd, " -d ");        /* uncompress */
  518. X# ifdef COMPRESS_OPTIONS
  519. X        Strcat(cmd, COMPRESS_OPTIONS);
  520. X        Strcat(cmd, " ");
  521. X# endif
  522. X        Strcat(cmd,cfn);
  523. X        (void) system(cmd);
  524. X    }
  525. X#endif
  526. X}
  527. X
  528. X/* ----------  END FILE COMPRESSION HANDLING ----------- */
  529. X
  530. X
  531. X/* ----------  BEGIN FILE LOCKING HANDLING ----------- */
  532. X
  533. X#ifdef NO_FILE_LINKS    /* implies UNIX */
  534. Xstatic int lockfd;    /* for lock_file() to pass to unlock_file() */
  535. X#endif
  536. X
  537. X#if defined(UNIX) || defined(VMS)
  538. X#define HUP    if(!done_hup)
  539. X
  540. Xstatic char *
  541. Xmake_lockname(filename)
  542. Xconst char *filename;
  543. X{
  544. X    static char lockname[BUFSZ];
  545. X
  546. X# ifdef NO_FILE_LINKS
  547. X    Strcpy(lockname, LOCKDIR);
  548. X    Strcat(lockname, "/");
  549. X    Strcat(lockname, filename);
  550. X# else
  551. X    Strcpy(lockname, filename);
  552. X# endif
  553. X# ifdef VMS
  554. X      {
  555. X    char *semi_colon = rindex(lockname, ';');
  556. X    if (semi_colon) *semi_colon = '\0';
  557. X      }
  558. X    Strcat(lockname, ".lock;1");
  559. X# else
  560. X    Strcat(lockname, "_lock");
  561. X# endif
  562. X    return lockname;
  563. X}
  564. X#endif  /* UNIX || VMS */
  565. X
  566. X
  567. X/* lock a file */
  568. Xboolean
  569. Xlock_file(filename, retryct)
  570. Xconst char *filename;
  571. Xint retryct;
  572. X{
  573. X#if defined(UNIX) || defined(VMS)
  574. X    char *lockname;
  575. X
  576. X    lockname = make_lockname(filename);
  577. X
  578. X# ifdef NO_FILE_LINKS
  579. X    while ((lockfd = open(lockname, O_RDWR|O_CREAT|O_EXCL, 0666)) == -1) {
  580. X# else
  581. X    while (link(filename, lockname) == -1) {
  582. X# endif
  583. X        register int errnosv = errno;
  584. X
  585. X        switch (errnosv) {    /* George Barbanis */
  586. X            case ENOENT:
  587. X            HUP raw_printf("Can't find file %s to lock!", filename);
  588. X            return FALSE;
  589. X            case EACCES:
  590. X            HUP raw_printf("No write permission to lock %s!",
  591. X                       filename);
  592. X            return FALSE;
  593. X            case EEXIST:
  594. X            break;    /* retry checks below */
  595. X            default:
  596. X            HUP perror(lockname);
  597. X            HUP raw_printf(
  598. X                     "Cannot lock %s for unknown reason (%d).",
  599. X                       filename, errnosv);
  600. X            return FALSE;
  601. X        }
  602. X
  603. X        if (!retryct--) {
  604. X            HUP (void) raw_print("I give up.  Sorry.");
  605. X            HUP raw_printf("Perhaps there is an old %s around?",
  606. X                       lockname);
  607. X            return FALSE;
  608. X        }
  609. X
  610. X        HUP raw_printf("Waiting for access to %s.  (%d retries left).",
  611. X                   filename, retryct);
  612. X# if defined(SYSV) || defined(ULTRIX) || defined(VMS)
  613. X        (void)
  614. X# endif
  615. X            sleep(1);
  616. X    }
  617. X#endif  /* UNIX || VMS */
  618. X    return TRUE;
  619. X}
  620. X
  621. X
  622. X#ifdef VMS    /* for unlock_file, use the unlink() routine in vmsunix.c */
  623. X# ifdef unlink
  624. X#  undef unlink
  625. X# endif
  626. X# define unlink(foo) vms_unlink(foo)
  627. X#endif
  628. X
  629. X/* unlock file, which must be currently locked by lock_file */
  630. Xvoid
  631. Xunlock_file(filename)
  632. Xconst char *filename;
  633. X{
  634. X#if defined(UNIX) || defined(VMS)
  635. X    char *lockname;
  636. X
  637. X    lockname = make_lockname(filename);
  638. X
  639. X    if (unlink(lockname) < 0)
  640. X        HUP raw_printf("Can't unlink %s.", lockname);
  641. X# ifdef NO_FILE_LINKS
  642. X    (void) close(lockfd);
  643. X# endif
  644. X
  645. X#endif  /* UNIX || VMS */
  646. X}
  647. X
  648. X/* ----------  END FILE LOCKING HANDLING ----------- */
  649. X
  650. X
  651. X/* ----------  BEGIN CONFIG FILE HANDLING ----------- */
  652. X
  653. Xconst char *configfile =
  654. X#ifdef UNIX
  655. X            ".nethackrc";
  656. X#else
  657. X#ifdef MAC
  658. X            "NetHack defaults";
  659. X#else
  660. X            "NetHack.cnf";
  661. X#endif
  662. X#endif
  663. X
  664. Xstatic FILE *FDECL(fopen_config_file, (const char *));
  665. Xstatic int FDECL(get_uchars, (FILE *, char *, char *, uchar *, int, const char *));
  666. Xint FDECL(parse_config_line, (FILE *, char *, char *, char *));
  667. X
  668. X#ifndef MFLOPPY
  669. X#define fopenp fopen
  670. X#endif
  671. X
  672. Xstatic FILE *
  673. Xfopen_config_file(filename)
  674. Xconst char *filename;
  675. X{
  676. X    FILE *fp;
  677. X#if defined(UNIX) || defined(VMS)
  678. X    char    tmp_config[BUFSZ];
  679. X#endif
  680. X
  681. X    /* "filename" is an environment variable, so it should hang around */
  682. X    if (filename && ((fp = fopenp(filename, "r")) != (FILE *)0)) {
  683. X        configfile = filename;
  684. X        return(fp);
  685. X    }
  686. X
  687. X#if defined(MICRO) || defined(MAC)
  688. X    if ((fp = fopenp(configfile, "r")) != (FILE *)0)
  689. X        return(fp);
  690. X#else
  691. X# ifdef VMS
  692. X    if ((fp = fopenp("nethackini", "r")) != (FILE *)0) {
  693. X        configfile = "nethackini";
  694. X        return(fp);
  695. X    }
  696. X    if ((fp = fopenp("sys$login:nethack.ini", "r")) != (FILE *)0) {
  697. X        configfile = "nethack.ini";
  698. X        return(fp);
  699. X    }
  700. X    Sprintf(tmp_config, "%s%s", getenv("HOME"), "NetHack.cnf");
  701. X    if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
  702. X        return(fp);
  703. X# else    /* should be only UNIX left */
  704. X    Sprintf(tmp_config, "%s/%s", getenv("HOME"), ".nethackrc");
  705. X    if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
  706. X        return(fp);
  707. X# endif
  708. X#endif
  709. X    return (FILE *)0;
  710. X
  711. X}
  712. X
  713. X
  714. X/*
  715. X * Retrieve a list of integers from a file into a uchar array.
  716. X *
  717. X * NOTE:  This routine is unable to read a value of 0.
  718. X */
  719. Xstatic int
  720. Xget_uchars(fp, buf, bufp, list, size, name)
  721. X    FILE *fp;        /* input file pointer */
  722. X    char *buf;        /* read buffer, must be of size BUFSZ */
  723. X    char *bufp;        /* current pointer */
  724. X    uchar *list;    /* return list */
  725. X    int  size;        /* return list size */
  726. X    const char *name;        /* name of option for error message */
  727. X{
  728. X    unsigned int num = 0;
  729. X    int count = 0;
  730. X
  731. X    while (1) {
  732. X    switch(*bufp) {
  733. X        case ' ':  case '\0':
  734. X        case '\t': case '\n':
  735. X        if (num) {
  736. X            list[count++] =  num;
  737. X            num = 0;
  738. X        }
  739. X        if (count == size || !*bufp) return count;
  740. X        bufp++;
  741. X        break;
  742. X
  743. X        case '0': case '1': case '2': case '3':
  744. X        case '4': case '5': case '6': case '7':
  745. X        case '8': case '9':
  746. X        num = num*10 + (*bufp-'0');
  747. X        bufp++;
  748. X        break;
  749. X
  750. X        case '\\':
  751. X            if (fp == (FILE *)0)
  752. X            goto gi_error;
  753. X        do  {
  754. X            if (!fgets(buf, BUFSZ, fp)) goto gi_error;
  755. X        } while (buf[0] == '#');
  756. X        bufp = buf;
  757. X        break;
  758. X
  759. X        default:
  760. Xgi_error:
  761. X        raw_printf("Syntax error in %s", name);
  762. X        wait_synch();
  763. X        return count;
  764. X    }
  765. X    }
  766. X    /*NOTREACHED*/
  767. X}
  768. X
  769. X/*ARGSUSED*/
  770. Xint
  771. Xparse_config_line(fp, buf, tmp_ramdisk, tmp_levels)
  772. XFILE        *fp;
  773. Xchar        *buf;
  774. Xchar        *tmp_ramdisk;
  775. Xchar        *tmp_levels;
  776. X{
  777. X    char        *bufp, *altp;
  778. X
  779. X    if (*buf == '#')
  780. X        return 1;
  781. X
  782. X    /* remove trailing whitespace */
  783. X    bufp = eos(buf);
  784. X    while (--bufp > buf && isspace(*bufp))
  785. X        continue;
  786. X
  787. X    if (bufp <= buf)
  788. X        return 1;        /* skip all-blank lines */
  789. X    else
  790. X        *(bufp + 1) = '\0';    /* terminate line */
  791. X
  792. X    /* find the '=' or ':' */
  793. X    bufp = index(buf, '=');
  794. X    altp = index(buf, ':');
  795. X    if (!bufp || (altp && altp < bufp)) bufp = altp;
  796. X    if (!bufp) return 0;
  797. X
  798. X    /* skip  whitespace between '=' and value */
  799. X    do { ++bufp; } while (isspace(*bufp));
  800. X
  801. X    /* Go through possible variables */
  802. X    if (!strncmpi(buf, "OPTIONS", 4)) {
  803. X        parseoptions(bufp, TRUE, TRUE);
  804. X        if (plname[0])        /* If a name was given */
  805. X            plnamesuffix();    /* set the character class */
  806. X#ifdef MICRO
  807. X    } else if (!strncmpi(buf, "HACKDIR", 4)) {
  808. X        (void) strncpy(hackdir, bufp, PATHLEN);
  809. X# ifdef MFLOPPY
  810. X    } else if (!strncmpi(buf, "RAMDISK", 3)) {
  811. X                /* The following ifdef is NOT in the wrong
  812. X                 * place.  For now, we accept and silently
  813. X                 * ignore RAMDISK */
  814. X#  ifndef AMIGA
  815. X        (void) strncpy(tmp_ramdisk, bufp, PATHLEN);
  816. X#  endif
  817. X# endif
  818. X    } else if (!strncmpi(buf, "LEVELS", 4)) {
  819. X        (void) strncpy(tmp_levels, bufp, PATHLEN);
  820. X
  821. X    } else if (!strncmpi(buf, "SAVE", 4)) {
  822. X        char *ptr;
  823. X        if (ptr = index(bufp, ';')) {
  824. X            *ptr = '\0';
  825. X# ifdef MFLOPPY
  826. X            if (*(ptr+1) == 'n' || *(ptr+1) == 'N') {
  827. X                extern    int saveprompt;
  828. X                saveprompt = FALSE;
  829. X            }
  830. X# endif
  831. X    }
  832. X        (void) strncpy(SAVEP, bufp, PATHLEN);
  833. X        append_slash(SAVEP);
  834. X#endif /* MICRO */
  835. X    } else if(!strncmpi(buf, "CHARACTER", 4)) {
  836. X        (void) strncpy(pl_character, bufp, PL_CSIZ);
  837. X    } else if(!strncmpi(buf, "DOGNAME", 3)) {
  838. X        (void) strncpy(dogname, bufp, 62);
  839. X    } else if(!strncmpi(buf, "CATNAME", 3)) {
  840. X        (void) strncpy(catname, bufp, 62);
  841. X    } else if(!strncmpi(buf, "NAME", 4)) {
  842. X        (void) strncpy(plname, bufp, PL_NSIZ);
  843. X        plnamesuffix();
  844. X    } else if (!strncmpi(buf, "GRAPHICS", 4)) {
  845. X        uchar   translate[MAXPCHARS];
  846. X        int   len;
  847. X
  848. X        len = get_uchars(fp, buf, bufp, translate,
  849. X                    MAXPCHARS, "GRAPHICS");
  850. X        assign_graphics(translate, len);
  851. X    } else if (!strncmpi(buf, "OBJECTS", 3)) {
  852. X        /* oc_syms[0] is the RANDOM object, unused */
  853. X        (void) get_uchars(fp, buf, bufp, &(oc_syms[1]),
  854. X                    MAXOCLASSES-1, "OBJECTS");
  855. X    } else if (!strncmpi(buf, "MONSTERS", 3)) {
  856. X        /* monsyms[0] is unused */
  857. X        (void) get_uchars(fp, buf, bufp, &(monsyms[1]),
  858. X                    MAXMCLASSES-1, "MONSTERS");
  859. X#ifdef AMIGA
  860. X    } else if (!strncmpi(buf, "PATH", 4)) {
  861. X        (void) strncpy(PATH, bufp, PATHLEN);
  862. X    } else if (!strncmpi(buf, "PENS", 3)) {
  863. X        int i;
  864. X        char *t;
  865. X        extern unsigned short amii_curmap[];
  866. X        for (i = 0, t = strtok(bufp, ",");
  867. X                t && i < 8;
  868. X                t = strtok(NULL, ","), ++i) {
  869. X            sscanf(t, "%hx", &amii_curmap[i]);
  870. X        }
  871. X        amii_setpens();
  872. X#endif
  873. X    } else
  874. X        return 0;
  875. X    return 1;
  876. X}
  877. X
  878. Xvoid
  879. Xread_config_file(filename)
  880. Xconst char *filename;
  881. X{
  882. X#define tmp_levels    (char *)0
  883. X#define tmp_ramdisk    (char *)0
  884. X
  885. X#ifdef MICRO
  886. X#undef tmp_levels
  887. X    char    tmp_levels[PATHLEN];
  888. X# ifdef MFLOPPY
  889. X#  ifndef AMIGA
  890. X#undef tmp_ramdisk
  891. X    char    tmp_ramdisk[PATHLEN];
  892. X#  endif
  893. X# endif
  894. X#endif
  895. X    char    buf[BUFSZ];
  896. X    FILE    *fp;
  897. X
  898. X#if defined(MAC)
  899. X    {
  900. X        long nul = 0L ;
  901. X        Str255 volName ;
  902. X        /*
  903. X         * We should try and get this data from a rsrc, in the profile file
  904. X         * the user double-clicked... This data should be saved with the
  905. X         * save file in the resource fork, AND be saveable in "stationery"
  906. X         */
  907. X        GetVol ( volName , & theDirs . dataRefNum ) ;
  908. X        GetWDInfo ( theDirs . dataRefNum , & theDirs . dataRefNum , & theDirs .
  909. X            dataDirID , & nul ) ;
  910. X        if ( volName [ 0 ] > 31 ) volName [ 0 ] = 31 ;
  911. X        for ( nul = 1 ; nul <= volName [ 0 ] ; nul ++ ) {
  912. X            if ( volName [ nul ] == ':' ) {
  913. X                volName [ nul ] = 0 ;
  914. X                volName [ 0 ] = nul - 1 ;
  915. X                break ;
  916. X            }
  917. X        }
  918. X        BlockMove ( volName , theDirs . dataName , 32L ) ;
  919. X    }
  920. X#endif /* MAC */
  921. X
  922. X    if (!(fp = fopen_config_file(filename))) return;
  923. X
  924. X#ifdef MICRO
  925. X# ifdef MFLOPPY
  926. X#  ifndef AMIGA
  927. X    tmp_ramdisk[0] = 0;
  928. X#  endif
  929. X# endif
  930. X    tmp_levels[0] = 0;
  931. X#endif
  932. X
  933. X    while (fgets(buf, BUFSZ, fp)) {
  934. X        if (!parse_config_line(fp, buf, tmp_ramdisk, tmp_levels)) {
  935. X            raw_printf("Bad option line:  \"%s\"", buf);
  936. X            wait_synch();
  937. X        }
  938. X    }
  939. X    (void) fclose(fp);
  940. X
  941. X#ifdef MICRO
  942. X# ifdef MFLOPPY
  943. X    Strcpy(permbones, tmp_levels);
  944. X#  ifndef AMIGA
  945. X    if (tmp_ramdisk[0]) {
  946. X        Strcpy(levels, tmp_ramdisk);
  947. X        if (strcmp(permbones, levels))        /* if not identical */
  948. X            ramdisk = TRUE;
  949. X    } else
  950. X#  endif /* AMIGA */
  951. X        Strcpy(levels, tmp_levels);
  952. X
  953. X    Strcpy(bones, levels);
  954. X# endif /* MFLOPPY */
  955. X#endif /* MICRO */
  956. X    return;
  957. X}
  958. X
  959. X/* ----------  END CONFIG FILE HANDLING ----------- */
  960. X
  961. X/* ----------  BEGIN SCOREBOARD CREATION ----------- */
  962. X
  963. X/* verify that we can write to the scoreboard file; if not, try to create one */
  964. Xvoid
  965. Xcheck_recordfile(dir)
  966. Xconst char *dir;
  967. X{
  968. X#if defined(UNIX) || defined(VMS)
  969. X    int fd = open(RECORD, O_RDWR, 0);
  970. X
  971. X    if (fd >= 0) {
  972. X# ifdef VMS    /* must be stream-lf to use UPDATE_RECORD_IN_PLACE */
  973. X        if (!file_is_stmlf(fd)) {
  974. X            raw_printf(    /* note: assume VMS dir has trailing punct */
  975. X          "Warning: scoreboard file %s%s is not in stream_lf format",
  976. X                (dir ? dir : "[]"), RECORD);
  977. X            wait_synch();
  978. X        }
  979. X# endif
  980. X        (void) close(fd);    /* RECORD is accessible */
  981. X    } else if ((fd = open(RECORD, O_CREAT|O_RDWR, FCMASK)) >= 0) {
  982. X        (void) close(fd);    /* RECORD newly created */
  983. X# if defined(VMS) && !defined(SECURE)
  984. X        /* Re-protect RECORD with world:read+write+execute+delete access. */
  985. X        (void) chmod(RECORD, FCMASK | 007); /* allow everyone full access */
  986. X# endif /* VMS && !SECURE */
  987. X    } else {
  988. X        raw_printf("Warning: cannot write scoreboard file %s/%s",
  989. X            (dir ? dir : "."), RECORD);
  990. X        wait_synch();
  991. X    }
  992. X#endif  /* !UNIX && !VMS */
  993. X
  994. X#ifdef MICRO
  995. X    int fd;
  996. X    char tmp[PATHLEN];
  997. X
  998. X# ifdef OS2_CODEVIEW   /* explicit path on opening for OS/2 */
  999. X    Strcpy(tmp, dir);
  1000. X    append_slash(tmp);
  1001. X    Strcat(tmp, RECORD);
  1002. X# else
  1003. X    Strcpy(tmp, RECORD);
  1004. X# endif
  1005. X
  1006. X    if ((fd = open(tmp, O_RDWR)) < 0) {
  1007. X        /* try to create empty record */
  1008. X# ifdef AZTEC_C
  1009. X        /* Aztec doesn't use the third argument */
  1010. X        if ((fd = open(tmp, O_CREAT|O_RDWR)) < 0) {
  1011. X# else
  1012. X        if ((fd = open(tmp, O_CREAT|O_RDWR, S_IREAD|S_IWRITE)) < 0) {
  1013. X# endif
  1014. X        raw_printf("Warning: cannot write record %s", tmp);
  1015. X        wait_synch();
  1016. X        } else
  1017. X        (void) close(fd);
  1018. X    } else        /* open succeeded */
  1019. X        (void) close(fd);
  1020. X#else /* MICRO */
  1021. X
  1022. X# ifdef MAC
  1023. X    int fd = macopen ( RECORD , O_RDWR | O_CREAT , TEXT_TYPE ) ;
  1024. X
  1025. X    if ( fd < 0 ) {
  1026. X        raw_printf ( "Warning: cannot write %s" , RECORD ) ;
  1027. X    } else {
  1028. X        close ( fd ) ;
  1029. X    }
  1030. X# endif /* MAC */
  1031. X
  1032. X#endif /* MICRO */
  1033. X}
  1034. X
  1035. X/* ----------  END SCOREBOARD CREATION ----------- */
  1036. X
  1037. X
  1038. X/*files.c*/
  1039. END_OF_FILE
  1040. if test 21581 -ne `wc -c <'src/files.c'`; then
  1041.     echo shar: \"'src/files.c'\" unpacked with wrong size!
  1042. fi
  1043. # end of 'src/files.c'
  1044. fi
  1045. if test -f 'src/zap.c2' -a "${1}" != "-c" ; then 
  1046.   echo shar: Will not clobber existing file \"'src/zap.c2'\"
  1047. else
  1048. echo shar: Extracting \"'src/zap.c2'\" \(32988 characters\)
  1049. sed "s/^X//" >'src/zap.c2' <<'END_OF_FILE'
  1050. Xconst char *
  1051. Xexclam(force)
  1052. Xregister int force;
  1053. X{
  1054. X    /* force == 0 occurs e.g. with sleep ray */
  1055. X    /* note that large force is usual with wands so that !! would
  1056. X        require information about hand/weapon/wand */
  1057. X    return (const char *)((force < 0) ? "?" : (force <= 4) ? "." : "!");
  1058. X}
  1059. X
  1060. Xvoid
  1061. Xhit(str,mtmp,force)
  1062. Xregister const char *str;
  1063. Xregister struct monst *mtmp;
  1064. Xregister const char *force;        /* usually either "." or "!" */
  1065. X{
  1066. X    if(!cansee(bhitpos.x,bhitpos.y) || !flags.verbose)
  1067. X        pline("%s hits it.", The(str));
  1068. X    else pline("%s hits %s%s", The(str), mon_nam(mtmp), force);
  1069. X}
  1070. X
  1071. Xvoid
  1072. Xmiss(str,mtmp)
  1073. Xregister const char *str;
  1074. Xregister struct monst *mtmp;
  1075. X{
  1076. X    pline("%s misses %s.", The(str),
  1077. X          (cansee(bhitpos.x,bhitpos.y) && flags.verbose) ?
  1078. X          mon_nam(mtmp) : "it");
  1079. X}
  1080. X
  1081. X/*
  1082. X *  Called for the following distance effects:
  1083. X *    when a weapon is thrown (weapon == THROWN_WEAPON)
  1084. X *    when an object is kicked (KICKED_WEAPON)
  1085. X *    when an IMMEDIATE wand is zapped (ZAPPED_WAND)
  1086. X *    when a light beam is flashed (FLASHED_LIGHT)
  1087. X *    for some invisible effect on a monster (INVIS_BEAM)
  1088. X *  A thrown/kicked object falls down at the end of its range or when a monster
  1089. X *  is hit.  The variable 'bhitpos' is set to the final position of the weapon
  1090. X *  thrown/zapped.  The ray of a wand may affect (by calling a provided
  1091. X *  function) several objects and monsters on its path.  The return value
  1092. X *  is the monster hit (weapon != ZAPPED_WAND), or a null monster pointer.
  1093. X *
  1094. X *  Check !u.uswallow before calling bhit().
  1095. X */
  1096. Xstruct monst *
  1097. Xbhit(ddx,ddy,range,weapon,fhitm,fhito,obj)
  1098. Xregister int ddx,ddy,range;        /* direction and range */
  1099. Xint weapon;                /* see values in hack.h */
  1100. X                    /* fns called when mon/obj hit */
  1101. Xint FDECL((*fhitm), (MONST_P, OBJ_P)),
  1102. X    FDECL((*fhito), (OBJ_P, OBJ_P));
  1103. Xstruct obj *obj;            /* object tossed/used */
  1104. X{
  1105. X    register struct monst *mtmp;
  1106. X    register uchar typ;
  1107. X    register boolean shopdoor = FALSE;
  1108. X
  1109. X    if (weapon == KICKED_WEAPON) {
  1110. X        /* object starts one square in front of player */
  1111. X        bhitpos.x = u.ux + ddx;
  1112. X        bhitpos.y = u.uy + ddy;
  1113. X        range--;
  1114. X    } else {
  1115. X        bhitpos.x = u.ux;
  1116. X        bhitpos.y = u.uy;
  1117. X    }
  1118. X
  1119. X    if (weapon == FLASHED_LIGHT) {
  1120. X        tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
  1121. X    } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
  1122. X        tmp_at(DISP_FLASH, obj_to_glyph(obj));
  1123. X    while(range-- > 0) {
  1124. X        int x,y;
  1125. X
  1126. X        bhitpos.x += ddx;
  1127. X        bhitpos.y += ddy;
  1128. X        x = bhitpos.x; y = bhitpos.y;
  1129. X
  1130. X        if(!isok(x, y)) {
  1131. X            bhitpos.x -= ddx;
  1132. X            bhitpos.y -= ddy;
  1133. X            break;
  1134. X        }
  1135. X        if(obj->otyp == PICK_AXE && inside_shop(x, y) &&
  1136. X                           shkcatch(obj, x, y)) {
  1137. X            tmp_at(DISP_END, 0);
  1138. X            return(m_at(x, y));
  1139. X        }
  1140. X
  1141. X        typ = levl[bhitpos.x][bhitpos.y].typ;
  1142. X
  1143. X        if (weapon == ZAPPED_WAND && find_drawbridge(&x,&y))
  1144. X            switch (obj->otyp) {
  1145. X            case WAN_OPENING:
  1146. X            case SPE_KNOCK:
  1147. X                if (is_db_wall(bhitpos.x, bhitpos.y)) {
  1148. X                if (cansee(x,y) || cansee(bhitpos.x,bhitpos.y))
  1149. X                    makeknown(obj->otyp);
  1150. X                open_drawbridge(x,y);
  1151. X                }
  1152. X                break;
  1153. X            case WAN_LOCKING:
  1154. X            case SPE_WIZARD_LOCK:
  1155. X                if ((cansee(x,y) || cansee(bhitpos.x, bhitpos.y))
  1156. X                && levl[x][y].typ == DRAWBRIDGE_DOWN)
  1157. X                makeknown(obj->otyp);
  1158. X                close_drawbridge(x,y);
  1159. X                break;
  1160. X            case WAN_STRIKING:
  1161. X            case SPE_FORCE_BOLT:
  1162. X                if (typ != DRAWBRIDGE_UP)
  1163. X                destroy_drawbridge(x,y);
  1164. X                makeknown(obj->otyp);
  1165. X                break;
  1166. X            }
  1167. X
  1168. X        if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
  1169. X            if(weapon != ZAPPED_WAND) {
  1170. X                if(weapon != INVIS_BEAM) tmp_at(DISP_END, 0);
  1171. X                return(mtmp);
  1172. X            }
  1173. X            (*fhitm)(mtmp, obj);
  1174. X            range -= 3;
  1175. X        }
  1176. X        if(fhito) {
  1177. X            if(bhitpile(obj,fhito,bhitpos.x,bhitpos.y))
  1178. X            range--;
  1179. X        } else if(weapon == KICKED_WEAPON && 
  1180. X                  ((obj->otyp == GOLD_PIECE && 
  1181. X                     OBJ_AT(bhitpos.x, bhitpos.y)) ||
  1182. X                        down_gate(bhitpos.x, bhitpos.y) != -1)) {
  1183. X            tmp_at(DISP_END, 0);
  1184. X            return (struct monst *)0;
  1185. X        }
  1186. X        if(weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
  1187. X            switch (obj->otyp) {
  1188. X            case WAN_OPENING:
  1189. X            case WAN_LOCKING:
  1190. X            case WAN_STRIKING:
  1191. X            case SPE_KNOCK:
  1192. X            case SPE_WIZARD_LOCK:
  1193. X            case SPE_FORCE_BOLT:
  1194. X            if (doorlock(obj, bhitpos.x, bhitpos.y)) {
  1195. X                if (cansee(bhitpos.x, bhitpos.y) ||
  1196. X                (obj->otyp == WAN_STRIKING))
  1197. X                makeknown(obj->otyp);
  1198. X                if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
  1199. X                && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
  1200. X                shopdoor = TRUE;
  1201. X                }
  1202. X            }
  1203. X            break;
  1204. X            }
  1205. X        }
  1206. X        if(!ZAP_POS(typ) || closed_door(bhitpos.x, bhitpos.y)) {
  1207. X            bhitpos.x -= ddx;
  1208. X            bhitpos.y -= ddy;
  1209. X            break;
  1210. X        }
  1211. X        if(weapon != ZAPPED_WAND && weapon != INVIS_BEAM) {
  1212. X            tmp_at(bhitpos.x, bhitpos.y);
  1213. X            delay_output();
  1214. X            /* kicked objects fall in pools */
  1215. X            if((weapon == KICKED_WEAPON) &&
  1216. X               is_pool(bhitpos.x, bhitpos.y))
  1217. X                break;
  1218. X#ifdef SINKS
  1219. X            if(IS_SINK(typ) && weapon != FLASHED_LIGHT)
  1220. X                break;    /* physical objects fall onto sink */
  1221. X#endif
  1222. X        }
  1223. X    }
  1224. X
  1225. X    if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) tmp_at(DISP_END, 0);
  1226. X
  1227. X    if(shopdoor)
  1228. X        pay_for_damage("destroy");
  1229. X
  1230. X    return (struct monst *)0;
  1231. X}
  1232. X
  1233. Xstruct monst *
  1234. Xboomhit(dx, dy)
  1235. Xint dx, dy;
  1236. X{
  1237. X    register int i, ct;
  1238. X    int boom = S_boomleft;    /* showsym[] index  */
  1239. X    struct monst *mtmp;
  1240. X
  1241. X    bhitpos.x = u.ux;
  1242. X    bhitpos.y = u.uy;
  1243. X
  1244. X    for(i=0; i<8; i++) if(xdir[i] == dx && ydir[i] == dy) break;
  1245. X    tmp_at(DISP_FLASH, cmap_to_glyph(boom));
  1246. X    for(ct=0; ct<10; ct++) {
  1247. X        if(i == 8) i = 0;
  1248. X        boom = (boom == S_boomleft) ? S_boomright : S_boomleft;
  1249. X        tmp_at(DISP_CHANGE, cmap_to_glyph(boom));/* change glyph */
  1250. X        dx = xdir[i];
  1251. X        dy = ydir[i];
  1252. X        bhitpos.x += dx;
  1253. X        bhitpos.y += dy;
  1254. X        if(MON_AT(bhitpos.x, bhitpos.y)) {
  1255. X            mtmp = m_at(bhitpos.x,bhitpos.y);
  1256. X            m_respond(mtmp);
  1257. X            tmp_at(DISP_END, 0);
  1258. X            return(mtmp);
  1259. X        }
  1260. X        if(!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ) ||
  1261. X           closed_door(bhitpos.x, bhitpos.y)) {
  1262. X            bhitpos.x -= dx;
  1263. X            bhitpos.y -= dy;
  1264. X            break;
  1265. X        }
  1266. X        if(bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
  1267. X            if(Fumbling || rn2(20) >= ACURR(A_DEX)) {
  1268. X                /* we hit ourselves */
  1269. X                (void) thitu(10, rnd(10), (struct obj *)0,
  1270. X                    "boomerang");
  1271. X                break;
  1272. X            } else {    /* we catch it */
  1273. X                tmp_at(DISP_END, 0);
  1274. X                pline("Skillfully, you catch the boomerang.");
  1275. X                return(&youmonst);
  1276. X            }
  1277. X        }
  1278. X        tmp_at(bhitpos.x, bhitpos.y);
  1279. X        delay_output();
  1280. X        if(ct % 5 != 0) i++;
  1281. X#ifdef SINKS
  1282. X        if(IS_SINK(levl[bhitpos.x][bhitpos.y].typ))
  1283. X            break;    /* boomerang falls on sink */
  1284. X#endif
  1285. X    }
  1286. X    tmp_at(DISP_END, 0);    /* do not leave last symbol */
  1287. X    return (struct monst *)0;
  1288. X}
  1289. X
  1290. Xstatic int
  1291. Xzhit(mon, type, nd)            /* returns damage to mon */
  1292. Xregister struct monst *mon;
  1293. Xregister int type, nd;
  1294. X{
  1295. X    register int tmp = 0;
  1296. X    register int abstype = abs(type) % 10;
  1297. X
  1298. X    switch(abstype) {
  1299. X    case ZT_MAGIC_MISSILE:
  1300. X        tmp = d(nd,6);
  1301. X        break;
  1302. X    case ZT_FIRE:
  1303. X        if(resists_fire(mon->data)) {
  1304. X            shieldeff(mon->mx, mon->my);
  1305. X            break;
  1306. X        }
  1307. X        tmp = d(nd,6);
  1308. X        if(resists_cold(mon->data)) tmp += 7;
  1309. X        break;
  1310. X    case ZT_COLD:
  1311. X        if(resists_cold(mon->data)) {
  1312. X            shieldeff(mon->mx, mon->my);
  1313. X            break;
  1314. X        }
  1315. X        tmp = d(nd,6);
  1316. X        if(resists_fire(mon->data)) tmp += d(nd, 3);
  1317. X        break;
  1318. X    case ZT_SLEEP:
  1319. X        tmp = 0;
  1320. X        if(resists_sleep(mon->data) ||
  1321. X           resist(mon, (type == ZT_WAND(ZT_SLEEP)) ?
  1322. X              WAND_CLASS : '\0', 0, NOTELL))
  1323. X            shieldeff(mon->mx, mon->my);
  1324. X        else if (mon->mcanmove) {
  1325. X            int tmp2 = d(nd,25);
  1326. X            mon->mcanmove = 0;
  1327. X            if ((unsigned)mon->mfrozen + tmp2 > 127) 
  1328. X                mon->mfrozen = 127;
  1329. X            else mon->mfrozen += tmp2;
  1330. X        }
  1331. X        break;
  1332. X    case ZT_DEATH:        /* death/disintegration */
  1333. X        if(abs(type) != ZT_BREATH(ZT_DEATH)) {    /* death */
  1334. X            if(mon->data == &mons[PM_DEATH]) {
  1335. X            mon->mhpmax += mon->mhpmax/2;
  1336. X            mon->mhp = mon->mhpmax;
  1337. X            tmp = 0;
  1338. X            break;
  1339. X            }
  1340. X            if(is_undead(mon->data)) {
  1341. X            shieldeff(mon->mx, mon->my);
  1342. X            break;
  1343. X            }
  1344. X            type = -1; /* so they don't get saving throws */
  1345. X        } else {
  1346. X            if (resists_disint(mon->data)) {
  1347. X            shieldeff(mon->mx, mon->my);
  1348. X            break;
  1349. X            } else {
  1350. X            tmp = MAGIC_COOKIE;
  1351. X            break;
  1352. X            }
  1353. X        }
  1354. X        tmp = mon->mhp+1;
  1355. X        break;
  1356. X    case ZT_LIGHTNING:
  1357. X        if(resists_elec(mon->data)) {
  1358. X            shieldeff(mon->mx, mon->my);
  1359. X            break;
  1360. X        }
  1361. X        tmp = d(nd,6);
  1362. X        if (haseyes(mon->data)) {
  1363. X            register unsigned rnd_tmp = rnd(50);
  1364. X            mon->mcansee = 0;
  1365. X            if((mon->mblinded + rnd_tmp) > 127)
  1366. X                mon->mblinded = 127;
  1367. X            else mon->mblinded += rnd_tmp;
  1368. X        }
  1369. X        break;
  1370. X    case ZT_POISON_GAS:
  1371. X        if(resists_poison(mon->data)) {
  1372. X            shieldeff(mon->mx, mon->my);
  1373. X            break;
  1374. X        }
  1375. X        tmp = d(nd,6);
  1376. X        break;
  1377. X    case ZT_ACID:
  1378. X        if(resists_acid(mon->data)) {
  1379. X            shieldeff(mon->mx, mon->my);
  1380. X            break;
  1381. X        }
  1382. X        tmp = d(nd,6);
  1383. X        break;
  1384. X    }
  1385. X#ifdef MULDGN
  1386. X    if(pl_character[0] == 'K' && type >= 10 && type <= 19 &&
  1387. X       u.uhave.questart) tmp *= 2;
  1388. X#endif
  1389. X    if (type >= 0)
  1390. X        if (resist(mon, (type < ZT_SPELL(0)) ? WAND_CLASS : '\0',
  1391. X               0, NOTELL)) tmp /= 2;
  1392. X    mon->mhp -= tmp;
  1393. X    return(tmp);
  1394. X}
  1395. X
  1396. X/*
  1397. X * burn scrolls and spell books on floor at position x,y
  1398. X * return the number of scrolls and spell books burned
  1399. X */
  1400. Xstatic int
  1401. Xburn_floor_paper(x, y)
  1402. Xint x, y;
  1403. X{
  1404. X    register struct obj *obj, *obj2;
  1405. X    register int cnt = 0;
  1406. X    register long i, scrquan;
  1407. X
  1408. X    for(obj = level.objects[x][y]; obj; obj = obj2) {
  1409. X        obj2 = obj->nexthere;
  1410. X        /* Bug fix - KAA */
  1411. X        if(obj->oclass == SCROLL_CLASS
  1412. X            || obj->oclass == SPBOOK_CLASS) {
  1413. X        if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
  1414. X            continue;
  1415. X        scrquan = obj->quan;
  1416. X        for(i = 1; i <= scrquan ; i++)
  1417. X            if(!rn2(3))  {
  1418. X            cnt++;
  1419. X            /* not useupf(), which charges */
  1420. X            if (obj->quan > 1L) obj->quan--;
  1421. X            else delobj(obj);
  1422. X            }
  1423. X        }
  1424. X    }
  1425. X    return(cnt);
  1426. X}
  1427. X
  1428. X/* type == 0 to 9     : you shooting a wand */
  1429. X/* type == 10 to 19   : you casting a spell */
  1430. X/* type == 20 to 29   : you breathing as a monster */
  1431. X/* type == -10 to -19   : monster casting spell */
  1432. X/* type == -20 to -29 : monster breathing at you */
  1433. X/* type == -30 to -39 : monster shooting a wand (MUSE only) */
  1434. X/* called with dx = dy = 0 with vertical bolts */
  1435. Xvoid
  1436. Xbuzz(type,nd,sx,sy,dx,dy)
  1437. Xregister int type, nd;
  1438. Xregister xchar sx,sy;
  1439. Xregister int dx,dy;
  1440. X{
  1441. X    int range, abstype = abs(type) % 10;
  1442. X    struct rm *lev;
  1443. X    register xchar lsx, lsy;
  1444. X    struct monst *mon;
  1445. X    boolean bodyhit = FALSE, shopdamage = FALSE;
  1446. X#ifdef MUSE
  1447. X    register const char *fltxt = fl[(type <= -30) ? abstype : abs(type)];
  1448. X#else
  1449. X    register const char *fltxt = fl[abs(type)];
  1450. X#endif
  1451. X    if(u.uswallow) {
  1452. X    register int tmp;
  1453. X
  1454. X    if(type < 0) return;
  1455. X    tmp = zhit(u.ustuck, type, nd);
  1456. X    if(!u.ustuck)    u.uswallow = 0;
  1457. X    else    pline("%s rips into %s%s",
  1458. X              The(fltxt), mon_nam(u.ustuck), exclam(tmp));
  1459. X    /* Using disintegration from the inside only makes a hole... */
  1460. X    if (tmp == MAGIC_COOKIE)
  1461. X        u.ustuck->mhp = 0;
  1462. X    if (u.ustuck->mhp < 1)
  1463. X        killed(u.ustuck);
  1464. X    return;
  1465. X    }
  1466. X    if(type < 0) newsym(u.ux,u.uy);
  1467. X    range = rn1(7,7);
  1468. X    if(dx == 0 && dy == 0) range = 1;
  1469. X    tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, abstype));
  1470. X    while(range-- > 0) {
  1471. X    lsx = sx; sx += dx;
  1472. X    lsy = sy; sy += dy;
  1473. X    if(isok(sx,sy) && (lev = &levl[sx][sy])->typ) {
  1474. X        if(cansee(sx,sy)) {
  1475. X        if(ZAP_POS(lev->typ) || cansee(lsx,lsy))
  1476. X            tmp_at(sx,sy);
  1477. X        delay_output(); /* wait a little */
  1478. X        }
  1479. X    } else
  1480. X        goto make_bounce;
  1481. X
  1482. X    if (type != ZT_SPELL(ZT_FIRE))
  1483. X        /* Fireballs only damage when they explode */
  1484. X        range += zap_over_floor(sx, sy, type, &shopdamage);
  1485. X    if ((mon = m_at(sx, sy)) != 0) {
  1486. X        if (type == ZT_SPELL(ZT_FIRE)) break;
  1487. X        if (type >= 0) mon->data->mflags3 &= ~M3_WAITMASK;
  1488. X        if (rnd(20) < 18 + find_mac(mon)) {
  1489. X#ifdef MUSE
  1490. X        struct obj *oshld = which_armor(mon, W_ARMS);
  1491. X
  1492. X        if (oshld && oshld->otyp == SHIELD_OF_REFLECTION) {
  1493. X            if(cansee(mon->mx,mon->my)) {
  1494. X            hit(fltxt, mon, exclam(0));
  1495. X            pline("But it reflects from %s shield!",
  1496. X                  s_suffix(mon_nam(mon)));
  1497. X            makeknown(SHIELD_OF_REFLECTION);
  1498. X            shieldeff(sx, sy);
  1499. X            }
  1500. X
  1501. X            dx = -dx;
  1502. X            dy = -dy;
  1503. X        } else
  1504. X#endif
  1505. X        {
  1506. X            register int tmp = zhit(mon, type, nd);
  1507. X
  1508. X            if (is_rider(mon->data) && type == ZT_BREATH(ZT_DEATH)) {
  1509. X                if(cansee(mon->mx, mon->my)) {
  1510. X                hit(fltxt, mon, exclam(tmp));
  1511. X                pline("%s disintegrates.", Monnam(mon));
  1512. X                if(Blind)
  1513. X               You("sense the fragments of %s body reassembling!",
  1514. X                     s_suffix(mon_nam(mon)));
  1515. X                else
  1516. X               pline("%s body fragments reassemble before your %s!",
  1517. X                     s_suffix(Monnam(mon)),
  1518. X                     makeplural(body_part(EYE)));
  1519. X                    pline("%s resurrects!", Monnam(mon));
  1520. X            }
  1521. X                mon->mhp = mon->mhpmax;
  1522. X            break; /* Out of while loop */
  1523. X            }
  1524. X            if(mon->data == &mons[PM_DEATH] &&
  1525. X                            abs(type)%10 == ZT_DEATH) {
  1526. X                if(cansee(mon->mx,mon->my)) {
  1527. X                hit(fltxt, mon, exclam(tmp));
  1528. X                    pline("Death absorbs the deadly %s!",
  1529. X                        type == ZT_BREATH(ZT_DEATH) ? 
  1530. X                        "blast" : "ray");
  1531. X                    pline("It seems even stronger than before.");
  1532. X                }
  1533. X                break; /* Out of while loop */
  1534. X            }
  1535. X            if (tmp == MAGIC_COOKIE) { /* disintegration */
  1536. X            struct obj *otmp, *otmp2;
  1537. X            pline("%s is disintegrated!", Monnam(mon));
  1538. X            mon->mgold = 0;
  1539. X            otmp = mon->minvent;
  1540. X            while(otmp) {
  1541. X#ifdef MULDGN
  1542. X                if (is_quest_artifact(otmp))
  1543. X                otmp = otmp->nobj;
  1544. X                else {
  1545. X#endif
  1546. X                otmp2 = otmp;
  1547. X                if (otmp == mon->minvent)
  1548. X                    mon->minvent = otmp->nobj;
  1549. X                otmp = otmp->nobj;
  1550. X                obfree(otmp2, (struct obj *)0);
  1551. X#ifdef MULDGN
  1552. X                }
  1553. X#endif
  1554. X            }
  1555. X            if (type < 0)
  1556. X                monkilled(mon, (char *)0, AD_RBRE);
  1557. X            else
  1558. X                xkilled(mon, 2);
  1559. X            } else if(mon->mhp < 1) {
  1560. X            if(type < 0)
  1561. X                monkilled(mon, fltxt, AD_RBRE);
  1562. X            else
  1563. X                killed(mon);
  1564. X            } else
  1565. X            hit(fltxt, mon, exclam(tmp));
  1566. X        }
  1567. X        range -= 2;
  1568. X        } else
  1569. X        miss(fltxt,mon);
  1570. X    } else if(sx == u.ux && sy == u.uy) {
  1571. X        nomul(0);
  1572. X        if(rnd(20) < 18+u.uac) {
  1573. X        register int dam = 0;
  1574. X        range -= 2;
  1575. X        pline("%s hits you!", The(fltxt));
  1576. X        if (Reflecting) {
  1577. X            if (!Blind) {
  1578. X            if(Reflecting & WORN_AMUL)
  1579. X                makeknown(AMULET_OF_REFLECTION);
  1580. X            else
  1581. X                makeknown(SHIELD_OF_REFLECTION);
  1582. X            pline("But it reflects from your %s!",
  1583. X                  (Reflecting & W_AMUL) ? "amulet" : "shield");
  1584. X            } else
  1585. X            pline("For some reason you are not affected.");
  1586. X            dx = -dx;
  1587. X            dy = -dy;
  1588. X            shieldeff(sx, sy);
  1589. X        }
  1590. X        else switch(abstype) {
  1591. X        case ZT_MAGIC_MISSILE:
  1592. X            if(Antimagic) {
  1593. X            shieldeff(sx, sy);
  1594. X            pline("The missiles bounce off!");
  1595. X            } else {
  1596. X                dam = d(nd,6);
  1597. X            exercise(A_STR, FALSE);
  1598. X            }
  1599. X            break;
  1600. X        case ZT_FIRE:
  1601. X            if(Fire_resistance) {
  1602. X            shieldeff(sx, sy);
  1603. X            You("don't feel hot!");
  1604. X#ifdef POLYSELF
  1605. X            ugolemeffects(AD_FIRE, d(nd, 6));
  1606. X#endif
  1607. X            } else dam = d(nd, 6);
  1608. X            while (1) {
  1609. X            switch(rn2(5)) {
  1610. X            case 0:
  1611. X                if (!rust_dmg(uarmh, "leather helmet", 0, FALSE))
  1612. X                continue;
  1613. X                break;
  1614. X            case 1:
  1615. X                bodyhit = TRUE;
  1616. X                if (uarmc) break;
  1617. X                if (uarm)
  1618. X                (void)(rust_dmg(uarm, xname(uarm), 0, FALSE));
  1619. X                break;
  1620. X            case 2:
  1621. X                if (!rust_dmg(uarms, "wooden shield", 0, FALSE))
  1622. X                continue;
  1623. X                break;
  1624. X            case 3:
  1625. X                if (!rust_dmg(uarmg, "gloves", 0, FALSE)) continue;
  1626. X                break;
  1627. X            case 4:
  1628. X                if (!rust_dmg(uarmf, "boots", 0, FALSE)) continue;
  1629. X                break;
  1630. X            }
  1631. X            break; /* Out of while loop */
  1632. X            }
  1633. X            if(!rn2(3) && bodyhit)
  1634. X            destroy_item(POTION_CLASS, AD_FIRE);
  1635. X            if(!rn2(3) && bodyhit)
  1636. X            destroy_item(SCROLL_CLASS, AD_FIRE);
  1637. X            if(!rn2(5) && bodyhit)
  1638. X            destroy_item(SPBOOK_CLASS, AD_FIRE);
  1639. X            break;
  1640. X        case ZT_COLD:
  1641. X            if(Cold_resistance) {
  1642. X            shieldeff(sx, sy);
  1643. X            You("don't feel cold.");
  1644. X#ifdef POLYSELF
  1645. X            ugolemeffects(AD_COLD, d(nd, 6));
  1646. X#endif
  1647. X            } else
  1648. X            dam = d(nd, 6);
  1649. X            if(!rn2(3))
  1650. X            destroy_item(POTION_CLASS, AD_COLD);
  1651. X            break;
  1652. X        case ZT_SLEEP:
  1653. X            if(Sleep_resistance) {
  1654. X            shieldeff(u.ux, u.uy);
  1655. X            You("don't feel sleepy.");
  1656. X            } else {
  1657. X            /* have to do this _before_ we reset multi */
  1658. X            stop_occupation();
  1659. X            nomul(-d(nd,25)); /* sleep ray */
  1660. X            u.usleep = 1;
  1661. X            nomovemsg = "You wake up.";
  1662. X            }
  1663. X            break;
  1664. X        case ZT_DEATH:
  1665. X            if(abs(type) == ZT_BREATH(ZT_DEATH)) {
  1666. X            if (Disint_resistance) {
  1667. X                You("are not disintegrated.");
  1668. X                break;
  1669. X            } else if(uarms) {
  1670. X                (void) destroy_arm(uarms);
  1671. X                break;
  1672. X            } else if (uarm)  {
  1673. X                (void) destroy_arm(uarm);
  1674. X                break;
  1675. X            }
  1676. X            }
  1677. X#ifdef POLYSELF
  1678. X            else if(is_undead(uasmon)) {
  1679. X            shieldeff(sx, sy);
  1680. X            You("seem unaffected.");
  1681. X            break;
  1682. X            }
  1683. X#endif
  1684. X            else if(Antimagic) {
  1685. X            shieldeff(sx, sy);
  1686. X            You("aren't affected.");
  1687. X            } else
  1688. X            u.uhp = -1;
  1689. X            break;
  1690. X        case ZT_LIGHTNING:
  1691. X            if (Shock_resistance) {
  1692. X            shieldeff(sx, sy);
  1693. X            You("aren't affected.");
  1694. X#ifdef POLYSELF
  1695. X            ugolemeffects(AD_ELEC, d(nd, 6));
  1696. X#endif
  1697. X            } else {
  1698. X            dam = d(nd, 6);
  1699. X            exercise(A_CON, FALSE);
  1700. X            }
  1701. X            if(!rn2(3))
  1702. X            destroy_item(WAND_CLASS, AD_ELEC);
  1703. X            if(!rn2(3))
  1704. X            destroy_item(RING_CLASS, AD_ELEC);
  1705. X            break;
  1706. X        case ZT_POISON_GAS:
  1707. X            poisoned("blast", A_DEX, "poisoned blast", 15);
  1708. X            break;
  1709. X        case ZT_ACID:
  1710. X#ifdef POLYSELF
  1711. X            if (resists_acid(uasmon))
  1712. X            dam = 0;
  1713. X            else
  1714. X#endif
  1715. X            {
  1716. X                pline("The acid burns!");
  1717. X                dam = d(nd,6);
  1718. X                exercise(A_STR, FALSE);
  1719. X            }
  1720. X            if(!rn2(6)) erode_weapon(TRUE);
  1721. X            if(!rn2(6)) erode_armor(TRUE);
  1722. X            break;
  1723. X        }
  1724. X        if(Half_spell_damage && dam &&
  1725. X           type < 0 && (type > -20 || type < -29)) /* !Breath */
  1726. X            dam = (dam+1) / 2;
  1727. X        losehp(dam, fltxt, KILLED_BY_AN);
  1728. X        } else pline("%s whizzes by you!", The(fltxt));
  1729. X        if (abstype == ZT_LIGHTNING && !Blind) {
  1730. X        You("are blinded by the flash!");
  1731. X        make_blinded((long)d(nd,50),FALSE);
  1732. X        }
  1733. X        stop_occupation();
  1734. X        nomul(0);
  1735. X    }
  1736. X    if(!ZAP_POS(lev->typ) || (closed_door(sx, sy) && (range >= 0))) {
  1737. X        int bounce;
  1738. X        uchar rmn;
  1739. X
  1740. X    make_bounce:
  1741. X        if (type == ZT_SPELL(ZT_FIRE)) {
  1742. X        sx = lsx;
  1743. X        sy = lsy;
  1744. X        break; /* fireballs explode before the wall */
  1745. X        }
  1746. X        bounce = 0;
  1747. X        range--;
  1748. X        if(range && cansee(lsx,lsy))
  1749. X        pline("%s bounces!", The(fltxt));
  1750. X        if(!dx || !dy || !rn2(20)) {
  1751. X        dx = -dx;
  1752. X        dy = -dy;
  1753. X        } else {
  1754. X        if(isok(sx,lsy) && ZAP_POS(rmn = levl[sx][lsy].typ) &&
  1755. X           (IS_ROOM(rmn) || (isok(sx+dx,lsy) &&
  1756. X                     ZAP_POS(levl[sx+dx][lsy].typ))))
  1757. X            bounce = 1;
  1758. X        if(isok(lsx,sy) && ZAP_POS(rmn = levl[lsx][sy].typ) &&
  1759. X           (IS_ROOM(rmn) || (isok(lsx,sy+dy) &&
  1760. X                     ZAP_POS(levl[lsx][sy+dy].typ))))
  1761. X            if(!bounce || rn2(2))
  1762. X            bounce = 2;
  1763. X
  1764. X        switch(bounce) {
  1765. X        case 0: dx = -dx; /* fall into... */
  1766. X        case 1: dy = -dy; break;
  1767. X        case 2: dx = -dx; break;
  1768. X        }
  1769. X        tmp_at(DISP_CHANGE, zapdir_to_glyph(dx,dy,abstype));
  1770. X        }
  1771. X    }
  1772. X    }
  1773. X    tmp_at(DISP_END,0);
  1774. X    if (type == ZT_SPELL(ZT_FIRE))
  1775. X    explode(sx, sy, type, d(12,6), 0);
  1776. X    if (shopdamage)
  1777. X    pay_for_damage(abstype == ZT_FIRE ?  "burn away" :
  1778. X               abstype == ZT_COLD ?  "shatter" :
  1779. X                  abstype == ZT_DEATH ? "disintegrate" : "destroy");
  1780. X}
  1781. X
  1782. X/* Burn floor scrolls, evaporate pools, etc...  in a single square.  Used
  1783. X * both for normal bolts of fire, cold, etc... and for fireballs.
  1784. X * Sets shopdamage to TRUE if a shop door is destroyed, and returns the 
  1785. X * amount by which range is reduced (the latter is just ignored by fireballs)
  1786. X */
  1787. Xint
  1788. Xzap_over_floor(x, y, type, shopdamage)
  1789. Xxchar x, y;
  1790. Xint type;
  1791. Xboolean *shopdamage;
  1792. X{
  1793. X    struct monst *mon;
  1794. X    int abstype = abs(type) % 10;
  1795. X    struct rm *lev = &levl[x][y];
  1796. X    int rangemod = 0;
  1797. X
  1798. X    if(abstype == ZT_FIRE) {
  1799. X        if(is_ice(x, y)) {
  1800. X        if (lev->typ == DRAWBRIDGE_UP)
  1801. X            lev->drawbridgemask &= ~DB_ICE;    /* revert to DB_MOAT */
  1802. X        else {    /* lev->typ == ICE */
  1803. X#ifdef STUPID
  1804. X            if (lev->icedpool == ICED_POOL) lev->typ = POOL;
  1805. X            else lev->typ = MOAT;
  1806. X#else
  1807. X            lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT);
  1808. X#endif
  1809. X            lev->icedpool = 0;
  1810. X        }
  1811. X        newsym(x,y);
  1812. X        Norep("The ice crackles and melts.");
  1813. X        if (x == u.ux && y == u.uy)
  1814. X            spoteffects();    /* possibly drown */
  1815. X        } else if(is_pool(x,y)) {
  1816. X        const char *msgtxt = "You hear a hissing sound.";
  1817. X        if(lev->typ != POOL) {    /* MOAT or DRAWBRIDGE_UP */
  1818. X            if (cansee(x,y)) msgtxt = "Some water evaporates.";
  1819. X        } else {
  1820. X            register struct trap *ttmp;
  1821. X
  1822. X            rangemod -= 3;
  1823. X            lev->typ = ROOM;
  1824. X            ttmp = maketrap(x, y, PIT);
  1825. X            ttmp->tseen = 1;
  1826. X            if (cansee(x,y)) msgtxt = "The water evaporates.";
  1827. X        }
  1828. X        Norep(msgtxt);
  1829. X        if (lev->typ == ROOM) newsym(x,y);
  1830. X        }
  1831. X    }
  1832. X    else if(abstype == ZT_COLD && (is_pool(x,y) || is_lava(x,y))) {
  1833. X        boolean lava = is_lava(x,y);
  1834. X        boolean moat = (!lava && (lev->typ != POOL) &&
  1835. X                (lev->typ != WATER) &&
  1836. X                !Is_medusa_level(&u.uz) &&
  1837. X                !Is_waterlevel(&u.uz));
  1838. X
  1839. X        if (lev->typ == WATER) {
  1840. X            /* For now, don't let WATER freeze. */
  1841. X            if (cansee(x,y))
  1842. X            pline("The water freezes for a moment.");
  1843. X            else
  1844. X            You("hear a soft crackling sound");
  1845. X            rangemod -= 1000;    /* stop */
  1846. X        } else {
  1847. X            rangemod -= 3;
  1848. X            if (lev->typ == DRAWBRIDGE_UP) {
  1849. X            lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
  1850. X            } else {
  1851. X            if (!lava)
  1852. X                lev->icedpool =
  1853. X                    (lev->typ == POOL ? ICED_POOL : ICED_MOAT);
  1854. X            lev->typ = (lava ? ROOM : ICE);
  1855. X            }
  1856. X            /*
  1857. X             * Not perfect: There could be stuff on the bottom.  If
  1858. X             * we leave it here, it'll pop to the surface which is
  1859. X             * strange, so just destroy all the objects at this location.
  1860. X             * A better solution requires major changes (as usual).
  1861. X             */
  1862. X            if(OBJ_AT(x,y))
  1863. X            delallobj(x,y);
  1864. X            if(cansee(x,y)) {
  1865. X            if(moat)
  1866. X                Norep("The moat is bridged with ice!");
  1867. X            else if(lava)
  1868. X                Norep("The lava cools and solidifies.");
  1869. X            else
  1870. X                Norep("The water freezes.");
  1871. X            newsym(x,y);
  1872. X            } else if(flags.soundok && !lava)
  1873. X            You("hear a crackling sound.");
  1874. X            if(x == u.ux && y == u.uy &&
  1875. X                   u.utrap && u.utraptype == TT_LAVA) {
  1876. X#ifdef POLYSELF
  1877. X            if (passes_walls(uasmon))
  1878. X                You("pass through the now-solid rock.");
  1879. X            else {
  1880. X#endif
  1881. X                u.utrap = rn1(50,20);
  1882. X                u.utraptype = TT_INFLOOR;
  1883. X                You("are firmly stuck in the cooling rock.");
  1884. X#ifdef POLYSELF
  1885. X            }
  1886. X#endif
  1887. X            }
  1888. X        }
  1889. X    }
  1890. X    if(closed_door(x, y)) {
  1891. X        rangemod = -1000;
  1892. X        switch(abstype) {
  1893. X        case ZT_FIRE:
  1894. X            if(type >= 0 && *in_rooms(x, y, SHOPBASE)) {
  1895. X            add_damage(x, y, 400L);
  1896. X            *shopdamage = TRUE;
  1897. X            }
  1898. X            lev->doormask = D_NODOOR;
  1899. X            unblock_point(x,y);    /* vision */
  1900. X            if(cansee(x,y)) {
  1901. X            pline("The door is consumed in flames!");
  1902. X            newsym(x,y);
  1903. X            }
  1904. X            else You("smell smoke.");
  1905. X            break;
  1906. X        case ZT_COLD:
  1907. X            if(type >= 0 && *in_rooms(x, y, SHOPBASE)) {
  1908. X            add_damage(x, y, 400L);
  1909. X            *shopdamage = TRUE;
  1910. X            }
  1911. X            lev->doormask = D_NODOOR;
  1912. X            unblock_point(x,y);    /* vision */
  1913. X            if(cansee(x,y)) {
  1914. X            pline("The door freezes and shatters!");
  1915. X            newsym(x,y);
  1916. X            }
  1917. X            else You("feel cold.");
  1918. X            break;
  1919. X        case ZT_DEATH:
  1920. X            /* death spells/wands don't disintegrate */
  1921. X            if(abs(type) != ZT_BREATH(ZT_DEATH))
  1922. X            goto def_case;
  1923. X            if(type >= 0 && *in_rooms(x, y, SHOPBASE)) {
  1924. X            add_damage(x, y, 400L);
  1925. X            *shopdamage = TRUE;
  1926. X            }
  1927. X            lev->doormask = D_NODOOR;
  1928. X            unblock_point(x,y);    /* vision */
  1929. X            if(cansee(x,y)) {
  1930. X            pline("The door disintegrates!");
  1931. X            newsym(x,y);
  1932. X            }
  1933. X            else if(flags.soundok)
  1934. X            You("hear a crashing sound.");
  1935. X            break;
  1936. X        case ZT_LIGHTNING:
  1937. X            if(type >= 0 && *in_rooms(x, y, SHOPBASE)) {
  1938. X            add_damage(x, y, 400L);
  1939. X            *shopdamage = TRUE;
  1940. X            }
  1941. X            lev->doormask = D_BROKEN;
  1942. X            unblock_point(x,y);    /* vision */
  1943. X            if(cansee(x,y)) {
  1944. X            pline("The door splinters!");
  1945. X            newsym(x,y);
  1946. X            }
  1947. X            else if(flags.soundok)
  1948. X            You("hear a crackling sound.");
  1949. X            break;
  1950. X        default:
  1951. X        def_case:
  1952. X            if(cansee(x,y)) {
  1953. X            pline("The door absorbs %s %s!",
  1954. X                  (type < 0) ? "the" : "your",
  1955. X                  abs(type) < ZT_SPELL(0) ? "bolt" :
  1956. X                  abs(type) < ZT_BREATH(0) ? "spell" :
  1957. X                  "blast");
  1958. X            } else You("feel vibrations.");
  1959. X            break;
  1960. X        }
  1961. X    }
  1962. X    if(OBJ_AT(x, y) && abstype == ZT_FIRE)
  1963. X        if(burn_floor_paper(x,y) && cansee(x,y))  {
  1964. X            newsym(x,y);
  1965. X            if(!Blind)
  1966. X            You("see a puff of smoke.");
  1967. X        }
  1968. X    if ((mon = m_at(x,y)) != 0) {
  1969. X        /* Cannot use wakeup() which also angers the monster */
  1970. X        mon->msleep = 0;
  1971. X        if(mon->m_ap_type) seemimic(mon);
  1972. X        if(type >= 0) {
  1973. X            setmangry(mon);
  1974. X            if(mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
  1975. X            ghod_hitsu(mon);
  1976. X            if(mon->isshk && !*u.ushops)
  1977. X            hot_pursuit(mon);
  1978. X        }
  1979. X    }
  1980. X    return rangemod;
  1981. X}
  1982. X
  1983. Xvoid
  1984. Xrloco(obj)
  1985. Xregister struct obj *obj;
  1986. X{
  1987. X    register xchar tx, ty, otx, oty;
  1988. X
  1989. X    otx = obj->ox;
  1990. X    oty = obj->oy;
  1991. X    do {
  1992. X        tx = rn1(COLNO-3,2);
  1993. X        ty = rn2(ROWNO);
  1994. X    } while(!goodpos(tx,ty,(struct monst *)0, (struct permonst *)0));
  1995. X    freeobj(obj);
  1996. X    if (flooreffects(obj, tx, ty, "fall"))
  1997. X         return;
  1998. X    if(costly_spot(otx, oty) && (!costly_spot(tx, ty) ||
  1999. X                     !index(in_rooms(tx, ty, 0),
  2000. X                        *in_rooms(otx, oty, 0)))) {
  2001. X        if(costly_spot(u.ux, u.uy) &&
  2002. X                index(u.urooms, *in_rooms(otx, oty, 0)))
  2003. X            addtobill(obj, FALSE, FALSE, FALSE);
  2004. X        else (void)stolen_value(obj, otx, oty, FALSE, FALSE);
  2005. X    }
  2006. X    obj->nobj = fobj;
  2007. X    fobj = obj;
  2008. X    place_object(obj, tx, ty);
  2009. X    newsym(otx, oty);
  2010. X    newsym(tx,ty);
  2011. X}
  2012. X
  2013. Xvoid
  2014. Xfracture_rock(obj)    /* fractured by pick-axe or wand of striking */
  2015. Xregister struct obj *obj;           /* no texts here! */
  2016. X{
  2017. X    obj->otyp = ROCK;
  2018. X    obj->quan = (long) rn1(60, 7);
  2019. X    obj->owt = weight(obj);
  2020. X    obj->oclass = GEM_CLASS;
  2021. X    obj->known = FALSE;
  2022. X    obj->onamelth = 0;        /* no names */
  2023. X    if(!does_block(obj->ox,obj->oy,&levl[obj->ox][obj->oy]))
  2024. X        unblock_point(obj->ox,obj->oy);
  2025. X    if(cansee(obj->ox,obj->oy))
  2026. X        newsym(obj->ox,obj->oy);
  2027. X}
  2028. X
  2029. Xboolean
  2030. Xbreak_statue(obj)
  2031. Xregister struct obj *obj;
  2032. X{
  2033. X    struct trap *trap;
  2034. X    struct obj *item, *nitem;
  2035. X
  2036. X    if((trap = t_at(obj->ox,obj->oy)) && trap->ttyp == STATUE_TRAP)
  2037. X        if(makemon(&mons[obj->corpsenm], obj->ox, obj->oy)) {
  2038. X        pline("Instead of shattering, the statue suddenly comes alive!");
  2039. X        delobj(obj);
  2040. X        deltrap(trap);
  2041. X        return FALSE;
  2042. X        }
  2043. X    for(item = obj->cobj; item; item = nitem) {
  2044. X        nitem = item->nobj;
  2045. X        item->nobj = fobj;
  2046. X        fobj = item;
  2047. X        place_object(item, obj->ox, obj->oy);
  2048. X    }
  2049. X    obj->cobj = (struct obj *)0;
  2050. X    fracture_rock(obj);
  2051. X    return TRUE;
  2052. X}
  2053. X
  2054. Xconst char *destroy_strings[] = {
  2055. X    "freezes and shatters", "freeze and shatter", "shattered potion",
  2056. X    "boils and explodes", "boil and explode", "boiling potion",
  2057. X    "catches fire and burns", "catch fire and burn", "burning scroll",
  2058. X    "catches fire and burns", "catch fire and burn", "burning book",
  2059. X    "turns to dust and vanishes", "turn to dust and vanish", "",
  2060. X    "breaks apart and explodes", "break apart and explode", "exploding wand"
  2061. X};
  2062. X
  2063. Xvoid
  2064. Xdestroy_item(osym, dmgtyp)
  2065. Xregister int osym, dmgtyp;
  2066. X{
  2067. X    register struct obj *obj, *obj2;
  2068. X    register int dmg, xresist, skip;
  2069. X    register long i, cnt, quan;
  2070. X    register int dindx;
  2071. X    const char *mult;
  2072. X
  2073. X    for(obj = invent; obj; obj = obj2) {
  2074. X
  2075. X        obj2 = obj->nobj;
  2076. X        if(obj->oclass != osym) continue; /* test only objs of type osym */
  2077. X        if(obj->oartifact) continue; /* don't destroy artifacts */
  2078. X        xresist = skip = 0;
  2079. X#ifdef GCC_WARN
  2080. X        dmg = dindx = 0;
  2081. X        quan = 0L;
  2082. X#endif
  2083. X        switch(dmgtyp) {
  2084. X        case AD_COLD:
  2085. X            if(osym == POTION_CLASS) {
  2086. X            quan = obj->quan;
  2087. X            dindx = 0;
  2088. X            dmg = rnd(4);
  2089. X            } else skip++;
  2090. X                break;
  2091. X        case AD_FIRE:
  2092. X            xresist = (Fire_resistance && obj->oclass != POTION_CLASS);
  2093. X
  2094. X            if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
  2095. X            skip++;
  2096. X            if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
  2097. X            skip++;
  2098. X            if (!Blind)
  2099. X                pline("%s glows a strange %s, but remains intact.",
  2100. X                The(xname(obj)),
  2101. X                Hallucination ? hcolor() : "dark red");
  2102. X            }
  2103. X            quan = obj->quan;
  2104. X            switch(osym) {
  2105. X            case POTION_CLASS:
  2106. X                dindx = 1;
  2107. X                dmg = rnd(6);
  2108. X                break;
  2109. X            case SCROLL_CLASS:
  2110. X                dindx = 2;
  2111. X                dmg = 1;
  2112. X                break;
  2113. X            case SPBOOK_CLASS:
  2114. X                dindx = 3;
  2115. X                dmg = 1;
  2116. X                break;
  2117. X            default:
  2118. X                skip++;
  2119. X                break;
  2120. X            }
  2121. X            break;
  2122. X        case AD_ELEC:
  2123. X            xresist = (Shock_resistance && obj->oclass != RING_CLASS);
  2124. X            quan = obj->quan;
  2125. X            switch(osym) {
  2126. X            case RING_CLASS:
  2127. X                if(obj->otyp == RIN_SHOCK_RESISTANCE)
  2128. X                    { skip++; break; }
  2129. X                dindx = 4;
  2130. X                dmg = 0;
  2131. X                break;
  2132. X            case WAND_CLASS:
  2133. X                if(obj->otyp == WAN_LIGHTNING) { skip++; break; }
  2134. X                dindx = 5;
  2135. X                dmg = rnd(10);
  2136. X                break;
  2137. X            default:
  2138. X                skip++;
  2139. X                break;
  2140. X            }
  2141. X            break;
  2142. X        default:
  2143. X            skip++;
  2144. X            break;
  2145. X        }
  2146. X        if(!skip) {
  2147. X        for(i = cnt = 0L; i < quan; i++)
  2148. X            if(!rn2(3)) cnt++;
  2149. X
  2150. X        if(!cnt) continue;
  2151. X        if(cnt == quan)    mult = "Your";
  2152. X        else    mult = (cnt == 1L) ? "One of your" : "Some of your";
  2153. X        pline("%s %s %s!", mult, xname(obj),
  2154. X            (cnt > 1L) ? destroy_strings[dindx*3 + 1]
  2155. X                  : destroy_strings[dindx*3]);
  2156. X        if(osym == POTION_CLASS && dmgtyp != AD_COLD)
  2157. X            potionbreathe(obj);
  2158. X        for(i = 0; i < cnt; i++) {
  2159. X            if (obj->owornmask) {
  2160. X            if (obj->owornmask & W_RING) /* ring being worn */
  2161. X                Ring_gone(obj);
  2162. X            else
  2163. X                setnotworn(obj);
  2164. X            }
  2165. X            useup(obj);
  2166. X        }
  2167. X        if(dmg) {
  2168. X            if(xresist)    You("aren't hurt!");
  2169. X            else {
  2170. X                losehp(dmg, (cnt==1L) ? destroy_strings[dindx*3 + 2] :
  2171. X                   (const char *)makeplural(destroy_strings[dindx*3 + 2]),
  2172. X                   (cnt==1L) ? KILLED_BY_AN : KILLED_BY);
  2173. X            exercise(A_STR, FALSE);
  2174. X           }
  2175. X        }
  2176. X        }
  2177. X    }
  2178. X    return;
  2179. X}
  2180. X
  2181. Xint
  2182. Xdestroy_mitem(mtmp, osym, dmgtyp)
  2183. Xregister struct monst *mtmp;
  2184. Xregister int osym, dmgtyp;
  2185. X{
  2186. X    register struct obj *obj, *obj2;
  2187. X    register int skip, tmp = 0;
  2188. X    register long i, cnt, quan;
  2189. X    register int dindx;
  2190. X    boolean vis=canseemon(mtmp);
  2191. X
  2192. X    for(obj = mtmp->minvent; obj; obj = obj2) {
  2193. X
  2194. X        obj2 = obj->nobj;
  2195. X        if(obj->oclass != osym) continue; /* test only objs of type osym */
  2196. X        skip = 0;
  2197. X#ifdef GCC_WARN
  2198. X        quan = 0L;
  2199. X        dindx = 0;
  2200. X#endif
  2201. X        switch(dmgtyp) {
  2202. X        case AD_COLD:
  2203. X            if(osym == POTION_CLASS) {
  2204. X            quan = obj->quan;
  2205. X            dindx = 0;
  2206. X            tmp++;
  2207. X            } else skip++;
  2208. X                break;
  2209. X        case AD_FIRE:
  2210. X            if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
  2211. X            skip++;
  2212. X            if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
  2213. X            skip++;
  2214. X            if (vis)
  2215. X                pline("%s glows a strange %s, but remains intact.",
  2216. X                The(distant_name(obj, xname)),
  2217. X                Hallucination ? hcolor() : "dark red");
  2218. X            }
  2219. X            quan = obj->quan;
  2220. X            switch(osym) {
  2221. X            case POTION_CLASS:
  2222. X                dindx = 1;
  2223. X                tmp++;
  2224. X                break;
  2225. X            case SCROLL_CLASS:
  2226. X                dindx = 2;
  2227. X                tmp++;
  2228. X                break;
  2229. X            case SPBOOK_CLASS:
  2230. X                dindx = 3;
  2231. X                tmp++;
  2232. X                break;
  2233. X            default:
  2234. X                skip++;
  2235. X                break;
  2236. X            }
  2237. X            break;
  2238. X        case AD_ELEC:
  2239. X            quan = obj->quan;
  2240. X            switch(osym) {
  2241. X            case RING_CLASS:
  2242. X                if(obj->otyp == RIN_SHOCK_RESISTANCE)
  2243. X                    { skip++; break; }
  2244. X                dindx = 4;
  2245. X                break;
  2246. X            case WAND_CLASS:
  2247. X                if(obj->otyp == WAN_LIGHTNING) { skip++; break; }
  2248. X                dindx = 5;
  2249. X                tmp++;
  2250. X                break;
  2251. X            default:
  2252. X                skip++;
  2253. X                break;
  2254. X            }
  2255. X            break;
  2256. X        default:
  2257. X            skip++;
  2258. X            break;
  2259. X        }
  2260. X        if(!skip) {
  2261. X        for(i = cnt = 0L; i < quan; i++)
  2262. X            if(!rn2(3)) cnt++;
  2263. X
  2264. X        if(!cnt) continue;
  2265. X        if (vis) pline("%s %s %s!", 
  2266. X            s_suffix(Monnam(mtmp)), xname(obj),
  2267. X            (cnt > 1L) ? destroy_strings[dindx*3 + 1]
  2268. X                  : destroy_strings[dindx*3]);
  2269. X        for(i = 0; i < cnt; i++) m_useup(mtmp, obj);
  2270. X        }
  2271. X    }
  2272. X    return(tmp);
  2273. X}
  2274. X
  2275. X/*ARGSUSED*/
  2276. Xint
  2277. Xresist(mtmp, class, damage, tell)
  2278. Xregister struct monst    *mtmp;
  2279. Xregister char    class;
  2280. Xregister int    damage, tell;
  2281. X{
  2282. X    register int    resisted;
  2283. X    register int    lev;
  2284. X
  2285. X    switch(class)  {
  2286. X
  2287. X        case WAND_CLASS:
  2288. X            lev = 8;
  2289. X            break;
  2290. X
  2291. X        case SCROLL_CLASS:
  2292. X            lev = 6;
  2293. X            break;
  2294. X
  2295. X        case POTION_CLASS:
  2296. X            lev = 5;
  2297. X            break;
  2298. X
  2299. X        default:    lev = u.ulevel;
  2300. X            break;
  2301. X    }
  2302. X
  2303. X    resisted = (rn2(100) - (unsigned)mtmp->m_lev + lev) < mtmp->data->mr;
  2304. X    if(resisted) {
  2305. X
  2306. X        if(tell) {
  2307. X            shieldeff(mtmp->mx, mtmp->my);
  2308. X            pline("%s resists!", Monnam(mtmp));
  2309. X        }
  2310. X        mtmp->mhp -= damage/2;
  2311. X    } else  mtmp->mhp -= damage;
  2312. X
  2313. X#ifdef MUSE
  2314. X    if(mtmp->mhp < 1) {
  2315. X        if(m_using) monkilled(mtmp, "", AD_RBRE);
  2316. X        else killed(mtmp);
  2317. X    }
  2318. X#else
  2319. X    if(mtmp->mhp < 1) killed(mtmp);
  2320. X#endif
  2321. X    return(resisted);
  2322. X}
  2323. X
  2324. Xvoid
  2325. Xmakewish()
  2326. X{
  2327. X    char buf[BUFSZ];
  2328. X    register struct obj *otmp;
  2329. X    int tries = 0;
  2330. X
  2331. X    if (flags.verbose) You("may wish for an object.");
  2332. Xretry:
  2333. X    getlin("For what do you wish?", buf);
  2334. X    if(buf[0] == '\033') buf[0] = 0;
  2335. X    /*
  2336. X     *  Note: if they wished for and got a non-object successfully,
  2337. X     *  otmp == &zeroobj
  2338. X     */
  2339. X    otmp = readobjnam(buf);
  2340. X    if (!otmp) {
  2341. X        pline("Nothing fitting that description exists in the game.");
  2342. X        if (++tries < 5) goto retry;
  2343. X        pline(thats_enough_tries);
  2344. X        if (!(otmp = readobjnam((char *)0)))
  2345. X        return; /* for safety; should never happen */
  2346. X    }
  2347. X    if (otmp != &zeroobj) {
  2348. X        if(otmp->oartifact && !touch_artifact(otmp,&youmonst))
  2349. X        dropy(otmp);
  2350. X        else
  2351. X        /* The(aobjnam()) is safe since otmp is unidentified -dlc */
  2352. X        (void) hold_another_object(otmp, u.uswallow ?
  2353. X                       "Oops!  %s out of your reach!" :
  2354. X                       Is_airlevel(&u.uz) ?
  2355. X                       "Oops!  %s out of your grasp!" :
  2356. X                       "Oops!  %s to the floor!",
  2357. X                       The(aobjnam(otmp, Is_airlevel(&u.uz) ?
  2358. X                           "slip" : "drop")),
  2359. X                       (const char *)0);
  2360. X        u.ublesscnt += rn1(100,50);  /* the gods take notice */
  2361. X    }
  2362. X}
  2363. X
  2364. X/*zap.c*/
  2365. END_OF_FILE
  2366. if test 32988 -ne `wc -c <'src/zap.c2'`; then
  2367.     echo shar: \"'src/zap.c2'\" unpacked with wrong size!
  2368. fi
  2369. # end of 'src/zap.c2'
  2370. fi
  2371. echo shar: End of archive 61 \(of 108\).
  2372. cp /dev/null ark61isdone
  2373. MISSING=""
  2374. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2375. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2376. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2377. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2378. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2379. 101 102 103 104 105 106 107 108 ; do
  2380.     if test ! -f ark${I}isdone ; then
  2381.     MISSING="${MISSING} ${I}"
  2382.     fi
  2383. done
  2384. if test "${MISSING}" = "" ; then
  2385.     echo You have unpacked all 108 archives.
  2386.     echo "Now execute 'rebuild.sh'"
  2387.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2388. else
  2389.     echo You still need to unpack the following archives:
  2390.     echo "        " ${MISSING}
  2391. fi
  2392. ##  End of shell archive.
  2393. exit 0
  2394.