home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume16 / nethack31 / part67 < 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: v16i075:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part67/108
  5. Message-ID: <4378@master.CNA.TEK.COM>
  6. Date: 1 Feb 93 19:51:23 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2214
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1625
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 75
  14. Archive-name: nethack31/Part67
  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 67 (of 108)."
  27. # Contents:  dat/knox.des src/topten.c src/trap.c2
  28. # Wrapped by billr@saab on Wed Jan 27 16:09:13 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'dat/knox.des' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'dat/knox.des'\"
  32. else
  33. echo shar: Extracting \"'dat/knox.des'\" \(3808 characters\)
  34. sed "s/^X//" >'dat/knox.des' <<'END_OF_FILE'
  35. X#    SCCS Id: @(#)knox.des    3.1    90/02/26
  36. X#    Copyright (c) 1989 by Jean-Christophe Collet
  37. X#    Copyright (c) 1992 by Izchak Miller
  38. X# NetHack may be freely redistributed.  See license for details.
  39. X#
  40. XMAZE:"knox",' '
  41. XFLAGS: noteleport
  42. XGEOMETRY:center,center
  43. XMAP
  44. X----------------------------------------------------------------------------
  45. X| |........|...............................................................|
  46. X| |........|.................................................------------..|
  47. X| -------+--.................................................|..........|..|
  48. X|       |........}}}}}}}....................}}}}}}}..........|..........|..|
  49. X|       |........}-----}....................}-----}..........--+--+--...|..|
  50. X|     ---........}|...|}}}}}}}}}}}}}}}}}}}}}}|...|}.................|...|..|
  51. X|     |..........}---S------------------------S---}.................|...|..|
  52. X|     |..........}}}|...............|..........|}}}.................+...|..|
  53. X| -------..........}|...............S..........|}...................|...|..|
  54. X| |.....|..........}|...............|......\...S}...................|...|..|
  55. X| |.....+........}}}|...............|..........|}}}.................+...|..|
  56. X| |.....|........}---S------------------------S---}.................|...|..|
  57. X| |.....|........}|...|}}}}}}}}}}}}}}}}}}}}}}|...|}.................|...|..|
  58. X| |..-S----......}-----}....................}-----}..........--+--+--...|..|
  59. X| |..|....|......}}}}}}}....................}}}}}}}..........|..........|..|
  60. X| |..|....|..................................................|..........|..|
  61. X| -----------................................................------------..|
  62. X|           |..............................................................|
  63. X----------------------------------------------------------------------------
  64. XENDMAP
  65. X# Non diggable walls
  66. XNON_DIGGABLE:(00,00,75,19)
  67. X# Portal arrival point
  68. XBRANCH:(08,16,08,16),(0,0,0,0)
  69. X#   Throne room, with Croesus on the throne
  70. XREGION:(37,08,46,11),lit,"throne"
  71. XMONSTER:'@',"Croesus",(43,10),hostile
  72. X#   The Vault
  73. X#   Using unfilled morgue for 
  74. X#   identification in mkmaze.c
  75. XREGION:(21,08,35,11),lit,"morgue",unfilled
  76. X#   Corner towers
  77. XREGION:(19,06,21,06),lit,"ordinary"
  78. XREGION:(46,06,48,06),lit,"ordinary"
  79. XREGION:(19,13,21,13),lit,"ordinary"
  80. XREGION:(46,13,48,13),lit,"ordinary"
  81. X#   A welcoming committee
  82. XREGION:(03,10,07,13),lit,"zoo",filled,true
  83. X#   Barracks
  84. XREGION:(62,03,71,04),lit,"barracks",filled,true
  85. X# Doors
  86. XDOOR:closed,(06,14)
  87. XDOOR:closed,(09,03)
  88. XDOOR:open,(63,05)
  89. XDOOR:open,(66,05)
  90. XDOOR:open,(68,08)
  91. XDOOR:locked,(08,11)
  92. XDOOR:open,(68,11)
  93. XDOOR:closed,(63,14)
  94. XDOOR:closed,(66,14)
  95. X# Soldiers guarding the fort
  96. XMONSTER:'@',"soldier",(12,14)
  97. XMONSTER:'@',"soldier",(12,13)
  98. XMONSTER:'@',"soldier",(11,10)
  99. XMONSTER:'@',"soldier",(13,02)
  100. XMONSTER:'@',"soldier",(14,03)
  101. XMONSTER:'@',"soldier",(20,02)
  102. XMONSTER:'@',"soldier",(30,02)
  103. XMONSTER:'@',"soldier",(40,02)
  104. XMONSTER:'@',"soldier",(30,16)
  105. XMONSTER:'@',"soldier",(32,16)
  106. XMONSTER:'@',"soldier",(40,16)
  107. XMONSTER:'@',"soldier",(54,16)
  108. XMONSTER:'@',"soldier",(54,14)
  109. XMONSTER:'@',"soldier",(54,13)
  110. XMONSTER:'@',"soldier",(57,10)
  111. XMONSTER:'@',"soldier",(57,09)
  112. XMONSTER:'@',"lieutenant",(15,08)
  113. X# Four dragons guarding each side
  114. XMONSTER:'D',random,(18,09)
  115. XMONSTER:'D',random,(49,10)
  116. XMONSTER:'D',random,(33,05)
  117. XMONSTER:'D',random,(33,14)
  118. X# Eels in the moat
  119. XMONSTER:';',"giant eel",(09,08)
  120. XMONSTER:';',"giant eel",(09,11)
  121. XMONSTER:';',"giant eel",(48,08)
  122. XMONSTER:';',"giant eel",(48,11)
  123. X# The corner rooms treasures
  124. XOBJECT:'*',"diamond",(19,06)
  125. XOBJECT:'*',"diamond",(20,06)
  126. XOBJECT:'*',"diamond",(21,06)
  127. XOBJECT:'*',"emerald",(19,13)
  128. XOBJECT:'*',"emerald",(20,13)
  129. XOBJECT:'*',"emerald",(21,13)
  130. XOBJECT:'*',"ruby",(46,06)
  131. XOBJECT:'*',"ruby",(47,06)
  132. XOBJECT:'*',"ruby",(48,06)
  133. XOBJECT:'*',"amethyst",(46,13)
  134. XOBJECT:'*',"amethyst",(47,13)
  135. XOBJECT:'*',"amethyst",(48,13)
  136. END_OF_FILE
  137. if test 3808 -ne `wc -c <'dat/knox.des'`; then
  138.     echo shar: \"'dat/knox.des'\" unpacked with wrong size!
  139. fi
  140. # end of 'dat/knox.des'
  141. fi
  142. if test -f 'src/topten.c' -a "${1}" != "-c" ; then 
  143.   echo shar: Will not clobber existing file \"'src/topten.c'\"
  144. else
  145. echo shar: Extracting \"'src/topten.c'\" \(18740 characters\)
  146. sed "s/^X//" >'src/topten.c' <<'END_OF_FILE'
  147. X/*    SCCS Id: @(#)topten.c    3.1    92/11/20    */
  148. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  149. X/* NetHack may be freely redistributed.  See license for details. */
  150. X
  151. X#include "hack.h"
  152. X
  153. X#ifdef VMS
  154. X /* We don't want to rewrite the whole file, because that entails     */
  155. X /* creating a new version which requires that the old one be deletable. */
  156. X# define UPDATE_RECORD_IN_PLACE
  157. X#endif
  158. X
  159. X/*
  160. X * Updating in place can leave junk at the end of the file in some
  161. X * circumstances (if it shrinks and the O.S. doesn't have a straightforward
  162. X * way to truncate it).  The trailing junk is harmless and the code
  163. X * which reads the scores will ignore it.
  164. X */
  165. X#ifdef UPDATE_RECORD_IN_PLACE
  166. X# ifndef SEEK_SET
  167. X#  define SEEK_SET 0
  168. X# endif
  169. Xstatic long final_fpos;
  170. X#endif
  171. X
  172. X#ifdef NO_SCAN_BRACK
  173. Xstatic void FDECL(nsb_mung_line,(char*));
  174. Xstatic void FDECL(nsb_unmung_line,(char*));
  175. X#endif
  176. X
  177. X#define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
  178. X#define dealloc_ttentry(ttent) free((genericptr_t) (ttent))
  179. X#define    NAMSZ    10
  180. X#define    DTHSZ    60
  181. X#define    PERSMAX     3        /* entries per name/uid per char. allowed */
  182. X#define    POINTSMIN    1    /* must be > 0 */
  183. X#define    ENTRYMAX    100    /* must be >= 10 */
  184. X
  185. X#ifndef MICRO
  186. X#define    PERS_IS_UID        /* delete for PERSMAX per name; now per uid */
  187. X#endif
  188. Xstruct toptenentry {
  189. X    struct toptenentry *tt_next;
  190. X#ifdef UPDATE_RECORD_IN_PLACE
  191. X    long fpos;
  192. X#endif
  193. X    long points;
  194. X    int deathdnum, deathlev;
  195. X    int maxlvl,hp,maxhp;
  196. X    int uid;
  197. X    char plchar;
  198. X    char sex;
  199. X    char name[NAMSZ+1];
  200. X    char death[DTHSZ+1];
  201. X    char date[7];        /* yymmdd */
  202. X} *tt_head;
  203. X
  204. Xstatic void NDECL(outheader);
  205. Xstatic int FDECL(outentry, (int,struct toptenentry *,int));
  206. Xstatic void FDECL(readentry, (FILE *,struct toptenentry *));
  207. Xstatic void FDECL(writeentry, (FILE *,struct toptenentry *));
  208. Xstatic int FDECL(classmon, (CHAR_P,BOOLEAN_P));
  209. X
  210. X/* must fit with end.c */
  211. Xconst char NEARDATA *killed_by_prefix[] = {
  212. X    "killed by ", "choked on ", "poisoned by ", "", "drowned in ",
  213. X    "", "crushed to death by ", "petrified by ", "",
  214. X    "", "",
  215. X    "", "", "" };
  216. X
  217. Xstatic void
  218. Xreadentry(rfile,tt)
  219. XFILE *rfile;
  220. Xstruct toptenentry *tt;
  221. X{
  222. X#ifdef UPDATE_RECORD_IN_PLACE
  223. X    /* note: fscanf() below must read the record's terminating newline */
  224. X    final_fpos = tt->fpos = ftell(rfile);
  225. X#endif
  226. X#ifdef NO_SCAN_BRACK
  227. X    if(fscanf(rfile,"%6s %d %d %d %d %d %d %ld%*c%c%c %s %s%*c",
  228. X#  define TTFIELDS 13
  229. X#else
  230. X    if(fscanf(rfile, "%6s %d %d %d %d %d %d %ld %c%c %[^,],%[^\n]%*c",
  231. X#  define TTFIELDS 12
  232. X#endif
  233. X            tt->date, &tt->uid,
  234. X            &tt->deathdnum, &tt->deathlev,
  235. X            &tt->maxlvl, &tt->hp, &tt->maxhp, &tt->points,
  236. X            &tt->plchar, &tt->sex,
  237. X#ifdef LATTICE    /* return value is broken also, sigh */
  238. X            tt->name, tt->death) < 1)
  239. X#else
  240. X            tt->name, tt->death) != TTFIELDS)
  241. X#endif
  242. X#undef TTFIELDS
  243. X        tt->points = 0;
  244. X    else {
  245. X#ifdef NO_SCAN_BRACK
  246. X        if(tt->points > 0) {
  247. X            nsb_unmung_line(tt->name);
  248. X            nsb_unmung_line(tt->death);
  249. X        }
  250. X#endif
  251. X    }
  252. X}
  253. X
  254. Xstatic void
  255. Xwriteentry(rfile,tt)
  256. XFILE *rfile;
  257. Xstruct toptenentry *tt;
  258. X{
  259. X#ifdef NO_SCAN_BRACK
  260. X    nsb_mung_line(tt->name);
  261. X    nsb_mung_line(tt->death);
  262. X    (void) fprintf(rfile,"%6s %d %d %d %d %d %d %ld %c%c %s %s\n",
  263. X#else
  264. X    (void) fprintf(rfile,"%6s %d %d %d %d %d %d %ld %c%c %s,%s\n",
  265. X#endif
  266. X        tt->date, tt->uid,
  267. X        tt->deathdnum, tt->deathlev,
  268. X        tt->maxlvl, tt->hp, tt->maxhp, tt->points,
  269. X        tt->plchar, tt->sex,
  270. X        onlyspace(tt->name) ? "_" : tt->name, tt->death);
  271. X#ifdef NO_SCAN_BRACK
  272. X    nsb_unmung_line(tt->name);
  273. X    nsb_unmung_line(tt->death);
  274. X#endif
  275. X}
  276. X
  277. Xvoid
  278. Xtopten(how)
  279. Xint how;
  280. X{
  281. X    int uid = getuid();
  282. X    int rank, rank0 = -1, rank1 = 0;
  283. X    int occ_cnt = PERSMAX;
  284. X    register struct toptenentry *t0, *tprev;
  285. X    struct toptenentry *t1;
  286. X    FILE *rfile;
  287. X    register int flg = 0;
  288. X#ifdef LOGFILE
  289. X    FILE *lfile;
  290. X#endif /* LOGFILE */
  291. X
  292. X#if defined(MICRO)
  293. X#define HUP
  294. X#else
  295. X#define    HUP    if(!done_hup)
  296. X#endif
  297. X    /* create a new 'topten' entry */
  298. X    t0 = newttentry();
  299. X    /* deepest_lev_reached() is in terms of depth(), and reporting the
  300. X     * deepest level reached in the dungeon death occurred in doesn't
  301. X     * seem right, so we have to report the death level in depth() terms
  302. X     * as well (which also seems reasonable since that's all the player
  303. X     * sees on the screen anyway)
  304. X     */
  305. X    t0->deathdnum = u.uz.dnum;
  306. X    t0->deathlev = depth(&u.uz);
  307. X    t0->maxlvl = deepest_lev_reached(TRUE);
  308. X    t0->hp = u.uhp;
  309. X    t0->maxhp = u.uhpmax;
  310. X    t0->points = u.urexp;
  311. X    t0->plchar = pl_character[0];
  312. X    t0->sex = (flags.female ? 'F' : 'M');
  313. X    t0->uid = uid;
  314. X    (void) strncpy(t0->name, plname, NAMSZ);
  315. X    t0->name[NAMSZ] = '\0';
  316. X    t0->death[0] = '\0';
  317. X    switch (killer_format) {
  318. X        default: impossible("bad killer format?");
  319. X        case KILLED_BY_AN:
  320. X            Strcat(t0->death, killed_by_prefix[how]);
  321. X            (void) strncat(t0->death, an(killer), DTHSZ);
  322. X            break;
  323. X        case KILLED_BY:
  324. X            Strcat(t0->death, killed_by_prefix[how]);
  325. X            (void) strncat(t0->death, killer, DTHSZ);
  326. X            break;
  327. X        case NO_KILLER_PREFIX:
  328. X            (void) strncat(t0->death, killer, DTHSZ);
  329. X            break;
  330. X    }
  331. X    Strcpy(t0->date, get_date());
  332. X    t0->tt_next = 0;
  333. X#ifdef UPDATE_RECORD_IN_PLACE
  334. X    t0->fpos = -1L;
  335. X#endif
  336. X
  337. X#ifdef LOGFILE        /* used for debugging (who dies of what, where) */
  338. X    if (lock_file(LOGFILE, 10)) {
  339. X        if(!(lfile = fopen_datafile(LOGFILE,"a"))) {
  340. X        HUP raw_print("Cannot open log file!");
  341. X        } else {
  342. X        writeentry(lfile, t0);
  343. X        (void) fclose(lfile);
  344. X        }
  345. X        unlock_file(LOGFILE);
  346. X    }
  347. X#endif /* LOGFILE */
  348. X
  349. X#if defined(WIZARD) || defined(EXPLORE_MODE)
  350. X    if (wizard || discover) {
  351. X        raw_print("");
  352. X        raw_printf(
  353. X          "Since you were in %s mode, the score list will not be checked.",
  354. X            wizard ? "wizard" : "discover");
  355. X        return;
  356. X    }
  357. X#endif
  358. X
  359. X    if (!lock_file(RECORD, 60)) return;
  360. X
  361. X#ifdef UPDATE_RECORD_IN_PLACE
  362. X    rfile = fopen_datafile(RECORD, "r+");
  363. X#else
  364. X    rfile = fopen_datafile(RECORD, "r");
  365. X#endif
  366. X
  367. X    if (!rfile) {
  368. X        HUP raw_print("Cannot open record file!");
  369. X        unlock_file(RECORD);
  370. X        return;
  371. X    }
  372. X
  373. X    HUP raw_print("");
  374. X
  375. X    /* assure minimum number of points */
  376. X    if(t0->points < POINTSMIN) t0->points = 0;
  377. X
  378. X    t1 = tt_head = newttentry();
  379. X    tprev = 0;
  380. X    /* rank0: -1 undefined, 0 not_on_list, n n_th on list */
  381. X    for(rank = 1; ; ) {
  382. X        readentry(rfile, t1);
  383. X        if (t1->points < POINTSMIN) t1->points = 0;
  384. X        if(rank0 < 0 && t1->points < t0->points) {
  385. X        rank0 = rank++;
  386. X        if(tprev == 0)
  387. X            tt_head = t0;
  388. X        else
  389. X            tprev->tt_next = t0;
  390. X        t0->tt_next = t1;
  391. X#ifdef UPDATE_RECORD_IN_PLACE
  392. X        t0->fpos = t1->fpos;    /* insert here */
  393. X#endif
  394. X        occ_cnt--;
  395. X        flg++;        /* ask for a rewrite */
  396. X        } else tprev = t1;
  397. X
  398. X        if(t1->points == 0) break;
  399. X        if(
  400. X#ifdef PERS_IS_UID
  401. X        t1->uid == t0->uid &&
  402. X#else
  403. X        strncmp(t1->name, t0->name, NAMSZ) == 0 &&
  404. X#endif
  405. X        t1->plchar == t0->plchar && --occ_cnt <= 0) {
  406. X            if(rank0 < 0) {
  407. X            rank0 = 0;
  408. X            rank1 = rank;
  409. X            HUP {
  410. X                raw_printf(
  411. X              "You didn't beat your previous score of %ld points.",
  412. X                    t1->points);
  413. X                raw_print("");
  414. X            }
  415. X            }
  416. X            if(occ_cnt < 0) {
  417. X            flg++;
  418. X            continue;
  419. X            }
  420. X        }
  421. X        if(rank <= ENTRYMAX) {
  422. X        t1 = t1->tt_next = newttentry();
  423. X        rank++;
  424. X        }
  425. X        if(rank > ENTRYMAX) {
  426. X        t1->points = 0;
  427. X        break;
  428. X        }
  429. X    }
  430. X    if(flg) {    /* rewrite record file */
  431. X#ifdef UPDATE_RECORD_IN_PLACE
  432. X        (void) fseek(rfile, (t0->fpos >= 0 ?
  433. X                     t0->fpos : final_fpos), SEEK_SET);
  434. X#else
  435. X        (void) fclose(rfile);
  436. X        if(!(rfile = fopen_datafile(RECORD,"w"))){
  437. X            HUP raw_print("Cannot write record file");
  438. X            unlock_file(RECORD);
  439. X            return;
  440. X        }
  441. X#endif    /* UPDATE_RECORD_IN_PLACE */
  442. X        if(!done_stopprint) if(rank0 > 0){
  443. X            if(rank0 <= 10)
  444. X            raw_print("You made the top ten list!");
  445. X            else {
  446. X            raw_printf(
  447. X              "You reached the %d%s place on the top %d list.",
  448. X                rank0, ordin(rank0), ENTRYMAX);
  449. X            }
  450. X            raw_print("");
  451. X        }
  452. X    }
  453. X    if(rank0 == 0) rank0 = rank1;
  454. X    if(rank0 <= 0) rank0 = rank;
  455. X    if(!done_stopprint) outheader();
  456. X    t1 = tt_head;
  457. X    for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
  458. X        if(flg
  459. X#ifdef UPDATE_RECORD_IN_PLACE
  460. X            && rank >= rank0
  461. X#endif
  462. X        ) writeentry(rfile, t1);
  463. X        if(done_stopprint) continue;
  464. X        if(rank > flags.end_top &&
  465. X          (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
  466. X          && (!flags.end_own ||
  467. X#ifdef PERS_IS_UID
  468. X                  t1->uid != t0->uid
  469. X#else
  470. X                  strncmp(t1->name, t0->name, NAMSZ)
  471. X#endif
  472. X        )) continue;
  473. X        if(rank == rank0-flags.end_around &&
  474. X           rank0 > flags.end_top+flags.end_around+1 &&
  475. X           !flags.end_own)
  476. X          raw_print("");
  477. X        if(rank != rank0)
  478. X        (void) outentry(rank, t1, 0);
  479. X        else if(!rank1)
  480. X        (void) outentry(rank, t1, 1);
  481. X        else {
  482. X        int t0lth = outentry(0, t0, -1);
  483. X        int t1lth = outentry(rank, t1, t0lth);
  484. X        if(t1lth > t0lth) t0lth = t1lth;
  485. X        (void) outentry(0, t0, t0lth);
  486. X        }
  487. X    }
  488. X    if(rank0 >= rank) if(!done_stopprint)
  489. X        (void) outentry(0, t0, 1);
  490. X#ifdef UPDATE_RECORD_IN_PLACE
  491. X    if (flg) {
  492. X# ifdef TRUNCATE_FILE
  493. X        /* if a reasonable way to truncate a file exists, use it */
  494. X        truncate_file(rfile);
  495. X# else
  496. X        /* use sentinel record rather than relying on truncation */
  497. X        t0->points = 0L;    /* terminates file when read back in */
  498. X        t0->uid = t0->deathdnum = t0->deathlev = 0;
  499. X        t0->maxlvl = t0->hp = t0->maxhp = 0;
  500. X        t0->plchar = t0->sex = '-';
  501. X        Strcpy(t0->name, "@");
  502. X        Strcpy(t0->death, "<eod>\n");
  503. X        writeentry(rfile, t0);
  504. X        (void) fflush(rfile);
  505. X# endif    /* TRUNCATE_FILE */
  506. X    }
  507. X#endif    /* UPDATE_RECORD_IN_PLACE */
  508. X    (void) fclose(rfile);
  509. X    unlock_file(RECORD);
  510. X}
  511. X
  512. Xstatic void
  513. Xoutheader() {
  514. X    char linebuf[BUFSZ];
  515. X    register char *bp;
  516. X
  517. X    Strcpy(linebuf, " No  Points     Name");
  518. X    bp = eos(linebuf);
  519. X    while(bp < linebuf + COLNO - 9) *bp++ = ' ';
  520. X    Strcpy(bp, "Hp [max]");
  521. X    raw_print(linebuf);
  522. X}
  523. X
  524. X/* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
  525. Xstatic int
  526. Xoutentry(rank, t1, so)
  527. Xregister struct toptenentry *t1;
  528. Xregister int rank, so;
  529. X{
  530. X    register boolean second_line = TRUE;
  531. X    char linebuf[BUFSZ], linebuf2[BUFSZ], linebuf3[BUFSZ], pbuf[BUFSZ];
  532. X
  533. X    linebuf[0] = linebuf2[0] = linebuf3[0] = 0;
  534. X    if(rank) Sprintf(eos(linebuf), "%3d", rank);
  535. X    else Strcat(linebuf, "   ");
  536. X
  537. X    Sprintf(eos(linebuf), " %10ld  %.10s", t1->points, t1->name);
  538. X    Sprintf(eos(linebuf), "-%c ", t1->plchar);
  539. X    if(!strncmp("escaped", t1->death, 7)) {
  540. X      second_line = FALSE;
  541. X      if(!strcmp(" (with the Amulet)", t1->death+7))
  542. X        Strcat(linebuf, "escaped the dungeon with the Amulet");
  543. X      else
  544. X        Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
  545. X          t1->maxlvl);
  546. X    } else if(!strncmp("ascended", t1->death, 8)) {
  547. X       Strcat(linebuf, "ascended to demigod");
  548. X       if (t1->sex == 'F') Strcat(linebuf, "dess");
  549. X       Strcat(linebuf, "-hood");
  550. X       second_line = FALSE;
  551. X    } else {
  552. X      if(!strncmp(t1->death,"quit",4)) {
  553. X        Strcat(linebuf, "quit");
  554. X        second_line = FALSE;
  555. X      } else if(!strncmp(t1->death,"starv",5)) {
  556. X        Strcat(linebuf, "starved to death");
  557. X        second_line = FALSE;
  558. X      } else if(!strncmp(t1->death,"choked",6)) {
  559. X        Sprintf(eos(linebuf), "choked on h%s food",
  560. X            (t1->sex == 'F') ? "er" : "is");
  561. X      } else if(!strncmp(t1->death,"poisoned",8)) {
  562. X        Strcat(linebuf, "was poisoned");
  563. X      } else if(!strncmp(t1->death,"crushed",7)) {
  564. X        Strcat(linebuf, "was crushed to death");
  565. X      } else if(!strncmp(t1->death, "petrified by ",13)) {
  566. X        Strcat(linebuf, "turned to stone");
  567. X      } else Strcat(linebuf, "died");
  568. X
  569. X      if (t1->deathdnum == astral_level.dnum)
  570. X        Strcpy(linebuf3, " in the endgame");
  571. X      else
  572. X        Sprintf(linebuf3, " in %s on level %d",
  573. X            dungeons[t1->deathdnum].dname, t1->deathlev);
  574. X      if(t1->deathlev != t1->maxlvl)
  575. X        Sprintf(eos(linebuf3), " [max %d]", t1->maxlvl);
  576. X      /* kludge for "quit while already on Charon's boat" */
  577. X      if(!strncmp(t1->death, "quit ", 5))
  578. X        Strcat(linebuf3, t1->death + 4);
  579. X    }
  580. X    Strcat(linebuf3, ".");
  581. X
  582. X    if(t1->maxhp) {
  583. X      register char *bp;
  584. X      char hpbuf[10];
  585. X      int hppos;
  586. X      int lngr = strlen(linebuf) + strlen(linebuf3);
  587. X      if (t1->hp <= 0) hpbuf[0] = '-', hpbuf[1] = '\0';
  588. X      else Sprintf(hpbuf, "%d", t1->hp);
  589. X      hppos = COLNO - 7 - (int)strlen(hpbuf);
  590. X      if (lngr >= hppos) {
  591. X          if(so > 0) {
  592. X          bp = eos(linebuf);
  593. X          while(bp < linebuf + (COLNO-1)) *bp++ = ' ';
  594. X          *bp = 0;
  595. X          raw_print_bold(linebuf);
  596. X          } else if(so == 0)
  597. X          raw_print(linebuf);
  598. X          Strcpy(linebuf, "               ");
  599. X      }
  600. X      Strcat(linebuf, linebuf3);
  601. X      bp = eos(linebuf);
  602. X
  603. X      if(bp <= linebuf + hppos) {
  604. X        /* pad any necessary blanks to the hit point entry */
  605. X        while(bp < linebuf + hppos) *bp++ = ' ';
  606. X        Strcpy(bp, hpbuf);
  607. X        if(t1->maxhp < 10)
  608. X         Sprintf(eos(bp), "   [%d]", t1->maxhp);
  609. X        else if(t1->maxhp < 100)
  610. X         Sprintf(eos(bp), "  [%d]", t1->maxhp);
  611. X        else Sprintf(eos(bp), " [%d]", t1->maxhp);
  612. X      }
  613. X    }
  614. X
  615. X/*    Line 2 now contains the killer name */
  616. X
  617. X    /* Quit, starved, ascended, and escaped contain no second line */
  618. X    if (second_line) {
  619. X        Strcpy(linebuf2, t1->death);
  620. X        *linebuf2 = highc(*linebuf2);
  621. X        Strcat(linebuf2, ".");
  622. X    }
  623. X
  624. X    if(so == 0) {
  625. X        raw_print(linebuf);
  626. X        if (second_line)
  627. X        raw_printf("                %s", linebuf2);
  628. X    } else if(so > 0) {
  629. X      register char *bp = eos(linebuf);
  630. X      if(so >= COLNO) so = COLNO-1;
  631. X      while(bp < linebuf + so) *bp++ = ' ';
  632. X      *bp = 0;
  633. X      raw_print_bold(linebuf);
  634. X      if(second_line) {
  635. X          Sprintf(pbuf, "                %s", linebuf2);
  636. X          raw_print_bold(pbuf);
  637. X      }
  638. X    }
  639. X    return((int)strlen(linebuf)+(int)strlen(linebuf2));
  640. X}
  641. X
  642. X/*
  643. X * Called with args from main if argc >= 0. In this case, list scores as
  644. X * requested. Otherwise, find scores for the current player (and list them
  645. X * if argc == -1).
  646. X */
  647. Xvoid
  648. Xprscore(argc,argv)
  649. Xint argc;
  650. Xchar **argv;
  651. X{
  652. X    const char **players;
  653. X    int playerct;
  654. X    int rank;
  655. X    register struct toptenentry *t1, *t2;
  656. X    FILE *rfile;
  657. X    register int flg = 0, i;
  658. X    char pbuf[BUFSZ];
  659. X#ifdef nonsense
  660. X    long total_score = 0L;
  661. X    char totchars[10];
  662. X    int totcharct = 0;
  663. X#endif
  664. X    int outflg = (argc >= -1);
  665. X#ifdef PERS_IS_UID
  666. X    int uid = -1;
  667. X#else
  668. X    const char *player0;
  669. X#endif
  670. X    rfile = fopen_datafile(RECORD, "r");
  671. X    if (!rfile) {
  672. X        raw_print("Cannot open record file!");
  673. X        return;
  674. X    }
  675. X
  676. X    /* If the score list isn't after a game, we never went through */
  677. X    /* init_dungeons() */
  678. X    if (wiz1_level.dlevel == 0) init_dungeons();
  679. X
  680. X    if(argc > 1 && !strncmp(argv[1], "-s", 2)){
  681. X        if(!argv[1][2]){
  682. X            argc--;
  683. X            argv++;
  684. X        } else if(!argv[1][3] && index(pl_classes, argv[1][2])) {
  685. X            argv[1]++;
  686. X            argv[1][0] = '-';
  687. X        } else    argv[1] += 2;
  688. X    }
  689. X    if(argc <= 1){
  690. X#ifdef PERS_IS_UID
  691. X        uid = getuid();
  692. X        playerct = 0;
  693. X#  if defined(LINT) || defined(GCC_WARN)
  694. X        players = 0;
  695. X#  endif
  696. X#else
  697. X        player0 = plname;
  698. X        if(!*player0)
  699. X            player0 = "hackplayer";
  700. X        playerct = 1;
  701. X        players = &player0;
  702. X#endif
  703. X    } else {
  704. X        playerct = --argc;
  705. X        players = (const char **)++argv;
  706. X    }
  707. X    if(outflg) raw_print("");
  708. X
  709. X    t1 = tt_head = newttentry();
  710. X    for(rank = 1; ; rank++) {
  711. X        readentry(rfile, t1);
  712. X        if(t1->points == 0) break;
  713. X#ifdef PERS_IS_UID
  714. X        if(!playerct && t1->uid == uid)
  715. X        flg++;
  716. X        else
  717. X#endif
  718. X        for(i = 0; i < playerct; i++){
  719. X        if(strcmp(players[i], "all") == 0 ||
  720. X           strncmp(t1->name, players[i], NAMSZ) == 0 ||
  721. X          (players[i][0] == '-' &&
  722. X           players[i][1] == t1->plchar &&
  723. X           players[i][2] == 0) ||
  724. X          (digit(players[i][0]) && rank <= atoi(players[i])))
  725. X            flg++;
  726. X        }
  727. X        t1 = t1->tt_next = newttentry();
  728. X    }
  729. X    (void) fclose(rfile);
  730. X    if(!flg) {
  731. X        if(outflg) {
  732. X        Strcpy(pbuf, "Cannot find any entries for ");
  733. X        if(playerct < 1) Strcat(pbuf, "you.");
  734. X        else {
  735. X          if(playerct > 1) Strcat(pbuf, "any of ");
  736. X          for(i=0; i<playerct; i++) {
  737. X              Strcat(pbuf, players[i]);
  738. X              if(i<playerct-1) Strcat(pbuf, ":");
  739. X          }
  740. X          raw_print(pbuf);
  741. X          raw_printf("Call is: %s -s [-role] [maxrank] [playernames]",
  742. X                 hname);
  743. X        }
  744. X        }
  745. X        return;
  746. X    }
  747. X
  748. X    if(outflg) outheader();
  749. X    t1 = tt_head;
  750. X    for(rank = 1; t1->points != 0; rank++, t1 = t2) {
  751. X        t2 = t1->tt_next;
  752. X#ifdef PERS_IS_UID
  753. X        if(!playerct && t1->uid == uid)
  754. X            goto outwithit;
  755. X        else
  756. X#endif
  757. X        for(i = 0; i < playerct; i++){
  758. X            if(strcmp(players[i], "all") == 0 ||
  759. X               strncmp(t1->name, players[i], NAMSZ) == 0 ||
  760. X              (players[i][0] == '-' &&
  761. X               players[i][1] == t1->plchar &&
  762. X               players[i][2] == 0) ||
  763. X              (digit(players[i][0]) && rank <= atoi(players[i]))){
  764. X#ifdef PERS_IS_UID
  765. X            outwithit:
  766. X#endif
  767. X                if(outflg)
  768. X                    (void) outentry(rank, t1, 0);
  769. X#ifdef nonsense
  770. X                total_score += t1->points;
  771. X                if(totcharct < sizeof(totchars)-1)
  772. X                    totchars[totcharct++] = t1->plchar;
  773. X#endif
  774. X                break;
  775. X            }
  776. X        }
  777. X        dealloc_ttentry(t1);
  778. X    }
  779. X#ifdef nonsense
  780. X    totchars[totcharct] = 0;
  781. X
  782. X    /* We would like to determine whether you're experienced.  However,
  783. X       the information collected here only tells about the scores/roles
  784. X       that got into the topten (top 100?).  We should maintain a
  785. X       .hacklog or something in his home directory. */
  786. X    flags.beginner = (total_score < 6000);
  787. X    for(i=0; i<6; i++)
  788. X        if(!index(totchars, pl_classes[i])) {
  789. X        flags.beginner = 1;
  790. X        if(!pl_character[0]) pl_character[0] = pl_classes[i];
  791. X        break;
  792. X    }
  793. X#endif /* nonsense /**/
  794. X}
  795. X
  796. Xstatic int
  797. Xclassmon(plch, fem)
  798. Xchar plch;
  799. Xboolean fem;
  800. X{
  801. X    switch (plch) {
  802. X        case 'A': return PM_ARCHEOLOGIST;
  803. X        case 'B': return PM_BARBARIAN;
  804. X        case 'C': return (fem ? PM_CAVEWOMAN : PM_CAVEMAN);
  805. X        case 'E': return PM_ELF;
  806. X        case 'H': return PM_HEALER;
  807. X        case 'F':    /* accept old Fighter class */
  808. X        case 'K': return PM_KNIGHT;
  809. X        case 'P': return (fem ? PM_PRIESTESS : PM_PRIEST);
  810. X        case 'R': return PM_ROGUE;
  811. X        case 'N':    /* accept old Ninja class */
  812. X        case 'S': return PM_SAMURAI;
  813. X#ifdef TOURIST
  814. X        case 'T': return PM_TOURIST;
  815. X#else
  816. X        case 'T': return PM_HUMAN;
  817. X#endif
  818. X        case 'V': return PM_VALKYRIE;
  819. X        case 'W': return PM_WIZARD;
  820. X        default: impossible("What weird class is this? (%c)", plch);
  821. X            return PM_HUMAN_ZOMBIE;
  822. X    }
  823. X}
  824. X
  825. X/*
  826. X * Get a random player name and class from the high score list,
  827. X * and attach them to an object (for statues or morgue corpses).
  828. X */
  829. Xstruct obj *
  830. Xtt_oname(otmp)
  831. Xstruct obj *otmp;
  832. X{
  833. X    int rank;
  834. X    register int i;
  835. X    register struct toptenentry *tt;
  836. X    FILE *rfile;
  837. X
  838. X    if (!otmp) return((struct obj *) 0);
  839. X
  840. X    rfile = fopen_datafile(RECORD, "r");
  841. X    if (!rfile) {
  842. X        panic("Cannot open record file!");
  843. X    }
  844. X
  845. X    tt = newttentry();
  846. X    rank = rnd(10);
  847. Xpickentry:
  848. X    for(i = rank; i; i--) {
  849. X        readentry(rfile, tt);
  850. X        if(tt->points == 0) break;
  851. X    }
  852. X
  853. X    if(tt->points == 0) {
  854. X        if(rank > 1) {
  855. X            rank = 1;
  856. X            rewind(rfile);
  857. X            goto pickentry;
  858. X        }
  859. X        dealloc_ttentry(tt);
  860. X        otmp = (struct obj *) 0;
  861. X    } else {
  862. X        otmp->corpsenm = classmon(tt->plchar, (tt->sex == 'F'));
  863. X        otmp->owt = weight(otmp);
  864. X        /* Note: oname() is safe since otmp is first in chains */
  865. X        otmp = oname(otmp, tt->name, 0);
  866. X        fobj = otmp;
  867. X        level.objects[otmp->ox][otmp->oy] = otmp;
  868. X        dealloc_ttentry(tt);
  869. X    }
  870. X
  871. X    (void) fclose(rfile);
  872. X    return otmp;
  873. X}
  874. X
  875. X#ifdef NO_SCAN_BRACK
  876. X/* Lattice scanf isn't up to reading the scorefile.  What */
  877. X/* follows deals with that; I admit it's ugly. (KL) */
  878. X/* Now generally available (KL) */
  879. Xstatic void
  880. Xnsb_mung_line(p)
  881. X    char *p;
  882. X    {
  883. X    while(p=index(p,' '))*p='|';
  884. X}
  885. X
  886. Xstatic void
  887. Xnsb_unmung_line(p)
  888. X    char *p;
  889. X    {
  890. X    while(p=index(p,'|'))*p=' ';
  891. X}
  892. X#endif
  893. X
  894. X/*topten.c*/
  895. END_OF_FILE
  896. if test 18740 -ne `wc -c <'src/topten.c'`; then
  897.     echo shar: \"'src/topten.c'\" unpacked with wrong size!
  898. fi
  899. # end of 'src/topten.c'
  900. fi
  901. if test -f 'src/trap.c2' -a "${1}" != "-c" ; then 
  902.   echo shar: Will not clobber existing file \"'src/trap.c2'\"
  903. else
  904. echo shar: Extracting \"'src/trap.c2'\" \(31932 characters\)
  905. sed "s/^X//" >'src/trap.c2' <<'END_OF_FILE'
  906. Xint
  907. Xfloat_down()
  908. X{
  909. X    register struct trap *trap = (struct trap *)0;
  910. X    boolean no_msg = FALSE;
  911. X
  912. X    if(Levitation) return(0); /* maybe another ring/potion/boots */
  913. X
  914. X    if (Punished && !carried(uball) &&
  915. X        (is_pool(uball->ox, uball->oy) || 
  916. X         ((trap = t_at(uball->ox, uball->oy)) && 
  917. X          ((trap->ttyp == PIT) || (trap->ttyp == SPIKED_PIT) ||
  918. X           (trap->ttyp == TRAPDOOR))))) {
  919. X            u.ux0 = u.ux;
  920. X            u.uy0 = u.uy;
  921. X            u.ux = uball->ox;
  922. X            u.uy = uball->oy;
  923. X            movobj(uchain, uball->ox, uball->oy);
  924. X            newsym(u.ux0, u.uy0);
  925. X            vision_full_recalc = 1;    /* in case the hero moved. */
  926. X    }
  927. X    /* check for falling into pool - added by GAN 10/20/86 */
  928. X#ifdef POLYSELF
  929. X    if(!is_flyer(uasmon)) {
  930. X#endif
  931. X        /* kludge alert:
  932. X         * drown() and lava_effects() print various messages almost
  933. X         * every time they're called which conflict with the "fall
  934. X         * into" message below.  Thus, we want to avoid printing
  935. X         * confusing, duplicate or out-of-order messages.
  936. X         * Use knowledge of the two routines as a hack -- this
  937. X         * should really handled differently -dlc
  938. X         */
  939. X        if(is_pool(u.ux,u.uy) && !Wwalking && !u.uinwater)
  940. X            no_msg = drown();
  941. X
  942. X        if(is_lava(u.ux,u.uy)) {
  943. X            (void) lava_effects();
  944. X            no_msg = TRUE;
  945. X        }
  946. X#ifdef POLYSELF
  947. X    }
  948. X#endif
  949. X    if (!trap) {
  950. X        if(Is_airlevel(&u.uz))
  951. X            You("begin to tumble in place.");
  952. X        if(Is_waterlevel(&u.uz) && !no_msg)
  953. X            You("feel heavier.");
  954. X        /* u.uinwater msgs already in spoteffects()/drown() */
  955. X        else if (!u.uinwater && !no_msg) {
  956. X            if (Hallucination)
  957. X                pline("Bummer!  You've %s.",
  958. X                      is_pool(u.ux,u.uy) ?
  959. X                          "splashed down" : "hit the ground");
  960. X            else
  961. X                You("float gently to the %s.",
  962. X                    is_pool(u.ux,u.uy) ? "water" : "ground");
  963. X        }
  964. X        trap = t_at(u.ux,u.uy);
  965. X    }
  966. X
  967. X    if(trap)
  968. X        switch(trap->ttyp) {
  969. X        case STATUE_TRAP:
  970. X            break;
  971. X        case TRAPDOOR:
  972. X            if(!Can_fall_thru(&u.uz) || u.ustuck)
  973. X                break;
  974. X            /* fall into next case */
  975. X        default:
  976. X            dotrap(trap);
  977. X    }
  978. X    if(!flags.nopick && OBJ_AT(u.ux, u.uy) &&
  979. X       !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) &&
  980. X       (!is_pool(u.ux,u.uy) || Underwater))
  981. X        pickup(1);
  982. X    return 0;
  983. X}
  984. X
  985. X
  986. Xvoid
  987. Xtele()
  988. X{
  989. X    coord cc;
  990. X
  991. X    /* Disable teleportation in stronghold && Vlad's Tower */
  992. X    if(level.flags.noteleport) {
  993. X#ifdef WIZARD
  994. X        if (!wizard) {
  995. X#endif
  996. X            pline("A mysterious force prevents you from teleporting!");
  997. X            return;
  998. X#ifdef WIZARD
  999. X        }
  1000. X#endif
  1001. X    }
  1002. X
  1003. X    /* don't show trap if "Sorry..." */
  1004. X    if(!Blinded) make_blinded(0L,FALSE);
  1005. X
  1006. X    if((u.uhave.amulet || Is_wiz1_level(&u.uz) || Is_wiz2_level(&u.uz) ||
  1007. X           Is_wiz3_level(&u.uz)) && !rn2(3)) {
  1008. X        You("feel disoriented for a moment.");
  1009. X        return;
  1010. X    }
  1011. X    if(Teleport_control
  1012. X#ifdef WIZARD
  1013. X                || wizard
  1014. X#endif
  1015. X                    ) {
  1016. X        if (unconscious())
  1017. X        pline("Being unconscious, you cannot control your teleport.");
  1018. X        else {
  1019. X            pline("To what position do you want to be teleported?");
  1020. X            cc.x = u.ux;
  1021. X            cc.y = u.uy;
  1022. X            getpos(&cc, TRUE, "the desired position");/* force valid*/
  1023. X                    if(cc.x == -10) return; /* abort */
  1024. X            /* possible extensions: introduce a small error if
  1025. X               magic power is low; allow transfer to solid rock */
  1026. X            if(teleok(cc.x, cc.y, FALSE)){
  1027. X            teleds(cc.x, cc.y);
  1028. X            return;
  1029. X            }
  1030. X            pline("Sorry...");
  1031. X        }
  1032. X    }
  1033. X
  1034. X    (void) safe_teleds();
  1035. X}
  1036. X
  1037. Xvoid
  1038. Xteleds(nux, nuy)
  1039. Xregister int nux,nuy;
  1040. X{
  1041. X    if (Punished) unplacebc();
  1042. X    u.utrap = 0;
  1043. X    u.ustuck = 0;
  1044. X    u.ux0 = u.ux;
  1045. X    u.uy0 = u.uy;
  1046. X    u.ux = nux;
  1047. X    u.uy = nuy;
  1048. X    fill_pit(u.ux0, u.uy0); /* do this now so that cansee() is correct */
  1049. X#ifdef POLYSELF
  1050. X    if (hides_under(uasmon))
  1051. X        u.uundetected = OBJ_AT(nux, nuy);
  1052. X    else 
  1053. X        u.uundetected = 0;
  1054. X    if (u.usym == S_MIMIC_DEF) u.usym = S_MIMIC;
  1055. X#endif
  1056. X    if(Punished) placebc();
  1057. X    if(u.uswallow){
  1058. X        u.uswldtim = u.uswallow = 0;
  1059. X        docrt();
  1060. X    }
  1061. X    initrack(); /* teleports mess up tracking monsters without this */
  1062. X    /*
  1063. X     *  Make sure the hero disappears from the old location.  This will
  1064. X     *  not happen if she is teleported within sight of her previous
  1065. X     *  location.  Force a full vision recalculation because the hero
  1066. X     *  is now in a new location.
  1067. X     */
  1068. X    newsym(u.ux0,u.uy0);
  1069. X    vision_full_recalc = 1;
  1070. X    nomul(0);
  1071. X    spoteffects();
  1072. X}
  1073. X
  1074. Xint
  1075. Xdotele()
  1076. X{
  1077. X    struct trap *trap;
  1078. X    boolean castit = FALSE;
  1079. X    register int sp_no = 0;
  1080. X
  1081. X    trap = t_at(u.ux, u.uy);
  1082. X    if (trap && (!trap->tseen || trap->ttyp != TELEP_TRAP))
  1083. X        trap = 0;
  1084. X
  1085. X    if (trap) {
  1086. X        if (trap->once) {
  1087. X            pline("This is a vault teleport, usable once only.");
  1088. X            if (yn("Jump in?") == 'n')
  1089. X                trap = 0;
  1090. X            else {
  1091. X                deltrap(trap);
  1092. X                newsym(u.ux, u.uy);
  1093. X            }
  1094. X        }
  1095. X        if (trap)
  1096. X#ifdef POLYSELF
  1097. X            You("%s onto the teleportation trap.",
  1098. X                locomotion(uasmon, "jump"));
  1099. X#else
  1100. X            You("jump onto the teleportation trap.");
  1101. X#endif
  1102. X    }
  1103. X    if(!trap && (!Teleportation ||
  1104. X       (u.ulevel < (pl_character[0] == 'W' ? 8 : 12)
  1105. X#ifdef POLYSELF
  1106. X        && !can_teleport(uasmon)
  1107. X#endif
  1108. X       )
  1109. X      )) {
  1110. X        /* Try to use teleport away spell. */
  1111. X        castit = objects[SPE_TELEPORT_AWAY].oc_name_known;
  1112. X        if (castit) {
  1113. X            for (sp_no = 0; sp_no < MAXSPELL &&
  1114. X                spl_book[sp_no].sp_id != NO_SPELL &&
  1115. X                spl_book[sp_no].sp_id != SPE_TELEPORT_AWAY; sp_no++);
  1116. X
  1117. X            if (sp_no == MAXSPELL ||
  1118. X            spl_book[sp_no].sp_id != SPE_TELEPORT_AWAY)
  1119. X                castit = FALSE;
  1120. X        }
  1121. X#ifdef WIZARD
  1122. X        if (!wizard) {
  1123. X#endif
  1124. X            if (!castit) {
  1125. X            if (!Teleportation)
  1126. X                You("don't know that spell.");
  1127. X            else You("are not able to teleport at will.");
  1128. X            return(0);
  1129. X            }
  1130. X#ifdef WIZARD
  1131. X        }
  1132. X#endif
  1133. X    }
  1134. X
  1135. X    if(!trap && (u.uhunger <= 100 || ACURR(A_STR) < 6)) {
  1136. X        You("lack the strength for a teleport spell.");
  1137. X#ifdef WIZARD
  1138. X        if(!wizard)
  1139. X#endif
  1140. X        return(1);
  1141. X    }
  1142. X    if(!trap &&
  1143. X      check_capacity("Your concentration falters from carrying so much."))
  1144. X        return 1;
  1145. X
  1146. X    if (castit) {
  1147. X        exercise(A_WIS, TRUE);
  1148. X        if (spelleffects(++sp_no, TRUE))
  1149. X            return(1);
  1150. X        else
  1151. X#ifdef WIZARD
  1152. X            if (!wizard)
  1153. X#endif
  1154. X            return(0);
  1155. X    }
  1156. X#ifdef WALKIES
  1157. X    if(next_to_u()) {
  1158. X#endif
  1159. X        if (trap && trap->once) vtele();
  1160. X        else tele();
  1161. X#ifdef WALKIES
  1162. X        (void) next_to_u();
  1163. X    } else {
  1164. X        You(shudder_for_moment);
  1165. X        return(0);
  1166. X    }
  1167. X#endif
  1168. X    if (!trap) morehungry(100);
  1169. X    return(1);
  1170. X}
  1171. X
  1172. X
  1173. Xvoid
  1174. Xlevel_tele()
  1175. X{
  1176. X    register int newlev;
  1177. X    d_level newlevel;
  1178. X
  1179. X    if((u.uhave.amulet || In_endgame(&u.uz))
  1180. X#ifdef WIZARD
  1181. X                        && !wizard
  1182. X#endif
  1183. X                            ) {
  1184. X        You("feel very disoriented for a moment.");
  1185. X        return;
  1186. X    }
  1187. X    if(Teleport_control
  1188. X#ifdef WIZARD
  1189. X       || wizard
  1190. X#endif
  1191. X        ) {
  1192. X        char buf[BUFSZ];
  1193. X
  1194. X        do {
  1195. X          getlin("To what level do you want to teleport? [type a number]",
  1196. X            buf);
  1197. X        } while(!digit(buf[0]) && (buf[0] != '-' || !digit(buf[1])));
  1198. X        newlev = atoi(buf);
  1199. X
  1200. X        /* no dungeon escape via this route */
  1201. X        if(newlev == 0) {
  1202. X            if(ynq("Go to Nowhere.  Are you sure?") != 'y') return;
  1203. X            You("scream in agony as your body begins to warp...");
  1204. X        display_nhwindow(WIN_MESSAGE, FALSE);
  1205. X            You("cease to exist.");
  1206. X            killer_format = NO_KILLER_PREFIX;
  1207. X            killer = "committed suicide";
  1208. X            done(DIED);
  1209. X        return;  
  1210. X        }
  1211. X#ifdef MULDGN
  1212. X        /* if in Knox and the requested level > 0, stay put.
  1213. X         * we let negative values requests fall into the "heaven" loop.
  1214. X         */
  1215. X        if(Is_knox(&u.uz) && newlev > 0) {
  1216. X            You(shudder_for_moment);
  1217. X        return;
  1218. X        }
  1219. X        /* if in Quest, the player sees "Home 1", etc., on the status
  1220. X         * line, instead of the logical depth of the level.  controlled
  1221. X         * level teleport request is likely to be relativized to the
  1222. X         * status line, and consequently it should be incremented to 
  1223. X         * the value of the logical depth of the target level.
  1224. X         *
  1225. X         * we let negative values requests fall into the "heaven" loop.
  1226. X         */
  1227. X        if(In_quest(&u.uz) && newlev > 0)
  1228. X            newlev = newlev + dungeons[u.uz.dnum].depth_start - 1;
  1229. X#endif
  1230. X    } else { /* involuntary level tele */
  1231. X#ifdef MULDGN
  1232. X        if(Is_knox(&u.uz)) {
  1233. X            You(shudder_for_moment);
  1234. X        return;
  1235. X        }
  1236. X#endif
  1237. X        if(rn2(5)) newlev = rnd((int)depth(&u.uz) + 3);
  1238. X        else {
  1239. X        You(shudder_for_moment);
  1240. X        return; 
  1241. X        }
  1242. X        if(newlev == depth(&u.uz)) {
  1243. X        /* if in a single-level dungeon... */
  1244. X        if(dunlevs_in_dungeon(&u.uz) == 1) {
  1245. X            You(shudder_for_moment);
  1246. X            return; 
  1247. X        }
  1248. X        else if(dunlev(&u.uz) == 1) newlev++;
  1249. X        else if(dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz)) newlev--;
  1250. X            else if(In_hell(&u.uz)) newlev--;
  1251. X        else newlev++;
  1252. X        } 
  1253. X    }
  1254. X
  1255. X#ifdef WALKIES
  1256. X    if(!next_to_u()) {
  1257. X        You(shudder_for_moment);
  1258. X        return;
  1259. X    }
  1260. X#endif
  1261. X    if(newlev < 0) {
  1262. X        if(newlev <= -10) {
  1263. X            You("arrive in heaven.");
  1264. X            verbalize("Thou art early, but we'll admit thee.");
  1265. X            killer_format = NO_KILLER_PREFIX;
  1266. X            killer = "went to heaven prematurely";
  1267. X            done(DIED);
  1268. X            return;
  1269. X        } else    if (newlev == -9) {
  1270. X            You("feel deliriously happy. ");
  1271. X            pline("(In fact, you're on Cloud 9!) ");
  1272. X            display_nhwindow(WIN_MESSAGE, FALSE);
  1273. X        } else
  1274. X            You("are now high above the clouds...");
  1275. X
  1276. X        if(Levitation || is_floater(uasmon)) {
  1277. X            You("float gently down to earth.");
  1278. X            u.uz.dnum = 0; /* he might have been in another dgn */
  1279. X            newlev = 1;
  1280. X        }
  1281. X#ifdef POLYSELF
  1282. X        else if(is_flyer(uasmon)) {
  1283. X            You("fly down to earth.");
  1284. X            u.uz.dnum = 0; /* he might have been in another dgn */
  1285. X            newlev = 1;
  1286. X        }
  1287. X#endif
  1288. X        else {
  1289. X            d_level save_dlevel;
  1290. X            
  1291. X            assign_level(&save_dlevel, &u.uz);
  1292. X            pline("Unfortunately, you don't know how to fly.");
  1293. X            You("plummet a few thousand feet to your death.");
  1294. X            u.uz.dnum = 0;
  1295. X            u.uz.dlevel = 0;
  1296. X            killer_format = NO_KILLER_PREFIX;
  1297. X            killer =
  1298. X    self_pronoun("teleported out of the dungeon and fell to %s death","his");
  1299. X            done(DIED);
  1300. X            assign_level(&u.uz, &save_dlevel);
  1301. X            flags.botl = 1;
  1302. X            return;
  1303. X        }
  1304. X    }
  1305. X
  1306. X# ifdef WIZARD
  1307. X    if (In_endgame(&u.uz)) {    /* must already be wizard */
  1308. X        newlevel.dnum = u.uz.dnum;
  1309. X        newlevel.dlevel = newlev;
  1310. X        goto_level(&newlevel, FALSE, FALSE, FALSE);
  1311. X        return;
  1312. X    }
  1313. X# endif
  1314. X
  1315. X    /* calls done(ESCAPED) if newlevel==0 */
  1316. X    if(u.uz.dnum == medusa_level.dnum &&
  1317. X        newlev >= dungeons[u.uz.dnum].depth_start +
  1318. X                        dunlevs_in_dungeon(&u.uz)) {
  1319. X
  1320. X        goto_hell(TRUE, FALSE);
  1321. X    } else {
  1322. X        /* if invocation did not yet occur, teleporting into
  1323. X         * the last level of Gehennom is forbidden.
  1324. X         */
  1325. X        if(Inhell && !u.uevent.invoked &&
  1326. X            newlev >= (dungeons[u.uz.dnum].depth_start +
  1327. X                    dunlevs_in_dungeon(&u.uz) - 1)) {
  1328. X        newlev = dungeons[u.uz.dnum].depth_start +
  1329. X                    dunlevs_in_dungeon(&u.uz) - 2;
  1330. X        pline("Sorry...");
  1331. X        }
  1332. X#ifdef MULDGN
  1333. X        /* no teleporting out of quest dungeon */
  1334. X        if(In_quest(&u.uz) && newlev < depth(&qstart_level))
  1335. X        newlev = depth(&qstart_level);
  1336. X#endif
  1337. X        /* the player thinks of levels purely in logical terms, so
  1338. X         * we must translate newlev to a number relative to the
  1339. X         * current dungeon.
  1340. X           */
  1341. X        get_level(&newlevel, newlev);
  1342. X        goto_level(&newlevel, FALSE, FALSE, FALSE);
  1343. X    }
  1344. X}
  1345. X
  1346. Xstatic void
  1347. Xdofiretrap()
  1348. X{
  1349. X
  1350. X    register int num;
  1351. X
  1352. X    /* changed to be in conformance with
  1353. X     * SCR_FIRE by GAN 11/02/86
  1354. X     */
  1355. X
  1356. X    pline("A tower of flame bursts from the floor!");
  1357. X    if(Fire_resistance) {
  1358. X        shieldeff(u.ux, u.uy);
  1359. X        You("are uninjured.");
  1360. X    } else {
  1361. X        num = rnd(6);
  1362. X        u.uhpmax -= num;
  1363. X        losehp(num,"burst of flame", KILLED_BY_AN);
  1364. X    }
  1365. X    destroy_item(SCROLL_CLASS, AD_FIRE);
  1366. X    destroy_item(SPBOOK_CLASS, AD_FIRE);
  1367. X    destroy_item(POTION_CLASS, AD_FIRE);
  1368. X}
  1369. X
  1370. Xstatic void
  1371. Xdomagicportal(ttmp)
  1372. Xregister struct trap *ttmp;
  1373. X{
  1374. X    struct d_level target_level;
  1375. X
  1376. X    /* if landed from another portal, do nothing */
  1377. X    /* problem: level teleport landing escapes the check */
  1378. X    if(!on_level(&u.uz, &u.uz0)) return;
  1379. X
  1380. X    You("activated a magic portal!");
  1381. X    You("feel dizzy for a moment, but the sensation passes.");
  1382. X
  1383. X    /* prevent the poor shnook, whose amulet was stolen  */
  1384. X    /* while in the endgame, from accidently triggering  */
  1385. X    /* the portal to the next level, and thus losing the */
  1386. X    /* game                                              */
  1387. X    if(In_endgame(&u.uz) && !u.uhave.amulet) return;
  1388. X
  1389. X    target_level = ttmp->dst;
  1390. X    goto_level(&target_level, FALSE, FALSE, TRUE);
  1391. X}
  1392. X
  1393. Xstatic void
  1394. Xdomagictrap()
  1395. X{
  1396. X    register int fate = rnd(20);
  1397. X
  1398. X    /* What happened to the poor sucker? */
  1399. X
  1400. X    if (fate < 10) {
  1401. X
  1402. X      /* Most of the time, it creates some monsters. */
  1403. X      register int cnt = rnd(4);
  1404. X
  1405. X      /* below checks for blindness added by GAN 10/30/86 */
  1406. X      if (!Blind)  {
  1407. X        You("are momentarily blinded by a flash of light!");
  1408. X        make_blinded((long)rn1(5,10),FALSE);
  1409. X      }  else
  1410. X        You("hear a deafening roar!");
  1411. X      while(cnt--)
  1412. X        (void) makemon((struct permonst *) 0, u.ux, u.uy);
  1413. X    }
  1414. X    else
  1415. X      switch (fate) {
  1416. X
  1417. X         case 10:
  1418. X         case 11:
  1419. X              /* sometimes nothing happens */
  1420. X            break;
  1421. X         case 12: /* a flash of fire */
  1422. X                dofiretrap();
  1423. X            break;
  1424. X
  1425. X         /* odd feelings */
  1426. X         case 13:    pline("A shiver runs up and down your %s!",
  1427. X                  body_part(SPINE));
  1428. X            break;
  1429. X         case 14:    You(Hallucination ?
  1430. X                "hear the moon howling at you." :
  1431. X                "hear distant howling.");
  1432. X            break;
  1433. X         case 15:    You("suddenly yearn for %s.",
  1434. X                Hallucination ? "Cleveland" :
  1435. X                        "your distant homeland");
  1436. X            break;
  1437. X         case 16:   Your("pack shakes violently!");
  1438. X            break;
  1439. X         case 17:    You(Hallucination ?
  1440. X                "smell hamburgers." :
  1441. X                "smell charred flesh.");
  1442. X            break;
  1443. X
  1444. X         /* very occasionally something nice happens. */
  1445. X
  1446. X         case 19:
  1447. X            /* tame nearby monsters */
  1448. X           {   register int i,j;
  1449. X               register struct monst *mtmp;
  1450. X
  1451. X               /* below pline added by GAN 10/30/86 */
  1452. X               (void) adjattrib(A_CHA,1,FALSE);
  1453. X               for(i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
  1454. X               if(!isok(u.ux+i, u.uy+j)) continue;
  1455. X               mtmp = m_at(u.ux+i, u.uy+j);
  1456. X               if(mtmp)
  1457. X                   (void) tamedog(mtmp, (struct obj *)0);
  1458. X               }
  1459. X               break;
  1460. X           }
  1461. X
  1462. X         case 20:
  1463. X            /* uncurse stuff */
  1464. X           {  register struct obj *obj;
  1465. X
  1466. X            /* below plines added by GAN 10/30/86 */
  1467. X            You(Hallucination ?
  1468. X                "feel in touch with the Universal Oneness." :
  1469. X                "feel like someone is helping you.");
  1470. X            for(obj = invent; obj ; obj = obj->nobj)
  1471. X                   if(obj->owornmask || obj->otyp == LOADSTONE)
  1472. X                    uncurse(obj);
  1473. X               if(Punished) unpunish();
  1474. X               break;
  1475. X           }
  1476. X         default: break;
  1477. X      }
  1478. X}
  1479. X
  1480. Xvoid
  1481. Xwater_damage(obj,force)
  1482. Xregister struct obj *obj;
  1483. Xregister boolean force;
  1484. X{
  1485. X    /* Scrolls, spellbooks, potions, weapons and
  1486. X       pieces of armor may get affected by the water */
  1487. X    for(; obj; obj = obj->nobj) {
  1488. X
  1489. X        (void) snuff_lit(obj);
  1490. X
  1491. X        if(obj->greased) {
  1492. X            if (force || !rn2(2)) obj->greased = 0;
  1493. X        } else if(Is_container(obj) && !Is_box(obj) &&
  1494. X            (obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) {
  1495. X            water_damage(obj->cobj,force);
  1496. X        } else if(obj->oclass == SCROLL_CLASS && (force || rn2(12) > Luck)
  1497. X#ifdef MAIL
  1498. X              && obj->otyp != SCR_MAIL
  1499. X#endif
  1500. X              ) {
  1501. X            obj->otyp = SCR_BLANK_PAPER;
  1502. X        } else if(obj->oclass == SPBOOK_CLASS && (force || rn2(12) > Luck)) {
  1503. X            if (obj->otyp == SPE_BOOK_OF_THE_DEAD)
  1504. X                pline("Steam rises from %s.", the(xname(obj)));
  1505. X            else obj->otyp = SPE_BLANK_PAPER;
  1506. X        } else if(obj->oclass == POTION_CLASS && (force || rn2(12) > Luck)) {
  1507. X            if (obj->spe == -1) {
  1508. X                obj->otyp = POT_WATER;
  1509. X                obj->blessed = obj->cursed = 0;
  1510. X                obj->spe = 0;
  1511. X            } else obj->spe--;
  1512. X        } else if(is_rustprone(obj) && obj->oeroded < MAX_ERODE &&
  1513. X              !(obj->oerodeproof || (obj->blessed && !rnl(4))) &&
  1514. X              (force || rn2(12) > Luck)) {
  1515. X            /* all metal stuff and armor except body armor
  1516. X               protected by oilskin cloak */
  1517. X            if(obj->oclass != ARMOR_CLASS || obj != uarm ||
  1518. X               !uarmc || uarmc->otyp != OILSKIN_CLOAK ||
  1519. X                (uarmc->cursed && !rn2(3)))
  1520. X                obj->oeroded++;
  1521. X        }
  1522. X    }
  1523. X}
  1524. X
  1525. X/*
  1526. X * This function is potentially expensive - rolling
  1527. X * inventory list multiple times.  Luckily it's seldom needed.
  1528. X * Returns TRUE if disrobing made player unencumbered enough to
  1529. X * crawl out of the current predicament.
  1530. X */
  1531. Xstatic boolean
  1532. Xemergency_disrobe(lostsome)
  1533. Xboolean *lostsome;
  1534. X{
  1535. X    int invc = inv_cnt();
  1536. X
  1537. X    while (near_capacity() > (Punished ? UNENCUMBERED : SLT_ENCUMBER)) {
  1538. X        register struct obj *obj, *otmp = (struct obj *)0;
  1539. X        register int i = rn2(invc);
  1540. X
  1541. X        for (obj = invent; obj; obj = obj->nobj) {
  1542. X            /*
  1543. X             * Undroppables are: body armor, boots, gloves,
  1544. X             * amulets, and rings because of the time and effort
  1545. X             * in removing them + loadstone and other cursed stuff
  1546. X             * for obvious reasons.
  1547. X             */
  1548. X            if (!(obj->otyp == LOADSTONE ||
  1549. X                  obj == uamul || obj == uleft || obj == uright ||
  1550. X                  obj == ublindf || obj == uarm || obj == uarmc ||
  1551. X                  obj == uarmg || obj == uarmf ||
  1552. X#ifdef TOURIST
  1553. X                  obj == uarmu ||
  1554. X#endif
  1555. X                  (obj->cursed && (obj == uarmh || obj == uarms)) ||
  1556. X                  welded(obj)))
  1557. X                otmp = obj;
  1558. X            /* reached the mark and found some stuff to drop? */
  1559. X            if (--i < 0 && otmp) break;
  1560. X
  1561. X            /* else continue */
  1562. X        }
  1563. X
  1564. X        /* nothing to drop and still overweight */
  1565. X        if (!otmp) return(FALSE);
  1566. X
  1567. X        if (otmp == uarmh) (void) Helmet_off();
  1568. X        else if (otmp == uarms) (void) Shield_off();
  1569. X        else if (otmp == uwep) setuwep((struct obj *)0);
  1570. X        *lostsome = TRUE;
  1571. X        dropx(otmp);
  1572. X        invc--;
  1573. X    }
  1574. X    return(TRUE);
  1575. X}
  1576. X
  1577. X/*
  1578. X *  return(TRUE) == player relocated
  1579. X */
  1580. Xboolean
  1581. Xdrown()
  1582. X{
  1583. X    boolean inpool_ok = FALSE, crawl_ok;
  1584. X    int i, x, y;
  1585. X
  1586. X    /* happily wading in the same contiguous pool */
  1587. X    if (u.uinwater && is_pool(u.ux-u.dx,u.uy-u.dy) &&
  1588. X       Magical_breathing) {
  1589. X        /* water effects on objects every now and then */
  1590. X        if (!rn2(5)) inpool_ok = TRUE;
  1591. X        else return(FALSE);
  1592. X    }
  1593. X
  1594. X    if (!u.uinwater) {
  1595. X        You("%s into the water!",
  1596. X        Is_waterlevel(&u.uz) ? "plunge" : "fall");
  1597. X#ifdef POLYSELF
  1598. X        if(!is_swimmer(uasmon))
  1599. X#endif
  1600. X        if (!Is_waterlevel(&u.uz))
  1601. X            You("sink like %s.",
  1602. X            Hallucination ? "the Titanic" : "a rock");
  1603. X    }
  1604. X
  1605. X    water_damage(invent,FALSE);
  1606. X
  1607. X#ifdef POLYSELF
  1608. X    if(u.umonnum == PM_GREMLIN && rn2(3)) {
  1609. X        struct monst *mtmp;
  1610. X        if(mtmp = cloneu()) {
  1611. X            mtmp->mhpmax = (u.mhmax /= 2);
  1612. X            You("multiply.");
  1613. X        }
  1614. X    }
  1615. X
  1616. X    if(is_swimmer(uasmon)) return(FALSE);
  1617. X#endif
  1618. X    if (inpool_ok) return(FALSE);
  1619. X#ifdef WALKIES
  1620. X    if ((i = number_leashed()) > 0) {
  1621. X        pline("The leash%s slip%s loose.",
  1622. X            (i > 1) ? "es" : "",
  1623. X            (i > 1) ? "" : "s");
  1624. X        unleash_all();
  1625. X    }
  1626. X#endif
  1627. X    if (Magical_breathing) {
  1628. X        pline("But wait!");
  1629. X        Your("lungs start acting like gills.");
  1630. X        if (!Is_waterlevel(&u.uz))
  1631. X            Your("%s the bottom.",Hallucination ? "keel hits" : "feet touch");
  1632. X        if (Punished) placebc();
  1633. X        u.uinwater = 1;
  1634. X        under_water(1);
  1635. X        return(FALSE);
  1636. X    }
  1637. X    if((Teleportation || can_teleport(uasmon)) &&
  1638. X       (Teleport_control || rn2(3) < Luck+2)) {
  1639. X        You("attempt a teleport spell.");    /* utcsri!carroll */
  1640. X        (void) dotele();
  1641. X        if(!is_pool(u.ux,u.uy))
  1642. X            return(TRUE);
  1643. X    }
  1644. X    crawl_ok = FALSE;
  1645. X    /* look around for a place to crawl to */
  1646. X    for (i = 0; i < 100; i++) {
  1647. X        x = rn1(3,u.ux - 1);
  1648. X        y = rn1(3,u.uy - 1);
  1649. X        if (teleok(x,y,TRUE)) {
  1650. X            crawl_ok = TRUE;
  1651. X            goto crawl;
  1652. X        }
  1653. X    }
  1654. X    /* one more scan */
  1655. X    for (x = u.ux - 1; x <= u.ux + 1; x++)
  1656. X        for (y = u.uy - 1; y <= u.uy + 1; y++)
  1657. X            if (teleok(x,y,TRUE)) {
  1658. X                crawl_ok = TRUE;
  1659. X                goto crawl;
  1660. X            }
  1661. Xcrawl:;
  1662. X    if (crawl_ok) {
  1663. X        boolean lost = FALSE;
  1664. X        /* time to do some strip-tease... */
  1665. X        boolean succ = Is_waterlevel(&u.uz) ? TRUE :
  1666. X                emergency_disrobe(&lost);
  1667. X
  1668. X        You("try to crawl out of the water.");
  1669. X        if (lost)
  1670. X            You("dump some of your gear to lose weight...");
  1671. X        if (succ) {
  1672. X            pline("Pheew!  That was close.");
  1673. X            teleds(x,y);
  1674. X            return(TRUE);
  1675. X        }
  1676. X        /* still too much weight */
  1677. X        pline("But in vain.");
  1678. X    }
  1679. X    u.uinwater = 1;
  1680. X    You("drown.");
  1681. X    killer_format = KILLED_BY_AN;
  1682. X    killer = (levl[u.ux][u.uy].typ == POOL || Is_medusa_level(&u.uz)) ?
  1683. X        "pool of water" : "moat";
  1684. X    done(DROWNING);
  1685. X    /* oops, we're still alive.  better get out of the water. */
  1686. X    if (!safe_teleds())
  1687. X        while (1) {
  1688. X            pline("You're still drowning.");
  1689. X            done(DROWNING);
  1690. X        }
  1691. X    u.uinwater = 0;
  1692. X    You("find yourself back %s.",Is_waterlevel(&u.uz) ?
  1693. X        "in an air bubble" : "on dry land");
  1694. X    return(TRUE);
  1695. X}
  1696. X
  1697. Xvoid
  1698. Xdrain_en(n)
  1699. Xregister int n;
  1700. X{
  1701. X    if (!u.uenmax) return;
  1702. X    You("feel your magical energy drain away!");
  1703. X    u.uen -= n;
  1704. X    if(u.uen < 0)  {
  1705. X        u.uenmax += u.uen;
  1706. X        if(u.uenmax < 0) u.uenmax = 0;
  1707. X        u.uen = 0;
  1708. X    }
  1709. X    flags.botl = 1;
  1710. X}
  1711. X
  1712. Xint
  1713. Xdountrap()    /* disarm a trapped object */
  1714. X{
  1715. X#ifdef POLYSELF
  1716. X    if(nohands(uasmon)) {
  1717. X        pline("And just how do you expect to do that?");
  1718. X        return(0);
  1719. X    }
  1720. X#endif
  1721. X    return untrap(FALSE);
  1722. X}
  1723. X
  1724. Xint
  1725. Xuntrap(force)
  1726. Xboolean force;
  1727. X{
  1728. X    register struct obj *otmp;
  1729. X    register boolean confused = (Confusion > 0 || Hallucination > 0);
  1730. X    register int x,y;
  1731. X    int ch;
  1732. X    struct trap *ttmp;
  1733. X    struct monst *mtmp;
  1734. X    boolean trap_skipped = FALSE;
  1735. X
  1736. X    if(!getdir(NULL)) return(0);
  1737. X    x = u.ux + u.dx;
  1738. X    y = u.uy + u.dy;
  1739. X
  1740. X    if(!u.dx && !u.dy) {
  1741. X        for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
  1742. X        if(Is_box(otmp)) {
  1743. X            pline("There is %s here.", doname(otmp));
  1744. X
  1745. X            switch (ynq("Check for traps?")) {
  1746. X            case 'q': return(0);
  1747. X            case 'n': continue;
  1748. X            }
  1749. X
  1750. X            if((otmp->otrapped && (force || (!confused
  1751. X                && rn2(MAXULEV + 1 - (int)u.ulevel) < 10)))
  1752. X               || (!force && confused && !rn2(3))) {
  1753. X            You("find a trap on %s!", the(xname(otmp)));
  1754. X            exercise(A_WIS, TRUE);
  1755. X
  1756. X            switch (ynq("Disarm it?")) {
  1757. X                case 'q': return(1);
  1758. X                case 'n': trap_skipped = TRUE;  continue;
  1759. X            }
  1760. X
  1761. X            if(otmp->otrapped) {
  1762. X                exercise(A_DEX, TRUE);
  1763. X                ch = ACURR(A_DEX) + u.ulevel;
  1764. X                if (pl_character[0] == 'R') ch *= 2;
  1765. X                if(!force && (confused || Fumbling ||
  1766. X                rnd(75+level_difficulty()/2) > ch)) {
  1767. X                (void) chest_trap(otmp, FINGER, TRUE);
  1768. X                } else {
  1769. X                You("disarm it!");
  1770. X                otmp->otrapped = 0;
  1771. X                }
  1772. X            } else pline("That %s was not trapped.", doname(otmp));
  1773. X            return(1);
  1774. X            } else {
  1775. X            You("find no traps on %s.", the(xname(otmp)));
  1776. X            return(1);
  1777. X            }
  1778. X        }
  1779. X        if ((ttmp = t_at(x,y)) && ttmp->tseen)
  1780. X        You("cannot disable this trap.");
  1781. X        else
  1782. X        You(trap_skipped ? "find no other traps here."
  1783. X                 : "know of no traps here.");
  1784. X        return(0);
  1785. X    }
  1786. X
  1787. X    if ((mtmp = m_at(x,y))                &&
  1788. X        mtmp->m_ap_type == M_AP_FURNITURE    &&
  1789. X        (mtmp->mappearance == S_hcdoor ||
  1790. X            mtmp->mappearance == S_vcdoor)    &&
  1791. X        !Protection_from_shape_changers)     {
  1792. X
  1793. X        stumble_onto_mimic(mtmp);
  1794. X        return(1);
  1795. X    }
  1796. X
  1797. X    if (!IS_DOOR(levl[x][y].typ)) {
  1798. X        if ((ttmp = t_at(x,y)) && ttmp->tseen)
  1799. X        You("cannot disable that trap.");
  1800. X        else
  1801. X        You("know of no traps there.");
  1802. X        return(0);
  1803. X    }
  1804. X
  1805. X    switch (levl[x][y].doormask) {
  1806. X        case D_NODOOR:
  1807. X        You("%s no door there.", Blind ? "feel" : "see");
  1808. X        return(0);
  1809. X        case D_ISOPEN:
  1810. X        pline("This door is safely open.");
  1811. X        return(0);
  1812. X        case D_BROKEN:
  1813. X        pline("This door is broken.");
  1814. X        return(0);
  1815. X    }
  1816. X
  1817. X    if ((levl[x][y].doormask & D_TRAPPED
  1818. X         && (force ||
  1819. X         (!confused && rn2(MAXULEV - (int)u.ulevel + 11) < 10)))
  1820. X        || (!force && confused && !rn2(3))) {
  1821. X        You("find a trap on the door!");
  1822. X        exercise(A_WIS, TRUE);
  1823. X        if (ynq("Disarm it?") != 'y') return(1);
  1824. X        if (levl[x][y].doormask & D_TRAPPED) {
  1825. X            ch = 15 +
  1826. X             (pl_character[0] == 'R') ? u.ulevel*3 :
  1827. X             u.ulevel;
  1828. X            exercise(A_DEX, TRUE);
  1829. X            if(!force && (confused || Fumbling || 
  1830. X                             rnd(75+level_difficulty()/2) > ch)) {
  1831. X                You("set it off!");
  1832. X                b_trapped("door");
  1833. X            } else
  1834. X                You("disarm it!");
  1835. X            levl[x][y].doormask &= ~D_TRAPPED;
  1836. X        } else pline("This door was not trapped.");
  1837. X        return(1);
  1838. X    } else {
  1839. X        You("find no traps on the door.");
  1840. X        return(1);
  1841. X    }
  1842. X}
  1843. X
  1844. X/* only called when the player is doing something to the chest directly */
  1845. Xboolean
  1846. Xchest_trap(obj, bodypart, disarm)
  1847. Xregister struct obj *obj;
  1848. Xregister int bodypart;
  1849. Xboolean disarm;
  1850. X{
  1851. X    register struct obj *otmp = obj, *otmp2;
  1852. X    char    buf[80];
  1853. X    const char *msg;
  1854. X
  1855. X    You(disarm ? "set it off!" : "trigger a trap!");
  1856. X    display_nhwindow(WIN_MESSAGE, FALSE);
  1857. X    if (Luck > -13 && rn2(13+Luck) > 7) {    /* saved by luck */
  1858. X        /* trap went off, but good luck prevents damage */
  1859. X        switch (rn2(13)) {
  1860. X        case 12:
  1861. X        case 11:  msg = "explosive charge is a dud";  break;
  1862. X        case 10:
  1863. X        case  9:  msg = "electric charge is grounded";  break;
  1864. X        case  8:
  1865. X        case  7:  msg = "flame fizzles out";  break;
  1866. X        case  6:
  1867. X        case  5:
  1868. X        case  4:  msg = "poisoned needle misses";  break;
  1869. X        case  3:
  1870. X        case  2:
  1871. X        case  1:
  1872. X        case  0:  msg = "gas cloud blows away";  break;
  1873. X        default:  impossible("chest disarm bug");  msg = NULL;  break;
  1874. X        }
  1875. X        if (msg) pline("But luckily the %s!", msg);
  1876. X    } else {
  1877. X        switch(rn2(20) ? ((Luck >= 13) ? 0 : rn2(13-Luck)) : rn2(26)) {
  1878. X        case 25:
  1879. X        case 24:
  1880. X        case 23:
  1881. X        case 22:
  1882. X        case 21: {
  1883. X                  register struct monst *shkp;
  1884. X              long loss = 0L;
  1885. X              boolean costly, insider;
  1886. X              register xchar ox = obj->ox, oy = obj->oy;
  1887. X
  1888. X#ifdef GCC_WARN
  1889. X              shkp = (struct monst *) 0;
  1890. X#endif
  1891. X              /* the obj location need not be that of player */
  1892. X              costly = (costly_spot(ox, oy) && 
  1893. X                   (shkp = shop_keeper(*in_rooms(ox, oy,
  1894. X                    SHOPBASE))) != (struct monst *)0);
  1895. X              insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
  1896. X                    *in_rooms(ox, oy, SHOPBASE) == *u.ushops);
  1897. X
  1898. X              pline("%s explodes!", The(xname(obj)));
  1899. X              Sprintf(buf, "exploding %s", xname(obj));
  1900. X
  1901. X              if(costly)
  1902. X                  loss += stolen_value(obj, ox, oy,
  1903. X                        (boolean)shkp->mpeaceful, TRUE);
  1904. X              delete_contents(obj);
  1905. X              for(otmp = level.objects[u.ux][u.uy];
  1906. X                            otmp; otmp = otmp2) {
  1907. X                  otmp2 = otmp->nexthere;
  1908. X                  if(costly)
  1909. X                      loss += stolen_value(otmp, otmp->ox, 
  1910. X                      otmp->oy, (boolean)shkp->mpeaceful,
  1911. X                      TRUE);
  1912. X                  delobj(otmp);
  1913. X              }
  1914. X              exercise(A_STR, FALSE);
  1915. X              losehp(d(6,6), buf, KILLED_BY_AN);
  1916. X              if(costly && loss) {
  1917. X                  if(insider)
  1918. X                  You("owe %ld zorkmids for objects destroyed.",
  1919. X                                              loss);
  1920. X                  else {
  1921. X                            You("caused %ld zorkmids worth of damage!",
  1922. X                                                  loss);
  1923. X                      make_angry_shk(shkp, ox, oy);
  1924. X                  }
  1925. X              }
  1926. X              wake_nearby();
  1927. X              return TRUE;
  1928. X            }
  1929. X        case 20:
  1930. X        case 19:
  1931. X        case 18:
  1932. X        case 17:
  1933. X            pline("A cloud of noxious gas billows from %s.",
  1934. X                  the(xname(obj)));
  1935. X            poisoned("gas cloud", A_STR, "cloud of poison gas",15);
  1936. X            exercise(A_CON, FALSE);
  1937. X            break;
  1938. X        case 16:
  1939. X        case 15:
  1940. X        case 14:
  1941. X        case 13:
  1942. X            You("feel a needle prick your %s.",body_part(bodypart));
  1943. X            poisoned("needle", A_CON, "poison needle",10);
  1944. X            exercise(A_CON, FALSE);
  1945. X            break;
  1946. X        case 12:
  1947. X        case 11:
  1948. X        case 10:
  1949. X        case 9:
  1950. X            pline("A tower of flame erupts from %s!",
  1951. X                  the(xname(obj)));
  1952. X            if(Fire_resistance) {
  1953. X                shieldeff(u.ux, u.uy);
  1954. X                You("don't seem to be affected.");
  1955. X            } else    losehp(d(4, 6), "tower of flame", KILLED_BY_AN);
  1956. X            destroy_item(SCROLL_CLASS, AD_FIRE);
  1957. X            destroy_item(SPBOOK_CLASS, AD_FIRE);
  1958. X            destroy_item(POTION_CLASS, AD_FIRE);
  1959. X            break;
  1960. X        case 8:
  1961. X        case 7:
  1962. X        case 6:
  1963. X            You("are jolted by a surge of electricity!");
  1964. X            if(Shock_resistance)  {
  1965. X                shieldeff(u.ux, u.uy);
  1966. X                You("don't seem to be affected.");
  1967. X            } else    losehp(d(4, 4), "electric shock", KILLED_BY_AN);
  1968. X            destroy_item(RING_CLASS, AD_ELEC);
  1969. X            destroy_item(WAND_CLASS, AD_ELEC);
  1970. X            break;
  1971. X        case 5:
  1972. X        case 4:
  1973. X        case 3:
  1974. X            pline("Suddenly you are frozen in place!");
  1975. X            nomul(-d(5, 6));
  1976. X            exercise(A_DEX, FALSE);
  1977. X            nomovemsg = "You can move again.";
  1978. X            break;
  1979. X        case 2:
  1980. X        case 1:
  1981. X        case 0:
  1982. X            pline("A cloud of %s gas billows from %s",
  1983. X                  hcolor(), the(xname(obj)));
  1984. X            if(!Stunned)
  1985. X                if (Hallucination)
  1986. X                pline("What a groovy feeling!");
  1987. X                else
  1988. X                You("stagger and your vision blurs...");
  1989. X            make_stunned(HStun + rn1(7, 16),FALSE);
  1990. X            make_hallucinated(HHallucination + rn1(5, 16),FALSE,0L);
  1991. X            break;
  1992. X        default: impossible("bad chest trap");
  1993. X            break;
  1994. X        }
  1995. X        bot();            /* to get immediate botl re-display */
  1996. X    }
  1997. X    otmp->otrapped = 0;        /* these traps are one-shot things */
  1998. X
  1999. X    return FALSE;
  2000. X}
  2001. X
  2002. X#endif /* OVLB */
  2003. X#ifdef OVL0
  2004. X
  2005. Xstruct trap *
  2006. Xt_at(x,y)
  2007. Xregister int x, y;
  2008. X{
  2009. X    register struct trap *trap = ftrap;
  2010. X    while(trap) {
  2011. X        if(trap->tx == x && trap->ty == y) return(trap);
  2012. X        trap = trap->ntrap;
  2013. X    }
  2014. X    return((struct trap *)0);
  2015. X}
  2016. X
  2017. X#endif /* OVL0 */
  2018. X#ifdef OVLB
  2019. X
  2020. Xvoid
  2021. Xdeltrap(trap)
  2022. Xregister struct trap *trap;
  2023. X{
  2024. X    register struct trap *ttmp;
  2025. X
  2026. X    if(trap == ftrap)
  2027. X        ftrap = ftrap->ntrap;
  2028. X    else {
  2029. X        for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
  2030. X        ttmp->ntrap = trap->ntrap;
  2031. X    }
  2032. X    dealloc_trap(trap);
  2033. X}
  2034. X
  2035. X/* used for doors.  can be used for anything else that opens. */
  2036. Xvoid
  2037. Xb_trapped(item)
  2038. Xregister const char *item;
  2039. X{
  2040. X    register int lvl = level_difficulty();
  2041. X    int dmg = rnd(5 + (lvl<5 ? lvl : 2+lvl/2));
  2042. X
  2043. X    pline("KABOOM!!  %s was booby-trapped!", The(item));
  2044. X    if (u.ulevel < 4 && lvl < 3 && !rnl(3))
  2045. X        You("are shaken, but luckily unhurt.");        
  2046. X    else losehp(dmg, "explosion", KILLED_BY_AN);
  2047. X    exercise(A_STR, FALSE);
  2048. X    make_stunned(HStun + dmg, TRUE);
  2049. X}
  2050. X
  2051. X/* Monster is hit by trap. */
  2052. X/* Note: doesn't work if both obj and d_override are null */
  2053. XSTATIC_OVL boolean
  2054. Xthitm(tlev, mon, obj, d_override)
  2055. Xregister int tlev;
  2056. Xregister struct monst *mon;
  2057. Xregister struct obj *obj;
  2058. Xint d_override;
  2059. X{
  2060. X    register int strike;
  2061. X    register boolean trapkilled = FALSE;
  2062. X
  2063. X    if (d_override) strike = 1;
  2064. X    else if (obj) strike = (find_mac(mon) + tlev + obj->spe <= rnd(20));
  2065. X    else strike = (find_mac(mon) + tlev <= rnd(20));
  2066. X
  2067. X    /* Actually more accurate than thitu, which doesn't take
  2068. X     * obj->spe into account.
  2069. X     */
  2070. X    if(!strike) {
  2071. X        if (cansee(mon->mx, mon->my))
  2072. X            pline("%s is almost hit by %s!", Monnam(mon),
  2073. X                                doname(obj));
  2074. X    } else {
  2075. X        int dam = 1;
  2076. X
  2077. X        if (obj && cansee(mon->mx, mon->my))
  2078. X            pline("%s is hit by %s!", Monnam(mon), doname(obj));
  2079. X        if (d_override) dam = d_override;
  2080. X        else if (obj) {
  2081. X            dam = dmgval(obj, mon->data);
  2082. X            if (dam < 1) dam = 1;
  2083. X        }
  2084. X        if ((mon->mhp -= dam) <= 0) {
  2085. X            int xx = mon->mx;
  2086. X            int yy = mon->my;
  2087. X
  2088. X            monkilled(mon, "", AD_PHYS);
  2089. X            newsym(xx, yy);
  2090. X            trapkilled = TRUE;
  2091. X        }
  2092. X    }
  2093. X    if (obj && (!strike || d_override)) {
  2094. X        place_object(obj, mon->mx, mon->my);
  2095. X        obj->nobj = fobj;
  2096. X        fobj = obj;
  2097. X        stackobj(fobj);
  2098. X    } else if (obj) dealloc_obj(obj);
  2099. X
  2100. X    return trapkilled;
  2101. X}
  2102. X
  2103. Xboolean
  2104. Xunconscious()
  2105. X{
  2106. X    return (multi < 0 && (!nomovemsg ||
  2107. X        u.usleep ||
  2108. X        !strncmp(nomovemsg,"You regain con", 15) ||
  2109. X        !strncmp(nomovemsg,"You are consci", 15)));
  2110. X}
  2111. X
  2112. Xstatic char lava_killer[] = "molten lava";
  2113. X
  2114. Xboolean
  2115. Xlava_effects()
  2116. X{
  2117. X    register struct obj *obj, *obj2;
  2118. X    int dmg;
  2119. X
  2120. X    if (!Fire_resistance) {
  2121. X    if(Wwalking) {
  2122. X        dmg = d(6,6);
  2123. X        pline("The lava here burns you!");
  2124. X        if(dmg < u.uhp) {
  2125. X        losehp(dmg, lava_killer, KILLED_BY);
  2126. X        goto burn_stuff;
  2127. X        }
  2128. X    } else
  2129. X        You("fall into the lava!");
  2130. X
  2131. X    for(obj = invent; obj; obj = obj2) {
  2132. X        obj2 = obj->nobj;
  2133. X        if(is_organic(obj) && !obj->oerodeproof) {
  2134. X        if(obj->owornmask) {
  2135. X            if(obj == uarm) (void) Armor_gone();
  2136. X            else if(obj == uarmc) (void) Cloak_off();
  2137. X            else if(obj == uarmh) (void) Helmet_off();
  2138. X            else if(obj == uarms) (void) Shield_off();
  2139. X            else if(obj == uarmg) (void) Gloves_off();
  2140. X            else if(obj == uarmf) (void) Boots_off();
  2141. X#ifdef TOURIST
  2142. X            else if(obj == uarmu) setnotworn(obj);
  2143. X#endif
  2144. X            else if(obj == uleft) Ring_gone(obj);
  2145. X            else if(obj == uright) Ring_gone(obj);
  2146. X            else if(obj == ublindf) Blindf_off(obj);
  2147. X            else if(obj == uwep) uwepgone();
  2148. X            if(Lifesaved
  2149. X#ifdef WIZARD
  2150. X               || wizard
  2151. X#endif
  2152. X               ) Your("%s into flame!", aobjnam(obj, "burst"));
  2153. X        }
  2154. X        useup(obj);
  2155. X        }
  2156. X    }
  2157. X
  2158. X    /* s/he died... */
  2159. X    u.uhp = -1;
  2160. X    killer_format = KILLED_BY;
  2161. X    killer = lava_killer;
  2162. X    You("burn to a crisp...");
  2163. X    done(BURNING);
  2164. X    if (!safe_teleds())
  2165. X        while (1) {
  2166. X            pline("You're still burning.");
  2167. X            done(BURNING);
  2168. X        }
  2169. X    You("find yourself back on solid ground.");
  2170. X    return(TRUE);
  2171. X    }
  2172. X
  2173. X    if (!Wwalking) {
  2174. X    u.utrap = rn1(4, 4) + (rn1(4, 12) << 8);
  2175. X    u.utraptype = TT_LAVA;
  2176. X    You("sink into the lava, but it doesn't burn you!");
  2177. X    }
  2178. X    /* just want to burn boots, not all armor; destroy_item doesn't work on
  2179. X       armor anyway */
  2180. Xburn_stuff:
  2181. X    if(uarmf && !uarmf->oerodeproof && is_organic(uarmf)) {
  2182. X    /* save uarmf value because Boots_off() sets uarmf to NULL */
  2183. X    obj = uarmf;
  2184. X    Your("%s burst into flame!", xname(obj));
  2185. X    (void) Boots_off();
  2186. X    useup(obj);
  2187. X    }
  2188. X    destroy_item(SCROLL_CLASS, AD_FIRE);
  2189. X    destroy_item(SPBOOK_CLASS, AD_FIRE);
  2190. X    destroy_item(POTION_CLASS, AD_FIRE);
  2191. X    return(FALSE);
  2192. X}
  2193. X
  2194. X#endif /* OVLB */
  2195. X
  2196. X/*trap.c*/
  2197. END_OF_FILE
  2198. if test 31932 -ne `wc -c <'src/trap.c2'`; then
  2199.     echo shar: \"'src/trap.c2'\" unpacked with wrong size!
  2200. fi
  2201. # end of 'src/trap.c2'
  2202. fi
  2203. echo shar: End of archive 67 \(of 108\).
  2204. cp /dev/null ark67isdone
  2205. MISSING=""
  2206. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2207. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2208. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2209. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2210. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2211. 101 102 103 104 105 106 107 108 ; do
  2212.     if test ! -f ark${I}isdone ; then
  2213.     MISSING="${MISSING} ${I}"
  2214.     fi
  2215. done
  2216. if test "${MISSING}" = "" ; then
  2217.     echo You have unpacked all 108 archives.
  2218.     echo "Now execute 'rebuild.sh'"
  2219.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2220. else
  2221.     echo You still need to unpack the following archives:
  2222.     echo "        " ${MISSING}
  2223. fi
  2224. ##  End of shell archive.
  2225. exit 0
  2226.