home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume7 / nethack3 / part18 < prev    next >
Internet Message Format  |  1989-07-31  |  56KB

  1. Path: uunet!zephyr.ens.tek.com!tektronix!tekgen!tekred!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v07i073:  NetHack3 -  display oriented dungeons & dragons (Ver. 3.0), Part18/38
  5. Message-ID: <4326@tekred.CNA.TEK.COM>
  6. Date: 24 Jul 89 05:05:27 GMT
  7. Sender: nobody@tekred.CNA.TEK.COM
  8. Lines: 2128
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
  12. Posting-number: Volume 7, Issue 73
  13. Archive-name: NetHack3/Part18
  14.  
  15.  
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 18 (of 38)."
  24. # Contents:  src/artifact.c src/makemon.c src/options.c
  25. # Wrapped by billr@saab on Sun Jul 23 21:33:01 1989
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'src/artifact.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'src/artifact.c'\"
  29. else
  30. echo shar: Extracting \"'src/artifact.c'\" \(6525 characters\)
  31. sed "s/^X//" >'src/artifact.c' <<'END_OF_FILE'
  32. X/*    SCCS Id: @(#)artifact.c    3.0    88/07/27
  33. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  34. X/* NetHack may be freely redistributed.  See license for details. */
  35. X
  36. X#include "hack.h"
  37. X
  38. X#ifdef NAMED_ITEMS
  39. X
  40. X#include "artifact.h"
  41. X
  42. X/* the artifacts (currently weapons only) */
  43. Xstatic const struct artifact artilist[] = {
  44. X
  45. X#define        NO_ATTK    0, 0, 0, 0
  46. X
  47. X{ LONG_SWORD,     "Excalibur",    (SPFX_NOGEN | SPFX_SEEK | SPFX_DEFN |
  48. X                                SPFX_SEARCH), 0,
  49. X  { 0, AD_PHYS, 5, 10 }, { 0, AD_DRLI, 0, 0} },
  50. X
  51. X{ KATANA,     "Snickersnee",    SPFX_RESTR, 0,
  52. X  { 0, AD_PHYS, 0, 8 }, NO_ATTK },
  53. X
  54. X/*    Ah, never shall I forget the cry, 
  55. X *        or the shriek that shrieked he,
  56. X *    As I gnashed my teeth, and from my sheath
  57. X *        I drew my Snickersnee!
  58. X *
  59. X *        --Koko, Lord high executioner of Titipu
  60. X *          (From Sir W.S. Gilbert's "The Mikado")
  61. X */
  62. X
  63. X{ AXE,         "Cleaver",    SPFX_RESTR, 0,
  64. X  { 0, AD_PHYS, 3, 12 }, NO_ATTK },
  65. X
  66. X/*  Special purpose swords - various types */
  67. X
  68. X{ TWO_HANDED_SWORD, "Orcrist",    SPFX_DCLAS, S_ORC,
  69. X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
  70. X
  71. X#ifdef TOLKIEN
  72. X{ ELVEN_DAGGER,     "Sting",    (SPFX_WARN | SPFX_DCLAS), S_ORC,
  73. X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
  74. X#else
  75. X{ DAGGER,     "Sting",    (SPFX_WARN | SPFX_DCLAS), S_ORC,
  76. X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
  77. X#endif
  78. X
  79. X{ LONG_SWORD,     "Frost Brand", (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN), 0,
  80. X  { 0, AD_COLD, 5, 0 }, { 0, AD_COLD, 0, 0 } },
  81. X
  82. X{ LONG_SWORD,     "Fire Brand",    (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN), 0,
  83. X  { 0, AD_FIRE, 5, 0 }, { 0, AD_FIRE, 0, 0 } },
  84. X
  85. X/* Stormbringer only has a 2 because it can drain a level, providing 8 more */
  86. X{ BROADSWORD,     "Stormbringer", (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN |
  87. X                                SPFX_DRLI), 0,
  88. X  { 0, AD_DRLI, 5, 2 }, { 0, AD_DRLI, 0, 0 } },
  89. X
  90. X{ LONG_SWORD,     "Sunsword",    (SPFX_RESTR | SPFX_DCLAS), 0, /* undead */
  91. X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
  92. X
  93. X{ BROADSWORD,     "Dragonbane",    (SPFX_RESTR | SPFX_DCLAS), S_DRAGON,
  94. X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
  95. X
  96. X{ LONG_SWORD,     "Demonbane",    (SPFX_RESTR | SPFX_DCLAS), 0, /* demons */
  97. X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
  98. X
  99. X{ LONG_SWORD,     "Werebane",    (SPFX_RESTR | SPFX_DCLAS), 0, /* weres */
  100. X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
  101. X
  102. X{ LONG_SWORD,     "Giantslayer", (SPFX_RESTR | SPFX_DCLAS), 0, /* giants */
  103. X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
  104. X
  105. X{ LUCERN_HAMMER, "Ogresmasher",    (SPFX_RESTR | SPFX_DCLAS),  S_OGRE,
  106. X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
  107. X
  108. X{ LUCERN_HAMMER, "Thunderfist",    (SPFX_RESTR | SPFX_ATTK),  0,
  109. X  { 0, AD_ELEC, 5, 24 }, NO_ATTK },
  110. X
  111. X{ MORNING_STAR,     "Trollsbane", (SPFX_RESTR | SPFX_DCLAS), S_TROLL,
  112. X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
  113. X
  114. X/*    ARRAY TERMINATOR    */
  115. X{ 0,  "", 0, 0, NO_ATTK, NO_ATTK }
  116. X};
  117. X
  118. Xvoid
  119. Xmkartifact(otmp1)
  120. Xstruct obj **otmp1;
  121. X{
  122. X    register struct artifact *artif;
  123. X    register struct obj *otmp = *otmp1;
  124. X    register int n = 0;
  125. X
  126. X    for(artif = artilist; artif->otyp; artif++)
  127. X        if(otmp->otyp == artif->otyp && !(artif->spfx & SPFX_NOGEN)) n++;
  128. X
  129. X    if (n) {
  130. X        n = rnd(n);
  131. X        for(artif = artilist; artif->otyp && n > 0; ) {
  132. X            if(otmp->otyp == artif->otyp && !(artif->spfx & SPFX_NOGEN)) n--;
  133. X            if (n>0) artif++;
  134. X        }
  135. X
  136. X        if(artif->otyp) *otmp1 = oname(otmp, artif->name, 0);
  137. X    }
  138. X}
  139. X
  140. Xstatic struct artifact *
  141. Xget_artifact(otmp)
  142. Xstruct obj *otmp;
  143. X{
  144. X    register struct artifact *artif;
  145. X
  146. X    if(otmp)
  147. X        if(strlen(ONAME(otmp)))
  148. X        for(artif = artilist; artif->otyp; artif++)
  149. X            if(artif->otyp == otmp->otyp &&
  150. X               !strcmp(ONAME(otmp), artif->name)) return(artif);
  151. X    return((struct artifact *)0);
  152. X}
  153. X
  154. Xboolean
  155. Xis_artifact(otmp)
  156. Xstruct obj *otmp;
  157. X{
  158. X    return(get_artifact(otmp) != (struct artifact *)0);
  159. X}
  160. X
  161. Xboolean
  162. Xspec_ability(otmp, abil)
  163. Xstruct obj *otmp;
  164. Xunsigned abil;
  165. X{
  166. X    struct artifact *arti = get_artifact(otmp);
  167. X    
  168. X    return(arti && (arti->spfx & abil));
  169. X}
  170. X
  171. Xint
  172. Xrestr_name(otmp, name)    /* returns 1 if name is restricted for otmp->otyp */
  173. Xregister struct obj *otmp;
  174. Xregister char    *name;
  175. X{
  176. X    register struct artifact *artif;
  177. X
  178. X    if(!strlen(name)) return(0);
  179. X
  180. X    for(artif = artilist; artif->otyp; artif++)
  181. X        if(artif->otyp == otmp->otyp)
  182. X        if(artif->spfx & (SPFX_NOGEN | SPFX_RESTR))
  183. X            if(!strcmp(artif->name, name)) return(1);
  184. X
  185. X    return(0);
  186. X}
  187. X
  188. X# if defined(THEOLOGY) && defined(ALTARS)
  189. Xstruct obj *
  190. Xmk_aligned_artifact(align)
  191. Xint align;
  192. X{
  193. X    register struct artifact *artif;
  194. X    register struct obj *otmp;
  195. X    register int n = 0;
  196. X
  197. X    for(artif = artilist; artif->otyp; artif++)
  198. X        if(align == artif->align && !(artif->spfx & SPFX_NOGEN)) n++;
  199. X    if (n) {
  200. X        n = rnd(n);
  201. X        for(artif = artilist; artif->otyp && n > 0; ) {
  202. X            if(align == artif->align && !(artif->spfx & SPFX_NOGEN))
  203. X            n--;
  204. X            if (n > 0) artif++;
  205. X        }
  206. X        if(artif->otyp) {
  207. X            otmp = mksobj((int)artif->otyp, FALSE);
  208. X            otmp = oname(otmp, artif->name, 0);
  209. X            return (otmp);
  210. X        }
  211. X    }
  212. X    return ((struct obj *) 0);
  213. X}
  214. X# endif
  215. X
  216. Xint
  217. Xdefends(adtyp, otmp)
  218. Xregister int adtyp;
  219. Xregister struct obj *otmp;
  220. X{
  221. X    register struct artifact *weap;
  222. X
  223. X    if(weap = get_artifact(otmp))
  224. X        return(weap->defn.adtyp == adtyp);
  225. X    return(0);
  226. X}
  227. X
  228. Xstatic int
  229. Xspec_applies(weap, ptr)
  230. Xregister struct artifact *weap;
  231. Xstruct permonst *ptr;
  232. X{
  233. X    if(!(weap->spfx & (SPFX_DMONS | SPFX_DCLAS | SPFX_ATTK)))
  234. X        return(1);
  235. X
  236. X    if(weap->spfx & SPFX_DMONS)
  237. X        return((ptr == &mons[weap->mtype]));
  238. X    else if(weap->spfx & SPFX_DCLAS) {
  239. X
  240. X        if(weap->mtype)
  241. X        return((weap->mtype == ptr->mlet));
  242. X        else {
  243. X        if(!strcmp(weap->name, "Sunsword"))
  244. X            return(is_undead(ptr));
  245. X        else if(!strcmp(weap->name, "Demonbane"))
  246. X            return(is_demon(ptr));
  247. X        else if(!strcmp(weap->name, "Werebane"))
  248. X            return(is_were(ptr));
  249. X        else if(!strcmp(weap->name, "Giantslayer"))
  250. X            return(is_giant(ptr));
  251. X        else impossible("Weird class specific weapon '%s'",
  252. X                weap->name);
  253. X        }
  254. X    } else if(weap->spfx & SPFX_ATTK) {
  255. X        switch(weap->attk.adtyp) {
  256. X        case AD_FIRE:    return(!resists_fire(ptr));
  257. X        case AD_COLD:    return(!resists_cold(ptr));
  258. X        case AD_ELEC:    return(!resists_elec(ptr));
  259. X        case AD_DRLI:    return(!resists_drli(ptr));
  260. X        case AD_STON:    return(!resists_ston(ptr));
  261. X        default:    impossible("Weird special attack for '%s'",
  262. X                       weap->name);
  263. X        }
  264. X    }
  265. X    return(0);
  266. X}
  267. X
  268. Xint
  269. Xspec_abon(otmp, ptr)
  270. Xstruct obj *otmp;
  271. Xstruct permonst *ptr;
  272. X{
  273. X    register struct artifact *weap;
  274. X
  275. X    if((weap = get_artifact(otmp)))
  276. X        if(spec_applies(weap, ptr))
  277. X            return((weap->attk.damn) ? rnd((int)weap->attk.damn) : 0);
  278. X    return(0);
  279. X}
  280. X
  281. Xint
  282. Xspec_dbon(otmp, ptr, tmp)
  283. Xregister struct obj *otmp;
  284. Xregister struct permonst *ptr;
  285. Xregister int    tmp;
  286. X{
  287. X    register struct artifact *weap;
  288. X
  289. X    if((weap = get_artifact(otmp)))
  290. X        if(spec_applies(weap, ptr))
  291. X            return((weap->attk.damd) ? rnd((int)weap->attk.damd) : tmp);
  292. X    return(0);
  293. X}
  294. X#endif /* NAMED_ITEMS */
  295. END_OF_FILE
  296. if test 6525 -ne `wc -c <'src/artifact.c'`; then
  297.     echo shar: \"'src/artifact.c'\" unpacked with wrong size!
  298. fi
  299. # end of 'src/artifact.c'
  300. fi
  301. if test -f 'src/makemon.c' -a "${1}" != "-c" ; then 
  302.   echo shar: Will not clobber existing file \"'src/makemon.c'\"
  303. else
  304. echo shar: Extracting \"'src/makemon.c'\" \(28290 characters\)
  305. sed "s/^X//" >'src/makemon.c' <<'END_OF_FILE'
  306. X/*    SCCS Id: @(#)makemon.c    3.0    88/04/11
  307. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  308. X/* NetHack may be freely redistributed.  See license for details. */
  309. X
  310. X#include    "hack.h"
  311. X
  312. Xstruct monst zeromonst;
  313. Xstatic int uncommon P((struct permonst *));
  314. X
  315. Xstatic int monstr[NUMMONS];
  316. X
  317. X#define m_initsgrp(mtmp, x, y) m_initgrp(mtmp, x, y, 3)
  318. X#define m_initlgrp(mtmp, x, y) m_initgrp(mtmp, x, y, 10)
  319. X#define toostrong(monindx, lev) (monstr[monindx] > lev)
  320. X#define tooweak(monindx, lev)    (monstr[monindx] < lev)
  321. X
  322. Xstatic void
  323. Xm_initgrp(mtmp, x, y, n)    /* make a group just like mtmp */
  324. Xregister struct monst *mtmp;
  325. Xregister int x, y, n;
  326. X{
  327. X    coord mm;
  328. X    register int cnt = rnd(n);
  329. X    struct monst *mon;
  330. X
  331. X    mm.x = x;
  332. X    mm.y = y;
  333. X    while(cnt--) {
  334. X        if (peace_minded(mtmp->data)) continue;
  335. X        /* Don't create groups of peaceful monsters since they'll get
  336. X         * in our way.  If the monster has a percentage chance so some
  337. X         * are peaceful and some are not, the result will just be a
  338. X         * smaller group.
  339. X         */
  340. X        enexto(&mm, mm.x, mm.y);
  341. X        mon = makemon(mtmp->data, mm.x, mm.y);
  342. X        mon->mpeaceful = 0;
  343. X        set_malign(mon);
  344. X        /* Undo the second peace_minded() check in makemon(); if the
  345. X         * monster turned out to be peaceful the first time we didn't
  346. X         * create it at all; we don't want a second check.
  347. X         */
  348. X    }
  349. X}
  350. X
  351. Xstatic void
  352. Xm_initthrow(mtmp,otyp,oquan)
  353. Xstruct monst *mtmp;
  354. Xint otyp,oquan;
  355. X{
  356. X    register struct obj *otmp;
  357. X
  358. X    otmp = mksobj(otyp,FALSE);
  359. X    otmp->quan = 2 + rnd(oquan);
  360. X    otmp->owt = weight(otmp);
  361. X#ifdef TOLKIEN
  362. X    if (otyp == ORCISH_ARROW) otmp->opoisoned = 1;
  363. X#endif
  364. X    mpickobj(mtmp, otmp);
  365. X}
  366. X
  367. Xstatic void
  368. Xm_initweap(mtmp)
  369. Xregister struct monst *mtmp;
  370. X{
  371. X    register struct permonst *ptr = mtmp->data;
  372. X#ifdef REINCARNATION
  373. X    if (dlevel==rogue_level) return;
  374. X#endif
  375. X/*
  376. X *    first a few special cases:
  377. X *
  378. X *        giants get a boulder to throw sometimes.
  379. X *        ettins get clubs
  380. X *        kobolds get darts to throw
  381. X *        centaurs get some sort of bow & arrows or bolts
  382. X *        soldiers get all sorts of things.
  383. X *        kops get clubs & cream pies.
  384. X */
  385. X    switch (mtmp->data->mlet) {
  386. X        case S_GIANT:
  387. X        if (rn2(2)) (void)mongets(mtmp, (ptr != &mons[PM_ETTIN]) ?
  388. X                    BOULDER : CLUB);
  389. X        break;
  390. X        case S_HUMAN:
  391. X        if(is_mercenary(ptr))
  392. X            switch(monsndx(ptr)) {
  393. X
  394. X#ifdef ARMY
  395. X            case PM_SOLDIER:
  396. X              (void) mongets(mtmp, rn2(2) ? SPEAR : SHORT_SWORD);
  397. X              break;
  398. X            case PM_SERGEANT:
  399. X              (void) mongets(mtmp, rn2(2) ? FLAIL : MACE);
  400. X              break;
  401. X            case PM_LIEUTENANT:
  402. X              (void) mongets(mtmp, rn2(2) ? GLAIVE : LONG_SWORD);
  403. X              break;
  404. X            case PM_CAPTAIN:
  405. X              (void) mongets(mtmp, rn2(2) ? LONG_SWORD : SCIMITAR);
  406. X              break;
  407. X#endif
  408. X            default:    if (!rn2(4)) (void) mongets(mtmp, DAGGER);
  409. X                    if (!rn2(7)) (void) mongets(mtmp, SPEAR);
  410. X                    break;
  411. X            }
  412. X            break;
  413. X
  414. X        case S_HUMANOID:
  415. X#ifdef TOLKIEN
  416. X        if (monsndx(ptr) == PM_HOBBIT) {
  417. X            switch (rn2(3)) {
  418. X              case 0:
  419. X                (void)mongets(mtmp, DAGGER);
  420. X                break;
  421. X            case 1:
  422. X                (void)mongets(mtmp, ELVEN_DAGGER);
  423. X                break;
  424. X              }
  425. X            if (!rn2(10)) (void)mongets(mtmp, ELVEN_MITHRIL_COAT);
  426. X        } else if (is_dwarf(ptr)) {
  427. X            (void)mongets(mtmp, DWARVISH_CLOAK);
  428. X            (void)mongets(mtmp, IRON_SHOES);
  429. X            if (!rn2(4)) {
  430. X            (void)mongets(mtmp, DWARVISH_SHORT_SWORD);
  431. X            (void)mongets(mtmp,
  432. X                rn2(3) ? DWARVISH_MATTOCK : AXE);
  433. X            (void)mongets(mtmp, DWARVISH_IRON_HELM);
  434. X            (void)mongets(mtmp, DWARVISH_ROUNDSHIELD);
  435. X            if (!rn2(3))
  436. X                (void)mongets(mtmp, DWARVISH_MITHRIL_COAT);
  437. X            } else {
  438. X            (void)mongets(mtmp, PICK_AXE);
  439. X            }
  440. X        } else if (is_elf(ptr)) {
  441. X            (void)mongets(mtmp,
  442. X            rn2(2) ? ELVEN_MITHRIL_COAT : ELVEN_CLOAK);
  443. X            if (rn2(2)) (void)mongets(mtmp, ELVEN_LEATHER_HELM);
  444. X            if (rn2(3)) (void)mongets(mtmp, ELVEN_DAGGER);
  445. X            switch (rn2(3)) {
  446. X            case 0:
  447. X                if (!rn2(4)) (void)mongets(mtmp, ELVEN_SHIELD);
  448. X                (void)mongets(mtmp, ELVEN_SHORT_SWORD);
  449. X                (void)mongets(mtmp, ELVEN_BOW);
  450. X                m_initthrow(mtmp, ELVEN_ARROW, 12);
  451. X                break;
  452. X            case 1:
  453. X                (void)mongets(mtmp, ELVEN_BROADSWORD);
  454. X                if (rn2(2)) (void)mongets(mtmp, ELVEN_SHIELD);
  455. X                break;
  456. X            case 2:
  457. X                (void)mongets(mtmp, ELVEN_SPEAR);
  458. X                (void)mongets(mtmp, ELVEN_SHIELD);
  459. X                break;
  460. X            }
  461. X        }
  462. X#else /* TOLKIEN */
  463. X        if (is_dwarf(ptr)) {
  464. X            (void)mongets(mtmp, IRON_SHOES);
  465. X            if (rn2(4) == 0) {
  466. X            (void)mongets(mtmp, SHORT_SWORD);
  467. X            (void)mongets(mtmp,
  468. X                (rn2(3) == 0) ? AXE : TWO_HANDED_SWORD);
  469. X            (void)mongets(mtmp, LARGE_SHIELD);
  470. X            if (rn2(3) == 0)
  471. X                (void)mongets(mtmp, DWARVISH_MITHRIL_COAT);
  472. X            } else {
  473. X            (void)mongets(mtmp, PICK_AXE);
  474. X            }
  475. X        } else if (is_elf(ptr)) {
  476. X            (void)mongets(mtmp, ELVEN_CLOAK);
  477. X            if (rn2(3)) (void)mongets(mtmp, DAGGER);
  478. X            switch (rn2(3)) {
  479. X            case 0:
  480. X                if (!rn2(4)) (void)mongets(mtmp, SMALL_SHIELD);
  481. X                (void)mongets(mtmp, SHORT_SWORD);
  482. X                (void)mongets(mtmp, BOW);
  483. X                m_initthrow(mtmp, ARROW, 12);
  484. X                break;
  485. X            case 1:
  486. X                (void)mongets(mtmp, BROADSWORD);
  487. X                if (rn2(2)) (void)mongets(mtmp, SMALL_SHIELD);
  488. X                break;
  489. X            case 2:
  490. X                (void)mongets(mtmp, SPEAR);
  491. X                (void)mongets(mtmp, SMALL_SHIELD);
  492. X                break;
  493. X            }
  494. X        }
  495. X#endif /* TOLKIEN */
  496. X        break;
  497. X# ifdef KOPS
  498. X        case S_KOP:        /* create Keystone Kops with cream pies to
  499. X                 * throw. As suggested by KAA.       [MRS]
  500. X                 */
  501. X        if (!rn2(4)) m_initthrow(mtmp, CREAM_PIE, 2);
  502. X        if (!rn2(3)) (void)mongets(mtmp, (rn2(2)) ? CLUB : RUBBER_HOSE);
  503. X        break;
  504. X#endif
  505. X        case S_ORC:
  506. X#ifdef TOLKIEN
  507. X        { int mm = monsndx(ptr);
  508. X          if(rn2(2)) (void)mongets(mtmp, ORCISH_HELM);
  509. X          if (mm == PM_MORDOR_ORC ||
  510. X             (mm == PM_ORC_CAPTAIN && rn2(2))) {
  511. X              if(rn2(2)) (void)mongets(mtmp, SCIMITAR);
  512. X              if(rn2(2)) (void)mongets(mtmp, ORCISH_SHIELD);
  513. X              if(rn2(2)) (void)mongets(mtmp, KNIFE);
  514. X              if(rn2(2)) (void)mongets(mtmp, ORCISH_CHAIN_MAIL);
  515. X          } else if (mm == PM_URUK_HAI || mm == PM_ORC_CAPTAIN) {
  516. X              if(rn2(2)) (void)mongets(mtmp, ORCISH_CLOAK);
  517. X              if(rn2(2)) (void)mongets(mtmp, ORCISH_SHORT_SWORD);
  518. X              if(rn2(2)) (void)mongets(mtmp, IRON_SHOES);
  519. X              if(rn2(2)) {
  520. X              (void)mongets(mtmp, ORCISH_BOW);
  521. X              m_initthrow(mtmp, ORCISH_ARROW, 12);
  522. X              }
  523. X              if(rn2(2)) (void)mongets(mtmp, URUK_HAI_SHIELD);
  524. X          } else if (mm != PM_ORC_SHAMAN) {
  525. X              (void)mongets(mtmp, (mm == PM_GOBLIN || rn2(2) == 0) ?
  526. X                    ORCISH_DAGGER : SCIMITAR);
  527. X          }
  528. X        }
  529. X#else /* TOLKIEN */
  530. X        { int mm = monsndx(ptr);
  531. X          if(rn2(2)) (void)mongets(mtmp, ORCISH_HELM);
  532. X          if (mm == PM_ORC_CAPTAIN) {
  533. X              if(rn2(2)) {
  534. X              if(rn2(2)) (void)mongets(mtmp, SCIMITAR);
  535. X              if(rn2(2)) (void)mongets(mtmp, SMALL_SHIELD);
  536. X              if(rn2(2)) (void)mongets(mtmp, KNIFE);
  537. X              if(rn2(2)) (void)mongets(mtmp, CHAIN_MAIL);
  538. X              } else {
  539. X              if(rn2(2)) (void)mongets(mtmp, SHORT_SWORD);
  540. X              if(rn2(2)) (void)mongets(mtmp, IRON_SHOES);
  541. X              if(rn2(2)) {
  542. X                  (void)mongets(mtmp, BOW);
  543. X                  m_initthrow(mtmp, ARROW, 12);
  544. X              }
  545. X              if(rn2(2)) (void)mongets(mtmp, SMALL_SHIELD);
  546. X              }
  547. X          } else if (mm != PM_ORC_SHAMAN) {
  548. X              (void)mongets(mtmp, (mm == PM_GOBLIN || rn2(2) == 0) ?
  549. X                    DAGGER : SCIMITAR);
  550. X          }
  551. X        }
  552. X#endif /* TOLKIEN */
  553. X        break;
  554. X        case S_KOBOLD:
  555. X        if (!rn2(4)) m_initthrow(mtmp, DART, 12);
  556. X        break;
  557. X
  558. X        case S_CENTAUR:
  559. X        if (rn2(2)) {
  560. X            if(ptr == &mons[PM_FOREST_CENTAUR]) {
  561. X            (void)mongets(mtmp, BOW);
  562. X            m_initthrow(mtmp, ARROW, 12);
  563. X            } else {
  564. X            (void)mongets(mtmp, CROSSBOW);
  565. X            m_initthrow(mtmp, CROSSBOW_BOLT, 12);
  566. X            }
  567. X        }
  568. X        break;
  569. X        case S_WRAITH:
  570. X        (void)mongets(mtmp, KNIFE);
  571. X        (void)mongets(mtmp, LONG_SWORD);
  572. X        break;
  573. X        case S_DEMON:
  574. X#ifdef HARD
  575. X        if (monsndx(ptr) == PM_BALROG) {
  576. X            (void)mongets(mtmp, BULLWHIP);
  577. X            (void)mongets(mtmp, BROADSWORD);
  578. X            break;
  579. X        }
  580. X#endif
  581. X        /* prevent djinnis and mail daemons from leaving objects when
  582. X         * they vanish
  583. X         */
  584. X        if (!is_demon(ptr)) break;
  585. X        /* fall thru */
  586. X/*
  587. X *    Now the general case, ~40% chance of getting some type
  588. X *    of weapon. TODO: Add more weapons types (use bigmonst());
  589. X */
  590. X        default:
  591. X        switch(rnd(12)) {
  592. X            case 1:
  593. X            m_initthrow(mtmp, DART, 12);
  594. X            break;
  595. X            case 2:
  596. X            (void) mongets(mtmp, CROSSBOW);
  597. X            m_initthrow(mtmp, CROSSBOW_BOLT, 12);
  598. X            break;
  599. X            case 3:
  600. X            (void) mongets(mtmp, BOW);
  601. X            m_initthrow(mtmp, ARROW, 12);
  602. X            break;
  603. X            case 4:
  604. X            m_initthrow(mtmp, DAGGER, 3);
  605. X            break;
  606. X            case 5:
  607. X            (void) mongets(mtmp, AKLYS);
  608. X            break;
  609. X            default:
  610. X            break;
  611. X        }
  612. X        break;
  613. X    }
  614. X}
  615. X
  616. Xstatic void
  617. Xm_initinv(mtmp)
  618. Xregister struct    monst    *mtmp;
  619. X{
  620. X    register int cnt;
  621. X    register struct obj *otmp;
  622. X    register struct permonst *ptr = mtmp->data;
  623. X#ifdef REINCARNATION
  624. X    if (dlevel==rogue_level) return;
  625. X#endif
  626. X/*
  627. X *    Soldiers get armour & rations - armour approximates their ac.
  628. X *    Nymphs may get mirror or potion of object detection.
  629. X */
  630. X    switch(mtmp->data->mlet) {
  631. X
  632. X        case S_HUMAN:
  633. X        if(is_mercenary(ptr)) {
  634. X            register int mac;
  635. X
  636. X            if((mac = ptr->ac) < -1)
  637. X            mac += 7 + mongets(mtmp, (rn2(5)) ?
  638. X                       PLATE_MAIL : CRYSTAL_PLATE_MAIL);
  639. X            else if(mac < 3)
  640. X            mac += 6 + mongets(mtmp, (rn2(3)) ?
  641. X                       SPLINT_MAIL : BANDED_MAIL);
  642. X            else
  643. X            mac += 3 + mongets(mtmp, (rn2(3)) ?
  644. X                       RING_MAIL : STUDDED_LEATHER_ARMOR);
  645. X
  646. X            if(mac < 10) {
  647. X            mac += 1 + mongets(mtmp, HELMET);
  648. X            if(mac < 10) {
  649. X                mac += 1 + mongets(mtmp, SMALL_SHIELD);
  650. X                if(mac < 10) {
  651. X                mac += 1 + mongets(mtmp, ELVEN_CLOAK);
  652. X                if(mac < 10)
  653. X                    mac += 1 +mongets(mtmp, LEATHER_GLOVES);
  654. X                }
  655. X            }
  656. X            }
  657. X
  658. X            if(mac != 10) {    /* make up the difference */
  659. X            otmp = mksobj(RIN_PROTECTION,FALSE);
  660. X            otmp->spe = (10 - mac);
  661. X            if(otmp->spe < 0) curse(otmp);
  662. X            mpickobj(mtmp, otmp);
  663. X            }
  664. X#ifdef ARMY
  665. X            if(ptr != &mons[PM_GUARD]) {
  666. X            if (!rn2(3)) (void) mongets(mtmp, K_RATION);
  667. X            if (!rn2(2)) (void) mongets(mtmp, C_RATION);
  668. X            }
  669. X#endif
  670. X        }
  671. X        break;
  672. X
  673. X        case S_NYMPH:
  674. X#ifdef MEDUSA
  675. X        if(!rn2(2)) (void) mongets(mtmp, MIRROR);
  676. X#endif
  677. X        if(!rn2(2)) (void) mongets(mtmp, POT_OBJECT_DETECTION);
  678. X        break;
  679. X
  680. X        case S_GIANT:
  681. X        if(mtmp->data == &mons[PM_MINOTAUR])
  682. X            (void) mongets(mtmp, WAN_DIGGING);
  683. X        else if (is_giant(mtmp->data)) {
  684. X            for(cnt = rn2((int)(mtmp->m_lev / 2)); cnt; cnt--) {
  685. X                do
  686. X                otmp = mkobj(GEM_SYM,FALSE);
  687. X                while (otmp->otyp >= LAST_GEM+5);
  688. X                otmp->quan = 2 + rnd(2);
  689. X                otmp->owt = weight(otmp);
  690. X                mpickobj(mtmp, otmp);
  691. X            }
  692. X        }
  693. X        break;
  694. X#ifdef TOLKIEN
  695. X        case S_WRAITH:
  696. X        if(mtmp->data == &mons[PM_NAZGUL]) {
  697. X            otmp = mksobj(RIN_INVISIBILITY, FALSE);
  698. X            curse(otmp);
  699. X            mpickobj(mtmp, otmp);
  700. X        }
  701. X        break;
  702. X#endif
  703. X        default:
  704. X        break;
  705. X    }
  706. X}
  707. X
  708. X/*
  709. X * called with [x,y] = coordinates;
  710. X *    [0,0] means anyplace
  711. X *    [u.ux,u.uy] means: call mnexto (if !in_mklev)
  712. X *
  713. X *    In case we make a monster group, only return the one at [x,y].
  714. X */
  715. Xstruct monst *
  716. Xmakemon(ptr, x, y)
  717. Xregister struct permonst *ptr;
  718. Xregister int    x, y;
  719. X{
  720. X    register struct monst *mtmp;
  721. X    register int    ct;
  722. X    boolean anything = (!ptr);
  723. X
  724. X    /* if caller wants random location, do it here */
  725. X    if(x == 0 && y == 0) {
  726. X        do {
  727. X            x = rn1(COLNO-3,2);
  728. X            y = rn2(ROWNO);
  729. X        } while(!goodpos(x, y));
  730. X    }
  731. X
  732. X    /* if a monster already exists at the position, return */
  733. X    if(levl[x][y].mmask) return((struct monst *) 0);
  734. X
  735. X    if(ptr){
  736. X        /* if you are to make a specific monster and it has 
  737. X           already been genocided, return */
  738. X        if(ptr->geno & G_GENOD) return((struct monst *) 0);
  739. X    } else {
  740. X        /* make a random (common) monster. */
  741. X#ifdef REINCARNATION
  742. X        if (!(ptr = (dlevel==rogue_level) ? roguemon() : rndmonst()))
  743. X#else
  744. X        if(!(ptr = rndmonst()))
  745. X#endif
  746. X        {
  747. X#ifdef DEBUG
  748. X            pline("Warning: no monster.");
  749. X#endif
  750. X            return((struct monst *) 0);    /* no more monsters! */
  751. X        }
  752. X    }
  753. X    /* if it's unique, don't ever make it again */
  754. X    if (ptr->geno & G_UNIQ) ptr->geno &= G_GENOD;
  755. X/* gotmon:    /* label not referenced */
  756. X    mtmp = newmonst(ptr->pxlth);
  757. X    *mtmp = zeromonst;        /* clear all entries in structure */
  758. X    for(ct = 0; ct < ptr->pxlth; ct++)
  759. X        ((char *) &(mtmp->mextra[0]))[ct] = 0;
  760. X     if(type_is_pname(ptr))
  761. X         Strcpy(NAME(mtmp), ptr->mname);
  762. X    mtmp->nmon = fmon;
  763. X    fmon = mtmp;
  764. X    mtmp->m_id = flags.ident++;
  765. X    mtmp->data = ptr;
  766. X    mtmp->mxlth = ptr->pxlth;
  767. X
  768. X    mtmp->m_lev = adj_lev(ptr);
  769. X#ifdef GOLEMS
  770. X    if (is_golem(ptr))
  771. X        mtmp->mhpmax = mtmp->mhp = golemhp(monsndx(ptr));
  772. X    else
  773. X#endif /* GOLEMS */
  774. X     if(ptr->mlevel > 49) {
  775. X        /* "special" fixed hp monster
  776. X         * the hit points are encoded in the mlevel in a somewhat strange
  777. X         * way to fit in the 50..127 positive range of a signed character
  778. X         * above the 1..49 that indicate "normal" monster levels */
  779. X         mtmp->mhpmax = mtmp->mhp = 2*(ptr->mlevel - 6);
  780. X         mtmp->m_lev = mtmp->mhp / 4;    /* approximation */
  781. X     } else if((ptr->mlet == S_DRAGON) && (ptr >= &mons[PM_GREY_DRAGON]))
  782. X        mtmp->mhpmax = mtmp->mhp = 80;
  783. X    else if(!mtmp->m_lev) mtmp->mhpmax = mtmp->mhp = rnd(4);
  784. X    else mtmp->mhpmax = mtmp->mhp = d((int)mtmp->m_lev, 8);
  785. X    mtmp->mx = x;
  786. X    mtmp->my = y;
  787. X    levl[x][y].mmask = 1;
  788. X    mtmp->mcansee = 1;
  789. X    mtmp->mpeaceful = peace_minded(ptr);
  790. X
  791. X    switch(ptr->mlet) {
  792. X        case S_MIMIC:
  793. X            set_mimic_sym(mtmp);
  794. X            break;
  795. X        case S_SPIDER:
  796. X        case S_SNAKE:
  797. X            mtmp->mhide = mtmp->mundetected = 1;
  798. X            if(in_mklev)
  799. X                if(mtmp->mx && mtmp->my)
  800. X                (void) mkobj_at(0, mtmp->mx, mtmp->my);
  801. X            break;
  802. X        case S_CHAMELEON:
  803. X            /* If you're protected with a ring, don't create
  804. X             * any shape-changing chameleons -dgk
  805. X             */
  806. X            if (Protection_from_shape_changers)
  807. X                mtmp->cham = 0;
  808. X            else {
  809. X                mtmp->cham = 1;
  810. X                (void) newcham(mtmp, rndmonst());
  811. X            }
  812. X            break;
  813. X        case S_STALKER:
  814. X        case S_EEL:
  815. X            mtmp->minvis = 1;
  816. X            break;
  817. X        case S_LEPRECHAUN:
  818. X            mtmp->msleep = 1;
  819. X            break;
  820. X        case S_NYMPH:
  821. X            if(rn2(5) && !u.uhave_amulet) mtmp->msleep = 1;
  822. X            break;
  823. X        case S_UNICORN:
  824. X            if ((ptr==&mons[PM_WHITE_UNICORN] && 
  825. X                u.ualigntyp == U_LAWFUL) ||
  826. X            (ptr==&mons[PM_GREY_UNICORN] && 
  827. X                u.ualigntyp == U_NEUTRAL) ||
  828. X            (ptr==&mons[PM_BLACK_UNICORN] && 
  829. X                u.ualigntyp == U_CHAOTIC))
  830. X                mtmp->mpeaceful = 1;
  831. X            break;
  832. X    }
  833. X    if (ptr == &mons[PM_WIZARD_OF_YENDOR]) {
  834. X        mtmp->iswiz = 1;
  835. X        flags.no_of_wizards++;
  836. X    }
  837. X
  838. X    if(in_mklev) {
  839. X        if(((is_ndemon(ptr)) ||
  840. X            (ptr == &mons[PM_WUMPUS]) ||
  841. X#ifdef WORM
  842. X            (ptr == &mons[PM_LONG_WORM]) ||
  843. X#endif
  844. X            (ptr == &mons[PM_GIANT_EEL])) && rn2(5))
  845. X            mtmp->msleep = 1;
  846. X    } else {
  847. X        if(x == u.ux && y == u.uy && ptr->mlet != S_GHOST) {
  848. X            mnexto(mtmp);
  849. X            if (ptr->mlet == S_MIMIC) set_mimic_sym(mtmp);
  850. X        }
  851. X    }
  852. X#ifdef HARD
  853. X    if(is_dprince(ptr)) {
  854. X        mtmp->mpeaceful = mtmp->minvis = 1;
  855. X# ifdef NAMED_ITEMS
  856. X        if(uwep)
  857. X        if(!strcmp(ONAME(uwep), "Excalibur"))
  858. X            mtmp->mpeaceful = mtmp->mtame = 0;
  859. X# endif
  860. X    }
  861. X#endif
  862. X#ifdef WORM
  863. X    if(ptr == &mons[PM_LONG_WORM] && getwn(mtmp))  initworm(mtmp);
  864. X#endif
  865. X    set_malign(mtmp);        /* having finished peaceful changes */
  866. X    if(anything) {
  867. X        if((ptr->geno & G_SGROUP) && rn2(2))
  868. X        m_initsgrp(mtmp, mtmp->mx, mtmp->my);
  869. X        else if(ptr->geno & G_LGROUP) {
  870. X            if(rn2(3))  m_initlgrp(mtmp, mtmp->mx, mtmp->my);
  871. X            else        m_initsgrp(mtmp, mtmp->mx, mtmp->my);
  872. X        }
  873. X    }
  874. X
  875. X    if(is_armed(ptr))
  876. X        m_initweap(mtmp);    /* equip with weapons / armour */
  877. X    m_initinv(mtmp);        /* add on a few special items */
  878. X
  879. X    return(mtmp);
  880. X}
  881. X
  882. Xvoid
  883. Xenexto(cc, xx,yy)
  884. Xcoord *cc;
  885. Xregister xchar xx, yy;
  886. X{
  887. X    register xchar x,y;
  888. X    coord foo[15], *tfoo;
  889. X    int range, i;
  890. X
  891. X    tfoo = foo;
  892. X    range = 1;
  893. X    do {    /* full kludge action. */
  894. X        for(x = xx-range; x <= xx+range; x++)
  895. X            if(goodpos(x, yy-range)) {
  896. X                tfoo->x = x;
  897. X                (tfoo++)->y = yy-range;
  898. X                if(tfoo == &foo[15]) goto foofull;
  899. X            }
  900. X        for(x = xx-range; x <= xx+range; x++)
  901. X            if(goodpos(x,yy+range)) {
  902. X                tfoo->x = x;
  903. X                (tfoo++)->y = yy+range;
  904. X                if(tfoo == &foo[15]) goto foofull;
  905. X            }
  906. X        for(y = yy+1-range; y < yy+range; y++)
  907. X            if(goodpos(xx-range,y)) {
  908. X                tfoo->x = xx-range;
  909. X                (tfoo++)->y = y;
  910. X                if(tfoo == &foo[15]) goto foofull;
  911. X            }
  912. X        for(y = yy+1-range; y < yy+range; y++)
  913. X            if(goodpos(xx+range,y)) {
  914. X                tfoo->x = xx+range;
  915. X                (tfoo++)->y = y;
  916. X                if(tfoo == &foo[15]) goto foofull;
  917. X            }
  918. X        range++;
  919. X    } while(tfoo == foo);
  920. Xfoofull:
  921. X    i = rn2(tfoo - foo);
  922. X    cc->x = foo[i].x;
  923. X    cc->y = foo[i].y;
  924. X    return;
  925. X}
  926. X
  927. Xint
  928. Xgoodpos(x, y)
  929. X{
  930. X#ifdef STUPID
  931. X    if (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 ||
  932. X        levl[x][y].mmask || !ACCESSIBLE(levl[x][y].typ))
  933. X      return 0;
  934. X    if (IS_DOOR(levl[x][y].typ) &&
  935. X        (levl[x][y].doormask & (D_LOCKED | D_CLOSED)))
  936. X      return 0;
  937. X    return !((x == u.ux && y == u.uy) || sobj_at(BOULDER, x, y));
  938. X#else
  939. X    return
  940. X    ! (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 ||
  941. X       levl[x][y].mmask || !ACCESSIBLE(levl[x][y].typ) ||
  942. X       (IS_DOOR(levl[x][y].typ) && 
  943. X        (levl[x][y].doormask & (D_LOCKED | D_CLOSED)) )
  944. X       || (x == u.ux && y == u.uy)
  945. X       || sobj_at(BOULDER, x, y)
  946. X    );
  947. X#endif /* STUPID */
  948. X}
  949. X
  950. Xvoid
  951. Xrloc(mtmp)
  952. Xstruct monst *mtmp;
  953. X{
  954. X    register int tx, ty;
  955. X
  956. X#ifdef WORM        /* do not relocate worms */
  957. X    if(mtmp->wormno && mtmp->mx) return;
  958. X#endif
  959. X    /* if the wiz teleports away to heal, try the up staircase,
  960. X       to block the player's escaping before he's healed */
  961. X    if(!mtmp->iswiz || !goodpos(tx = xupstair, ty = yupstair))
  962. X       do {
  963. X        tx = rn1(COLNO-3,2);
  964. X        ty = rn2(ROWNO);
  965. X       } while(!goodpos(tx,ty));
  966. X    if(mtmp->mx != 0 && mtmp->my != 0)
  967. X        levl[mtmp->mx][mtmp->my].mmask = 0;
  968. X    mtmp->mx = tx;
  969. X    mtmp->my = ty;
  970. X    levl[tx][ty].mmask = 1;
  971. X    if(u.ustuck == mtmp){
  972. X        if(u.uswallow) {
  973. X            u.ux = tx;
  974. X            u.uy = ty;
  975. X            docrt();
  976. X        } else    u.ustuck = 0;
  977. X    }
  978. X    pmon(mtmp);
  979. X    set_apparxy(mtmp);
  980. X}
  981. X
  982. Xstruct monst *
  983. Xmkmon_at(name, x, y)
  984. Xchar *name;
  985. Xregister int x,y;
  986. X{
  987. X    register int ct;
  988. X    register struct permonst *ptr;
  989. X
  990. X    for(ct = PM_CHAMELEON; ct >= 0; ct--) { /* Chameleon is last monster */
  991. X        ptr = &mons[ct];
  992. X        if(!strcmp(ptr->mname, name))
  993. X            return(makemon(ptr, x, y));
  994. X    }
  995. X    return((struct monst *)0);
  996. X}
  997. X
  998. Xstatic int
  999. Xcmnum()    {    /* return the number of "common" monsters */
  1000. X
  1001. X    int    i, count;
  1002. X
  1003. X    for(i = count = 0; mons[i].mlet; i++)
  1004. X       if(!uncommon(&mons[i]))  count++;
  1005. X
  1006. X    return(count);
  1007. X}
  1008. X
  1009. Xstatic int
  1010. Xuncommon(ptr)
  1011. Xstruct    permonst *ptr;
  1012. X{
  1013. X    return (ptr->geno & (G_GENOD | G_NOGEN | G_UNIQ)) ||
  1014. X        (!Inhell ? ptr->geno & G_HELL : ptr->maligntyp > 0);
  1015. X}
  1016. X
  1017. X/* This routine is designed to return an integer value which represents
  1018. X * an approximation of monster strength.  It uses a similar method of
  1019. X * determination as "experience()" to arrive at the strength.
  1020. X */
  1021. Xstatic int
  1022. Xmstrength(ptr)
  1023. Xstruct permonst *ptr;
  1024. X{
  1025. X    int    i, tmp2, n, tmp = ptr->mlevel;
  1026. X
  1027. X     if(tmp > 49)        /* special fixed hp monster */
  1028. X        tmp = 2*(tmp - 6) / 4;
  1029. X
  1030. X/*    For creation in groups */
  1031. X    n = (!!(ptr->geno & G_SGROUP));
  1032. X    n += (!!(ptr->geno & G_LGROUP)) << 1;
  1033. X
  1034. X/*    For higher ac values */
  1035. X    n += (ptr->ac < 0);
  1036. X
  1037. X/*    For very fast monsters */
  1038. X    n += (ptr->mmove >= 18);
  1039. X
  1040. X/*    For each attack and "special" attack */
  1041. X    for(i = 0; i < NATTK; i++) {
  1042. X
  1043. X        tmp2 = ptr->mattk[i].aatyp;
  1044. X        n += (tmp2 > 0);
  1045. X        n += (tmp2 == AT_MAGC);
  1046. X    }
  1047. X
  1048. X/*    For each "special" damage type */
  1049. X    for(i = 0; i < NATTK; i++) {
  1050. X
  1051. X        tmp2 = ptr->mattk[i].adtyp;
  1052. X        if((tmp2 == AD_DRLI) || (tmp2 == AD_STON)) n += 2;
  1053. X        else n += (tmp2 != AD_PHYS);
  1054. X        n += ((ptr->mattk[i].damd * ptr->mattk[i].damn) > 23);
  1055. X    }
  1056. X
  1057. X/*    Finally, adjust the monster level  0 <= n <= 24 (approx.) */
  1058. X    if(n == 0) tmp--;
  1059. X    else if(n >= 6) tmp += ( n / 2 );
  1060. X    else tmp += ( n / 3 + 1);
  1061. X
  1062. X    return((tmp >= 0) ? tmp : 0);
  1063. X}
  1064. X
  1065. Xvoid
  1066. Xinit_monstr()
  1067. X{
  1068. X    register int ct;
  1069. X
  1070. X    for(ct = 0; mons[ct].mlet; ct++)
  1071. X        monstr[ct] = mstrength(&(mons[ct]));
  1072. X}
  1073. X
  1074. Xstruct    permonst *
  1075. Xrndmonst() {        /* select a random monster */
  1076. X    register struct permonst *ptr;
  1077. X    register int i, ct;
  1078. X    register int zlevel;
  1079. X    static int minmlev, maxmlev, accept;
  1080. X    static long oldmoves = 0L;    /* != 1, starting value of moves */
  1081. X
  1082. X    if(oldmoves != moves) {        /* must recalculate accept */
  1083. X        oldmoves = moves;
  1084. X        zlevel = u.uhave_amulet ? MAXLEVEL : dlevel;
  1085. X        if(cmnum() <= 0) {
  1086. X#ifdef DEBUG
  1087. X        pline("cmnum() fails!");
  1088. X#endif
  1089. X        return((struct permonst *) 0);
  1090. X        }
  1091. X
  1092. X        /* determine the level of the weakest monster to make. */
  1093. X        minmlev = zlevel/6;
  1094. X        /* determine the level of the strongest monster to make. */
  1095. X        maxmlev = (zlevel + u.ulevel)>>1;
  1096. X/*
  1097. X *    Find out how many monsters exist in the range we have selected.
  1098. X */
  1099. X        for(accept = ct = 0 ; mons[ct].mlet; ct++) {
  1100. X        ptr = &(mons[ct]);
  1101. X        if(uncommon(ptr)) continue;
  1102. X        if(tooweak(ct, minmlev) || toostrong(ct, maxmlev))
  1103. X            continue;
  1104. X        accept += (ptr->geno & G_FREQ);
  1105. X        }
  1106. X    }
  1107. X
  1108. X    if(!accept) {
  1109. X#ifdef DEBUG
  1110. X        pline("no accept!");
  1111. X#endif
  1112. X        return((struct permonst *) 0);
  1113. X    }
  1114. X/*
  1115. X *    Now, select a monster at random.
  1116. X */
  1117. X    ct = rnd(accept);
  1118. X    for(i = 0; mons[i].mlet && ct > 0; i++) {
  1119. X        ptr = &(mons[i]);
  1120. X        if(uncommon(ptr)) continue;
  1121. X        if(tooweak(i, minmlev) || toostrong(i, maxmlev))
  1122. X            continue;
  1123. X        ct -= (ptr->geno & G_FREQ);
  1124. X    }
  1125. X    if(ct > 0) {
  1126. X#ifdef DEBUG
  1127. X        pline("no count!");
  1128. X#endif
  1129. X        return((struct permonst *) 0);
  1130. X    }
  1131. X    return(ptr);
  1132. X}
  1133. X
  1134. X/*    The routine below is used to make one of the multiple types
  1135. X *    of a given monster class.  It will return 0 if no monsters
  1136. X *    in that class can be made.
  1137. X */
  1138. X
  1139. Xstruct permonst *
  1140. Xmkclass(mlet)
  1141. Xchar    mlet;
  1142. X{
  1143. X    register int    first, last, num = 0;
  1144. X
  1145. X    if(!mlet) {
  1146. X        impossible("mkclass called with null arg!");
  1147. X        return((struct permonst *) 0);
  1148. X    }
  1149. X/*    Assumption #1:    monsters of a given class are contiguous in the
  1150. X *            mons[] array.
  1151. X */
  1152. X    for(first = 0; mons[first].mlet != mlet; first++)
  1153. X        if(!mons[first].mlet)    return((struct permonst *) 0);
  1154. X
  1155. X    for(last = first; mons[last].mlet && mons[last].mlet == mlet; last++)
  1156. X        if(!(mons[last].geno & (G_GENOD | G_NOGEN | G_UNIQ)))
  1157. X        num += mons[last].geno & G_FREQ;
  1158. X
  1159. X    if(!num) return((struct permonst *) 0);
  1160. X
  1161. X/*    Assumption #2:    monsters of a given class are presented in ascending
  1162. X *            order of strength.
  1163. X */
  1164. X    for(num = rnd(num); num > 0; first++)
  1165. X        if(!(mons[first].geno & (G_GENOD | G_NOGEN | G_UNIQ))) { /* consider it */
  1166. X        /* skew towards lower value monsters at lower exp. levels */
  1167. X        if(adj_lev(&mons[first]) > (u.ulevel*2)) num--;
  1168. X        num -= mons[first].geno & G_FREQ;
  1169. X        }
  1170. X    first--; /* correct an off-by-one error */
  1171. X
  1172. X    return(&mons[first]);
  1173. X}
  1174. X
  1175. Xint
  1176. Xadj_lev(ptr)    /* adjust strength of monsters based on dlevel and u.ulevel */
  1177. Xregister struct permonst *ptr;
  1178. X{
  1179. X    int    tmp, tmp2;
  1180. X
  1181. X    if((tmp = ptr->mlevel) > 49) return(50); /* "special" demons/devils */
  1182. X    tmp2 = (dlevel - tmp);
  1183. X    if(tmp2 < 0) tmp--;        /* if mlevel > dlevel decrement tmp */
  1184. X    else tmp += (tmp2 / 5);        /* else increment 1 per five diff */
  1185. X
  1186. X    tmp2 = (u.ulevel - ptr->mlevel);    /* adjust vs. the player */
  1187. X    if(tmp2 > 0) tmp += (tmp2 / 4);        /* level as well */
  1188. X
  1189. X    tmp2 = 3 * ptr->mlevel/ 2;        /* crude upper limit */
  1190. X    return((tmp > tmp2) ? tmp2 : (tmp > 0 ? tmp : 0)); /* 0 lower limit */
  1191. X}
  1192. X
  1193. Xstruct permonst *
  1194. Xgrow_up(mtmp)        /* mon mtmp "grows up" to a bigger version. */
  1195. Xregister struct monst *mtmp;
  1196. X{
  1197. X    register int newtype;
  1198. X    register struct permonst *ptr = mtmp->data;
  1199. X
  1200. X    if (ptr->mlevel >= 50 || mtmp->mhpmax <= 8*mtmp->m_lev)
  1201. X        return ptr;
  1202. X    newtype = little_to_big(monsndx(ptr));
  1203. X    if (++mtmp->m_lev >= mons[newtype].mlevel) {
  1204. X        if (mons[newtype].geno & G_GENOD) {
  1205. X            pline("As %s grows up into a%s %s, %s dies!",
  1206. X                mon_nam(mtmp),
  1207. X                index(vowels,*mons[newtype].mname) ? "n" : "",
  1208. X                mons[newtype].mname,
  1209. X                mon_nam(mtmp));
  1210. X            mondied(mtmp);
  1211. X            return (struct permonst *)0;
  1212. X        }
  1213. X        mtmp->data = &mons[newtype];
  1214. X        mtmp->m_lev = mons[newtype].mlevel;
  1215. X    }
  1216. X    if (mtmp->m_lev > 3*mtmp->data->mlevel / 2)
  1217. X        mtmp->m_lev = 3*mtmp->data->mlevel / 2;
  1218. X    return(mtmp->data);
  1219. X}
  1220. X
  1221. Xint
  1222. Xmongets(mtmp, otyp)
  1223. Xregister struct monst *mtmp;
  1224. Xregister int otyp;
  1225. X{
  1226. X    register struct obj *otmp;
  1227. X
  1228. X    if((otmp = (otyp) ? mksobj(otyp,FALSE) : mkobj(otyp,FALSE))) {
  1229. X        if (mtmp->data->mlet == S_DEMON) {
  1230. X        /* demons always get cursed objects */
  1231. X        curse(otmp);
  1232. X        }
  1233. X        mpickobj(mtmp, otmp);
  1234. X        return(otmp->spe);        
  1235. X    } else return(0);
  1236. X}
  1237. X
  1238. X#ifdef REINCARNATION
  1239. Xstruct permonst *
  1240. Xroguemon()
  1241. X{
  1242. X/* Make a monster for a Rogue-like level; only capital letters.  There are
  1243. X * no checks for "too hard" or "too easy", though dragons are specifically
  1244. X * ruled out because playtesting showed they made the level too hard.
  1245. X * Modified from rndmonst().
  1246. X */
  1247. X#define isupper(x) ('A'<=(x) && (x)<='Z')
  1248. X    register struct permonst *ptr;
  1249. X    register int accept,ct,i;
  1250. X
  1251. X    /* See how many there are. */
  1252. X    accept = 0;
  1253. X    for(ct = PM_APE ; isupper(mons[ct].mlet); ct++) {
  1254. X        if (mons[ct].mlet == S_DRAGON) continue;
  1255. X        ptr = &(mons[ct]);
  1256. X        if(uncommon(ptr)) continue;
  1257. X        accept += (ptr->geno & G_FREQ);
  1258. X    }
  1259. X    if(!accept) return((struct permonst *) 0);
  1260. X
  1261. X    /* Now, select one at random. */
  1262. X    ct = rnd(accept);
  1263. X    for(i = PM_APE; isupper(mons[i].mlet) && ct > 0; i++) {
  1264. X        if (mons[i].mlet == S_DRAGON) continue;
  1265. X        ptr = &(mons[i]);
  1266. X        if(uncommon(ptr)) continue;
  1267. X        ct -= (ptr->geno & G_FREQ);
  1268. X    }
  1269. X    if(ct > 0) return((struct permonst *) 0);
  1270. X    return(ptr);
  1271. X}
  1272. X#endif
  1273. X
  1274. X#ifdef GOLEMS
  1275. Xint
  1276. Xgolemhp(type)
  1277. Xint type;
  1278. X{
  1279. X    switch(type) {
  1280. X        case PM_STRAW_GOLEM: return 20;
  1281. X        case PM_ROPE_GOLEM: return 30;
  1282. X        case PM_LEATHER_GOLEM: return 40;
  1283. X        case PM_WOOD_GOLEM: return 50;
  1284. X        case PM_FLESH_GOLEM: return 40;
  1285. X        case PM_CLAY_GOLEM: return 50;
  1286. X        case PM_STONE_GOLEM: return 60;
  1287. X        case PM_IRON_GOLEM: return 80;
  1288. X        default: return 0;
  1289. X    }
  1290. X}
  1291. X#endif /* GOLEMS */
  1292. X
  1293. X/*
  1294. X *    Alignment vs. yours determines monster's attitude to you.
  1295. X *    ( some "animal" types are co-aligned, but also hungry )
  1296. X */
  1297. Xboolean
  1298. Xpeace_minded(ptr)
  1299. Xregister struct permonst *ptr;
  1300. X{
  1301. X    schar mal = ptr->maligntyp, ual = u.ualigntyp;
  1302. X
  1303. X    if (always_peaceful(ptr)) return TRUE;
  1304. X    if (always_hostile(ptr)) return FALSE;
  1305. X
  1306. X    /* the monster is hostile if its alignment is different from the
  1307. X     * player's */
  1308. X    if (sgn(mal) != sgn(ual)) return FALSE;
  1309. X
  1310. X    /* Negative monster hostile to player with Amulet. */
  1311. X    if (mal < 0 && u.uhave_amulet) return FALSE;
  1312. X
  1313. X    /* Last case:  a chance of a co-aligned monster being
  1314. X     * hostile.  This chance is greater if the player has strayed
  1315. X     * (u.ualign negative) or the monster is not strongly aligned.
  1316. X     */
  1317. X    return !!rn2(16 + (u.ualign < -15 ? -15 : u.ualign)) &&
  1318. X        !!rn2(2 + abs(mal));
  1319. X}
  1320. X
  1321. X/* Set malign to have the proper effect on player alignment if monster is
  1322. X * killed.  Negative numbers mean it's bad to kill this monster; positive
  1323. X * numbers mean it's good.  Since there are more hostile monsters than
  1324. X * peaceful monsters, the penalty for killing a peaceful monster should be
  1325. X * greater than the bonus for killing a hostile monster to maintain balance.
  1326. X * Rules:
  1327. X *   it's bad to kill peaceful monsters, potentially worse to kill always-
  1328. X *    peaceful monsters
  1329. X *   it's never bad to kill a hostile monster, although it may not be good
  1330. X */
  1331. Xvoid
  1332. Xset_malign(mtmp)
  1333. Xstruct monst *mtmp;
  1334. X{
  1335. X    schar mal = mtmp->data->maligntyp;
  1336. X    boolean coaligned = (sgn(mal) == sgn(u.ualigntyp));
  1337. X
  1338. X    if (always_peaceful(mtmp->data))
  1339. X        mtmp->malign = -3*max(5,abs(mal));
  1340. X    else if (always_hostile(mtmp->data)) {
  1341. X        if (coaligned)
  1342. X            mtmp->malign = 0;
  1343. X        else
  1344. X            mtmp->malign = max(5,abs(mal));
  1345. X    } else if (coaligned) {
  1346. X        if (mtmp->mpeaceful)
  1347. X            mtmp->malign = -3*max(3,abs(mal));
  1348. X        else    /* renegade */
  1349. X            mtmp->malign = max(3,abs(mal));
  1350. X    } else    /* not coaligned and therefore hostile */
  1351. X        mtmp->malign = abs(mal);
  1352. X}
  1353. X
  1354. Xstatic char syms[] = { 0, 0, RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, GOLD_SYM,
  1355. X    SCROLL_SYM, POTION_SYM, ARMOR_SYM, AMULET_SYM, TOOL_SYM, ROCK_SYM,
  1356. X    GEM_SYM,
  1357. X#ifdef SPELLS
  1358. X    SPBOOK_SYM,
  1359. X#endif
  1360. X    S_MIMIC_DEF, S_MIMIC_DEF, S_MIMIC_DEF,
  1361. X};
  1362. X
  1363. Xvoid
  1364. Xset_mimic_sym(mtmp) /* KAA */
  1365. Xregister struct monst *mtmp;
  1366. X{
  1367. X    int roomno, rt;
  1368. X    char sym;
  1369. X    if (!mtmp) return;
  1370. X
  1371. X    syms[0] = UP_SYM;
  1372. X    syms[1] = DN_SYM;
  1373. X
  1374. X    mtmp->mimic = 1;
  1375. X    roomno = inroom(mtmp->mx, mtmp->my);
  1376. X    if (levl[mtmp->mx][mtmp->my].gmask)
  1377. X        sym = GOLD_SYM;
  1378. X    else if (levl[mtmp->mx][mtmp->my].omask)
  1379. X        sym = o_at(mtmp->mx,mtmp->my)->olet;
  1380. X    else if (IS_DOOR(levl[mtmp->mx][mtmp->my].typ) ||
  1381. X         IS_WALL(levl[mtmp->mx][mtmp->my].typ))
  1382. X        sym = DOOR_SYM;
  1383. X    else if (is_maze_lev)
  1384. X        sym = rn2(2) ? ROCK_SYM : syms[rn2(sizeof syms)];
  1385. X    else if (roomno < 0)
  1386. X        sym = ROCK_SYM;
  1387. X    else if ((rt = rooms[roomno].rtype) == ZOO || rt == VAULT)
  1388. X        sym = GOLD_SYM;
  1389. X#ifdef ORACLE
  1390. X    else if (rt == DELPHI)
  1391. X        sym = rn2(2) ? ROCK_SYM : FOUNTAIN_SYM;
  1392. X#endif
  1393. X#ifdef ALTARS
  1394. X    else if (rt == TEMPLE)
  1395. X        sym = ALTAR_SYM;
  1396. X#endif
  1397. X    /* We won't bother with beehives, morgues, barracks, throne rooms
  1398. X     * since they shouldn't contain mimics anyway...
  1399. X     */
  1400. X    else if (rt >= SHOPBASE) {
  1401. X        int s_sym = get_shop_item(rt - SHOPBASE);
  1402. X
  1403. X        if (s_sym < 0) sym = objects[-sym].oc_olet;
  1404. X        else if (sym == RANDOM_SYM)
  1405. X            sym = syms[rn2(sizeof(syms)-2) + 2];
  1406. X        else sym = s_sym;
  1407. X    } else sym = syms[rn2(sizeof syms)];
  1408. X    mtmp->mappearance = sym;
  1409. X}
  1410. END_OF_FILE
  1411. if test 28290 -ne `wc -c <'src/makemon.c'`; then
  1412.     echo shar: \"'src/makemon.c'\" unpacked with wrong size!
  1413. fi
  1414. # end of 'src/makemon.c'
  1415. fi
  1416. if test -f 'src/options.c' -a "${1}" != "-c" ; then 
  1417.   echo shar: Will not clobber existing file \"'src/options.c'\"
  1418. else
  1419. echo shar: Extracting \"'src/options.c'\" \(16326 characters\)
  1420. sed "s/^X//" >'src/options.c' <<'END_OF_FILE'
  1421. X/*    SCCS Id: @(#)options.c    3.0    88/11/09
  1422. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  1423. X/* NetHack may be freely redistributed.  See license for details. */
  1424. X
  1425. X#include "hack.h"
  1426. Xstatic boolean set_order;
  1427. X
  1428. Xstatic void nmcpy();
  1429. X
  1430. Xvoid
  1431. Xinitoptions()
  1432. X{
  1433. X    register char *opts;
  1434. X
  1435. X    flags.time = flags.nonews = flags.notombstone = flags.end_own =
  1436. X    flags.standout = flags.nonull = flags.ignintr = FALSE;
  1437. X    flags.no_rest_on_space = flags.invlet_constant = TRUE;
  1438. X    flags.end_top = 5;
  1439. X    flags.end_around = 4;
  1440. X    flags.female = FALSE;            /* players are usually male */
  1441. X    flags.sortpack = TRUE;
  1442. X    flags.soundok = TRUE;
  1443. X    flags.verbose = TRUE;
  1444. X    flags.confirm = TRUE;
  1445. X    flags.safe_dog = TRUE;
  1446. X    flags.silent =     flags.pickup = TRUE;
  1447. X    nmcpy(pl_fruit, objects[SLIME_MOLD].oc_name, PL_FSIZ);
  1448. X    flags.num_pad = FALSE;
  1449. X#ifdef MSDOS
  1450. X#ifdef DECRAINBOW
  1451. X    flags.DECRainbow = FALSE;
  1452. X#endif
  1453. X#ifdef DGK
  1454. X    flags.IBMBIOS =
  1455. X    flags.rawio = FALSE;
  1456. X#endif
  1457. X    read_config_file();
  1458. X#endif /* MSDOS */
  1459. X    if(opts = getenv("NETHACKOPTIONS"))
  1460. X        parseoptions(opts,TRUE);
  1461. X    (void)fruitadd(pl_fruit);
  1462. X    objects[SLIME_MOLD].oc_name = "\033";
  1463. X    /* Put something untypable in there */
  1464. X    /* We cannot just use NULL because that marks the end of objects */
  1465. X}
  1466. X
  1467. Xstatic void
  1468. Xnmcpy(dest, source, maxlen)
  1469. X    char    *dest, *source;
  1470. X    int    maxlen;
  1471. X{
  1472. X    char    *cs, *cd;
  1473. X    int    count;
  1474. X
  1475. X    cd = dest;
  1476. X    cs = source;
  1477. X    for(count = 1; count < maxlen; count++) {
  1478. X        if(*cs == ',' || *cs == '\0') break; /*exit on \0 terminator*/
  1479. X        *cd++ = *cs++;
  1480. X    }
  1481. X    *cd = 0;
  1482. X}
  1483. X
  1484. X/*
  1485. X * escapes: escape expansion for showsyms. C-style escapes understood include
  1486. X * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). The ^-prefix
  1487. X * for control characters is also understood, and \[mM] followed by any of the
  1488. X * previous forms or by a character has the effect of 'meta'-ing the value (so
  1489. X * that the alternate character set will be enabled).
  1490. X */
  1491. Xvoid
  1492. Xescapes(cp, tp)
  1493. Xchar    *cp, *tp;
  1494. X{
  1495. X    while (*cp)
  1496. X    {
  1497. X    int    cval = 0, meta = 0;
  1498. X
  1499. X    if (*cp == '\\' && index("mM", cp[1])) {
  1500. X        meta = 1;
  1501. X        cp += 2;
  1502. X    }
  1503. X    if (*cp == '\\' && index("0123456789xXoO", cp[1]))
  1504. X    {
  1505. X        char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
  1506. X        int dcount = 0;
  1507. X
  1508. X        cp++;
  1509. X        if (*cp == 'x' || *cp == 'X')
  1510. X        for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
  1511. X            cval = (cval * 16) + (dp - hex) / 2;
  1512. X        else if (*cp == 'o' || *cp == 'O')
  1513. X        for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++)
  1514. X            cval = (cval * 8) + (*cp - '0');
  1515. X        else
  1516. X        for (; (index("0123456789",*cp)) && (dcount++ < 3); cp++)
  1517. X            cval = (cval * 10) + (*cp - '0');
  1518. X    }
  1519. X    else if (*cp == '\\')        /* C-style character escapes */
  1520. X    {
  1521. X        switch (*++cp)
  1522. X        {
  1523. X        case '\\': cval = '\\'; break;
  1524. X        case 'n': cval = '\n'; break;
  1525. X        case 't': cval = '\t'; break;
  1526. X        case 'b': cval = '\b'; break;
  1527. X        case 'r': cval = '\r'; break;
  1528. X        default: cval = *cp;
  1529. X        }
  1530. X        cp++;
  1531. X    }
  1532. X    else if (*cp == '^')        /* expand control-character syntax */
  1533. X    {
  1534. X        cval = (*++cp & 0x1f);
  1535. X        cp++;
  1536. X    }
  1537. X    else
  1538. X        cval = *cp++;
  1539. X    if (meta)
  1540. X        cval |= 0x80;
  1541. X    *tp++ = cval;
  1542. X    }
  1543. X    *tp = '\0';
  1544. X}
  1545. X
  1546. Xvoid
  1547. Xparseoptions(opts, from_env)
  1548. Xregister char *opts;
  1549. Xboolean from_env;
  1550. X{
  1551. X    register char *op;
  1552. X/*
  1553. X    register char *op2;
  1554. X*/
  1555. X    unsigned num;
  1556. X    boolean negated;
  1557. X
  1558. X    if(op = index(opts, ',')) {
  1559. X        *op++ = 0;
  1560. X        parseoptions(op, from_env);
  1561. X    }
  1562. X/*
  1563. X    if(op = index(opts, ' ')) {
  1564. X        op2 = op;
  1565. X        while(*op++)
  1566. X            if(*op != ' ') *op2++ = *op;
  1567. X    }
  1568. X*/
  1569. X    if(!*opts) return;
  1570. X    negated = FALSE;
  1571. X    while((*opts == '!') || !strncmp(opts, "no", 2)) {
  1572. X        if(*opts == '!') opts++; else opts += 2;
  1573. X        negated = !negated;
  1574. X    }
  1575. X    
  1576. X#ifndef MSDOS
  1577. X    if (!strncmp(opts, "standout", 4)) {
  1578. X        flags.standout = !negated;
  1579. X        return;
  1580. X    }
  1581. X
  1582. X    if (!strncmp(opts, "null", 4)) {
  1583. X        flags.nonull = negated;
  1584. X        return;
  1585. X    }
  1586. X#endif
  1587. X
  1588. X    if (!strncmp(opts, "ignintr", 3)) {
  1589. X        flags.ignintr = !negated;
  1590. X        return;
  1591. X    }
  1592. X
  1593. X    if (!strncmp(opts, "tombstone", 4)) {
  1594. X        flags.notombstone = negated;
  1595. X        return;
  1596. X    }
  1597. X
  1598. X#ifdef NEWS
  1599. X    if (!strncmp(opts, "news", 4)) {
  1600. X        flags.nonews = negated;
  1601. X        return;
  1602. X    }
  1603. X#endif
  1604. X
  1605. X    if (!strncmp(opts, "confirm", 4)) {
  1606. X        flags.confirm = !negated;
  1607. X        return;
  1608. X    }
  1609. X    if (!strncmp(opts, "safe", 4)) {
  1610. X        flags.safe_dog = !negated;
  1611. X        return;
  1612. X    }
  1613. X
  1614. X    if (!strncmp(opts, "silent", 4)) {
  1615. X        flags.silent = !negated;
  1616. X        return;
  1617. X    }
  1618. X
  1619. X    if (!strncmp(opts, "verbose", 4)) {
  1620. X        flags.verbose = !negated;
  1621. X        return;
  1622. X    }
  1623. X
  1624. X    if (!strncmp(opts, "pickup", 4)) {
  1625. X        flags.pickup = !negated;
  1626. X        return;
  1627. X    }
  1628. X
  1629. X    if (!strncmp(opts, "number_pad", 4)) {
  1630. X        flags.num_pad = !negated;
  1631. X        return;
  1632. X    }
  1633. X
  1634. X#ifdef DGK
  1635. X    if (!strncmp(opts, "IBM", 3)) {
  1636. X        flags.IBMBIOS = !negated;
  1637. X        return;
  1638. X    }
  1639. X
  1640. X    if (!strncmp(opts, "rawio", 4)) {
  1641. X        if (from_env)
  1642. X            flags.rawio = !negated;
  1643. X        else
  1644. X            pline("\"rawio\" settable only from %s.", configfile);
  1645. X        return;
  1646. X    }
  1647. X
  1648. X#ifdef DECRAINBOW
  1649. X    if (!strncmp(opts, "DEC", 3)) {
  1650. X        flags.DECRainbow = !negated;
  1651. X        return;
  1652. X    }
  1653. X#endif /* DECRAINBOW */
  1654. X#endif
  1655. X
  1656. X    if (!strncmp(opts, "sort", 4)) {
  1657. X        flags.sortpack = !negated;
  1658. X        return;
  1659. X    }
  1660. X
  1661. X    /*
  1662. X     * the order to list the pack
  1663. X     */
  1664. X    if (!strncmp(opts, "packorder", 4)) {
  1665. X        register char    *sp, *tmp;
  1666. X        int tmpend;
  1667. X
  1668. X        op = index(opts,':');
  1669. X        if(!op) goto bad;
  1670. X        op++;            /* skip : */
  1671. X
  1672. X        /* Missing characters in new order are filled in at the end 
  1673. X         * from inv_order.
  1674. X         */
  1675. X        for (sp = op; *sp; sp++)
  1676. X            if (!index(inv_order, *sp))
  1677. X                goto bad;        /* bad char in order */
  1678. X            else if (index(sp + 1, *sp))
  1679. X                goto bad;        /* dup char in order */
  1680. X        tmp = (char *) alloc((unsigned)(strlen(inv_order)+1));
  1681. X        Strcpy(tmp, op);
  1682. X        for (sp = inv_order, tmpend = strlen(tmp); *sp; sp++)
  1683. X            if (!index(tmp, *sp)) {
  1684. X                tmp[tmpend++] = *sp;
  1685. X                tmp[tmpend] = 0;
  1686. X            }
  1687. X        Strcpy(inv_order, tmp);
  1688. X        free((genericptr_t)tmp);
  1689. X        set_order = TRUE;
  1690. X        return;
  1691. X    }
  1692. X
  1693. X    if (!strncmp(opts, "time", 4)) {
  1694. X        flags.time = !negated;
  1695. X        flags.botl = 1;
  1696. X        return;
  1697. X    }
  1698. X
  1699. X    if (!strncmp(opts, "rest_on_space", 4)) {
  1700. X        flags.no_rest_on_space = negated;
  1701. X        return;
  1702. X    }
  1703. X
  1704. X    if (!strncmp(opts, "fixinv", 3)) {
  1705. X        flags.invlet_constant = !negated;
  1706. X        if(!from_env && flags.invlet_constant) reassign ();
  1707. X        return;
  1708. X    }
  1709. X
  1710. X    if (!strncmp(opts, "male", 4)) {
  1711. X        if(!from_env && flags.female != negated)
  1712. X            pline("That is not anatomically possible.");
  1713. X        else
  1714. X            flags.female = negated;
  1715. X        return;
  1716. X    }
  1717. X    if (!strncmp(opts, "female", 3)) {
  1718. X        if(!from_env && flags.female == negated)
  1719. X            pline("That is not anatomically possible.");
  1720. X        else
  1721. X            flags.female = !negated;
  1722. X        return;
  1723. X    }
  1724. X
  1725. X    /* name:string */
  1726. X    if (!strncmp(opts, "name", 4)) {
  1727. X        if(!from_env) {
  1728. X#ifdef MSDOS
  1729. X          pline("\"name\" settable only from %s.", configfile);
  1730. X#else
  1731. X          pline("The playername can be set only from NETHACKOPTIONS.");
  1732. X#endif
  1733. X          return;
  1734. X        }
  1735. X        op = index(opts,':');
  1736. X        if(!op) goto bad;
  1737. X        nmcpy(plname, op+1, sizeof(plname)-1);
  1738. X        return;
  1739. X    }
  1740. X
  1741. X    /* graphics:string */
  1742. X    if (!strncmp(opts, "graphics", 4)) {
  1743. X        if(!from_env) {
  1744. X#ifdef MSDOS
  1745. X          pline("\"graphics\" settable only from %s.", configfile);
  1746. X#else
  1747. X          pline("The graphics string can be set only from NETHACKOPTIONS.");
  1748. X#endif
  1749. X          return;
  1750. X        }
  1751. X        op = index(opts,':');
  1752. X        if(!op)
  1753. X            goto bad;
  1754. X        else
  1755. X            opts = op + 1;
  1756. X        escapes(opts, opts);
  1757. X#define SETPCHAR(f, n)    showsyms.f = (strlen(opts) > n) ? opts[n] : defsyms.f
  1758. X        SETPCHAR(stone, 0);
  1759. X        SETPCHAR(vwall, 1);
  1760. X        SETPCHAR(hwall, 2);
  1761. X        SETPCHAR(tlcorn, 3);
  1762. X        SETPCHAR(trcorn, 4);
  1763. X        SETPCHAR(blcorn, 5);
  1764. X        SETPCHAR(brcorn, 6);
  1765. X        SETPCHAR(crwall, 7);
  1766. X        SETPCHAR(tuwall, 8);
  1767. X        SETPCHAR(tdwall, 9);
  1768. X        SETPCHAR(tlwall, 10);
  1769. X        SETPCHAR(trwall, 11);
  1770. X        SETPCHAR(vbeam, 12);
  1771. X        SETPCHAR(hbeam, 13);
  1772. X        SETPCHAR(lslant, 14);
  1773. X        SETPCHAR(rslant, 15);
  1774. X        SETPCHAR(door, 16);
  1775. X        SETPCHAR(room, 17);
  1776. X        SETPCHAR(corr, 18);
  1777. X        SETPCHAR(upstair, 19);
  1778. X        SETPCHAR(dnstair, 20);
  1779. X        SETPCHAR(trap, 21);
  1780. X        SETPCHAR(web, 22);
  1781. X        SETPCHAR(pool, 23);
  1782. X#ifdef FOUNTAINS
  1783. X        SETPCHAR(fountain, 24);
  1784. X#endif
  1785. X#ifdef SINKS
  1786. X        SETPCHAR(sink, 25);
  1787. X#endif
  1788. X#ifdef THRONES
  1789. X        SETPCHAR(throne, 26);
  1790. X#endif
  1791. X#ifdef ALTARS
  1792. X        SETPCHAR(altar, 27);
  1793. X#endif
  1794. X#ifdef STRONGHOLD
  1795. X        SETPCHAR(upladder, 28);
  1796. X        SETPCHAR(dnladder, 29);
  1797. X        SETPCHAR(dbvwall, 30);
  1798. X        SETPCHAR(dbhwall, 31);
  1799. X#endif
  1800. X#undef SETPCHAR
  1801. X        return;
  1802. X    }
  1803. X
  1804. X    /* endgame:5t[op] 5a[round] o[wn] */
  1805. X    if (!strncmp(opts, "endgame", 3)) {
  1806. X        op = index(opts,':');
  1807. X        if(!op) goto bad;
  1808. X        op++;
  1809. X        while(*op) {
  1810. X            num = 1;
  1811. X            if(digit(*op)) {
  1812. X                num = atoi(op);
  1813. X                while(digit(*op)) op++;
  1814. X            } else
  1815. X            if(*op == '!') {
  1816. X                negated = !negated;
  1817. X                op++;
  1818. X            }
  1819. X            switch(*op) {
  1820. X            case 't':
  1821. X                flags.end_top = num;
  1822. X                break;
  1823. X            case 'a':
  1824. X                flags.end_around = num;
  1825. X                break;
  1826. X            case 'o':
  1827. X                flags.end_own = !negated;
  1828. X                break;
  1829. X            default:
  1830. X                goto bad;
  1831. X            }
  1832. X            while(letter(*++op)) ;
  1833. X            if(*op == '/') op++;
  1834. X        }
  1835. X        return;
  1836. X    }
  1837. X    if (!strncmp(opts, "dogname", 3)) {
  1838. X        if(!from_env) {
  1839. X#ifdef MSDOS
  1840. X          pline("\"dogname\" settable only from %s.", configfile);
  1841. X#else
  1842. X          Your("dog's name can be set only from NETHACKOPTIONS.");
  1843. X#endif
  1844. X          return;
  1845. X        }
  1846. X        op = index(opts, ':');
  1847. X        if (!op) goto bad;
  1848. X        nmcpy(dogname, ++op, 62);
  1849. X        return;
  1850. X    }
  1851. X    if (!strncmp(opts, "catname", 3)) {
  1852. X        if(!from_env) {
  1853. X#ifdef MSDOS
  1854. X          pline("\"catname\" settable only from %s.", configfile);
  1855. X#else
  1856. X          Your("cat's name can be set only from NETHACKOPTIONS.");
  1857. X#endif
  1858. X          return;
  1859. X        }
  1860. X        op = index(opts, ':');
  1861. X        if (!op) goto bad;
  1862. X        nmcpy(catname, ++op, 62);
  1863. X        return;
  1864. X    }
  1865. X    if (!strncmp(opts, "fruit", 2)) {
  1866. X        op = index(opts, ':');
  1867. X        if (!op++) goto bad;
  1868. X        if (!from_env) {
  1869. X            struct fruit *f;
  1870. X            int numfruits = 0;
  1871. X
  1872. X            for(f=ffruit; f; f=f->nextf) {
  1873. X            if (!strcmp(op, f->fname)) goto goodfruit;
  1874. X            numfruits++;
  1875. X            }
  1876. X            if (numfruits >= 100) {
  1877. X            pline("Doing that so many times isn't very fruitful.");
  1878. X            return;
  1879. X            }
  1880. X        }
  1881. Xgoodfruit:
  1882. X        nmcpy(pl_fruit, op, PL_FSIZ);
  1883. X        if (!from_env)
  1884. X            (void)fruitadd(pl_fruit);
  1885. X        /* If from_env, then initoptions is allowed to do it instead
  1886. X         * of here (initoptions always has to do it even if there's
  1887. X         * no fruit option at all.  Also, we don't want people
  1888. X         * setting multiple fruits in their options.)
  1889. X         */
  1890. X        return;
  1891. X    }
  1892. Xbad:
  1893. X    if(!from_env) {
  1894. X        if(!strncmp(opts, "h", 1) ||
  1895. X           !strncmp(opts, "?", 1)) {
  1896. X            option_help();
  1897. X            return;
  1898. X        }
  1899. X        pline("Unknown option: %s.  Enter \"O?\" for help.", opts);
  1900. X        return;
  1901. X    }
  1902. X#ifdef MSDOS
  1903. X    Printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts);
  1904. X#else
  1905. X    Printf("Bad syntax in NETHACKOPTIONS: %s.", opts);
  1906. X    (void) puts("Use for example:");
  1907. X    (void) puts(
  1908. X"NETHACKOPTIONS=\"!rest_on_space,notombstone,endgame:own/5 topscorers/4 around me\""
  1909. X    );
  1910. X#endif
  1911. X    getret();
  1912. X}
  1913. X
  1914. Xint
  1915. Xdoset()
  1916. X{
  1917. X    char buf[BUFSZ];
  1918. X
  1919. X    pline("What options do you want to set? ");
  1920. X    getlin(buf);
  1921. X    if(!buf[0] || buf[0] == '\033') {
  1922. X#ifdef MSDOS
  1923. X        Strcpy(buf,"OPTIONS=");
  1924. X#ifdef DGK
  1925. X        if (flags.rawio) Strcat(buf,"rawio,");
  1926. X        if (flags.IBMBIOS) Strcat(buf,"IBM_BIOS,");
  1927. X#endif /* DGK */
  1928. X#ifdef DECRAINBOW
  1929. X        if (flags.DECRainbow) Strcat(buf,"DEC_Rainbow,");
  1930. X#endif /* DECRAINBOW */
  1931. X#else /* MSDOS */
  1932. X        Strcpy(buf,"NETHACKOPTIONS=");
  1933. X        if(flags.standout) Strcat(buf,"standout,");
  1934. X        if(flags.nonull) Strcat(buf,"nonull,");
  1935. X#endif /* MSDOS */
  1936. X        if(flags.ignintr) Strcat(buf,"ignintr,");
  1937. X        if(flags.num_pad) Strcat(buf,"number_pad,");
  1938. X#ifdef NEWS
  1939. X        if(flags.nonews) Strcat(buf,"nonews,");
  1940. X#endif
  1941. X        if(flags.notombstone) Strcat(buf,"notombstone,");
  1942. X        Strcat(buf, flags.female ? "female," : "male,");
  1943. X        if(flags.no_rest_on_space)    Strcat(buf,"!rest_on_space,");
  1944. X        if (flags.invlet_constant) Strcat(buf,"fixinv,");
  1945. X        if (flags.sortpack) Strcat(buf,"sortpack,");
  1946. X        if (set_order){
  1947. X        Strcat(buf, "packorder: ");
  1948. X        Strcat(buf, inv_order);
  1949. X        Strcat(buf, ",");
  1950. X        }
  1951. X        if (flags.confirm) Strcat(buf,"confirm,");
  1952. X        if (flags.safe_dog) Strcat(buf,"safe_pet,");
  1953. X        if (flags.pickup) Strcat(buf,"pickup,");
  1954. X        if (flags.silent) Strcat(buf,"silent,");
  1955. X        if (flags.time) Strcat(buf,"time,");
  1956. X        if (flags.verbose) Strcat(buf,"verbose,");
  1957. X        Sprintf(eos(buf), "fruit:%s,", pl_fruit);
  1958. X        if(flags.end_top != 5 || flags.end_around != 4 || flags.end_own){
  1959. X        Sprintf(eos(buf), "endgame: %u top scores/%u around me",
  1960. X            flags.end_top, flags.end_around);
  1961. X        if(flags.end_own) Strcat(buf, "/own scores");
  1962. X        } else {
  1963. X        register char *eop = eos(buf);
  1964. X        if(*--eop == ',') *eop = 0;
  1965. X        }
  1966. X        pline(buf);
  1967. X    } else {
  1968. X        clrlin();
  1969. X        parseoptions(buf, FALSE);
  1970. X    }
  1971. X
  1972. X    return 0;
  1973. X}
  1974. X
  1975. Xint
  1976. Xdotogglepickup() {
  1977. X    flags.pickup = !flags.pickup;
  1978. X    pline("Pickup: %s.", flags.pickup ? "ON" : "OFF");
  1979. X    return 0;
  1980. X}
  1981. X
  1982. Xchar    packorder[] =    {
  1983. X    AMULET_SYM, WEAPON_SYM, ARMOR_SYM, FOOD_SYM, SCROLL_SYM,
  1984. X# ifdef SPELLS
  1985. X    SPBOOK_SYM,
  1986. X# endif
  1987. X    WAND_SYM, RING_SYM, POTION_SYM, TOOL_SYM, GEM_SYM, BALL_SYM, ROCK_SYM };
  1988. X#define Page_line(x)    if(page_line(x)) goto quit
  1989. X
  1990. Xvoid
  1991. Xoption_help() {
  1992. X    char    buf[BUFSZ];
  1993. X
  1994. X    set_pager(0);
  1995. X    Sprintf(buf, "                 NetHack Options Help:");
  1996. X    if(page_line("") || page_line(buf) || page_line(""))     goto quit;
  1997. X
  1998. X#ifdef MSDOS
  1999. X    Sprintf(buf, "To set options use OPTIONS=<options> in %s;", configfile);
  2000. X    Page_line(buf);
  2001. X#else
  2002. X    Page_line("To set options use `NETHACKOPTIONS=\"<options>\"' in your environment;");
  2003. X#endif
  2004. X
  2005. X    Page_line("or press \"O\" while playing, and type your <options> at the prompt.");
  2006. X    Page_line("In either case, <options> is a list of options separated by commas.");
  2007. X    Page_line("");
  2008. X
  2009. X    Page_line("Boolean options (which can be negated by prefixing them with '!' or \"no\"):");
  2010. X    Page_line("confirm, (fe)male, fixinv, pickup, rest_on_space, safe_pet, silent, sortpack,");
  2011. X#ifdef MSDOS
  2012. X#ifdef NEWS
  2013. X    Page_line("time, tombstone, verbose, news, number_pad, rawio, and IBM_BIOS");
  2014. X#else
  2015. X    Page_line("time, tombstone, verbose, number_pad, rawio, and IBM_BIOS");
  2016. X#endif
  2017. X#ifdef DECRAINBOW
  2018. X    Page_line("and DEC_Rainbow.");
  2019. X#endif /* DECRAINBOW */
  2020. X#else /* MSDOS */
  2021. X#ifdef NEWS
  2022. X    Page_line("time, tombstone, verbose, news, null, ignintr, and standout.");
  2023. X#else
  2024. X    Page_line("time, tombstone, verbose, null, ignintr, and standout.");
  2025. X#endif
  2026. X#endif /* MSDOS */
  2027. X    Page_line("");
  2028. X
  2029. X    Page_line("Compound options:");
  2030. X    Page_line("`name'      - your character's name (e.g., name:Merlin-W),");
  2031. X    Page_line("`dogname'   - the name of your (first) dog (e.g., dogname:Fang),");
  2032. X
  2033. X    Page_line("`packorder' - the inventory order of the items in your pack");
  2034. X    Sprintf(buf, "              (currently, packorder:%s ),", packorder);
  2035. X    Page_line(buf);
  2036. X    Page_line("`fruit'     - the name of a fruit you enjoy eating,");
  2037. X
  2038. X    Page_line("`endgame'   - the parts of the score list you wish to see,");
  2039. X
  2040. X    Page_line("`graphics'  - defines the symbols to use in drawing the dungeon map.");
  2041. X    Page_line("");
  2042. X    Page_line("Some of the options can be set only before the game is started.  You will");
  2043. X    Page_line("be so informed, if you attempt to set them while in the game.");
  2044. X    set_pager(1);
  2045. X    return;
  2046. Xquit:
  2047. X    set_pager(2);
  2048. X    return;
  2049. X}
  2050. X
  2051. X/* Returns the fid of the fruit type; if that type already exists, it
  2052. X * returns the fid of that one; if it does not exist, it adds a new fruit
  2053. X * type to the chain and returns the new one.
  2054. X */
  2055. Xint
  2056. Xfruitadd(str)
  2057. Xchar *str;
  2058. X{
  2059. X    register int i,j;
  2060. X    register struct fruit *f;
  2061. X    struct fruit *lastf;
  2062. X    int highest_fruit_id = 0;
  2063. X    char buf[PL_FSIZ];
  2064. X    boolean user_specified = (str == pl_fruit);
  2065. X    /* if not user-specified, then it's a fruit name for a fruit on
  2066. X     * a bones level...
  2067. X     */
  2068. X
  2069. X    /* Note: every fruit has an id (spe for fruit objects) of at least
  2070. X     * 1; 0 is an error.
  2071. X     */
  2072. X    if (user_specified) {
  2073. X        /* disallow naming after other foods (since it'd be impossible
  2074. X         * to tell the difference)
  2075. X         */
  2076. X
  2077. X        boolean found = FALSE;
  2078. X
  2079. X        for(i = bases[j=letindex(FOOD_SYM)]; i < bases[j+1]; i++) {
  2080. X            if (!strcmp(objects[i].oc_name, pl_fruit)) {
  2081. X                found = TRUE;
  2082. X                break;
  2083. X            }
  2084. X        }
  2085. X        if (found ||
  2086. X            (!strncmp(buf, "tin of ", 7) && name_to_mon(buf+7) > -1) ||
  2087. X            !strcmp(buf, "empty tin") ||
  2088. X            !strcmp(buf, "tin of spinach") ||
  2089. X            (!strncmp(eos(buf)-6," corpse",6) && name_to_mon(buf) > -1))
  2090. X            {
  2091. X                Strcpy(buf, pl_fruit);
  2092. X                Strcpy(pl_fruit, "candied ");
  2093. X                nmcpy(pl_fruit+8, buf, PL_FSIZ-8);
  2094. X        }
  2095. X    }
  2096. X    for(f=ffruit; f; f = f->nextf) {
  2097. X        lastf = f;
  2098. X        if(f->fid > highest_fruit_id) highest_fruit_id = f->fid;
  2099. X        if(!strncmp(str, f->fname, PL_FSIZ))
  2100. X            goto nonew;
  2101. X    }
  2102. X    /* if adding another fruit would overflow spe, use a random
  2103. X       fruit instead... we've got a lot to choose from. */
  2104. X    if (highest_fruit_id >= 127) return rnd(127);
  2105. X    highest_fruit_id++;
  2106. X    f = newfruit();
  2107. X    if (ffruit) lastf->nextf = f;
  2108. X    else ffruit = f;
  2109. X    Strcpy(f->fname, str);
  2110. X    f->fid = highest_fruit_id;
  2111. X    f->nextf = 0;
  2112. Xnonew:
  2113. X    if (user_specified) current_fruit = highest_fruit_id;
  2114. X    return f->fid;
  2115. X}
  2116. END_OF_FILE
  2117. if test 16326 -ne `wc -c <'src/options.c'`; then
  2118.     echo shar: \"'src/options.c'\" unpacked with wrong size!
  2119. fi
  2120. # end of 'src/options.c'
  2121. fi
  2122. echo shar: End of archive 18 \(of 38\).
  2123. cp /dev/null ark18isdone
  2124. MISSING=""
  2125. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ; do
  2126.     if test ! -f ark${I}isdone ; then
  2127.     MISSING="${MISSING} ${I}"
  2128.     fi
  2129. done
  2130. if test "${MISSING}" = "" ; then
  2131.     echo You have unpacked all 38 archives.
  2132.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2133. else
  2134.     echo You still need to unpack the following archives:
  2135.     echo "        " ${MISSING}
  2136. fi
  2137. ##  End of shell archive.
  2138. exit 0
  2139.