billr@saab.CNA.TEK.COM (Bill Randle) (07/24/89)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu> Posting-number: Volume 7, Issue 64 Archive-name: NetHack3/Part09 #! /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 9 (of 38)." # Contents: src/objnam.c src/u_init.c # Wrapped by billr@saab on Sun Jul 23 21:32:52 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'src/objnam.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/objnam.c'\" else echo shar: Extracting \"'src/objnam.c'\" \(33829 characters\) sed "s/^X//" >'src/objnam.c' <<'END_OF_FILE' X/* SCCS Id: @(#)objnam.c 3.0 88/11/30 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#define PREFIX 30 X X/* We want the player to be able to learn what key goes in what lock. */ Xconst char *keystr[N_LOX] = { "round", "square", "triangular", "oval", X "octagonal", "hexagonal", "cylindrical", X "irregular", "conical", "wedge-shaped" }, X *lockstr[N_LOX] = { "round", "square", "triangular", "oval", X "octagonal", "hexagonal", "wide", X "notched", "large round", "large square" }; X Xstatic int rnd_class P((int,int)); X Xstatic int Xnamed_key(s) register char *s; { X char tc[BUFSZ]; X register int i; X X for(i=0; i<10; i++) { X Strcpy(tc, keystr[i]); X Strcat(tc, " key"); X if(!strcmp(s,tc)) return(i+1); X } X return(0); X} X Xstatic int Xnamed_box(s) Xregister char *s; X{ X char tc[BUFSZ]; X register int i; X X for(i=0; i<10; i++) { X Strcpy(tc, lockstr[i]); X Strcat(tc, " keyhole)"); X if(!strcmp(s,tc)) return(i+1); X } X return(0); X} X Xstatic char * Xstrprepend(s,pref) register char *s, *pref; { Xregister int i = strlen(pref); X if(i > PREFIX) { X pline("WARNING: prefix too short."); X return(s); X } X s -= i; X (void) strncpy(s, pref, i); /* do not copy trailing 0 */ X return(s); X} X Xstatic char * Xsitoa(a) int a; { X#ifdef LINT /* static char buf[13]; */ X char buf[13]; X#else X static char buf[13]; X#endif X Sprintf(buf, (a < 0) ? "%d" : "+%d", a); X return(buf); X} X Xchar * Xtypename(otyp) Xregister int otyp; X{ X#ifdef LINT /* static char buf[BUFSZ]; */ Xchar buf[BUFSZ]; X#else Xstatic char buf[BUFSZ]; X#endif Xregister struct objclass *ocl = &objects[otyp]; Xregister char *an = ocl->oc_name; Xregister char *dn = ocl->oc_descr; Xregister char *un = ocl->oc_uname; Xregister int nn = ocl->oc_name_known; X switch(ocl->oc_olet) { X case POTION_SYM: X Strcpy(buf, "potion"); X break; X case SCROLL_SYM: X Strcpy(buf, "scroll"); X break; X case WAND_SYM: X Strcpy(buf, "wand"); X break; X#ifdef SPELLS X case SPBOOK_SYM: X Strcpy(buf, "spellbook"); X break; X#endif X case RING_SYM: X Strcpy(buf, "ring"); X break; X case AMULET_SYM: X if(nn) X Strcpy(buf,an); X else X Strcpy(buf,"amulet"); X if(un) X Sprintf(eos(buf)," called %s",un); X if(dn) X Sprintf(eos(buf)," (%s)",dn); X return(buf); X default: X if(nn) { X Strcpy(buf, an); X if(otyp >= TURQUOISE && otyp <= JADE) X Strcat(buf, " stone"); X if(un) X Sprintf(eos(buf), " called %s", un); X if(dn) X Sprintf(eos(buf), " (%s)", dn); X } else { X Strcpy(buf, dn ? dn : an); X if(ocl->oc_olet == GEM_SYM) { X if (otyp == LOADSTONE || otyp == LUCKSTONE) X Strcat(buf, " stone"); X else X Strcat(buf, " gem"); X } X if(un) X Sprintf(eos(buf), " called %s", un); X } X return(buf); X } X /* here for ring/scroll/potion/wand */ X if(nn) X Sprintf(eos(buf), " of %s", an); X if(un) X Sprintf(eos(buf), " called %s", un); X if(dn) X Sprintf(eos(buf), " (%s)", dn); X return(buf); X} X X/* Give the name of an object seen at a distance. Unlike xname/doname, X * we don't want to set dknown if it's not set already. The kludge used is X * to temporarily set Blind so that xname() skips the dknown setting. This X * assumes that we don't want to do this too often; if this function becomes X * frequently used, it'd probably be better to pass a parameter to xname() X * or doname() instead. X */ Xchar * Xdistant_name(obj, func) Xregister struct obj *obj; Xchar *(*func) P((struct obj *)); X{ X char *str; X X long save_Blinded = Blinded; X Blinded = 1; X str = func(obj); X Blinded = save_Blinded; X return str; X} X Xchar * Xxname(obj) Xregister struct obj *obj; X{ X#ifdef LINT /* lint may handle static decl poorly -- static char bufr[]; */ Xchar bufr[BUFSZ]; X#else Xstatic char bufr[BUFSZ]; X#endif Xregister char *buf = &(bufr[PREFIX]); /* leave room for "17 -3 " */ Xregister int nn = objects[obj->otyp].oc_name_known; Xregister char *an = objects[obj->otyp].oc_name; Xregister char *dn = objects[obj->otyp].oc_descr; Xregister char *un = objects[obj->otyp].oc_uname; X X buf[0] = 0; X if(!Blind) obj->dknown=1; X switch(obj->olet) { X case AMULET_SYM: X if(obj->otyp == AMULET_OF_YENDOR) { X Strcpy(buf, (obj->spe < 0 && obj->known) ? X "cheap plastic imitation of the " : ""); X Strcat(buf, an); X } else if (!obj->dknown) X Strcpy(buf, "amulet"); X else if (nn) X Strcpy(buf, an); X else if (un) X Sprintf(buf,"amulet called %s", un); X else X Sprintf(buf,"%s amulet", dn); X break; X case WEAPON_SYM: X if(obj->otyp <= SHURIKEN && obj->opoisoned) X Strcpy(buf, "poisoned "); X case VENOM_SYM: X case TOOL_SYM: X if(nn) Strcat(buf, an); X else Strcat(buf, dn); X if(obj->otyp == FIGURINE && obj->known) { X Sprintf(eos(buf), " of a%s %s", X index(vowels, *mons[obj->corpsenm].mname) X ? "n" : "", X mons[obj->corpsenm].mname); X break; X } X break; X case ARMOR_SYM: X if(obj->otyp==DRAGON_SCALE_MAIL) { X Sprintf(buf, "%s scale mail", X mons[obj->corpsenm].mname); X break; X } X X if(is_boots(obj) || is_gloves(obj)) Strcpy(buf,"pair of "); X X if(nn) Strcat(buf, an); X else if(un) { X if(is_boots(obj)) X Strcat(buf,"boots"); X else if(is_gloves(obj)) X Strcat(buf,"gloves"); X else if(is_cloak(obj)) X Strcpy(buf,"cloak"); X else if(is_helmet(obj)) X Strcpy(buf,"helmet"); X else if(is_shield(obj)) X Strcpy(buf,"shield"); X else X Strcpy(buf,"armor"); X Strcat(buf, " called "); X Strcat(buf, un); X } else Strcat(buf, dn); X break; X case FOOD_SYM: X if (obj->otyp == SLIME_MOLD) { X register struct fruit *f; X X for(f=ffruit; f; f = f->nextf) { X if(f->fid == obj->spe) { X Strcpy(buf, f->fname); X break; X } X } X if (!f) impossible("Bad fruit #%d?", obj->spe); X break; X } X Strcpy(buf, an); X if(obj->otyp == TIN && obj->known) { X if(obj->spe > 0) X Strcat(buf, " of spinach"); X else if (mons[obj->corpsenm].mlet == S_FUNGUS) X Sprintf(eos(buf), " of %s", mons[obj->corpsenm].mname); X else if(obj->corpsenm >= 0) X Sprintf(eos(buf), " of %s meat", mons[obj->corpsenm].mname); X else Strcpy(buf, "empty tin"); X } X break; X case CHAIN_SYM: X Strcpy(buf, an); X break; X case ROCK_SYM: X if(obj->otyp == STATUE) X Sprintf(buf, "%s of a%s %s", an, X (index(vowels, *(mons[obj->corpsenm].mname))) ? "n" : "", X mons[obj->corpsenm].mname); X else Strcpy(buf, an); X break; X case BALL_SYM: X Sprintf(buf, "%sheavy iron ball", X (obj->owt > objects[obj->otyp].oc_weight) ? "very " : ""); X break; X case POTION_SYM: X if(nn || un || !obj->dknown) { X Strcpy(buf, "potion"); X if(!obj->dknown) break; X if(nn) { X Strcat(buf, " of "); X if(obj->otyp == POT_WATER && X objects[POT_WATER].oc_name_known && X (obj->bknown || pl_character[0] == 'P') && X (obj->blessed || obj->cursed)) { X Strcat(buf, obj->blessed ? "holy " : "unholy "); X } X Strcat(buf, an); X } else { X Strcat(buf, " called "); X Strcat(buf, un); X } X } else { X Strcpy(buf, dn); X Strcat(buf, " potion"); X } X break; X case SCROLL_SYM: X Strcpy(buf, "scroll"); X if(!obj->dknown) break; X if(nn) { X Strcat(buf, " of "); X Strcat(buf, an); X } else if(un) { X Strcat(buf, " called "); X Strcat(buf, un); X } else { X Strcat(buf, " labeled "); X Strcat(buf, dn); X } X break; X case WAND_SYM: X if(!obj->dknown) X Sprintf(buf, "wand"); X else if(nn) X Sprintf(buf, "wand of %s", an); X else if(un) X Sprintf(buf, "wand called %s", un); X else X Sprintf(buf, "%s wand", dn); X break; X#ifdef SPELLS X case SPBOOK_SYM: X if(!obj->dknown) X Sprintf(buf, "spellbook"); X else if(nn) X Sprintf(buf, "spellbook of %s", an); X else if(un) X Sprintf(buf, "spellbook called %s", un); X else X Sprintf(buf, "%s spellbook", dn); X break; X#endif X case RING_SYM: X if(!obj->dknown) X Sprintf(buf, "ring"); X else if(nn) X Sprintf(buf, "ring of %s", an); X else if(un) X Sprintf(buf, "ring called %s", un); X else X Sprintf(buf, "%s ring", dn); X break; X case GEM_SYM: X if(!obj->dknown) { X if (obj->otyp == ROCK || obj->otyp == LOADSTONE X || obj->otyp == LUCKSTONE) X Strcpy(buf, "stone"); X else X Strcpy(buf, "gem"); X break; X } X if(!nn) { X char *rock=(obj->otyp==LOADSTONE||obj->otyp==LUCKSTONE) X ? "stone" : "gem"; X if(un) Sprintf(buf,"%s called %s", rock, un); X else Sprintf(buf, "%s %s", dn, rock); X break; X } X Strcpy(buf, an); X if(obj->otyp >= TURQUOISE && obj->otyp <= JADE) X Strcat(buf, " stone"); X break; X default: X Sprintf(buf,"glorkum %c (0%o) %u %d", X obj->olet,obj->olet,obj->otyp,obj->spe); X } X if(obj->quan != 1) Strcpy(buf, makeplural(buf)); X X if(obj->onamelth) { X Strcat(buf, " named "); X Strcat(buf, ONAME(obj)); X } X return(buf); X} X Xchar * Xdoname(obj) Xregister struct obj *obj; X{ X boolean ispoisoned = FALSE; X char prefix[PREFIX]; X char tmpbuf[PREFIX+1]; X /* when we have to add something at the start of prefix instead of the X * end (Strcat is used on the end) X */ X register char *bp = xname(obj); X /* When using xname, we want "poisoned arrow", and when using X * doname, we want "poisoned +0 arrow". This kludge is about the only X * way to do it, at least until someone overhauls xname() and doname(), X * combining both into one function taking a parameter. X */ X if (!strncmp(bp, "poisoned ", 9)) { X bp += 9; X ispoisoned = TRUE; X } X X if(obj->quan != 1) X Sprintf(prefix, "%u ", obj->quan); X else X Strcpy(prefix, "a "); X if((obj->bknown || pl_character[0] == 'P') && X (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known X || (!obj->cursed && !obj->blessed))) { X /* allow 'blessed clear potion' if we don't know it's holy water; X * always allow "uncursed potion of water" X */ X if(obj->cursed) X Strcat(prefix, "cursed "); X else if(obj->blessed) X Strcat(prefix, "blessed "); X else if (((obj->olet != ARMOR_SYM X && obj->olet != WAND_SYM X && obj->olet != WEAPON_SYM X && ((obj->olet != TOOL_SYM && X obj->olet != RING_SYM) || X !objects[obj->otyp].oc_charged)) X || !obj->known) X /* For items with charges or +/-, knowing the +/- means that X * the item has been totally identified, and therefore there X * is no doubt as to the object being uncursed if it's X * not described as "blessed" or "cursed". X * X * If the +/- isn't known, "uncursed" must be printed to X * avoid ambiguity between an item whose curse status is X * unknown, and an item known to be uncursed. X */ X#ifdef MAIL X && obj->otyp != SCR_MAIL X#endif X && obj->otyp != AMULET_OF_YENDOR && X pl_character[0] != 'P') X Strcat(prefix, "uncursed "); X } X switch(obj->olet) { X case AMULET_SYM: X if(obj->otyp == AMULET_OF_YENDOR) X if(strncmp(bp, "cheap ", 6)) { X Strcpy(tmpbuf, "the "); X Strcat(tmpbuf, prefix+2); /* skip the "a " */ X Strcpy(prefix, tmpbuf); X } X if(obj->owornmask & W_AMUL) X Strcat(bp, " (being worn)"); X break; X case WEAPON_SYM: X if(ispoisoned) X Strcat(prefix, "poisoned "); Xplus: X if(obj->known) { X Strcat(prefix, sitoa(obj->spe)); X Strcat(prefix, " "); X } X break; X case ARMOR_SYM: X if(obj->owornmask & W_ARMOR) X Strcat(bp, " (being worn)"); X goto plus; X case TOOL_SYM: /* temp. hack by GAN 11/18/86 */ X if(obj->owornmask & W_TOOL) { /* blindfold */ X Strcat(bp, " (being worn)"); X break; X } X#ifdef WALKIES X if(obj->otyp == LEASH && obj->leashmon != 0) { X Strcat(bp, " (in use)"); X break; X } X#endif X if(obj->otyp == KEY || X (obj->otyp == SKELETON_KEY && X !objects[obj->otyp].oc_name_known)) { X Strcat(prefix, keystr[obj->spe]); X Strcat(prefix, " "); X break; X } X if(obj->otyp == LARGE_BOX || obj->otyp == CHEST) { X Sprintf(eos(bp), " (%s keyhole)", lockstr[obj->spe]); X break; X } X if(obj->otyp == PICK_AXE) goto plus; X if(!objects[obj->otyp].oc_charged) break; X /* if special tool, fall through to show charges */ X case WAND_SYM: X if(obj->known) X Sprintf(eos(bp), " (%d)", obj->spe); X break; X case RING_SYM: X if(obj->owornmask & W_RINGR) Strcat(bp, " (on right "); X if(obj->owornmask & W_RINGL) Strcat(bp, " (on left "); X if(obj->owornmask & W_RING) { X Strcat(bp, body_part(HAND)); X Strcat(bp, ")"); X } X if(obj->known && objects[obj->otyp].oc_charged) { X Strcat(prefix, sitoa(obj->spe)); X Strcat(prefix, " "); X } X break; X case FOOD_SYM: X if(obj->otyp == CORPSE) { X Strcat(prefix, mons[obj->corpsenm].mname); X Strcat(prefix, " "); X } else if(obj->otyp == EGG && obj->known) { X if(obj->corpsenm >= 0) { X Strcat(prefix, mons[obj->corpsenm].mname); X Strcat(prefix, " "); X#ifdef POLYSELF X if (obj->spe) X Strcat(bp, " (laid by you)"); X#endif X } X } X break; X case BALL_SYM: X if(obj->owornmask & W_BALL) X Strcat(bp, " (chained to you)"); X break; X } X X if(obj->owornmask & W_WEP) { X Strcat(bp, " (weapon in "); X Strcat(bp, body_part(HAND)); X Strcat(bp, ")"); X } X if(obj->unpaid) X Strcat(bp, " (unpaid)"); X if (!strncmp(prefix, "a ", 2) && X index(vowels, *(prefix+2) ? *(prefix+2) : *bp) X && (*(prefix+2) || strncmp(bp, "uranium", 7))) { X Strcpy(tmpbuf, prefix); X Strcpy(prefix, "an "); X Strcpy(prefix+3, tmpbuf+2); X } X bp = strprepend(bp, prefix); X return(bp); X} X X/* used only in fight.c (thitu) */ Xvoid Xsetan(str,buf) Xregister char *str,*buf; X{ X if(index(vowels,*str)) X Sprintf(buf, "an %s", str); X else X Sprintf(buf, "a %s", str); X} X Xchar * Xaobjnam(otmp,verb) register struct obj *otmp; register char *verb; { Xregister char *bp = xname(otmp); Xchar prefix[PREFIX]; X if(otmp->quan != 1) { X Sprintf(prefix, "%u ", otmp->quan); X bp = strprepend(bp, prefix); X } X X if(verb) { X /* verb is given in plural (i.e., without trailing s) */ X Strcat(bp, " "); X if(otmp->quan != 1) X Strcat(bp, verb); X else if(!strcmp(verb, "are")) X Strcat(bp, "is"); X else { X Strcat(bp, verb); X Strcat(bp, "s"); X } X } X return(bp); X} X Xchar * XDoname2(obj) Xregister struct obj *obj; X{ X register char *s = doname(obj); X X if('a' <= *s && *s <= 'z') *s -= ('a' - 'A'); X return(s); X} X Xconst char *wrp[] = { "wand", "ring", "potion", "scroll", "gem", "amulet", X#ifdef SPELLS X "spellbook", X#endif X /* for non-specific wishes */ X "weapon", "armor", "tool", "food", "comestible", X }; Xconst char wrpsym[] = {WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM, AMULET_SYM, X#ifdef SPELLS X SPBOOK_SYM, X#endif X WEAPON_SYM, ARMOR_SYM, TOOL_SYM, FOOD_SYM, FOOD_SYM X }; X Xvoid Xlcase(str) Xregister char *str; X{ X register char *p; X for (p = str; *p; p++) X if('A' <= *p && *p <= 'Z') *p += 'a'-'A'; X} X X/* Plural routine; chiefly used for user-defined fruits. We have to try to X * account for everything reasonable the player has; something unreasonable X * can still break the code. However, it's still a lot more accurate than X * "just add an s at the end", which Rogue uses... X * X * Also used for plural monster names ("Wiped out all homunculi.") X * and body parts. X */ Xchar * Xmakeplural(oldstr) Xchar *oldstr; X{ X register char *spot; X static char str[BUFSZ]; X static char *excess; X int len; X X while (*oldstr==' ') oldstr++; X if (!oldstr || !*oldstr) { X impossible("plural of null?"); X return("s"); X } X Strcpy(str, oldstr); X X /* Search for common compounds, i.e. lump of royal jelly */ X for(excess=0, spot=str; *spot; spot++) { X if (!strncmp(spot, " of ", 4) || !strncmp(spot, " with ", 6) X || !strncmp(spot, " a la ", 6) X || !strncmp(spot, " from ", 6) X || !strncmp(spot, " in ", 4) X || !strncmp(spot, " labeled ", 9) X || !strncmp(spot, " called ", 8) X || !strncmp(spot, " named ", 7) X || !strncmp(spot, " on ", 4) X || !strcmp(spot, " above") /* lurkers above */ X || !strncmp(spot, " versus ", 8) X || !strncmp(spot, " de ", 4) X || !strncmp(spot, " d'", 3) X || !strncmp(spot, " du ", 4)) { X excess = oldstr + (spot - str); X *spot = 0; X break; X } X } X spot--; X while (*spot==' ') spot--; /* Strip blanks from end */ X *(spot+1) = 0; X /* Now spot is the last character of the string */ X X /* Single letters */ X len = strlen(str); X if (len==1) { X Strcpy(spot+1, "'s"); X goto bottom; X } X X /* man/men ("Wiped out all cavemen.") */ X if (len >= 3 && !strcmp(spot-2, "man") && X (len<6 || strcmp(spot-5, "shaman")) && X (len<5 || strcmp(spot-4, "human"))) { X *(spot-1) = 'e'; X goto bottom; X } X X /* mouse/mice,louse/lice (not a monster, but possible in a food name) */ X if (len >= 5 && !strcmp(spot-3, "ouse") && index("MmLl", *(spot-4))) { X Strcpy(spot-3, "ice"); X goto bottom; X } X X /* matzoh/matzot, possible food name */ X if (len >= 6 && !strcmp(spot-5, "matzoh")) { X *(spot) = 't'; X goto bottom; X } X X /* child/children (for the wise guys who give their food funny names) */ X if (len >= 5 && !strcmp(spot-4, "child")) { X Strcpy(spot, "dren"); X goto bottom; X } X X /* tooth/teeth */ X if (len >= 5 && !strcmp(spot-4, "tooth")) { X Strcpy(spot-3, "eeth"); X goto bottom; X } X X /* knife/knives, etc... */ X if (!strcmp(spot-1, "fe")) X *(spot-1) = 'v'; X else if (*spot == 'f') X if (index("lr", *(spot-1)) || index(vowels, *(spot-1))) X *spot = 'v'; X else if (!strncmp(spot-4, "staf", 4)) X Strcpy(spot-1, "ve"); X X /* foot/feet (body part) */ X if (len >= 4 && !strcmp(spot-3, "foot")) { X Strcpy(spot-2, "eet"); X goto bottom; X } X X /* ium/ia (mycelia, baluchitheria) */ X if (len >= 3 && !strcmp(spot-2, "ium")) { X *(spot--) = (char)0; X *spot = 'a'; X goto bottom; X } X X /* algae, larvae, hyphae (another fungus part) */ X if ((len >= 4 && !strcmp(spot-3, "alga")) || X (len >= 5 && X (!strcmp(spot-4, "hypha") || !strcmp(spot-4, "larva")))) { X Strcpy(spot, "ae"); X goto bottom; X } X X /* fungus/fungi, homunculus/homunculi */ X if (!strcmp(spot-1, "us")) { X *(spot--) = (char)0; X *spot = 'i'; X goto bottom; X } X X /* vortex/vortices */ X if (len >= 6 && !strcmp(spot-3, "rtex")) { X Strcpy(spot-1, "ices"); X goto bottom; X } X X /* djinni/djinn (note: also efreeti/efreet) */ X if (len >= 6 && !strcmp(spot-5, "djinni")) { X *(spot--) = (char)0; X goto bottom; X } X X /* same singular and plural */ X /* note: also swine, trout, grouse */ X if ((len >= 7 && !strcmp(spot-6, "samurai")) || X (len >= 5 && X (!strcmp(spot-4, "manes") || !strcmp(spot-4, "sheep"))) || X (len >= 4 && X (!strcmp(spot-3, "fish") || !strcmp(spot-3, "tuna") || X !strcmp(spot-3, "deer")))) X goto bottom; X X /* Aren't the following two going a bit far? --KAA */ X /* eau/eaux (gateau) */ X if (len >= 3 && !strcmp(spot-2, "eau")) { X Strcpy(spot, "ux"); X goto bottom; X } X X /* sis/ses (oasis, nemesis) */ X if (len >= 3 && !strcmp(spot-2, "sis")) { X *(spot-1) = 'e'; X goto bottom; X } X X /* note: ox/oxen, VAX/VAXen, goose/geese */ X X /* Ends in z, x, s, ch, sh; add an "es" */ X if (index("zxsv", *spot) || (*spot=='h' && index("cs", *(spot-1))) || X /* Kludge to get "tomatoes" and "potatoes" right */ X (len >= 4 && !strcmp(spot-2, "ato"))) { X Strcpy(spot+1, "es"); X goto bottom; X } X X /* Ends in y preceded by consonant or "qu"; change to "ies" */ X if (*spot == 'y' && X (!index(vowels, *(spot-1)) || !strncmp("qu", spot-2, 2))) { X Strcpy(spot, "ies"); X goto bottom; X } X X /* Default: append an 's' */ X Strcpy(spot+1, "s"); X Xbottom: if (excess) Strcpy(str+strlen(str), excess); X return str; X} X Xstatic const char *armor_classes[] = { X /* "shield called reflection" gives a specific type of shield. X * "shield" gives a random type of shield--but not of all armor. X */ X "gloves", "boots", "cloak", "shield", "helmet" X}; X#define ARMOR_CLASSES 5 X X/* Return something wished for. If not an object, return &zeroobj; if an error X * (no matching object), return (struct obj *)0. Giving readobjnam() a null X * pointer skips the error return and creates a random object instead. X */ Xstruct obj * Xreadobjnam(bp) Xregister char *bp; X{ X register char *p; X register int i; X register struct obj *otmp; X struct fruit *f; X int cnt, spe, spesgn, typ, heavy, blessed, uncursed; X int iscursed, ispoisoned, mntmp, contents, iskey=0; X int isnamedbox=0, ftype = current_fruit; X char let; X char *un, *dn, *an; X char *name=0; X char fruitbuf[BUFSZ]; X /* We want to check for fruits last so that, for example, someone X * who names their fruit "katana" and wishes for a katana gets a real X * one. But, we have to keep around the old buf since in the meantime X * we have deleted "empty", "+6", etc... X */ X#ifdef WIZARD X int fake=0; X#endif X X cnt = spe = spesgn = typ = heavy = X blessed = uncursed = iscursed = ispoisoned = 0; X mntmp = -1; X#define UNDEFINED 0 X#define EMPTY 1 X#define SPINACH 2 X contents = UNDEFINED; X let = 0; X an = dn = un = 0; X X for(;;) { X if (!bp) goto any; X if(!strncmp(bp, "an ", 3)) { X cnt = 1; X bp += 3; X } else if(!strncmp(bp, "a ", 2)) { X cnt = 1; X bp += 2; X } else if(!strncmp(bp, "cheap plastic imitation of ", 27)) { X#ifdef WIZARD X fake = 1; X#endif X bp += 27; X } else if(!strncmp(bp, "the ", 4)){ X /* the = 1; */ X bp += 4; X } else if(!cnt && digit(*bp)){ X cnt = atoi(bp); X while(digit(*bp)) bp++; X while(*bp == ' ') bp++; X } else if(!strncmp(bp,"blessed ",8) || !strncmp(bp,"holy ",5)) { X blessed=1; X bp += 8; X } else if(!strncmp(bp,"cursed ",7) || !strncmp(bp,"unholy ",7)){ X iscursed=1; X bp += 7; X } else if(!strncmp(bp, "uncursed ",9)) { X uncursed=1; X bp += 9; X } else break; X } X if(!cnt) cnt = 1; /* %% what with "gems" etc. ? */ X Strcpy(fruitbuf, bp); X if(!strncmp(bp, "empty ", 6)) { X contents = EMPTY; X bp += 6; X } else if(!strncmp(bp, "poisoned ",9)) { X ispoisoned=1; X bp += 9; X#ifdef WIZARD X } else if(wizard && !strncmp(bp, "trapped ",8)) { X ispoisoned=1; X bp += 8; X#endif X } X if(*bp == '+' || *bp == '-'){ X spesgn = (*bp++ == '+') ? 1 : -1; X spe = atoi(bp); X while(digit(*bp)) bp++; X while(*bp == ' ') bp++; X } else { X p = rindex(bp, '('); X if(p) { X if(p > bp && p[-1] == ' ') p[-1] = 0; X else *p = 0; X p++; X if (!(isnamedbox = named_box(p))) { X spe = atoi(p); X while(digit(*p)) p++; X if (*p != ')') spe = 0; X else { X spesgn = 1; X p++; X if (*p) Strcat(bp, p); X } X } X } X } X /* now we have the actual name, as delivered by xname, say X green potions called whisky X scrolls labeled "QWERTY" X egg X fortune cookies X very heavy iron ball named hoei X wand of wishing X elven cloak X */ X for(p = bp; *p; p++) if(!strncmp(p, " named ", 7)) { X *p = 0; X name = p+7; X } X for(p = bp; *p; p++) if(!strncmp(p, " called ", 8)) { X *p = 0; X un = p+8; X /* "helmet called telepathy" is not "helmet" (a specific type) X * "shield called reflection" is not "shield" (a general type) X */ X for(i=0; i<ARMOR_CLASSES; i++) X if(!strncmp(bp,armor_classes[i], strlen(armor_classes[i]))){ X let = ARMOR_SYM; X goto srch; X } X } X for(p = bp; *p; p++) if(!strncmp(p, " labeled ", 9)) { X *p = 0; X dn = p+9; X } X for(p = bp; *p; p++) if(!strncmp(p, " labelled ", 10)) { X *p = 0; X dn = p+10; X } X for(p = bp; *p; p++) if(!strncmp(p, " of spinach", 11)) { X *p = 0; X contents = SPINACH; X } X X /* Skip over "pair of ", then jump to the singular so we don't X try to convert "gloves" or "boots". */ X if(cnt == 1 && !strncmp(bp, "pair of ",8)) { X bp += 8; X cnt = 2; X /* cnt is ignored for armor and other non-stackable objects; X DTRT for stackable objects */ X } else if(cnt > 1 && !strncmp(bp, "pairs of ",9)) { X bp += 9; X cnt *= 2; X } X X /* Find corpse type using "of" (figurine of an orc, tin of orc meat) */ X for(p = bp; *p; p++) X if (!strncmp(p, " of ", 4) && (mntmp = name_to_mon(p+4)) >= 0) { X *p = 0; X break; X } X /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */ X if (strncmp(bp, "samurai sword", 13)) /* not the "samurai" monster! */ X if (strncmp(bp, "orcish", 6)) /* not the "orc" monster! */ X if (mntmp < 0) if ((mntmp = name_to_mon(bp)) >= 0) { X bp += strlen(mons[mntmp].mname); X if (*bp==' ') bp++; X } X X /* first change to singular if necessary */ X if(cnt != 1) { X /* find "cloves of garlic", "worthless pieces of blue glass" */ X for(p = bp; *p; p++) X if(!strncmp(p, "s of ", 5)){ X /* but don't singularize "gauntlets" */ X if(strncmp(p-8, "gauntlet", 8)) X while(*p = p[1]) p++; X goto sing; X } X /* remove -s or -es (boxes) or -ies (rubies) */ X p = eos(bp); X if(p[-1] == 's') { X if(p[-2] == 'e') { X if(p[-3] == 'i') { X X if(!strcmp(p-7, "cookies") || X !strcmp(p-4, "pies")) X goto mins; X Strcpy(p-3, "y"); X goto sing; X } X X /* note: cloves / knives from clove / knife */ X if(!strcmp(p-6, "knives")) { X Strcpy(p-3, "fe"); X goto sing; X } X X /* note: nurses, axes but boxes */ X if(!strcmp(p-5, "boxes")) { X p[-2] = 0; X goto sing; X } X } X /* but don't singularize boots or gloves */ X else if(!strcmp(p-5, "boots") || X !strcmp(p-6, "gloves")) X goto sing; X mins: X p[-1] = 0; X } else { X if(!strcmp(p-5, "teeth")) { X Strcpy(p-5, "tooth"); X goto sing; X } X /* here we cannot find the plural suffix */ X } X } Xsing: X /* Maybe we need a special strcmp() which ignores capitalization and X * dashes/spaces/underscores, so the below 3 special cases would be X * unnecessary. X */ X /* Alternate spellings (two-handed sword vs. two handed sword) */ X if(!strcmp(bp, "two handed sword")) { X typ = TWO_HANDED_SWORD; X goto typfnd; X } X /* pick-axe vs. pick axe */ X if(!strcmp(bp, "pick axe")) { X typ = PICK_AXE; X goto typfnd; X } X if(!strcmp(bp, "luck stone")){ X typ = LUCKSTONE; X goto typfnd; X } X if(!strcmp(bp, "load stone")){ X typ = LOADSTONE; X goto typfnd; X } X /* Alternate capitalizations (Amulet of Yendor, amulet of esp) */ X if(!strcmp(bp, "amulet of Yendor")) { X typ = AMULET_OF_YENDOR; X goto typfnd; X } X if(!strcmp(bp, "amulet of ESP")) { X typ = AMULET_OF_ESP; X goto typfnd; X } X if(!strcmp(bp, "ring mail") || /* Note: ring mail is not a ring ! */ X !strcmp(bp, "leather armor") || /* Prevent falling to 'armor'. */ X !strcmp(bp, "studded leather armor")) { X let = ARMOR_SYM; X an = bp; X goto srch; X } X if(!strcmp(bp, "food ration")){ X let = FOOD_SYM; X an = bp; X goto srch; X } X if((iskey = named_key(bp)) > 0) { X typ = KEY; X goto typfnd; X } X p = eos(bp); X if(!strcmp(p-10, "holy water")) { X typ = POT_WATER; X if (*(p-12) == 'u') iscursed = 1; /* unholy water */ X else blessed = 1; X goto typfnd; X } X#ifdef SHIRT X if (!strcmp(p-5, "shirt")) { X typ = HAWAIIAN_SHIRT; X goto typfnd; X } X#endif X if (strlen(bp) == 1 && index(obj_symbols, *bp)) { X let = *bp; X goto any; X } X if(strncmp(bp, "enchant ", 8) && X strncmp(bp, "destroy ", 8) && X strncmp(bp, "food detection", 14)) X /* allow wishes for "enchant weapon" and "food detection" */ X for(i = 0; i < sizeof(wrpsym); i++) { X register int j = strlen(wrp[i]); X if(!strncmp(bp, wrp[i], j)){ X let = wrpsym[i]; X if(let != AMULET_SYM) { X bp += j; X if(!strncmp(bp, " of ", 4)) an = bp+4; X /* else if(*bp) ?? */ X } else X an = bp; X goto srch; X } X if(!strcmp(p-j, wrp[i])){ X let = wrpsym[i]; X p -= j; X *p = 0; X if(p[-1] == ' ') p[-1] = 0; X dn = bp; X goto srch; X } X } X if(!strcmp(p-6, " stone")){ X p[-6] = 0; X let = GEM_SYM; X dn = an = bp; X goto srch; X } X if(!strcmp(p-10, "gold piece") || !strcmp(p-7, "zorkmid") || X !strcmp(bp, "Zorkmid") || X !strcmp(bp, "gold") || !strcmp(bp, "money") || *bp == GOLD_SYM) { X if (cnt > 5000 X#ifdef WIZARD X && !wizard X#endif X ) cnt=5000; X if (cnt < 1) cnt=1; X pline("%d gold piece%s.", cnt, cnt==1 ? "" : "s"); X u.ugold += cnt; X flags.botl=1; X return (&zeroobj); X } X#ifdef WIZARD X /* Let wizards wish for traps --KAA */ X if (wizard) { X int trap; X char *tname; X X for (trap = NO_TRAP+1; trap < TRAPNUM; trap++) { X tname = index(traps[trap], ' '); X if (tname) { X if (!strncmp(tname+1, bp, strlen(tname+1))) { X (void) maketrap(u.ux, u.uy, trap); X pline("A%s.", traps[trap]); X if (Invisible) newsym(u.ux,u.uy); X return(&zeroobj); X } X } X } X } X#endif X if(!strcmp(bp, "very heavy iron ball")) { X heavy = 1; X typ = HEAVY_IRON_BALL; X goto typfnd; X } X if(!strcmp(bp, "bag")) { X typ = rnd_class(SACK, BAG_OF_TRICKS); X goto typfnd; X } X if(!strcmp(bp, armor_classes[0])){ /* pair of gloves */ X typ = rnd_class(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY); X goto typfnd; X } X if(!strcmp(bp, armor_classes[1])){ /* pair of boots */ X typ = rnd_class(LOW_BOOTS, LEVITATION_BOOTS); X goto typfnd; X } X if(!strcmp(bp, armor_classes[2])){ /* cloak */ X typ = rnd_class(MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT); X goto typfnd; X } X if(!strcmp(bp, armor_classes[3])){ /* shield */ X typ = rnd_class(SMALL_SHIELD, SHIELD_OF_REFLECTION); X goto typfnd; X } X /* helmet is not generic */ X X an = bp; X if (!dn) dn = an; /* i.e., "black cap" */ Xsrch: X i = 1; X if(let) i = bases[letindex(let)]; X while(i <= NROFOBJECTS && (!let || objects[i].oc_olet == let)){ X register char *zn; X X if(an && (zn = objects[i].oc_name) && !strcmp(an, zn)) { X typ = i; X goto typfnd; X } X if(dn && (zn = objects[i].oc_descr) && !strcmp(dn, zn)) { X typ = i; X goto typfnd; X } X if(un && (zn = objects[i].oc_uname) && !strcmp(un, zn)) { X typ = i; X goto typfnd; X } X i++; X } X for(f=ffruit; f; f = f->nextf) { X char *f1 = f->fname, *f2 = makeplural(f->fname); X X if(!strncmp(fruitbuf, f1, strlen(f1)) || X !strncmp(fruitbuf, f2, strlen(f2))) { X typ = SLIME_MOLD; X ftype = f->fid; X goto typfnd; X } X } X if(!let) return((struct obj *)0); Xany: X if(!let) let = wrpsym[rn2(sizeof(wrpsym))]; Xtypfnd: X if(typ) { X let = objects[typ].oc_olet; X otmp = mksobj(typ,FALSE); X } else { X otmp = mkobj(let,FALSE); X typ = otmp->otyp; X } X X /* venom isn't really an object and can't be wished for; but allow X * wizards to wish for it since it's faster than polymorphing and X * spitting. X */ X if(otmp->olet==VENOM_SYM X#ifdef WIZARD X && !wizard X#endif X ) { X free((genericptr_t) otmp); X return((struct obj *)0); X } X if(iskey) otmp->spe = (iskey-1); X if(isnamedbox && (otmp->otyp==LARGE_BOX || otmp->otyp==CHEST)) X otmp->spe = (isnamedbox-1); X X if(cnt > 0 && objects[typ].oc_merge && X#ifdef SPELLS X let != SPBOOK_SYM && X#endif X (cnt < rnd(6) || X#ifdef WIZARD X wizard || X#endif X (cnt <= 20 && X (let == WEAPON_SYM && typ <= SHURIKEN) || (typ == ROCK)))) X otmp->quan = cnt; X X if (spesgn == 0) spe = otmp->spe; X#ifdef WIZARD X else if (wizard) /* no alteration to spe */ ; X#endif X else if (let == ARMOR_SYM || let == WEAPON_SYM || typ == PICK_AXE || X (let==RING_SYM && objects[typ].oc_charged)) { X if(spe > rnd(5) && spe > otmp->spe) spe = 0; X if(spe > 2 && u.uluck < 0) spesgn = -1; X } else { X if (let == WAND_SYM) { X if (spe > 1 && spesgn == -1) spe = 1; X } else { X if (spe > 0 && spesgn == -1) spe = 0; X } X if (spe > otmp->spe) spe = otmp->spe; X } X X if (spesgn == -1) spe = -spe; X X /* set otmp->spe. This may, or may not, use spe... */ X switch (typ) { X case TIN: if (contents==EMPTY) { X otmp->corpsenm = -1; X otmp->spe = 0; X } else if (contents==SPINACH) { X otmp->corpsenm = -1; X otmp->spe = 1; X } X break; X case SLIME_MOLD: otmp->spe = ftype; X /* Fall through */ X case SKELETON_KEY: case KEY: case CHEST: case LARGE_BOX: X case HEAVY_IRON_BALL: case IRON_CHAIN: case STATUE: X /* otmp->spe already done in mksobj() */ X break; X#ifdef MAIL X case SCR_MAIL: otmp->spe = 1; break; X#endif X case AMULET_OF_YENDOR: X#ifdef WIZARD X if (fake || !wizard) X#endif X otmp->spe = -1; X#ifdef WIZARD X else otmp->spe = 0; X#endif X break; X case WAN_WISHING: X#ifdef WIZARD X if (!wizard) X#endif X otmp->spe = (rn2(10) ? -1 : 0); break; X /* fall through, if wizard */ X default: otmp->spe = spe; X } X X /* set otmp->corpsenm */ X if (mntmp > -1) switch(typ) { X case TIN: X otmp->spe = 0; /* No spinach */ X case CORPSE: X if (!(mons[mntmp].geno & G_NOCORPSE)) X otmp->corpsenm = mntmp; X break; X case FIGURINE: X if (!is_dlord(&mons[mntmp]) && !is_dprince(&mons[mntmp]) X && !is_human(&mons[mntmp]) X#ifdef WORM X && mntmp != PM_LONG_WORM X#endif X ) X otmp->corpsenm = mntmp; X break; X case EGG: if (lays_eggs(&mons[mntmp]) || mntmp==PM_KILLER_BEE) X otmp->corpsenm = mntmp; X break; X case STATUE: otmp->corpsenm = mntmp; X break; X case DRAGON_SCALE_MAIL: /* Not actually possible unless they X typed "red dragon dragon scale mail" */ X case SCALE_MAIL: X if (mntmp >= PM_GREY_DRAGON && X mntmp <= PM_YELLOW_DRAGON) X otmp->corpsenm = mntmp; X if (otmp->corpsenm >= 0) X otmp->otyp = DRAGON_SCALE_MAIL; X break; X } X X /* set blessed/cursed */ X if (iscursed) { X curse(otmp); X } else if (uncursed) { X otmp->blessed = 0; X otmp->cursed = (u.uluck < 0); X } else if (blessed) { X otmp->blessed = (u.uluck >= 0); X otmp->cursed = (u.uluck < 0); X } else if (spesgn < 0) { X curse(otmp); X } X X /* set poisoned */ X if (ispoisoned) { X if (let == WEAPON_SYM && typ <= SHURIKEN) X otmp->opoisoned = (u.uluck >= 0); X#ifdef WIZARD X else if (Is_box(otmp)) X otmp->otrapped = 1; X else if (let == FOOD_SYM) X /* try to taint by making it as old as possible */ X otmp->age = 1L; X#endif X } X X if (name) otmp = oname(otmp, name, 0); X otmp->owt = weight(otmp); X if (heavy) otmp->owt += 15; X return(otmp); X} X Xboolean Xuses_known(otmp) Xregister struct obj *otmp; X/* returns TRUE if otmp->known would be used to affect the full description X * of the item X * if not, otmp->dknown and otmp->bknown give all the information of otmp->known X * and otmp->known should always be set to avoid problems with items not X * merging due to different values of otmp->known X */ X{ X return (otmp->olet == ARMOR_SYM || X otmp->olet == WAND_SYM || X otmp->olet == WEAPON_SYM || X ((otmp->olet == TOOL_SYM || otmp->olet == RING_SYM) && X objects[otmp->otyp].oc_charged) || X otmp->otyp == FIGURINE || X otmp->otyp == EGG || X otmp->otyp == TIN || X otmp->otyp == AMULET_OF_YENDOR); X} X Xstatic int Xrnd_class(first,last) Xint first,last; X{ X int i, x, sum=0; X for(i=first; i<=last; i++) X sum += objects[i].oc_prob; X x = rnd(sum); X for(i=first; i<=last; i++) X if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0) X return i; X return 0; X} END_OF_FILE if test 33829 -ne `wc -c <'src/objnam.c'`; then echo shar: \"'src/objnam.c'\" unpacked with wrong size! fi # end of 'src/objnam.c' fi if test -f 'src/u_init.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/u_init.c'\" else echo shar: Extracting \"'src/u_init.c'\" \(17550 characters\) sed "s/^X//" >'src/u_init.c' <<'END_OF_FILE' X/* SCCS Id: @(#)u_init.c 3.0 88/04/13 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 trobj { X unsigned short int trotyp; X schar trspe; X char trolet; X Bitfield(trquan,6); X Bitfield(trknown,1); X Bitfield(trbless,2); X}; X Xstatic void ini_inv P((struct trobj *)); X X#define UNDEF_TYP 0 X#define UNDEF_SPE '\177' X#define UNDEF_BLESS 2 X Xchar *(roles[]) = { /* must all have distinct first letter */ X /* roles[2] and [6] are changed for females */ X /* in all cases, the corresponding male and female */ X /* roles must start with the same letter */ X "Archeologist", "Barbarian", "Cave-man", "Elf", "Healer", "Knight", X "Priest", "Rogue", "Samurai", "Tourist", "Valkyrie", "Wizard" X}; X Xstruct you zerou; X X#define NR_OF_ROLES SIZE(roles) Xchar rolesyms[NR_OF_ROLES + 1]; /* filled by u_init() */ X Xstruct trobj Cave_man[] = { X#define C_ARROWS 2 X { CLUB, 1, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { BOW, 1, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { ARROW, 0, WEAPON_SYM, 25, 1, UNDEF_BLESS }, /* quan is variable */ X { LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Barbarian[] = { X { TWO_HANDED_SWORD, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { AXE, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { RING_MAIL, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { FOOD_RATION, 0, FOOD_SYM, 1, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Knight[] = { X { LONG_SWORD, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { SPEAR, 2, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { RING_MAIL, 1, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { HELMET, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { SMALL_SHIELD, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { LEATHER_GLOVES, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Elf[] = { X#define E_ARROWS 2 X#define E_ARMOR 3 X#ifdef TOLKIEN X { ELVEN_SHORT_SWORD, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { ELVEN_BOW, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { ELVEN_ARROW, 0, WEAPON_SYM, 25, 1, UNDEF_BLESS }, X { UNDEF_TYP, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { LEMBAS_WAFER, 0, FOOD_SYM, 2, 1, 0 }, X#else X { SHORT_SWORD, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { BOW, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { ARROW, 0, WEAPON_SYM, 25, 1, UNDEF_BLESS }, X { ELVEN_CLOAK, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { FOOD_RATION, 0, FOOD_SYM, 2, 1, 0 }, X#endif X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Valkyrie[] = { X { LONG_SWORD, 1, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { DAGGER, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { SMALL_SHIELD, 3, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { FOOD_RATION, 0, FOOD_SYM, 1, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Healer[] = { X { SCALPEL, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { LEATHER_GLOVES, 1, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { STETHOSCOPE, 0, TOOL_SYM, 1, 1, 0 }, X { POT_HEALING, 0, POTION_SYM, 4, 1, UNDEF_BLESS }, X { POT_EXTRA_HEALING, 0, POTION_SYM, 4, 1, UNDEF_BLESS }, X { WAN_SLEEP, UNDEF_SPE, WAND_SYM, 1, 1, UNDEF_BLESS }, X { APPLE, 0, FOOD_SYM, 5, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Archeologist[] = { X /* if adventure has a name... idea from tan@uvm-gen */ X { BULLWHIP, 2, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { FEDORA, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { FOOD_RATION, 0, FOOD_SYM, 3, 1, 0 }, X { PICK_AXE, UNDEF_SPE, TOOL_SYM, 1, 1, UNDEF_BLESS }, X { TINNING_KIT, 0, TOOL_SYM, 1, 1, UNDEF_BLESS }, X { SACK, 0, TOOL_SYM, 1, 0, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Tinopener[] = { X { TIN_OPENER, 0, TOOL_SYM, 1, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Magicmarker[] = { X { MAGIC_MARKER, UNDEF_SPE, TOOL_SYM, 1, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Lamp[] = { X { LAMP, 5, TOOL_SYM, 1, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X X#ifndef HARD Xstruct trobj Saving[] = { X { AMULET_OF_LIFE_SAVING, 0, TOOL_SYM, 1, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X#endif X X#ifdef EXPLORE_MODE Xstruct trobj Wishing[] = { X { WAN_WISHING, 3, WAND_SYM, 1, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X#endif X X#ifdef WALKIES Xstruct trobj Leash[] = { X { LEASH, 0, TOOL_SYM, 1, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X#endif X Xstruct trobj Blindfold[] = { X { BLINDFOLD, 0, TOOL_SYM, 1, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Tourist[] = { X#define T_DARTS 0 X { DART, 2, WEAPON_SYM, 25, 1, UNDEF_BLESS }, /* quan is variable */ X { UNDEF_TYP, UNDEF_SPE, FOOD_SYM, 10, 1, 0 }, X { POT_EXTRA_HEALING, 0, POTION_SYM, 2, 1, UNDEF_BLESS }, X { SCR_MAGIC_MAPPING, 0, SCROLL_SYM, 4, 1, UNDEF_BLESS }, X { EXPENSIVE_CAMERA, 0, TOOL_SYM, 1, 1, 0 }, X#ifdef SHIRT X { HAWAIIAN_SHIRT, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X#endif X { CREDIT_CARD, 0, TOOL_SYM, 1, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Rogue[] = { X#define R_DAGGERS 1 X { SHORT_SWORD, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { DAGGER, 0, WEAPON_SYM, 10, 1, 0 }, /* quan is variable */ X { LEATHER_ARMOR, 1, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { POT_SICKNESS, 0, POTION_SYM, 1, 1, 0 }, X { LOCK_PICK, 9, TOOL_SYM, 1, 1, 0 }, X { SACK, 0, TOOL_SYM, 1, 0, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Wizard[] = { X#define W_MULTSTART 2 X#ifdef SPELLS X# define W_MULTEND 6 X#else X# define W_MULTEND 5 X#endif X { DAGGER, 0, WEAPON_SYM, 1, 1, 1 }, /* for dealing with ghosts */ X { CLOAK_OF_MAGIC_RESISTANCE, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { UNDEF_TYP, UNDEF_SPE, WAND_SYM, 1, 1, UNDEF_BLESS }, X { UNDEF_TYP, UNDEF_SPE, RING_SYM, 2, 1, UNDEF_BLESS }, X { UNDEF_TYP, UNDEF_SPE, POTION_SYM, 3, 1, UNDEF_BLESS }, X { UNDEF_TYP, UNDEF_SPE, SCROLL_SYM, 3, 1, UNDEF_BLESS }, X#ifdef SPELLS X { UNDEF_TYP, UNDEF_SPE, SPBOOK_SYM, 1, 1, UNDEF_BLESS }, X#endif X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Samurai[] = { X { KATANA, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, X { SHORT_SWORD, 0, WEAPON_SYM, 1, 1, UNDEF_BLESS }, /* the wakizashi */ X { SHURIKEN, 0, WEAPON_SYM, 9, 1, UNDEF_BLESS }, /* quan is variable */ X { SPLINT_MAIL, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { FORTUNE_COOKIE, 0, FOOD_SYM, 3, 1, 0 }, X { 0, 0, 0, 0, 0, 0 } X}; X Xstruct trobj Priest[] = { X { MACE, 1, WEAPON_SYM, 1, 1, 1 }, X { CHAIN_MAIL, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { SMALL_SHIELD, 0, ARMOR_SYM, 1, 1, UNDEF_BLESS }, X { POT_WATER, 0, POTION_SYM, 4, 1, 1 }, /* holy water */ X { CLOVE_OF_GARLIC, 0, FOOD_SYM, 1, 1, 0 }, X#ifdef SPELLS X { UNDEF_TYP, UNDEF_SPE, SPBOOK_SYM, 2, 1, UNDEF_BLESS }, X#endif X { 0, 0, 0, 0, 0, 0 } X}; X Xstatic void Xknows_class(sym) Xregister char sym; X{ X register unsigned ct; X for (ct = 1; ct <= NROFOBJECTS; ct++) X if (objects[ct].oc_olet == sym) { X makeknown(ct); X objects[ct].oc_descr = NULL; /* not a "discovery" */ X } X} X Xstatic int Xrole_index(pc) Xchar pc; X{ /* must be called only from u_init() */ X /* so that rolesyms[] is defined */ X register char *cp; X X if(cp = index(rolesyms, pc)) X return(cp - rolesyms); X return(-1); X} X Xvoid Xu_init() X{ X register int i; X char pick, pc; X X Printf("\nNetHack, Copyright 1985, 1986, 1987, 1988, 1989."); X Printf("\n By Stichting Mathematisch Centrum and M. Stephenson."); X Printf("\n See license for details.\n\n"); X X if(flags.female) { /* should have been set in NETHACKOPTIONS */ X roles[2] = "Cave-woman"; X roles[6] = "Priestess"; X } X for(i = 0; i < NR_OF_ROLES; i++) X rolesyms[i] = roles[i][0]; X rolesyms[i] = 0; X X if(pc = pl_character[0]) { X if('a' <= pc && pc <= 'z') pc += 'A'-'a'; X if((i = role_index(pc)) >= 0) X goto got_suffix; X Printf("\nUnknown role: %c\n", pc); X pl_character[0] = pc = 0; X } X X Printf("\nShall I pick a character for you? [Y,N, or Q(quit)] "); X X while(!index("yYnNqQ", (pick = readchar())) && !index(quitchars, pick)) X bell(); X X if(index(quitchars, pick)) pick = 'Y'; X else if('a' <= pick && pick <= 'z') pick += 'A'-'a'; X X Printf("%c\n", pick); /* echo */ X X if (pick == 'Q') { X clearlocks(); X settty(NULL); X exit(0); X } X X if (pick == 'Y') X goto beginner; X X Printf("\nWhat kind of character are you:\n\n"); X Printf(" An"); X Printf(" %s,",roles[0]); X for(i = 1; i < NR_OF_ROLES; i++) { X Printf(" a%s %s", index(vowels,roles[i][0]) ? "n" : "", roles[i]); X if((((i + 1) % 4) == 0) && (i != NR_OF_ROLES -1)) Printf(",\n "); X else if(i < NR_OF_ROLES - 2) Printf(","); X if(i == NR_OF_ROLES - 2) Printf(" or"); X } X Printf("?\n ["); X for(i = 0; i < NR_OF_ROLES; i++) Printf("%c,", rolesyms[i]); X Printf(" or Q] "); X X while(pc = readchar()) { X if('a' <= pc && pc <= 'z') pc += 'A'-'a'; X if (pc == 'Q') { X clearlocks(); X settty(NULL); X exit(0); X } X if((i = role_index(pc)) >= 0) { X Printf("%c\n", pc); /* echo */ X (void) fflush(stdout); /* should be seen */ X break; X } X if(pc == '\n') break; X bell(); X } X if(pc == '\n') pc = 0; X Xbeginner: X if(!pc) { X i = rn2(NR_OF_ROLES); X pc = rolesyms[i]; X Printf("\nThis game you will be %s %s.\n", X index("AEIOU", roles[i][0]) ? "an" : "a", X roles[i]); X getret(); X /* give him some feedback in case mklev takes much time */ X (void) putchar('\n'); X (void) fflush(stdout); X } X Xgot_suffix: X X (void) strncpy(pl_character, roles[i], PL_CSIZ-1); X pl_character[PL_CSIZ-1] = 0; X flags.beginner = 1; X u = zerou; X u.usym = S_HUMAN; X u.umoved = FALSE; X u.ugrave_arise = -1; X X u.ulevel = 0; /* set up some of the initial attributes */ X u.uhp = u.uhpmax = newhp(); X adjabil(1); X u.ulevel = 1; X X u.uluck = u.moreluck = 0; X init_uhunger(); X uarm = uarmc = uarmh = uarms = uarmg = uarmf = X#ifdef SHIRT X uarmu = X#endif X uwep = uball = uchain = uleft = uright = 0; X X#ifdef SPELLS X u.uen = u.uenmax = 1; X for (i = 0; i <= MAXSPELL; i++) spl_book[i].sp_id = NO_SPELL; X#endif X#ifdef THEOLOGY X u.ublesscnt = 300; /* no prayers just yet */ X u.ublessed = 0; /* not worthy yet */ X u.ugangr = 0; /* gods not angry */ X#endif X#if defined(THEOLOGY) && defined(ELBERETH) X u.uhand_of_elbereth = 0; X#endif X#ifdef MEDUSA X u.ukilled_medusa = 0; X#endif X#ifdef HARD X u.udemigod = u.udg_cnt = 0; /* not a demi-god yet... */ X#endif X#ifdef POLYSELF X u.umonnum = u.ulycn = -1; X u.mh = u.mhmax = u.mtimedone = 0; X set_uasmon(); X#endif X switch(pc) { X /* pc will always be in uppercase by this point */ X case 'C': X Cave_man[C_ARROWS].trquan = 12 + rnd(30); X ini_inv(Cave_man); X break; X case 'T': X Tourist[T_DARTS].trquan = 20 + rnd(20); X u.ugold = u.ugold0 = rnd(1000); X ini_inv(Tourist); X if(!rn2(25)) ini_inv(Tinopener); X else if(!rn2(25)) ini_inv(Magicmarker); X#ifdef WALKIES X else if(!rn2(25)) ini_inv(Leash); X#endif X break; X case 'R': X Rogue[R_DAGGERS].trquan = 5 + rnd(10); X u.ugold = u.ugold0 = 0; X ini_inv(Rogue); X if(!rn2(5)) ini_inv(Blindfold); X makeknown(SACK); X break; X case 'W': X#ifdef SPELLS X u.uen = u.uenmax += rn2(4); X#endif X ini_inv(Wizard); X if(!rn2(5)) ini_inv(Magicmarker); X if(!rn2(5)) ini_inv(Blindfold); X break; X case 'A': X ini_inv(Archeologist); X if(!rn2(10)) ini_inv(Tinopener); X else if(!rn2(4)) ini_inv(Lamp); X else if(!rn2(10)) ini_inv(Magicmarker); X knows_class(GEM_SYM); X makeknown(SACK); X /* We can't set trknown for it, then it'd be "uncursed" X * sack... X */ X break; X case 'E': X Elf[E_ARROWS].trquan = 15+rnd(20); X#ifdef TOLKIEN X Elf[E_ARMOR].trotyp = ((rn2(100) >= 50) X ? ELVEN_MITHRIL_COAT : ELVEN_CLOAK); X /* rn2(100) > 50 necessary because some random number X * generators are bad enough to seriously skew the X * results if we use rn2(2)... --KAA X */ X#endif X ini_inv(Elf); X if(!rn2(5)) ini_inv(Blindfold); X else if(!rn2(6)) ini_inv(Lamp); X#ifdef TOLKIEN X /* makeknown(ELVEN_SHORT_SWORD); X * no need to do this since the initial inventory contains one, X * so ini_inv already did it for us X */ X objects[ELVEN_SHORT_SWORD].oc_descr = NULL; X /* makeknown(ELVEN_ARROW); */ X objects[ELVEN_ARROW].oc_descr = NULL; X /* makeknown(ELVEN_BOW); */ X objects[ELVEN_BOW].oc_descr = NULL; X makeknown(ELVEN_SPEAR); X objects[ELVEN_SPEAR].oc_descr = NULL; X makeknown(ELVEN_DAGGER); X objects[ELVEN_DAGGER].oc_descr = NULL; X makeknown(ELVEN_BROADSWORD); X objects[ELVEN_BROADSWORD].oc_descr = NULL; X#endif X makeknown(ELVEN_CLOAK); X objects[ELVEN_CLOAK].oc_descr = NULL; X break; X case 'V': X flags.female = TRUE; X ini_inv(Valkyrie); X if(!rn2(6)) ini_inv(Lamp); X knows_class(WEAPON_SYM); X break; X case 'H': X u.ugold = u.ugold0 = rnd(1000)+1000; X ini_inv(Healer); X if(!rn2(25)) ini_inv(Lamp); X break; X case 'K': X ini_inv(Knight); X knows_class(WEAPON_SYM); X break; X case 'B': X ini_inv(Barbarian); X if(!rn2(6)) ini_inv(Lamp); X knows_class(WEAPON_SYM); X break; X case 'S': X ini_inv(Samurai); X if(!rn2(5)) ini_inv(Blindfold); X objects[SHORT_SWORD].oc_name = "wakizashi"; X objects[BROADSWORD].oc_name = "ninja-to"; X objects[GLAIVE].oc_name = "naginata"; X /* objects[BOW].oc_name = "yumi"; */ X objects[LOCK_PICK].oc_name = "osaku"; X knows_class(WEAPON_SYM); X break; X case 'P': X#ifdef SPELLS X u.uen = u.uenmax += rn2(4); X#endif X ini_inv(Priest); X if(!rn2(10)) ini_inv(Magicmarker); X else if(!rn2(10)) ini_inv(Lamp); X break; X X default: /* impossible */ X break; X } X#ifndef HARD X ini_inv(Saving); /* give beginners an extra chance */ X#endif X#ifdef EXPLORE_MODE X if (discover) X ini_inv(Wishing); X#endif X find_ac(); /* get initial ac value */ X init_attr((pick != 'y') ? 69 : 72); /* init attribute values */ X max_rank_sz(); /* set max str size for class ranks */ X/* X * Do we really need this? X */ X for(i = 0; i < A_MAX; i++) X if(!rn2(20)) { X register int xd = rn2(7) - 2; /* biased variation */ X adjattrib(i, xd, TRUE); X } X X /* make sure he can carry all he has - especially for T's */ X while(inv_weight() > 0) X adjattrib(A_STR, 1, TRUE); X X#ifdef THEOLOGY X u.ualignbase[0] = u.ualignbase[1] = u.ualigntyp; X#endif X} X Xstatic void Xini_inv(trop) Xregister struct trobj *trop; X{ X struct obj *obj; X while(trop->trolet) { X boolean undefined = (trop->trotyp == UNDEF_TYP); X X if (!undefined) X obj = mksobj((int)trop->trotyp,FALSE); X else obj = mkobj(trop->trolet,FALSE); X X /* For random objects, do not create certain overly powerful X * items: wand of wishing, ring of levitation, or the X * polymorph/polymorph control combination. Specific objects, X * i.e. the discovery wishing, are still OK. X */ X if (undefined) { X#ifdef POLYSELF X static int nocreate = STRANGE_OBJECT; X# ifdef SPELLS X static int nocreate2 = STRANGE_OBJECT; X# endif X#endif X X while(obj->otyp == WAN_WISHING X#ifdef POLYSELF X || obj->otyp == nocreate X# ifdef SPELLS X || obj->otyp == nocreate2 X# endif X#endif X#ifdef ELBERETH X || obj->otyp == RIN_LEVITATION X#endif X ) { X free((genericptr_t) obj); X obj = mkobj(trop->trolet, FALSE); X } X X /* Don't start with +0 or negative rings */ X if(objects[obj->otyp].oc_charged && obj->spe <= 0) X obj->spe = rne(3); X X /* Heavily relies on the fact that 1) we create wands X * before rings, 2) that we create rings before X * spellbooks, and that 3) not more than 1 object of a X * particular symbol is to be prohibited. X */ X#ifdef POLYSELF X if (obj->otyp == WAN_POLYMORPH) X nocreate = RIN_POLYMORPH_CONTROL; X if (obj->otyp == RIN_POLYMORPH) X nocreate = RIN_POLYMORPH_CONTROL; X if (obj->otyp == RIN_POLYMORPH_CONTROL) { X nocreate = RIN_POLYMORPH; X# ifdef SPELLS X nocreate2 = SPE_POLYMORPH; X# endif /* SPELLS */ X } X#endif /* POLYSELF */ X } X X obj->bknown = trop->trknown; X if(uses_known(obj)) obj->known = trop->trknown; X /* not obj->dknown = 1; - let him look at it at least once */ X obj->cursed = 0; X if(obj->olet == TOOL_SYM){ /* problem with multiple tools */ X obj->quan = 1; /* might be > because of grenades */ X } X if(obj->olet == WEAPON_SYM) { X obj->quan = trop->trquan; X trop->trquan = 1; X } X if(obj->olet == FOOD_SYM && undefined) { X obj->known = 1; X /* needed for tins and eggs; harmless otherwise */ X obj->bknown = (obj->otyp != DEAD_LIZARD); X /* only for dead lizards does the blessing not matter */ X } X /* X * The below lines not needed because they don't correspond X * to any actual inventory; nobody gets random tools. X else if(obj->olet == TOOL_SYM && undefined) { X obj->bknown = (obj->otyp != BAG_OF_TRICKS X && obj->otyp != SACK X && obj->otyp != CHEST X && obj->otyp != LARGE_BOX X && obj->otyp != ICE_BOX) X } X */ X if(trop->trspe != UNDEF_SPE) X obj->spe = trop->trspe; X if(trop->trbless != UNDEF_BLESS) X obj->blessed = trop->trbless; X X if (!Is_container(obj)) X obj->owt = weight(obj); X /* defined after setting otyp+quan */ X obj = addinv(obj); X X /* Make the type known if necessary */ X if (objects[obj->otyp].oc_descr && obj->known) X makeknown(obj->otyp); X X if(obj->olet == ARMOR_SYM){ X if (is_shield(obj) && !uarms) X setworn(obj, W_ARMS); X else if (is_helmet(obj) && !uarmh) X setworn(obj, W_ARMH); X else if (is_gloves(obj) && !uarmg) X setworn(obj, W_ARMG); X#ifdef SHIRT X else if (obj->otyp == HAWAIIAN_SHIRT && !uarmu) X setworn(obj, W_ARMU); X#endif X else if (is_cloak(obj) && !uarmc) X setworn(obj, W_ARMC); X else if (is_boots(obj) && !uarmf) X setworn(obj, W_ARMF); X else if (!uarm) X setworn(obj, W_ARM); X } X /* below changed by GAN 01/09/87 to allow wielding of X * pick-axe or can-opener if there is no weapon X */ X if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE || X obj->otyp == TIN_OPENER) X if(!uwep) setuwep(obj); X#ifndef PYRAMID_BUG X if(--trop->trquan) continue; /* make a similar object */ X#else X if(trop->trquan) { /* check if zero first */ X --trop->trquan; X if(trop->trquan) X continue; /* make a similar object */ X } X#endif X trop++; X } X} X Xvoid Xplnamesuffix() { X register char *p; X if(p = rindex(plname, '-')) { X *p = 0; X pl_character[0] = p[1]; X pl_character[1] = 0; X if(!plname[0]) { X askname(); X plnamesuffix(); X } X } X} END_OF_FILE if test 17550 -ne `wc -c <'src/u_init.c'`; then echo shar: \"'src/u_init.c'\" unpacked with wrong size! fi # end of 'src/u_init.c' fi echo shar: End of archive 9 \(of 38\). cp /dev/null ark9isdone 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