hack.read.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. /* $NetBSD: hack.read.c,v 1.8 2003/04/02 18:36:39 jsm Exp $ */
  2. /*
  3. * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
  4. * Amsterdam
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are
  9. * met:
  10. *
  11. * - Redistributions of source code must retain the above copyright notice,
  12. * this list of conditions and the following disclaimer.
  13. *
  14. * - Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. *
  18. * - Neither the name of the Stichting Centrum voor Wiskunde en
  19. * Informatica, nor the names of its contributors may be used to endorse or
  20. * promote products derived from this software without specific prior
  21. * written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  24. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  25. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  26. * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  27. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  28. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  29. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  30. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  31. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  32. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  33. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. /*
  36. * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
  37. * All rights reserved.
  38. *
  39. * Redistribution and use in source and binary forms, with or without
  40. * modification, are permitted provided that the following conditions
  41. * are met:
  42. * 1. Redistributions of source code must retain the above copyright
  43. * notice, this list of conditions and the following disclaimer.
  44. * 2. Redistributions in binary form must reproduce the above copyright
  45. * notice, this list of conditions and the following disclaimer in the
  46. * documentation and/or other materials provided with the distribution.
  47. * 3. The name of the author may not be used to endorse or promote products
  48. * derived from this software without specific prior written permission.
  49. *
  50. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  51. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  52. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  53. * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  54. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  55. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  56. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  57. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  58. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  59. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  60. */
  61. #include <sys/cdefs.h>
  62. #ifndef lint
  63. __RCSID("$NetBSD: hack.read.c,v 1.8 2003/04/02 18:36:39 jsm Exp $");
  64. #endif /* not lint */
  65. #include <stdlib.h>
  66. #include "hack.h"
  67. #include "extern.h"
  68. int
  69. doread()
  70. {
  71. struct obj *scroll;
  72. boolean confused = (Confusion != 0);
  73. boolean known = FALSE;
  74. scroll = getobj("?", "read");
  75. if (!scroll)
  76. return (0);
  77. if (!scroll->dknown && Blind) {
  78. pline("Being blind, you cannot read the formula on the scroll.");
  79. return (0);
  80. }
  81. if (Blind)
  82. pline("As you pronounce the formula on it, the scroll disappears.");
  83. else
  84. pline("As you read the scroll, it disappears.");
  85. if (confused)
  86. pline("Being confused, you mispronounce the magic words ... ");
  87. switch (scroll->otyp) {
  88. #ifdef MAIL
  89. case SCR_MAIL:
  90. readmail( /* scroll */ );
  91. break;
  92. #endif /* MAIL */
  93. case SCR_ENCHANT_ARMOR:
  94. {
  95. struct obj *otmp = some_armor();
  96. if (!otmp) {
  97. strange_feeling(scroll, "Your skin glows then fades.");
  98. return (1);
  99. }
  100. if (confused) {
  101. pline("Your %s glows silver for a moment.",
  102. objects[otmp->otyp].oc_name);
  103. otmp->rustfree = 1;
  104. break;
  105. }
  106. if (otmp->spe > 3 && rn2(otmp->spe)) {
  107. pline("Your %s glows violently green for a while, then evaporates.",
  108. objects[otmp->otyp].oc_name);
  109. useup(otmp);
  110. break;
  111. }
  112. pline("Your %s glows green for a moment.",
  113. objects[otmp->otyp].oc_name);
  114. otmp->cursed = 0;
  115. otmp->spe++;
  116. break;
  117. }
  118. case SCR_DESTROY_ARMOR:
  119. if (confused) {
  120. struct obj *otmp = some_armor();
  121. if (!otmp) {
  122. strange_feeling(scroll, "Your bones itch.");
  123. return (1);
  124. }
  125. pline("Your %s glows purple for a moment.",
  126. objects[otmp->otyp].oc_name);
  127. otmp->rustfree = 0;
  128. break;
  129. }
  130. if (uarm) {
  131. pline("Your armor turns to dust and falls to the floor!");
  132. useup(uarm);
  133. } else if (uarmh) {
  134. pline("Your helmet turns to dust and is blown away!");
  135. useup(uarmh);
  136. } else if (uarmg) {
  137. pline("Your gloves vanish!");
  138. useup(uarmg);
  139. selftouch("You");
  140. } else {
  141. strange_feeling(scroll, "Your skin itches.");
  142. return (1);
  143. }
  144. break;
  145. case SCR_CONFUSE_MONSTER:
  146. if (confused) {
  147. pline("Your hands begin to glow purple.");
  148. Confusion += rnd(100);
  149. } else {
  150. pline("Your hands begin to glow blue.");
  151. u.umconf = 1;
  152. }
  153. break;
  154. case SCR_SCARE_MONSTER:
  155. {
  156. int ct = 0;
  157. struct monst *mtmp;
  158. for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  159. if (cansee(mtmp->mx, mtmp->my)) {
  160. if (confused)
  161. mtmp->mflee = mtmp->mfroz =
  162. mtmp->msleep = 0;
  163. else
  164. mtmp->mflee = 1;
  165. ct++;
  166. }
  167. if (!ct) {
  168. if (confused)
  169. pline("You hear sad wailing in the distance.");
  170. else
  171. pline("You hear maniacal laughter in the distance.");
  172. }
  173. break;
  174. }
  175. case SCR_BLANK_PAPER:
  176. if (confused)
  177. pline("You see strange patterns on this scroll.");
  178. else
  179. pline("This scroll seems to be blank.");
  180. break;
  181. case SCR_REMOVE_CURSE:
  182. {
  183. struct obj *obj;
  184. if (confused)
  185. pline("You feel like you need some help.");
  186. else
  187. pline("You feel like someone is helping you.");
  188. for (obj = invent; obj; obj = obj->nobj)
  189. if (obj->owornmask)
  190. obj->cursed = confused;
  191. if (Punished && !confused) {
  192. Punished = 0;
  193. freeobj(uchain);
  194. unpobj(uchain);
  195. free((char *) uchain);
  196. uball->spe = 0;
  197. uball->owornmask &= ~W_BALL;
  198. uchain = uball = (struct obj *) 0;
  199. }
  200. break;
  201. }
  202. case SCR_CREATE_MONSTER:
  203. {
  204. int cnt = 1;
  205. if (!rn2(73))
  206. cnt += rnd(4);
  207. if (confused)
  208. cnt += 12;
  209. while (cnt--)
  210. (void) makemon(confused ? PM_ACID_BLOB :
  211. (struct permonst *) 0, u.ux, u.uy);
  212. break;
  213. }
  214. case SCR_ENCHANT_WEAPON:
  215. if (uwep && confused) {
  216. pline("Your %s glows silver for a moment.",
  217. objects[uwep->otyp].oc_name);
  218. uwep->rustfree = 1;
  219. } else if (!chwepon(scroll, 1)) /* tests for !uwep */
  220. return (1);
  221. break;
  222. case SCR_DAMAGE_WEAPON:
  223. if (uwep && confused) {
  224. pline("Your %s glows purple for a moment.",
  225. objects[uwep->otyp].oc_name);
  226. uwep->rustfree = 0;
  227. } else if (!chwepon(scroll, -1)) /* tests for !uwep */
  228. return (1);
  229. break;
  230. case SCR_TAMING:
  231. {
  232. int i, j;
  233. int bd = confused ? 5 : 1;
  234. struct monst *mtmp;
  235. for (i = -bd; i <= bd; i++)
  236. for (j = -bd; j <= bd; j++)
  237. if ((mtmp = m_at(u.ux + i, u.uy + j)) != NULL)
  238. (void) tamedog(mtmp, (struct obj *) 0);
  239. break;
  240. }
  241. case SCR_GENOCIDE:
  242. {
  243. char buf[BUFSZ];
  244. struct monst *mtmp, *mtmp2;
  245. pline("You have found a scroll of genocide!");
  246. known = TRUE;
  247. if (confused)
  248. *buf = u.usym;
  249. else
  250. do {
  251. pline("What monster do you want to genocide (Type the letter)? ");
  252. getlin(buf);
  253. } while (strlen(buf) != 1 || !monstersym(*buf));
  254. if (!strchr(fut_geno, *buf))
  255. charcat(fut_geno, *buf);
  256. if (!strchr(genocided, *buf))
  257. charcat(genocided, *buf);
  258. else {
  259. pline("Such monsters do not exist in this world.");
  260. break;
  261. }
  262. for (mtmp = fmon; mtmp; mtmp = mtmp2) {
  263. mtmp2 = mtmp->nmon;
  264. if (mtmp->data->mlet == *buf)
  265. mondead(mtmp);
  266. }
  267. pline("Wiped out all %c's.", *buf);
  268. if (*buf == u.usym) {
  269. killer = "scroll of genocide";
  270. u.uhp = -1;
  271. }
  272. break;
  273. }
  274. case SCR_LIGHT:
  275. if (!Blind)
  276. known = TRUE;
  277. litroom(!confused);
  278. break;
  279. case SCR_TELEPORTATION:
  280. if (confused)
  281. level_tele();
  282. else {
  283. #ifdef QUEST
  284. int oux = u.ux, ouy = u.uy;
  285. tele();
  286. if (dist(oux, ouy) > 100)
  287. known = TRUE;
  288. #else /* QUEST */
  289. int uroom = inroom(u.ux, u.uy);
  290. tele();
  291. if (uroom != inroom(u.ux, u.uy))
  292. known = TRUE;
  293. #endif /* QUEST */
  294. }
  295. break;
  296. case SCR_GOLD_DETECTION:
  297. /*
  298. * Unfortunately this code has become slightly less elegant,
  299. * now that gold and traps no longer are of the same type.
  300. */
  301. if (confused) {
  302. struct trap *ttmp;
  303. if (!ftrap) {
  304. strange_feeling(scroll, "Your toes stop itching.");
  305. return (1);
  306. } else {
  307. for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
  308. if (ttmp->tx != u.ux || ttmp->ty != u.uy)
  309. goto outtrapmap;
  310. /*
  311. * only under me - no separate display
  312. * required
  313. */
  314. pline("Your toes itch!");
  315. break;
  316. outtrapmap:
  317. cls();
  318. for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
  319. at(ttmp->tx, ttmp->ty, '$');
  320. prme();
  321. pline("You feel very greedy!");
  322. }
  323. } else {
  324. struct gold *gtmp;
  325. if (!fgold) {
  326. strange_feeling(scroll, "You feel materially poor.");
  327. return (1);
  328. } else {
  329. known = TRUE;
  330. for (gtmp = fgold; gtmp; gtmp = gtmp->ngold)
  331. if (gtmp->gx != u.ux || gtmp->gy != u.uy)
  332. goto outgoldmap;
  333. /*
  334. * only under me - no separate display
  335. * required
  336. */
  337. pline("You notice some gold between your feet.");
  338. break;
  339. outgoldmap:
  340. cls();
  341. for (gtmp = fgold; gtmp; gtmp = gtmp->ngold)
  342. at(gtmp->gx, gtmp->gy, '$');
  343. prme();
  344. pline("You feel very greedy, and sense gold!");
  345. }
  346. }
  347. /* common sequel */
  348. more();
  349. docrt();
  350. break;
  351. case SCR_FOOD_DETECTION:
  352. {
  353. int ct = 0, ctu = 0;
  354. struct obj *obj;
  355. char foodsym = confused ? POTION_SYM : FOOD_SYM;
  356. for (obj = fobj; obj; obj = obj->nobj)
  357. if (obj->olet == FOOD_SYM) {
  358. if (obj->ox == u.ux && obj->oy == u.uy)
  359. ctu++;
  360. else
  361. ct++;
  362. }
  363. if (!ct && !ctu) {
  364. strange_feeling(scroll, "Your nose twitches.");
  365. return (1);
  366. } else if (!ct) {
  367. known = TRUE;
  368. pline("You smell %s close nearby.",
  369. confused ? "something" : "food");
  370. } else {
  371. known = TRUE;
  372. cls();
  373. for (obj = fobj; obj; obj = obj->nobj)
  374. if (obj->olet == foodsym)
  375. at(obj->ox, obj->oy, FOOD_SYM);
  376. prme();
  377. pline("Your nose tingles and you smell %s!",
  378. confused ? "something" : "food");
  379. more();
  380. docrt();
  381. }
  382. break;
  383. }
  384. case SCR_IDENTIFY:
  385. /* known = TRUE; */
  386. if (confused)
  387. pline("You identify this as an identify scroll.");
  388. else
  389. pline("This is an identify scroll.");
  390. useup(scroll);
  391. objects[SCR_IDENTIFY].oc_name_known = 1;
  392. if (!confused)
  393. while (
  394. !ggetobj("identify", identify, rn2(5) ? 1 : rn2(5))
  395. && invent
  396. );
  397. return (1);
  398. case SCR_MAGIC_MAPPING:
  399. {
  400. struct rm *lev;
  401. int num, zx, zy;
  402. known = TRUE;
  403. pline("On this scroll %s a map!",
  404. confused ? "was" : "is");
  405. for (zy = 0; zy < ROWNO; zy++)
  406. for (zx = 0; zx < COLNO; zx++) {
  407. if (confused && rn2(7))
  408. continue;
  409. lev = &(levl[zx][zy]);
  410. if ((num = lev->typ) == 0)
  411. continue;
  412. if (num == SCORR) {
  413. lev->typ = CORR;
  414. lev->scrsym = CORR_SYM;
  415. } else if (num == SDOOR) {
  416. lev->typ = DOOR;
  417. lev->scrsym = '+';
  418. /* do sth in doors ? */
  419. } else if (lev->seen)
  420. continue;
  421. #ifndef QUEST
  422. if (num != ROOM)
  423. #endif /* QUEST */
  424. {
  425. lev->seen = lev->new = 1;
  426. if (lev->scrsym == ' ' || !lev->scrsym)
  427. newsym(zx, zy);
  428. else
  429. on_scr(zx, zy);
  430. }
  431. }
  432. break;
  433. }
  434. case SCR_AMNESIA:
  435. {
  436. int zx, zy;
  437. known = TRUE;
  438. for (zx = 0; zx < COLNO; zx++)
  439. for (zy = 0; zy < ROWNO; zy++)
  440. if (!confused || rn2(7))
  441. if (!cansee(zx, zy))
  442. levl[zx][zy].seen = 0;
  443. docrt();
  444. pline("Thinking of Maud you forget everything else.");
  445. break;
  446. }
  447. case SCR_FIRE:
  448. {
  449. int num = 0;
  450. struct monst *mtmp;
  451. known = TRUE;
  452. if (confused) {
  453. pline("The scroll catches fire and you burn your hands.");
  454. losehp(1, "scroll of fire");
  455. } else {
  456. pline("The scroll erupts in a tower of flame!");
  457. if (Fire_resistance)
  458. pline("You are uninjured.");
  459. else {
  460. num = rnd(6);
  461. u.uhpmax -= num;
  462. losehp(num, "scroll of fire");
  463. }
  464. }
  465. num = (2 * num + 1) / 3;
  466. for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  467. if (dist(mtmp->mx, mtmp->my) < 3) {
  468. mtmp->mhp -= num;
  469. if (strchr("FY", mtmp->data->mlet))
  470. mtmp->mhp -= 3 * num; /* this might well kill
  471. * 'F's */
  472. if (mtmp->mhp < 1) {
  473. killed(mtmp);
  474. break; /* primitive */
  475. }
  476. }
  477. }
  478. break;
  479. }
  480. case SCR_PUNISHMENT:
  481. known = TRUE;
  482. if (confused) {
  483. pline("You feel guilty.");
  484. break;
  485. }
  486. pline("You are being punished for your misbehaviour!");
  487. if (Punished) {
  488. pline("Your iron ball gets heavier.");
  489. uball->owt += 15;
  490. break;
  491. }
  492. Punished = INTRINSIC;
  493. setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN);
  494. setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL);
  495. uball->spe = 1; /* special ball (see save) */
  496. break;
  497. default:
  498. impossible("What weird language is this written in? (%u)",
  499. scroll->otyp);
  500. }
  501. if (!objects[scroll->otyp].oc_name_known) {
  502. if (known && !confused) {
  503. objects[scroll->otyp].oc_name_known = 1;
  504. more_experienced(0, 10);
  505. } else if (!objects[scroll->otyp].oc_uname)
  506. docall(scroll);
  507. }
  508. useup(scroll);
  509. return (1);
  510. }
  511. int
  512. identify(otmp) /* also called by newmail() */
  513. struct obj *otmp;
  514. {
  515. objects[otmp->otyp].oc_name_known = 1;
  516. otmp->known = otmp->dknown = 1;
  517. prinv(otmp);
  518. return (1);
  519. }
  520. void
  521. litroom(on)
  522. boolean on;
  523. {
  524. #ifndef QUEST
  525. int num, zx, zy;
  526. #endif
  527. /* first produce the text (provided he is not blind) */
  528. if (Blind)
  529. goto do_it;
  530. if (!on) {
  531. if (u.uswallow || !xdnstair || levl[u.ux][u.uy].typ == CORR ||
  532. !levl[u.ux][u.uy].lit) {
  533. pline("It seems even darker in here than before.");
  534. return;
  535. } else
  536. pline("It suddenly becomes dark in here.");
  537. } else {
  538. if (u.uswallow) {
  539. pline("%s's stomach is lit.", Monnam(u.ustuck));
  540. return;
  541. }
  542. if (!xdnstair) {
  543. pline("Nothing Happens.");
  544. return;
  545. }
  546. #ifdef QUEST
  547. pline("The cave lights up around you, then fades.");
  548. return;
  549. #else /* QUEST */
  550. if (levl[u.ux][u.uy].typ == CORR) {
  551. pline("The corridor lights up around you, then fades.");
  552. return;
  553. } else if (levl[u.ux][u.uy].lit) {
  554. pline("The light here seems better now.");
  555. return;
  556. } else
  557. pline("The room is lit.");
  558. #endif /* QUEST */
  559. }
  560. do_it:
  561. #ifdef QUEST
  562. return;
  563. #else /* QUEST */
  564. if (levl[u.ux][u.uy].lit == on)
  565. return;
  566. if (levl[u.ux][u.uy].typ == DOOR) {
  567. if (IS_ROOM(levl[u.ux][u.uy + 1].typ))
  568. zy = u.uy + 1;
  569. else if (IS_ROOM(levl[u.ux][u.uy - 1].typ))
  570. zy = u.uy - 1;
  571. else
  572. zy = u.uy;
  573. if (IS_ROOM(levl[u.ux + 1][u.uy].typ))
  574. zx = u.ux + 1;
  575. else if (IS_ROOM(levl[u.ux - 1][u.uy].typ))
  576. zx = u.ux - 1;
  577. else
  578. zx = u.ux;
  579. } else {
  580. zx = u.ux;
  581. zy = u.uy;
  582. }
  583. for (seelx = u.ux; (num = levl[seelx - 1][zy].typ) != CORR && num != 0;
  584. seelx--);
  585. for (seehx = u.ux; (num = levl[seehx + 1][zy].typ) != CORR && num != 0;
  586. seehx++);
  587. for (seely = u.uy; (num = levl[zx][seely - 1].typ) != CORR && num != 0;
  588. seely--);
  589. for (seehy = u.uy; (num = levl[zx][seehy + 1].typ) != CORR && num != 0;
  590. seehy++);
  591. for (zy = seely; zy <= seehy; zy++)
  592. for (zx = seelx; zx <= seehx; zx++) {
  593. levl[zx][zy].lit = on;
  594. if (!Blind && dist(zx, zy) > 2) {
  595. if (on)
  596. prl(zx, zy);
  597. else
  598. nosee(zx, zy);
  599. }
  600. }
  601. if (!on)
  602. seehx = 0;
  603. #endif /* QUEST */
  604. }
  605. /* Test whether we may genocide all monsters with symbol ch */
  606. int
  607. monstersym(ch) /* arnold@ucsfcgl */
  608. char ch;
  609. {
  610. const struct permonst *mp;
  611. /*
  612. * can't genocide certain monsters
  613. */
  614. if (strchr("12 &:", ch))
  615. return FALSE;
  616. if (ch == pm_eel.mlet)
  617. return TRUE;
  618. for (mp = mons; mp < &mons[CMNUM + 2]; mp++)
  619. if (mp->mlet == ch)
  620. return TRUE;
  621. return FALSE;
  622. }