home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume16 / nethck31 / part46 < prev    next >
Encoding:
Internet Message Format  |  1993-01-31  |  57.2 KB

  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: v16i054:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part46/108
  5. Message-ID: <4348@master.CNA.TEK.COM>
  6. Date: 30 Jan 93 01:14:07 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2284
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1603
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 54
  14. Archive-name: nethack31/Part46
  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 46 (of 108)."
  27. # Contents:  src/priest.c win/tty/wintty.c
  28. # Wrapped by billr@saab on Wed Jan 27 16:09:04 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'src/priest.c' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'src/priest.c'\"
  32. else
  33. echo shar: Extracting \"'src/priest.c'\" \(16798 characters\)
  34. sed "s/^X//" >'src/priest.c' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)priest.c    3.1    92/01/05
  36. X/* Copyright (c) Izchak Miller, Steve Linhart, 1989.           */
  37. X/* NetHack may be freely redistributed.  See license for details. */
  38. X
  39. X#include "hack.h"
  40. X#include "mfndpos.h"
  41. X#include "eshk.h"
  42. X#include "epri.h"
  43. X#include "emin.h"
  44. X
  45. X#ifdef OVLB
  46. X
  47. Xstatic boolean FDECL(histemple_at,(struct monst *,XCHAR_P,XCHAR_P));
  48. Xstatic boolean FDECL(has_shrine,(struct monst *));
  49. X
  50. X/*
  51. X * Move for priests and shopkeepers.  Called from shk_move() and pri_move().
  52. X * Valid returns are  1: moved  0: didn't  -1: let m_move do it  -2: died.
  53. X */
  54. Xint
  55. Xmove_special(mtmp,in_his_shop,appr,uondoor,avoid,omx,omy,gx,gy)
  56. Xregister struct monst *mtmp;
  57. Xboolean in_his_shop;
  58. Xschar appr;
  59. Xboolean uondoor,avoid;
  60. Xregister xchar omx,omy,gx,gy;
  61. X{
  62. X    register xchar nx,ny,nix,niy;
  63. X    register schar i;
  64. X    schar chcnt,cnt;
  65. X    coord poss[9];
  66. X    long info[9];
  67. X    long allowflags;
  68. X    struct obj *ib = (struct obj *)0;
  69. X
  70. X    if(omx == gx && omy == gy)
  71. X        return(0);
  72. X    if(mtmp->mconf) {
  73. X        avoid = FALSE;
  74. X        appr = 0;
  75. X    }
  76. X
  77. X    nix = omx;
  78. X    niy = omy;
  79. X    if (mtmp->isshk) allowflags = ALLOW_SSM;
  80. X    else allowflags = ALLOW_SSM | ALLOW_SANCT;
  81. X    if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL);
  82. X    if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK;
  83. X    if (tunnels(mtmp->data) &&
  84. X            (!needspick(mtmp->data) || m_carrying(mtmp, PICK_AXE)))
  85. X        allowflags |= ALLOW_DIG;
  86. X    if (!nohands(mtmp->data) && !verysmall(mtmp->data)) {
  87. X        allowflags |= OPENDOOR;
  88. X        if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR;
  89. X    }
  90. X    if (is_giant(mtmp->data)) allowflags |= BUSTDOOR;
  91. X    cnt = mfndpos(mtmp, poss, info, allowflags);
  92. X
  93. X    if(mtmp->isshk && avoid && uondoor) { /* perhaps we cannot avoid him */
  94. X        for(i=0; i<cnt; i++)
  95. X            if(!(info[i] & NOTONL)) goto pick_move;
  96. X        avoid = FALSE;
  97. X    }
  98. X
  99. X#define    GDIST(x,y)    (dist2(x,y,gx,gy))
  100. Xpick_move:
  101. X    chcnt = 0;
  102. X    for(i=0; i<cnt; i++) {
  103. X        nx = poss[i].x;
  104. X        ny = poss[i].y;
  105. X        if(levl[nx][ny].typ == ROOM ||
  106. X            (mtmp->ispriest &&
  107. X                levl[nx][ny].typ == ALTAR) ||
  108. X            (mtmp->isshk &&
  109. X                (!in_his_shop || ESHK(mtmp)->following))) {
  110. X            if(avoid && (info[i] & NOTONL))
  111. X            continue;
  112. X            if((!appr && !rn2(++chcnt)) ||
  113. X            (appr && GDIST(nx,ny) < GDIST(nix,niy))) {
  114. X                nix = nx;
  115. X                niy = ny;
  116. X            }
  117. X        }
  118. X    }
  119. X    if(mtmp->ispriest && avoid &&
  120. X            nix == omx && niy == omy && onlineu(omx,omy)) {
  121. X        /* might as well move closer as long it's going to stay
  122. X         * lined up */
  123. X        avoid = FALSE;
  124. X        goto pick_move;
  125. X    }
  126. X
  127. X    if(nix != omx || niy != omy) {
  128. X        remove_monster(omx, omy);
  129. X        place_monster(mtmp, nix, niy);
  130. X        newsym(nix,niy);
  131. X        if (mtmp->isshk && !in_his_shop && inhishop(mtmp))
  132. X            check_special_room(FALSE);
  133. X        if(ib) {
  134. X            if (cansee(mtmp->mx,mtmp->my))
  135. X                pline("%s picks up %s.", Monnam(mtmp),
  136. X                distant_name(ib,doname));
  137. X            freeobj(ib);
  138. X            mpickobj(mtmp, ib);
  139. X        }
  140. X        return(1);
  141. X    }
  142. X    return(0);
  143. X}
  144. X
  145. X#endif /* OVLB */
  146. X
  147. X#ifdef OVL0
  148. X
  149. Xchar
  150. Xtemple_occupied(array)
  151. Xregister char *array;
  152. X{
  153. X    register char *ptr;
  154. X
  155. X    for (ptr = array; *ptr; ptr++)
  156. X        if (rooms[*ptr - ROOMOFFSET].rtype == TEMPLE)
  157. X            return(*ptr);
  158. X    return('\0');
  159. X}
  160. X
  161. X#endif /* OVL0 */
  162. X#ifdef OVLB
  163. X
  164. Xstatic boolean
  165. Xhistemple_at(priest, x, y)
  166. Xregister struct monst *priest;
  167. Xregister xchar x, y;
  168. X{
  169. X    return((EPRI(priest)->shroom == *in_rooms(x, y, TEMPLE)) &&
  170. X           on_level(&(EPRI(priest)->shrlevel), &u.uz));
  171. X}
  172. X
  173. X/*
  174. X * pri_move: return 1: moved  0: didn't  -1: let m_move do it  -2: died
  175. X */
  176. Xint
  177. Xpri_move(priest)
  178. Xregister struct monst *priest;
  179. X{
  180. X    register xchar gx,gy,omx,omy;
  181. X    schar temple;
  182. X    boolean avoid = TRUE;
  183. X
  184. X    omx = priest->mx;
  185. X    omy = priest->my;
  186. X
  187. X    if(!histemple_at(priest, omx, omy)) return(-1);
  188. X
  189. X    temple = EPRI(priest)->shroom;
  190. X
  191. X    gx = EPRI(priest)->shrpos.x;
  192. X    gy = EPRI(priest)->shrpos.y;
  193. X
  194. X    gx += rn1(3,-1);    /* mill around the altar */
  195. X    gy += rn1(3,-1);
  196. X
  197. X    if(!priest->mpeaceful ||
  198. X       (Conflict && !resist(priest, RING_CLASS, 0, 0))) {
  199. X        if(monnear(priest, u.ux, u.uy)) {
  200. X            if(Displaced)
  201. X                Your("displaced image doesn't fool %s!",
  202. X                    mon_nam(priest));
  203. X            (void) mattacku(priest);
  204. X            return(0);
  205. X        } else if(index(u.urooms, temple)) {
  206. X            /* chase player if inside temple & can see him */
  207. X            if(priest->mcansee && m_canseeu(priest)) {
  208. X                gx = u.ux;
  209. X                gy = u.uy;
  210. X            }
  211. X            avoid = FALSE;
  212. X        }
  213. X    } else if(Invis) avoid = FALSE;
  214. X
  215. X    return(move_special(priest,FALSE,TRUE,FALSE,avoid,omx,omy,gx,gy));
  216. X}
  217. X
  218. X/* exclusively for mktemple() */
  219. Xvoid
  220. Xpriestini(lvl, sroom, sx, sy, sanctum)
  221. Xd_level    *lvl;
  222. Xstruct mkroom *sroom;
  223. Xint sx, sy;
  224. Xboolean sanctum;   /* is it the seat of the high priest? */
  225. X{
  226. X    register struct monst *priest;
  227. X    register struct obj *otmp;
  228. X    register int cnt;
  229. X
  230. X    if(MON_AT(sx+1, sy))
  231. X        rloc(m_at(sx+1, sy)); /* insurance */
  232. X
  233. X    if(priest = (sanctum ? makemon(&mons[PM_HIGH_PRIEST], sx+1, sy)
  234. X                 : makemon(&mons[PM_ALIGNED_PRIEST], sx+1, sy))) {
  235. X        EPRI(priest)->shroom = (sroom - rooms) + ROOMOFFSET;
  236. X        EPRI(priest)->shralign = Amask2align(levl[sx][sy].altarmask);
  237. X        EPRI(priest)->shrpos.x = sx;
  238. X        EPRI(priest)->shrpos.y = sy;
  239. X        assign_level(&(EPRI(priest)->shrlevel), lvl);
  240. X        priest->mtrapseen = ~0;    /* traps are known */
  241. X        priest->mpeaceful = 1;
  242. X        priest->ispriest = 1;
  243. X        priest->msleep = 0;
  244. X        set_malign(priest); /* mpeaceful may have changed */
  245. X
  246. X        /* now his/her goodies... */
  247. X        (void) mongets(priest, CHAIN_MAIL);
  248. X        (void) mongets(priest, SMALL_SHIELD);
  249. X#ifdef MUSE
  250. X        m_dowear(priest, TRUE);
  251. X#endif
  252. X        priest->mgold = (long)rn1(10,20);
  253. X        if(sanctum && EPRI(priest)->shralign == A_NONE &&
  254. X             on_level(&sanctum_level, &u.uz))
  255. X            (void) mongets(priest, AMULET_OF_YENDOR);
  256. X        /* Do NOT put the rest in m_initinv.    */
  257. X        /* Priests created elsewhere than in a  */
  258. X        /* temple should not carry these items, */
  259. X        /* except for the mace.            */
  260. X        cnt = rn1(2,3);
  261. X        while(cnt) {
  262. X            otmp = mkobj(SPBOOK_CLASS, FALSE);
  263. X            if(otmp) mpickobj(priest, otmp);
  264. X            cnt--;
  265. X        }
  266. X        if(p_coaligned(priest))
  267. X            (void) mongets(priest, rn2(2) ? CLOAK_OF_PROTECTION
  268. X                          : CLOAK_OF_MAGIC_RESISTANCE);
  269. X        else {
  270. X            if(!rn2(5))
  271. X            otmp = mksobj(CLOAK_OF_MAGIC_RESISTANCE, TRUE, FALSE);
  272. X            else otmp = mksobj(CLOAK_OF_PROTECTION, TRUE, FALSE);
  273. X            if(otmp) {
  274. X            if(!rn2(2)) curse(otmp);
  275. X            mpickobj(priest, otmp);
  276. X            }
  277. X        }
  278. X
  279. X        otmp = mksobj(MACE, FALSE, FALSE);
  280. X        if(otmp) {
  281. X            otmp->spe = rnd(3);
  282. X            if(!rn2(2)) curse(otmp);
  283. X            mpickobj(priest, otmp);
  284. X        }
  285. X    }
  286. X}
  287. X
  288. X/*
  289. X * Specially aligned monsters are named specially.
  290. X *    - aligned priests with ispriest and high priests have shrines
  291. X *        they retain ispriest and epri when polymorphed
  292. X *    - aligned priests without ispriest and Angels are roamers
  293. X *        they retain isminion and access epri as emin when polymorphed
  294. X *        (coaligned Angels are also created as minions, but they
  295. X *        use the same naming convention)
  296. X *    - minions do not have ispriest but have isminion and emin
  297. X */
  298. Xchar *
  299. Xpriestname(mon)
  300. Xregister struct monst *mon;
  301. X{
  302. X    static char NEARDATA pname[PL_NSIZ];
  303. X
  304. X    Strcpy(pname, "the ");
  305. X    if (mon->minvis) Strcat(pname, "invisible ");
  306. X    if (mon->ispriest || mon->data == &mons[PM_ALIGNED_PRIEST] ||
  307. X                    mon->data == &mons[PM_ANGEL]) {
  308. X        /* use epri */
  309. X        if (mon->mtame && mon->data == &mons[PM_ANGEL])
  310. X            Strcat(pname, "guardian ");
  311. X        if (mon->data != &mons[PM_ALIGNED_PRIEST] &&
  312. X                mon->data != &mons[PM_HIGH_PRIEST]) {
  313. X            Strcat(pname, mon->data->mname);
  314. X            Strcat(pname, " ");
  315. X        }
  316. X        if (mon->data != &mons[PM_ANGEL]) {
  317. X            if (!mon->ispriest && EPRI(mon)->renegade)
  318. X                Strcat(pname, "renegade ");
  319. X            if (mon->data == &mons[PM_HIGH_PRIEST])
  320. X                Strcat(pname, "high ");
  321. X            if (mon->female)
  322. X                Strcat(pname, "priestess ");
  323. X            else
  324. X                Strcat(pname, "priest ");
  325. X        }
  326. X        Strcat(pname, "of ");
  327. X        Strcat(pname, align_gname((int)EPRI(mon)->shralign));
  328. X        return(pname);
  329. X    }
  330. X    /* use emin instead of epri */
  331. X    Strcat(pname, mon->data->mname);
  332. X    Strcat(pname, " of ");
  333. X    Strcat(pname, align_gname(EMIN(mon)->min_align));
  334. X    return(pname);
  335. X}
  336. X
  337. Xboolean
  338. Xp_coaligned(priest)
  339. Xstruct monst *priest;
  340. X{
  341. X    return(u.ualign.type == ((int)EPRI(priest)->shralign));
  342. X}
  343. X
  344. Xstatic boolean
  345. Xhas_shrine(pri)
  346. Xstruct monst *pri;
  347. X{
  348. X    struct rm *lev;
  349. X
  350. X    if(!pri)
  351. X        return(FALSE);
  352. X    lev = &levl[EPRI(pri)->shrpos.x][EPRI(pri)->shrpos.y];
  353. X    if (!IS_ALTAR(lev->typ) || !(lev->altarmask & AM_SHRINE))
  354. X        return(FALSE);
  355. X    return(EPRI(pri)->shralign == Amask2align(lev->altarmask & ~AM_SHRINE));
  356. X}
  357. X
  358. Xstruct monst *
  359. Xfindpriest(roomno)
  360. Xchar roomno;
  361. X{
  362. X    register struct monst *mtmp;
  363. X    extern struct monst *fdmon; /* from mon.c */
  364. X
  365. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  366. X        if(mtmp->ispriest && (EPRI(mtmp)->shroom == roomno) &&
  367. X           histemple_at(mtmp,mtmp->mx,mtmp->my))
  368. X        return(mtmp);
  369. X    for(mtmp = fdmon; mtmp; mtmp = mtmp->nmon)
  370. X        if(mtmp->ispriest && (EPRI(mtmp)->shroom == roomno) &&
  371. X           histemple_at(mtmp,mtmp->mx,mtmp->my))
  372. X        return(mtmp);
  373. X    return (struct monst *)0;
  374. X}
  375. X
  376. X/* called from check_special_room() when the player enters the temple room */
  377. Xvoid
  378. Xintemple(roomno)
  379. Xregister int roomno;
  380. X{
  381. X    register struct monst *priest = findpriest((char)roomno);
  382. X    boolean tended = (priest != (struct monst *)0);
  383. X    boolean shrined = (tended && has_shrine(priest));
  384. X    boolean sanctum = (tended && priest->data == &mons[PM_HIGH_PRIEST] &&
  385. X                (Is_sanctum(&u.uz) || In_endgame(&u.uz)));
  386. X
  387. X    if(!temple_occupied(u.urooms0)) {
  388. X        if(tended) {
  389. X        pline("%s intones:",
  390. X              (!Blind ? Monnam(priest) : "A nearby voice"));
  391. X        if(sanctum && Is_sanctum(&u.uz)) {
  392. X            if(priest->mpeaceful) {
  393. X              verbalize("Infidel, you entered Moloch's Sanctum!");
  394. X              verbalize("Be gone!");
  395. X              priest->mpeaceful = 0;
  396. X              set_malign(priest);
  397. X            } else
  398. X              verbalize("You desecrate this place by your presence!");
  399. X        } else verbalize("Pilgrim, you enter a%s place!",
  400. X               !shrined ? " desecrated" :
  401. X               " sacred");
  402. X        if(!sanctum) {
  403. X            /* !tended -> !shrined */
  404. X            if(!shrined || !p_coaligned(priest) ||
  405. X                           u.ualign.record < -5)
  406. X            You("have a%s forbidding feeling...",
  407. X                (!shrined) ? "" : " strange");
  408. X            else You("experience a strange sense of peace.");
  409. X        }
  410. X        } else {
  411. X        switch(rn2(3)) {
  412. X          case 0: You("have an eerie feeling..."); break;
  413. X          case 1: You("feel like you are being watched."); break;
  414. X          default: pline("A shiver runs down your spine."); break;
  415. X        }
  416. X        if(!rn2(5)) {
  417. X            struct monst *mtmp;
  418. X
  419. X            if(!(mtmp = makemon(&mons[PM_GHOST],u.ux,u.uy))) return;
  420. X            pline("An enormous ghost appears next to you!");
  421. X            mtmp->mpeaceful = 0;
  422. X            set_malign(mtmp);
  423. X            if(flags.verbose)
  424. X            You("are frightened to death, and unable to move.");
  425. X            nomul(-3);
  426. X            nomovemsg = "You regain your composure.";
  427. X           }
  428. X       }
  429. X       }
  430. X}
  431. X
  432. Xvoid
  433. Xpriest_talk(priest)
  434. Xregister struct monst *priest;
  435. X{
  436. X    boolean coaligned = p_coaligned(priest);
  437. X    boolean strayed = (u.ualign.record < 0);
  438. X
  439. X    if(priest->mflee || (!priest->ispriest && coaligned && strayed)) {
  440. X        pline("%s doesn't want anything to do with you!",
  441. X                Monnam(priest));
  442. X        priest->mpeaceful = 0;
  443. X        return;
  444. X    }
  445. X
  446. X    /* priests don't chat unless peaceful and in their own temple */
  447. X    if(!histemple_at(priest,priest->mx,priest->my) ||
  448. X         !priest->mpeaceful || !priest->mcanmove || priest->msleep) {
  449. X        if(!priest->mcanmove || priest->msleep) {
  450. X        pline("%s breaks out of %s reverie!",
  451. X            humanoid(priest->data)
  452. X                ? (priest->female ? "her" : "his")
  453. X                : "its",
  454. X            Monnam(priest));
  455. X        priest->mfrozen = priest->msleep = 0;
  456. X        priest->mcanmove = 1;
  457. X        }
  458. X        priest->mpeaceful = 0;
  459. X        switch(rn2(3)) {
  460. X        case 0:
  461. X           verbalize("Thou wouldst have words, eh?  I'll give thee a word or two!");
  462. X           break;
  463. X        case 1:
  464. X           verbalize("Talk?  Here is what I have to say!");
  465. X           break;
  466. X        default:
  467. X           verbalize("Pilgrim, I have lost mine desire to talk.");
  468. X           break;
  469. X        }
  470. X        return;
  471. X    }
  472. X
  473. X    /* you desecrated the temple and now you want to chat? */
  474. X    if(priest->mpeaceful && *in_rooms(priest->mx, priest->my, TEMPLE) &&
  475. X          !has_shrine(priest)) {
  476. X        verbalize("Begone!  Thou desecratest this holy place with thy presence.");
  477. X        priest->mpeaceful = 0;
  478. X        return;
  479. X    }
  480. X
  481. X    if(!u.ugold) {
  482. X        if(coaligned && !strayed) {
  483. X        if (priest->mgold > 0L) {
  484. X            /* Note: two bits is actually 25 cents.  Hmm. */
  485. X            pline("%s gives you %s for an ale.", Monnam(priest),
  486. X            (priest->mgold == 1L) ? "one bit" : "two bits");
  487. X            if (priest->mgold > 1L)
  488. X            u.ugold = 2L;
  489. X            else
  490. X            u.ugold = 1L;
  491. X            priest->mgold -= u.ugold;
  492. X            flags.botl = 1;
  493. X        } else
  494. X            pline("%s preaches the virtues of poverty.", Monnam(priest));
  495. X        exercise(A_WIS, TRUE);
  496. X        } else
  497. X        pline("%s is not interested.", Monnam(priest));
  498. X        return;
  499. X    } else {
  500. X        long offer;
  501. X
  502. X        pline("%s asks you for a contribution for the temple.",
  503. X            Monnam(priest));
  504. X        if((offer = bribe(priest)) == 0) {
  505. X        verbalize("Thou shalt regret thine action!");
  506. X        if(coaligned) u.ualign.record--;
  507. X        } else if(offer < (u.ulevel * 200)) {
  508. X        if(u.ugold > (offer * 2L)) verbalize("Cheapskate.");
  509. X        else {
  510. X            verbalize("I thank thee for thy contribution.");
  511. X            /*  give player some token  */
  512. X            exercise(A_WIS, TRUE);
  513. X        }
  514. X        } else if(offer < (u.ulevel * 400)) {
  515. X        verbalize("Thou art indeed a pious individual.");
  516. X        if(u.ugold < (offer * 2L)) {
  517. X            if(coaligned && u.ualign.record < -5) u.ualign.record++;
  518. X            verbalize("I bestow upon thee a blessing.");
  519. X            Clairvoyant += rn1(500,500);
  520. X        }
  521. X        } else if(offer < (u.ulevel * 600)) {
  522. X        verbalize("Thy devotion has been rewarded.");
  523. X        if (!(Protection & INTRINSIC))  {
  524. X            Protection |= FROMOUTSIDE;
  525. X            if (!u.ublessed)  u.ublessed = rn1(3, 2);
  526. X        } else u.ublessed++;
  527. X        } else {
  528. X        verbalize("Thy selfless generosity is deeply appreciated.");
  529. X        if(u.ugold < (offer * 2L) && coaligned) {
  530. X            if(strayed && (moves - u.ucleansed) > 5000L) {
  531. X            u.ualign.record = 0; /* cleanse him */
  532. X            u.ucleansed = moves;
  533. X            } else {
  534. X            u.ualign.record += 2;
  535. X            }
  536. X        }
  537. X        }
  538. X    }
  539. X}
  540. X
  541. Xstruct monst *
  542. Xmk_roamer(ptr, alignment, x, y, peaceful)
  543. Xregister struct permonst *ptr;
  544. Xaligntyp alignment;
  545. Xxchar x, y;
  546. Xboolean peaceful;
  547. X{
  548. X    register struct monst *roamer;
  549. X    register boolean coaligned = (u.ualign.type == alignment);
  550. X
  551. X    if (ptr != &mons[PM_ALIGNED_PRIEST] && ptr != &mons[PM_ANGEL])
  552. X        return((struct monst *)0);
  553. X    
  554. X    if (MON_AT(x, y)) rloc(m_at(x, y));    /* insurance */
  555. X
  556. X    if (!(roamer = makemon(ptr, x, y)))
  557. X        return((struct monst *)0);
  558. X
  559. X    EPRI(roamer)->shralign = alignment;
  560. X    if (coaligned && !peaceful)
  561. X        EPRI(roamer)->renegade = TRUE;
  562. X    /* roamer->ispriest == FALSE naturally */
  563. X    roamer->isminion = TRUE;    /* borrowing this bit */
  564. X    roamer->mtrapseen = ~0;        /* traps are known */
  565. X    roamer->mpeaceful = peaceful;
  566. X    roamer->msleep = 0;
  567. X    set_malign(roamer); /* peaceful may have changed */
  568. X
  569. X    /* MORE TO COME */
  570. X    return(roamer);
  571. X}
  572. X
  573. Xvoid
  574. Xreset_hostility(roamer)
  575. Xregister struct monst *roamer;
  576. X{
  577. X        if(!(roamer->isminion && (roamer->data == &mons[PM_ALIGNED_PRIEST] ||
  578. X                  roamer->data == &mons[PM_ANGEL])))
  579. X            return;
  580. X
  581. X        if(EPRI(roamer)->shralign != u.ualign.type) {
  582. X        roamer->mpeaceful = roamer->mtame = 0;
  583. X        set_malign(roamer);
  584. X    }
  585. X    newsym(roamer->mx, roamer->my);
  586. X}
  587. X
  588. Xboolean
  589. Xin_your_sanctuary(x, y)
  590. Xxchar x, y;
  591. X{
  592. X    register char roomno;
  593. X    register struct monst *priest;
  594. X
  595. X    if ((u.ualign.record < -5) || !(roomno = temple_occupied(u.urooms)) ||
  596. X        (roomno != *in_rooms(x, y, TEMPLE)) ||
  597. X        !(priest = findpriest(roomno)))
  598. X        return(FALSE);
  599. X    return(has_shrine(priest) && p_coaligned(priest) && priest->mpeaceful);
  600. X}
  601. X
  602. Xvoid
  603. Xghod_hitsu(priest)     /* when attacking "priest" in his temple */
  604. Xstruct monst *priest;
  605. X{
  606. X    int x, y, ax, ay, roomno = (int)temple_occupied(u.urooms);
  607. X    struct mkroom *troom;
  608. X
  609. X    if (!roomno || !has_shrine(priest))
  610. X        return;
  611. X
  612. X    ax = x = EPRI(priest)->shrpos.x;
  613. X    ay = y = EPRI(priest)->shrpos.y;
  614. X    troom = &rooms[roomno - ROOMOFFSET];
  615. X
  616. X    if((u.ux == x && u.uy == y) || !linedup(u.ux, u.uy, x, y)) {
  617. X        if(IS_DOOR(levl[u.ux][u.uy].typ)) {
  618. X
  619. X        if(u.ux == troom->lx - 1) {
  620. X            x = troom->hx;
  621. X            y = u.uy;
  622. X        } else if(u.ux == troom->hx + 1) {
  623. X            x = troom->lx;
  624. X            y = u.uy;
  625. X        } else if(u.uy == troom->ly - 1) {
  626. X            x = u.ux;
  627. X            y = troom->hy;
  628. X        } else if(u.uy == troom->hy + 1) {
  629. X            x = u.ux;
  630. X            y = troom->ly;
  631. X        }
  632. X        } else {
  633. X        switch(rn2(4)) {
  634. X        case 0:  x = u.ux; y = troom->ly; break;
  635. X        case 1:  x = u.ux; y = troom->hy; break;
  636. X        case 2:  x = troom->lx; y = u.uy; break;
  637. X        default: x = troom->hx; y = u.uy; break;
  638. X        }
  639. X        }
  640. X        if(!linedup(u.ux, u.uy, x, y)) return;
  641. X    }
  642. X
  643. X    switch(rn2(3)) {
  644. X    case 0:
  645. X        pline("%s roars in anger:  \"Thou shalt suffer!\"",
  646. X            a_gname_at(ax, ay));
  647. X        break;
  648. X    case 1:
  649. X        pline("%s voice booms:  \"How darest thou harm my servant!\"",
  650. X            s_suffix(a_gname_at(ax, ay)));
  651. X        break;
  652. X    default:
  653. X        pline("%s roars:  \"Thou dost profane my shrine!\"",
  654. X            a_gname_at(ax, ay));
  655. X        break;
  656. X    }
  657. X
  658. X    buzz(-10-(AD_ELEC-1), 6, x, y, sgn(tbx), sgn(tby)); /* bolt of lightning */
  659. X    exercise(A_WIS, FALSE);
  660. X}
  661. X
  662. Xvoid
  663. Xangry_priest()
  664. X{
  665. X    register struct monst *priest;
  666. X
  667. X    if(priest = findpriest(temple_occupied(u.urooms)))
  668. X        wakeup(priest);
  669. X}
  670. X
  671. X#endif /* OVLB */
  672. X
  673. X/*priest.c*/
  674. END_OF_FILE
  675. if test 16798 -ne `wc -c <'src/priest.c'`; then
  676.     echo shar: \"'src/priest.c'\" unpacked with wrong size!
  677. fi
  678. # end of 'src/priest.c'
  679. fi
  680. if test -f 'win/tty/wintty.c' -a "${1}" != "-c" ; then 
  681.   echo shar: Will not clobber existing file \"'win/tty/wintty.c'\"
  682. else
  683. echo shar: Extracting \"'win/tty/wintty.c'\" \(36808 characters\)
  684. sed "s/^X//" >'win/tty/wintty.c' <<'END_OF_FILE'
  685. X/*    SCCS Id: @(#)wintty.c    3.1    92/10/21    */
  686. X/* Copyright (c) David Cohrs, 1991                  */
  687. X/* NetHack may be freely redistributed.  See license for details. */
  688. X
  689. X#include "hack.h"
  690. X#include "termcap.h"
  691. X#include "wintty.h"
  692. X#if (defined(BSD) || defined(ULTRIX) || defined(AIX_31) || defined(_BULL_SOURCE)) && defined(CLIPPING)
  693. X#include <signal.h>
  694. X#endif
  695. X
  696. X#define DEBUG
  697. X
  698. Xextern const char *roles[];    /* from u_init.c */
  699. X
  700. X/* Interface definition, for windows.c */
  701. Xstruct window_procs tty_procs = {
  702. X    "tty",
  703. X    tty_init_nhwindows,
  704. X    tty_player_selection,
  705. X    tty_askname,
  706. X    tty_get_nh_event,
  707. X    tty_exit_nhwindows,
  708. X    tty_suspend_nhwindows,
  709. X    tty_resume_nhwindows,
  710. X    tty_create_nhwindow,
  711. X    tty_clear_nhwindow,
  712. X    tty_display_nhwindow,
  713. X    tty_destroy_nhwindow,
  714. X    tty_curs,
  715. X    tty_putstr,
  716. X    tty_display_file,
  717. X    tty_start_menu,
  718. X    tty_add_menu,
  719. X    tty_end_menu,
  720. X    tty_select_menu,
  721. X    tty_update_inventory,
  722. X    tty_mark_synch,
  723. X    tty_wait_synch,
  724. X#ifdef CLIPPING
  725. X    tty_cliparound,
  726. X#endif
  727. X    tty_print_glyph,
  728. X    tty_raw_print,
  729. X    tty_raw_print_bold,
  730. X    tty_nhgetch,
  731. X    tty_nh_poskey,
  732. X    tty_nhbell,
  733. X    tty_doprev_message,
  734. X    tty_yn_function,
  735. X    tty_getlin,
  736. X#ifdef COM_COMPL
  737. X    tty_get_ext_cmd,
  738. X#endif /* COM_COMPL */
  739. X    tty_number_pad,
  740. X    tty_delay_output,
  741. X    /* other defs that really should go away (they're tty specific) */
  742. X    tty_start_screen,
  743. X    tty_end_screen,
  744. X};
  745. X
  746. Xstatic int maxwin = 0;            /* number of windows in use */
  747. Xwinid BASE_WINDOW;
  748. Xstruct WinDesc *wins[MAXWIN];
  749. Xstruct DisplayDesc *ttyDisplay;    /* the tty display descriptor */
  750. X
  751. Xextern void FDECL(cmov, (int,int)); /* from termcap.c */
  752. Xextern void FDECL(nocmov, (int,int)); /* from termcap.c */
  753. X#if defined(UNIX) || defined(VMS)
  754. Xstatic char obuf[BUFSIZ];    /* BUFSIZ is defined in stdio.h */
  755. X#endif
  756. X
  757. Xstatic char winpanicstr[] = "Bad window id %d";
  758. Xchar defmorestr[] = "--More--";
  759. X
  760. X#ifdef CLIPPING
  761. Xstatic boolean clipping = FALSE;    /* clipping on? */
  762. Xstatic int clipx = 0, clipy = 0, clipxmax = 0, clipymax = 0;
  763. X#endif
  764. X
  765. X#ifdef ASCIIGRAPH
  766. Xboolean GFlag = FALSE;
  767. X#endif
  768. X
  769. X#ifdef MICRO
  770. X#define getret() getreturn("to continue")
  771. X#else
  772. Xstatic void NDECL(getret);
  773. X#endif
  774. Xstatic void FDECL(dmore,(struct WinDesc *));
  775. Xstatic char * FDECL(s_atr2str, (int));
  776. Xstatic char * FDECL(e_atr2str, (int));
  777. Xstatic const char * FDECL(compress_str, (const char *));
  778. Xstatic void FDECL(tty_putsym, (winid, int, int, CHAR_P));
  779. X
  780. X#if defined(SIGWINCH) && defined(CLIPPING)
  781. Xstatic void
  782. Xwinch()
  783. X{
  784. X    int oldLI = LI, oldCO = CO, i;
  785. X    register struct WinDesc *cw;
  786. X
  787. X    getwindowsz();
  788. X    if((oldLI != LI || oldCO != CO) && ttyDisplay) {
  789. X    ttyDisplay->rows = LI;
  790. X    ttyDisplay->cols = CO;
  791. X
  792. X    cw = wins[BASE_WINDOW];
  793. X    cw->rows = ttyDisplay->rows;
  794. X    cw->cols = ttyDisplay->cols;
  795. X
  796. X    if(flags.window_inited) {
  797. X        cw = wins[WIN_MESSAGE];
  798. X        cw->curx = cw->cury = 0;
  799. X
  800. X        tty_destroy_nhwindow(WIN_STATUS);
  801. X        WIN_STATUS = tty_create_nhwindow(NHW_STATUS);
  802. X
  803. X        if(u.ux) {
  804. X#ifdef CLIPPING
  805. X        if(CO < COLNO || LI < ROWNO+3) {
  806. X            setclipped();
  807. X            tty_cliparound(u.ux, u.uy);
  808. X        } else {
  809. X            clipping = FALSE;
  810. X            clipx = clipy = 0;
  811. X        }
  812. X#endif
  813. X        i = ttyDisplay->toplin;
  814. X        ttyDisplay->toplin = 0;
  815. X        docrt();
  816. X        bot();
  817. X        ttyDisplay->toplin = i;
  818. X        flush_screen(1);
  819. X        if(i) {
  820. X            addtopl(toplines);
  821. X        } else
  822. X            for(i=WIN_INVEN; i < MAXWIN; i++)
  823. X            if(wins[i] && wins[i]->active) {
  824. X                /* cop-out */
  825. X                addtopl("Press Return to continue: ");
  826. X                break;
  827. X            }
  828. X        (void) fflush(stdout);
  829. X        if(i < 2) flush_screen(1);
  830. X        }
  831. X    }
  832. X    }
  833. X}
  834. X#endif
  835. X
  836. Xvoid
  837. Xtty_init_nhwindows()
  838. X{
  839. X    int wid, hgt;
  840. X
  841. X    /*
  842. X     *  Remember tty modes, to be restored on exit.
  843. X     *
  844. X     *  gettty() must be called before tty_startup()
  845. X     *    due to ordering of LI/CO settings
  846. X     *  tty_startup() must be called before initoptions()
  847. X     *    due to ordering of graphics settings
  848. X     */
  849. X#if defined(UNIX) || defined(VMS)
  850. X    setbuf(stdout,obuf);
  851. X#endif
  852. X    gettty();
  853. X
  854. X    /* to port dependant tty setup */
  855. X    tty_startup(&wid, &hgt);
  856. X    setftty();            /* calls start_screen */
  857. X
  858. X    /* set up tty descriptor */
  859. X    ttyDisplay = (struct DisplayDesc*) alloc(sizeof(struct DisplayDesc));
  860. X    ttyDisplay->toplin = 0;
  861. X    ttyDisplay->rows = hgt;
  862. X    ttyDisplay->cols = wid;
  863. X    ttyDisplay->curx = ttyDisplay->cury = 0;
  864. X    ttyDisplay->inmore = ttyDisplay->inread = 0;
  865. X#ifdef TEXTCOLOR
  866. X    ttyDisplay->color = NO_COLOR;
  867. X#endif
  868. X    ttyDisplay->attrs = 0;
  869. X
  870. X    /* set up the default windows */
  871. X    BASE_WINDOW = tty_create_nhwindow(NHW_BASE);
  872. X    wins[BASE_WINDOW]->active = 1;
  873. X
  874. X    ttyDisplay->lastwin = WIN_ERR;
  875. X
  876. X#if defined(SIGWINCH) && defined(CLIPPING)
  877. X    (void) signal(SIGWINCH, winch);
  878. X#endif
  879. X
  880. X    tty_clear_nhwindow(BASE_WINDOW);
  881. X
  882. X    tty_putstr(BASE_WINDOW, 0, "");
  883. X    tty_putstr(BASE_WINDOW, 0,
  884. X     "NetHack, Copyright 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993");
  885. X    tty_putstr(BASE_WINDOW, 0,
  886. X     "         By Stichting Mathematisch Centrum and M. Stephenson.");
  887. X    tty_putstr(BASE_WINDOW, 0, "         See license for details.");
  888. X    tty_putstr(BASE_WINDOW, 0, "");
  889. X    tty_display_nhwindow(BASE_WINDOW, FALSE);
  890. X}
  891. X
  892. Xvoid
  893. Xtty_player_selection()
  894. X{
  895. X    char pbuf[QBUFSZ];
  896. X    char pick, pc;
  897. X    int i, linecount;
  898. X
  899. X    linecount = wins[BASE_WINDOW]->cury+1;
  900. X    if ((pc = highc(pl_character[0])) != 0) {
  901. X    if(index(pl_classes, pc) != (char*) 0)
  902. X        goto got_suffix;
  903. X    tty_putstr(BASE_WINDOW, 0, "");
  904. X    Sprintf(pbuf, "Unknown role: %c", pc);
  905. X    tty_putstr(BASE_WINDOW, 0, pbuf);
  906. X    linecount += 2;
  907. X    pl_character[0] = pc = 0;
  908. X    }
  909. X
  910. X#define PICK_PROMPT "Shall I pick a character for you? [Y, N, or Q(quit)] "
  911. X    tty_putstr(BASE_WINDOW, 0, "");
  912. X    tty_putstr(BASE_WINDOW, 0, PICK_PROMPT);
  913. X
  914. X    while(!index("yYnNqQ", (pick = readchar())) && !index(quitchars, pick))
  915. X    tty_nhbell();
  916. X
  917. X    pick = index(quitchars, pick) ? 'Y' : highc(pick);
  918. X
  919. X    tty_putsym(BASE_WINDOW, (int)strlen(PICK_PROMPT)+1, linecount, pick); /* echo */
  920. X
  921. X    if (pick == 'Q') {
  922. X    clearlocks();
  923. X    tty_exit_nhwindows(NULL);
  924. X    terminate(0);
  925. X    }
  926. X
  927. X    if (pick == 'Y') {
  928. X    tty_putstr(BASE_WINDOW, 0, "");
  929. X    goto beginner;
  930. X    }
  931. X
  932. X    tty_curs(BASE_WINDOW, 1, linecount+2);
  933. X    tty_putstr(BASE_WINDOW, 0, "What kind of character are you:");
  934. X    tty_putstr(BASE_WINDOW, 0, "");
  935. X    Sprintf(pbuf, "      %s,", An(roles[0]));
  936. X    for(i = 1; roles[i]; i++) {
  937. X    Sprintf(eos(pbuf), " %s", an(roles[i]));
  938. X    if((((i + 1) % 4) == 0) && roles[i+1]) {
  939. X        Strcat(pbuf, ",");
  940. X        tty_putstr(BASE_WINDOW, 0, pbuf);
  941. X        linecount++;
  942. X        Strcpy(pbuf, "        ");
  943. X    }
  944. X    else if(roles[i+1] && roles[i+2])    Strcat(pbuf, ",");
  945. X    if(roles[i+1] && !roles[i+2])    Strcat(pbuf, " or");
  946. X    }
  947. X    Strcat(pbuf ,"?");
  948. X    tty_putstr(BASE_WINDOW, 0, pbuf);
  949. X    Strcpy(pbuf, "         [");
  950. X    for(i = 0; roles[i]; i++)
  951. X    Sprintf(eos(pbuf), "%c,", pl_classes[i]);
  952. X    Strcat(pbuf, " or Q] ");
  953. X    tty_putstr(BASE_WINDOW, 0, pbuf);
  954. X    linecount += 5;
  955. X
  956. X    while ((pc = readchar()) != 0) {
  957. X    if ((pc = highc(pc)) == 'Q') {
  958. X        clearlocks();
  959. X        tty_exit_nhwindows(NULL);
  960. X        terminate(0);
  961. X    }
  962. X    if(index(pl_classes, pc) != (char *) 0) {
  963. X        tty_putsym(BASE_WINDOW, (int)strlen(pbuf)+1, linecount, pc); /* echo */
  964. X        tty_putstr(BASE_WINDOW, 0, "");
  965. X        tty_display_nhwindow(BASE_WINDOW, TRUE);
  966. X        break;
  967. X    }
  968. X    if(pc == '\n') {
  969. X        pc = 0;
  970. X        break;
  971. X    }
  972. X    tty_nhbell();
  973. X    }
  974. X
  975. Xbeginner:
  976. X    if(!pc) {
  977. X    i = rn2((int)strlen(pl_classes));
  978. X    pc = pl_classes[i];
  979. X    tty_putstr(BASE_WINDOW, 0, "");
  980. X    Sprintf(pbuf, "This game you will be %s.", an(roles[i]));
  981. X    tty_putstr(BASE_WINDOW, 0, pbuf);
  982. X    tty_putstr(BASE_WINDOW, 0, "");
  983. X    tty_display_nhwindow(BASE_WINDOW, TRUE);
  984. X    getret();
  985. X    }
  986. Xgot_suffix:
  987. X
  988. X    tty_clear_nhwindow(BASE_WINDOW);
  989. X    pl_character[0] = pc;
  990. X    return;
  991. X}
  992. X
  993. X/*
  994. X * plname is filled either by an option (-u Player  or  -uPlayer) or
  995. X * explicitly (by being the wizard) or by askname.
  996. X * It may still contain a suffix denoting pl_character.
  997. X * Always called after init_nhwindows() and before display_gamewindows().
  998. X */
  999. Xvoid
  1000. Xtty_askname()
  1001. X{
  1002. X    register int c, ct;
  1003. X
  1004. X    tty_putstr(BASE_WINDOW, 0, "");
  1005. X    tty_putstr(BASE_WINDOW, 0, "Who are you? ");
  1006. X    tty_curs(BASE_WINDOW, 14, wins[BASE_WINDOW]->cury-1);
  1007. X    ct = 0;
  1008. X    while((c = tty_nhgetch()) != '\n') {
  1009. X        if(c == EOF) error("End of input\n");
  1010. X#ifndef VMS
  1011. X        /* some people get confused when their erase char is not ^H */
  1012. X        if(c == '\b') {
  1013. X            if(ct) {
  1014. X                ct--;
  1015. X# ifdef MICRO
  1016. X                msmsg("\b \b");
  1017. X# else
  1018. X                (void) putchar('\b');
  1019. X                (void) putchar(' ');
  1020. X                (void) putchar('\b');
  1021. X# endif
  1022. X            }
  1023. X            continue;
  1024. X        }
  1025. X#endif
  1026. X#if defined(UNIX) || defined(VMS)
  1027. X        if(c != '-')
  1028. X        if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
  1029. X#endif
  1030. X        if(ct < sizeof(plname)-1) {
  1031. X#if defined(MICRO)
  1032. X            msmsg("%c", c);
  1033. X#else
  1034. X            (void) putchar(c);
  1035. X#endif
  1036. X            plname[ct++] = c;
  1037. X        }
  1038. X    }
  1039. X    plname[ct] = 0;
  1040. X    tty_curs(BASE_WINDOW, 1, wins[BASE_WINDOW]->cury+1);
  1041. X    if(ct == 0) tty_askname();
  1042. X}
  1043. X
  1044. Xvoid
  1045. Xtty_get_nh_event()
  1046. X{
  1047. X#ifdef LINT
  1048. X    /*
  1049. X     * We should do absolutely nothing here - but lint
  1050. X     * complains about that, so we call donull().
  1051. X     */
  1052. X     (void) donull();
  1053. X#endif
  1054. X}
  1055. X
  1056. X#ifndef MICRO
  1057. Xstatic void
  1058. Xgetret()
  1059. X{
  1060. X    xputs("\n");
  1061. X    if(flags.standout)
  1062. X        standoutbeg();
  1063. X    xputs("Hit ");
  1064. X    xputs(flags.cbreak ? "space" : "return");
  1065. X    xputs(" to continue: ");
  1066. X    if(flags.standout)
  1067. X        standoutend();
  1068. X    xwaitforspace("");
  1069. X}
  1070. X#endif
  1071. X
  1072. Xvoid
  1073. Xtty_suspend_nhwindows(str)
  1074. X    const char *str;
  1075. X{
  1076. X    settty(str);        /* calls end_screen, perhaps raw_print */
  1077. X    if (!str) tty_raw_print("");    /* calls fflush(stdout) */
  1078. X}
  1079. X
  1080. Xvoid
  1081. Xtty_resume_nhwindows()
  1082. X{
  1083. X    gettty();
  1084. X    setftty();            /* calls start_screen */
  1085. X    docrt();
  1086. X}
  1087. X
  1088. Xvoid
  1089. Xtty_exit_nhwindows(str)
  1090. X    const char *str;
  1091. X{
  1092. X    winid i;
  1093. X
  1094. X    tty_suspend_nhwindows(str);
  1095. X    /* Just forget any windows existed, since we're about to exit anyway.
  1096. X     * Disable windows to avoid calls to window routines.
  1097. X     */
  1098. X    for(i=0; i<MAXWIN; i++)
  1099. X    if(i != BASE_WINDOW)
  1100. X        wins[i] = 0;
  1101. X    flags.window_inited = 0;
  1102. X}
  1103. X
  1104. Xwinid
  1105. Xtty_create_nhwindow(type)
  1106. X    int type;
  1107. X{
  1108. X    struct WinDesc* newwin;
  1109. X    int i;
  1110. X    int newid;
  1111. X
  1112. X    if(maxwin == MAXWIN)
  1113. X    return WIN_ERR;
  1114. X
  1115. X    newwin = (struct WinDesc*) alloc(sizeof(struct WinDesc));
  1116. X    newwin->type = type;
  1117. X    newwin->flags = 0;
  1118. X    newwin->active = FALSE;
  1119. X    newwin->curx = newwin->cury = 0;
  1120. X    newwin->resp = newwin->canresp = newwin->morestr = 0;
  1121. X    switch(type) {
  1122. X    case NHW_BASE:
  1123. X    /* base window, used for absolute movement on the screen */
  1124. X    newwin->offx = newwin->offy = 0;
  1125. X    newwin->rows = ttyDisplay->rows;
  1126. X    newwin->cols = ttyDisplay->cols;
  1127. X    newwin->maxrow = newwin->maxcol = 0;
  1128. X    break;
  1129. X    case NHW_MESSAGE:
  1130. X    /* message window, 1 line long, very wide, top of screen */
  1131. X    newwin->offx = newwin->offy = 0;
  1132. X    /* sanity check */
  1133. X    if(flags.msg_history < 20) flags.msg_history = 20;
  1134. X    else if(flags.msg_history > 60) flags.msg_history = 60;
  1135. X    newwin->maxrow = newwin->rows = flags.msg_history;
  1136. X    newwin->maxcol = newwin->cols = 0;
  1137. X    break;
  1138. X    case NHW_STATUS:
  1139. X    /* status window, 2 lines long, full width, bottom of screen */
  1140. X    newwin->offx = 0;
  1141. X    newwin->offy = min((int)ttyDisplay->rows-2, ROWNO+1);
  1142. X    newwin->rows = newwin->maxrow = 2;
  1143. X    newwin->cols = newwin->maxcol = min(ttyDisplay->cols, COLNO);
  1144. X    break;
  1145. X    case NHW_MAP:
  1146. X    /* map window, ROWNO lines long, full width, below message window */
  1147. X    newwin->offx = 0;
  1148. X    newwin->offy = 1;
  1149. X    newwin->rows = ROWNO;
  1150. X    newwin->cols = COLNO;
  1151. X    newwin->maxrow = 0;    /* no buffering done -- let gbuf do it */
  1152. X    newwin->maxcol = 0;
  1153. X    break;
  1154. X    case NHW_MENU:
  1155. X    newwin->resp = (char*) alloc(256);
  1156. X    newwin->resp[0] = 0;
  1157. X    case NHW_TEXT:
  1158. X    /* inventory/menu window, variable length, full width, top of screen */
  1159. X    /* help window, the same, different semantics for display, etc */
  1160. X    newwin->offx = newwin->offy = 0;
  1161. X    newwin->rows = 0;
  1162. X    newwin->cols = ttyDisplay->cols;
  1163. X    newwin->maxrow = newwin->maxcol = 0;
  1164. X    break;
  1165. X   default:
  1166. X    panic("Tried to create window type %d\n", (int) type);
  1167. X    return WIN_ERR;
  1168. X    }
  1169. X
  1170. X    for(newid = 0; newid<MAXWIN; newid++) {
  1171. X    if(wins[newid] == 0) {
  1172. X        wins[newid] = newwin;
  1173. X        break;
  1174. X    }
  1175. X    }
  1176. X    if(newid == MAXWIN) {
  1177. X    panic("No window slots!");
  1178. X    return WIN_ERR;
  1179. X    }
  1180. X
  1181. X    if(newwin->maxrow) {
  1182. X    newwin->data = (char**) alloc(sizeof(char**) * newwin->maxrow);
  1183. X    if(newwin->maxcol) {
  1184. X        for(i=0; i< newwin->maxrow; i++)
  1185. X        newwin->data[i] = (char*)alloc(sizeof(char*) * newwin->maxcol);
  1186. X    } else {
  1187. X        for(i=0; i< newwin->maxrow; i++)
  1188. X        newwin->data[i] = 0;
  1189. X    }
  1190. X    if(newwin->type == NHW_MESSAGE)
  1191. X        newwin->maxrow = 0;
  1192. X    } else
  1193. X    newwin->data = 0;
  1194. X
  1195. X    return newid;
  1196. X}
  1197. X
  1198. Xvoid
  1199. Xtty_clear_nhwindow(window)
  1200. X    winid window;
  1201. X{
  1202. X    register struct WinDesc *cw = 0;
  1203. X    int i;
  1204. X
  1205. X    if(window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0)
  1206. X    panic(winpanicstr,  window);
  1207. X    ttyDisplay->lastwin = window;
  1208. X
  1209. X    switch(cw->type) {
  1210. X    case NHW_MESSAGE:
  1211. X    if(ttyDisplay->toplin) {
  1212. X        home();
  1213. X        cl_end();
  1214. X        if(cw->cury)
  1215. X        docorner(1, cw->cury+1);
  1216. X        ttyDisplay->toplin = 0;
  1217. X    }
  1218. X    break;
  1219. X    case NHW_STATUS:
  1220. X    tty_curs(window, 1, 0);
  1221. X    cl_end();
  1222. X    tty_curs(window, 1, 1);
  1223. X    cl_end();
  1224. X    break;
  1225. X    case NHW_MAP:
  1226. X    /* cheap -- clear the whole thing and tell nethack to redraw botl */
  1227. X    flags.botlx = 1;
  1228. X    /* fall into ... */
  1229. X    case NHW_BASE:
  1230. X    clear_screen();
  1231. X    break;
  1232. X    case NHW_MENU:
  1233. X    case NHW_TEXT:
  1234. X    if(cw->active) {
  1235. X        if(cw->offx == 0)
  1236. X        if(cw->offy) {
  1237. X            tty_curs(window, 1, 0);
  1238. X            cl_eos();
  1239. X        } else
  1240. X            clear_screen();
  1241. X        else
  1242. X        docorner((int)cw->offx, cw->maxrow+1);
  1243. X    }
  1244. X    for(i=0; i<cw->maxrow; i++)
  1245. X        if(cw->data[i]) {
  1246. X        free((genericptr_t)cw->data[i]);
  1247. X        cw->data[i] = 0;
  1248. X        }
  1249. X    cw->maxrow = cw->maxcol = 0;
  1250. X    if(cw->resp)
  1251. X        cw->resp[0] = 0;
  1252. X    if(cw->canresp) {
  1253. X        free((genericptr_t)cw->canresp);
  1254. X        cw->canresp = 0;
  1255. X    }
  1256. X    if(cw->morestr) {
  1257. X        free((genericptr_t)cw->morestr);
  1258. X        cw->morestr = 0;
  1259. X    }
  1260. X    break;
  1261. X    }
  1262. X    cw->curx = cw->cury = 0;
  1263. X}
  1264. X
  1265. Xstatic void
  1266. Xdmore(cw)
  1267. X    register struct WinDesc *cw;
  1268. X{
  1269. X    const char *s = (cw->resp && *cw->resp) ? cw->resp : quitchars;
  1270. X    const char *prompt = cw->morestr ? cw->morestr : defmorestr;
  1271. X    if(cw->type == NHW_TEXT)
  1272. X    tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1, (int)ttyDisplay->cury);
  1273. X    else
  1274. X    tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+2, (int)ttyDisplay->cury);
  1275. X    if(flags.standout)
  1276. X    standoutbeg();
  1277. X    xputs(prompt);
  1278. X    ttyDisplay->curx += strlen(prompt);
  1279. X    if(flags.standout)
  1280. X    standoutend();
  1281. X
  1282. X    xwaitforspace(s);
  1283. X}
  1284. X
  1285. X/*ARGSUSED*/
  1286. Xvoid
  1287. Xtty_display_nhwindow(window, blocking)
  1288. X    winid window;
  1289. X    boolean blocking;    /* with ttys, all windows are blocking */
  1290. X{
  1291. X    register struct WinDesc *cw = 0;
  1292. X    int i, n, attr;
  1293. X    register char *cp;
  1294. X
  1295. X    if(window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0)
  1296. X    panic(winpanicstr,  window);
  1297. X    if(cw->flags & WIN_CANCELLED)
  1298. X    return;
  1299. X    ttyDisplay->lastwin = window;
  1300. X    ttyDisplay->rawprint = 0;
  1301. X
  1302. X    switch(cw->type) {
  1303. X    case NHW_MESSAGE:
  1304. X    if(ttyDisplay->toplin == 1) {
  1305. X        more();
  1306. X        ttyDisplay->toplin = 1; /* more resets this */
  1307. X        tty_clear_nhwindow(window);
  1308. X    } else
  1309. X        ttyDisplay->toplin = 0;
  1310. X    cw->curx = cw->cury = 0;
  1311. X    if(!cw->active)
  1312. X        flags.window_inited = TRUE;
  1313. X    break;
  1314. X    case NHW_MAP:
  1315. X    end_glyphout();
  1316. X    if(blocking) {
  1317. X        if(!ttyDisplay->toplin) ttyDisplay->toplin = 1;
  1318. X        tty_display_nhwindow(WIN_MESSAGE, TRUE);
  1319. X        return;
  1320. X    }
  1321. X    case NHW_BASE:
  1322. X    (void) fflush(stdout);
  1323. X    break;
  1324. X    case NHW_TEXT:
  1325. X    cw->maxcol = ttyDisplay->cols; /* force full-screen mode */
  1326. X    case NHW_MENU:
  1327. X    cw->active = 1;
  1328. X    /* avoid converting to uchar before calculations are finished */
  1329. X    cw->offx = (uchar) (int)
  1330. X        max((int) 10, (int) (ttyDisplay->cols - cw->maxcol - 1));
  1331. X    if(cw->type == NHW_MENU)
  1332. X        cw->offy = 0;
  1333. X    if(ttyDisplay->toplin == 1)
  1334. X        tty_display_nhwindow(WIN_MESSAGE, TRUE);
  1335. X    if(cw->offx == 10 || cw->maxrow >= (int) ttyDisplay->rows) {
  1336. X        cw->offx = 0;
  1337. X        if(cw->offy) {
  1338. X        tty_curs(window, 1, 0);
  1339. X        cl_eos();
  1340. X        } else
  1341. X        clear_screen();
  1342. X        ttyDisplay->toplin = 0;
  1343. X    } else
  1344. X        tty_clear_nhwindow(WIN_MESSAGE);
  1345. X
  1346. X    for(n=0, i=0; i<cw->maxrow; i++) {
  1347. X        if(!cw->offx && (n+cw->offy == ttyDisplay->rows-1)) {
  1348. X        tty_curs(window, 1, n);
  1349. X        cl_end();
  1350. X        dmore(cw);
  1351. X        if(morc) {
  1352. X            if(!cw->canresp && (morc == '\033'))
  1353. X            cw->flags |= WIN_CANCELLED;
  1354. X            else if(cw->canresp && index(&cw->canresp[1], morc)) {
  1355. X            morc = cw->canresp[0];
  1356. X            cw->flags |= WIN_CANCELLED;
  1357. X            }
  1358. X            break;
  1359. X        }
  1360. X        if(cw->offy) {
  1361. X            tty_curs(window, 1, 0);
  1362. X            cl_eos();
  1363. X        } else
  1364. X            clear_screen();
  1365. X        n = 0;
  1366. X        }
  1367. X        tty_curs(window, 1, n++);
  1368. X        if(cw->offx) cl_end();
  1369. X        if(cw->data[i]) {
  1370. X        attr = cw->data[i][0]-1;
  1371. X        if(cw->type == NHW_MENU) {
  1372. X            (void) putchar(' '); ++ttyDisplay->curx;
  1373. X        }
  1374. X        if(attr)
  1375. X            xputs(s_atr2str(attr));
  1376. X        for(cp = &cw->data[i][1];
  1377. X            *cp && (int)++ttyDisplay->curx < (int) ttyDisplay->cols; )
  1378. X            (void) putchar(*cp++);
  1379. X        if(attr)
  1380. X            xputs(e_atr2str(attr));
  1381. X        }
  1382. X    }
  1383. X    if(i == cw->maxrow) {
  1384. X        if(cw->type == NHW_TEXT)
  1385. X        tty_curs(BASE_WINDOW, (int)cw->offx+1, (int)ttyDisplay->rows-1);
  1386. X        else
  1387. X        tty_curs(BASE_WINDOW, (int)cw->offx+1, n);
  1388. X        cl_end();
  1389. X        dmore(cw);
  1390. X        if(morc) {
  1391. X        if(!cw->canresp && (morc == '\033'))
  1392. X            cw->flags |= WIN_CANCELLED;
  1393. X        else if(cw->canresp && index(&cw->canresp[1], morc)) {
  1394. X            morc = cw->canresp[0];
  1395. X            cw->flags |= WIN_CANCELLED;
  1396. X        }
  1397. X        }
  1398. X    }
  1399. X    break;
  1400. X    }
  1401. X    cw->active = 1;
  1402. X}
  1403. X
  1404. Xvoid
  1405. Xtty_dismiss_nhwindow(window)
  1406. X    winid window;
  1407. X{
  1408. X    register struct WinDesc *cw = 0;
  1409. X
  1410. X    if(window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0)
  1411. X    panic(winpanicstr,  window);
  1412. X
  1413. X    switch(cw->type) {
  1414. X    case NHW_STATUS:
  1415. X    case NHW_BASE:
  1416. X    case NHW_MESSAGE:
  1417. X    case NHW_MAP:
  1418. X    /*
  1419. X     * these should only get dismissed when the game is going away
  1420. X     * or suspending
  1421. X     */
  1422. X    tty_curs(BASE_WINDOW, 1, (int)ttyDisplay->rows-1);
  1423. X    cw->active = 0;
  1424. X    break;
  1425. X    case NHW_MENU:
  1426. X    case NHW_TEXT:
  1427. X    if(cw->active) {
  1428. X        if(cw->offx == 0) {
  1429. X        if(cw->offy) {
  1430. X            tty_curs(window, 1, 0);
  1431. X            cl_eos();
  1432. X        } else
  1433. X            docrt();
  1434. X        } else {
  1435. X        docorner((int)cw->offx, cw->maxrow+1);
  1436. X        }
  1437. X        cw->active = 0;
  1438. X    }
  1439. X    break;
  1440. X    }
  1441. X    cw->flags = 0;
  1442. X}
  1443. X
  1444. Xvoid
  1445. Xtty_destroy_nhwindow(window)
  1446. X    winid window;
  1447. X{
  1448. X    register struct WinDesc *cw = 0;
  1449. X    int i;
  1450. X
  1451. X    if(window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0)
  1452. X    panic(winpanicstr,  window);
  1453. X
  1454. X    if(cw->active)
  1455. X    tty_dismiss_nhwindow(window);
  1456. X    if(cw->type == NHW_MESSAGE)
  1457. X    flags.window_inited = 0;
  1458. X    if(cw->type == NHW_MAP)
  1459. X    clear_screen();
  1460. X
  1461. X    if(cw->data) {
  1462. X    for(i=0; i<cw->rows; i++)
  1463. X        if(cw->data[i])
  1464. X        free((genericptr_t)cw->data[i]);
  1465. X    free((genericptr_t)cw->data);
  1466. X    }
  1467. X    if(cw->resp)
  1468. X    free((genericptr_t)cw->resp);
  1469. X    if(cw->canresp)
  1470. X    free((genericptr_t)cw->canresp);
  1471. X    free((genericptr_t)cw);
  1472. X    wins[window] = 0;
  1473. X}
  1474. X
  1475. Xvoid
  1476. Xtty_curs(window, x, y)
  1477. Xwinid window;
  1478. Xregister int x, y;    /* not xchar: perhaps xchar is unsigned and
  1479. X               curx-x would be unsigned as well */
  1480. X{
  1481. X    struct WinDesc *cw = 0;
  1482. X    int cx = ttyDisplay->curx;
  1483. X    int cy = ttyDisplay->cury;
  1484. X
  1485. X    if(window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0)
  1486. X    panic(winpanicstr,  window);
  1487. X    ttyDisplay->lastwin = window;
  1488. X
  1489. X    cw->curx = --x;    /* column 0 is never used */
  1490. X    cw->cury = y;
  1491. X#ifdef DEBUG
  1492. X    if(x<0 || y<0 || y >= cw->rows || x >= cw->cols) {
  1493. X    const char *s = "[unknown type]";
  1494. X    switch(cw->type) {
  1495. X    case NHW_MESSAGE: s = "[topl window]"; break;
  1496. X    case NHW_STATUS: s = "[status window]"; break;
  1497. X    case NHW_MAP: s = "[map window]"; break;
  1498. X    case NHW_MENU: s = "[corner window]"; break;
  1499. X    case NHW_TEXT: s = "[text window]"; break;
  1500. X    case NHW_BASE: s = "[base window]"; break;
  1501. X    }
  1502. X    impossible("bad curs positioning win %d %s (%d,%d)", window, s, x, y);
  1503. X    return;
  1504. X    }
  1505. X#endif
  1506. X    x += cw->offx;
  1507. X    y += cw->offy;
  1508. X
  1509. X#ifdef CLIPPING
  1510. X    if(clipping && window == WIN_MAP) {
  1511. X    x -= clipx;
  1512. X    y -= clipy;
  1513. X    }
  1514. X#endif
  1515. X
  1516. X    if (y == cy && x == cx)
  1517. X    return;
  1518. X
  1519. X    if(cw->type == NHW_MAP)
  1520. X    end_glyphout();
  1521. X
  1522. X    if(!ND && (cx != x || x <= 3)) { /* Extremely primitive */
  1523. X    cmov(x, y); /* bunker!wtm */
  1524. X    return;
  1525. X    }
  1526. X    if((cy -= y) < 0) cy = -cy;
  1527. X    if((cx -= x) < 0) cx = -cx;
  1528. X    if(cy <= 3 && cx <= 3)
  1529. X    nocmov(x, y);
  1530. X    else if((x <= 3 && cy <= 3) || (!CM && x < cx)) {
  1531. X    (void) putchar('\r');
  1532. X    ttyDisplay->curx = 0;
  1533. X    nocmov(x, y);
  1534. X    } else if(!CM) {
  1535. X    nocmov(x, y);
  1536. X    } else
  1537. X    cmov(x, y);
  1538. X
  1539. X    ttyDisplay->curx = x;
  1540. X    ttyDisplay->cury = y;
  1541. X}
  1542. X
  1543. Xstatic void
  1544. Xtty_putsym(window, x, y, ch)
  1545. X    winid window;
  1546. X    int x, y;
  1547. X    char ch;
  1548. X{
  1549. X    register struct WinDesc *cw = 0;
  1550. X
  1551. X    if(window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0)
  1552. X    panic(winpanicstr,  window);
  1553. X
  1554. X    switch(cw->type) {
  1555. X    case NHW_STATUS:
  1556. X    case NHW_MAP:
  1557. X    case NHW_BASE:
  1558. X    tty_curs(window, x, y);
  1559. X    (void) putchar(ch);
  1560. X    ttyDisplay->curx++;
  1561. X    cw->curx++;
  1562. X    break;
  1563. X    case NHW_MESSAGE:
  1564. X    case NHW_MENU:
  1565. X    case NHW_TEXT:
  1566. X    impossible("Can't putsym to window type %d", cw->type);
  1567. X    break;
  1568. X    }
  1569. X}
  1570. X
  1571. Xstatic char nulstr[] = "";
  1572. X
  1573. Xstatic char *
  1574. Xs_atr2str(n)
  1575. X    int n;
  1576. X{
  1577. X    switch(n) {
  1578. X    case ATR_ULINE:
  1579. X    if(US) return US;
  1580. X    case ATR_BOLD:
  1581. X    case ATR_BLINK:
  1582. X    case ATR_INVERSE:
  1583. X    return HI;
  1584. X    }
  1585. X    return nulstr;
  1586. X}
  1587. X
  1588. Xstatic char *
  1589. Xe_atr2str(n)
  1590. X    int n;
  1591. X{
  1592. X    switch(n) {
  1593. X    case ATR_ULINE:
  1594. X    if(UE) return UE;
  1595. X    case ATR_BOLD:
  1596. X    case ATR_BLINK:
  1597. X    case ATR_INVERSE:
  1598. X    return HE;
  1599. X    }
  1600. X    return nulstr;
  1601. X}
  1602. X
  1603. Xstatic const char*
  1604. Xcompress_str(str)
  1605. Xconst char *str;
  1606. X{
  1607. X        static char cbuf[BUFSZ];
  1608. X    /* compress in case line too long */
  1609. X    if((int)strlen(str) >= CO) {
  1610. X        register const char *bp0 = str;
  1611. X        register char *bp1 = cbuf;
  1612. X
  1613. X        do {
  1614. X#ifdef CLIPPING
  1615. X            if(*bp0 != ' ' || bp0[1] != ' ')
  1616. X#else
  1617. X            if(*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ')
  1618. X#endif
  1619. X                *bp1++ = *bp0;
  1620. X        } while(*bp0++);
  1621. X    } else
  1622. X        return str;
  1623. X    return cbuf;
  1624. X}
  1625. X
  1626. Xvoid
  1627. Xtty_putstr(window, attr, str)
  1628. X    winid window;
  1629. X    int attr;
  1630. X    const char *str;
  1631. X{
  1632. X    register struct WinDesc *cw = 0;
  1633. X    register char *ob;
  1634. X    register const char *nb;
  1635. X    register int i, j, n0;
  1636. X
  1637. X    /* Assume there's a real problem if the window is missing --
  1638. X     * probably a panic message
  1639. X     */
  1640. X    if(window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0) {
  1641. X    tty_raw_print(str);
  1642. X    return;
  1643. X    }
  1644. X
  1645. X    if(str == (const char*)NULL || (cw->flags & WIN_CANCELLED))
  1646. X    return;
  1647. X    if(cw->type != NHW_MESSAGE)
  1648. X    str = compress_str(str);
  1649. X
  1650. X    ttyDisplay->lastwin = window;
  1651. X
  1652. X    switch(cw->type) {
  1653. X    case NHW_MESSAGE:
  1654. X    /* really do this later */
  1655. X    update_topl(str);
  1656. X    break;
  1657. X
  1658. X    case NHW_STATUS:
  1659. X    ob = &cw->data[cw->cury][j = cw->curx];
  1660. X    if(flags.botlx) *ob = 0;
  1661. X    if(!cw->cury && (int)strlen(str) >= CO) {
  1662. X        /* the characters before "St:" are unnecessary */
  1663. X        nb = index(str, ':');
  1664. X        if(nb && nb > str+2)
  1665. X        str = nb - 2;
  1666. X    }
  1667. X    nb = str;
  1668. X    for(i = cw->curx+1, n0 = cw->cols; i < n0; i++, nb++) {
  1669. X        if(!*nb) {
  1670. X        if(*ob || flags.botlx) {
  1671. X            /* last char printed may be in middle of line */
  1672. X            tty_curs(WIN_STATUS, i, cw->cury);
  1673. X            cl_end();
  1674. X        }
  1675. X        break;
  1676. X        }
  1677. X        if(*ob != *nb)
  1678. X        tty_putsym(WIN_STATUS, i, cw->cury, *nb);
  1679. X        if(*ob) ob++;
  1680. X    }
  1681. X
  1682. X    (void) strncpy(&cw->data[cw->cury][j], str, cw->cols - j - 1);
  1683. X    cw->data[cw->cury][cw->cols-1] = '\0'; /* null terminate */
  1684. X    cw->cury = (cw->cury+1) % 2;
  1685. X    cw->curx = 0;
  1686. X    break;
  1687. X    case NHW_MAP:
  1688. X    case NHW_BASE:
  1689. X    tty_curs(window, cw->curx+1, cw->cury);
  1690. X    if(attr)
  1691. X        xputs(s_atr2str(attr));
  1692. X    while(*str && (int) ttyDisplay->curx < (int) ttyDisplay->cols-1) {
  1693. X        (void) putchar(*str++);
  1694. X        ttyDisplay->curx++;
  1695. X    }
  1696. X    cw->curx = 0;
  1697. X    cw->cury++;
  1698. X    if(attr)
  1699. X        xputs(e_atr2str(attr));
  1700. X    break;
  1701. X    case NHW_MENU:
  1702. X    case NHW_TEXT:
  1703. X    if(!(cw->resp && cw->resp[0]) && cw->cury == ttyDisplay->rows-1) {
  1704. X        /* not a menu, so save memory and output 1 page at a time */
  1705. X        cw->maxcol = ttyDisplay->cols; /* force full-screen mode */
  1706. X        tty_display_nhwindow(window, TRUE);
  1707. X        cw->maxrow = cw->cury = 0;
  1708. X    }
  1709. X    /* always grows one at a time, but alloc 12 at a time */
  1710. X    if(cw->cury >= cw->rows) {
  1711. X        char **tmp;
  1712. X
  1713. X        cw->rows += 12;
  1714. X        tmp = (char**) alloc(sizeof(char*) * cw->rows);
  1715. X        for(i=0; i<cw->maxrow; i++)
  1716. X        tmp[i] = cw->data[i];
  1717. X        if(cw->data)
  1718. X        free((genericptr_t)cw->data);
  1719. X        cw->data = tmp;
  1720. X
  1721. X        for(i=cw->maxrow; i<cw->rows; i++)
  1722. X        cw->data[i] = 0;
  1723. X    }
  1724. X    if(cw->data[cw->cury])
  1725. X        free((genericptr_t)cw->data[cw->cury]);
  1726. X    n0 = strlen(str)+1;
  1727. X    cw->data[cw->cury] = (char*) alloc(n0+1);
  1728. X    cw->data[cw->cury][0] = attr+1;    /* avoid nuls, for convenience */
  1729. X    Strcpy(&cw->data[cw->cury][1], str);
  1730. X
  1731. X    if(n0 > cw->maxcol)
  1732. X        cw->maxcol = n0;
  1733. X    if(++cw->cury > cw->maxrow)
  1734. X        cw->maxrow = cw->cury;
  1735. X    if(n0 > CO) {
  1736. X        /* attempt to break the line */
  1737. X        for(i = CO-1; i && str[i] != ' ';)
  1738. X        i--;
  1739. X        if(i) {
  1740. X        cw->data[cw->cury-1][++i] = '\0';
  1741. X        tty_putstr(window, attr, &str[i]);
  1742. X        }
  1743. X        
  1744. X    }
  1745. X    break;
  1746. X    }
  1747. X}
  1748. X
  1749. Xvoid
  1750. Xtty_display_file(fname, complain)
  1751. Xconst char *fname;
  1752. Xboolean complain;
  1753. X{
  1754. X#ifdef DEF_PAGER            /* this implies that UNIX is defined */
  1755. X    {
  1756. X    /* use external pager; this may give security problems */
  1757. X    register int fd = open(fname, 0);
  1758. X
  1759. X    if(fd < 0) {
  1760. X        if(complain) pline("Cannot open %s.", fname);
  1761. X        else docrt();
  1762. X        return;
  1763. X    }
  1764. X    if(child(1)) {
  1765. X        /* Now that child() does a setuid(getuid()) and a chdir(),
  1766. X           we may not be able to open file fname anymore, so make
  1767. X           it stdin. */
  1768. X        (void) close(0);
  1769. X        if(dup(fd)) {
  1770. X        if(complain) raw_printf("Cannot open %s as stdin.", fname);
  1771. X        } else {
  1772. X        (void) execlp(catmore, "page", NULL);
  1773. X        if(complain) raw_printf("Cannot exec %s.", catmore);
  1774. X        }
  1775. X        if(complain) sleep(10); /* want to wait_synch() but stdin is gone */
  1776. X        terminate(1);
  1777. X    }
  1778. X    (void) close(fd);
  1779. X    }
  1780. X#else
  1781. X    {
  1782. X    FILE *f;
  1783. X    char buf[BUFSZ];
  1784. X    char *cr;
  1785. X
  1786. X    tty_clear_nhwindow(WIN_MESSAGE);
  1787. X    f = fopen_datafile(fname, "r");
  1788. X    if (!f) {
  1789. X        if(complain) {
  1790. X        home();  tty_mark_synch();  tty_raw_print("");
  1791. X        perror(fname);  tty_wait_synch();
  1792. X        pline("Cannot open \"%s\".", fname);
  1793. X        } else if(u.ux) docrt();
  1794. X    } else {
  1795. X        winid datawin = tty_create_nhwindow(NHW_TEXT);
  1796. X        if(complain && CD) {
  1797. X        /* attempt to scroll text below map window if there's room */
  1798. X        wins[datawin]->offy = wins[WIN_STATUS]->offy+3;
  1799. X        if((int) wins[datawin]->offy + 12 > (int) ttyDisplay->rows)
  1800. X            wins[datawin]->offy = 0;
  1801. X        }
  1802. X        while (fgets(buf, BUFSZ, f)) {
  1803. X        if ((cr = index(buf, '\n')) != 0) *cr = 0;
  1804. X        if (index(buf, '\t') != 0) (void) tabexpand(buf);
  1805. X        tty_putstr(datawin, 0, buf);
  1806. X        if(wins[datawin]->flags & WIN_CANCELLED)
  1807. X            break;
  1808. X        }
  1809. X        tty_display_nhwindow(datawin, FALSE);
  1810. X        tty_destroy_nhwindow(datawin);
  1811. X        (void) fclose(f);
  1812. X    }
  1813. X    }
  1814. X#endif /* DEF_PAGER */
  1815. X}
  1816. X
  1817. Xvoid
  1818. Xtty_start_menu(window)
  1819. X    winid window;
  1820. X{
  1821. X    tty_clear_nhwindow(window);
  1822. X    return;
  1823. X}
  1824. X
  1825. X/*
  1826. X * Add a menu item.  window must be an NHW_MENU type,
  1827. X * ch is the value to return if this entry is selected.
  1828. X * attr are attributes to set for this line (like tty_putstr())
  1829. X * str is the value to display on this menu line
  1830. X */
  1831. Xvoid
  1832. Xtty_add_menu(window, ch, attr, str)
  1833. X    winid window;
  1834. X    char ch;
  1835. X    int attr;
  1836. X    const char *str;
  1837. X{
  1838. X    register struct WinDesc *cw = 0;
  1839. X    char tmpbuf[2];
  1840. X
  1841. X    if(str == (const char*)NULL)
  1842. X    return;
  1843. X
  1844. X    if(window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0
  1845. X       || cw->type != NHW_MENU)
  1846. X    panic(winpanicstr,  window);
  1847. X
  1848. X    tty_putstr(window, attr, str);
  1849. X    if(ch != '\0') {
  1850. X    tmpbuf[0] = ch;
  1851. X    tmpbuf[1] = 0;
  1852. X    Strcat(cw->resp, tmpbuf);
  1853. X    }
  1854. X}
  1855. X
  1856. X/*
  1857. X * End a menu in this window, window must a type NHW_MENU.
  1858. X * ch is the value to return if the menu is canceled,
  1859. X * str is a list of cancel characters (values that may be input)
  1860. X * morestr is a prompt to display, rather than the default.
  1861. X * str and morestr might be ignored by some ports.
  1862. X */
  1863. Xvoid
  1864. Xtty_end_menu(window, ch, str, morestr)
  1865. X    winid window;
  1866. X    char ch;
  1867. X    const char *str;
  1868. X    const char *morestr;
  1869. X{
  1870. X    register struct WinDesc *cw = 0;
  1871. X
  1872. X    if(window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0 ||
  1873. X       cw->type != NHW_MENU || cw->canresp)
  1874. X    panic(winpanicstr,  window);
  1875. X
  1876. X    if(str) {
  1877. X    cw->canresp = (char*) alloc(strlen(str)+2);
  1878. X    cw->canresp[0] = ch;            /* this could be NUL? */
  1879. X    Strcpy(&cw->canresp[1], str);
  1880. X    Strcat(cw->resp, str);
  1881. X    }
  1882. X    if(morestr) {
  1883. X    unsigned int len = strlen(morestr) + 1;
  1884. X    cw->morestr = (char*) alloc(len);
  1885. X    Strcpy(cw->morestr, morestr);
  1886. X    if(++len > cw->maxcol)    /* add one to avoid using the rtmost column */
  1887. X        cw->maxcol = len;
  1888. X    }
  1889. X}
  1890. X
  1891. Xchar
  1892. Xtty_select_menu(window)
  1893. X    winid window;
  1894. X{
  1895. X    register struct WinDesc *cw = 0;
  1896. X
  1897. X    morc = 0;
  1898. X    if(window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0
  1899. X       || cw->type != NHW_MENU)
  1900. X    panic(winpanicstr,  window);
  1901. X    tty_display_nhwindow(window, TRUE);
  1902. X    tty_dismiss_nhwindow(window);
  1903. X
  1904. X    return morc;
  1905. X}
  1906. X
  1907. Xvoid
  1908. Xtty_update_inventory()
  1909. X{
  1910. X}
  1911. X
  1912. Xvoid
  1913. Xtty_mark_synch()
  1914. X{
  1915. X    (void) fflush(stdout);
  1916. X}
  1917. X
  1918. Xvoid
  1919. Xtty_wait_synch()
  1920. X{
  1921. X    /* we just need to make sure all windows are synch'd */
  1922. X    if(!ttyDisplay || ttyDisplay->rawprint) {
  1923. X    getret();
  1924. X    if(ttyDisplay) ttyDisplay->rawprint = 0;
  1925. X    } else {
  1926. X    tty_display_nhwindow(WIN_MAP, FALSE);
  1927. X    if(ttyDisplay->inmore) {
  1928. X        addtopl("--More--");
  1929. X        (void) fflush(stdout);
  1930. X    } else if(ttyDisplay->inread) {
  1931. X        ttyDisplay->toplin = 3;
  1932. X        /* do this twice; 1st time gets the Quit? message again */
  1933. X        (void) tty_doprev_message();
  1934. X        (void) tty_doprev_message();
  1935. X        (void) fflush(stdout);
  1936. X    }
  1937. X    }
  1938. X}
  1939. X
  1940. Xvoid
  1941. Xdocorner(xmin, ymax)
  1942. X    register int xmin, ymax;
  1943. X{
  1944. X    register int y;
  1945. X    register struct WinDesc *cw = wins[WIN_MAP];
  1946. X
  1947. X    if (u.uswallow) {    /* Can be done more efficiently */
  1948. X    swallowed(1);
  1949. X    return;
  1950. X    }
  1951. X
  1952. X#if defined(SIGWINCH) && defined(CLIPPING)
  1953. X    if(ymax > LI) ymax = LI;        /* can happen if window gets smaller */
  1954. X#endif
  1955. X    for (y = 0; y < ymax; y++) {
  1956. X    tty_curs(BASE_WINDOW, xmin,y);    /* move cursor */
  1957. X    cl_end();            /* clear to end of line */
  1958. X#ifdef CLIPPING
  1959. X    if (y<(int) cw->offy || y+clipy > ROWNO) 
  1960. X        continue; /* only refresh board */
  1961. X    row_refresh(xmin+clipx-(int)cw->offx,COLNO-1,y+clipy-(int)cw->offy);
  1962. X#else
  1963. X    if (y<cw->offy || y > ROWNO) continue; /* only refresh board  */
  1964. X    row_refresh(xmin-(int)cw->offx,COLNO-1,y-(int)cw->offy);
  1965. X#endif
  1966. X    }
  1967. X
  1968. X    end_glyphout();
  1969. X    if (ymax >= (int) wins[WIN_STATUS]->offy) { 
  1970. X                    /* we have wrecked the bottom line */
  1971. X    flags.botlx = 1;
  1972. X    bot();
  1973. X    }
  1974. X}
  1975. X
  1976. Xvoid
  1977. Xend_glyphout()
  1978. X{
  1979. X#ifdef ASCIIGRAPH
  1980. X    if (GFlag) {
  1981. X    GFlag = FALSE;
  1982. X    graph_off();
  1983. X    }
  1984. X#endif
  1985. X#ifdef TEXTCOLOR
  1986. X    if(ttyDisplay->color != NO_COLOR) {
  1987. X    xputs(HE);
  1988. X    ttyDisplay->color = NO_COLOR;
  1989. X    }
  1990. X#endif
  1991. X}
  1992. X
  1993. X#ifdef ASCIIGRAPH
  1994. Xvoid
  1995. Xg_putch(ch)
  1996. X    uchar ch;
  1997. X{
  1998. X    if (flags.IBMgraphics)
  1999. X    /* IBM-compatible displays don't need other stuff */
  2000. X    (void) putchar((char) ch);
  2001. X    else if (ch & 0x80) {
  2002. X    if (!GFlag) {
  2003. X        graph_on();
  2004. X        GFlag = TRUE;
  2005. X    }
  2006. X    (void) putchar((char) (ch ^ 0x80)); /* Strip 8th bit */
  2007. X    } else {
  2008. X    if (GFlag) {
  2009. X        graph_off();
  2010. X        GFlag = FALSE;
  2011. X    }
  2012. X    (void) putchar((char) ch);
  2013. X    }
  2014. X}
  2015. X
  2016. X#else
  2017. X
  2018. Xvoid
  2019. Xg_putch(ch)
  2020. X    uchar ch;
  2021. X{
  2022. X    (void) putchar((char)(ch));
  2023. X};
  2024. X
  2025. X#endif    /* ASCIIGRAPH */
  2026. X
  2027. X#ifdef CLIPPING
  2028. Xvoid
  2029. Xsetclipped()
  2030. X{
  2031. X    clipping = TRUE;
  2032. X    clipx = clipy = 0;
  2033. X    clipxmax = CO;
  2034. X    clipymax = LI - 3;
  2035. X}
  2036. X
  2037. Xvoid
  2038. Xtty_cliparound(x, y)
  2039. Xint x, y;
  2040. X{
  2041. X    int oldx = clipx, oldy = clipy;
  2042. X
  2043. X    if (!clipping) return;
  2044. X    if (x < clipx + 5) {
  2045. X        clipx = max(0, x - 20);
  2046. X        clipxmax = clipx + CO;
  2047. X    }
  2048. X    else if (x > clipxmax - 5) {
  2049. X        clipxmax = min(COLNO, clipxmax + 20);
  2050. X        clipx = clipxmax - CO;
  2051. X    }
  2052. X    if (y < clipy + 2) {
  2053. X        clipy = max(0, y - (clipymax - clipy) / 2);
  2054. X        clipymax = clipy + (LI - 3);
  2055. X    }
  2056. X    else if (y > clipymax - 2) {
  2057. X        clipymax = min(ROWNO, clipymax + (clipymax - clipy) / 2);
  2058. X        clipy = clipymax - (LI - 3);
  2059. X    }
  2060. X    if (clipx != oldx || clipy != oldy) {
  2061. X        (void) doredraw();
  2062. X    }
  2063. X}
  2064. X#endif /* CLIPPING */
  2065. X
  2066. X
  2067. X/*
  2068. X *  tty_print_glyph
  2069. X *
  2070. X *  Print the glyph to the output device.  Don't flush the output device.
  2071. X *
  2072. X *  Since this is only called from show_glyph(), it is assumed that the
  2073. X *  position and glyph are always correct (checked there)!
  2074. X */
  2075. Xvoid
  2076. Xtty_print_glyph(window, x, y, glyph)
  2077. X    winid window;
  2078. X    xchar x, y;
  2079. X    int glyph;
  2080. X{
  2081. X    uchar   ch;
  2082. X    register int offset;
  2083. X#ifdef TEXTCOLOR
  2084. X    int        color;
  2085. X
  2086. X#define zap_color(n)  color = flags.use_color ? zapcolors[n] : NO_COLOR
  2087. X#define cmap_color(n) color = flags.use_color ? defsyms[n].color : NO_COLOR
  2088. X#define trap_color(n) color = flags.use_color ? \
  2089. X                (((n) == WEB) ? defsyms[S_web ].color  : \
  2090. X                            defsyms[S_trap].color) : \
  2091. X                        NO_COLOR
  2092. X#define obj_color(n)  color = flags.use_color ? objects[n].oc_color : NO_COLOR
  2093. X#define mon_color(n)  color = flags.use_color ? mons[n].mcolor : NO_COLOR
  2094. X#define pet_color(n)  color = flags.use_color ? mons[n].mcolor :          \
  2095. X                /* If no color, try to hilite pets; black  */ \
  2096. X                /* should be HI                   */ \
  2097. X                    ((flags.hilite_pet && hilites[BLACK]) ?          \
  2098. X                            BLACK : NO_COLOR)
  2099. X# else /* no text color */
  2100. X
  2101. X#define zap_color(n)
  2102. X#define cmap_color(n)
  2103. X#define trap_color(n)
  2104. X#define obj_color(n)
  2105. X#define mon_color(n)
  2106. X#define pet_color(c)
  2107. X#endif
  2108. X
  2109. X#ifdef CLIPPING
  2110. X    if(clipping) {
  2111. X    if(x <= clipx || y < clipy || x >= clipxmax || y >= clipymax)
  2112. X        return;
  2113. X    }
  2114. X#endif
  2115. X    /*
  2116. X     *  Map the glyph back to a character.
  2117. X     *
  2118. X     *  Warning:  For speed, this makes an assumption on the order of
  2119. X     *          offsets.  The order is set in display.h.
  2120. X     */
  2121. X    if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) {        /* swallow */
  2122. X    /* see swallow_to_glyph() in display.c */
  2123. X    ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)];
  2124. X    mon_color(offset >> 3);
  2125. X    } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) {    /* zap beam */
  2126. X    /* see zapdir_to_glyph() in display.c */
  2127. X    ch = showsyms[S_vbeam + (offset & 0x3)];
  2128. X    zap_color((offset >> 2));
  2129. X    } else if ((offset = (glyph - GLYPH_CMAP_OFF)) >= 0) {    /* cmap */
  2130. X    ch = showsyms[offset];
  2131. X    cmap_color(offset);
  2132. X    } else if ((offset = (glyph - GLYPH_TRAP_OFF)) >= 0) {    /* trap */
  2133. X    ch = (offset == WEB) ? showsyms[S_web] : showsyms[S_trap];
  2134. X    trap_color(offset);
  2135. X    } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) {    /* object */
  2136. X    ch = oc_syms[objects[offset].oc_class];
  2137. X    obj_color(offset);
  2138. X    } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) {    /* a corpse */
  2139. X    ch = oc_syms[objects[CORPSE].oc_class];
  2140. X    mon_color(offset);
  2141. X    } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) {    /* a pet */
  2142. X    ch = monsyms[mons[offset].mlet];
  2143. X    pet_color(offset);
  2144. X    } else {                            /* a monster */
  2145. X    ch = monsyms[mons[glyph].mlet];
  2146. X    mon_color(glyph);
  2147. X    }
  2148. X
  2149. X    /* Move the cursor. */
  2150. X    tty_curs(window, x,y);
  2151. X
  2152. X    if (ul_hack && ch == '_') {        /* non-destructive underscore */
  2153. X    (void) putchar((char) ' ');
  2154. X    backsp();
  2155. X    }
  2156. X
  2157. X#ifdef TEXTCOLOR
  2158. X    /* Turn off color if no color defined, or rogue level. */
  2159. X#  ifdef REINCARNATION
  2160. X    if (hilites[color] == NULL || Is_rogue_level(&u.uz))
  2161. X#  else
  2162. X    if (hilites[color] == NULL)
  2163. X#  endif
  2164. X    color = NO_COLOR;
  2165. X
  2166. X    if (color != ttyDisplay->color) {
  2167. X    if(ttyDisplay->color != NO_COLOR)
  2168. X        xputs(HE);
  2169. X    ttyDisplay->color = color;
  2170. X    if(color != NO_COLOR)
  2171. X        xputs(hilites[color]);
  2172. X    }
  2173. X#endif
  2174. X    g_putch(ch);        /* print the character */
  2175. X    wins[window]->curx++;    /* one character over */
  2176. X    ttyDisplay->curx++;        /* the real cursor moved too */
  2177. X}
  2178. X
  2179. Xvoid
  2180. Xtty_raw_print(str)
  2181. X    const char *str;
  2182. X{
  2183. X    if(ttyDisplay) ttyDisplay->rawprint++;
  2184. X#ifdef MICRO
  2185. X    msmsg("%s\n", str);
  2186. X#else
  2187. X    puts(str); (void) fflush(stdout);
  2188. X#endif
  2189. X}
  2190. X
  2191. Xvoid
  2192. Xtty_raw_print_bold(str)
  2193. X    const char *str;
  2194. X{
  2195. X    if(ttyDisplay) ttyDisplay->rawprint++;
  2196. X    xputs(HI);
  2197. X#ifdef MICRO
  2198. X    msmsg("%s", str);
  2199. X#else
  2200. X    (void) fputs(str, stdout);
  2201. X#endif
  2202. X    xputs(HE);
  2203. X#ifdef MICRO
  2204. X    msmsg("\n");
  2205. X#else
  2206. X    puts("");
  2207. X    (void) fflush(stdout);
  2208. X#endif
  2209. X}
  2210. X
  2211. Xint
  2212. Xtty_nhgetch()
  2213. X{
  2214. X    int i;
  2215. X#ifdef UNIX
  2216. X    /* kludge alert: Some Unix variants return funny values if getc()
  2217. X     * is called, interrupted, and then called again.  There
  2218. X     * is non-reentrant code in the internal _filbuf() routine, called by
  2219. X     * getc().
  2220. X     */
  2221. X    static volatile int nesting = 0;
  2222. X    char nestbuf;
  2223. X#endif
  2224. X
  2225. X    (void) fflush(stdout);
  2226. X    /* Note: if raw_print() and wait_synch() get called to report terminal
  2227. X     * initialization problems, then wins[] and ttyDisplay might not be
  2228. X     * available yet.  Such problems will probably be fatal before we get
  2229. X     * here, but validate those pointers just in case...
  2230. X     */
  2231. X    if (WIN_MESSAGE != WIN_ERR && wins[WIN_MESSAGE])
  2232. X        wins[WIN_MESSAGE]->flags &= ~WIN_STOP;
  2233. X#ifdef UNIX
  2234. X    i = ((++nesting == 1) ? tgetch() :
  2235. X     (read(fileno(stdin), (genericptr_t)&nestbuf,1) == 1 ? (int)nestbuf :
  2236. X                                EOF));
  2237. X    --nesting;
  2238. X#else
  2239. X    i = tgetch();
  2240. X#endif
  2241. X    if (!i) i = '\033'; /* map NUL to ESC since nethack doesn't expect NUL */
  2242. X    if (ttyDisplay && ttyDisplay->toplin == 1)
  2243. X    ttyDisplay->toplin = 2;
  2244. X    return i;
  2245. X}
  2246. X
  2247. X/*
  2248. X * return a key, or 0, in which case a mouse button was pressed
  2249. X * mouse events should be returned as character postitions in the map window.
  2250. X * Since normal tty's don't have mice, just return a key.
  2251. X */
  2252. X/*ARGSUSED*/
  2253. Xint
  2254. Xtty_nh_poskey(x, y, mod)
  2255. X    int *x, *y, *mod;
  2256. X{
  2257. X    return tty_nhgetch();
  2258. X}
  2259. X
  2260. Xvoid
  2261. Xwin_tty_init()
  2262. X{
  2263. X    return;
  2264. X}
  2265. X
  2266. X/*wintty.c*/
  2267. END_OF_FILE
  2268. if test 36808 -ne `wc -c <'win/tty/wintty.c'`; then
  2269.     echo shar: \"'win/tty/wintty.c'\" unpacked with wrong size!
  2270. fi
  2271. # end of 'win/tty/wintty.c'
  2272. fi
  2273. echo shar: End of archive 46 \(of 108\).
  2274. cp /dev/null ark46isdone
  2275. MISSING=""
  2276. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2277. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2278. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2279. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2280. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2281. 101 102 103 104 105 106 107 108 ; do
  2282.     if test ! -f ark${I}isdone ; then
  2283.     MISSING="${MISSING} ${I}"
  2284.     fi
  2285. done
  2286. if test "${MISSING}" = "" ; then
  2287.     echo You have unpacked all 108 archives.
  2288.     echo "Now execute 'rebuild.sh'"
  2289.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2290. else
  2291.     echo You still need to unpack the following archives:
  2292.     echo "        " ${MISSING}
  2293. fi
  2294. ##  End of shell archive.
  2295. exit 0
  2296.