home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume10 / nethack3p9 / part34 < prev    next >
Internet Message Format  |  1990-07-27  |  61KB

  1. Path: uunet!lll-winken!sun-barr!cs.utexas.edu!rice!uw-beaver!zephyr.ens.tek.com!tekred!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v10i079:  nethack3p9 -  display oriented dungeons & dragons (Ver. 3.0i), Part34/56
  5. Message-ID: <5937@tekred.CNA.TEK.COM>
  6. Date: 12 Jul 90 16:07:40 GMT
  7. Sender: news@tekred.CNA.TEK.COM
  8. Lines: 2504
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
  12. Posting-number: Volume 10, Issue 79
  13. Archive-name: nethack3p9/Part34
  14. Supersedes: NetHack3: Volume 7, Issue 56-93
  15.  
  16.  
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 34 (of 56)."
  25. # Contents:  src/dbridge.c src/pager.c src/sit.c
  26. # Wrapped by billr@saab on Wed Jul 11 17:11:42 1990
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'src/dbridge.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'src/dbridge.c'\"
  30. else
  31. echo shar: Extracting \"'src/dbridge.c'\" \(20980 characters\)
  32. sed "s/^X//" >'src/dbridge.c' <<'END_OF_FILE'
  33. X/*     SCCS Id: @(#)dbridge.c  3.0     88/18/12
  34. X/*     Copyright (c) 1989 by Jean-Christophe Collet */
  35. X/* NetHack may be freely redistributed.  See license for details. */
  36. X
  37. X/*
  38. X * This file contains the drawbridge manipulation (create, open, close,
  39. X * destroy).
  40. X *
  41. X * Added comprehensive monster-handling, and the "entity" structure to 
  42. X * deal with players as well. - 11/89
  43. X */
  44. X
  45. X#include "hack.h"
  46. X
  47. X#ifdef STRONGHOLD
  48. X# ifdef OVLB
  49. Xstatic void FDECL(redosym, (int, int));
  50. Xstatic void FDECL(get_wall_for_db, (int *, int *));
  51. Xstatic struct entity *FDECL(e_at, (int, int));
  52. Xstatic void FDECL(m_to_e, (struct monst *, struct entity *));
  53. Xstatic void FDECL(u_to_e, (struct entity *));
  54. Xstatic void FDECL(set_entity, (int, int, struct entity *));
  55. Xstatic char *FDECL(e_nam, (struct entity *));
  56. X/* static char *FDECL(Enam, (struct entity *)); */ /* unused */
  57. Xstatic char *FDECL(E_phrase, (struct entity *, const char *));
  58. Xstatic boolean FDECL(e_survives_at, (struct entity *, int, int));
  59. Xstatic void FDECL(e_died, (struct entity *, int, int));
  60. Xstatic boolean FDECL(automiss, (struct entity *));
  61. Xstatic boolean FDECL(e_missed, (struct entity *, BOOLEAN_P));
  62. Xstatic boolean FDECL(e_jumps, (struct entity *));
  63. Xstatic void FDECL(do_entity, (struct entity *));
  64. X# endif /* OVLB */
  65. X#endif /* STRONGHOLD */
  66. X
  67. X#ifdef OVL0
  68. X
  69. Xboolean
  70. Xis_pool(x,y)
  71. Xint x,y;
  72. X{
  73. X       if(levl[x][y].typ == POOL || levl[x][y].typ == MOAT) return TRUE;
  74. X#ifdef STRONGHOLD
  75. X       if(levl[x][y].typ == DRAWBRIDGE_UP &&
  76. X               (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT) return TRUE;
  77. X#endif
  78. X       return FALSE;
  79. X}
  80. X
  81. X#endif /* OVL0 */
  82. X
  83. X#ifdef STRONGHOLD
  84. X
  85. X#ifdef OVL1
  86. X
  87. Xvoid
  88. Xinitsym(x,y)
  89. Xint x,y;
  90. X{
  91. X    char oldseen;
  92. X    struct rm *crm = &levl[x][y];
  93. X
  94. X    oldseen = crm->seen;
  95. X    crm->seen = 1;
  96. X    crm->scrsym = news0(x,y);
  97. X    crm->seen = oldseen;
  98. X}
  99. X
  100. X#endif /* OVL1 */
  101. X#ifdef OVLB
  102. X
  103. Xstatic void
  104. Xredosym(x,y)
  105. Xint x,y;
  106. X{
  107. X    if(cansee(x,y)) {
  108. X        levl[x][y].seen = 0;            /* force prl */
  109. X        prl(x, y);
  110. X    } else {
  111. X        initsym(x,y);
  112. X        levl[x][y].seen = 0;
  113. X    }
  114. X}
  115. X
  116. X#endif /* OVLB */
  117. X#ifdef OVL1
  118. X
  119. X/* 
  120. X * We want to know whether a wall (or a door) is the portcullis (passageway)
  121. X * of an eventual drawbridge.
  122. X *
  123. X * Return value:  the direction of the drawbridge.
  124. X */
  125. X
  126. Xint
  127. Xis_drawbridge_wall(x,y)
  128. Xint x,y;
  129. X{
  130. X    struct rm *lev;
  131. X
  132. X    lev = &levl[x][y];
  133. X    if (lev->typ != DOOR && !(lev->diggable & W_GATEWAY))
  134. X        return (-1);
  135. X    switch (lev->typ) {
  136. X    case DOOR:
  137. X    case VWALL:
  138. X        if (IS_DRAWBRIDGE(levl[x+1][y].typ) &&
  139. X             (levl[x+1][y].drawbridgemask & DB_DIR) == DB_WEST)
  140. X            return (DB_WEST);
  141. X        if (IS_DRAWBRIDGE(levl[x-1][y].typ) && 
  142. X            (levl[x-1][y].drawbridgemask & DB_DIR) == DB_EAST)
  143. X            return (DB_EAST);
  144. X        if (lev->typ == VWALL) break;
  145. X    case HWALL:
  146. X        if (IS_DRAWBRIDGE(levl[x][y-1].typ) && 
  147. X            (levl[x][y-1].drawbridgemask & DB_DIR) == DB_SOUTH)
  148. X            return (DB_SOUTH);
  149. X        if (IS_DRAWBRIDGE(levl[x][y+1].typ) && 
  150. X            (levl[x][y+1].drawbridgemask & DB_DIR) == DB_NORTH)
  151. X            return (DB_NORTH);
  152. X    }
  153. X    return (-1);
  154. X}
  155. X
  156. X/*
  157. X * Use is_db_wall where you want to verify that a
  158. X * drawbridge "wall" is UP in the location x, y
  159. X * (instead of UP or DOWN, as with is_drawbridge_wall). 
  160. X */ 
  161. Xboolean
  162. Xis_db_wall(x,y)
  163. Xint x,y;
  164. X{
  165. X    return( (levl[x][y].typ == VWALL || levl[x][y].typ == HWALL) &&
  166. X        levl[x][y].diggable & W_GATEWAY);
  167. X}
  168. X
  169. X
  170. X/*
  171. X * Return true with x,y pointing to the drawbridge if x,y initially indicate
  172. X * a drawbridge or drawbridge wall.
  173. X */
  174. Xboolean
  175. Xfind_drawbridge(x,y)
  176. Xint *x,*y;
  177. X{
  178. X    int dir;
  179. X
  180. X    if (IS_DRAWBRIDGE(levl[*x][*y].typ))
  181. X        return TRUE;
  182. X    dir = is_drawbridge_wall(*x,*y);
  183. X    if (dir >= 0) {
  184. X        switch(dir) {
  185. X            case DB_NORTH: (*y)++; break;
  186. X            case DB_SOUTH: (*y)--; break;
  187. X            case DB_EAST:  (*x)--; break;
  188. X            case DB_WEST:  (*x)++; break;
  189. X        }
  190. X        return TRUE;
  191. X    }
  192. X    return FALSE;
  193. X}
  194. X
  195. X#endif /* OVL1 */
  196. X#ifdef OVLB
  197. X
  198. X/* 
  199. X * Find the drawbridge wall associated with a drawbridge.
  200. X */
  201. Xstatic void
  202. Xget_wall_for_db(x,y)
  203. Xint *x,*y;
  204. X{
  205. X    switch (levl[*x][*y].drawbridgemask & DB_DIR) {
  206. X        case DB_NORTH: (*y)--; break;
  207. X        case DB_SOUTH: (*y)++; break;
  208. X        case DB_EAST:  (*x)++; break;
  209. X        case DB_WEST:  (*x)--; break;
  210. X    }
  211. X}
  212. X
  213. X/*
  214. X * Creation of a drawbridge at pos x,y.
  215. X *     dir is the direction.
  216. X *     flag must be put to TRUE if we want the drawbridge to be opened.
  217. X */
  218. X
  219. Xboolean
  220. Xcreate_drawbridge(x,y,dir,flag)
  221. Xint x,y,dir;
  222. Xboolean flag;
  223. X{
  224. X    int x2,y2;
  225. X    uchar wall;
  226. X
  227. X    x2 = x; y2 = y;
  228. X    switch(dir) {
  229. X        case DB_NORTH:
  230. X            wall = HWALL;
  231. X            y2--;
  232. X            break;
  233. X        case DB_SOUTH:
  234. X            wall = HWALL;
  235. X            y2++;
  236. X            break;
  237. X        case DB_EAST:
  238. X            wall = VWALL;
  239. X            x2++;
  240. X            break;
  241. X        default:
  242. X            impossible("bad direction in create_drawbridge");
  243. X            /* fall through */
  244. X        case DB_WEST:
  245. X            wall = VWALL;
  246. X            x2--;
  247. X            break;
  248. X    }
  249. X    if (!IS_WALL(levl[x2][y2].typ))
  250. X        return(FALSE);
  251. X    if (flag) {             /* We want the bridge open */
  252. X        levl[x][y].typ = DRAWBRIDGE_DOWN;
  253. X        levl[x2][y2].typ = DOOR;
  254. X        levl[x2][y2].doormask = D_NODOOR;
  255. X    } else {
  256. X        levl[x][y].typ = DRAWBRIDGE_UP;
  257. X        levl[x2][y2].typ = wall;
  258. X        /* Beware, drawbridges are non-diggable. */
  259. X        levl[x2][y2].diggable = (W_NONDIGGABLE | W_GATEWAY);
  260. X    }
  261. X    levl[x][y].drawbridgemask = dir;        /* always have DB_MOAT */
  262. X    initsym(x,y);
  263. X    initsym(x2,y2);
  264. X    return(TRUE);           
  265. X}
  266. X
  267. Xstruct entity {
  268. X    struct monst *emon;       /* youmonst for the player */
  269. X    struct permonst *edata;    /* must be non-zero for record to be valid */
  270. X    int ex, ey;
  271. X};
  272. X
  273. X#define ENTITIES 2
  274. X
  275. Xstatic struct entity NEARDATA occupants[ENTITIES];
  276. X
  277. Xstatic
  278. Xstruct entity *
  279. Xe_at(x, y)
  280. Xint x, y;
  281. X{
  282. X    int entitycnt;
  283. X    
  284. X    for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++)
  285. X        if ((occupants[entitycnt].edata) && 
  286. X            (occupants[entitycnt].ex == x) &&
  287. X            (occupants[entitycnt].ey == y))
  288. X            break;
  289. X#ifdef D_DEBUG
  290. X    pline("entitycnt = %d", entitycnt);
  291. X    fflush(stdout);
  292. X#endif
  293. X    return((entitycnt == ENTITIES)? 
  294. X           (struct entity *)0 : &(occupants[entitycnt]));
  295. X}
  296. X
  297. Xstatic void
  298. Xm_to_e(mtmp, etmp)
  299. Xstruct monst *mtmp;
  300. Xstruct entity *etmp;
  301. X{
  302. X    etmp->emon = mtmp;
  303. X    if (mtmp) {
  304. X        etmp->ex = mtmp->mx;
  305. X        etmp->ey = mtmp->my;
  306. X        etmp->edata = mtmp->data;
  307. X    } else
  308. X        etmp->edata = (struct permonst *)0;
  309. X}
  310. X
  311. Xstatic void
  312. Xu_to_e(etmp)
  313. Xstruct entity *etmp;
  314. X{
  315. X    etmp->emon = &youmonst;
  316. X    etmp->ex = u.ux;
  317. X    etmp->ey = u.uy;
  318. X    etmp->edata = uasmon;
  319. X}
  320. X
  321. Xstatic void
  322. Xset_entity(x, y, etmp)
  323. Xint x, y;
  324. Xstruct entity *etmp;
  325. X{
  326. X    if ((x == u.ux) && (y == u.uy))
  327. X        u_to_e(etmp);
  328. X    else
  329. X        if (MON_AT(x, y))
  330. X            m_to_e(m_at(x, y), etmp);
  331. X        else
  332. X            etmp->edata = (struct permonst *)0;
  333. X}
  334. X
  335. X#ifdef POLYSELF
  336. X#define is_u(etmp) (etmp->emon == &youmonst)
  337. X#else
  338. X#define is_u(x) FALSE
  339. X#endif
  340. X
  341. X/* 
  342. X * WARNING! THE FOLLOWING IS ONLY USEFUL FOR CANSEEMON, OR OTHER FUNCS WHICH 
  343. X * ALWAYS RETURN TRUE FOR U.
  344. X */
  345. X
  346. X#define e_boolean(etmp, func) (is_u(etmp)? (boolean)TRUE : func(etmp->emon)) 
  347. X
  348. X/*
  349. X * e_strg is a utility routine which is not actually in use anywhere, since 
  350. X * the specialized routines below suffice for all current purposes. 
  351. X */
  352. X
  353. X/* #define e_strg(etmp, func) (is_u(etmp)? (char *)0 : func(etmp->emon)) */
  354. X
  355. Xstatic char *
  356. Xe_nam(etmp)
  357. Xstruct entity *etmp;
  358. X{
  359. X    return(is_u(etmp)? "you" : mon_nam(etmp->emon));
  360. X}
  361. X
  362. X/*
  363. X * Enam is another unused utility routine:  E_phrase is preferable.
  364. X */
  365. X
  366. X/*
  367. Xstatic char *
  368. XEnam(etmp)
  369. Xstruct entity *etmp;
  370. X{
  371. X    return(is_u(etmp)? "You" : Monnam(etmp->emon));
  372. X}
  373. X*/
  374. X
  375. X/*
  376. X * Generates capitalized entity name, makes 2nd -> 3rd person conversion on 
  377. X * verb, where necessary.
  378. X */
  379. X
  380. Xstatic char *
  381. XE_phrase(etmp, verb)
  382. Xstruct entity *etmp;
  383. Xconst char *verb;
  384. X{
  385. X    char wholebuf[80], verbbuf[30];
  386. X
  387. X    if (is_u(etmp)) 
  388. X        Strcpy(wholebuf, "You");
  389. X    else
  390. X        Strcpy(wholebuf, Monnam(etmp->emon));
  391. X    if (!*verb)
  392. X        return(wholebuf);
  393. X    Strcat(wholebuf, " ");
  394. X    verbbuf[0] = '\0';
  395. X    if (is_u(etmp)) 
  396. X        Strcpy(verbbuf, verb);
  397. X    else {
  398. X        if (!strcmp(verb, "are"))
  399. X            Strcpy(verbbuf, "is");
  400. X        if (!strcmp(verb, "have"))
  401. X            Strcpy(verbbuf, "has");
  402. X        if (!verbbuf[0]) {
  403. X            Strcpy(verbbuf, verb);
  404. X            switch (verbbuf[strlen(verbbuf) - 1]) {
  405. X                case 'y':
  406. X                    verbbuf[strlen(verbbuf) - 1] = '\0';
  407. X                    Strcat(verbbuf, "ies");
  408. X                    break;
  409. X                case 'h':
  410. X                case 'o':
  411. X                case 's':
  412. X                    Strcat(verbbuf, "es");
  413. X                    break;
  414. X                default:
  415. X                    Strcat(verbbuf, "s");
  416. X                    break;
  417. X            }
  418. X        }
  419. X    }
  420. X    Strcat(wholebuf, verbbuf);
  421. X    return(wholebuf);
  422. X}
  423. X
  424. X/*
  425. X * Simple-minded "can it be here?" routine
  426. X */
  427. X
  428. Xstatic boolean
  429. Xe_survives_at(etmp, x, y)
  430. Xstruct entity *etmp;
  431. Xint x, y;
  432. X{
  433. X    if (noncorporeal(etmp->edata))
  434. X        return(TRUE);
  435. X    if (is_pool(x, y))
  436. X        return((is_u(etmp) && (Wwalking || Levitation)) ||
  437. X               is_swimmer(etmp->edata) || is_flyer(etmp->edata) ||
  438. X               is_floater(etmp->edata));
  439. X    if (is_db_wall(x, y))
  440. X        return(passes_walls(etmp->edata));
  441. X    return(TRUE);
  442. X}
  443. X
  444. Xstatic void
  445. Xe_died(etmp, dest, how)
  446. Xstruct entity *etmp;
  447. Xint dest, how;
  448. X{
  449. X    if (is_u(etmp)) {
  450. X        if (how == DROWNING)
  451. X            drown();
  452. X        else {
  453. X            coord xy;
  454. X
  455. X            killer_format = KILLED_BY_AN;
  456. X            killer = "falling drawbridge";
  457. X            done(how);
  458. X            /* So, you didn't die */
  459. X            if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
  460. X                pline("A %s force teleports you away...",
  461. X                            Hallucination ? "normal" : "strange");
  462. X                (void) enexto(&xy, etmp->ex, etmp->ey,
  463. X                                etmp->edata);
  464. X                teleds(xy.x, xy.y);
  465. X            }
  466. X        }
  467. X    } else {
  468. X        xkilled(etmp->emon, dest);
  469. X        etmp->edata = (struct permonst *)0;    
  470. X    }
  471. X}
  472. X
  473. X
  474. X/*
  475. X * These are never directly affected by a bridge or portcullis.
  476. X */
  477. X
  478. Xstatic boolean
  479. Xautomiss(etmp)
  480. Xstruct entity *etmp;
  481. X{
  482. X    return(passes_walls(etmp->edata) || noncorporeal(etmp->edata));
  483. X}
  484. X
  485. X/*
  486. X * Does falling drawbridge or portcullis miss etmp?
  487. X */
  488. X
  489. Xstatic boolean
  490. Xe_missed(etmp, chunks)
  491. Xstruct entity *etmp;
  492. Xboolean chunks;
  493. X{
  494. X    int misses;
  495. X
  496. X#ifdef D_DEBUG
  497. X    if (chunks)
  498. X        pline("Do chunks miss?");
  499. X#endif
  500. X    if (automiss(etmp))
  501. X        return(TRUE);    
  502. X
  503. X    if (is_flyer(etmp->edata) && 
  504. X        (is_u(etmp)? !Sleeping : 
  505. X         (etmp->emon->mcanmove && !etmp->emon->msleep)))
  506. X                          /* flying requires mobility */
  507. X        misses = 5;    /* out of 8 */    
  508. X    else
  509. X        if (is_floater(etmp->edata) ||
  510. X            (is_u(etmp) && Levitation))      /* doesn't require mobility */
  511. X            misses = 3;
  512. X        else
  513. X            if (chunks && is_pool(etmp->ex, etmp->ey))
  514. X                misses = 2;              /* sitting ducks */
  515. X            else
  516. X                misses = 0;      
  517. X
  518. X    if (is_db_wall(etmp->ex, etmp->ey))
  519. X        misses -= 3;                     /* less airspace */
  520. X
  521. X#ifdef D_DEBUG
  522. X    pline("Miss chance = %d (out of 8)", misses);
  523. X#endif
  524. X
  525. X    return((misses >= rnd(8))? TRUE : FALSE);
  526. X}
  527. X
  528. X/*
  529. X * Can etmp jump from death?
  530. X */ 
  531. X
  532. Xstatic boolean
  533. Xe_jumps(etmp)
  534. Xstruct entity *etmp;
  535. X{
  536. X    int tmp = 4;         /* out of 10 */
  537. X
  538. X    if (is_u(etmp)? (Sleeping || Fumbling) : 
  539. X                (!etmp->emon->mcanmove || etmp->emon->msleep || 
  540. X             !etmp->edata->mmove))
  541. X        return(FALSE);
  542. X
  543. X    if (is_u(etmp)? Confusion : etmp->emon->mconf)
  544. X        tmp -= 2;
  545. X
  546. X    if (is_u(etmp)? Stunned : etmp->emon->mstun)
  547. X        tmp -= 3;
  548. X
  549. X    if (is_db_wall(etmp->ex, etmp->ey))
  550. X        tmp -= 2;                 /* less room to maneuver */
  551. X    
  552. X#ifdef D_DEBUG
  553. X    pline("%s to jump (%d chances in 10)", E_phrase(etmp, "try"), tmp);
  554. X#endif
  555. X    return((tmp >= rnd(10))? TRUE : FALSE);
  556. X}
  557. X
  558. Xstatic void
  559. Xdo_entity(etmp)
  560. Xstruct entity *etmp;
  561. X{
  562. X    int newx, newy, at_portcullis, oldx, oldy;
  563. X    boolean must_jump = FALSE, relocates = FALSE, e_inview;
  564. X    struct rm *crm;
  565. X
  566. X    if (!etmp->edata)
  567. X        return;
  568. X
  569. X    e_inview = e_boolean(etmp, canseemon);
  570. X
  571. X    oldx = etmp->ex;
  572. X    oldy = etmp->ey;
  573. X
  574. X    at_portcullis = is_db_wall(oldx, oldy);
  575. X
  576. X    crm = &levl[oldx][oldy];
  577. X
  578. X    if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) {
  579. X        char edifice[20];
  580. X
  581. X        if (e_inview) {
  582. X            *edifice = '\0';
  583. X            if ((crm->typ == DRAWBRIDGE_DOWN) ||
  584. X                    (crm->typ == DRAWBRIDGE_UP))
  585. X                Strcpy(edifice, "drawbridge");
  586. X            else
  587. X                     if (at_portcullis) 
  588. X                    Strcpy(edifice, "portcullis");
  589. X            if (*edifice)
  590. X                pline("The %s passes through %s!", edifice, 
  591. X                            e_nam(etmp));            
  592. X        }
  593. X        return;
  594. X    }
  595. X    if (e_missed(etmp, FALSE)) { 
  596. X        if (at_portcullis)
  597. X            pline("The portcullis misses %s!",
  598. X                  e_nam(etmp));
  599. X#ifdef D_DEBUG
  600. X        else
  601. X            pline("The drawbridge misses %s!", 
  602. X                  e_nam(etmp));
  603. X#endif
  604. X        if (e_survives_at(etmp, oldx, oldy)) 
  605. X            return;
  606. X        else {
  607. X#ifdef D_DEBUG
  608. X            pline("Mon can't survive here");
  609. X#endif
  610. X            if (at_portcullis)
  611. X                must_jump = TRUE;
  612. X            else
  613. X                relocates = TRUE;  /* just ride drawbridge in */
  614. X        }
  615. X    } else {
  616. X        if (crm->typ == DRAWBRIDGE_DOWN) {
  617. X            pline("%s crushed underneath the drawbridge.",
  618. X                        E_phrase(etmp, "are"));              /* no jump */
  619. X            e_died(etmp, e_inview? 2 : 3, CRUSHING); /* no corpse */
  620. X            return;   /* Note: Beyond this point, we know we're   */
  621. X        }                 /* not at an opened drawbridge, since all   */
  622. X        must_jump = TRUE; /* *missable* creatures survive on the      */
  623. X    }              /* square, and all the unmissed ones die.   */
  624. X    if (must_jump) 
  625. X        if (at_portcullis) {
  626. X            if (e_jumps(etmp)) {
  627. X                relocates = TRUE;
  628. X#ifdef D_DEBUG
  629. X                pline("Jump succeeds!");
  630. X#endif
  631. X            } else {
  632. X                if (e_inview)
  633. X                   pline("%s crushed by the falling portcullis!",
  634. X                                 E_phrase(etmp, "are"));
  635. X                else
  636. X                    if (flags.soundok)
  637. X                        You("hear a crushing sound.");
  638. X                e_died(etmp, e_inview? 1 : 0, CRUSHING);
  639. X                                    /* corpse */
  640. X                return;
  641. X            }
  642. X        } else {       /* tries to jump off bridge to original square */
  643. X            relocates = !e_jumps(etmp); 
  644. X#ifdef D_DEBUG
  645. X            pline("Jump %s!", (relocates)? "fails" : "succeeds");
  646. X#endif
  647. X        }
  648. X
  649. X/*
  650. X * Here's where we try to do relocation.  Assumes that etmp is not arriving
  651. X * at the portcullis square while the drawbridge is falling, since this square
  652. X * would be inaccessible (i.e. etmp started on drawbridge square) or 
  653. X * unnecessary (i.e. etmp started here) in such a situation.
  654. X */
  655. X#ifdef D_DEBUG
  656. X    pline("Doing relocation");
  657. X#endif
  658. X    newx = oldx;
  659. X    newy = oldy;
  660. X    (void)find_drawbridge(&newx, &newy);
  661. X    if ((newx == oldx) && (newy == oldy))
  662. X        get_wall_for_db(&newx, &newy);
  663. X#ifdef D_DEBUG
  664. X    pline("Checking new square for occupancy");
  665. X#endif
  666. X    if (relocates && (e_at(newx, newy))) { 
  667. X
  668. X/* 
  669. X * Standoff problem:  one or both entities must die, and/or both switch 
  670. X * places.  Avoid infinite recursion by checking first whether the other 
  671. X * entity is staying put.  Clean up if we happen to move/die in recursion.
  672. X */
  673. X        struct entity *other;
  674. X
  675. X        other = e_at(newx, newy);
  676. X#ifdef D_DEBUG
  677. X        pline("New square is occupied by %s", e_nam(other));
  678. X#endif
  679. X        if (e_survives_at(other, newx, newy) && automiss(other)) {
  680. X            relocates = FALSE;                /* "other" won't budge */
  681. X#ifdef D_DEBUG
  682. X            pline("%s suicide.", E_phrase(etmp, "commit"));
  683. X#endif
  684. X        } else {
  685. X
  686. X#ifdef D_DEBUG
  687. X            pline("Handling %s", e_nam(other));
  688. X#endif
  689. X            while ((e_at(newx, newy)) && 
  690. X                   (e_at(newx, newy) != etmp))
  691. X                       do_entity(other);
  692. X#ifdef D_DEBUG
  693. X            pline("Checking existence of %s", 
  694. X                  e_nam(etmp));
  695. X            fflush(stdout);
  696. X#endif
  697. X            if (e_at(oldx, oldy) != etmp) {
  698. X#ifdef D_DEBUG
  699. X                    pline("%s moved or died in recursion somewhere",
  700. X                      E_phrase(etmp, "have"));
  701. X                fflush(stdout);
  702. X#endif
  703. X                return;
  704. X            }
  705. X        }
  706. X    }
  707. X    if (relocates) {
  708. X#ifdef D_DEBUG
  709. X        pline("Moving %s", e_nam(etmp));
  710. X#endif
  711. X        if (!is_u(etmp)) {
  712. X            remove_monster(etmp->ex, etmp->ey);
  713. X            place_monster(etmp->emon, newx, newy);
  714. X        } else {
  715. X            u.ux = newx;
  716. X            u.uy = newy;
  717. X        }
  718. X        etmp->ex = newx;
  719. X        etmp->ey = newy;
  720. X        e_inview = e_boolean(etmp, canseemon);
  721. X    }
  722. X#ifdef D_DEBUG
  723. X    pline("Final disposition of %s", e_nam(etmp));
  724. X    fflush(stdout);
  725. X#endif
  726. X    if (is_db_wall(etmp->ex, etmp->ey)) {
  727. X#ifdef D_DEBUG
  728. X        pline("%s in portcullis chamber", E_phrase(etmp, "are"));
  729. X        fflush(stdout);
  730. X#endif
  731. X        if (e_inview)
  732. X            if (is_u(etmp)) {
  733. X                You("tumble towards the closed portcullis!"); 
  734. X                if (automiss(etmp))
  735. X                    You("pass through it!");
  736. X                else
  737. X                    pline("The drawbridge closes in...");
  738. X            } else
  739. X                pline("%s behind the drawbridge.",
  740. X                                  E_phrase(etmp, "disappear"));
  741. X        if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
  742. X            killer_format = KILLED_BY_AN;
  743. X            killer = "closing drawbridge";
  744. X            e_died(etmp, 0, CRUSHING);         /* no message */
  745. X            return;
  746. X        }
  747. X#ifdef D_DEBUG
  748. X        pline("%s in here", E_phrase(etmp, "survive"));
  749. X#endif
  750. X    } else {
  751. X#ifdef D_DEBUG
  752. X        pline("%s on drawbridge square", E_phrase(etmp, "are"));
  753. X#endif
  754. X        if (is_pool(etmp->ex, etmp->ey) && !e_inview)
  755. X            if (flags.soundok)
  756. X                You("hear a splash.");
  757. X        if (e_survives_at(etmp, etmp->ex, etmp->ey)) {
  758. X            if (e_inview && !is_flyer(etmp->edata) &&
  759. X                !is_floater(etmp->edata))
  760. X                pline("%s from the bridge.",
  761. X                                  E_phrase(etmp, "fall"));    
  762. X            return;    
  763. X        }
  764. X#ifdef D_DEBUG
  765. X        pline("%s cannot survive on the drawbridge square", Enam(etmp));
  766. X#endif
  767. X        if (is_pool(etmp->ex, etmp->ey))
  768. X            if (e_inview && 
  769. X                !is_u(etmp))  /* drown() will supply msgs if nec. */
  770. X                if (Hallucination)
  771. X                      pline("%s the moat and disappears.",
  772. X                        E_phrase(etmp, "drink"));
  773. X                else
  774. X                      pline("%s into the moat.",
  775. X                                  E_phrase(etmp, "fall"));
  776. X        killer_format = NO_KILLER_PREFIX;
  777. X        killer = "fell from a drawbridge";
  778. X        e_died(etmp, e_inview? 1 : 0,        /* CRUSHING is arbitrary */
  779. X               (is_pool(etmp->ex, etmp->ey))? DROWNING : CRUSHING);
  780. X                                           /* corpse */
  781. X        return;
  782. X    }
  783. X}
  784. X
  785. X/*
  786. X * Close the drawbridge located at x,y
  787. X */
  788. X
  789. Xvoid
  790. Xclose_drawbridge(x,y)
  791. Xint x,y;
  792. X{
  793. X    register struct rm *lev1, *lev2;
  794. X    struct obj *otmp, *otmp2;
  795. X    int x2, y2;
  796. X
  797. X    lev1 = &levl[x][y];
  798. X    if (lev1->typ != DRAWBRIDGE_DOWN) return;
  799. X    x2 = x; y2 = y;
  800. X    get_wall_for_db(&x2,&y2);
  801. X    if (cansee(x,y))   /* change msgs if you are a w-walker at portcullis */
  802. X        You("see a drawbridge %s up!", 
  803. X            ((u.ux == x2) && (u.uy == y2))? "coming" : "going");
  804. X    lev1->typ = DRAWBRIDGE_UP;
  805. X    lev2 = &levl[x2][y2];
  806. X    switch (lev1->drawbridgemask & DB_DIR) {
  807. X        case DB_NORTH:
  808. X        case DB_SOUTH:
  809. X            lev2->typ = HWALL;
  810. X            break;
  811. X        case DB_WEST:
  812. X        case DB_EAST:
  813. X            lev2->typ = VWALL;
  814. X            break;
  815. X    }
  816. X    lev2->diggable = (W_NONDIGGABLE | W_GATEWAY);
  817. X    set_entity(x, y, &(occupants[0]));
  818. X    set_entity(x2, y2, &(occupants[1]));
  819. X    do_entity(&(occupants[0]));
  820. X    do_entity(&(occupants[1]));
  821. X    redosym(x, y);
  822. X    for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
  823. X        otmp2 = otmp->nexthere;
  824. X        delobj(otmp);
  825. X    }
  826. X    for (otmp = level.objects[x2][y2]; otmp; otmp = otmp2) {
  827. X        otmp2 = otmp->nexthere;
  828. X        delobj(otmp);
  829. X    }
  830. X    redosym(x2, y2);
  831. X}
  832. X
  833. X/* 
  834. X * Open the drawbridge located at x,y
  835. X */
  836. X
  837. Xvoid
  838. Xopen_drawbridge(x,y)
  839. Xint x,y;
  840. X{
  841. X    register struct rm *lev1, *lev2;
  842. X    int x2, y2;
  843. X
  844. X    lev1 = &levl[x][y];
  845. X    if (lev1->typ != DRAWBRIDGE_UP) return;
  846. X    x2 = x; y2 = y;
  847. X    get_wall_for_db(&x2,&y2);
  848. X    if (cansee(x,y))   /* change msgs if you are a w-walker at portcullis */
  849. X        You("see a drawbridge %s down!",
  850. X            ((x2 == u.ux) && (y2 == u.uy))? "going" : "coming");
  851. X    lev1->typ = DRAWBRIDGE_DOWN;
  852. X    lev2 = &levl[x2][y2];
  853. X    lev2->typ = DOOR;
  854. X    lev2->doormask = D_NODOOR;
  855. X    set_entity(x, y, &(occupants[0]));
  856. X    set_entity(x2, y2, &(occupants[1]));
  857. X    do_entity(&(occupants[0]));
  858. X    do_entity(&(occupants[1]));
  859. X    redosym(x, y);
  860. X    redosym(x2, y2);
  861. X}
  862. X
  863. X/*
  864. X * Let's destroy the drawbridge located at x,y
  865. X */
  866. X
  867. Xvoid
  868. Xdestroy_drawbridge(x,y)
  869. Xint x,y;
  870. X{
  871. X    register struct rm *lev1, *lev2;
  872. X    int x2, y2;
  873. X    boolean e_inview;
  874. X    struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);
  875. X
  876. X    lev1 = &levl[x][y];
  877. X    if (!IS_DRAWBRIDGE(lev1->typ))
  878. X        return;
  879. X    x2 = x; y2 = y;
  880. X    get_wall_for_db(&x2,&y2);
  881. X    lev2 = &levl[x2][y2];
  882. X    if ((lev1->drawbridgemask & DB_UNDER) == DB_MOAT) {
  883. X        if (lev1->typ == DRAWBRIDGE_UP) {
  884. X            if (cansee(x2,y2))
  885. X        pline("The portcullis of the drawbridge falls into the moat!");
  886. X            else if (flags.soundok)
  887. X                You("hear a loud *SPLASH*!");
  888. X        } else {
  889. X            if (cansee(x,y))
  890. X                pline("The drawbridge collapses into the moat!");
  891. X            else if (flags.soundok)
  892. X                You("hear a loud *SPLASH*!");
  893. X        }
  894. X        lev1->typ = MOAT;
  895. X        lev1->drawbridgemask = 0;
  896. X    } else {
  897. X        if (cansee(x,y))
  898. X            pline("The drawbridge disintegrates!");
  899. X        else
  900. X            You("hear a loud *CRASH*!");
  901. X        lev1->typ = ROOM;
  902. X        lev1->icedpool =
  903. X            ((lev1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
  904. X    }
  905. X    set_entity(x2, y2, etmp2); /* currently, only automissers can be here */
  906. X    if (etmp2->edata) {
  907. X        e_inview = e_boolean(etmp2, canseemon);
  908. X        if (!automiss(etmp2)) {               /* i.e. no-one yet */
  909. X            if (e_inview)
  910. X                pline("%s blown apart by flying debris",
  911. X                            E_phrase(etmp2, "are"));
  912. X            killer_format = KILLED_BY_AN;
  913. X            killer = "exploding drawbridge";
  914. X            e_died(etmp2, e_inview? 2 : 3, CRUSHING);/* no corpse */
  915. X        }          /* nothing which is vulnerable can survive this */
  916. X    }
  917. X    lev2->typ = DOOR;
  918. X    lev2->doormask = D_NODOOR;
  919. X    set_entity(x, y, etmp1);
  920. X    if (etmp1->edata) {
  921. X        e_inview = e_boolean(etmp1, canseemon);
  922. X        if (e_missed(etmp1, TRUE)) {
  923. X#ifdef D_DEBUG
  924. X            pline("%s spared!", E_phrase(etmp1, "are"));
  925. X#endif
  926. X        } else {
  927. X            if (e_inview) 
  928. X                if (!is_u(etmp1) && Hallucination)
  929. X                    pline("%s into some heavy metal",
  930. X                          E_phrase(etmp1, "get"));
  931. X                else
  932. X                    pline("%s hit by a huge chunk of metal!",
  933. X                                E_phrase(etmp1, "are"));
  934. X            else 
  935. X                if (flags.soundok && !is_u(etmp1) && 
  936. X                    !is_pool(x, y))
  937. X                    You("hear a crushing sound");
  938. X#ifdef D_DEBUG
  939. X                else
  940. X                    pline("%s from shrapnel", 
  941. X                          E_phrase(etmp1, "die"));
  942. X#endif
  943. X            killer_format = KILLED_BY_AN;
  944. X            killer = "collapsing drawbridge";
  945. X            e_died(etmp1, e_inview? 0 : 1, CRUSHING);   /* corpse */
  946. X        }
  947. X    }
  948. X    redosym(x,y);
  949. X    redosym(x2,y2);
  950. X}
  951. X
  952. X
  953. X#endif /* OVLB */
  954. X
  955. X#endif /* STRONGHOLD /**/
  956. END_OF_FILE
  957. if test 20980 -ne `wc -c <'src/dbridge.c'`; then
  958.     echo shar: \"'src/dbridge.c'\" unpacked with wrong size!
  959. fi
  960. # end of 'src/dbridge.c'
  961. fi
  962. if test -f 'src/pager.c' -a "${1}" != "-c" ; then 
  963.   echo shar: Will not clobber existing file \"'src/pager.c'\"
  964. else
  965. echo shar: Extracting \"'src/pager.c'\" \(28788 characters\)
  966. sed "s/^X//" >'src/pager.c' <<'END_OF_FILE'
  967. X/*    SCCS Id: @(#)pager.c    3.0    89/11/19
  968. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  969. X/* NetHack may be freely redistributed.  See license for details. */
  970. X
  971. X/* This file contains the command routine dowhatis() and a pager. */
  972. X/* Also readmail() and doshell(), and generally the things that
  973. X   contact the outside world. */
  974. X
  975. X#define MONATTK_H    /* comment line for pre-compiled headers */
  976. X/* block some unused #defines to avoid overloading some cpp's */
  977. X#include    "hack.h"
  978. X
  979. X#include <ctype.h>
  980. X#ifndef NO_SIGNAL
  981. X#include <signal.h>
  982. X#endif
  983. X#if defined(BSD) || defined(ULTRIX)
  984. X#include <sys/wait.h>
  985. X#endif
  986. X#ifdef MACOS
  987. Xextern WindowPtr    HackWindow;
  988. Xextern short macflags;
  989. X#endif
  990. X
  991. X#ifndef SEEK_SET
  992. X#define SEEK_SET 0
  993. X#endif
  994. X
  995. XSTATIC_DCL boolean FDECL(clear_help, (CHAR_P));
  996. XSTATIC_DCL boolean FDECL(valid_help, (CHAR_P));
  997. X
  998. X#ifndef OVLB
  999. XSTATIC_DCL char hc;
  1000. X#else /* OVLB */
  1001. XSTATIC_OVL char NEARDATA hc = 0;
  1002. X
  1003. Xstatic void FDECL(page_more, (FILE *,int));
  1004. Xstatic boolean FDECL(is_swallow_sym, (UCHAR_P));
  1005. Xstatic boolean FDECL(pmatch,(const char *,const char *));
  1006. Xstatic boolean FDECL(outspec,(const char *,int));
  1007. Xstatic const char *FDECL(lookat,(int,int,UCHAR_P));
  1008. X#ifdef WIZARD
  1009. Xstatic void NDECL(wiz_help);
  1010. X#endif
  1011. Xstatic void NDECL(help_menu);
  1012. X
  1013. X/*
  1014. X * simple pattern matcher: '*' matches 0 or more characters
  1015. X * returns TRUE if strng matches patrn
  1016. X */
  1017. X
  1018. Xstatic boolean
  1019. Xpmatch(patrn, strng)
  1020. X    const char *patrn, *strng;
  1021. X{
  1022. X    char s, p;
  1023. X
  1024. X    s = *strng;
  1025. X    p = *patrn;
  1026. X
  1027. X    if (!p) {
  1028. X        return (s == 0);
  1029. X    }
  1030. X
  1031. X    if (p == '*') {
  1032. X        if (!patrn[1] || pmatch(patrn+1, strng)) {
  1033. X            return TRUE;
  1034. X        }
  1035. X        return (s ? pmatch(patrn, strng+1) : FALSE);
  1036. X    }
  1037. X
  1038. X    return (p == s) ? pmatch(patrn+1, strng+1) : FALSE;
  1039. X}
  1040. X
  1041. X/*
  1042. X * returns "true" for characters that could represent a monster's stomach
  1043. X */
  1044. X
  1045. Xstatic boolean
  1046. Xis_swallow_sym(c)
  1047. Xuchar c;
  1048. X{
  1049. X    return (index(" /-\\|", (char)c) != 0);
  1050. X}
  1051. X
  1052. X/*
  1053. X * print out another possibility for dowhatis. "new" is the possible new
  1054. X * string; "out_flag" indicates whether we really want output, and if
  1055. X * so what kind of output: 0 == no output, 1 == "(or %s)" output. 
  1056. X * Returns TRUE if this new string wasn't the last string printed.
  1057. X */
  1058. X
  1059. Xstatic boolean
  1060. Xoutspec(new, out_flag)
  1061. Xconst char *new;
  1062. Xint out_flag;
  1063. X{
  1064. X    static char NEARDATA old[50];
  1065. X
  1066. X    if (!strcmp(old, new))
  1067. X        return FALSE;        /* don't print the same thing twice */
  1068. X
  1069. X    if (out_flag)
  1070. X        pline("(or %s)", an(new));
  1071. X
  1072. X    Strcpy(old, new);
  1073. X    return 1;
  1074. X}
  1075. X
  1076. X/*
  1077. X * return the name of the character ch found at (x,y)
  1078. X */
  1079. X
  1080. Xstatic
  1081. Xconst char *
  1082. Xlookat(x, y, ch)
  1083. Xint x,y;
  1084. Xuchar ch;
  1085. X{
  1086. X    register struct monst *mtmp;
  1087. X    register struct obj *otmp;
  1088. X    struct trap *trap;
  1089. X    static char NEARDATA answer[50];
  1090. X    register char *s, *t;
  1091. X    uchar typ;
  1092. X
  1093. X    answer[0] = 0;
  1094. X
  1095. X    if(MON_AT(x,y)) {
  1096. X        mtmp = m_at(x,y);
  1097. X        if (!showmon(mtmp) || Hallucination)
  1098. X            mtmp = (struct monst *)0;
  1099. X    } else
  1100. X        mtmp = (struct monst *) 0;
  1101. X    typ = levl[x][y].typ;
  1102. X    if (!Invisible 
  1103. X#ifdef POLYSELF
  1104. X            && !u.uundetected
  1105. X#endif
  1106. X            && u.ux==x && u.uy==y) {
  1107. X        Sprintf(answer, "%s named %s",
  1108. X#ifdef POLYSELF
  1109. X            u.mtimedone ? mons[u.umonnum].mname :
  1110. X#endif
  1111. X            pl_character, plname);
  1112. X    } else if (u.uswallow && is_swallow_sym(ch)) {
  1113. X        Sprintf(answer, "interior of %s", defmonnam(u.ustuck));
  1114. X    } else if (mtmp && !mtmp->mimic)
  1115. X        Sprintf(answer, "%s%s",
  1116. X           mtmp->mtame ? "tame " :
  1117. X           mtmp->mpeaceful ? "peaceful " : "",
  1118. X           strncmp(lmonnam(mtmp), "the ", 4)
  1119. X              ? lmonnam(mtmp) : lmonnam(mtmp)+4);
  1120. X    else if (!levl[x][y].seen)
  1121. X        Strcpy(answer,"dark part of a room");
  1122. X    else if (mtmp && mtmp->mimic) {
  1123. X        if (mtmp->m_ap_type == M_AP_FURNITURE) {
  1124. X            if (mtmp->mappearance == S_altar)
  1125. X                Strcpy(answer, "neutral altar");
  1126. X            else
  1127. X                Strcpy(answer, explainsyms[mtmp->mappearance]);
  1128. X        }
  1129. X        else if (mtmp->m_ap_type == M_AP_OBJECT) {
  1130. X            if (mtmp->mappearance == STRANGE_OBJECT)
  1131. X                Strcpy(answer, "strange object");
  1132. X            else {
  1133. X                int oindx = mtmp->mappearance;
  1134. X                otmp = mksobj(oindx,FALSE );
  1135. X                if(oindx == STATUE || oindx == FIGURINE)
  1136. X                    otmp->corpsenm = PM_KOBOLD;
  1137. X                else if (oindx == DRAGON_SCALE_MAIL)
  1138. X                    otmp->corpsenm = PM_RED_DRAGON;
  1139. X                Strcpy(answer, distant_name(otmp, xname));
  1140. X                free((genericptr_t) otmp);
  1141. X            }
  1142. X        }
  1143. X        else if (mtmp->m_ap_type == M_AP_GOLD)
  1144. X            Strcpy(answer, "pile of gold");
  1145. X    }
  1146. X    else if (OBJ_AT(x, y)) {
  1147. X        otmp = level.objects[x][y];
  1148. X        Strcpy(answer, distant_name(otmp, xname));
  1149. X    }
  1150. X    else if (ch == GOLD_SYM) {
  1151. X        Strcpy(answer, "pile of gold");
  1152. X    }
  1153. X#ifdef ALTARS
  1154. X    else if (ch == ALTAR_SYM && IS_ALTAR(typ)) {
  1155. X        int kind = levl[x][y].altarmask & ~A_SHRINE;
  1156. X        Sprintf( answer, "%s altar",
  1157. X            (kind == A_CHAOS) ? "chaotic" :
  1158. X            (kind == A_NEUTRAL) ? "neutral" :
  1159. X             "lawful" );
  1160. X    }
  1161. X#endif
  1162. X#ifdef STRONGHOLD
  1163. X    else if ((ch == DB_VWALL_SYM || ch == DB_HWALL_SYM) && is_db_wall(x,y))
  1164. X        Strcpy(answer,"raised drawbridge");
  1165. X#endif
  1166. X#ifdef THRONES
  1167. X    else if ((ch == THRONE_SYM) && IS_THRONE(typ))
  1168. X        Strcpy(answer, "throne");
  1169. X#endif
  1170. X    else if ( (ch==H_OPEN_DOOR_SYM ||
  1171. X           ch==V_OPEN_DOOR_SYM ||
  1172. X           ch==CLOSED_DOOR_SYM ||
  1173. X           ch==NO_DOOR_SYM) &&
  1174. X          IS_DOOR(typ) ) {
  1175. X        switch(levl[x][y].doormask & ~D_TRAPPED) {
  1176. X            case D_NODOOR: Strcpy(answer,"doorway"); break;
  1177. X            case D_BROKEN: Strcpy(answer,"broken door"); break;
  1178. X            case D_ISOPEN: Strcpy(answer,"open door"); break;
  1179. X            default:       Strcpy(answer,"closed door"); break;
  1180. X                       /* locked or not */
  1181. X        }
  1182. X    }
  1183. X#ifdef SINKS
  1184. X    else if (ch == SINK_SYM && IS_SINK(levl[x][y].typ))
  1185. X        Strcpy(answer,"sink");
  1186. X#endif
  1187. X    else if ((ch == TRAP_SYM || ch == WEB_SYM) && (trap = t_at(x, y))) {
  1188. X        if (trap->ttyp == WEB && ch == WEB_SYM)
  1189. X            Strcpy(answer, "web");
  1190. X        else if (trap->ttyp != MONST_TRAP && ch == TRAP_SYM) {
  1191. X            Strcpy(answer, traps[ Hallucination ?
  1192. X                rn2(TRAPNUM-3)+3 : trap->ttyp]);
  1193. X        /* strip leading garbage */
  1194. X            for (s = answer; *s && *s != ' '; s++) ;
  1195. X            if (*s) ++s;
  1196. X            for (t = answer; *t++ = *s++; ) ;
  1197. X        }
  1198. X    }
  1199. X    else if (ch == UP_SYM && x == xupstair && y == yupstair)
  1200. X        Strcpy(answer, "staircase up");
  1201. X    else if (ch == DN_SYM && x == xdnstair && y == ydnstair)
  1202. X        Strcpy(answer, "staircase down");
  1203. X#ifdef STRONGHOLD
  1204. X    else if (ch == UPLADDER_SYM && x && x == xupladder && y == ydnladder)
  1205. X        Strcpy(answer, "ladder up");
  1206. X    else if (ch == DNLADDER_SYM && x && x == xdnladder && y == ydnladder)
  1207. X        Strcpy(answer, "ladder down");
  1208. X#endif
  1209. X    else if (IS_ROOM(typ)) {
  1210. X        if (ch == ROOM_SYM) {
  1211. X            if (levl[x][y].icedpool)
  1212. X                Strcpy(answer,"iced pool");
  1213. X            else
  1214. X                Strcpy(answer,"floor of a room");
  1215. X        }
  1216. X        else if (ch == STONE_SYM || ch == ' ')
  1217. X            Strcpy(answer,"dark part of a room");
  1218. X    }
  1219. X    else if (ch == CORR_SYM && SPACE_POS(typ))
  1220. X        Strcpy(answer,"corridor");
  1221. X    else if (!ACCESSIBLE(typ)) {
  1222. X        if (ch == STONE_SYM || ch == ' ')
  1223. X            Strcpy(answer,"dark part of a room");
  1224. X        else
  1225. X            Strcpy(answer,"wall");
  1226. X    }
  1227. X    return answer;
  1228. X}
  1229. X
  1230. X    
  1231. Xint
  1232. Xdowhatis()
  1233. X{
  1234. X    FILE *fp;
  1235. X    char buf[BUFSZ], inpbuf[BUFSZ];
  1236. X    register char *ep, *inp = inpbuf;
  1237. X    char *alt = 0;        /* alternate description */
  1238. X#ifdef __GNULINT__
  1239. X    const char *firstmatch = 0;
  1240. X#else
  1241. X    const char *firstmatch;
  1242. X#endif
  1243. X    uchar q;
  1244. X    register int i;
  1245. X    coord    cc;
  1246. X    boolean oldverb = flags.verbose;
  1247. X    boolean found_in_file = FALSE, need_to_print = FALSE;
  1248. X    int    found = 0;
  1249. X    static const char *mon_interior = "the interior of a monster";
  1250. X
  1251. X#ifdef OS2_CODEVIEW
  1252. X    char tmp[PATHLEN];
  1253. X
  1254. X    Strcpy(tmp,hackdir);
  1255. X    append_slash(tmp);
  1256. X    Strcat(tmp,DATAFILE);
  1257. X    fp = fopen(tmp,"r"));
  1258. X#else
  1259. X    fp = fopen(DATAFILE, "r");
  1260. X#endif
  1261. X    if(!fp) {
  1262. X#ifdef MACOS
  1263. X        fp = openFile(DATAFILE, "r");
  1264. X    }
  1265. X    if (!fp) {
  1266. X#endif
  1267. X        pline("Cannot open data file!");
  1268. X        return 0;
  1269. X    }
  1270. X
  1271. X    pline ("Specify unknown object by cursor? ");
  1272. X    q = ynq();
  1273. X    if (q == 'q') {
  1274. X        (void) fclose(fp);
  1275. X        return 0;
  1276. X    } else if (q == 'n') {
  1277. X        cc.x = cc.y = -1;
  1278. X        pline("Specify what? (type the word) ");
  1279. X        getlin(inp);
  1280. X        if (inp[0] == '\033' || !inp[0]) {
  1281. X            (void)fclose(fp);
  1282. X            return 0;
  1283. X        }
  1284. X        if (!inp[1])
  1285. X            q = inp[0];
  1286. X        else
  1287. X            q = 0;
  1288. X    } else {
  1289. X        cc.x = u.ux;
  1290. X        cc.y = u.uy;
  1291. Xselobj:
  1292. X        need_to_print = found_in_file = FALSE;
  1293. X        found = 0;
  1294. X        inp = inpbuf;
  1295. X        alt = 0;
  1296. X        (void) outspec("", 0);        /* reset output */
  1297. X        if(flags.verbose)
  1298. X            pline("Please move the cursor to an unknown object.");
  1299. X        else
  1300. X            pline("Pick an object.");
  1301. X        getpos(&cc, FALSE, "an unknown object");
  1302. X        if (cc.x < 0) {
  1303. X                (void) fclose(fp); /* sweet@scubed */
  1304. X                flags.verbose = oldverb;
  1305. X                return 0;
  1306. X        }
  1307. X        flags.verbose = FALSE;
  1308. X        if (!u.uswallow) {
  1309. X            q = levl[cc.x][cc.y].scrsym;
  1310. X            if (!q || (!levl[cc.x][cc.y].seen && !MON_AT(cc.x,cc.y)))
  1311. X                q = ' ';
  1312. X        }
  1313. X        else if (cc.x == u.ux && cc.y == u.uy)
  1314. X            q = u.usym;
  1315. X        else {
  1316. X            i = (u.uy - cc.y)+1;
  1317. X            if (i < 0 || i > 2)
  1318. X                q = ' ';
  1319. X            else {
  1320. X                firstmatch = (i == 0) ? "/-\\" :
  1321. X                    (i == 1) ? "| |" : "\\-/";
  1322. X                i = (u.ux - cc.x)+1;
  1323. X                if (i < 0 || i > 2)
  1324. X                    q = ' ';
  1325. X                else
  1326. X                    q = firstmatch[i];
  1327. X            }
  1328. X        }
  1329. X    }
  1330. X
  1331. X    if (!q)
  1332. X        goto checkfile; /* user typed in a complete string */
  1333. X
  1334. X    if (q != ' ' && index(quitchars, (char)q)) {
  1335. X        (void) fclose(fp); /* sweet@scubed */
  1336. X        flags.verbose = oldverb;
  1337. X        return 0;
  1338. X    }
  1339. X/*
  1340. X * if the user just typed one letter, or we're identifying from the
  1341. X * screen, then we have to check all the possibilities and print them
  1342. X * out for him/her.
  1343. X */
  1344. X
  1345. X/* Check for monsters */
  1346. X    for (i = 0; monsyms[i]; i++) {
  1347. X        if (q == monsyms[i]) {
  1348. X            need_to_print = TRUE;
  1349. X            pline("%c       %s",q,an(monexplain[i]));
  1350. X            (void) outspec(firstmatch = monexplain[i], 0);
  1351. X            found++;
  1352. X            break;
  1353. X        }
  1354. X    }
  1355. X
  1356. X/* Special case: if identifying from the screen, and
  1357. X * we're swallowed, and looking at something other than our own symbol,
  1358. X * then just say "the interior of a monster".
  1359. X */
  1360. X    if (u.uswallow && is_swallow_sym(q)) {
  1361. X        if (!found) {
  1362. X            pline("%c       %s", q, mon_interior);
  1363. X            (void)outspec(firstmatch=mon_interior, 0);
  1364. X        }
  1365. X        else
  1366. X            (void)outspec(mon_interior, 1);
  1367. X        found++; need_to_print = TRUE;
  1368. X    }
  1369. X
  1370. X/* Now check for objects */
  1371. X    for (i = 0; objsyms[i]; i++) {
  1372. X        if (q == objsyms[i]) {
  1373. X            need_to_print = TRUE;
  1374. X            if (!found) {
  1375. X                pline("%c       %s",q,an(objexplain[i]));
  1376. X                (void)outspec(firstmatch = objexplain[i], 0);
  1377. X                found++;
  1378. X            }
  1379. X            else if (outspec(objexplain[i], 1))
  1380. X                found++;
  1381. X        }
  1382. X    }
  1383. X
  1384. X/* Now check for graphics symbols */
  1385. X    for (i = 0; i < MAXPCHARS; i++) {
  1386. X        if ( q == showsyms[i] && (*explainsyms[i])) {
  1387. X            if (!found) {
  1388. X                pline("%c       %s",q,an(explainsyms[i]));
  1389. X                (void)outspec(firstmatch = explainsyms[i], 0);
  1390. X                found++;
  1391. X            }
  1392. X            else if (outspec(explainsyms[i], 1))
  1393. X                found++;
  1394. X            if (i == S_altar || i == S_trap || i == S_web)
  1395. X                need_to_print = TRUE;
  1396. X        }
  1397. X    }
  1398. X
  1399. X    if (!found)
  1400. X        pline("I've never heard of such things.");
  1401. X    else if (cc.x != -1) {    /* a specific object on screen */
  1402. X        if (found > 1 || need_to_print) {
  1403. X            Strcpy(inp, lookat(cc.x, cc.y, q));
  1404. X            if (*inp)
  1405. X                pline("(%s)", inp);
  1406. X        }
  1407. X        else {
  1408. X            Strcpy(inp, firstmatch);
  1409. X        }
  1410. X    }
  1411. X    else if (found == 1) {
  1412. X        Strcpy(inp, firstmatch);
  1413. X    }
  1414. X    else
  1415. X        found = FALSE;    /* abort the 'More info?' stuff */
  1416. X
  1417. X/* check the data file for information about this thing */
  1418. X
  1419. Xcheckfile:
  1420. X
  1421. X    if (!strncmp(inp, "interior of ", 12))
  1422. X        inp += 12;
  1423. X    if (!strncmp(inp, "a ", 2))
  1424. X        inp += 2;
  1425. X    else if (!strncmp(inp, "an ", 3))
  1426. X        inp += 3;
  1427. X    else if (!strncmp(inp, "the ", 4))
  1428. X        inp += 4;
  1429. X    if (!strncmp(inp, "tame ", 5))
  1430. X        inp += 5;
  1431. X    else if (!strncmp(inp, "peaceful ", 9))
  1432. X        inp += 9;
  1433. X    if (!strncmp(inp, "invisible ", 10))
  1434. X        inp += 10;
  1435. X
  1436. X/*
  1437. X * look in the file for more info if:
  1438. X * the user typed in the whole name (!q)
  1439. X * OR we've found a possible match with the character q (found) and
  1440. X *    flags.help is TRUE
  1441. X * and, of course, the name to look for must be non-empty.
  1442. X */
  1443. X    if ((!q || (found && flags.help)) && *inp) {
  1444. X/* adjust the input to remove "named " and convert to lower case */
  1445. X         for (ep = inp; *ep; ) {
  1446. X            if ((!strncmp(ep, " named ", 7) && (alt = ep + 7)) ||
  1447. X                !strncmp(ep, " called ", 8))
  1448. X                *ep = 0;
  1449. X            else {
  1450. X                if(isupper(*ep)) *ep = tolower(*ep);
  1451. X                ep++;
  1452. X            }
  1453. X        }
  1454. X
  1455. X/*
  1456. X * If the object is named, then the name is the alternate search string;
  1457. X * otherwise, the result of makesingular() applied to the name is. This
  1458. X * isn't strictly optimal, but named objects of interest to the user
  1459. X * will usually be found under their name, rather than under their
  1460. X * object type, so looking for a singular form is pointless.
  1461. X */
  1462. X
  1463. X        if (!alt)
  1464. X            alt = makesingular(inp);
  1465. X        else
  1466. X            for (ep = alt; *ep; ep++) 
  1467. X                if(isupper(*ep)) *ep = tolower(*ep);
  1468. X
  1469. X        while(fgets(buf,BUFSZ,fp)) {
  1470. X            if(*buf != '\t') {
  1471. X                ep = index(buf, '\n');
  1472. X                if(ep) *ep = 0;
  1473. X                else impossible("bad data file");
  1474. X                if (pmatch(buf, inp)||(alt && pmatch(buf, alt))) {
  1475. X                found_in_file = TRUE;
  1476. X                break;
  1477. X                }
  1478. X            }
  1479. X        }
  1480. X    }
  1481. X
  1482. X    if(found_in_file) {
  1483. X/* skip over other possible matches for the info */
  1484. X        for(;;) {
  1485. X            if ( (i = getc(fp)) == '\t' ) {
  1486. X                (void) ungetc(i, fp);
  1487. X                break;
  1488. X            }
  1489. X            if (!fgets(buf, BUFSZ, fp)) {
  1490. X                break;
  1491. X            }
  1492. X        }
  1493. X        if (q) {
  1494. X            pline("More info? ");
  1495. X            if(yn() == 'y') {
  1496. X                page_more(fp,1); /* does fclose() */
  1497. X                flags.verbose = oldverb;
  1498. X                return 0;
  1499. X            }
  1500. X        }
  1501. X        else {
  1502. X            page_more(fp, 1);
  1503. X            flags.verbose = oldverb;
  1504. X            return 0;
  1505. X        }
  1506. X    }
  1507. X    else if (!q)
  1508. X        pline("I don't have any information on those things.");
  1509. X
  1510. X/* if specified by cursor, keep going */
  1511. X    if(cc.x != -1) {
  1512. X        more();
  1513. X        rewind(fp);
  1514. X        goto selobj;
  1515. X    }
  1516. X    (void) fclose(fp);     /* kopper@psuvax1 */
  1517. X    flags.verbose = oldverb;
  1518. X    return 0;
  1519. X}
  1520. X
  1521. Xint
  1522. Xdowhatdoes()
  1523. X{
  1524. X    FILE *fp;
  1525. X    char bufr[BUFSZ+6];
  1526. X    register char *buf = &bufr[6], *ep, q, ctrl, meta;
  1527. X#ifdef OS2_CODEVIEW
  1528. X    char tmp[PATHLEN];
  1529. X
  1530. X    Strcpy(tmp,hackdir);
  1531. X    append_slash(tmp);
  1532. X    Strcat(tmp,CMDHELPFILE);
  1533. X    if(!(fp = fopen(tmp,"r"))) {
  1534. X#else
  1535. X# ifdef MACOS
  1536. X    if(!(fp = fopen(CMDHELPFILE, "r")))
  1537. X        fp = openFile(CMDHELPFILE, "r");
  1538. X    if (!fp) {
  1539. X# else
  1540. X    if(!(fp = fopen(CMDHELPFILE, "r"))) {
  1541. X# endif
  1542. X#endif
  1543. X        pline("Cannot open data file!");
  1544. X        return 0;
  1545. X    }
  1546. X
  1547. X    pline("What command? ");
  1548. X#if defined(UNIX) || defined(VMS)
  1549. X    introff();
  1550. X#endif
  1551. X    q = readchar();
  1552. X#if defined(UNIX) || defined(VMS)
  1553. X    intron();
  1554. X#endif
  1555. X    ctrl = ((q <= '\033') ? (q - 1 + 'A') : 0);
  1556. X    meta = ((0x80 & q) ? (0x7f & q) : 0);
  1557. X    while(fgets(buf,BUFSZ,fp))
  1558. X        if ((ctrl && *buf=='^' && *(buf+1)==ctrl) ||
  1559. X        (meta && *buf=='M' && *(buf+1)=='-' && *(buf+2)==meta) ||
  1560. X        *buf==q) {
  1561. X        ep = index(buf, '\n');
  1562. X        if(ep) *ep = 0;
  1563. X        if (ctrl && buf[2] == '\t'){
  1564. X            buf = bufr + 1;
  1565. X            (void) strncpy(buf, "^?      ", 8);
  1566. X            buf[1] = ctrl;
  1567. X        } else if (meta && buf[3] == '\t'){
  1568. X            buf = bufr + 2;
  1569. X            (void) strncpy(buf, "M-?     ", 8);
  1570. X            buf[2] = meta;
  1571. X        } else if(buf[1] == '\t'){
  1572. X            buf = bufr;
  1573. X            buf[0] = q;
  1574. X            (void) strncpy(buf+1, "       ", 7);
  1575. X        }
  1576. X        pline("%s", buf);
  1577. X        (void) fclose(fp);
  1578. X        return 0;
  1579. X        }
  1580. X    pline("I've never heard of such commands.");
  1581. X    (void) fclose(fp);
  1582. X    return 0;
  1583. X}
  1584. X
  1585. X/* make the paging of a file interruptible */
  1586. Xstatic volatile int NEARDATA got_intrup;
  1587. X
  1588. X#if !defined(MSDOS) && !defined(TOS) && !defined(MACOS)
  1589. Xstatic int
  1590. Xintruph(){
  1591. X    (void) signal(SIGINT, (SIG_RET_TYPE) intruph);
  1592. X    got_intrup++;
  1593. X    return 0;
  1594. X}
  1595. X#endif
  1596. X
  1597. X/* simple pager, also used from dohelp() */
  1598. Xstatic void
  1599. Xpage_more(fp,strip)
  1600. XFILE *fp;
  1601. Xint strip;    /* nr of chars to be stripped from each line (0 or 1) */
  1602. X{
  1603. X#ifdef MACOS
  1604. X    short tmpflags;
  1605. X    
  1606. X    tmpflags = macflags;
  1607. X    macflags &= ~fDoUpdate;
  1608. X    if(!mac_more(fp, strip)) {
  1609. X        macflags |= (tmpflags & fDoUpdate);
  1610. X        return;
  1611. X    }
  1612. X    macflags |= (tmpflags & fDoUpdate);
  1613. X#else
  1614. X    register char *bufr;
  1615. X#if !defined(MSDOS) && !defined(MINIMAL_TERM)
  1616. X    register char *ep;
  1617. X#endif
  1618. X#if !defined(MSDOS) && !defined(TOS)
  1619. X    int (*prevsig)() = (int (*)())signal(SIGINT, (SIG_RET_TYPE) intruph);
  1620. X#endif
  1621. X#if defined(MSDOS) || defined(MINIMAL_TERM)
  1622. X    /* There seems to be a bug in ANSI.SYS  The first tab character
  1623. X     * after a clear screen sequence is not expanded correctly.  Thus
  1624. X     * expand the tabs by hand -dgk
  1625. X     */
  1626. X    int tabstop = 8, spaces;
  1627. X    char buf[BUFSIZ], *bufp, *bufrp;
  1628. X
  1629. X    set_pager(0);
  1630. X    bufr = (char *) alloc((unsigned) COLNO);
  1631. X    while (fgets(buf, BUFSIZ, fp) && (!strip || *buf == '\t')){
  1632. X        bufp = buf;
  1633. X        bufrp = bufr;
  1634. X        if (strip && *bufp && *bufp != '\n')
  1635. X            *bufrp++ = *bufp++;
  1636. X        while (*bufp && *bufp != '\n') {
  1637. X            if (*bufp == '\t') {
  1638. X                spaces = tabstop - (bufrp - bufr) % tabstop;
  1639. X                while (spaces--)
  1640. X                    *bufrp++ = ' ';
  1641. X                bufp++;
  1642. X            } else
  1643. X                *bufrp++ = *bufp++;
  1644. X        }
  1645. X        *bufrp = '\0';
  1646. X#else /* MSDOS /**/
  1647. X    set_pager(0);
  1648. X    bufr = (char *) alloc((unsigned) COLNO);
  1649. X    bufr[COLNO-1] = 0;
  1650. X    while(fgets(bufr,COLNO-1,fp) && (!strip || *bufr == '\t')){
  1651. X        ep = index(bufr, '\n');
  1652. X        if(ep)
  1653. X            *ep = 0;
  1654. X#endif /* MSDOS /**/
  1655. X        if(got_intrup || page_line(bufr+strip)) {
  1656. X            set_pager(2);
  1657. X            goto ret;
  1658. X        }
  1659. X    }
  1660. X    set_pager(1);
  1661. Xret:
  1662. X    free((genericptr_t) bufr);
  1663. X    (void) fclose(fp);
  1664. X#if !defined(MSDOS) && !defined(TOS)
  1665. X    (void) signal(SIGINT, (SIG_RET_TYPE) prevsig);
  1666. X    got_intrup = 0;
  1667. X#endif
  1668. X#endif /* MACOS */
  1669. X}
  1670. X
  1671. X#endif /* OVLB */
  1672. X
  1673. X#define    PAGMIN    12    /* minimum # of lines for page below level map */
  1674. X
  1675. X#ifndef OVLB
  1676. X
  1677. XSTATIC_DCL boolean whole_screen;
  1678. X
  1679. X#else /* OVLB */
  1680. X
  1681. XSTATIC_OVL boolean NEARDATA whole_screen = TRUE;
  1682. X
  1683. Xvoid
  1684. Xset_whole_screen() {    /* called in termcap as soon as LI is known */
  1685. X    whole_screen = (LI-ROWNO-2 <= PAGMIN || !CD);
  1686. X}
  1687. X
  1688. X#ifdef NEWS
  1689. Xint
  1690. Xreadnews() {
  1691. X    register int ret;
  1692. X
  1693. X    whole_screen = TRUE;    /* force a docrt(), our first */
  1694. X    ret = page_file(NEWS, TRUE);
  1695. X    set_whole_screen();
  1696. X    return(ret);        /* report whether we did docrt() */
  1697. X}
  1698. X#endif
  1699. X
  1700. Xvoid
  1701. Xset_pager(mode)
  1702. Xregister int mode;    /* 0: open  1: wait+close  2: close */
  1703. X{
  1704. X#ifdef LINT    /* lint may handle static decl poorly -- static boolean so; */
  1705. X    boolean so;
  1706. X#else
  1707. X    static boolean NEARDATA so;
  1708. X#endif
  1709. X    if(mode == 0) {
  1710. X        if(!whole_screen) {
  1711. X            /* clear topline */
  1712. X            clrlin();
  1713. X            /* use part of screen below level map */
  1714. X            curs(1, ROWNO+4);
  1715. X        } else {
  1716. X            cls();
  1717. X        }
  1718. X        so = flags.standout;
  1719. X        flags.standout = 1;
  1720. X    } else {
  1721. X        if(mode == 1) {
  1722. X            curs(1, LI);
  1723. X            more();
  1724. X        }
  1725. X        flags.standout = so;
  1726. X        if(whole_screen)
  1727. X            docrt();
  1728. X        else {
  1729. X            curs(1, ROWNO+4);
  1730. X            cl_eos();
  1731. X        }
  1732. X    }
  1733. X}
  1734. X
  1735. X#endif /* OVLB */
  1736. X#ifdef OVL0
  1737. X
  1738. Xint
  1739. Xpage_line(s)        /* returns 1 if we should quit */
  1740. Xregister const char *s;
  1741. X{
  1742. X#ifdef CLIPPING
  1743. X/* we assume here that no data files have more than 80 chars/line */
  1744. X    static char tmp[81], *t;
  1745. X#endif
  1746. X    if(cury == LI-1) {
  1747. X        if(!*s)
  1748. X            return(0);    /* suppress blank lines at top */
  1749. X        (void) putchar('\n');
  1750. X        cury++;
  1751. X        cmore("q\033");
  1752. X        if(morc) {
  1753. X            morc = 0;
  1754. X            return(1);
  1755. X        }
  1756. X        if(whole_screen)
  1757. X            cls();
  1758. X        else {
  1759. X            curs(1, ROWNO+4);
  1760. X            cl_eos();
  1761. X        }
  1762. X    }
  1763. X#ifdef CLIPPING
  1764. X/* if lines are too long for the screen, first try stripping leading blanks */
  1765. X    if (strlen(s) >= CO) {
  1766. X        while (*s == ' ' || *s == '\t') s++;
  1767. X    }
  1768. X
  1769. X/* if it's still too long, try compressing blanks */
  1770. X    if (strlen(s) >= CO) {
  1771. X        t = tmp;
  1772. X        while ( (*t = *s) != 0) {
  1773. X            if (*t == ' ') {
  1774. X                while (*s == ' ')
  1775. X                    s++;
  1776. X            }
  1777. X            else
  1778. X                s++;
  1779. X            t++;
  1780. X        }
  1781. X        s = tmp;
  1782. X    }
  1783. X#endif /* CLIPPING */
  1784. X
  1785. X#ifdef TERMINFO
  1786. X    xputs(s); xputc('\n');
  1787. X#else
  1788. X    (void) puts(s);
  1789. X# ifdef MACOS
  1790. X    (void) putchar('\n');
  1791. X# endif
  1792. X#endif
  1793. X    cury++;
  1794. X    return(0);
  1795. X}
  1796. X
  1797. X/*
  1798. X * Flexible pager: feed it with a number of lines and it will decide
  1799. X * whether these should be fed to the pager above, or displayed in a
  1800. X * corner.
  1801. X * Call:
  1802. X *    cornline(0, title or 0)    : initialize
  1803. X *    cornline(1, text)    : add text to the chain of texts
  1804. X *    cornline(2, morcs)    : output everything and cleanup
  1805. X *    cornline(3, 0)        : cleanup
  1806. X *    cornline(-1,"")        : special, for help menu mode only
  1807. X */
  1808. X
  1809. Xvoid
  1810. Xcornline(mode, text)
  1811. Xint mode;
  1812. Xconst char *text;
  1813. X{
  1814. X    static struct line {
  1815. X        struct line *next_line;
  1816. X        char *line_text;
  1817. X    } NEARDATA *texthead, NEARDATA *texttail;
  1818. X    static int NEARDATA maxlen;
  1819. X    static int NEARDATA linect;
  1820. X    register struct line *tl;
  1821. X    register boolean hmenu = FALSE;
  1822. X
  1823. X    if(mode == -1) { /* help menu display only */
  1824. X        mode = 2;
  1825. X        hmenu = TRUE;
  1826. X    }
  1827. X    if(mode == 0) {
  1828. X        texthead = 0;
  1829. X        maxlen = 0;
  1830. X        linect = 0;
  1831. X        if(text) {
  1832. X            cornline(1, text);    /* title */
  1833. X            cornline(1, "");    /* blank line */
  1834. X        }
  1835. X        return;
  1836. X    }
  1837. X
  1838. X    if(mode == 1) {
  1839. X        register int len;
  1840. X
  1841. X        if(!text) return;    /* superfluous, just to be sure */
  1842. X        linect++;
  1843. X        len = strlen(text) + 1; /* allow for an extra leading space */
  1844. X        if(len > maxlen)
  1845. X        maxlen = len;
  1846. X        tl = (struct line *)
  1847. X        alloc((unsigned)(len + sizeof(struct line) + 1));
  1848. X        tl->next_line = 0;
  1849. X        tl->line_text = (char *)(tl + 1);
  1850. X        tl->line_text[0] = ' ';
  1851. X        tl->line_text[1] = '\0';
  1852. X        Strcat(tl->line_text, text);
  1853. X        if(!texthead)
  1854. X        texthead = tl;
  1855. X        else
  1856. X        texttail->next_line = tl;
  1857. X        texttail = tl;
  1858. X        return;
  1859. X    }
  1860. X
  1861. X    /* --- now we really do it --- */
  1862. X    if(mode == 2 && linect == 1)                /* topline only */
  1863. X        pline("%s", texthead->line_text);
  1864. X    else
  1865. X    if(mode == 2) {
  1866. X        register int curline, lth;
  1867. X
  1868. X        if(flags.toplin == 1) more();    /* ab@unido */
  1869. X        remember_topl();
  1870. X
  1871. X        lth = CO - maxlen - 2;           /* Use full screen width */
  1872. X        if (linect < LI && lth >= 10) {             /* in a corner */
  1873. X        home ();
  1874. X        cl_end ();
  1875. X        flags.toplin = 0;
  1876. X        curline = 1;
  1877. X        for (tl = texthead; tl; tl = tl->next_line) {
  1878. X#if defined(MSDOS) && !defined(AMIGA)
  1879. X            cmov (lth, curline);
  1880. X#else
  1881. X            curs (lth, curline);
  1882. X#endif
  1883. X            if(curline > 1)
  1884. X            cl_end ();
  1885. X            xputs(tl->line_text);
  1886. X            curx = curx + strlen(tl->line_text);
  1887. X            curline++;
  1888. X        }
  1889. X        if(hmenu) {    /* help menu display */
  1890. X            do 
  1891. X                hc = lowc(readchar());
  1892. X            while (!valid_help(hc));
  1893. X        }
  1894. X#if defined(MSDOS) && !defined(AMIGA)
  1895. X        cmov (lth, curline);
  1896. X#else
  1897. X        curs (lth, curline);
  1898. X#endif
  1899. X        cl_end ();
  1900. X        if (!hmenu) {
  1901. X            cmore (text);
  1902. X        }
  1903. X        if (!hmenu || clear_help(hc)) {
  1904. X            home ();
  1905. X            cl_end ();
  1906. X            docorner (lth, curline-1);
  1907. X        }
  1908. X        } else {                    /* feed to pager */
  1909. X#ifdef MACOS
  1910. X        short    tmpflags;
  1911. X        
  1912. X        tmpflags = macflags;
  1913. X        macflags &= ~fDoNonKeyEvt;
  1914. X#endif
  1915. X        set_pager(0);
  1916. X        for (tl = texthead; tl; tl = tl->next_line) {
  1917. X            if (page_line (tl->line_text)) {
  1918. X            set_pager(2);
  1919. X#ifdef MACOS
  1920. X            macflags = tmpflags;
  1921. X#endif
  1922. X            while(tl = texthead) {
  1923. X                texthead = tl->next_line;
  1924. X                free((genericptr_t) tl);
  1925. X            }
  1926. X            return;
  1927. X            }
  1928. X        }
  1929. X        if(text) {
  1930. X            cgetret(text);
  1931. X            set_pager(2);
  1932. X        } else
  1933. X            set_pager(1);
  1934. X#ifdef MACOS
  1935. X        macflags = tmpflags;
  1936. X#endif
  1937. X        }
  1938. X    }
  1939. X
  1940. X    while(tl = texthead) {
  1941. X        texthead = tl->next_line;
  1942. X        free((genericptr_t) tl);
  1943. X    }
  1944. X}
  1945. X
  1946. X#endif /* OVL0 */
  1947. X#ifdef OVLB
  1948. X
  1949. X#ifdef WIZARD
  1950. Xstatic
  1951. Xvoid
  1952. Xwiz_help()
  1953. X{
  1954. X    cornline(0, "Wizard-Mode Quick Reference:");
  1955. X    cornline(1, "^E  ==  detect secret doors and traps.");
  1956. X    cornline(1, "^F  ==  do magic mapping.");
  1957. X    cornline(1, "^G  ==  create monster.");
  1958. X    cornline(1, "^I  ==  identify items in pack.");
  1959. X    cornline(1, "^O  ==  tell locations of special levels.");
  1960. X    cornline(1, "^T  ==  do intra-level teleport.");
  1961. X    cornline(1, "^V  ==  do trans-level teleport.");
  1962. X    cornline(1, "^W  ==  make wish.");
  1963. X    cornline(1, "^X  ==  show intrinsic attributes.");
  1964. X    cornline(1, "");
  1965. X    cornline(2, "");
  1966. X}
  1967. X#endif
  1968. X
  1969. Xstatic void
  1970. Xhelp_menu() {
  1971. X    cornline(0, "Information available:");
  1972. X    cornline(1, "a.  Long description of the game and commands.");
  1973. X    cornline(1, "b.  List of game commands.");
  1974. X    cornline(1, "c.  Concise history of NetHack.");
  1975. X    cornline(1, "d.  Info on a character in the game display.");
  1976. X    cornline(1, "e.  Info on what a given key does.");
  1977. X    cornline(1, "f.  List of game options.");
  1978. X    cornline(1, "g.  Longer explanation of game options.");
  1979. X    cornline(1, "h.  List of extended commands.");
  1980. X    cornline(1, "i.  The NetHack license.");
  1981. X#ifdef MACOS
  1982. X    cornline(1, "j.  Macintosh primer.");
  1983. X#endif
  1984. X#ifdef WIZARD
  1985. X    if (wizard)
  1986. X# ifdef MACOS
  1987. X        cornline(1, "k.  List of wizard-mode commands.");
  1988. X# else
  1989. X        cornline(1, "j.  List of wizard-mode commands.");
  1990. X# endif
  1991. X#endif
  1992. X    cornline(1, "");
  1993. X#ifdef WIZARD
  1994. X    if (wizard)
  1995. X# ifdef MACOS
  1996. X        cornline(1, "Select one of a,b,c,d,e,f,g,h,i,j,k or ESC: ");
  1997. X# else
  1998. X        cornline(1, "Select one of a,b,c,d,e,f,g,h,i,j or ESC: ");
  1999. X# endif
  2000. X    else
  2001. X#endif
  2002. X#ifdef MACOS
  2003. X        cornline(1, "Select one of a,b,c,d,e,f,g,h,i,j or ESC: ");
  2004. X#else
  2005. X        cornline(1, "Select one of a,b,c,d,e,f,g,h,i or ESC: ");
  2006. X#endif
  2007. X    cornline(-1,"");
  2008. X}
  2009. X
  2010. XSTATIC_OVL boolean
  2011. Xclear_help(c)
  2012. Xchar c;
  2013. X{
  2014. X    /* those valid_help characters which do not correspond to help routines
  2015. X     * that redraw the whole screen on their own.  if we always clear the
  2016. X     * help menu, we end up restoring the part of the maze underneath the
  2017. X     * help menu when the last page of a long help file is displayed with
  2018. X     * an external pager.
  2019. X     *
  2020. X     * When whole_screen is FALSE and the internal pager is used, the
  2021. X     * screen is big enough so that the maze is left in place during paging
  2022. X     * and the paging occurs in the lower part of the screen.  In this case
  2023. X     * the pager clears out the part it wrote over when it exits but it
  2024. X     * doesn't redraw the whole screen.  So all characters require that
  2025. X     * the help menu be cleared.
  2026. X     *
  2027. X     * When an external pager is used, the screen is always cleared.
  2028. X     * However, the "f" and "h" help options always use the internal
  2029. X     * pager even if DEF_PAGER is defined.
  2030. X     *                        - Bob Wilber  wilber@homxb.att.com  10/20/89
  2031. X     */
  2032. X    return(index(quitchars,c) || c == 'd' || c == 'e'
  2033. X#ifdef DEF_PAGER
  2034. X            || (!whole_screen && (c == 'f' || c == 'h'))
  2035. X#else
  2036. X            || !whole_screen
  2037. X#endif
  2038. X#ifdef WIZARD
  2039. X# ifdef MACOS
  2040. X        || c == 'k'
  2041. X# else
  2042. X        || c == 'j'
  2043. X# endif
  2044. X#endif
  2045. X        );
  2046. X}
  2047. X
  2048. XSTATIC_OVL boolean
  2049. Xvalid_help(c)
  2050. Xchar c;
  2051. X{
  2052. X#ifdef WIZARD
  2053. X# ifdef MACOS
  2054. X    return ((c >= 'a' && c <= (wizard ? 'k' : 'j')) || index(quitchars,c));
  2055. X# else
  2056. X    return ((c >= 'a' && c <= (wizard ? 'j' : 'i')) || index(quitchars,c));
  2057. X# endif
  2058. X#else
  2059. X# ifdef MACOS
  2060. X    return ((c >= 'a' && c <= 'j') || index(quitchars,c));
  2061. X# else
  2062. X    return ((c >= 'a' && c <= 'i') || index(quitchars,c));
  2063. X# endif
  2064. X#endif
  2065. X}
  2066. X
  2067. Xint
  2068. Xdohelp()
  2069. X{
  2070. X#ifdef MACOS
  2071. X    term_info    *t;
  2072. X
  2073. X    macflags &= ~fDoNonKeyEvt;
  2074. X    t = (term_info *)GetWRefCon(HackWindow);
  2075. X    SetVol((StringPtr)NULL,
  2076. X        (t->auxFileVRefNum) ? t->auxFileVRefNum : t->recordVRefNum);
  2077. X#endif
  2078. X    help_menu();
  2079. X    if (!index(quitchars, hc)) {
  2080. X        switch(hc) {
  2081. X            case 'a':  (void) page_file(HELP, FALSE);  break;
  2082. X            case 'b':  (void) page_file(SHELP, FALSE);  break;
  2083. X            case 'c':  (void) dohistory();  break;
  2084. X            case 'd':  (void) dowhatis();  break;
  2085. X            case 'e':  (void) dowhatdoes();  break;
  2086. X            case 'f':  option_help();  break;
  2087. X            case 'g':  (void) page_file(OPTIONFILE, FALSE);  break;
  2088. X            case 'h':  (void) doextlist();  break;
  2089. X            case 'i':  (void) page_file(LICENSE, FALSE);  break;
  2090. X#ifdef WIZARD
  2091. X# ifdef MACOS
  2092. X            case 'j':  (void) page_file(MACHELP, FALSE);  break;
  2093. X            case 'k':  wiz_help();  break;
  2094. X# else
  2095. X            case 'j':  wiz_help();  break;
  2096. X# endif
  2097. X#endif
  2098. X        }
  2099. X    }
  2100. X#ifdef MACOS
  2101. X    SetVol((StringPtr)NULL, t->recordVRefNum);
  2102. X    macflags |= fDoNonKeyEvt;
  2103. X#endif
  2104. X    return 0;
  2105. X}
  2106. X
  2107. Xint
  2108. Xdohistory()
  2109. X{
  2110. X    (void) page_file(HISTORY, FALSE);
  2111. X    return 0;
  2112. X}
  2113. X
  2114. Xint
  2115. Xpage_file(fnam, silent)    /* return: 0 - cannot open fnam; 1 - otherwise */
  2116. Xregister const char *fnam;
  2117. Xboolean silent;
  2118. X{
  2119. X#ifdef DEF_PAGER            /* this implies that UNIX is defined */
  2120. X      {
  2121. X    /* use external pager; this may give security problems */
  2122. X
  2123. X    register int fd = open(fnam, 0);
  2124. X
  2125. X    if(fd < 0) {
  2126. X        if(!silent) pline("Cannot open %s.", fnam);
  2127. X        return(0);
  2128. X    }
  2129. X    if(child(1)){
  2130. X        /* Now that child() does a setuid(getuid()) and a chdir(),
  2131. X           we may not be able to open file fnam anymore, so make
  2132. X           it stdin. */
  2133. X        (void) close(0);
  2134. X        if(dup(fd)) {
  2135. X            if(!silent) Printf("Cannot open %s as stdin.\n", fnam);
  2136. X        } else {
  2137. X            (void) execl(catmore, "page", NULL);
  2138. X            if(!silent) Printf("Cannot exec %s.\n", catmore);
  2139. X        }
  2140. X        exit(1);
  2141. X    }
  2142. X    (void) close(fd);
  2143. X      }
  2144. X#else
  2145. X      {
  2146. X    FILE *f;            /* free after Robert Viduya */
  2147. X#ifdef OS2_CODEVIEW
  2148. X    char tmp[PATHLEN];
  2149. X
  2150. X    Strcpy(tmp,hackdir);
  2151. X    append_slash(tmp);
  2152. X    Strcat(tmp,fnam);
  2153. X    if ((f = fopen (tmp, "r")) == (FILE *) 0) {
  2154. X#else
  2155. X# ifdef MACOS
  2156. X    if ((f = fopen (fnam, "r")) == (FILE *) 0)
  2157. X        f = openFile(fnam, "r");
  2158. X    if (!f) {
  2159. X# else
  2160. X    if ((f = fopen (fnam, "r")) == (FILE *) 0) {
  2161. X# endif
  2162. X#endif
  2163. X        if(!silent) {
  2164. X            home(); perror (fnam); flags.toplin = 1;
  2165. X            pline ("Cannot open %s.", fnam);
  2166. X        }
  2167. X        return(0);
  2168. X    }
  2169. X    page_more(f, 0);
  2170. X      }
  2171. X#endif /* DEF_PAGER /**/
  2172. X
  2173. X    return(1);
  2174. X}
  2175. X
  2176. X#ifdef UNIX
  2177. X#ifdef SHELL
  2178. Xint
  2179. Xdosh(){
  2180. Xregister char *str;
  2181. X    if(child(0)) {
  2182. X        if(str = getenv("SHELL"))
  2183. X            (void) execl(str, str, NULL);
  2184. X        else
  2185. X            (void) execl("/bin/sh", "sh", NULL);
  2186. X        pline("sh: cannot execute.");
  2187. X        exit(1);
  2188. X    }
  2189. X    return 0;
  2190. X}
  2191. X#endif /* SHELL /**/
  2192. X
  2193. X#if defined(SHELL) || defined(DEF_PAGER) || defined(DEF_MAILREADER)
  2194. Xint
  2195. Xchild(wt)
  2196. Xint wt;
  2197. X{
  2198. Xregister int f = fork();
  2199. X    if(f == 0){        /* child */
  2200. X        settty(NULL);        /* also calls end_screen() */
  2201. X        (void) setgid(getgid());
  2202. X        (void) setuid(getuid());
  2203. X#ifdef CHDIR
  2204. X        (void) chdir(getenv("HOME"));
  2205. X#endif
  2206. X        return(1);
  2207. X    }
  2208. X    if(f == -1) {    /* cannot fork */
  2209. X        pline("Fork failed.  Try again.");
  2210. X        return(0);
  2211. X    }
  2212. X    /* fork succeeded; wait for child to exit */
  2213. X    (void) signal(SIGINT,SIG_IGN);
  2214. X    (void) signal(SIGQUIT,SIG_IGN);
  2215. X    (void) wait(
  2216. X#if defined(BSD) || defined(ULTRIX)
  2217. X        (union wait *)
  2218. X#else
  2219. X        (int *)
  2220. X#endif
  2221. X        0);
  2222. X    gettty();
  2223. X    setftty();
  2224. X    (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  2225. X#ifdef WIZARD
  2226. X    if(wizard) (void) signal(SIGQUIT,SIG_DFL);
  2227. X#endif
  2228. X    if(wt) {
  2229. X        boolean so;
  2230. X
  2231. X        cmov(1, LI);    /* get prompt in reasonable place */
  2232. X        so = flags.standout;
  2233. X        flags.standout = 1;
  2234. X        more();
  2235. X        flags.standout = so;
  2236. X    }
  2237. X    docrt();
  2238. X    return(0);
  2239. X}
  2240. X#endif
  2241. X#endif /* UNIX /**/
  2242. X
  2243. X#endif /* OVLB */
  2244. END_OF_FILE
  2245. if test 28788 -ne `wc -c <'src/pager.c'`; then
  2246.     echo shar: \"'src/pager.c'\" unpacked with wrong size!
  2247. fi
  2248. # end of 'src/pager.c'
  2249. fi
  2250. if test -f 'src/sit.c' -a "${1}" != "-c" ; then 
  2251.   echo shar: Will not clobber existing file \"'src/sit.c'\"
  2252. else
  2253. echo shar: Extracting \"'src/sit.c'\" \(5549 characters\)
  2254. sed "s/^X//" >'src/sit.c' <<'END_OF_FILE'
  2255. X/*    SCCS Id: @(#)sit.c    3.0    89/06/12
  2256. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2257. X/* NetHack may be freely redistributed.  See license for details. */
  2258. X
  2259. X#include "hack.h"
  2260. X
  2261. X#if defined(THRONES) || defined(SPELLS)
  2262. Xvoid
  2263. Xtake_gold()
  2264. X{
  2265. X    if (u.ugold <= 0)  {
  2266. X        You("feel a strange sensation.");
  2267. X    } else {
  2268. X        You("notice you have no gold!");
  2269. X        u.ugold = 0;
  2270. X        flags.botl = 1;
  2271. X    }
  2272. X}
  2273. X#endif
  2274. X
  2275. Xint
  2276. Xdosit() {
  2277. X#ifdef THRONES
  2278. X    register int cnt;
  2279. X#endif
  2280. X
  2281. X    if(Levitation)  {
  2282. X        pline("There's nothing to sit on up here.");
  2283. X#ifdef THRONES
  2284. X    } else  if(IS_THRONE(levl[u.ux][u.uy].typ)) {
  2285. X
  2286. X        if (rnd(6) > 4)  {
  2287. X        switch (rnd(13))  {
  2288. X            case 1:
  2289. X            adjattrib(rn2(A_MAX), -rn1(4,3), FALSE);
  2290. X            losehp(rnd(10), "cursed throne", KILLED_BY_AN);
  2291. X            break;
  2292. X            case 2:
  2293. X            adjattrib(rn2(A_MAX), 1, FALSE);
  2294. X            break;
  2295. X            case 3:
  2296. X        pline("A%s charge of electricity shoots through your body!",
  2297. X                  (Shock_resistance) ? "" : " massive");
  2298. X            if(Shock_resistance)
  2299. X                losehp(rnd(6), "electric chair", KILLED_BY_AN);
  2300. X            else    losehp(rnd(30), "electric chair", KILLED_BY_AN);
  2301. X            break;
  2302. X            case 4:
  2303. X            You("feel much, much better!");
  2304. X            if(u.uhp >= (u.uhpmax - 5))  u.uhpmax += 4;
  2305. X            u.uhp = u.uhpmax;
  2306. X            make_blinded(0L,TRUE);
  2307. X            make_sick(0L,FALSE);
  2308. X            heal_legs();
  2309. X            flags.botl = 1;
  2310. X            break;
  2311. X            case 5:
  2312. X            take_gold();
  2313. X            break;
  2314. X            case 6:
  2315. X            if(u.uluck + rn2(5) < 0) {
  2316. X                You("feel your luck is changing.");
  2317. X                change_luck(1);
  2318. X            } else        makewish();
  2319. X            break;
  2320. X            case 7:
  2321. X            cnt = rnd(10);
  2322. X            You("hear a voice echo:");
  2323. X            pline("\"Thy audience hath been summoned, Sire!\"");
  2324. X            while(cnt--)
  2325. X                (void) makemon(courtmon(), u.ux, u.uy);
  2326. X            break;
  2327. X            case 8:
  2328. X            You("hear a voice echo:");
  2329. X            pline("\"By thy Imperious order, Sire...\"");
  2330. X            do_genocide(1);
  2331. X            break;
  2332. X            case 9:
  2333. X            You("hear a voice echo:");
  2334. X    pline("\"A curse upon thee for sitting upon this most holy throne!\"");
  2335. X            if (Luck > 0)  {
  2336. X                make_blinded(Blinded + rn1(100,250),TRUE);
  2337. X            } else        rndcurse();
  2338. X            break;
  2339. X            case 10:
  2340. X            if (Luck < 0 || (HSee_invisible & INTRINSIC))  {
  2341. X                pline("An image forms in your mind.");
  2342. X                do_mapping();
  2343. X            } else  {
  2344. X                Your("vision clarifies.");
  2345. X                HSee_invisible |= INTRINSIC;
  2346. X            }
  2347. X            break;
  2348. X            case 11:
  2349. X            if (Luck < 0)  {
  2350. X                You("feel threatened.");
  2351. X                aggravate();
  2352. X            } else  {
  2353. X
  2354. X                You("feel a wrenching sensation.");
  2355. X                tele();        /* teleport him */
  2356. X            }
  2357. X            break;
  2358. X            case 12:
  2359. X            You("are granted a gift of insight!");
  2360. X            while (!ggetobj("identify", identify, rn2(5))
  2361. X                && invent);
  2362. X            break;
  2363. X            case 13:
  2364. X            Your("mind turns into a pretzel!");
  2365. X            make_confused(HConfusion + rn1(7,16),FALSE);
  2366. X            break;
  2367. X            default:    impossible("throne effect");
  2368. X                break;
  2369. X        }
  2370. X        } else    You("feel somehow out of place...");
  2371. X
  2372. X        if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ))    {
  2373. X        pline("The throne vanishes in a puff of logic.");
  2374. X/*        levl[u.ux][u.uy].scrsym = ROOM_SYM; */
  2375. X        levl[u.ux][u.uy].typ = ROOM;
  2376. X        if(Invisible) newsym(u.ux,u.uy);
  2377. X        }
  2378. X#endif
  2379. X#ifdef POLYSELF
  2380. X    } else if (lays_eggs(uasmon) || u.umonnum == PM_QUEEN_BEE) {
  2381. X        struct obj *uegg;
  2382. X
  2383. X        if (u.uhunger < objects[EGG].nutrition) {
  2384. X            You("are too weak to lay an egg.");
  2385. X            return 0;
  2386. X        }
  2387. X
  2388. X        uegg = mksobj(EGG, 0);
  2389. X        uegg->spe = 1;
  2390. X        uegg->quan = 1;
  2391. X        uegg->owt = weight(uegg);
  2392. X        uegg->corpsenm =
  2393. X            (u.umonnum==PM_QUEEN_BEE ? PM_KILLER_BEE : monsndx(uasmon));
  2394. X        uegg->known = uegg->dknown = 1;
  2395. X        You("lay an egg.");
  2396. X        dropy(uegg);
  2397. X        stackobj(uegg);
  2398. X        morehungry(objects[EGG].nutrition);
  2399. X#endif
  2400. X    } else
  2401. X        pline("Having fun sitting on the floor?");
  2402. X    return(1);
  2403. X}
  2404. X
  2405. Xvoid
  2406. Xrndcurse() {            /* curse a few inventory items at random! */
  2407. X
  2408. X    int    nobj = 0;
  2409. X    int    cnt, onum;
  2410. X    struct    obj    *otmp;
  2411. X
  2412. X    if(Antimagic) {
  2413. X        shieldeff(u.ux, u.uy);
  2414. X        You("feel a malignant aura surround you.");
  2415. X    }
  2416. X
  2417. X    for (otmp = invent; otmp; otmp = otmp->nobj)  nobj++;
  2418. X
  2419. X    if (nobj)
  2420. X        for (cnt = rnd(6/((!!Antimagic) + 1)); cnt > 0; cnt--)  {
  2421. X        onum = rn2(nobj);
  2422. X        for(otmp = invent; onum != 0; onum--)
  2423. X            otmp = otmp->nobj;
  2424. X        if(otmp->blessed)
  2425. X            otmp->blessed = 0;
  2426. X        else
  2427. X            otmp->cursed++;
  2428. X        }
  2429. X}
  2430. X
  2431. Xvoid
  2432. Xattrcurse() {            /* remove a random INTRINSIC ability */
  2433. X    switch(rnd(10)) {
  2434. X    case 1 : if (HFire_resistance & INTRINSIC) {
  2435. X            HFire_resistance &= ~INTRINSIC;
  2436. X            if (Inhell && !Fire_resistance) {
  2437. X                You("burn to a crisp.");
  2438. X                killer_format = NO_KILLER_PREFIX;
  2439. X                killer = self_pronoun("a gremlin stole %s fire resistance in hell", "his");
  2440. X                done(BURNING);
  2441. X            } else You("feel warmer.");
  2442. X            break;
  2443. X        }
  2444. X    case 2 : if (HTeleportation & INTRINSIC) {
  2445. X            HTeleportation &= ~INTRINSIC;
  2446. X            You("feel less jumpy.");
  2447. X            break;
  2448. X        }
  2449. X    case 3 : if (HPoison_resistance & INTRINSIC) {
  2450. X            HPoison_resistance &= ~INTRINSIC;
  2451. X            You("feel a little sick!");
  2452. X            break;
  2453. X        }
  2454. X    case 4 : if (HTelepat & INTRINSIC) {
  2455. X            HTelepat &= ~INTRINSIC;
  2456. X            Your("senses fail!");
  2457. X            break;
  2458. X        }
  2459. X    case 5 : if (HCold_resistance & INTRINSIC) {
  2460. X            HCold_resistance &= ~INTRINSIC;
  2461. X            You("feel cooler.");
  2462. X            break;
  2463. X        }
  2464. X    case 6 : if (HInvis & INTRINSIC) {
  2465. X            HInvis &= ~INTRINSIC;
  2466. X            You("feel paranoid.");
  2467. X            break;
  2468. X        }
  2469. X    case 7 : if (HSee_invisible & INTRINSIC) {
  2470. X            HSee_invisible &= ~INTRINSIC;
  2471. X            You("thought you saw something!");
  2472. X            break;
  2473. X        }
  2474. X    case 8 : if (Fast & INTRINSIC) {
  2475. X            Fast &= ~INTRINSIC;
  2476. X            You("feel slower.");
  2477. X            break;
  2478. X        }
  2479. X    case 9 : if (Stealth & INTRINSIC) {
  2480. X            Stealth &= ~INTRINSIC;
  2481. X            You("feel clumsy.");
  2482. X            break;
  2483. X        }
  2484. X    case 10: if (Protection & INTRINSIC) {
  2485. X            Protection &= ~INTRINSIC;
  2486. X            You("feel vulnerable.");
  2487. X            break;
  2488. X        }
  2489. X    default: break;
  2490. X    }
  2491. X}
  2492. END_OF_FILE
  2493. if test 5549 -ne `wc -c <'src/sit.c'`; then
  2494.     echo shar: \"'src/sit.c'\" unpacked with wrong size!
  2495. fi
  2496. # end of 'src/sit.c'
  2497. fi
  2498. echo shar: End of archive 34 \(of 56\).
  2499. cp /dev/null ark34isdone
  2500. MISSING=""
  2501. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ; do
  2502.     if test ! -f ark${I}isdone ; then
  2503.     MISSING="${MISSING} ${I}"
  2504.     fi
  2505. done
  2506. if test "${MISSING}" = "" ; then
  2507.     echo You have unpacked all 56 archives.
  2508.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2509. else
  2510.     echo You still need to unpack the following archives:
  2511.     echo "        " ${MISSING}
  2512. fi
  2513. ##  End of shell archive.
  2514. exit 0
  2515.