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