billr@saab.CNA.TEK.COM (Bill Randle) (07/25/89)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu> Posting-number: Volume 7, Issue 81 Archive-name: NetHack3/Part26 #! /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 26 (of 38)." # Contents: others/random.c src/engrave.c src/mkobj.c src/shknam.c # Wrapped by billr@saab on Sun Jul 23 21:33:09 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'others/random.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'others/random.c'\" else echo shar: Extracting \"'others/random.c'\" \(12793 characters\) sed "s/^X//" >'others/random.c' <<'END_OF_FILE' X/* X * Copyright (c) 1983 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that the above copyright notice and this paragraph are X * duplicated in all such forms and that any documentation, X * advertising materials, and other materials related to such X * distribution and use acknowledge that the software was developed X * by the University of California, Berkeley. The name of the X * University may not be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)random.c 5.5 (Berkeley) 7/6/88"; X#endif /* LIBC_SCCS and not lint */ X X#include <stdio.h> X X/* X * random.c: X * An improved random number generation package. In addition to the standard X * rand()/srand() like interface, this package also has a special state info X * interface. The initstate() routine is called with a seed, an array of X * bytes, and a count of how many bytes are being passed in; this array is then X * initialized to contain information for random number generation with that X * much state information. Good sizes for the amount of state information are X * 32, 64, 128, and 256 bytes. The state can be switched by calling the X * setstate() routine with the same array as was initiallized with initstate(). X * By default, the package runs with 128 bytes of state information and X * generates far better random numbers than a linear congruential generator. X * If the amount of state information is less than 32 bytes, a simple linear X * congruential R.N.G. is used. X * Internally, the state information is treated as an array of longs; the X * zeroeth element of the array is the type of R.N.G. being used (small X * integer); the remainder of the array is the state information for the X * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of X * state information, which will allow a degree seven polynomial. (Note: the X * zeroeth word of state information also has some other information stored X * in it -- see setstate() for details). X * The random number generation technique is a linear feedback shift register X * approach, employing trinomials (since there are fewer terms to sum up that X * way). In this approach, the least significant bit of all the numbers in X * the state table will act as a linear feedback shift register, and will have X * period 2^deg - 1 (where deg is the degree of the polynomial being used, X * assuming that the polynomial is irreducible and primitive). The higher X * order bits will have longer periods, since their values are also influenced X * by pseudo-random carries out of the lower bits. The total period of the X * generator is approximately deg*(2**deg - 1); thus doubling the amount of X * state information has a vast influence on the period of the generator. X * Note: the deg*(2**deg - 1) is an approximation only good for large deg, X * when the period of the shift register is the dominant factor. With deg X * equal to seven, the period is actually much longer than the 7*(2**7 - 1) X * predicted by this formula. X */ X X X X/* X * For each of the currently supported random number generators, we have a X * break value on the amount of state information (you need at least this X * many bytes of state info to support this random number generator), a degree X * for the polynomial (actually a trinomial) that the R.N.G. is based on, and X * the separation between the two lower order coefficients of the trinomial. X */ X X#define TYPE_0 0 /* linear congruential */ X#define BREAK_0 8 X#define DEG_0 0 X#define SEP_0 0 X X#define TYPE_1 1 /* x**7 + x**3 + 1 */ X#define BREAK_1 32 X#define DEG_1 7 X#define SEP_1 3 X X#define TYPE_2 2 /* x**15 + x + 1 */ X#define BREAK_2 64 X#define DEG_2 15 X#define SEP_2 1 X X#define TYPE_3 3 /* x**31 + x**3 + 1 */ X#define BREAK_3 128 X#define DEG_3 31 X#define SEP_3 3 X X#define TYPE_4 4 /* x**63 + x + 1 */ X#define BREAK_4 256 X#define DEG_4 63 X#define SEP_4 1 X X X/* X * Array versions of the above information to make code run faster -- relies X * on fact that TYPE_i == i. X */ X X#define MAX_TYPES 5 /* max number of types above */ X Xstatic int degrees[ MAX_TYPES ] = { DEG_0, DEG_1, DEG_2, X DEG_3, DEG_4 }; X Xstatic int seps[ MAX_TYPES ] = { SEP_0, SEP_1, SEP_2, X SEP_3, SEP_4 }; X X X X/* X * Initially, everything is set up as if from : X * initstate( 1, &randtbl, 128 ); X * Note that this initialization takes advantage of the fact that srandom() X * advances the front and rear pointers 10*rand_deg times, and hence the X * rear pointer which starts at 0 will also end up at zero; thus the zeroeth X * element of the state information, which contains info about the current X * position of the rear pointer is just X * MAX_TYPES*(rptr - state) + TYPE_3 == TYPE_3. X */ X Xstatic long randtbl[ DEG_3 + 1 ] = { TYPE_3, X 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, X 0xde3b81e0, 0xdf0a6fb5, 0xf103bc02, 0x48f340fb, X 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, X 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, X 0xda672e2a, 0x1588ca88, 0xe369735d, 0x904f35f7, X 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, X 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, X 0xf5ad9d0e, 0x8999220b, 0x27fb47b9 }; X X/* X * fptr and rptr are two pointers into the state info, a front and a rear X * pointer. These two pointers are always rand_sep places aparts, as they cycle X * cyclically through the state information. (Yes, this does mean we could get X * away with just one pointer, but the code for random() is more efficient this X * way). The pointers are left positioned as they would be from the call X * initstate( 1, randtbl, 128 ) X * (The position of the rear pointer, rptr, is really 0 (as explained above X * in the initialization of randtbl) because the state table pointer is set X * to point to randtbl[1] (as explained below). X */ X Xstatic long *fptr = &randtbl[ SEP_3 + 1 ]; Xstatic long *rptr = &randtbl[ 1 ]; X X X X/* X * The following things are the pointer to the state information table, X * the type of the current generator, the degree of the current polynomial X * being used, and the separation between the two pointers. X * Note that for efficiency of random(), we remember the first location of X * the state information, not the zeroeth. Hence it is valid to access X * state[-1], which is used to store the type of the R.N.G. X * Also, we remember the last location, since this is more efficient than X * indexing every time to find the address of the last element to see if X * the front and rear pointers have wrapped. X */ X Xstatic long *state = &randtbl[ 1 ]; X Xstatic int rand_type = TYPE_3; Xstatic int rand_deg = DEG_3; Xstatic int rand_sep = SEP_3; X Xstatic long *end_ptr = &randtbl[ DEG_3 + 1 ]; X X X X/* X * srandom: X * Initialize the random number generator based on the given seed. If the X * type is the trivial no-state-information type, just remember the seed. X * Otherwise, initializes state[] based on the given "seed" via a linear X * congruential generator. Then, the pointers are set to known locations X * that are exactly rand_sep places apart. Lastly, it cycles the state X * information a given number of times to get rid of any initial dependencies X * introduced by the L.C.R.N.G. X * Note that the initialization of randtbl[] for default usage relies on X * values produced by this routine. X */ X Xsrandom( x ) X X unsigned x; X{ X register int i, j; X long random(); X X if( rand_type == TYPE_0 ) { X state[ 0 ] = x; X } X else { X j = 1; X state[ 0 ] = x; X for( i = 1; i < rand_deg; i++ ) { X state[i] = 1103515245*state[i - 1] + 12345; X } X fptr = &state[ rand_sep ]; X rptr = &state[ 0 ]; X for( i = 0; i < 10*rand_deg; i++ ) random(); X } X} X X X X/* X * initstate: X * Initialize the state information in the given array of n bytes for X * future random number generation. Based on the number of bytes we X * are given, and the break values for the different R.N.G.'s, we choose X * the best (largest) one we can and set things up for it. srandom() is X * then called to initialize the state information. X * Note that on return from srandom(), we set state[-1] to be the type X * multiplexed with the current value of the rear pointer; this is so X * successive calls to initstate() won't lose this information and will X * be able to restart with setstate(). X * Note: the first thing we do is save the current state, if any, just like X * setstate() so that it doesn't matter when initstate is called. X * Returns a pointer to the old state. X */ X Xchar * Xinitstate( seed, arg_state, n ) X X unsigned seed; /* seed for R. N. G. */ X char *arg_state; /* pointer to state array */ X int n; /* # bytes of state info */ X{ X register char *ostate = (char *)( &state[ -1 ] ); X X if( rand_type == TYPE_0 ) state[ -1 ] = rand_type; X else state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type; X if( n < BREAK_1 ) { X if( n < BREAK_0 ) { X fprintf( stderr, "initstate: not enough state (%d bytes) with which to do jack; ignored.\n", n ); X return; X } X rand_type = TYPE_0; X rand_deg = DEG_0; X rand_sep = SEP_0; X } X else { X if( n < BREAK_2 ) { X rand_type = TYPE_1; X rand_deg = DEG_1; X rand_sep = SEP_1; X } X else { X if( n < BREAK_3 ) { X rand_type = TYPE_2; X rand_deg = DEG_2; X rand_sep = SEP_2; X } X else { X if( n < BREAK_4 ) { X rand_type = TYPE_3; X rand_deg = DEG_3; X rand_sep = SEP_3; X } X else { X rand_type = TYPE_4; X rand_deg = DEG_4; X rand_sep = SEP_4; X } X } X } X } X state = &( ( (long *)arg_state )[1] ); /* first location */ X end_ptr = &state[ rand_deg ]; /* must set end_ptr before srandom */ X srandom( seed ); X if( rand_type == TYPE_0 ) state[ -1 ] = rand_type; X else state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type; X return( ostate ); X} X X X X/* X * setstate: X * Restore the state from the given state array. X * Note: it is important that we also remember the locations of the pointers X * in the current state information, and restore the locations of the pointers X * from the old state information. This is done by multiplexing the pointer X * location into the zeroeth word of the state information. X * Note that due to the order in which things are done, it is OK to call X * setstate() with the same state as the current state. X * Returns a pointer to the old state information. X */ X Xchar * Xsetstate( arg_state ) X X char *arg_state; X{ X register long *new_state = (long *)arg_state; X register int type = new_state[0]%MAX_TYPES; X register int rear = new_state[0]/MAX_TYPES; X char *ostate = (char *)( &state[ -1 ] ); X X if( rand_type == TYPE_0 ) state[ -1 ] = rand_type; X else state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type; X switch( type ) { X case TYPE_0: X case TYPE_1: X case TYPE_2: X case TYPE_3: X case TYPE_4: X rand_type = type; X rand_deg = degrees[ type ]; X rand_sep = seps[ type ]; X break; X X default: X fprintf( stderr, "setstate: state info has been munged; not changed.\n" ); X } X state = &new_state[ 1 ]; X if( rand_type != TYPE_0 ) { X rptr = &state[ rear ]; X fptr = &state[ (rear + rand_sep)%rand_deg ]; X } X end_ptr = &state[ rand_deg ]; /* set end_ptr too */ X return( ostate ); X} X X X X/* X * random: X * If we are using the trivial TYPE_0 R.N.G., just do the old linear X * congruential bit. Otherwise, we do our fancy trinomial stuff, which is the X * same in all ther other cases due to all the global variables that have been X * set up. The basic operation is to add the number at the rear pointer into X * the one at the front pointer. Then both pointers are advanced to the next X * location cyclically in the table. The value returned is the sum generated, X * reduced to 31 bits by throwing away the "least random" low bit. X * Note: the code takes advantage of the fact that both the front and X * rear pointers can't wrap on the same call by not testing the rear X * pointer if the front one has wrapped. X * Returns a 31-bit random number. X */ X Xlong Xrandom() X{ X long i; X X if( rand_type == TYPE_0 ) { X i = state[0] = ( state[0]*1103515245 + 12345 )&0x7fffffff; X } X else { X *fptr += *rptr; X i = (*fptr >> 1)&0x7fffffff; /* chucking least random bit */ X if( ++fptr >= end_ptr ) { X fptr = state; X ++rptr; X } X else { X if( ++rptr >= end_ptr ) rptr = state; X } X } X return( i ); X} X END_OF_FILE if test 12793 -ne `wc -c <'others/random.c'`; then echo shar: \"'others/random.c'\" unpacked with wrong size! fi # end of 'others/random.c' fi if test -f 'src/engrave.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/engrave.c'\" else echo shar: Extracting \"'src/engrave.c'\" \(13424 characters\) sed "s/^X//" >'src/engrave.c' <<'END_OF_FILE' X/* SCCS Id: @(#)engrave.c 3.0 89/06/12 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" X Xstatic void del_engr P((struct engr *)); X Xstruct engr { X struct engr *nxt_engr; X char *engr_txt; X xchar engr_x, engr_y; X unsigned engr_lth; /* for save & restore; not length of text */ X long engr_time; /* moment engraving was (will be) finished */ X xchar engr_type; X#define DUST 1 X#define ENGRAVE 2 X#define BURN 3 X#define MARK 4 X#define POLY 5 /* temporary type - for polymorphing engraving */ X} *head_engr; X X/* random engravings */ Xconst char *random_engr[] = X {"Elbereth", "ad ae?ar um", X "?la? ?as he??", X /* more added by Eric Backus */ X "?ilroy wa? h?re", "?ala??iel", X "Fo? a ?ood time c?ll 6?6-4311", X /* some other famous engravings -3. */ X "Lasc?ate o?ni sp?ranz? o vo? c?'en?rate", X "Y?u won?t get i? up ?he ste?s", X "A.S. ->"}; X Xstatic struct engr * Xengr_at(x,y) register xchar x,y; { Xregister struct engr *ep = head_engr; X while(ep) { X if(x == ep->engr_x && y == ep->engr_y) X return(ep); X ep = ep->nxt_engr; X } X return((struct engr *) 0); X} X X#ifdef ELBERETH Xint Xsengr_at(s,x,y) X register char *s; X register xchar x,y; X{ X register struct engr *ep = engr_at(x,y); X register char *t; X register int n; X X if(ep && ep->engr_time <= moves) { X t = ep->engr_txt; X/* X if(!strcmp(s,t)) return(1); X*/ X n = strlen(s); X while(*t) { X if(!strncmp(s,t,n)) return(1); X t++; X } X } X return(0); X} X#endif X Xvoid Xu_wipe_engr(cnt) Xregister int cnt; X{ X if(!u.uswallow && !Levitation) X wipe_engr_at(u.ux, u.uy, cnt); X} X Xvoid Xwipe_engr_at(x,y,cnt) register xchar x,y,cnt; { Xregister struct engr *ep = engr_at(x,y); Xregister int lth,pos; Xchar ch; X if(ep){ X if(ep->engr_type != BURN) { X if(ep->engr_type != DUST) { X cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; X } X lth = strlen(ep->engr_txt); X if(lth && cnt > 0 ) { X while(cnt--) { X pos = rn2(lth); X if((ch = ep->engr_txt[pos]) == ' ') X continue; X ep->engr_txt[pos] = (ch != '?') ? '?' : ' '; X } X } X while(lth && ep->engr_txt[lth-1] == ' ') X ep->engr_txt[--lth] = 0; X while(ep->engr_txt[0] == ' ') X ep->engr_txt++; X if(!ep->engr_txt[0]) del_engr(ep); X } X } X} X Xvoid Xread_engr_at(x,y) register int x,y; { Xregister struct engr *ep = engr_at(x,y); Xregister int canfeel; X if(ep && ep->engr_txt[0]) { X switch(ep->engr_type) { X case DUST: X if(!Blind) pline("Something is written here in the dust."); X canfeel = 0; X break; X case ENGRAVE: X pline("Something is engraved here on the floor."); X canfeel = 1; X break; X case BURN: X pline("Some text has been burned here in the floor."); X canfeel = 1; X break; X case MARK: X if(!Blind) pline("There's some graffiti here on the floor."); X canfeel = 0; X break; X default: X impossible("Something is written in a very strange way."); X canfeel = 1; X } X if (canfeel || !Blind) X You("%s: \"%s\".", X (Blind) ? "feel the words" : "read", ep->engr_txt); X } X} X Xvoid Xmake_engr_at(x,y,s) Xregister int x,y; Xregister char *s; X{ X register struct engr *ep; X X if(ep = engr_at(x,y)) X del_engr(ep); X ep = (struct engr *) X alloc((unsigned)(sizeof(struct engr) + strlen(s) + 1)); X ep->nxt_engr = head_engr; X head_engr = ep; X ep->engr_x = x; X ep->engr_y = y; X ep->engr_txt = (char *)(ep + 1); X Strcpy(ep->engr_txt, s); X ep->engr_time = 0; X ep->engr_type = DUST; X ep->engr_lth = strlen(s) + 1; X} X X/* X * freehand - returns true if player has a free hand X */ Xint Xfreehand(){ X X return(!uwep || X !uwep->cursed || X (!bimanual(uwep) && (!uarms || !uarms->cursed))); X/* if ((uwep && bimanual(uwep)) || X (uwep && uarms)) X return(0); X else X return(1);*/ X} X Xstatic const char styluses[] = { '#', '-', TOOL_SYM, WEAPON_SYM, WAND_SYM, 0 }; Xstatic const char too_large[] = { ARMOR_SYM, BALL_SYM, ROCK_SYM, 0 }; Xstatic const char paper[] = { SCROLL_SYM, X#ifdef SPELLS X SPBOOK_SYM, X#endif X 0 }; X Xint Xdoengrave(){ Xregister int len, tmp; Xregister char *sp, *sptmp; Xregister struct engr *ep, *oep = engr_at(u.ux,u.uy); Xchar buf[BUFSZ]; Xxchar type, polytype = 0; Xint spct; /* number of leading spaces */ Xregister struct obj *otmp; X multi = 0; X X if(u.uswallow) { X pline("What would you write? \"Jonah was here\"?"); X return(0); X } X X /* one may write with finger, weapon or wand */ X /* edited by GAN 10/20/86 so as not to change X * weapon wielded. X */ X otmp = getobj(styluses, "write with"); X if(!otmp) return(0); X X /* There's no reason you should be able to write with a wand X * while both your hands are tied up. X */ X if (!freehand() && otmp != uwep) { X You("have no free %s to write with!", body_part(HAND)); X return(0); X } X#ifdef POLYSELF X if (cantwield(uasmon)) { X You("can't even hold anything!"); X return(0); X } X#endif X if(otmp != &zeroobj && index(too_large,otmp->olet)) { X You("can't engrave with such a large object!"); X return(1); X } X X if(otmp != &zeroobj && index(paper,otmp->olet)) { X Your("%s would get dirty.",xname(otmp)); X return(1); X } X X if(Levitation && otmp->olet != WAND_SYM){ /* riv05!a3 */ X You("can't reach the floor!"); X return(0); X } X X if(otmp == &zeroobj) { X You("write in the dust with your %s.", X makeplural(body_part(FINGER))); X type = DUST; X } else if(otmp->olet == WAND_SYM && zappable(otmp)) { X /* changed so any wand gets zapped out, but fire X * wands become known. X */ X if((objects[otmp->otyp].bits & NODIR)) { X zapnodir(otmp); X type = DUST; X } else { X switch(otmp->otyp) { X case WAN_LIGHTNING: X if(!objects[otmp->otyp].oc_name_known) { X if(flags.verbose) X pline("The %s is a wand of lightning!", X xname(otmp)); X makeknown(otmp->otyp); X more_experienced(0,10); X } X type = BURN; X break; X case WAN_FIRE: X if(!objects[otmp->otyp].oc_name_known) { X if(flags.verbose) X pline("The %s is a wand of fire!", X xname(otmp)); X makeknown(otmp->otyp); X more_experienced(0,10); X } X type = BURN; X break; X case WAN_DIGGING: X if(!objects[otmp->otyp].oc_name_known) { X if(flags.verbose) X pline("The %s is a wand of digging!", X xname(otmp)); X makeknown(otmp->otyp); X more_experienced(0,10); X } X type = ENGRAVE; X break; X case WAN_POLYMORPH: X if(oep) { X del_engr(oep); X oep = 0; X type = POLY; X } else X type = DUST; X break; X case WAN_COLD: X type = DUST; X if(!oep || (oep->engr_type != BURN)) X break; X case WAN_CANCELLATION: X case WAN_MAKE_INVISIBLE: X if(!oep) { /* Eric Backus */ X type = DUST; X break; X } X del_engr(oep); X pline("The engraving on the floor vanishes!"); X return(1); X /* break; */ X case WAN_TELEPORTATION: X if(!oep) X type = DUST; X else { X register int tx,ty; X X do { X tx = rn1(COLNO-3,2); X ty = rn2(ROWNO); X } while(!goodpos(tx,ty)); X oep->engr_x = tx; X oep->engr_y = ty; X pline("The engraving on the floor vanishes!"); X return(1); X } X break; X default: X type = DUST; X } X } X if(type == DUST) X You("write in the dust with %s.", X doname(otmp)); X X } else { X if(otmp->otyp == DAGGER || X#ifdef WORM X otmp->otyp == CRYSKNIFE || X#endif X is_sword(otmp) || otmp->otyp == AXE) { X type = ENGRAVE; X if((int)otmp->spe <= -3) { X Your("%s too dull for engraving.", X aobjnam(otmp, "are")); X type = DUST; X /* following messaged added 10/20/86 - GAN */ X You("write in the dust with %s.", X doname(otmp)); X } else X You("engrave with %s.", doname(otmp)); X } else if(otmp->otyp == MAGIC_MARKER) { X if(otmp->spe <= 0) { X Your("marker is dried out."); X You("write in the dust with the marker."); X type = DUST; X } else { X You("write with %s.", doname(otmp)); X type = MARK; X } X } else { X You("write in the dust with %s.", X doname(otmp)); X type = DUST; X } X } X X if(type != POLY && oep && oep->engr_type == DUST){ X You("wipe out the message that was written here."); X del_engr(oep); X oep = 0; X } X if(type == DUST && oep) { X You("cannot wipe out the message that is %s in the rock.", X (oep->engr_type == BURN) ? "burned" : X (oep->engr_type == ENGRAVE) ? "engraved" : "scribbled"); X return(1); X } X if(type == POLY) { X polytype = rnd(4); X Strcpy(buf,random_engr[rn2(SIZE(random_engr))]); X switch(polytype){ X case DUST: X pline("\"%s\" is now written on the ground.",buf); X break; X case ENGRAVE: X pline("\"%s\" is now engraved in the rock.",buf); X break; X case BURN: X pline("\"%s\" is now burned in the rock.",buf); X break; X case MARK: X pline("\"%s\" is now scribbled on the rock.",buf); X break; X default: X impossible("\"%s\" is now written in a very strange way.", X buf); X } X } else { X pline("What do you want to %s on the floor here? ", X (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write"); X getlin(buf); X clrlin(); X } X spct = 0; X sp = buf; X while(*sp == ' ') spct++, sp++; X len = strlen(sp); X if(!len || *buf == '\033') { X /* changed by GAN 11/01/86 to not recharge wand */ X return(1); X } X if(otmp->otyp == WAN_FIRE) { X if (!Blind) pline("Flames fly from the wand."); X else You("feel the wand heat up."); X } else if(otmp->otyp == WAN_LIGHTNING) { X if (!Blind) { X pline("Lightning arcs from the wand."); X You("are blinded by the flash!"); X make_blinded((long)rnd(50),FALSE); X } else You("hear crackling!"); X } else if(otmp->otyp == WAN_DIGGING) { X if (!Blind) pline("Gravel flies up from the floor."); X else You("hear drilling!"); X } X /* kludge by stewr 870708 */ X for (sptmp = sp, tmp=0; !(tmp == len); sptmp++,tmp++) { X if (((type == DUST) && !rn2(25)) X || (Blind && !rn2(12)) X || (Confusion && !rn2(3))) { X *sptmp = '!' + rn2(93); /* ASCII-code only */ X } X } X X switch(type) { X case DUST: X case BURN: X if(len > 15) { X multi = -(len/10); X nomovemsg = "You finish writing."; X } X break; X case ENGRAVE: X case MARK: X { int len2; X X if(type == ENGRAVE) X len2 = (otmp->spe + 3) * 2 + 1; X else X len2 = (otmp->spe) * 2; X nomovemsg = "You finish writing."; X if(type != MARK) X nomovemsg = "You finish engraving."; X if(otmp->olet != WAND_SYM) { X if(otmp->olet == WEAPON_SYM) X Your("%s dull.", X aobjnam(otmp, "get")); X if(len2 < len) { X len = len2; X sp[len] = 0; X if(type == ENGRAVE) { X otmp->spe = -3; X } else { X Your("marker dries out!"); X otmp->spe = 0; X } X /* next line added by GAN 10/20/86 */ X You("only write \"%s\".", sp); X nomovemsg = "You cannot write more."; X } else X otmp->spe -= len >> 1; X if(type == MARK) X multi = -(len/10); X else X multi = -len; X } else X multi = -(len/10); X if (multi == 0) X nomovemsg = (char *)0; X } X break; X case POLY: X type = polytype; X multi = 0; X break; X } X if(oep) len += strlen(oep->engr_txt) + spct; X ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1)); X ep->nxt_engr = head_engr; X head_engr = ep; X ep->engr_x = u.ux; X ep->engr_y = u.uy; X sp = (char *)(ep + 1); /* (char *)ep + sizeof(struct engr) */ X ep->engr_txt = sp; X if(oep) { X Strcpy(sp, oep->engr_txt); X Strcat(sp, buf); X del_engr(oep); X } else X Strcpy(sp, buf); X ep->engr_lth = len+1; X ep->engr_type = type; X ep->engr_time = moves-multi; X X /* kludge to protect pline against excessively long texts */ X if(len > BUFSZ-20) sp[BUFSZ-20] = 0; X X /* cute messages for odd wands */ X switch(otmp->otyp) { X case WAN_SLOW_MONSTER: X pline("The bugs on the ground slow down!"); X break; X case WAN_SPEED_MONSTER: X pline("The bugs on the ground speed up!"); X break; X case WAN_MAGIC_MISSILE: X pline("The ground is riddled by bullet holes!"); X break; X case WAN_SLEEP: X case WAN_DEATH: /* can't tell sleep from death - Eric Backus */ X pline("The bugs on the ground stop moving!"); X break; X case WAN_COLD: X pline("A few ice cubes drop from your %s.",xname(otmp)); X break; X case WAN_STRIKING: X pline("The %s unsuccessfully fights your attempt to write!",xname(otmp)); X } X X return(1); X} X Xvoid Xsave_engravings(fd) int fd; { Xregister struct engr *ep = head_engr; Xregister struct engr *ep2; X while(ep) { X ep2 = ep->nxt_engr; X if(ep->engr_lth && ep->engr_txt[0]){ X bwrite(fd, (genericptr_t)&(ep->engr_lth), sizeof(ep->engr_lth)); X bwrite(fd, (genericptr_t)ep, sizeof(struct engr) + ep->engr_lth); X } X#if defined(DGK) && !defined(TOS) X if (!count_only) X#endif X free((genericptr_t) ep); X ep = ep2; X } X bwrite(fd, (genericptr_t)nul, sizeof(unsigned)); X#if defined(DGK) && !defined(TOS) X if (!count_only) X#endif X head_engr = 0; X} X Xvoid Xrest_engravings(fd) int fd; { Xregister struct engr *ep; Xunsigned lth; X head_engr = 0; X while(1) { X mread(fd, (genericptr_t) <h, sizeof(unsigned)); X if(lth == 0) return; X ep = (struct engr *) alloc(sizeof(struct engr) + lth); X mread(fd, (genericptr_t) ep, sizeof(struct engr) + lth); X ep->nxt_engr = head_engr; X ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */ X head_engr = ep; X } X} X Xstatic void Xdel_engr(ep) register struct engr *ep; { Xregister struct engr *ept; X if(ep == head_engr) X head_engr = ep->nxt_engr; X else { X for(ept = head_engr; ept; ept = ept->nxt_engr) { X if(ept->nxt_engr == ep) { X ept->nxt_engr = ep->nxt_engr; X goto fnd; X } X } X impossible("Error in del_engr?"); X return; X fnd: ; X } X free((genericptr_t) ep); X} END_OF_FILE if test 13424 -ne `wc -c <'src/engrave.c'`; then echo shar: \"'src/engrave.c'\" unpacked with wrong size! fi # end of 'src/engrave.c' fi if test -f 'src/mkobj.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/mkobj.c'\" else echo shar: Extracting \"'src/mkobj.c'\" \(12813 characters\) sed "s/^X//" >'src/mkobj.c' <<'END_OF_FILE' X/* SCCS Id: @(#)mkobj.c 3.0 88/10/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 Xstruct icp { X int iprob; /* probability of an item type */ X char ilet; /* item class */ X}; X Xconst struct icp mkobjprobs[] = { X{10, WEAPON_SYM}, X{10, ARMOR_SYM}, X{20, FOOD_SYM}, X{ 8, TOOL_SYM}, X{ 8, GEM_SYM}, X#ifdef SPELLS X{16, POTION_SYM}, X{16, SCROLL_SYM}, X{ 4, SPBOOK_SYM}, X#else X{18, POTION_SYM}, X{18, SCROLL_SYM}, X#endif X{ 4, WAND_SYM}, X{ 3, RING_SYM}, X{ 1, AMULET_SYM}}; X Xconst struct icp boxiprobs[] = { X{18, GEM_SYM}, X#ifdef SPELLS X{15, FOOD_SYM}, X{20, POTION_SYM}, X{20, SCROLL_SYM}, X{15, SPBOOK_SYM}, X#else X{20, FOOD_SYM}, X{25, POTION_SYM}, X{25, SCROLL_SYM}, X#endif X{ 6, WAND_SYM}, X{ 5, RING_SYM}, X{ 1, AMULET_SYM}}; X X#ifdef REINCARNATION Xconst struct icp rogueprobs[] = { X{12, WEAPON_SYM}, X{12, ARMOR_SYM}, X{22, FOOD_SYM}, X{22, POTION_SYM}, X{22, SCROLL_SYM}, X{ 5, WAND_SYM}, X{ 5, RING_SYM}}; X#endif X Xconst struct icp hellprobs[] = { X{20, WEAPON_SYM}, X{20, ARMOR_SYM}, X{16, FOOD_SYM}, X{12, TOOL_SYM}, X{10, GEM_SYM}, X{ 1, POTION_SYM}, X{ 1, SCROLL_SYM}, X{ 8, WAND_SYM}, X{ 8, RING_SYM}, X{ 4, AMULET_SYM}}; X Xstatic int mksx=0, mksy=0; X Xstruct obj * Xmkobj_at(let,x,y) Xchar let; Xint x,y; X{ X register struct obj *otmp; X X mksx = x; mksy = y; X /* We might need to know the X, Y coordinates while creating the X * object, i.e. to insure shop boxes are empty. X * Yes, this is a horrible kludge... X */ X otmp = mkobj(let,TRUE); X otmp->ox = x; X otmp->oy = y; X otmp->nobj = fobj; X fobj = otmp; X levl[x][y].omask = 1; X mksx = mksy = 0; X return(otmp); X} X Xstruct obj * Xmksobj_at(otyp,x,y) Xint otyp,x,y; X{ X register struct obj *otmp; X X mksx = x; mksy = y; X otmp = mksobj(otyp,TRUE); X otmp->ox = x; X otmp->oy = y; X otmp->nobj = fobj; X levl[x][y].omask = 1; X mksx = mksy = 0; X return((fobj = otmp)); X} X Xstruct obj * Xmkobj(let, artif) Xchar let; Xboolean artif; X{ X register int tprob, i, prob = rnd(1000); X X if(let == RANDOM_SYM) { X struct icp *iprobs = X#ifdef REINCARNATION X (dlevel == rogue_level) ? rogueprobs : X#endif X Inhell ? hellprobs : X mkobjprobs; X X for(tprob = rnd(100); X (tprob -= iprobs->iprob) > 0; X iprobs++); X let = iprobs->ilet; X } X X i = bases[letindex(let)]; X while((prob -= objects[i].oc_prob) > 0) i++; X X if(objects[i].oc_olet != let || !objects[i].oc_name) X panic("probtype error, let=%c i=%d", let, i); X X return(mksobj(i, artif)); X} X Xstatic void Xmkbox_cnts(box) X/* Note: does not check to see if it overloaded the box weight; usually X * possible only with corpses in ice boxes. X */ Xstruct obj *box; X{ X register int n; X register struct obj *otmp; X X if(in_shop(mksx, mksy)) return; /* boxes are empty in shops */ X X switch(box->otyp) { X case ICE_BOX: n = 20; break; X case CHEST: n = 5; break; X case LARGE_BOX: n = 3; break; X case SACK: X case BAG_OF_HOLDING: n = 1; break; X default: n = 0; break; X } X X for(n = rn2(n+1); n > 0; n--) { X if (box->otyp == ICE_BOX) { X otmp = mksobj(CORPSE, TRUE); X otmp->age = moves; X } else { X register int tprob; X struct icp *iprobs = boxiprobs; X X for(tprob = rnd(100); X (tprob -= iprobs->iprob) > 0; X iprobs++); X otmp = mkobj(iprobs->ilet, TRUE); X } X if (otmp) { X otmp->cobj = box; X otmp->nobj = fcobj; X fcobj = otmp; X inc_cwt(box, otmp); X } X } X return; X} X Xint Xrndmonnum() { /* select a random, common monster type */ X X register struct permonst *ptr; X register int i; X X /* Plan A: get a level-appropriate common monster */ X ptr = rndmonst(); X if (ptr) return(monsndx(ptr)); X X /* Plan B: get any common monster */ X do { X ptr = &mons[(i = rn2(NUMMONS))]; X } while((ptr->geno & G_NOGEN) || (!Inhell && (ptr->geno & G_HELL))); X X return(i); X} X Xconst char dknowns[] = { WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM, X#ifdef SPELLS XSPBOOK_SYM, X#endif XWEAPON_SYM, 0}; X X/*ARGSUSED*/ Xstruct obj * Xmksobj(otyp, artif) Xint otyp; Xboolean artif; X{ X int tryct; X struct obj *otmp; X char let = objects[otyp].oc_olet; X X otmp = newobj(0); X *otmp = zeroobj; X otmp->age = moves; X otmp->o_id = flags.ident++; X otmp->quan = 1; X otmp->olet = let; X otmp->otyp = otyp; X otmp->dknown = index(dknowns, let) ? 0 : 1; X if (!uses_known(otmp)) X otmp->known = 1; X switch(let) { X case WEAPON_SYM: X otmp->quan = (otmp->otyp <= SHURIKEN) ? rn1(6,6) : 1; X if(!rn2(11)) { X otmp->spe = rne(2); X otmp->blessed = rn2(2); X } else if(!rn2(10)) { X curse(otmp); X otmp->spe = -rne(2); X } else blessorcurse(otmp, 10); X X#ifdef NAMED_ITEMS X if(artif && !rn2(20)) mkartifact(&otmp); X#endif X break; X case FOOD_SYM: X if(otmp->otyp == CORPSE) { X /* overridden by mkcorpse_at() */ X do otmp->corpsenm = rndmonnum(); X while (mons[otmp->corpsenm].geno & G_NOCORPSE); X break; X } else if(otmp->otyp == EGG) { X if(!rn2(3)) { /* "live" eggs */ X register struct permonst *ptr; X for(tryct = 0; X (!(ptr = rndmonst()) || X (!lays_eggs(ptr) && ptr != &mons[PM_KILLER_BEE])) && X tryct < 100; X tryct++); X if(tryct < 100) otmp->corpsenm = monsndx(ptr); X else otmp->corpsenm = -1; /* empty */ X } else otmp->corpsenm = -1; /* empty */ X } else if(otmp->otyp == TIN) { X if(!rn2(10)) { X otmp->spe = 1; /* spinach */ X otmp->corpsenm = -1; X } else do { X otmp->corpsenm = rndmonnum(); X } while (mons[otmp->corpsenm].geno & G_NOCORPSE); X blessorcurse(otmp, 10); X } else if (otmp->otyp == SLIME_MOLD) X otmp->spe = current_fruit; X /* fall into next case */ X case GEM_SYM: X if (otmp->otyp == LOADSTONE) curse(otmp); X else if (otmp->otyp == ROCK) otmp->quan = rn1(6,6); X else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2; X else otmp->quan = 1; X break; X case TOOL_SYM: X switch(otmp->otyp) { X case LAMP: otmp->spe = rnd(10); X blessorcurse(otmp, 5); X break; X case MAGIC_LAMP: otmp->spe = 1; X blessorcurse(otmp, 2); X break; X case KEY: /* key # index */ X case SKELETON_KEY: otmp->spe = rn2(N_LOX); X break; X case CHEST: /* lock # index */ X case LARGE_BOX: otmp->spe = rn2(N_LOX); X otmp->olocked = !!(rn2(5)); X otmp->otrapped = !(rn2(10)); X case ICE_BOX: X case SACK: X case BAG_OF_HOLDING: mkbox_cnts(otmp); X break; X case MAGIC_MARKER: otmp->spe = rn1(70,30); X break; X case CRYSTAL_BALL: otmp->spe = rnd(5); X blessorcurse(otmp, 2); X break; X case BAG_OF_TRICKS: otmp->spe = rnd(20); X break; X case FIGURINE: otmp->corpsenm = rndmonnum(); X blessorcurse(otmp, 4); X break; X#ifdef MUSIC X case MAGIC_FLUTE: X case MAGIC_HARP: X case FROST_HORN: X case FIRE_HORN: X case DRUM_OF_EARTHQUAKE: X otmp->spe = rn1(5,4); X break; X#endif /* MUSIC /**/ X } X break; X case AMULET_SYM: X if(rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION || X otmp->otyp == AMULET_OF_CHANGE || X otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) { X curse(otmp); X } else blessorcurse(otmp, 10); X case VENOM_SYM: X case CHAIN_SYM: X case BALL_SYM: X break; X case POTION_SYM: X case SCROLL_SYM: X#ifdef MAIL X if (otmp->otyp != SCR_MAIL) X#endif X blessorcurse(otmp, 4); X break; X#ifdef SPELLS X case SPBOOK_SYM: X blessorcurse(otmp, 17); X break; X#endif X case ARMOR_SYM: X if(rn2(10) && (otmp->otyp == FUMBLE_BOOTS || X otmp->otyp == LEVITATION_BOOTS || X otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT || X otmp->otyp == GAUNTLETS_OF_FUMBLING || X !rn2(11))) { X curse(otmp); X otmp->spe = -rne(2); X } else if(!rn2(10)) { X otmp->spe = rne(2); X otmp->blessed = rn2(2); X } else blessorcurse(otmp, 10); X if(otmp->otyp == DRAGON_SCALE_MAIL) X otmp->corpsenm = PM_GREY_DRAGON + X rn2(PM_YELLOW_DRAGON-PM_GREY_DRAGON+1); X break; X case WAND_SYM: X#ifdef HARD X if(otmp->otyp == WAN_WISHING) otmp->spe = rnd(3); else X#else X if(otmp->otyp == WAN_WISHING) otmp->spe = 3; else X#endif X otmp->spe = rn1(5, X (objects[otmp->otyp].bits & NODIR) ? 11 : 4); X blessorcurse(otmp, 17); X otmp->recharged = 0; /* used to control recharging */ X break; X case RING_SYM: X if(objects[otmp->otyp].oc_charged) { X blessorcurse(otmp, 3); X if(rn2(10)) { X if(rn2(10) && bcsign(otmp)) X otmp->spe = bcsign(otmp) * rne(3); X else otmp->spe = rn2(2) ? rne(3) : -rne(3); X } X if (otmp->spe < 0 && rn2(5)) curse(otmp); X } else if(rn2(10) && (otmp->otyp == RIN_TELEPORTATION || X#ifdef POLYSELF X otmp->otyp == RIN_POLYMORPH || X#endif X otmp->otyp == RIN_AGGRAVATE_MONSTER || X otmp->otyp == RIN_HUNGER || !rn2(9))) { X curse(otmp); X } X break; X case ROCK_SYM: X switch (otmp->otyp) { X case STATUE: X /* contains book? */ X otmp->spe = (rn2(dlevel/2 + 10) > 10); X /* overridden by mkstatue() */ X otmp->corpsenm = rndmonnum(); X otmp->owt = mons[otmp->corpsenm].cwt; X } X break; X default: X impossible("impossible mkobj %d, sym '%c'.", otmp->otyp, let); X return (struct obj *)0; X } X otmp->owt = weight(otmp); X return(otmp); X} X Xvoid Xbless(otmp) Xregister struct obj *otmp; X{ X otmp->cursed = 0; X otmp->blessed = 1; X return; X} X Xvoid Xcurse(otmp) Xregister struct obj *otmp; X{ X otmp->blessed = 0; X otmp->cursed = 1; X return; X} X Xvoid Xblessorcurse(otmp, chance) Xregister struct obj *otmp; Xregister int chance; X{ X if(otmp->blessed || otmp->cursed) return; X X if(!rn2(chance)) X if(!rn2(2) || Inhell) { /* in hell, don't usually bless items */ X curse(otmp); X } else { X bless(otmp); X } X return; X} X Xint Xbcsign(otmp) Xregister struct obj *otmp; X{ X return(!!otmp->blessed - !!otmp->cursed); X} X Xint Xletter(c) { X return(('@' <= c && c <= 'Z') || ('a' <= c && c <= 'z')); X} X Xint Xweight(obj) Xregister struct obj *obj; X{ X register int wt = objects[obj->otyp].oc_weight; X X if (Is_container(obj)) { X struct obj *contents; X for(contents=fcobj; contents; contents=contents->nobj) { X if (contents->cobj == obj) X inc_cwt(obj, contents); X } X return obj->owt; X } X if (obj->otyp == CORPSE && obj->corpsenm > -1) X return obj->quan * mons[obj->corpsenm].cwt; X else if (obj->otyp == STATUE && obj->corpsenm > -1) X return obj->quan * (mons[obj->corpsenm].cwt * 3 / 2); X return(wt ? wt*obj->quan : (obj->quan + 1)>>1); X} X Xvoid Xmkgold(num,x,y) Xlong num; Xint x, y; X{ X register struct gold *gold; X register long amount = (num ? num : 1 + (rnd(dlevel+2) * rnd(30))); X X if(levl[x][y].gmask) { X gold = g_at(x,y); X gold->amount += amount; X } else { X gold = newgold(); X gold->ngold = fgold; X gold->gx = x; X gold->gy = y; X gold->amount = amount; X fgold = gold; X levl[x][y].gmask = 1; X /* do sth with display? */ X } X return; X} X Xstruct obj * Xmkcorpse_at(ptr, x, y) Xregister struct permonst *ptr; Xint x, y; X{ X register struct obj *otmp; X X otmp = mksobj_at(CORPSE, x, y); X if(otmp) { X otmp->corpsenm = monsndx(ptr); X otmp->owt = ptr->cwt; X } X return(otmp); X} X Xstruct obj * Xmk_tt_corpse(x, y) Xregister int x, y; X{ X register struct obj *otmp; X X if((otmp = mksobj(CORPSE,FALSE))) { X otmp->ox = x; X otmp->oy = y; X if(otmp = tt_oname(otmp)) { X otmp->nobj = fobj; X fobj = otmp; X levl[x][y].omask = 1; X } X } X return(otmp); X} X Xstruct obj * Xmkstatue(ptr, x, y) Xregister struct permonst *ptr; Xint x, y; X{ X register struct obj *otmp; X X if((otmp = mksobj_at(STATUE, x, y))) { X X if(ptr) otmp->corpsenm = monsndx(ptr); X else otmp->corpsenm = rndmonnum(); X } X return(otmp); X} X Xstruct obj * Xmk_named_object(objtype, ptr, x, y, nm, lth) Xint objtype; /* CORPSE or STATUE */ Xregister struct permonst *ptr; Xint x, y; Xchar * nm; Xregister int lth; X{ X struct obj *otmp; X register struct obj *obj2; X X if (lth == 0) { X switch(objtype) { X case STATUE: return (mkstatue(ptr, x, y)); X case CORPSE: return (mkcorpse_at(ptr, x, y)); X default: impossible("making named type %d", objtype); X return mksobj_at(objtype, x, y); X } X } X X if((otmp = mksobj(objtype,FALSE))) { X obj2 = newobj(lth); X *obj2 = *otmp; X obj2->corpsenm = monsndx(ptr); X obj2->owt = ptr->cwt; X obj2->onamelth = lth; X Strcpy (ONAME(obj2), nm); X free( (genericptr_t)otmp); X obj2->ox = x; X obj2->oy = y; X obj2->nobj = fobj; X fobj = obj2; X levl[x][y].omask = 1; X return(obj2); X } else return((struct obj *)0); X} X X#ifdef MEDUSA Xstruct obj * Xmk_tt_statue(x, y) Xregister int x, y; X{ X register struct obj *otmp; X X if((otmp = mksobj(STATUE,FALSE))) { X otmp->ox = x; X otmp->oy = y; X if(otmp = tt_oname(otmp)) { X otmp->nobj = fobj; X fobj = otmp; X levl[x][y].omask = 1; X otmp->spe = 0; X /* player statues never contain books */ X } X } X return(otmp); X} X#endif X Xboolean Xis_flammable(otmp) Xregister struct obj *otmp; X{ X return((objects[otmp->otyp].oc_material == WOOD || X objects[otmp->otyp].oc_material == 0)); X X} X Xboolean Xis_rustprone(otmp) Xregister struct obj *otmp; X{ X return(objects[otmp->otyp].oc_material == METAL); X} X Xvoid Xset_omask(x, y) Xregister xchar x, y; X{ X levl[x][y].gmask = (g_at(x, y) != (struct gold *)0); X levl[x][y].omask = (o_at(x, y) != (struct obj *)0); X} END_OF_FILE if test 12813 -ne `wc -c <'src/mkobj.c'`; then echo shar: \"'src/mkobj.c'\" unpacked with wrong size! fi # end of 'src/mkobj.c' fi if test -f 'src/shknam.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/shknam.c'\" else echo shar: Extracting \"'src/shknam.c'\" \(11750 characters\) sed "s/^X//" >'src/shknam.c' <<'END_OF_FILE' X/* SCCS Id: @(#)shknam.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/* shknam.c -- initialize a shop */ X X#include "hack.h" X#include "eshk.h" X Xstatic const char *shkliquors[] = { X /* Ukraine */ X "Njezjin", "Tsjernigof", "Gomel", "Ossipewsk", "Gorlowka", X /* N. Russia */ X "Konosja", "Weliki Oestjoeg", "Syktywkar", "Sablja", X "Narodnaja", "Kyzyl", X /* Silezie */ X "Walbrzych", "Swidnica", "Klodzko", "Raciborz", "Gliwice", X "Brzeg", "Krnov", "Hradec Kralove", X /* Schweiz */ X "Leuk", "Brig", "Brienz", "Thun", "Sarnen", "Burglen", "Elm", X "Flims", "Vals", "Schuls", "Zum Loch", X "" X}; X Xstatic const char *shkbooks[] = { X /* Eire */ X "Skibbereen", "Kanturk", "Rath Luirc", "Ennistymon", "Lahinch", X "Kinnegad", "Lugnaquillia", "Enniscorthy", "Gweebarra", X "Kittamagh", "Nenagh", "Sneem", "Ballingeary", "Kilgarvan", X "Cahersiveen", "Glenbeigh", "Kilmihil", "Kiltamagh", X "Droichead Atha", "Inniscrone", "Clonegal", "Lisnaskea", X "Culdaff", "Dunfanaghy", "Inishbofin", "Kesh", X "" X}; X Xstatic const char *shkarmors[] = { X /* Turquie */ X "Demirci", "Kalecik", "Boyabai", "Yildizeli", "Gaziantep", X "Siirt", "Akhalataki", "Tirebolu", "Aksaray", "Ermenak", X "Iskenderun", "Kadirli", "Siverek", "Pervari", "Malasgirt", X "Bayburt", "Ayancik", "Zonguldak", "Balya", "Tefenni", X "Artvin", "Kars", "Makharadze", "Malazgirt", "Midyat", X "Birecik", "Kirikkale", "Alaca", "Polatli", "Nallihan", X "" X}; X Xstatic const char *shkwands[] = { X /* Wales */ X "Yr Wyddgrug", "Trallwng", "Mallwyd", "Pontarfynach", X "Rhaeader", "Llandrindod", "Llanfair-ym-muallt", X "Y-Fenni", "Measteg", "Rhydaman", "Beddgelert", X "Curig", "Llanrwst", "Llanerchymedd", "Caergybi", X /* Scotland */ X "Nairn", "Turriff", "Inverurie", "Braemar", "Lochnagar", X "Kerloch", "Beinn a Ghlo", "Drumnadrochit", "Morven", X "Uist", "Storr", "Sgurr na Ciche", "Cannich", "Gairloch", X "Kyleakin", "Dunvegan", X "" X}; X Xstatic const char *shkrings[] = { X /* Hollandse familienamen */ X "Feyfer", "Flugi", "Gheel", "Havic", "Haynin", "Hoboken", X "Imbyze", "Juyn", "Kinsky", "Massis", "Matray", "Moy", X "Olycan", "Sadelin", "Svaving", "Tapper", "Terwen", "Wirix", X "Ypey", X /* Skandinaviske navne */ X "Rastegaisa", "Varjag Njarga", "Kautekeino", "Abisko", X "Enontekis", "Rovaniemi", "Avasaksa", "Haparanda", X "Lulea", "Gellivare", "Oeloe", "Kajaani", "Fauske", X "" X}; X Xstatic const char *shkfoods[] = { X /* Indonesia */ X "Djasinga", "Tjibarusa", "Tjiwidej", "Pengalengan", X "Bandjar", "Parbalingga", "Bojolali", "Sarangan", X "Ngebel", "Djombang", "Ardjawinangun", "Berbek", X "Papar", "Baliga", "Tjisolok", "Siboga", "Banjoewangi", X "Trenggalek", "Karangkobar", "Njalindoeng", "Pasawahan", X "Pameunpeuk", "Patjitan", "Kediri", "Pemboeang", "Tringanoe", X "Makin", "Tipor", "Semai", "Berhala", "Tegal", "Samoe", X "" X}; X Xstatic const char *shkweapons[] = { X /* Perigord */ X "Voulgezac", "Rouffiac", "Lerignac", "Touverac", "Guizengeard", X "Melac", "Neuvicq", "Vanzac", "Picq", "Urignac", "Corignac", X "Fleac", "Lonzac", "Vergt", "Queyssac", "Liorac", "Echourgnac", X "Cazelon", "Eypau", "Carignan", "Monbazillac", "Jonzac", X "Pons", "Jumilhac", "Fenouilledes", "Laguiolet", "Saujon", X "Eymoutiers", "Eygurande", "Eauze", "Labouheyre", X "" X}; X Xstatic const char *shktools[] = { X /* Spmi */ X "Ymla", "Eed-morra", "Cubask", "Nieb", "Bnowr Falr", "Telloc Cyaj", X "Sperc", "Noskcirdneh", "Yawolloh", "Hyeghu", "Niskal", "Trahnil", X "Htargcm", "Enrobwem", "Kachzi Rellim", "Regien", "Donmyar", X "Yelpur", "Nosnehpets", "Stewe", "Renrut", "Zlaw", "Nosalnef", X "Rewuorb", "Rellenk", X "" X}; X Xstatic const char *shkgeneral[] = { X /* Suriname */ X "Hebiwerie", "Possogroenoe", "Asidonhopo", "Manlobbi", X "Adjama", "Pakka Pakka", "Kabalebo", "Wonotobo", X "Akalapi", "Sipaliwini", X /* Greenland */ X "Annootok", "Upernavik", "Angmagssalik", X /* N. Canada */ X "Aklavik", "Inuvik", "Tuktoyaktuk", X "Chicoutimi", "Ouiatchouane", "Chibougamau", X "Matagami", "Kipawa", "Kinojevis", X "Abitibi", "Maganasipi", X /* Iceland */ X "Akureyri", "Kopasker", "Budereyri", "Akranes", "Bordeyri", X "Holmavik", X "" X}; X X/* X * To add new shop types, all that is necessary is to edit the shtypes[] array. X * See mkroom.h for the structure definition. Typically, you'll have to lower X * some or all of the probability fields in old entries to free up some X * percentage for the new type. X * X * The placement type field is not yet used but will be in the near future. X * X * The iprobs array in each entry defines the probabilities for various kinds X * of artifacts to be present in the given shop type. You can associate with X * each percentage either a generic artifact type (represented by one of the X * *_SYM macros) or a specific artifact (represented by an onames.h define). X * In the latter case, prepend it with a unary minus so the code can know X * (by testing the sign) whether to use mkobj() or mksobj(). X */ Xconst struct shclass shtypes[] = { X {"general store", RANDOM_SYM, X#ifdef SPELLS X 44, X#else X 47, X#endif X D_SHOP, {{100, RANDOM_SYM}, {0, 0}, {0, 0}}, shkgeneral}, X {"used armor dealership", ARMOR_SYM, 14, X D_SHOP, {{90, ARMOR_SYM}, {10, WEAPON_SYM}, {0, 0}}, shkarmors}, X {"second hand bookstore", SCROLL_SYM, 10, D_SHOP, X#ifdef SPELLS X {{90, SCROLL_SYM}, {10, SPBOOK_SYM}, {0, 0}}, X#else X {{100, SCROLL_SYM}, {0, 0}, {0, 0}}, X#endif X shkbooks}, X {"liquor emporium", POTION_SYM, 10, D_SHOP, X {{100, POTION_SYM}, {0, 0}, {0, 0}}, shkliquors}, X {"antique weapons outlet", WEAPON_SYM, 5, D_SHOP, X {{90, WEAPON_SYM}, {10, ARMOR_SYM}, {0, 0}}, shkweapons}, X {"delicatessen", FOOD_SYM, 5, D_SHOP, X {{95, FOOD_SYM}, {5, POTION_SYM}, {0, 0}}, shkfoods}, X {"jewelers", RING_SYM, 3, D_SHOP, X {{85, RING_SYM}, {10, GEM_SYM}, {5, AMULET_SYM}, {0, 0}}, shkrings}, X {"quality apparel and accessories", WAND_SYM, 3, D_SHOP, X {{90, WAND_SYM}, {5, -LEATHER_GLOVES}, {5, -ELVEN_CLOAK}, {0, 0}}, X shkwands}, X {"hardware store", TOOL_SYM, 3, D_SHOP, X {{100, TOOL_SYM}, {0, 0}, {0, 0}}, shktools}, X /* Actually shktools is ignored; the code specifically chooses a X * random implementor name (the only shop type with random shopkeepers) X */ X#ifdef SPELLS X {"rare books", SPBOOK_SYM, 3, D_SHOP, X {{90, SPBOOK_SYM}, {10, SCROLL_SYM}, {0, 0}}, shkbooks}, X#endif X {NULL, 0, 0, 0, {{0, 0}, {0, 0}, {0, 0}}, (char **)0} X}; X Xstatic void Xmkshobj_at(shp, sx, sy) X/* make an object of the appropriate type for a shop square */ Xstruct shclass *shp; Xint sx, sy; X{ X register struct monst *mtmp; X int atype; X X if (rn2(100) < dlevel && levl[sx][sy].mmask == 0 && X (mtmp=makemon(mkclass(S_MIMIC),sx,sy))) { X mtmp->mimic = 1; X /* note: makemon will set the mimic symbol to a shop item */ X if (rn2(10) >= dlevel) mtmp->mappearance = S_MIMIC_DEF; X } else if ((atype = get_shop_item(shp - shtypes)) < 0) X (void) mksobj_at(-atype, sx, sy); X else (void) mkobj_at(atype, sx, sy); X} X Xstatic void Xfindname(nampt, nlp) X/* extract a shopkeeper name for the given shop type */ X char *nampt; X char *nlp[]; X{ X register int i; X X for(i = 0; i < dlevel; i++) X if (strlen(nlp[i]) == 0) { X /* Not enough names, try general name */ X if (nlp != shkgeneral) X findname(nampt, shkgeneral); X else X Strcpy(nampt, "Dirk"); X return; X } X (void) strncpy(nampt, nlp[i-1], PL_NSIZ); X nampt[PL_NSIZ-1] = 0; X} X Xstatic int Xshkinit(shp, sroom) /* create a new shopkeeper in the given room */ Xstruct shclass *shp; Xstruct mkroom *sroom; X{ X register int sh, sx, sy; X struct monst *shk; X X /* place the shopkeeper in the given room */ X sh = sroom->fdoor; X sx = doors[sh].x; X sy = doors[sh].y; X X /* check that the shopkeeper placement is sane */ X if(sx == sroom->lx-1) sx++; else X if(sx == sroom->hx+1) sx--; else X if(sy == sroom->ly-1) sy++; else X if(sy == sroom->hy+1) sy--; else { X#ifdef DEBUG X# ifdef WIZARD X /* Said to happen sometimes, but I have never seen it. */ X /* Supposedly fixed by fdoor change in mklev.c */ X if(wizard) { X register int j = sroom->doorct; X X pline("Where is shopdoor?"); X pline("Room at (%d,%d),(%d,%d).", X sroom->lx, sroom->ly, sroom->hx, sroom->hy); X pline("doormax=%d doorct=%d fdoor=%d", X doorindex, sroom->doorct, sh); X while(j--) { X pline("door [%d,%d]", doors[sh].x, doors[sh].y); X sh++; X } X more(); X } X# endif X#endif X return(-1); X } X X /* now initialize the shopkeeper monster structure */ X if(!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy))) return(-1); X shk->isshk = shk->mpeaceful = 1; X shk->msleep = 0; X shk->mtrapseen = ~0; /* we know all the traps already */ X ESHK(shk)->shoproom = sroom - rooms; X ESHK(shk)->shoplevel = dlevel; X ESHK(shk)->shd = doors[sh]; X ESHK(shk)->shk.x = sx; X ESHK(shk)->shk.y = sy; X /* makemon() has already zeroed out all the extra space X ESHK(shk)->robbed = 0; X ESHK(shk)->credit = 0; X ESHK(shk)->debit = 0; X ESHK(shk)->visitct = 0; X ESHK(shk)->following = 0; X ESHK(shk)->billct = 0; X */ X shk->mgold = 1000 + 30*rnd(100); /* initial capital */ X if (shp->shknms == shktools) { X static int who; X who = rn2(sizeof(shktools)/sizeof(char *)); X if (who==21) ESHK(shk)->ismale = FALSE; X else ESHK(shk)->ismale = TRUE; X (void) strncpy(ESHK(shk)->shknam, shp->shknms[who], PL_NSIZ); X ESHK(shk)->shknam[PL_NSIZ-1] = 0; X } else { X ESHK(shk)->ismale = dlevel%2; X findname(ESHK(shk)->shknam, shp->shknms); X } X X return(sh); X} X Xvoid Xstock_room(shp, sroom) X/* stock a newly-created room with artifacts */ Xstruct shclass *shp; Xregister struct mkroom *sroom; X{ X /* X * Someday soon we'll dispatch on the dist field of shclass to do X * different placements in this routine. Currently it only supports X * shop-style placement (all squares except a row nearest the first X * door get artifacts). X */ X register int sx, sy, sh; X X /* first, try to place a shopkeeper in the room */ X if ((sh = shkinit(shp, sroom)) < 0) X return; X X /* make sure no doorways without doors in shops */ X for(sx = sroom->lx - 1; sx <= sroom->hx + 1; sx++) X for(sy = sroom->ly - 1; sy <= sroom->hy + 1; sy++) { X if(IS_DOOR(levl[sx][sy].typ)) X if (levl[sx][sy].doormask == D_NODOOR) X levl[sx][sy].doormask = D_ISOPEN; X } X X for(sx = sroom->lx; sx <= sroom->hx; sx++) X for(sy = sroom->ly; sy <= sroom->hy; sy++) { X if((sx == sroom->lx && doors[sh].x == sx-1) || X (sx == sroom->hx && doors[sh].x == sx+1) || X (sy == sroom->ly && doors[sh].y == sy-1) || X (sy == sroom->hy && doors[sh].y == sy+1)) continue; X mkshobj_at(shp, sx, sy); X } X X /* X * Special monster placements (if any) should go here: that way, X * monsters will sit on top of artifacts and not the other way around. X */ X} X Xint Xsaleable(nshop, obj) /* does "shop" stock this item type */ Xregister int nshop; Xregister struct obj *obj; X{ X int i; X X if(shtypes[nshop].symb == RANDOM_SYM) return(1); X else { X for(i = 0; shtypes[nshop].iprobs[i].iprob; i++) X if(shtypes[nshop].iprobs[i].itype < 0) { X if(shtypes[nshop].iprobs[i].itype == - obj->otyp) return(1); X } X else if(shtypes[nshop].iprobs[i].itype == obj->olet) return(1); X } X return(0); X} X X/* positive value: letter; negative value: specific item type */ Xint Xget_shop_item(type) Xint type; X{ X struct shclass *shp = shtypes+type; X register int i,j; X X /* select an appropriate artifact type at random */ X for(j = rnd(100), i = 0; j -= shp->iprobs[i].iprob; i++) X if (j < 0) break; X X return shp->iprobs[i].itype; X} END_OF_FILE if test 11750 -ne `wc -c <'src/shknam.c'`; then echo shar: \"'src/shknam.c'\" unpacked with wrong size! fi # end of 'src/shknam.c' fi echo shar: End of archive 26 \(of 38\). cp /dev/null ark26isdone 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