billr@saab.CNA.TEK.COM (Bill Randle) (07/24/89)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu> Posting-number: Volume 7, Issue 73 Archive-name: NetHack3/Part18 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 18 (of 38)." # Contents: src/artifact.c src/makemon.c src/options.c # Wrapped by billr@saab on Sun Jul 23 21:33:01 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'src/artifact.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/artifact.c'\" else echo shar: Extracting \"'src/artifact.c'\" \(6525 characters\) sed "s/^X//" >'src/artifact.c' <<'END_OF_FILE' X/* SCCS Id: @(#)artifact.c 3.0 88/07/27 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" X X#ifdef NAMED_ITEMS X X#include "artifact.h" X X/* the artifacts (currently weapons only) */ Xstatic const struct artifact artilist[] = { X X#define NO_ATTK 0, 0, 0, 0 X X{ LONG_SWORD, "Excalibur", (SPFX_NOGEN | SPFX_SEEK | SPFX_DEFN | X SPFX_SEARCH), 0, X { 0, AD_PHYS, 5, 10 }, { 0, AD_DRLI, 0, 0} }, X X{ KATANA, "Snickersnee", SPFX_RESTR, 0, X { 0, AD_PHYS, 0, 8 }, NO_ATTK }, X X/* Ah, never shall I forget the cry, X * or the shriek that shrieked he, X * As I gnashed my teeth, and from my sheath X * I drew my Snickersnee! X * X * --Koko, Lord high executioner of Titipu X * (From Sir W.S. Gilbert's "The Mikado") X */ X X{ AXE, "Cleaver", SPFX_RESTR, 0, X { 0, AD_PHYS, 3, 12 }, NO_ATTK }, X X/* Special purpose swords - various types */ X X{ TWO_HANDED_SWORD, "Orcrist", SPFX_DCLAS, S_ORC, X { 0, AD_PHYS, 5, 0 }, NO_ATTK }, X X#ifdef TOLKIEN X{ ELVEN_DAGGER, "Sting", (SPFX_WARN | SPFX_DCLAS), S_ORC, X { 0, AD_PHYS, 5, 0 }, NO_ATTK }, X#else X{ DAGGER, "Sting", (SPFX_WARN | SPFX_DCLAS), S_ORC, X { 0, AD_PHYS, 5, 0 }, NO_ATTK }, X#endif X X{ LONG_SWORD, "Frost Brand", (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN), 0, X { 0, AD_COLD, 5, 0 }, { 0, AD_COLD, 0, 0 } }, X X{ LONG_SWORD, "Fire Brand", (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN), 0, X { 0, AD_FIRE, 5, 0 }, { 0, AD_FIRE, 0, 0 } }, X X/* Stormbringer only has a 2 because it can drain a level, providing 8 more */ X{ BROADSWORD, "Stormbringer", (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN | X SPFX_DRLI), 0, X { 0, AD_DRLI, 5, 2 }, { 0, AD_DRLI, 0, 0 } }, X X{ LONG_SWORD, "Sunsword", (SPFX_RESTR | SPFX_DCLAS), 0, /* undead */ X { 0, AD_PHYS, 5, 0 }, NO_ATTK }, X X{ BROADSWORD, "Dragonbane", (SPFX_RESTR | SPFX_DCLAS), S_DRAGON, X { 0, AD_PHYS, 5, 0 }, NO_ATTK }, X X{ LONG_SWORD, "Demonbane", (SPFX_RESTR | SPFX_DCLAS), 0, /* demons */ X { 0, AD_PHYS, 5, 0 }, NO_ATTK }, X X{ LONG_SWORD, "Werebane", (SPFX_RESTR | SPFX_DCLAS), 0, /* weres */ X { 0, AD_PHYS, 5, 0 }, NO_ATTK }, X X{ LONG_SWORD, "Giantslayer", (SPFX_RESTR | SPFX_DCLAS), 0, /* giants */ X { 0, AD_PHYS, 5, 0 }, NO_ATTK }, X X{ LUCERN_HAMMER, "Ogresmasher", (SPFX_RESTR | SPFX_DCLAS), S_OGRE, X { 0, AD_PHYS, 5, 0 }, NO_ATTK }, X X{ LUCERN_HAMMER, "Thunderfist", (SPFX_RESTR | SPFX_ATTK), 0, X { 0, AD_ELEC, 5, 24 }, NO_ATTK }, X X{ MORNING_STAR, "Trollsbane", (SPFX_RESTR | SPFX_DCLAS), S_TROLL, X { 0, AD_PHYS, 5, 0 }, NO_ATTK }, X X/* ARRAY TERMINATOR */ X{ 0, "", 0, 0, NO_ATTK, NO_ATTK } X}; X Xvoid Xmkartifact(otmp1) Xstruct obj **otmp1; X{ X register struct artifact *artif; X register struct obj *otmp = *otmp1; X register int n = 0; X X for(artif = artilist; artif->otyp; artif++) X if(otmp->otyp == artif->otyp && !(artif->spfx & SPFX_NOGEN)) n++; X X if (n) { X n = rnd(n); X for(artif = artilist; artif->otyp && n > 0; ) { X if(otmp->otyp == artif->otyp && !(artif->spfx & SPFX_NOGEN)) n--; X if (n>0) artif++; X } X X if(artif->otyp) *otmp1 = oname(otmp, artif->name, 0); X } X} X Xstatic struct artifact * Xget_artifact(otmp) Xstruct obj *otmp; X{ X register struct artifact *artif; X X if(otmp) X if(strlen(ONAME(otmp))) X for(artif = artilist; artif->otyp; artif++) X if(artif->otyp == otmp->otyp && X !strcmp(ONAME(otmp), artif->name)) return(artif); X return((struct artifact *)0); X} X Xboolean Xis_artifact(otmp) Xstruct obj *otmp; X{ X return(get_artifact(otmp) != (struct artifact *)0); X} X Xboolean Xspec_ability(otmp, abil) Xstruct obj *otmp; Xunsigned abil; X{ X struct artifact *arti = get_artifact(otmp); X X return(arti && (arti->spfx & abil)); X} X Xint Xrestr_name(otmp, name) /* returns 1 if name is restricted for otmp->otyp */ Xregister struct obj *otmp; Xregister char *name; X{ X register struct artifact *artif; X X if(!strlen(name)) return(0); X X for(artif = artilist; artif->otyp; artif++) X if(artif->otyp == otmp->otyp) X if(artif->spfx & (SPFX_NOGEN | SPFX_RESTR)) X if(!strcmp(artif->name, name)) return(1); X X return(0); X} X X# if defined(THEOLOGY) && defined(ALTARS) Xstruct obj * Xmk_aligned_artifact(align) Xint align; X{ X register struct artifact *artif; X register struct obj *otmp; X register int n = 0; X X for(artif = artilist; artif->otyp; artif++) X if(align == artif->align && !(artif->spfx & SPFX_NOGEN)) n++; X if (n) { X n = rnd(n); X for(artif = artilist; artif->otyp && n > 0; ) { X if(align == artif->align && !(artif->spfx & SPFX_NOGEN)) X n--; X if (n > 0) artif++; X } X if(artif->otyp) { X otmp = mksobj((int)artif->otyp, FALSE); X otmp = oname(otmp, artif->name, 0); X return (otmp); X } X } X return ((struct obj *) 0); X} X# endif X Xint Xdefends(adtyp, otmp) Xregister int adtyp; Xregister struct obj *otmp; X{ X register struct artifact *weap; X X if(weap = get_artifact(otmp)) X return(weap->defn.adtyp == adtyp); X return(0); X} X Xstatic int Xspec_applies(weap, ptr) Xregister struct artifact *weap; Xstruct permonst *ptr; X{ X if(!(weap->spfx & (SPFX_DMONS | SPFX_DCLAS | SPFX_ATTK))) X return(1); X X if(weap->spfx & SPFX_DMONS) X return((ptr == &mons[weap->mtype])); X else if(weap->spfx & SPFX_DCLAS) { X X if(weap->mtype) X return((weap->mtype == ptr->mlet)); X else { X if(!strcmp(weap->name, "Sunsword")) X return(is_undead(ptr)); X else if(!strcmp(weap->name, "Demonbane")) X return(is_demon(ptr)); X else if(!strcmp(weap->name, "Werebane")) X return(is_were(ptr)); X else if(!strcmp(weap->name, "Giantslayer")) X return(is_giant(ptr)); X else impossible("Weird class specific weapon '%s'", X weap->name); X } X } else if(weap->spfx & SPFX_ATTK) { X switch(weap->attk.adtyp) { X case AD_FIRE: return(!resists_fire(ptr)); X case AD_COLD: return(!resists_cold(ptr)); X case AD_ELEC: return(!resists_elec(ptr)); X case AD_DRLI: return(!resists_drli(ptr)); X case AD_STON: return(!resists_ston(ptr)); X default: impossible("Weird special attack for '%s'", X weap->name); X } X } X return(0); X} X Xint Xspec_abon(otmp, ptr) Xstruct obj *otmp; Xstruct permonst *ptr; X{ X register struct artifact *weap; X X if((weap = get_artifact(otmp))) X if(spec_applies(weap, ptr)) X return((weap->attk.damn) ? rnd((int)weap->attk.damn) : 0); X return(0); X} X Xint Xspec_dbon(otmp, ptr, tmp) Xregister struct obj *otmp; Xregister struct permonst *ptr; Xregister int tmp; X{ X register struct artifact *weap; X X if((weap = get_artifact(otmp))) X if(spec_applies(weap, ptr)) X return((weap->attk.damd) ? rnd((int)weap->attk.damd) : tmp); X return(0); X} X#endif /* NAMED_ITEMS */ END_OF_FILE if test 6525 -ne `wc -c <'src/artifact.c'`; then echo shar: \"'src/artifact.c'\" unpacked with wrong size! fi # end of 'src/artifact.c' fi if test -f 'src/makemon.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/makemon.c'\" else echo shar: Extracting \"'src/makemon.c'\" \(28290 characters\) sed "s/^X//" >'src/makemon.c' <<'END_OF_FILE' X/* SCCS Id: @(#)makemon.c 3.0 88/04/11 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" X Xstruct monst zeromonst; Xstatic int uncommon P((struct permonst *)); X Xstatic int monstr[NUMMONS]; X X#define m_initsgrp(mtmp, x, y) m_initgrp(mtmp, x, y, 3) X#define m_initlgrp(mtmp, x, y) m_initgrp(mtmp, x, y, 10) X#define toostrong(monindx, lev) (monstr[monindx] > lev) X#define tooweak(monindx, lev) (monstr[monindx] < lev) X Xstatic void Xm_initgrp(mtmp, x, y, n) /* make a group just like mtmp */ Xregister struct monst *mtmp; Xregister int x, y, n; X{ X coord mm; X register int cnt = rnd(n); X struct monst *mon; X X mm.x = x; X mm.y = y; X while(cnt--) { X if (peace_minded(mtmp->data)) continue; X /* Don't create groups of peaceful monsters since they'll get X * in our way. If the monster has a percentage chance so some X * are peaceful and some are not, the result will just be a X * smaller group. X */ X enexto(&mm, mm.x, mm.y); X mon = makemon(mtmp->data, mm.x, mm.y); X mon->mpeaceful = 0; X set_malign(mon); X /* Undo the second peace_minded() check in makemon(); if the X * monster turned out to be peaceful the first time we didn't X * create it at all; we don't want a second check. X */ X } X} X Xstatic void Xm_initthrow(mtmp,otyp,oquan) Xstruct monst *mtmp; Xint otyp,oquan; X{ X register struct obj *otmp; X X otmp = mksobj(otyp,FALSE); X otmp->quan = 2 + rnd(oquan); X otmp->owt = weight(otmp); X#ifdef TOLKIEN X if (otyp == ORCISH_ARROW) otmp->opoisoned = 1; X#endif X mpickobj(mtmp, otmp); X} X Xstatic void Xm_initweap(mtmp) Xregister struct monst *mtmp; X{ X register struct permonst *ptr = mtmp->data; X#ifdef REINCARNATION X if (dlevel==rogue_level) return; X#endif X/* X * first a few special cases: X * X * giants get a boulder to throw sometimes. X * ettins get clubs X * kobolds get darts to throw X * centaurs get some sort of bow & arrows or bolts X * soldiers get all sorts of things. X * kops get clubs & cream pies. X */ X switch (mtmp->data->mlet) { X case S_GIANT: X if (rn2(2)) (void)mongets(mtmp, (ptr != &mons[PM_ETTIN]) ? X BOULDER : CLUB); X break; X case S_HUMAN: X if(is_mercenary(ptr)) X switch(monsndx(ptr)) { X X#ifdef ARMY X case PM_SOLDIER: X (void) mongets(mtmp, rn2(2) ? SPEAR : SHORT_SWORD); X break; X case PM_SERGEANT: X (void) mongets(mtmp, rn2(2) ? FLAIL : MACE); X break; X case PM_LIEUTENANT: X (void) mongets(mtmp, rn2(2) ? GLAIVE : LONG_SWORD); X break; X case PM_CAPTAIN: X (void) mongets(mtmp, rn2(2) ? LONG_SWORD : SCIMITAR); X break; X#endif X default: if (!rn2(4)) (void) mongets(mtmp, DAGGER); X if (!rn2(7)) (void) mongets(mtmp, SPEAR); X break; X } X break; X X case S_HUMANOID: X#ifdef TOLKIEN X if (monsndx(ptr) == PM_HOBBIT) { X switch (rn2(3)) { X case 0: X (void)mongets(mtmp, DAGGER); X break; X case 1: X (void)mongets(mtmp, ELVEN_DAGGER); X break; X } X if (!rn2(10)) (void)mongets(mtmp, ELVEN_MITHRIL_COAT); X } else if (is_dwarf(ptr)) { X (void)mongets(mtmp, DWARVISH_CLOAK); X (void)mongets(mtmp, IRON_SHOES); X if (!rn2(4)) { X (void)mongets(mtmp, DWARVISH_SHORT_SWORD); X (void)mongets(mtmp, X rn2(3) ? DWARVISH_MATTOCK : AXE); X (void)mongets(mtmp, DWARVISH_IRON_HELM); X (void)mongets(mtmp, DWARVISH_ROUNDSHIELD); X if (!rn2(3)) X (void)mongets(mtmp, DWARVISH_MITHRIL_COAT); X } else { X (void)mongets(mtmp, PICK_AXE); X } X } else if (is_elf(ptr)) { X (void)mongets(mtmp, X rn2(2) ? ELVEN_MITHRIL_COAT : ELVEN_CLOAK); X if (rn2(2)) (void)mongets(mtmp, ELVEN_LEATHER_HELM); X if (rn2(3)) (void)mongets(mtmp, ELVEN_DAGGER); X switch (rn2(3)) { X case 0: X if (!rn2(4)) (void)mongets(mtmp, ELVEN_SHIELD); X (void)mongets(mtmp, ELVEN_SHORT_SWORD); X (void)mongets(mtmp, ELVEN_BOW); X m_initthrow(mtmp, ELVEN_ARROW, 12); X break; X case 1: X (void)mongets(mtmp, ELVEN_BROADSWORD); X if (rn2(2)) (void)mongets(mtmp, ELVEN_SHIELD); X break; X case 2: X (void)mongets(mtmp, ELVEN_SPEAR); X (void)mongets(mtmp, ELVEN_SHIELD); X break; X } X } X#else /* TOLKIEN */ X if (is_dwarf(ptr)) { X (void)mongets(mtmp, IRON_SHOES); X if (rn2(4) == 0) { X (void)mongets(mtmp, SHORT_SWORD); X (void)mongets(mtmp, X (rn2(3) == 0) ? AXE : TWO_HANDED_SWORD); X (void)mongets(mtmp, LARGE_SHIELD); X if (rn2(3) == 0) X (void)mongets(mtmp, DWARVISH_MITHRIL_COAT); X } else { X (void)mongets(mtmp, PICK_AXE); X } X } else if (is_elf(ptr)) { X (void)mongets(mtmp, ELVEN_CLOAK); X if (rn2(3)) (void)mongets(mtmp, DAGGER); X switch (rn2(3)) { X case 0: X if (!rn2(4)) (void)mongets(mtmp, SMALL_SHIELD); X (void)mongets(mtmp, SHORT_SWORD); X (void)mongets(mtmp, BOW); X m_initthrow(mtmp, ARROW, 12); X break; X case 1: X (void)mongets(mtmp, BROADSWORD); X if (rn2(2)) (void)mongets(mtmp, SMALL_SHIELD); X break; X case 2: X (void)mongets(mtmp, SPEAR); X (void)mongets(mtmp, SMALL_SHIELD); X break; X } X } X#endif /* TOLKIEN */ X break; X# ifdef KOPS X case S_KOP: /* create Keystone Kops with cream pies to X * throw. As suggested by KAA. [MRS] X */ X if (!rn2(4)) m_initthrow(mtmp, CREAM_PIE, 2); X if (!rn2(3)) (void)mongets(mtmp, (rn2(2)) ? CLUB : RUBBER_HOSE); X break; X#endif X case S_ORC: X#ifdef TOLKIEN X { int mm = monsndx(ptr); X if(rn2(2)) (void)mongets(mtmp, ORCISH_HELM); X if (mm == PM_MORDOR_ORC || X (mm == PM_ORC_CAPTAIN && rn2(2))) { X if(rn2(2)) (void)mongets(mtmp, SCIMITAR); X if(rn2(2)) (void)mongets(mtmp, ORCISH_SHIELD); X if(rn2(2)) (void)mongets(mtmp, KNIFE); X if(rn2(2)) (void)mongets(mtmp, ORCISH_CHAIN_MAIL); X } else if (mm == PM_URUK_HAI || mm == PM_ORC_CAPTAIN) { X if(rn2(2)) (void)mongets(mtmp, ORCISH_CLOAK); X if(rn2(2)) (void)mongets(mtmp, ORCISH_SHORT_SWORD); X if(rn2(2)) (void)mongets(mtmp, IRON_SHOES); X if(rn2(2)) { X (void)mongets(mtmp, ORCISH_BOW); X m_initthrow(mtmp, ORCISH_ARROW, 12); X } X if(rn2(2)) (void)mongets(mtmp, URUK_HAI_SHIELD); X } else if (mm != PM_ORC_SHAMAN) { X (void)mongets(mtmp, (mm == PM_GOBLIN || rn2(2) == 0) ? X ORCISH_DAGGER : SCIMITAR); X } X } X#else /* TOLKIEN */ X { int mm = monsndx(ptr); X if(rn2(2)) (void)mongets(mtmp, ORCISH_HELM); X if (mm == PM_ORC_CAPTAIN) { X if(rn2(2)) { X if(rn2(2)) (void)mongets(mtmp, SCIMITAR); X if(rn2(2)) (void)mongets(mtmp, SMALL_SHIELD); X if(rn2(2)) (void)mongets(mtmp, KNIFE); X if(rn2(2)) (void)mongets(mtmp, CHAIN_MAIL); X } else { X if(rn2(2)) (void)mongets(mtmp, SHORT_SWORD); X if(rn2(2)) (void)mongets(mtmp, IRON_SHOES); X if(rn2(2)) { X (void)mongets(mtmp, BOW); X m_initthrow(mtmp, ARROW, 12); X } X if(rn2(2)) (void)mongets(mtmp, SMALL_SHIELD); X } X } else if (mm != PM_ORC_SHAMAN) { X (void)mongets(mtmp, (mm == PM_GOBLIN || rn2(2) == 0) ? X DAGGER : SCIMITAR); X } X } X#endif /* TOLKIEN */ X break; X case S_KOBOLD: X if (!rn2(4)) m_initthrow(mtmp, DART, 12); X break; X X case S_CENTAUR: X if (rn2(2)) { X if(ptr == &mons[PM_FOREST_CENTAUR]) { X (void)mongets(mtmp, BOW); X m_initthrow(mtmp, ARROW, 12); X } else { X (void)mongets(mtmp, CROSSBOW); X m_initthrow(mtmp, CROSSBOW_BOLT, 12); X } X } X break; X case S_WRAITH: X (void)mongets(mtmp, KNIFE); X (void)mongets(mtmp, LONG_SWORD); X break; X case S_DEMON: X#ifdef HARD X if (monsndx(ptr) == PM_BALROG) { X (void)mongets(mtmp, BULLWHIP); X (void)mongets(mtmp, BROADSWORD); X break; X } X#endif X /* prevent djinnis and mail daemons from leaving objects when X * they vanish X */ X if (!is_demon(ptr)) break; X /* fall thru */ X/* X * Now the general case, ~40% chance of getting some type X * of weapon. TODO: Add more weapons types (use bigmonst()); X */ X default: X switch(rnd(12)) { X case 1: X m_initthrow(mtmp, DART, 12); X break; X case 2: X (void) mongets(mtmp, CROSSBOW); X m_initthrow(mtmp, CROSSBOW_BOLT, 12); X break; X case 3: X (void) mongets(mtmp, BOW); X m_initthrow(mtmp, ARROW, 12); X break; X case 4: X m_initthrow(mtmp, DAGGER, 3); X break; X case 5: X (void) mongets(mtmp, AKLYS); X break; X default: X break; X } X break; X } X} X Xstatic void Xm_initinv(mtmp) Xregister struct monst *mtmp; X{ X register int cnt; X register struct obj *otmp; X register struct permonst *ptr = mtmp->data; X#ifdef REINCARNATION X if (dlevel==rogue_level) return; X#endif X/* X * Soldiers get armour & rations - armour approximates their ac. X * Nymphs may get mirror or potion of object detection. X */ X switch(mtmp->data->mlet) { X X case S_HUMAN: X if(is_mercenary(ptr)) { X register int mac; X X if((mac = ptr->ac) < -1) X mac += 7 + mongets(mtmp, (rn2(5)) ? X PLATE_MAIL : CRYSTAL_PLATE_MAIL); X else if(mac < 3) X mac += 6 + mongets(mtmp, (rn2(3)) ? X SPLINT_MAIL : BANDED_MAIL); X else X mac += 3 + mongets(mtmp, (rn2(3)) ? X RING_MAIL : STUDDED_LEATHER_ARMOR); X X if(mac < 10) { X mac += 1 + mongets(mtmp, HELMET); X if(mac < 10) { X mac += 1 + mongets(mtmp, SMALL_SHIELD); X if(mac < 10) { X mac += 1 + mongets(mtmp, ELVEN_CLOAK); X if(mac < 10) X mac += 1 +mongets(mtmp, LEATHER_GLOVES); X } X } X } X X if(mac != 10) { /* make up the difference */ X otmp = mksobj(RIN_PROTECTION,FALSE); X otmp->spe = (10 - mac); X if(otmp->spe < 0) curse(otmp); X mpickobj(mtmp, otmp); X } X#ifdef ARMY X if(ptr != &mons[PM_GUARD]) { X if (!rn2(3)) (void) mongets(mtmp, K_RATION); X if (!rn2(2)) (void) mongets(mtmp, C_RATION); X } X#endif X } X break; X X case S_NYMPH: X#ifdef MEDUSA X if(!rn2(2)) (void) mongets(mtmp, MIRROR); X#endif X if(!rn2(2)) (void) mongets(mtmp, POT_OBJECT_DETECTION); X break; X X case S_GIANT: X if(mtmp->data == &mons[PM_MINOTAUR]) X (void) mongets(mtmp, WAN_DIGGING); X else if (is_giant(mtmp->data)) { X for(cnt = rn2((int)(mtmp->m_lev / 2)); cnt; cnt--) { X do X otmp = mkobj(GEM_SYM,FALSE); X while (otmp->otyp >= LAST_GEM+5); X otmp->quan = 2 + rnd(2); X otmp->owt = weight(otmp); X mpickobj(mtmp, otmp); X } X } X break; X#ifdef TOLKIEN X case S_WRAITH: X if(mtmp->data == &mons[PM_NAZGUL]) { X otmp = mksobj(RIN_INVISIBILITY, FALSE); X curse(otmp); X mpickobj(mtmp, otmp); X } X break; X#endif X default: X break; X } X} X X/* X * called with [x,y] = coordinates; X * [0,0] means anyplace X * [u.ux,u.uy] means: call mnexto (if !in_mklev) X * X * In case we make a monster group, only return the one at [x,y]. X */ Xstruct monst * Xmakemon(ptr, x, y) Xregister struct permonst *ptr; Xregister int x, y; X{ X register struct monst *mtmp; X register int ct; X boolean anything = (!ptr); X X /* if caller wants random location, do it here */ X if(x == 0 && y == 0) { X do { X x = rn1(COLNO-3,2); X y = rn2(ROWNO); X } while(!goodpos(x, y)); X } X X /* if a monster already exists at the position, return */ X if(levl[x][y].mmask) return((struct monst *) 0); X X if(ptr){ X /* if you are to make a specific monster and it has X already been genocided, return */ X if(ptr->geno & G_GENOD) return((struct monst *) 0); X } else { X /* make a random (common) monster. */ X#ifdef REINCARNATION X if (!(ptr = (dlevel==rogue_level) ? roguemon() : rndmonst())) X#else X if(!(ptr = rndmonst())) X#endif X { X#ifdef DEBUG X pline("Warning: no monster."); X#endif X return((struct monst *) 0); /* no more monsters! */ X } X } X /* if it's unique, don't ever make it again */ X if (ptr->geno & G_UNIQ) ptr->geno &= G_GENOD; X/* gotmon: /* label not referenced */ X mtmp = newmonst(ptr->pxlth); X *mtmp = zeromonst; /* clear all entries in structure */ X for(ct = 0; ct < ptr->pxlth; ct++) X ((char *) &(mtmp->mextra[0]))[ct] = 0; X if(type_is_pname(ptr)) X Strcpy(NAME(mtmp), ptr->mname); X mtmp->nmon = fmon; X fmon = mtmp; X mtmp->m_id = flags.ident++; X mtmp->data = ptr; X mtmp->mxlth = ptr->pxlth; X X mtmp->m_lev = adj_lev(ptr); X#ifdef GOLEMS X if (is_golem(ptr)) X mtmp->mhpmax = mtmp->mhp = golemhp(monsndx(ptr)); X else X#endif /* GOLEMS */ X if(ptr->mlevel > 49) { X /* "special" fixed hp monster X * the hit points are encoded in the mlevel in a somewhat strange X * way to fit in the 50..127 positive range of a signed character X * above the 1..49 that indicate "normal" monster levels */ X mtmp->mhpmax = mtmp->mhp = 2*(ptr->mlevel - 6); X mtmp->m_lev = mtmp->mhp / 4; /* approximation */ X } else if((ptr->mlet == S_DRAGON) && (ptr >= &mons[PM_GREY_DRAGON])) X mtmp->mhpmax = mtmp->mhp = 80; X else if(!mtmp->m_lev) mtmp->mhpmax = mtmp->mhp = rnd(4); X else mtmp->mhpmax = mtmp->mhp = d((int)mtmp->m_lev, 8); X mtmp->mx = x; X mtmp->my = y; X levl[x][y].mmask = 1; X mtmp->mcansee = 1; X mtmp->mpeaceful = peace_minded(ptr); X X switch(ptr->mlet) { X case S_MIMIC: X set_mimic_sym(mtmp); X break; X case S_SPIDER: X case S_SNAKE: X mtmp->mhide = mtmp->mundetected = 1; X if(in_mklev) X if(mtmp->mx && mtmp->my) X (void) mkobj_at(0, mtmp->mx, mtmp->my); X break; X case S_CHAMELEON: X /* If you're protected with a ring, don't create X * any shape-changing chameleons -dgk X */ X if (Protection_from_shape_changers) X mtmp->cham = 0; X else { X mtmp->cham = 1; X (void) newcham(mtmp, rndmonst()); X } X break; X case S_STALKER: X case S_EEL: X mtmp->minvis = 1; X break; X case S_LEPRECHAUN: X mtmp->msleep = 1; X break; X case S_NYMPH: X if(rn2(5) && !u.uhave_amulet) mtmp->msleep = 1; X break; X case S_UNICORN: X if ((ptr==&mons[PM_WHITE_UNICORN] && X u.ualigntyp == U_LAWFUL) || X (ptr==&mons[PM_GREY_UNICORN] && X u.ualigntyp == U_NEUTRAL) || X (ptr==&mons[PM_BLACK_UNICORN] && X u.ualigntyp == U_CHAOTIC)) X mtmp->mpeaceful = 1; X break; X } X if (ptr == &mons[PM_WIZARD_OF_YENDOR]) { X mtmp->iswiz = 1; X flags.no_of_wizards++; X } X X if(in_mklev) { X if(((is_ndemon(ptr)) || X (ptr == &mons[PM_WUMPUS]) || X#ifdef WORM X (ptr == &mons[PM_LONG_WORM]) || X#endif X (ptr == &mons[PM_GIANT_EEL])) && rn2(5)) X mtmp->msleep = 1; X } else { X if(x == u.ux && y == u.uy && ptr->mlet != S_GHOST) { X mnexto(mtmp); X if (ptr->mlet == S_MIMIC) set_mimic_sym(mtmp); X } X } X#ifdef HARD X if(is_dprince(ptr)) { X mtmp->mpeaceful = mtmp->minvis = 1; X# ifdef NAMED_ITEMS X if(uwep) X if(!strcmp(ONAME(uwep), "Excalibur")) X mtmp->mpeaceful = mtmp->mtame = 0; X# endif X } X#endif X#ifdef WORM X if(ptr == &mons[PM_LONG_WORM] && getwn(mtmp)) initworm(mtmp); X#endif X set_malign(mtmp); /* having finished peaceful changes */ X if(anything) { X if((ptr->geno & G_SGROUP) && rn2(2)) X m_initsgrp(mtmp, mtmp->mx, mtmp->my); X else if(ptr->geno & G_LGROUP) { X if(rn2(3)) m_initlgrp(mtmp, mtmp->mx, mtmp->my); X else m_initsgrp(mtmp, mtmp->mx, mtmp->my); X } X } X X if(is_armed(ptr)) X m_initweap(mtmp); /* equip with weapons / armour */ X m_initinv(mtmp); /* add on a few special items */ X X return(mtmp); X} X Xvoid Xenexto(cc, xx,yy) Xcoord *cc; Xregister xchar xx, yy; X{ X register xchar x,y; X coord foo[15], *tfoo; X int range, i; X X tfoo = foo; X range = 1; X do { /* full kludge action. */ X for(x = xx-range; x <= xx+range; x++) X if(goodpos(x, yy-range)) { X tfoo->x = x; X (tfoo++)->y = yy-range; X if(tfoo == &foo[15]) goto foofull; X } X for(x = xx-range; x <= xx+range; x++) X if(goodpos(x,yy+range)) { X tfoo->x = x; X (tfoo++)->y = yy+range; X if(tfoo == &foo[15]) goto foofull; X } X for(y = yy+1-range; y < yy+range; y++) X if(goodpos(xx-range,y)) { X tfoo->x = xx-range; X (tfoo++)->y = y; X if(tfoo == &foo[15]) goto foofull; X } X for(y = yy+1-range; y < yy+range; y++) X if(goodpos(xx+range,y)) { X tfoo->x = xx+range; X (tfoo++)->y = y; X if(tfoo == &foo[15]) goto foofull; X } X range++; X } while(tfoo == foo); Xfoofull: X i = rn2(tfoo - foo); X cc->x = foo[i].x; X cc->y = foo[i].y; X return; X} X Xint Xgoodpos(x, y) X{ X#ifdef STUPID X if (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 || X levl[x][y].mmask || !ACCESSIBLE(levl[x][y].typ)) X return 0; X if (IS_DOOR(levl[x][y].typ) && X (levl[x][y].doormask & (D_LOCKED | D_CLOSED))) X return 0; X return !((x == u.ux && y == u.uy) || sobj_at(BOULDER, x, y)); X#else X return X ! (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 || X levl[x][y].mmask || !ACCESSIBLE(levl[x][y].typ) || X (IS_DOOR(levl[x][y].typ) && X (levl[x][y].doormask & (D_LOCKED | D_CLOSED)) ) X || (x == u.ux && y == u.uy) X || sobj_at(BOULDER, x, y) X ); X#endif /* STUPID */ X} X Xvoid Xrloc(mtmp) Xstruct monst *mtmp; X{ X register int tx, ty; X X#ifdef WORM /* do not relocate worms */ X if(mtmp->wormno && mtmp->mx) return; X#endif X /* if the wiz teleports away to heal, try the up staircase, X to block the player's escaping before he's healed */ X if(!mtmp->iswiz || !goodpos(tx = xupstair, ty = yupstair)) X do { X tx = rn1(COLNO-3,2); X ty = rn2(ROWNO); X } while(!goodpos(tx,ty)); X if(mtmp->mx != 0 && mtmp->my != 0) X levl[mtmp->mx][mtmp->my].mmask = 0; X mtmp->mx = tx; X mtmp->my = ty; X levl[tx][ty].mmask = 1; X if(u.ustuck == mtmp){ X if(u.uswallow) { X u.ux = tx; X u.uy = ty; X docrt(); X } else u.ustuck = 0; X } X pmon(mtmp); X set_apparxy(mtmp); X} X Xstruct monst * Xmkmon_at(name, x, y) Xchar *name; Xregister int x,y; X{ X register int ct; X register struct permonst *ptr; X X for(ct = PM_CHAMELEON; ct >= 0; ct--) { /* Chameleon is last monster */ X ptr = &mons[ct]; X if(!strcmp(ptr->mname, name)) X return(makemon(ptr, x, y)); X } X return((struct monst *)0); X} X Xstatic int Xcmnum() { /* return the number of "common" monsters */ X X int i, count; X X for(i = count = 0; mons[i].mlet; i++) X if(!uncommon(&mons[i])) count++; X X return(count); X} X Xstatic int Xuncommon(ptr) Xstruct permonst *ptr; X{ X return (ptr->geno & (G_GENOD | G_NOGEN | G_UNIQ)) || X (!Inhell ? ptr->geno & G_HELL : ptr->maligntyp > 0); X} X X/* This routine is designed to return an integer value which represents X * an approximation of monster strength. It uses a similar method of X * determination as "experience()" to arrive at the strength. X */ Xstatic int Xmstrength(ptr) Xstruct permonst *ptr; X{ X int i, tmp2, n, tmp = ptr->mlevel; X X if(tmp > 49) /* special fixed hp monster */ X tmp = 2*(tmp - 6) / 4; X X/* For creation in groups */ X n = (!!(ptr->geno & G_SGROUP)); X n += (!!(ptr->geno & G_LGROUP)) << 1; X X/* For higher ac values */ X n += (ptr->ac < 0); X X/* For very fast monsters */ X n += (ptr->mmove >= 18); X X/* For each attack and "special" attack */ X for(i = 0; i < NATTK; i++) { X X tmp2 = ptr->mattk[i].aatyp; X n += (tmp2 > 0); X n += (tmp2 == AT_MAGC); X } X X/* For each "special" damage type */ X for(i = 0; i < NATTK; i++) { X X tmp2 = ptr->mattk[i].adtyp; X if((tmp2 == AD_DRLI) || (tmp2 == AD_STON)) n += 2; X else n += (tmp2 != AD_PHYS); X n += ((ptr->mattk[i].damd * ptr->mattk[i].damn) > 23); X } X X/* Finally, adjust the monster level 0 <= n <= 24 (approx.) */ X if(n == 0) tmp--; X else if(n >= 6) tmp += ( n / 2 ); X else tmp += ( n / 3 + 1); X X return((tmp >= 0) ? tmp : 0); X} X Xvoid Xinit_monstr() X{ X register int ct; X X for(ct = 0; mons[ct].mlet; ct++) X monstr[ct] = mstrength(&(mons[ct])); X} X Xstruct permonst * Xrndmonst() { /* select a random monster */ X register struct permonst *ptr; X register int i, ct; X register int zlevel; X static int minmlev, maxmlev, accept; X static long oldmoves = 0L; /* != 1, starting value of moves */ X X if(oldmoves != moves) { /* must recalculate accept */ X oldmoves = moves; X zlevel = u.uhave_amulet ? MAXLEVEL : dlevel; X if(cmnum() <= 0) { X#ifdef DEBUG X pline("cmnum() fails!"); X#endif X return((struct permonst *) 0); X } X X /* determine the level of the weakest monster to make. */ X minmlev = zlevel/6; X /* determine the level of the strongest monster to make. */ X maxmlev = (zlevel + u.ulevel)>>1; X/* X * Find out how many monsters exist in the range we have selected. X */ X for(accept = ct = 0 ; mons[ct].mlet; ct++) { X ptr = &(mons[ct]); X if(uncommon(ptr)) continue; X if(tooweak(ct, minmlev) || toostrong(ct, maxmlev)) X continue; X accept += (ptr->geno & G_FREQ); X } X } X X if(!accept) { X#ifdef DEBUG X pline("no accept!"); X#endif X return((struct permonst *) 0); X } X/* X * Now, select a monster at random. X */ X ct = rnd(accept); X for(i = 0; mons[i].mlet && ct > 0; i++) { X ptr = &(mons[i]); X if(uncommon(ptr)) continue; X if(tooweak(i, minmlev) || toostrong(i, maxmlev)) X continue; X ct -= (ptr->geno & G_FREQ); X } X if(ct > 0) { X#ifdef DEBUG X pline("no count!"); X#endif X return((struct permonst *) 0); X } X return(ptr); X} X X/* The routine below is used to make one of the multiple types X * of a given monster class. It will return 0 if no monsters X * in that class can be made. X */ X Xstruct permonst * Xmkclass(mlet) Xchar mlet; X{ X register int first, last, num = 0; X X if(!mlet) { X impossible("mkclass called with null arg!"); X return((struct permonst *) 0); X } X/* Assumption #1: monsters of a given class are contiguous in the X * mons[] array. X */ X for(first = 0; mons[first].mlet != mlet; first++) X if(!mons[first].mlet) return((struct permonst *) 0); X X for(last = first; mons[last].mlet && mons[last].mlet == mlet; last++) X if(!(mons[last].geno & (G_GENOD | G_NOGEN | G_UNIQ))) X num += mons[last].geno & G_FREQ; X X if(!num) return((struct permonst *) 0); X X/* Assumption #2: monsters of a given class are presented in ascending X * order of strength. X */ X for(num = rnd(num); num > 0; first++) X if(!(mons[first].geno & (G_GENOD | G_NOGEN | G_UNIQ))) { /* consider it */ X /* skew towards lower value monsters at lower exp. levels */ X if(adj_lev(&mons[first]) > (u.ulevel*2)) num--; X num -= mons[first].geno & G_FREQ; X } X first--; /* correct an off-by-one error */ X X return(&mons[first]); X} X Xint Xadj_lev(ptr) /* adjust strength of monsters based on dlevel and u.ulevel */ Xregister struct permonst *ptr; X{ X int tmp, tmp2; X X if((tmp = ptr->mlevel) > 49) return(50); /* "special" demons/devils */ X tmp2 = (dlevel - tmp); X if(tmp2 < 0) tmp--; /* if mlevel > dlevel decrement tmp */ X else tmp += (tmp2 / 5); /* else increment 1 per five diff */ X X tmp2 = (u.ulevel - ptr->mlevel); /* adjust vs. the player */ X if(tmp2 > 0) tmp += (tmp2 / 4); /* level as well */ X X tmp2 = 3 * ptr->mlevel/ 2; /* crude upper limit */ X return((tmp > tmp2) ? tmp2 : (tmp > 0 ? tmp : 0)); /* 0 lower limit */ X} X Xstruct permonst * Xgrow_up(mtmp) /* mon mtmp "grows up" to a bigger version. */ Xregister struct monst *mtmp; X{ X register int newtype; X register struct permonst *ptr = mtmp->data; X X if (ptr->mlevel >= 50 || mtmp->mhpmax <= 8*mtmp->m_lev) X return ptr; X newtype = little_to_big(monsndx(ptr)); X if (++mtmp->m_lev >= mons[newtype].mlevel) { X if (mons[newtype].geno & G_GENOD) { X pline("As %s grows up into a%s %s, %s dies!", X mon_nam(mtmp), X index(vowels,*mons[newtype].mname) ? "n" : "", X mons[newtype].mname, X mon_nam(mtmp)); X mondied(mtmp); X return (struct permonst *)0; X } X mtmp->data = &mons[newtype]; X mtmp->m_lev = mons[newtype].mlevel; X } X if (mtmp->m_lev > 3*mtmp->data->mlevel / 2) X mtmp->m_lev = 3*mtmp->data->mlevel / 2; X return(mtmp->data); X} X Xint Xmongets(mtmp, otyp) Xregister struct monst *mtmp; Xregister int otyp; X{ X register struct obj *otmp; X X if((otmp = (otyp) ? mksobj(otyp,FALSE) : mkobj(otyp,FALSE))) { X if (mtmp->data->mlet == S_DEMON) { X /* demons always get cursed objects */ X curse(otmp); X } X mpickobj(mtmp, otmp); X return(otmp->spe); X } else return(0); X} X X#ifdef REINCARNATION Xstruct permonst * Xroguemon() X{ X/* Make a monster for a Rogue-like level; only capital letters. There are X * no checks for "too hard" or "too easy", though dragons are specifically X * ruled out because playtesting showed they made the level too hard. X * Modified from rndmonst(). X */ X#define isupper(x) ('A'<=(x) && (x)<='Z') X register struct permonst *ptr; X register int accept,ct,i; X X /* See how many there are. */ X accept = 0; X for(ct = PM_APE ; isupper(mons[ct].mlet); ct++) { X if (mons[ct].mlet == S_DRAGON) continue; X ptr = &(mons[ct]); X if(uncommon(ptr)) continue; X accept += (ptr->geno & G_FREQ); X } X if(!accept) return((struct permonst *) 0); X X /* Now, select one at random. */ X ct = rnd(accept); X for(i = PM_APE; isupper(mons[i].mlet) && ct > 0; i++) { X if (mons[i].mlet == S_DRAGON) continue; X ptr = &(mons[i]); X if(uncommon(ptr)) continue; X ct -= (ptr->geno & G_FREQ); X } X if(ct > 0) return((struct permonst *) 0); X return(ptr); X} X#endif X X#ifdef GOLEMS Xint Xgolemhp(type) Xint type; X{ X switch(type) { X case PM_STRAW_GOLEM: return 20; X case PM_ROPE_GOLEM: return 30; X case PM_LEATHER_GOLEM: return 40; X case PM_WOOD_GOLEM: return 50; X case PM_FLESH_GOLEM: return 40; X case PM_CLAY_GOLEM: return 50; X case PM_STONE_GOLEM: return 60; X case PM_IRON_GOLEM: return 80; X default: return 0; X } X} X#endif /* GOLEMS */ X X/* X * Alignment vs. yours determines monster's attitude to you. X * ( some "animal" types are co-aligned, but also hungry ) X */ Xboolean Xpeace_minded(ptr) Xregister struct permonst *ptr; X{ X schar mal = ptr->maligntyp, ual = u.ualigntyp; X X if (always_peaceful(ptr)) return TRUE; X if (always_hostile(ptr)) return FALSE; X X /* the monster is hostile if its alignment is different from the X * player's */ X if (sgn(mal) != sgn(ual)) return FALSE; X X /* Negative monster hostile to player with Amulet. */ X if (mal < 0 && u.uhave_amulet) return FALSE; X X /* Last case: a chance of a co-aligned monster being X * hostile. This chance is greater if the player has strayed X * (u.ualign negative) or the monster is not strongly aligned. X */ X return !!rn2(16 + (u.ualign < -15 ? -15 : u.ualign)) && X !!rn2(2 + abs(mal)); X} X X/* Set malign to have the proper effect on player alignment if monster is X * killed. Negative numbers mean it's bad to kill this monster; positive X * numbers mean it's good. Since there are more hostile monsters than X * peaceful monsters, the penalty for killing a peaceful monster should be X * greater than the bonus for killing a hostile monster to maintain balance. X * Rules: X * it's bad to kill peaceful monsters, potentially worse to kill always- X * peaceful monsters X * it's never bad to kill a hostile monster, although it may not be good X */ Xvoid Xset_malign(mtmp) Xstruct monst *mtmp; X{ X schar mal = mtmp->data->maligntyp; X boolean coaligned = (sgn(mal) == sgn(u.ualigntyp)); X X if (always_peaceful(mtmp->data)) X mtmp->malign = -3*max(5,abs(mal)); X else if (always_hostile(mtmp->data)) { X if (coaligned) X mtmp->malign = 0; X else X mtmp->malign = max(5,abs(mal)); X } else if (coaligned) { X if (mtmp->mpeaceful) X mtmp->malign = -3*max(3,abs(mal)); X else /* renegade */ X mtmp->malign = max(3,abs(mal)); X } else /* not coaligned and therefore hostile */ X mtmp->malign = abs(mal); X} X Xstatic char syms[] = { 0, 0, RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, GOLD_SYM, X SCROLL_SYM, POTION_SYM, ARMOR_SYM, AMULET_SYM, TOOL_SYM, ROCK_SYM, X GEM_SYM, X#ifdef SPELLS X SPBOOK_SYM, X#endif X S_MIMIC_DEF, S_MIMIC_DEF, S_MIMIC_DEF, X}; X Xvoid Xset_mimic_sym(mtmp) /* KAA */ Xregister struct monst *mtmp; X{ X int roomno, rt; X char sym; X if (!mtmp) return; X X syms[0] = UP_SYM; X syms[1] = DN_SYM; X X mtmp->mimic = 1; X roomno = inroom(mtmp->mx, mtmp->my); X if (levl[mtmp->mx][mtmp->my].gmask) X sym = GOLD_SYM; X else if (levl[mtmp->mx][mtmp->my].omask) X sym = o_at(mtmp->mx,mtmp->my)->olet; X else if (IS_DOOR(levl[mtmp->mx][mtmp->my].typ) || X IS_WALL(levl[mtmp->mx][mtmp->my].typ)) X sym = DOOR_SYM; X else if (is_maze_lev) X sym = rn2(2) ? ROCK_SYM : syms[rn2(sizeof syms)]; X else if (roomno < 0) X sym = ROCK_SYM; X else if ((rt = rooms[roomno].rtype) == ZOO || rt == VAULT) X sym = GOLD_SYM; X#ifdef ORACLE X else if (rt == DELPHI) X sym = rn2(2) ? ROCK_SYM : FOUNTAIN_SYM; X#endif X#ifdef ALTARS X else if (rt == TEMPLE) X sym = ALTAR_SYM; X#endif X /* We won't bother with beehives, morgues, barracks, throne rooms X * since they shouldn't contain mimics anyway... X */ X else if (rt >= SHOPBASE) { X int s_sym = get_shop_item(rt - SHOPBASE); X X if (s_sym < 0) sym = objects[-sym].oc_olet; X else if (sym == RANDOM_SYM) X sym = syms[rn2(sizeof(syms)-2) + 2]; X else sym = s_sym; X } else sym = syms[rn2(sizeof syms)]; X mtmp->mappearance = sym; X} END_OF_FILE if test 28290 -ne `wc -c <'src/makemon.c'`; then echo shar: \"'src/makemon.c'\" unpacked with wrong size! fi # end of 'src/makemon.c' fi if test -f 'src/options.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/options.c'\" else echo shar: Extracting \"'src/options.c'\" \(16326 characters\) sed "s/^X//" >'src/options.c' <<'END_OF_FILE' X/* SCCS Id: @(#)options.c 3.0 88/11/09 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" Xstatic boolean set_order; X Xstatic void nmcpy(); X Xvoid Xinitoptions() X{ X register char *opts; X X flags.time = flags.nonews = flags.notombstone = flags.end_own = X flags.standout = flags.nonull = flags.ignintr = FALSE; X flags.no_rest_on_space = flags.invlet_constant = TRUE; X flags.end_top = 5; X flags.end_around = 4; X flags.female = FALSE; /* players are usually male */ X flags.sortpack = TRUE; X flags.soundok = TRUE; X flags.verbose = TRUE; X flags.confirm = TRUE; X flags.safe_dog = TRUE; X flags.silent = flags.pickup = TRUE; X nmcpy(pl_fruit, objects[SLIME_MOLD].oc_name, PL_FSIZ); X flags.num_pad = FALSE; X#ifdef MSDOS X#ifdef DECRAINBOW X flags.DECRainbow = FALSE; X#endif X#ifdef DGK X flags.IBMBIOS = X flags.rawio = FALSE; X#endif X read_config_file(); X#endif /* MSDOS */ X if(opts = getenv("NETHACKOPTIONS")) X parseoptions(opts,TRUE); X (void)fruitadd(pl_fruit); X objects[SLIME_MOLD].oc_name = "\033"; X /* Put something untypable in there */ X /* We cannot just use NULL because that marks the end of objects */ X} X Xstatic void Xnmcpy(dest, source, maxlen) X char *dest, *source; X int maxlen; X{ X char *cs, *cd; X int count; X X cd = dest; X cs = source; X for(count = 1; count < maxlen; count++) { X if(*cs == ',' || *cs == '\0') break; /*exit on \0 terminator*/ X *cd++ = *cs++; X } X *cd = 0; X} X X/* X * escapes: escape expansion for showsyms. C-style escapes understood include X * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). The ^-prefix X * for control characters is also understood, and \[mM] followed by any of the X * previous forms or by a character has the effect of 'meta'-ing the value (so X * that the alternate character set will be enabled). X */ Xvoid Xescapes(cp, tp) Xchar *cp, *tp; X{ X while (*cp) X { X int cval = 0, meta = 0; X X if (*cp == '\\' && index("mM", cp[1])) { X meta = 1; X cp += 2; X } X if (*cp == '\\' && index("0123456789xXoO", cp[1])) X { X char *dp, *hex = "00112233445566778899aAbBcCdDeEfF"; X int dcount = 0; X X cp++; X if (*cp == 'x' || *cp == 'X') X for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++) X cval = (cval * 16) + (dp - hex) / 2; X else if (*cp == 'o' || *cp == 'O') X for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++) X cval = (cval * 8) + (*cp - '0'); X else X for (; (index("0123456789",*cp)) && (dcount++ < 3); cp++) X cval = (cval * 10) + (*cp - '0'); X } X else if (*cp == '\\') /* C-style character escapes */ X { X switch (*++cp) X { X case '\\': cval = '\\'; break; X case 'n': cval = '\n'; break; X case 't': cval = '\t'; break; X case 'b': cval = '\b'; break; X case 'r': cval = '\r'; break; X default: cval = *cp; X } X cp++; X } X else if (*cp == '^') /* expand control-character syntax */ X { X cval = (*++cp & 0x1f); X cp++; X } X else X cval = *cp++; X if (meta) X cval |= 0x80; X *tp++ = cval; X } X *tp = '\0'; X} X Xvoid Xparseoptions(opts, from_env) Xregister char *opts; Xboolean from_env; X{ X register char *op; X/* X register char *op2; X*/ X unsigned num; X boolean negated; X X if(op = index(opts, ',')) { X *op++ = 0; X parseoptions(op, from_env); X } X/* X if(op = index(opts, ' ')) { X op2 = op; X while(*op++) X if(*op != ' ') *op2++ = *op; X } X*/ X if(!*opts) return; X negated = FALSE; X while((*opts == '!') || !strncmp(opts, "no", 2)) { X if(*opts == '!') opts++; else opts += 2; X negated = !negated; X } X X#ifndef MSDOS X if (!strncmp(opts, "standout", 4)) { X flags.standout = !negated; X return; X } X X if (!strncmp(opts, "null", 4)) { X flags.nonull = negated; X return; X } X#endif X X if (!strncmp(opts, "ignintr", 3)) { X flags.ignintr = !negated; X return; X } X X if (!strncmp(opts, "tombstone", 4)) { X flags.notombstone = negated; X return; X } X X#ifdef NEWS X if (!strncmp(opts, "news", 4)) { X flags.nonews = negated; X return; X } X#endif X X if (!strncmp(opts, "confirm", 4)) { X flags.confirm = !negated; X return; X } X if (!strncmp(opts, "safe", 4)) { X flags.safe_dog = !negated; X return; X } X X if (!strncmp(opts, "silent", 4)) { X flags.silent = !negated; X return; X } X X if (!strncmp(opts, "verbose", 4)) { X flags.verbose = !negated; X return; X } X X if (!strncmp(opts, "pickup", 4)) { X flags.pickup = !negated; X return; X } X X if (!strncmp(opts, "number_pad", 4)) { X flags.num_pad = !negated; X return; X } X X#ifdef DGK X if (!strncmp(opts, "IBM", 3)) { X flags.IBMBIOS = !negated; X return; X } X X if (!strncmp(opts, "rawio", 4)) { X if (from_env) X flags.rawio = !negated; X else X pline("\"rawio\" settable only from %s.", configfile); X return; X } X X#ifdef DECRAINBOW X if (!strncmp(opts, "DEC", 3)) { X flags.DECRainbow = !negated; X return; X } X#endif /* DECRAINBOW */ X#endif X X if (!strncmp(opts, "sort", 4)) { X flags.sortpack = !negated; X return; X } X X /* X * the order to list the pack X */ X if (!strncmp(opts, "packorder", 4)) { X register char *sp, *tmp; X int tmpend; X X op = index(opts,':'); X if(!op) goto bad; X op++; /* skip : */ X X /* Missing characters in new order are filled in at the end X * from inv_order. X */ X for (sp = op; *sp; sp++) X if (!index(inv_order, *sp)) X goto bad; /* bad char in order */ X else if (index(sp + 1, *sp)) X goto bad; /* dup char in order */ X tmp = (char *) alloc((unsigned)(strlen(inv_order)+1)); X Strcpy(tmp, op); X for (sp = inv_order, tmpend = strlen(tmp); *sp; sp++) X if (!index(tmp, *sp)) { X tmp[tmpend++] = *sp; X tmp[tmpend] = 0; X } X Strcpy(inv_order, tmp); X free((genericptr_t)tmp); X set_order = TRUE; X return; X } X X if (!strncmp(opts, "time", 4)) { X flags.time = !negated; X flags.botl = 1; X return; X } X X if (!strncmp(opts, "rest_on_space", 4)) { X flags.no_rest_on_space = negated; X return; X } X X if (!strncmp(opts, "fixinv", 3)) { X flags.invlet_constant = !negated; X if(!from_env && flags.invlet_constant) reassign (); X return; X } X X if (!strncmp(opts, "male", 4)) { X if(!from_env && flags.female != negated) X pline("That is not anatomically possible."); X else X flags.female = negated; X return; X } X if (!strncmp(opts, "female", 3)) { X if(!from_env && flags.female == negated) X pline("That is not anatomically possible."); X else X flags.female = !negated; X return; X } X X /* name:string */ X if (!strncmp(opts, "name", 4)) { X if(!from_env) { X#ifdef MSDOS X pline("\"name\" settable only from %s.", configfile); X#else X pline("The playername can be set only from NETHACKOPTIONS."); X#endif X return; X } X op = index(opts,':'); X if(!op) goto bad; X nmcpy(plname, op+1, sizeof(plname)-1); X return; X } X X /* graphics:string */ X if (!strncmp(opts, "graphics", 4)) { X if(!from_env) { X#ifdef MSDOS X pline("\"graphics\" settable only from %s.", configfile); X#else X pline("The graphics string can be set only from NETHACKOPTIONS."); X#endif X return; X } X op = index(opts,':'); X if(!op) X goto bad; X else X opts = op + 1; X escapes(opts, opts); X#define SETPCHAR(f, n) showsyms.f = (strlen(opts) > n) ? opts[n] : defsyms.f X SETPCHAR(stone, 0); X SETPCHAR(vwall, 1); X SETPCHAR(hwall, 2); X SETPCHAR(tlcorn, 3); X SETPCHAR(trcorn, 4); X SETPCHAR(blcorn, 5); X SETPCHAR(brcorn, 6); X SETPCHAR(crwall, 7); X SETPCHAR(tuwall, 8); X SETPCHAR(tdwall, 9); X SETPCHAR(tlwall, 10); X SETPCHAR(trwall, 11); X SETPCHAR(vbeam, 12); X SETPCHAR(hbeam, 13); X SETPCHAR(lslant, 14); X SETPCHAR(rslant, 15); X SETPCHAR(door, 16); X SETPCHAR(room, 17); X SETPCHAR(corr, 18); X SETPCHAR(upstair, 19); X SETPCHAR(dnstair, 20); X SETPCHAR(trap, 21); X SETPCHAR(web, 22); X SETPCHAR(pool, 23); X#ifdef FOUNTAINS X SETPCHAR(fountain, 24); X#endif X#ifdef SINKS X SETPCHAR(sink, 25); X#endif X#ifdef THRONES X SETPCHAR(throne, 26); X#endif X#ifdef ALTARS X SETPCHAR(altar, 27); X#endif X#ifdef STRONGHOLD X SETPCHAR(upladder, 28); X SETPCHAR(dnladder, 29); X SETPCHAR(dbvwall, 30); X SETPCHAR(dbhwall, 31); X#endif X#undef SETPCHAR X return; X } X X /* endgame:5t[op] 5a[round] o[wn] */ X if (!strncmp(opts, "endgame", 3)) { X op = index(opts,':'); X if(!op) goto bad; X op++; X while(*op) { X num = 1; X if(digit(*op)) { X num = atoi(op); X while(digit(*op)) op++; X } else X if(*op == '!') { X negated = !negated; X op++; X } X switch(*op) { X case 't': X flags.end_top = num; X break; X case 'a': X flags.end_around = num; X break; X case 'o': X flags.end_own = !negated; X break; X default: X goto bad; X } X while(letter(*++op)) ; X if(*op == '/') op++; X } X return; X } X if (!strncmp(opts, "dogname", 3)) { X if(!from_env) { X#ifdef MSDOS X pline("\"dogname\" settable only from %s.", configfile); X#else X Your("dog's name can be set only from NETHACKOPTIONS."); X#endif X return; X } X op = index(opts, ':'); X if (!op) goto bad; X nmcpy(dogname, ++op, 62); X return; X } X if (!strncmp(opts, "catname", 3)) { X if(!from_env) { X#ifdef MSDOS X pline("\"catname\" settable only from %s.", configfile); X#else X Your("cat's name can be set only from NETHACKOPTIONS."); X#endif X return; X } X op = index(opts, ':'); X if (!op) goto bad; X nmcpy(catname, ++op, 62); X return; X } X if (!strncmp(opts, "fruit", 2)) { X op = index(opts, ':'); X if (!op++) goto bad; X if (!from_env) { X struct fruit *f; X int numfruits = 0; X X for(f=ffruit; f; f=f->nextf) { X if (!strcmp(op, f->fname)) goto goodfruit; X numfruits++; X } X if (numfruits >= 100) { X pline("Doing that so many times isn't very fruitful."); X return; X } X } Xgoodfruit: X nmcpy(pl_fruit, op, PL_FSIZ); X if (!from_env) X (void)fruitadd(pl_fruit); X /* If from_env, then initoptions is allowed to do it instead X * of here (initoptions always has to do it even if there's X * no fruit option at all. Also, we don't want people X * setting multiple fruits in their options.) X */ X return; X } Xbad: X if(!from_env) { X if(!strncmp(opts, "h", 1) || X !strncmp(opts, "?", 1)) { X option_help(); X return; X } X pline("Unknown option: %s. Enter \"O?\" for help.", opts); X return; X } X#ifdef MSDOS X Printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts); X#else X Printf("Bad syntax in NETHACKOPTIONS: %s.", opts); X (void) puts("Use for example:"); X (void) puts( X"NETHACKOPTIONS=\"!rest_on_space,notombstone,endgame:own/5 topscorers/4 around me\"" X ); X#endif X getret(); X} X Xint Xdoset() X{ X char buf[BUFSZ]; X X pline("What options do you want to set? "); X getlin(buf); X if(!buf[0] || buf[0] == '\033') { X#ifdef MSDOS X Strcpy(buf,"OPTIONS="); X#ifdef DGK X if (flags.rawio) Strcat(buf,"rawio,"); X if (flags.IBMBIOS) Strcat(buf,"IBM_BIOS,"); X#endif /* DGK */ X#ifdef DECRAINBOW X if (flags.DECRainbow) Strcat(buf,"DEC_Rainbow,"); X#endif /* DECRAINBOW */ X#else /* MSDOS */ X Strcpy(buf,"NETHACKOPTIONS="); X if(flags.standout) Strcat(buf,"standout,"); X if(flags.nonull) Strcat(buf,"nonull,"); X#endif /* MSDOS */ X if(flags.ignintr) Strcat(buf,"ignintr,"); X if(flags.num_pad) Strcat(buf,"number_pad,"); X#ifdef NEWS X if(flags.nonews) Strcat(buf,"nonews,"); X#endif X if(flags.notombstone) Strcat(buf,"notombstone,"); X Strcat(buf, flags.female ? "female," : "male,"); X if(flags.no_rest_on_space) Strcat(buf,"!rest_on_space,"); X if (flags.invlet_constant) Strcat(buf,"fixinv,"); X if (flags.sortpack) Strcat(buf,"sortpack,"); X if (set_order){ X Strcat(buf, "packorder: "); X Strcat(buf, inv_order); X Strcat(buf, ","); X } X if (flags.confirm) Strcat(buf,"confirm,"); X if (flags.safe_dog) Strcat(buf,"safe_pet,"); X if (flags.pickup) Strcat(buf,"pickup,"); X if (flags.silent) Strcat(buf,"silent,"); X if (flags.time) Strcat(buf,"time,"); X if (flags.verbose) Strcat(buf,"verbose,"); X Sprintf(eos(buf), "fruit:%s,", pl_fruit); X if(flags.end_top != 5 || flags.end_around != 4 || flags.end_own){ X Sprintf(eos(buf), "endgame: %u top scores/%u around me", X flags.end_top, flags.end_around); X if(flags.end_own) Strcat(buf, "/own scores"); X } else { X register char *eop = eos(buf); X if(*--eop == ',') *eop = 0; X } X pline(buf); X } else { X clrlin(); X parseoptions(buf, FALSE); X } X X return 0; X} X Xint Xdotogglepickup() { X flags.pickup = !flags.pickup; X pline("Pickup: %s.", flags.pickup ? "ON" : "OFF"); X return 0; X} X Xchar packorder[] = { X AMULET_SYM, WEAPON_SYM, ARMOR_SYM, FOOD_SYM, SCROLL_SYM, X# ifdef SPELLS X SPBOOK_SYM, X# endif X WAND_SYM, RING_SYM, POTION_SYM, TOOL_SYM, GEM_SYM, BALL_SYM, ROCK_SYM }; X#define Page_line(x) if(page_line(x)) goto quit X Xvoid Xoption_help() { X char buf[BUFSZ]; X X set_pager(0); X Sprintf(buf, " NetHack Options Help:"); X if(page_line("") || page_line(buf) || page_line("")) goto quit; X X#ifdef MSDOS X Sprintf(buf, "To set options use OPTIONS=<options> in %s;", configfile); X Page_line(buf); X#else X Page_line("To set options use `NETHACKOPTIONS=\"<options>\"' in your environment;"); X#endif X X Page_line("or press \"O\" while playing, and type your <options> at the prompt."); X Page_line("In either case, <options> is a list of options separated by commas."); X Page_line(""); X X Page_line("Boolean options (which can be negated by prefixing them with '!' or \"no\"):"); X Page_line("confirm, (fe)male, fixinv, pickup, rest_on_space, safe_pet, silent, sortpack,"); X#ifdef MSDOS X#ifdef NEWS X Page_line("time, tombstone, verbose, news, number_pad, rawio, and IBM_BIOS"); X#else X Page_line("time, tombstone, verbose, number_pad, rawio, and IBM_BIOS"); X#endif X#ifdef DECRAINBOW X Page_line("and DEC_Rainbow."); X#endif /* DECRAINBOW */ X#else /* MSDOS */ X#ifdef NEWS X Page_line("time, tombstone, verbose, news, null, ignintr, and standout."); X#else X Page_line("time, tombstone, verbose, null, ignintr, and standout."); X#endif X#endif /* MSDOS */ X Page_line(""); X X Page_line("Compound options:"); X Page_line("`name' - your character's name (e.g., name:Merlin-W),"); X Page_line("`dogname' - the name of your (first) dog (e.g., dogname:Fang),"); X X Page_line("`packorder' - the inventory order of the items in your pack"); X Sprintf(buf, " (currently, packorder:%s ),", packorder); X Page_line(buf); X Page_line("`fruit' - the name of a fruit you enjoy eating,"); X X Page_line("`endgame' - the parts of the score list you wish to see,"); X X Page_line("`graphics' - defines the symbols to use in drawing the dungeon map."); X Page_line(""); X Page_line("Some of the options can be set only before the game is started. You will"); X Page_line("be so informed, if you attempt to set them while in the game."); X set_pager(1); X return; Xquit: X set_pager(2); X return; X} X X/* Returns the fid of the fruit type; if that type already exists, it X * returns the fid of that one; if it does not exist, it adds a new fruit X * type to the chain and returns the new one. X */ Xint Xfruitadd(str) Xchar *str; X{ X register int i,j; X register struct fruit *f; X struct fruit *lastf; X int highest_fruit_id = 0; X char buf[PL_FSIZ]; X boolean user_specified = (str == pl_fruit); X /* if not user-specified, then it's a fruit name for a fruit on X * a bones level... X */ X X /* Note: every fruit has an id (spe for fruit objects) of at least X * 1; 0 is an error. X */ X if (user_specified) { X /* disallow naming after other foods (since it'd be impossible X * to tell the difference) X */ X X boolean found = FALSE; X X for(i = bases[j=letindex(FOOD_SYM)]; i < bases[j+1]; i++) { X if (!strcmp(objects[i].oc_name, pl_fruit)) { X found = TRUE; X break; X } X } X if (found || X (!strncmp(buf, "tin of ", 7) && name_to_mon(buf+7) > -1) || X !strcmp(buf, "empty tin") || X !strcmp(buf, "tin of spinach") || X (!strncmp(eos(buf)-6," corpse",6) && name_to_mon(buf) > -1)) X { X Strcpy(buf, pl_fruit); X Strcpy(pl_fruit, "candied "); X nmcpy(pl_fruit+8, buf, PL_FSIZ-8); X } X } X for(f=ffruit; f; f = f->nextf) { X lastf = f; X if(f->fid > highest_fruit_id) highest_fruit_id = f->fid; X if(!strncmp(str, f->fname, PL_FSIZ)) X goto nonew; X } X /* if adding another fruit would overflow spe, use a random X fruit instead... we've got a lot to choose from. */ X if (highest_fruit_id >= 127) return rnd(127); X highest_fruit_id++; X f = newfruit(); X if (ffruit) lastf->nextf = f; X else ffruit = f; X Strcpy(f->fname, str); X f->fid = highest_fruit_id; X f->nextf = 0; Xnonew: X if (user_specified) current_fruit = highest_fruit_id; X return f->fid; X} END_OF_FILE if test 16326 -ne `wc -c <'src/options.c'`; then echo shar: \"'src/options.c'\" unpacked with wrong size! fi # end of 'src/options.c' fi echo shar: End of archive 18 \(of 38\). cp /dev/null ark18isdone MISSING="" 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 if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 38 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0