billr@saab.CNA.TEK.COM (Bill Randle) (07/14/90)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu> Posting-number: Volume 10, Issue 89 Archive-name: nethack3p9/Part44 Supersedes: NetHack3: Volume 7, Issue 56-93 #! /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 44 (of 56)." # Contents: src/attrib.c src/dothrow.c src/mkroom.c src/mthrowu.c # src/steal.c # Wrapped by billr@saab on Wed Jul 11 17:11:59 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'src/attrib.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/attrib.c'\" else echo shar: Extracting \"'src/attrib.c'\" \(11892 characters\) sed "s/^X//" >'src/attrib.c' <<'END_OF_FILE' X/* SCCS Id: @(#)attrib.c 3.0 90/2/15 X/* Copyright 1988, 1989, 1990, M. Stephenson */ X/* NetHack may be freely redistributed. See license for details. */ X X/* attribute modification routines. */ X X#include "hack.h" X X#ifdef OVLB X Xconst char *plusattr[] = { /* part of the output on gain of attribute */ X X "strong", "smart", "wise", "agile", "tough", "charismatic" X}; X Xconst char *minusattr[] = { /* part of the output on loss of attribute */ X X "weak", "stupid", "foolish", "clumsy", "vulnerable", "ugly" X}; X Xstruct attribs attrmax = { /* max values for the attributes */ X X 118, 18, 18, 18, 18, 18 X}, X attrmin = { /* min values for the attributes */ X X 3, 3, 3, 3, 3, 3 X}; X Xconst struct innate { X X schar ulevel; X long *ability; X const char *gainstr, *losestr; X} a_abil[] = { { 1, &(Stealth), "", "" }, X { 1, &(Fast), "", "" }, X { 10, &(Searching), "perceptive", "" }, X { 0, 0, 0, 0 } }, X X b_abil[] = { { 1, &(HPoison_resistance), "", "" }, X { 7, &(Fast), "quick", "slow" }, X { 15, &(Stealth), "stealthy", "" }, X { 0, 0, 0, 0 } }, X X c_abil[] = { { 7, &(Fast), "quick", "slow" }, X { 15, &(Warning), "sensitive", "" }, X { 0, 0, 0, 0 } }, X X e_abil[] = { { 1, &(Fast), "", "" }, X { 1, &(HSee_invisible), "", "" }, X { 1, &(Searching), "", "" }, X { 1, &(HSleep_resistance), "", "" }, X { 0, 0, 0, 0 } }, X X h_abil[] = { { 1, &(HPoison_resistance), "", "" }, X { 15, &(Warning), "sensitive", "" }, X { 0, 0, 0, 0 } }, X X k_abil[] = { { 7, &(Fast), "quick", "slow" }, X { 0, 0, 0, 0 } }, X X p_abil[] = { { 15, &(Warning), "sensitive", "" }, X { 20, &(HFire_resistance), "cool", "warmer" }, X { 0, 0, 0, 0 } }, X X r_abil[] = { { 1, &(Stealth), "", "" }, X { 10, &(Searching), "perceptive", "" }, X { 0, 0, 0, 0 } }, X X s_abil[] = { { 1, &(Fast), "", "" }, X { 15, &(Stealth), "stealthy", "" }, X { 0, 0, 0, 0 } }, X X t_abil[] = { { 10, &(Searching), "perceptive", "" }, X { 20, &(HPoison_resistance), "hardy", "" }, X { 0, 0, 0, 0 } }, X X v_abil[] = { { 1, &(HCold_resistance), "", "" }, X { 1, &(Stealth), "", "" }, X { 7, &(Fast), "quick", "slow" }, X { 0, 0, 0, 0 } }, X X w_abil[] = { { 15, &(Warning), "sensitive", "" }, X { 17, &(HTeleport_control), "controlled","uncontrolled" }, X { 0, 0, 0, 0 } }; X Xconst struct clattr { X X struct attribs base, dist; X schar align, aligntyp; X schar shp, hd, xlev, ndx; X/* According to AD&D, HD for some classes (ex. Wizard) should be smaller X * (4-sided for wizards). But this is not AD&D, and using the AD&D X * rule here produces an unplayable character. This I have used a minimum X * of an 10-sided hit die for everything. Another AD&D change: wizards get X * a minimum strength of 6 since without one you can't teleport or cast X * spells. --KAA X */ X const struct innate *abil; X} a_attr = { { 7, 10, 10, 7, 7, 7 }, /* Archeologist */ X { 20, 20, 20, 10, 20, 10 }, X 10, 1, 13, 10, 14, 2, a_abil }, X X b_attr = { { 16, 7, 7, 15, 16, 6 }, /* Barbarian */ X { 30, 6, 7, 20, 30, 7 }, X 10, -1, 16, 12, 10, 3, b_abil }, X X c_attr = { { 10, 7, 7, 7, 8, 6 }, /* Caveman (fighter) */ X { 30, 6, 7, 20, 30, 7 }, X 0, 1, 16, 10, 10, 3, c_abil }, X X/* X e_attr = { { 13, 13, 14, 6, 14, 6 }, X */ X e_attr = { { 13, 13, 13, 9, 13, 7 }, /* Elf (ranger) */ X { 30, 10, 10, 20, 20, 10 }, X 10, 1, 15, 10, 11, 2, e_abil }, X X h_attr = { { 7, 7, 13, 7, 11, 16 }, /* Healer (druid) */ X { 15, 20, 20, 15, 25, 10 }, X 10, 1, 13, 10, 20, 2, h_abil }, X X k_attr = { { 13, 7, 14, 8, 10, 17 }, /* Knight (paladin) */ X { 20, 15, 15, 10, 20, 10 }, X 10, 1, 16, 10, 10, 3, k_abil }, X X p_attr = { { 7, 7, 10, 7, 7, 7 }, /* Priest (cleric) */ X { 15, 10, 30, 15, 20, 10 }, X 0, 0, 14, 10, 10, 2, p_abil }, X X r_attr = { { 7, 7, 7, 10, 7, 6 }, /* Rogue (thief) */ X { 20, 10, 10, 30, 20, 10 }, X 10, -1, 12, 10, 11, 2, r_abil }, X X s_attr = { { 10, 8, 7, 10, 17, 6 }, /* Samurai (fighter/thief) */ X { 30, 10, 10, 30, 14, 10 }, X 10, 1, 15, 10, 11, 2, s_abil }, X X t_attr = { { 7, 10, 6, 7, 7, 10 }, /* Tourist */ X { 15, 10, 10, 15, 30, 20 }, X 0, 0, 10, 10, 14, 1, t_abil }, X X v_attr = { { 10, 7, 7, 7, 10, 7 }, /* Valkyrie (fighter) */ X { 30, 6, 7, 20, 30, 7 }, X 0, -1, 16, 10, 10, 3, v_abil }, X X w_attr = { { 7, 10, 7, 7, 7, 7 }, /* Wizard (magic-user) */ X { 10, 30, 10, 20, 20, 10 }, X 0, 0, 12, 10, 12, 1, w_abil }, X X X_attr = { { 3, 3, 3, 3, 3, 3 }, X { 20, 15, 15, 15, 20, 15 }, X 0, 0, 12, 10, 14, 1, 0 }; X Xstatic const struct clattr NEARDATA *NDECL(clx); Xstatic void NDECL(init_align); X Xvoid Xadjattrib(ndx, incr, silent) X X int ndx, incr; X boolean silent; X{ X if(!incr) return; X X if(incr > 0) { X if((AMAX(ndx) >= attrmax.a[ndx]) && (ACURR(ndx) >= AMAX(ndx))) { X X if(!silent && flags.verbose) X pline("You're already as %s as you can get.", X plusattr[ndx]); X ABASE(ndx) = AMAX(ndx) = attrmax.a[ndx]; /* just in case */ X return; X } X X ABASE(ndx) += incr; X if(ABASE(ndx) > AMAX(ndx)) { X incr = ABASE(ndx) - AMAX(ndx); X AMAX(ndx) += incr; X if(AMAX(ndx) > attrmax.a[ndx]) X AMAX(ndx) = attrmax.a[ndx]; X ABASE(ndx) = AMAX(ndx); X } X } else { X if((AMAX(ndx) <= attrmin.a[ndx]) && (ABASE(ndx) == AMAX(ndx))) { X if(!silent && flags.verbose) X pline("You're already as %s as you can get.", X minusattr[ndx]); X ABASE(ndx) = AMAX(ndx) = attrmin.a[ndx]; /* just in case */ X return; X } X X ABASE(ndx) += incr; X if(ABASE(ndx) < attrmin.a[ndx]) { X incr = ABASE(ndx) - attrmin.a[ndx]; X ABASE(ndx) = attrmin.a[ndx]; X AMAX(ndx) += incr; X if(AMAX(ndx) < attrmin.a[ndx]) X AMAX(ndx) = attrmin.a[ndx]; X } X } X if(!silent) X You("feel %s%s!", X (incr > 1) ? "very ": "", X (incr > 0) ? plusattr[ndx] : minusattr[ndx]); X flags.botl = 1; X return; X} X Xvoid Xgainstr(otmp, incr) X register struct obj *otmp; X register int incr; X{ X int num = 1; X X if(incr) num = incr; X else { X if(ABASE(A_STR) < 18) num = (rn2(4) ? 1 : rnd(6) ); X else if (ABASE(A_STR) < 103) num = rnd(10); X } X adjattrib(A_STR, (otmp && otmp->cursed) ? -num : num, TRUE); X} X Xvoid Xlosestr(num) /* may kill you; cause may be poison or monster like 'a' */ X register int num; X{ X int ustr = ABASE(A_STR) - num; X X while(ustr < 3) { X ustr++; X num--; X u.uhp -= 6; X u.uhpmax -= 6; X } X adjattrib(A_STR, -num, TRUE); X} X Xvoid Xchange_luck(n) X register schar n; X{ X u.uluck += n; X if (u.uluck < 0 && u.uluck < LUCKMIN) u.uluck = LUCKMIN; X if (u.uluck > 0 && u.uluck > LUCKMAX) u.uluck = LUCKMAX; X} X Xint Xstone_luck(parameter) Xboolean parameter; /* So I can't think up of a good name. So sue me. --KAA */ X{ X register struct obj *otmp; X register int bonchance = 0; X X for(otmp = invent; otmp; otmp=otmp->nobj) X if(otmp->otyp == LUCKSTONE) { X if (otmp->cursed) bonchance -= (int)otmp->quan; X else if (otmp->blessed) bonchance += otmp->quan; X else if (parameter) bonchance += otmp->quan; X } X X return sgn(bonchance); X} X X#endif /* OVLB */ X#ifdef OVL1 X Xvoid Xrestore_attrib() { X X int i; X X for(i = 0; i < A_MAX; i++) { /* all temporary losses/gains */ X X if(ATEMP(i) && ATIME(i)) { X if(!(--(ATIME(i)))) { /* countdown for change */ X ATEMP(i) += ATEMP(i) > 0 ? -1 : 1; X X if(ATEMP(i)) /* reset timer */ X ATIME(i) = 100 / ACURR(A_CON); X } X } X } X} X X#endif /* OVL1 */ X#ifdef OVLB X Xstatic const struct clattr * Xclx() { X X register const struct clattr *attr; X X switch (pl_character[0]) { X X case 'A': attr = &a_attr; X break; X case 'B': attr = &b_attr; X break; X case 'C': attr = &c_attr; X break; X case 'E': attr = &e_attr; X break; X case 'H': attr = &h_attr; X break; X case 'K': attr = &k_attr; X break; X case 'P': attr = &p_attr; X break; X case 'R': attr = &r_attr; X break; X case 'S': attr = &s_attr; X break; X case 'T': attr = &t_attr; X break; X case 'V': attr = &v_attr; X break; X case 'W': attr = &w_attr; X break; X default: /* unknown type */ X attr = &X_attr; X break; X } X return(attr); X} X Xstatic void Xinit_align() { /* called from newhp if u.ulevel is 0 */ X X register const struct clattr *attr = clx(); X X u.ualign = (int)attr->align; X u.ualigntyp = attr->aligntyp; X} X Xvoid Xinit_attr(np) X register int np; X{ X register int i, x, tryct; X register const struct clattr *attr = clx(); X X for(i = 0; i < A_MAX; i++) { X X ABASE(i) = AMAX(i) = attr->base.a[i]; X ATEMP(i) = ATIME(i) = 0; X np -= attr->base.a[i]; X } X X tryct = 0; X while(np > 0 && tryct < 100) { X X x = rn2(100); X for(i = 0; (i < A_MAX) && ((x -= attr->dist.a[i]) > 0); i++); X if(i >= A_MAX) continue; /* impossible */ X X if(ABASE(i) >= attrmax.a[i]) { X X tryct++; X continue; X } X tryct = 0; X ABASE(i)++; X AMAX(i)++; X np--; X } X X tryct = 0; X while(np < 0 && tryct < 100) { /* for redistribution */ X X x = rn2(100); X for(i = 0; (i < A_MAX) && ((x -= attr->dist.a[i]) > 0); i++); X if(i >= A_MAX) continue; /* impossible */ X X if(ABASE(i) <= attrmin.a[i]) { X X tryct++; X continue; X } X tryct = 0; X ABASE(i)--; X AMAX(i)--; X np++; X } X} X Xvoid Xredist_attr() { X X register int i, tmp; X X for(i = 0; i < A_MAX; i++) { X if (i==A_INT || i==A_WIS) continue; X /* Polymorphing doesn't change your mind */ X tmp = AMAX(i); X AMAX(i) += (rn2(5)-2); X if (AMAX(i) > attrmax.a[i]) AMAX(i) = attrmax.a[i]; X if (AMAX(i) < attrmin.a[i]) AMAX(i) = attrmin.a[i]; X ABASE(i) = ABASE(i) * AMAX(i) / tmp; X /* ABASE(i) > attrmax.a[i] is impossible */ X if (ABASE(i) < attrmin.a[i]) ABASE(i) = attrmin.a[i]; X } X} X Xvoid Xadjabil(oldlevel,newlevel) Xint oldlevel, newlevel; X{ X register const struct clattr *attr = clx(); X#ifdef __GNULINT__ X /* this is the "right" definition */ X register const struct innate *abil = attr->abil; X#else X /* this one satisfies more compilers */ X register struct innate *abil = (struct innate *)attr->abil; X#endif X X if(abil) { X for(; abil->ability; abil++) { X if(oldlevel < abil->ulevel && newlevel >= abil->ulevel) { X if(!(*(abil->ability) & INTRINSIC)) { X *(abil->ability) |= INTRINSIC; X if(strlen(abil->gainstr)) X You("feel %s!", abil->gainstr); X } X } else if (oldlevel >= abil->ulevel && newlevel < abil->ulevel) { X if((*(abil->ability) & INTRINSIC)) { X *(abil->ability) &= ~INTRINSIC; X if(strlen(abil->losestr)) X You("feel %s!", abil->losestr); X else if(strlen(abil->gainstr)) X You("feel less %s!", abil->gainstr); X } X } X } X } X} X Xint Xnewhp() { X register const struct clattr *attr = clx(); X int hp, conplus; X X if(u.ulevel == 0) { X X hp = attr->shp; X init_align(); /* initialize alignment stuff */ X return hp; X } else { X X if(u.ulevel < attr->xlev) X hp = rnd(attr->hd); X else X hp = attr->ndx; X } X X switch(ACURR(A_CON)) { X case 3: conplus = -2; break; X case 4: X case 5: X case 6: conplus = -1; break; X case 15: X case 16: conplus = 1; break; X case 17: conplus = 2; break; X case 18: conplus = 3; break; X default: conplus = 0; X } X hp += conplus; X return((hp <= 0) ? 1 : hp); X} X X#endif /* OVLB */ X#ifdef OVL0 X Xschar Xacurr(x) Xint x; X{ X register int tmp = (u.abon.a[x] + u.atemp.a[x] + u.acurr.a[x]); X X if (x == A_STR) { X if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER) return(125); X else return((tmp >= 125) ? 125 : (tmp <= 3) ? 3 : tmp); X } X else return((tmp >= 25) ? 25 : (tmp <= 3) ? 3 : tmp); X} X X#endif /* OVL0 */ X#ifdef OVL2 X X/* avoid possible problems with alignment overflow, and provide a centralized X * location for any future alignment limits X */ Xvoid Xadjalign(n) Xregister int n; X{ X register int newalign = u.ualign + n; X X if(n < 0) { X if(newalign < u.ualign) X u.ualign = newalign; X } else X if(newalign > u.ualign) X u.ualign = newalign; X} X X#endif /* OVL2 */ END_OF_FILE if test 11892 -ne `wc -c <'src/attrib.c'`; then echo shar: \"'src/attrib.c'\" unpacked with wrong size! fi # end of 'src/attrib.c' fi if test -f 'src/dothrow.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/dothrow.c'\" else echo shar: Extracting \"'src/dothrow.c'\" \(11651 characters\) sed "s/^X//" >'src/dothrow.c' <<'END_OF_FILE' X/* SCCS Id: @(#)dothrow.c 3.0 89/11/15 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X/* Contains code for 't' (throw) */ X X#include "hack.h" X Xstatic void FDECL(hitfloor, (struct obj *)); Xstatic void FDECL(gem_accept, (struct monst *, struct obj *)); Xstatic boolean NDECL(martial); Xstatic int FDECL(throw_gold, (struct obj *)); Xstatic const char NEARDATA toss_objs[] = { '0', GOLD_SYM, '#', WEAPON_SYM, 0 }; X#ifdef WORM Xextern boolean notonhead; X#endif X Xint Xdothrow() { X register struct obj *obj; X X obj = getobj(toss_objs, "throw"); X /* it is also possible to throw food */ X /* (or jewels, or iron balls... ) */ X X if(!obj || !getdir(1)) { /* ask "in what direction?" */ X if(obj && obj->olet == GOLD_SYM) u.ugold += OGOLD(obj); X return(0); X } X X if(obj->olet == GOLD_SYM) return(throw_gold(obj)); X X if(!canletgo(obj,"throw")) X return(0); X if(obj->otyp == BOULDER X#ifdef POLYSELF X && !throws_rocks(uasmon) X#endif X ) { X pline("It's too heavy."); X return(1); X } X if(!u.dx && !u.dy && !u.dz) { X You("cannot throw an object at yourself."); X return(0); X } X u_wipe_engr(2); X X if(obj == uwep) { X if(welded(obj)) { X weldmsg(obj, FALSE); X return(1); X } X if(obj->quan > 1) X setuwep(splitobj(obj, 1)); X else { X setuwep((struct obj *)0); X if (uwep) return(1); /* unwielded, died, rewielded */ X } X } X else if(obj->quan > 1) X (void) splitobj(obj, 1); X freeinv(obj); X return(throwit(obj)); X} X Xstatic void Xhitfloor(obj) Xregister struct obj *obj; X{ X#ifdef ALTARS X if (IS_ALTAR(levl[u.ux][u.uy].typ)) doaltarobj(obj); X else X#endif X pline("%s hits the floor.", Doname2(obj)); X if (breaks(obj, TRUE)) return; X else if(obj->olet == POTION_SYM) { X pline("The flask breaks, and you smell a peculiar odor..."); X potionbreathe(obj); X obfree(obj, (struct obj *)0); X } else X dropy(obj); X} X Xint Xthrowit(obj) Xregister struct obj *obj; X{ X register struct monst *mon; X register int range; X X if(u.uswallow) { X mon = u.ustuck; X bhitpos.x = mon->mx; X bhitpos.y = mon->my; X } else if(u.dz) { X if(u.dz < 0) { X pline("%s hits the ceiling, then falls back on top of your %s.", X Doname2(obj), /* note: obj->quan == 1 */ X body_part(HEAD)); X if(obj->olet == POTION_SYM) X potionhit(&youmonst, obj); X else { X if(uarmh) pline("Fortunately, you are wearing a helmet!"); X losehp(uarmh ? 1 : rnd((int)(obj->owt)), "falling object", X KILLED_BY_AN); X if (!breaks(obj, TRUE)) dropy(obj); X } X } else hitfloor(obj); X return(1); X X } else if(obj->otyp == BOOMERANG) { X mon = boomhit(u.dx, u.dy); X if(mon == &youmonst) { /* the thing was caught */ X (void) addinv(obj); X return(1); X } X } else { X if(shkcatch(obj)) X return(1); X X range = (int)((ACURR(A_STR) > 18 ? 20 : ACURR(A_STR))/2 - obj->owt/4); X if (obj == uball) { X if (u.ustuck) range = 1; X else if (range >= 5) range = 5; X } X if (range < 1) range = 1; X X if ((obj->olet == WEAPON_SYM || obj->olet == GEM_SYM) && X uwep && X objects[obj->otyp].w_propellor == X -objects[uwep->otyp].w_propellor) X range++; X#ifdef POLYSELF X if (obj->otyp == BOULDER) range = 20; X#endif X X mon = bhit(u.dx, u.dy, range, obj->olet, X (int (*)()) 0, (int (*)()) 0, obj); X } X if(mon) { X /* awake monster if sleeping */ X wakeup(mon); X#ifdef WORM X if(bhitpos.x != mon->mx || bhitpos.y != mon->my) X notonhead = TRUE; X#endif X if(thitmonst(mon, obj)) return(1); X } X if(!u.uswallow) { X char let = obj->olet; X X /* the code following might become part of dropy() */ X if (breaks(obj, TRUE)) { X tmp_at(-1, let); X#ifdef TEXTCOLOR X tmp_at(-3, (int)objects[obj->otyp].oc_color); X#else X tmp_at(-3, (int)AT_OBJ); X#endif X tmp_at(bhitpos.x, bhitpos.y); X tmp_at(-1, -1); X return(1); X } X if(flooreffects(obj,bhitpos.x,bhitpos.y)) return(1); X#ifdef WORM X if(obj->otyp == CRYSKNIFE) X obj->otyp = WORM_TOOTH; X#endif X obj->nobj = fobj; X fobj = obj; X place_object(obj, bhitpos.x, bhitpos.y); X if(obj != uball && costly_spot(bhitpos.x, bhitpos.y) && X !(mon && mon->isshk && bhitpos.x == mon->mx && X bhitpos.y == mon->my && !(obj->unpaid))) X sellobj(obj); X stackobj(obj); X if(obj == uball && X (bhitpos.x != u.ux || bhitpos.y != u.uy)){ X if(u.utrap){ X if(u.utraptype == TT_PIT) X pline("The ball pulls you out of the pit!"); X else if(u.utraptype == TT_WEB) { X pline("The ball pulls you out of the web!"); X pline("The web is destroyed!"); X deltrap(t_at(u.ux,u.uy)); X } else { X register long side = X rn2(3) ? LEFT_SIDE : RIGHT_SIDE; X pline("The ball pulls you out of the bear trap."); X Your("%s %s is severely damaged.", X (side == LEFT_SIDE) ? "left" : "right", X body_part(LEG)); X set_wounded_legs(side, 500+rn2(1000)); X losehp(2, "leg damage from being pulled out of a bear trap", X KILLED_BY); X } X u.utrap = 0; X } X unsee(); X u.ux = bhitpos.x - u.dx; X u.uy = bhitpos.y - u.dy; X movobj(uchain,u.ux,u.uy); X setsee(); X spoteffects(); X } X if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y); X } else X mpickobj(u.ustuck,obj); X return(1); X} X Xint Xthitmonst(mon, obj) Xregister struct monst *mon; Xregister struct obj *obj; X{ X register int tmp; /* Base chance to hit */ X X /* Differences from melee weapons: X * X * Dex still gives a bonus, but strength does not. X * Polymorphed players lacking attacks may still throw. X * There's a base -2 to hit. X * No bonuses for fleeing or stunned targets (they don't dodge X * melee blows as readily, but dodging arrows is hard anyway). X * Not affected by traps, etc... X * Certain items which don't in themselves do damage ignore tmp. X */ X tmp = -2 + Luck + mon->data->ac; X#ifdef POLYSELF X if (u.umonnum >= 0) tmp += uasmon->mlevel; X else X#endif X tmp += u.ulevel; X if(ACURR(A_DEX) < 4) tmp -= 3; X else if(ACURR(A_DEX) < 6) tmp -= 2; X else if(ACURR(A_DEX) < 8) tmp -= 1; X else if(ACURR(A_DEX) > 15) tmp += (ACURR(A_DEX) - 15); X X if(mon->msleep) { X mon->msleep = 0; X tmp += 2; X } X if(!mon->mcanmove) { X tmp += 4; X if(!rn2(10)) { X mon->mcanmove = 1; X mon->mfrozen = 0; X } X } X if (is_orc(mon->data) && pl_character[0]=='E') tmp++; X if (u.uswallow && mon == u.ustuck) tmp += 1000; /* Guaranteed hit */ X X if(obj->olet == GEM_SYM && mon->data->mlet == S_UNICORN) { X if (mon->mtame) { X kludge("%s catches and drops the %s.", X Monnam(mon), xname(obj)); X return(0); X } else { X kludge("%s catches the %s.", Monnam(mon), xname(obj)); X gem_accept(mon, obj); X return(1); X } X } X if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE || X obj->otyp == UNICORN_HORN || obj->olet == GEM_SYM) { X if(obj->otyp < DART || obj->olet == GEM_SYM) { X if (!uwep || X objects[obj->otyp].w_propellor != X -objects[uwep->otyp].w_propellor) X tmp -= 4; X else tmp += uwep->spe; X } else if(obj->otyp == BOOMERANG) tmp += 4; X tmp += obj->spe; X tmp += hitval(obj, mon->data); X if(tmp >= rnd(20)) { X if(hmon(mon,obj,1) == TRUE){ X /* mon still alive */ X#ifdef WORM X cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp); X#endif X } else mon = 0; X /* projectiles thrown disappear sometimes */ X if((obj->otyp < BOOMERANG || obj->olet == GEM_SYM) X && rn2(3)) { X /* check bill; free */ X obfree(obj, (struct obj *)0); X return(1); X } X } else miss(xname(obj), mon); X } else if(obj->otyp == HEAVY_IRON_BALL) { X if(obj != uball) tmp += 2; X if(tmp >= rnd(20)) { X if(hmon(mon,obj,1) == FALSE) X mon = 0; /* he died */ X } else miss(xname(obj), mon); X } else if (obj->otyp == BOULDER) { X tmp += 6; /* Likely to hit! */ X if(tmp >= rnd(20)) { X if(hmon(mon,obj,1) == FALSE) X mon = 0; /* he died */ X } else miss(xname(obj), mon); X } else if((obj->otyp == CREAM_PIE X#ifdef POLYSELF X || obj->otyp == BLINDING_VENOM X#endif X ) && ACURR(A_DEX) >= rnd(10)) { X (void) hmon(mon,obj,1); /* can't die from it */ X#ifdef POLYSELF X } else if(obj->otyp == ACID_VENOM && ACURR(A_DEX) >= rnd(10)) { X if(hmon(mon,obj,1) == FALSE) X mon = 0; X#endif X } else if(obj->olet == POTION_SYM && ACURR(A_DEX) >= rnd(15)) { X potionhit(mon, obj); X return(1); X } else { X pline("The %s misses %s.", xname(obj), X cansee(bhitpos.x,bhitpos.y) ? mon_nam(mon) : "it"); X if(obj->olet == FOOD_SYM && is_domestic(mon->data)) X if(tamedog(mon,obj)) return(1); X } X return(0); X} X Xstatic void Xgem_accept(mon, obj) Xregister struct monst *mon; Xregister struct obj *obj; X{ X char buf[BUFSZ]; X static const char NEARDATA nogood[] = " is not interested in your junk."; X static const char NEARDATA maybeluck[] = " hesitatingly accepts your gift."; X static const char NEARDATA addluck[] = " graciously accepts your gift."; X X Strcpy(buf,Monnam(mon)); X X mon->mpeaceful = 1; X if(obj->dknown && objects[obj->otyp].oc_name_known) { X if(objects[obj->otyp].g_val > 0) { X if(mon->data == &mons[ X ((u.ualigntyp== U_CHAOTIC) ? PM_BLACK_UNICORN : X (u.ualigntyp == U_LAWFUL) ? PM_WHITE_UNICORN X : PM_GRAY_UNICORN)]) { X Strcat(buf, addluck); X change_luck(5); X } else { X Strcat(buf, maybeluck); X change_luck(rn2(7)-3); X } X } else { X Strcat(buf,nogood); X goto nopick; X } X } else { /* value unknown to @ */ X change_luck(1); X Strcat(buf,addluck); X } X mpickobj(mon, obj); Xnopick: X if(!Blind) pline(buf); X rloc(mon); X} X X/* returns 0 if object doesn't break */ X/* returns 1 if object broke */ Xint Xbreaks(obj, loose) Xregister struct obj *obj; Xregister boolean loose; /* if not loose, obj is in fobj chain */ X{ X switch(obj->otyp) { X#ifdef MEDUSA X case MIRROR: X change_luck(-2); /* and fall through */ X#endif X case EXPENSIVE_CAMERA: X case CRYSTAL_BALL: X if(!Blind) X pline("%s shatters into a thousand pieces!", X Doname2(obj)); X else You("hear something shatter!"); X break; X case EGG: X pline("Splat!"); X break; X case CREAM_PIE: X pline("What a mess!"); X break; X case ACID_VENOM: X case BLINDING_VENOM: X pline("Splash!"); X break; X default: X return 0; X } X X if(loose) { X unpobj(obj); X obfree(obj, (struct obj *)0); X } else { X addtobill(obj, FALSE); X delobj(obj); X } X return(1); X} X Xstatic boolean Xmartial() X{ X return((pl_character[0] == 'S' || pl_character[0] == 'P')); X} X Xstatic int Xthrow_gold(obj) Xstruct obj *obj; X{ X int range = 0, odx, ody; X long zorks = OGOLD(obj); X register struct monst *mon; X X free((genericptr_t) obj); X if(zorks < 0) { X /* watch negative overflows a la drop() */ X u.ugold += zorks; X pline("The LRS would be very interested to know you have that much."); X return(0); X } X X if(u.uswallow) { X if (is_animal(u.ustuck->data)) X pline("The gold disappears in the %s's entrails.", X mon_nam(u.ustuck)); X else X pline("The gold disappears into %s.", X mon_nam(u.ustuck)); X u.ustuck->mgold += zorks; X return(1); X } X X if(u.dz) { X if(u.dz < 0) { X pline("The gold hits the ceiling, then falls back on top of your %s.", X body_part(HEAD)); X /* some self damage? */ X if(uarmh) pline("Fortunately, you are wearing a helmet!"); X } else pline("The gold hits the floor."); X bhitpos.x = u.ux; /* a msg is needed here */ X bhitpos.y = u.uy; X goto skip; X } X X range = rnd((int)ACURR(A_STR)); X if(martial()) range = range + rnd(3); X X /* see if the gold has a place to move into */ X odx = u.ux + u.dx; X ody = u.uy + u.dy; X if(bad_kick_throw_pos(odx,ody)) { X bhitpos.x = u.ux; X bhitpos.y = u.uy; X } else { X if (mon = ghit(u.dx, u.dy, range)) X if (ghitm(mon, zorks)) /* was it caught? */ X zorks = 0; X } Xskip: X if (zorks) /* perhaps it was caught */ X mkgold(zorks, bhitpos.x, bhitpos.y); X if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y); X return(1); X} END_OF_FILE if test 11651 -ne `wc -c <'src/dothrow.c'`; then echo shar: \"'src/dothrow.c'\" unpacked with wrong size! fi # end of 'src/dothrow.c' fi if test -f 'src/mkroom.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/mkroom.c'\" else echo shar: Extracting \"'src/mkroom.c'\" \(11429 characters\) sed "s/^X//" >'src/mkroom.c' <<'END_OF_FILE' X/* SCCS Id: @(#)mkroom.c 3.0 88/11/24 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X/* X * Entry points: X * mkroom() -- make and stock a room of a given type X * nexttodoor() -- return TRUE if adjacent to a door X * has_dnstairs() -- return TRUE if given room has a down staircase X * has_upstairs() -- return TRUE if given room has an up staircase X * dist2() -- Euclidean square-of-distance function X * courtmon() -- generate a court monster X */ X X#define MONATTK_H /* comment line for pre-compiled headers */ X/* block some unused #defines to avoid overloading some cpp's */ X#include "hack.h" X X#ifdef OVLB Xstatic boolean FDECL(isbig, (struct mkroom *)); Xstatic struct mkroom * FDECL(pick_room,(BOOLEAN_P)); Xstatic void NDECL(mkshop), FDECL(mkzoo,(int)), NDECL(mkswamp); X#ifdef ORACLE Xstatic void NDECL(mkdelphi); X#endif X#if defined(ALTARS) && defined(THEOLOGY) Xstatic void NDECL(mktemple); X#endif X Xstatic struct permonst * NDECL(morguemon); X#ifdef ARMY Xstatic struct permonst * NDECL(squadmon); X#endif X#endif /* OVLB */ X X#define sq(x) ((x)*(x)) X X#ifdef OVLB X Xstatic boolean Xisbig(sroom) Xregister struct mkroom *sroom; X{ X register int area = (sroom->hx - sroom->lx) * (sroom->hy - sroom->ly); X return( area > 20 ); X} X Xvoid Xmkroom(roomtype) X/* make and stock a room of a given type */ Xint roomtype; X{ X X if (roomtype >= SHOPBASE) X mkshop(); /* someday, we should be able to specify shop type */ X else switch(roomtype) { X#ifdef THRONES X case COURT: mkzoo(COURT); break; X#endif X case ZOO: mkzoo(ZOO); break; X case BEEHIVE: mkzoo(BEEHIVE); break; X case MORGUE: mkzoo(MORGUE); break; X case BARRACKS: mkzoo(BARRACKS); break; X case SWAMP: mkswamp(); break; X#ifdef ORACLE X case DELPHI: mkdelphi(); break; X#endif X#if defined(ALTARS) && defined(THEOLOGY) X case TEMPLE: mktemple(); break; X#endif X default: impossible("Tried to make a room of type %d.", roomtype); X } X} X Xstatic void Xmkshop() X{ X register struct mkroom *sroom; X int i = -1; X#ifdef WIZARD X# ifdef __GNULINT__ X register char *ep = (char *)0; X# else X register char *ep; X# endif X X /* first determine shoptype */ X if(wizard){ X ep = getenv("SHOPTYPE"); X if(ep){ X if(*ep == 'z' || *ep == 'Z'){ X mkzoo(ZOO); X return; X } X if(*ep == 'm' || *ep == 'M'){ X mkzoo(MORGUE); X return; X } X if(*ep == 'b' || *ep == 'B'){ X mkzoo(BEEHIVE); X return; X } X#ifdef THRONES X if(*ep == 't' || *ep == 'T' || *ep == '\\'){ X mkzoo(COURT); X return; X } X#endif X#ifdef ARMY X if(*ep == 's' || *ep == 'S'){ X mkzoo(BARRACKS); X return; X } X#endif /* ARMY */ X#if defined(ALTARS) && defined(THEOLOGY) X if(*ep == '_'){ X mktemple(); X return; X } X#endif X if(*ep == '}'){ X mkswamp(); X return; X } X for(i=0; shtypes[i].name; i++) X if(*ep == shtypes[i].symb) goto gottype; X if(*ep == 'g' || *ep == 'G') X i = 0; X else X i = -1; X } X } Xgottype: X#endif X for(sroom = &rooms[0]; ; sroom++){ X if(sroom->hx < 0) return; X if(sroom - rooms >= nroom) { X pline("rooms not closed by -1?"); X return; X } X if(sroom->rtype != OROOM) continue; X if(!sroom->rlit || has_dnstairs(sroom) || has_upstairs(sroom)) X continue; X if( X#ifdef WIZARD X (wizard && ep && sroom->doorct != 0) || X#endif X sroom->doorct == 1) break; X } X X if(i < 0) { /* shoptype not yet determined */ X register int j; X X /* pick a shop type at random */ X for(j = rn2(100), i = 0; j -= shtypes[i].prob; i++) X if (j < 0) break; X X /* big rooms cannot be wand or book shops, X * - so make them general stores X */ X if(isbig(sroom) && (shtypes[i].symb == WAND_SYM X#ifdef SPELLS X || shtypes[i].symb == SPBOOK_SYM X#endif X )) i = 0; X } X sroom->rtype = SHOPBASE + i; X X /* stock the room with a shopkeeper and artifacts */ X stock_room(&(shtypes[i]), sroom); X} X Xstatic struct mkroom * Xpick_room(strict) Xregister boolean strict; X/* pick an unused room, preferably with only one door */ X{ X register struct mkroom *sroom; X register int i = nroom; X X for(sroom = &rooms[rn2(nroom)]; i--; sroom++) { X if(sroom == &rooms[nroom]) X sroom = &rooms[0]; X if(sroom->hx < 0) X return (struct mkroom *)0; X if(sroom->rtype != OROOM) continue; X if(!strict) { X if(has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3))) X continue; X } else if(has_upstairs(sroom) || has_dnstairs(sroom)) X continue; X if(sroom->doorct == 1 || !rn2(5)) X return sroom; X } X return (struct mkroom *)0; X} X Xstatic void Xmkzoo(type) Xint type; X{ X register struct mkroom *sroom; X struct monst *mon; X register int sx,sy,i; X int sh, tx, ty, goldlim = 500 * dlevel; X X if(!(sroom = pick_room(FALSE))) return; X X sroom->rtype = type; X sh = sroom->fdoor; X switch(type) { X#ifdef __GNULINT__ X default: X /* make sure tx and ty are initialized */ X#endif X case COURT: X tx = somex(sroom); ty = somey(sroom); break; X /* TODO: try to ensure the enthroned monster is an M2_PRINCE */ X case BEEHIVE: X tx = sroom->lx + (sroom->hx - sroom->lx + 1)/2; X ty = sroom->ly + (sroom->hy - sroom->ly + 1)/2; X break; 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 mon = makemon( X#ifdef THRONES X (type == COURT) ? courtmon() : X#endif X#ifdef ARMY X (type == BARRACKS) ? squadmon() : X#endif X (type == MORGUE) ? morguemon() : X (type == BEEHIVE) ? X (sx == tx && sy == ty ? &mons[PM_QUEEN_BEE] : X &mons[PM_KILLER_BEE]) : X (struct permonst *) 0, X sx, sy); X if(mon) { X mon->msleep = 1; X#ifdef THRONES X if (type==COURT && mon->mpeaceful) { X mon->mpeaceful = 0; X mon->malign = max(3,abs(mon->data->maligntyp)); X } X#endif X } X switch(type) { X case ZOO: X i = sq(dist2(sx,sy,doors[sh].x,doors[sh].y)); X if(i >= goldlim) i = 5*dlevel; X goldlim -= i; X mkgold((long)(10 + rn2(i)), sx, sy); X break; X case MORGUE: X if(!rn2(5)) X (void) mk_tt_object(CORPSE, sx, sy); X if(!rn2(10)) /* lots of treasure buried with dead */ X (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy); X break; X case BEEHIVE: X if(!rn2(3)) X (void) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy); X break; X case BARRACKS: X if(!rn2(20)) /* the payroll and some loot */ X (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy); X break; X } X } X#ifdef THRONES X if(type == COURT) { X levl[tx][ty].typ = THRONE; X levl[tx][ty].scrsym = THRONE_SYM; X X sx = somex(sroom); X sy = somey(sroom); X mkgold((long) rn1(50 * dlevel,10), sx, sy); X (void) mksobj_at(CHEST, sx, sy); /* the royal coffers */ X } X#endif X X} X Xstatic struct permonst * Xmorguemon() X{ X register int i = rn2(100), hd = rn2(dlevel); X X if(hd > 10 && i < 10) X return((Inhell) ? mkclass(S_DEMON) : &mons[ndemon()]); X if(hd > 8 && i > 85) X return(mkclass(S_VAMPIRE)); X X return((i < 20) ? &mons[PM_GHOST] X : (i < 40) ? &mons[PM_WRAITH] : mkclass(S_ZOMBIE)); X} X Xstatic void Xmkswamp() /* Michiel Huisjes & Fred de Wilde */ X{ X register struct mkroom *sroom; X register int sx,sy,i,eelct = 0; X X for(i=0; i<5; i++) { /* 5 tries */ X sroom = &rooms[rn2(nroom)]; X if(sroom->hx < 0 || sroom->rtype != OROOM || X has_upstairs(sroom) || has_dnstairs(sroom)) X continue; X X /* satisfied; make a swamp */ X sroom->rtype = SWAMP; X for(sx = sroom->lx; sx <= sroom->hx; sx++) X for(sy = sroom->ly; sy <= sroom->hy; sy++) X if(!OBJ_AT(sx, sy) && levl[sx][sy].gmask == 0 && X !MON_AT(sx, sy) && !t_at(sx,sy) && !nexttodoor(sx,sy)) { X if((sx+sy)%2) { X levl[sx][sy].typ = POOL; X levl[sx][sy].scrsym = POOL_SYM; X if(!eelct || !rn2(4)) { X (void) makemon(mkclass(S_EEL), sx, sy); X eelct++; X } X } else if(!rn2(4)) /* swamps tend to be moldy */ X (void) makemon(mkclass(S_FUNGUS), sx, sy); X } X } X} X X#ifdef ORACLE Xstatic void Xmkdelphi() X{ X register struct mkroom *sroom; X register struct monst *oracl; X int dy,xx,yy; X X if(doorindex >= DOORMAX) return; X if(!(sroom = pick_room(FALSE))) return; X X if(!place_oracle(sroom,&dy,&xx,&yy)) return; X X if(MON_AT(xx, yy)) X rloc(m_at(xx, yy)); /* insurance */ X X /* set up Oracle and environment */ X if(!(oracl = makemon(&mons[PM_ORACLE],xx,yy))) return; X sroom->rtype = DELPHI; X oracl->mpeaceful = 1; X X yy -= dy; X if(accessible(xx-1, yy)) X (void) mkcorpstat(STATUE, &mons[PM_FOREST_CENTAUR], xx-1, yy); X if(accessible(xx, yy)) X (void) mkcorpstat(STATUE, &mons[PM_MOUNTAIN_CENTAUR], xx, yy); X if(accessible(xx+1,yy)) X (void) mkcorpstat(STATUE, &mons[PM_PLAINS_CENTAUR], xx+1, yy); X# ifdef FOUNTAINS X mkfount(0,sroom); X# endif X} X#endif X X#if defined(ALTARS) && defined(THEOLOGY) Xvoid Xshrine_pos(sx,sy,troom) Xint *sx,*sy; Xstruct mkroom *troom; X{ X *sx = troom->lx + ((troom->hx - troom->lx) / 2); X *sy = troom->ly + ((troom->hy - troom->ly) / 2); X} X Xstatic void Xmktemple() X{ X register struct mkroom *sroom; X int sx,sy; X X if(!(sroom = pick_room(TRUE))) return; X X /* set up Priest and shrine */ X sroom->rtype = TEMPLE; X shrine_pos(&sx,&sy,sroom); X /* X * In temples, shrines are blessed altars X * located in the center of the room X */ X levl[sx][sy].typ = ALTAR; X levl[sx][sy].scrsym = ALTAR_SYM; X levl[sx][sy].altarmask = rn2((int)A_LAW+1); X priestini(dlevel, sx, sy, (int) levl[sx][sy].altarmask); X levl[sx][sy].altarmask |= A_SHRINE; X} X#endif X Xboolean Xnexttodoor(sx,sy) Xregister int sx, sy; X{ X register int dx, dy; X register struct rm *lev; X for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++) { X if(!isok(sx+dx, sy+dy)) continue; X if(IS_DOOR((lev = &levl[sx+dx][sy+dy])->typ) || X lev->typ == SDOOR) X return(TRUE); X } X return(FALSE); X} X Xboolean Xhas_dnstairs(sroom) Xregister struct mkroom *sroom; X{ X return(sroom->lx <= xdnstair && xdnstair <= sroom->hx && X sroom->ly <= ydnstair && ydnstair <= sroom->hy); X} X Xboolean Xhas_upstairs(sroom) Xregister struct mkroom *sroom; X{ X return(sroom->lx <= xupstair && xupstair <= sroom->hx && X sroom->ly <= yupstair && yupstair <= sroom->hy); X} X X#endif /* OVLB */ X#ifdef OVL0 X Xint Xdist2(x0,y0,x1,y1) Xint x0, y0, x1, y1; X{ X register int dx = x0 - x1, dy = y0 - y1; X return sq(dx) + sq(dy); X} X X#endif /* OVL0 */ X#ifdef OVLB X X#ifdef THRONES Xstruct permonst * Xcourtmon() X{ X int i = rn2(60) + rn2(3*dlevel); X if (i > 100) return(mkclass(S_DRAGON)); X else if (i > 95) return(mkclass(S_GIANT)); X else if (i > 85) return(mkclass(S_TROLL)); X else if (i > 75) return(mkclass(S_CENTAUR)); X else if (i > 60) return(mkclass(S_ORC)); X else if (i > 45) return(&mons[PM_BUGBEAR]); X else if (i > 30) return(&mons[PM_HOBGOBLIN]); X else if (i > 15) return(mkclass(S_GNOME)); X else return(mkclass(S_KOBOLD)); X} X#endif /* THRONES /**/ X X#ifdef ARMY X#define NSTYPES (PM_CAPTAIN-PM_SOLDIER+1) X Xstruct { X unsigned pm; X unsigned prob; X} squadprob[NSTYPES] = { X PM_SOLDIER, 80, PM_SERGEANT, 15, PM_LIEUTENANT, 4, PM_CAPTAIN, 1 X}; X Xstatic struct permonst * Xsquadmon() { /* return soldier types. */ X X register struct permonst *ptr; X register int i, cpro, sel_prob = rnd(80+dlevel); X X for(cpro = i = 0; i < NSTYPES; i++) X if((cpro += squadprob[i].prob) > sel_prob) { X X ptr = &mons[squadprob[i].pm]; X goto gotone; X } X ptr = &mons[squadprob[rn2(NSTYPES)].pm]; Xgotone: X if(!(ptr->geno & G_GENOD)) return(ptr); X else return((struct permonst *) 0); X} X#endif /* ARMY /* */ X X#endif /* OVLB */ END_OF_FILE if test 11429 -ne `wc -c <'src/mkroom.c'`; then echo shar: \"'src/mkroom.c'\" unpacked with wrong size! fi # end of 'src/mkroom.c' fi if test -f 'src/mthrowu.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/mthrowu.c'\" else echo shar: Extracting \"'src/mthrowu.c'\" \(12098 characters\) sed "s/^X//" >'src/mthrowu.c' <<'END_OF_FILE' X/* SCCS Id: @(#)mthrowu.c 3.0 89/11/22 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_DCL int FDECL(movedist,(int,int,int,int)); XSTATIC_DCL void FDECL(drop_throw,(struct obj *,BOOLEAN_P,int,int)); XSTATIC_DCL void FDECL(m_throw,(int,int,int,int,int,struct obj *)); X X#define URETREATING(x,y) (movedist(u.ux,u.uy,x,y) > movedist(u.ux0,u.uy0,x,y)) X Xboolean FDECL(lined_up, (struct monst *)); X X#ifndef OVLB X XSTATIC_DCL const char *breathwep[]; X X#else /* OVLB */ X Xschar NEARDATA tbx = 0, NEARDATA tby = 0; X /* used for direction of throw, buzz, etc. */ X XSTATIC_OVL const char NEARDATA *breathwep[] = { "fragments", X "fire", X "sleep gas", X "frost", X "death", X "lightning", X "poison gas", X "acid" X}; X Xint Xthitu(tlev, dam, obj, name) /* u is hit by sth, but not a monster */ X register int tlev, dam; X struct obj *obj; X register const char *name; X{ X const char *onm = an(name); X boolean is_acid = (obj && obj->otyp == ACID_VENOM); X X if(u.uac + tlev <= rnd(20)) { X if(Blind || !flags.verbose) pline("It misses."); X else You("are almost hit by %s!", onm); X return(0); X } else { X if(Blind || !flags.verbose) You("are hit!"); X else You("are hit by %s!", onm); X#ifdef POLYSELF X if (obj && obj->otyp == SILVER_ARROW && (u.ulycn != -1 || X is_demon(uasmon) || u.usym == S_VAMPIRE || X (u.usym == S_IMP && u.umonnum != PM_TENGU))) { X dam += rnd(20); X pline("The %sarrow sears your flesh!", X Blind ? "" : "silver "); X } X if (is_acid && resists_acid(uasmon)) X pline("It doesn't seem to hurt you."); X else { X#endif X if (is_acid) pline("It burns!"); X losehp(dam, name, KILLED_BY_AN); X#ifdef POLYSELF X } X#endif X return(1); X } X} X X/* Be sure this corresponds with what happens to player-thrown objects in X * dothrow.c (for consistency). --KAA X */ X XSTATIC_OVL void Xdrop_throw(obj, ohit, x, y) Xregister struct obj *obj; Xboolean ohit; Xint x,y; X{ X int create; X X if (obj->otyp == CREAM_PIE || obj->olet == VENOM_SYM) X create = 0; X else if (ohit && X ((obj->otyp >= ARROW && obj->otyp <= SHURIKEN) || X obj->otyp == ROCK)) X create = !rn2(3); X else create = 1; X if (create && !flooreffects(obj,x,y)) { X place_object(obj, x, y); X obj->nobj = fobj; X fobj = obj; X stackobj(fobj); X } else free((genericptr_t)obj); X} X X#endif /* OVLB */ X#ifdef OVL1 X XSTATIC_OVL void Xm_throw(x, y, dx, dy, range, obj) X register int x,y,dx,dy,range; /* direction and range */ X register struct obj *obj; X{ X register struct monst *mtmp; X struct obj *singleobj; X char sym = obj->olet; X int damage; X int hitu, blindinc=0; X X bhitpos.x = x; X bhitpos.y = y; X X singleobj = splitobj(obj, (int)obj->quan-1); X /* splitobj leaves the new object in the chain (i.e. the monster's X * inventory). Remove it. We can do this in 1 line, but it's highly X * dependent on the fact that we know splitobj() places it immediately X * after obj. X */ X obj->nobj = singleobj->nobj; X X if(sym) { X tmp_at(-1, sym); /* open call */ X#ifdef TEXTCOLOR X tmp_at(-3, (int)objects[obj->otyp].oc_color); X#else X tmp_at(-3, (int)AT_OBJ); X#endif X } X while(range-- > 0) { /* Actually the loop is always exited by break */ X boolean vis; X X bhitpos.x += dx; X bhitpos.y += dy; X vis = cansee(bhitpos.x, bhitpos.y); X if(MON_AT(bhitpos.x, bhitpos.y)) { X mtmp = m_at(bhitpos.x,bhitpos.y); X X if(mtmp->data->ac + 8 + obj->spe <= rnd(20)) { X if (!vis) pline("It is missed."); X else miss(distant_name(singleobj,xname), mtmp); X if (!range) { /* Last position; object drops */ X drop_throw(singleobj, 0, mtmp->mx, mtmp->my); X break; X } X } else { X damage = dmgval(obj, mtmp->data); X if (damage < 1) damage = 1; X if (obj->otyp==ACID_VENOM && resists_acid(mtmp->data)) X damage = 0; X if (!vis) pline("It is hit%s", exclam(damage)); X else hit(distant_name(singleobj,xname), X mtmp,exclam(damage)); X if (obj->opoisoned) { X if (resists_poison(mtmp->data)) { X if (vis) X pline("The poison doesn't seem to affect %s.", X mon_nam(mtmp)); X } else { X if (rn2(30)) damage += rnd(6); X else { X if (vis) X pline("The poison was deadly..."); X damage = mtmp->mhp; X } X } X } X if (obj->otyp==SILVER_ARROW && (is_were(mtmp->data) X || is_demon(mtmp->data) X || mtmp->data->mlet == S_VAMPIRE X || (mtmp->data->mlet==S_IMP X && mtmp->data != &mons[PM_TENGU]))) { X if (vis) pline("The silver arrow sears %s's flesh!", X mon_nam(mtmp)); X else pline("Its flesh is seared!"); X damage += rnd(20); X } X if (obj->otyp==ACID_VENOM && cansee(mtmp->mx,mtmp->my)){ X if (resists_acid(mtmp->data)) { X pline("%s is unaffected.", vis ? Monnam(mtmp) X : "It"); X damage = 0; X } else if (vis) X pline("The acid burns %s!", mon_nam(mtmp)); X else pline("It is burned!"); X } X mtmp->mhp -= damage; X if(mtmp->mhp < 1) { X pline("%s is %s!", vis ? Monnam(mtmp) : "It", X (is_demon(mtmp->data) || X is_undead(mtmp->data) || !vis) ? X "destroyed" : "killed"); X mondied(mtmp); X } X X if((obj->otyp == CREAM_PIE) || X (obj->otyp == BLINDING_VENOM)) { X if (vis) X pline("%s is blinded by the %s.", X Monnam(mtmp), xname(singleobj)); X if(mtmp->msleep) mtmp->msleep = 0; X mtmp->mcansee = 0; X { X register unsigned rnd_tmp = rnd(25) + 20; X if((mtmp->mblinded + rnd_tmp) > 127) X mtmp->mblinded = 127; X else mtmp->mblinded += rnd_tmp; X } X } X drop_throw(singleobj, 1, bhitpos.x, bhitpos.y); X break; X } X } X if (bhitpos.x == u.ux && bhitpos.y == u.uy) { X if (multi) nomul(0); X X switch(obj->otyp) { X int dam; X case CREAM_PIE: X case BLINDING_VENOM: X hitu = thitu(8, 0, singleobj, xname(singleobj)); X break; X default: X dam = dmgval(obj, uasmon); X if (dam < 1) dam = 1; X hitu = thitu(8+obj->spe, dam, singleobj, X xname(singleobj)); X } X if (hitu && obj->opoisoned) X /* it's safe to call xname twice because it's the X same object both times... */ X poisoned(xname(singleobj), A_STR, xname(singleobj), 10); X if(hitu && (obj->otyp == CREAM_PIE || X obj->otyp == BLINDING_VENOM)) { X blindinc = rnd(25); X if(obj->otyp == CREAM_PIE) { X if(!Blind) pline("Yecch! You've been creamed."); X else pline("There's something sticky all over your %s.", body_part(FACE)); X } else { /* venom in the eyes */ X if(Blindfolded) /* nothing */ ; X else if(!Blind) pline("The venom blinds you."); X else Your("%s sting.", X makeplural(body_part(EYE))); X } X } X stop_occupation(); X if (hitu || !range) { X drop_throw(singleobj, hitu, u.ux, u.uy); X break; X } X } else if (!range /* reached end of path */ X /* missile hits edge of screen */ X || !isok(bhitpos.x+dx,bhitpos.y+dy) X /* missile hits the wall */ X || IS_WALL(levl[bhitpos.x+dx][bhitpos.y+dy].typ) X || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SDOOR X || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SCORR X#ifdef SINKS X /* Thrown objects "sink" */ X || IS_SINK(levl[bhitpos.x][bhitpos.y].typ) X#endif X ) { X drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); X break; X } X tmp_at(bhitpos.x, bhitpos.y); X } X tmp_at(bhitpos.x, bhitpos.y); X tmp_at(-1, -1); X /* blindfold keeps substances out of your eyes */ X if (blindinc && !Blindfolded) { X u.ucreamed += blindinc; X make_blinded(Blinded + blindinc,FALSE); X } X} X X#endif /* OVL1 */ X#ifdef OVLB X X/* Remove an item from the monster's inventory. X */ Xvoid Xm_useup(mon, obj) Xstruct monst *mon; Xstruct obj *obj; X{ X struct obj *otmp, *prev; X X if (obj->quan > 1) { X obj->quan--; X return; X } X prev = ((struct obj *) 0); X for (otmp = mon->minvent; otmp; otmp = otmp->nobj) { X if (otmp == obj) { X if (prev) X prev->nobj = obj->nobj; X else X mon->minvent = obj->nobj; X free((genericptr_t) obj); X break; X } X prev = otmp; X } X} X X#endif /* OVLB */ X#ifdef OVL1 X X/* Always returns 0??? -SAC */ Xint Xthrwmu(mtmp) /* monster throws item at you */ Xregister struct monst *mtmp; X{ X struct obj *otmp, *select_rwep(); X register xchar x, y; X X if(lined_up(mtmp)) { X X if((otmp = select_rwep(mtmp))) { X X /* If you are coming toward the monster, the monster X * should try to soften you up with missiles. If you are X * going away, you are probably hurt or running. Give X * chase, but if you are getting too far away, throw. X */ X x = mtmp->mx; X y = mtmp->my; X if(!URETREATING(x,y) || X !rn2(BOLT_LIM-movedist(x,mtmp->mux,y,mtmp->muy))) X { X unsigned savequan = otmp->quan; X const char *verb = "throws"; X X if (otmp->otyp == ARROW X#ifdef TOLKIEN X || otmp->otyp == ELVEN_ARROW X || otmp->otyp == ORCISH_ARROW X#endif X || otmp->otyp == CROSSBOW_BOLT) verb = "shoots"; X otmp->quan = 1; X if (canseemon(mtmp)) X pline("%s %s %s!", Monnam(mtmp), verb, an(xname(otmp))); X otmp->quan = savequan; X m_throw(mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), X movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy), otmp); X if (!otmp->quan) m_useup(mtmp, otmp); X nomul(0); X return 0; X } X } X } X return 0; X} X X#endif /* OVL1 */ X#ifdef OVLB X Xint Xspitmu(mtmp, mattk) /* monster spits substance at you */ Xregister struct monst *mtmp; Xregister struct attack *mattk; X{ X register struct obj *otmp; X X if(mtmp->mcan) { X X if(flags.soundok) X pline("A dry rattle comes from %s's throat", mon_nam(mtmp)); X return 0; X } X if(lined_up(mtmp)) { X switch (mattk->adtyp) { X case AD_BLND: X case AD_DRST: X otmp = mksobj(BLINDING_VENOM, FALSE); X break; X default: X impossible("bad attack type in spitmu"); X /* fall through */ X case AD_ACID: X otmp = mksobj(ACID_VENOM, FALSE); X break; X } X if(!rn2(BOLT_LIM-movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy))) { X if (canseemon(mtmp)) X pline("%s spits venom!", Monnam(mtmp)); X m_throw(mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), X movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy), otmp); X nomul(0); X return 0; X } X } X return 0; X} X X#endif /* OVLB */ X#ifdef OVL1 X Xint Xbreamu(mtmp, mattk) /* monster breathes at you (ranged) */ X register struct monst *mtmp; X register struct attack *mattk; X{ X if(lined_up(mtmp)) { X X if(mtmp->mcan) { X if(flags.soundok) { X if(canseemon(mtmp)) X pline("%s coughs.", Monnam(mtmp)); X else X You("hear a cough."); X } X return(0); X } X if(rn2(3)) { X X if((mattk->adtyp >= 1) && (mattk->adtyp < 11)) { X X if(canseemon(mtmp)) X pline("%s breathes %s!", Monnam(mtmp), X breathwep[mattk->adtyp-1]); X buzz((int) (-20 - (mattk->adtyp-1)), (int)mattk->damn, X mtmp->mx, mtmp->my, sgn(tbx), sgn(tby)); X nomul(0); X } else impossible("Breath weapon %d used", mattk->adtyp-1); X } X } X return(1); X} X Xboolean Xlinedup(ax, ay, bx, by) Xregister xchar ax, ay, bx, by; X{ X register xchar x, y; X X tbx = ax - bx; /* These two values are set for use */ X tby = ay - by; /* after successful return. */ X X if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */ X && movedist(tbx, 0, tby, 0) < BOLT_LIM) { X X /* Check if there are any dead squares between. If so, X * it will not be possible to shoot. X */ X x = bx; y = by; X while(x != ax || y != ay) { X X if(!accessible(x, y)) return FALSE; X x += sgn(tbx), y += sgn(tby); X } X return TRUE; X } X return FALSE; X} X Xboolean Xlined_up(mtmp) /* is mtmp in position to use ranged attack? */ X register struct monst *mtmp; X{ X return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my)); X} X X#endif /* OVL1 */ X#ifdef OVL0 X X/* Check if a monster is carrying a particular item. X */ Xstruct obj * Xm_carrying(mtmp, type) Xstruct monst *mtmp; Xint type; X{ X register struct obj *otmp; X X for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) X if(otmp->otyp == type) X return(otmp); X return((struct obj *) 0); X} X X#endif /* OVL0 */ X#ifdef OVL1 X XSTATIC_OVL int Xmovedist(x0, x1, y0, y1) Xint x0, x1, y0, y1; X{ X register int absdx, absdy; X X absdx = abs(x1 - x0); X absdy = abs(y1 - y0); X X return (max(absdx,absdy)); X} X X#endif /* OVL1 */ END_OF_FILE if test 12098 -ne `wc -c <'src/mthrowu.c'`; then echo shar: \"'src/mthrowu.c'\" unpacked with wrong size! fi # end of 'src/mthrowu.c' fi if test -f 'src/steal.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/steal.c'\" else echo shar: Extracting \"'src/steal.c'\" \(7653 characters\) sed "s/^X//" >'src/steal.c' <<'END_OF_FILE' X/* SCCS Id: @(#)steal.c 3.0 88/07/06 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_DCL int NDECL(stealarm); X X#ifdef OVLB Xstatic const char * FDECL(equipname, (struct obj *)); X Xstatic const char * Xequipname(otmp) X X register struct obj *otmp; X{ X X return ( X#ifdef SHIRT X (otmp == uarmu) ? "shirt" : X#endif X (otmp == uarmf) ? "boots" : X (otmp == uarms) ? "shield" : X (otmp == uarmg) ? "gloves" : X (otmp == uarmc) ? "cloak" : X (otmp == uarmh) ? "helmet" : "armor"); X} X Xlong /* actually returns something that fits in an int */ Xsomegold(){ X#ifdef LINT /* long conv. ok */ X return(0L); X#else X return (long)( (u.ugold < 100) ? u.ugold : X (u.ugold > 10000) ? rnd(10000) : rnd((int) u.ugold) ); X#endif X} X Xvoid Xstealgold(mtmp) Xregister struct monst *mtmp; X{ X register struct gold *gold = g_at(u.ux, u.uy); X register long tmp; X if(gold && ( !u.ugold || gold->amount > u.ugold || !rn2(5))) { X mtmp->mgold += gold->amount; X freegold(gold); X if(Invisible) newsym(u.ux, u.uy); X pline("%s quickly snatches some gold from between your %s!", X Blind ? "It" : Monnam(mtmp), makeplural(body_part(FOOT))); X if(!u.ugold || !rn2(5)) { X rloc(mtmp); X mtmp->mflee = 1; X } X } else if(u.ugold) { X u.ugold -= (tmp = somegold()); X Your("purse feels lighter."); X mtmp->mgold += tmp; X rloc(mtmp); X mtmp->mflee = 1; X flags.botl = 1; X } X} X X/* steal armor after he finishes taking it off */ Xunsigned int stealoid; /* object to be stolen */ Xunsigned int stealmid; /* monster doing the stealing */ X XSTATIC_OVL int Xstealarm(){ X register struct monst *mtmp; X register struct obj *otmp; X X for(otmp = invent; otmp; otmp = otmp->nobj) X if(otmp->o_id == stealoid) { X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) X if(mtmp->m_id == stealmid) { X if(otmp->unpaid) subfrombill(otmp); X freeinv(otmp); X pline("%s steals %s!", Blind ? "It" : X Monnam(mtmp), doname(otmp)); X mpickobj(mtmp,otmp); X mtmp->mflee = 1; X rloc(mtmp); X break; X } X break; X } X return stealoid = 0; X} X X/* Returns 1 when something was stolen (or at least, when N should flee now) X * Returns -1 if the monster died in the attempt X * Avoid stealing the object stealoid X */ Xint Xsteal(mtmp) Xstruct monst *mtmp; X{ X register struct obj *otmp; X register int tmp; X register int named = 0; X X /* the following is true if successful on first of two attacks. */ X if(!monnear(mtmp, u.ux, u.uy)) return(0); X X if(!invent){ X /* Not even a thousand men in armor can strip a naked man. */ X if(Blind) X pline("Somebody tries to rob you, but finds nothing to steal."); X else X pline("%s tries to rob you, but she finds nothing to steal!", X Monnam(mtmp)); X return(1); /* let her flee */ X } X X if(Adornment & LEFT_RING) { X otmp = uleft; X goto gotobj; X } else if(Adornment & RIGHT_RING) { X otmp = uright; X goto gotobj; X } X X tmp = 0; X for(otmp = invent; otmp; otmp = otmp->nobj) if(!uarm || otmp != uarmc) X tmp += ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1); X tmp = rn2(tmp); X for(otmp = invent; otmp; otmp = otmp->nobj) if(!uarm || otmp != uarmc) X if((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1)) X < 0) break; X if(!otmp) { X impossible("Steal fails!"); X return(0); X } X /* can't steal gloves while wielding - so steal the wielded item. */ X if (otmp == uarmg && uwep) X otmp = uwep; X /* can't steal armor while wearing cloak - so steal the cloak. */ X else if(otmp == uarm && uarmc) otmp = uarmc; X#ifdef SHIRT X else if(otmp == uarmu && uarmc) otmp = uarmc; X else if(otmp == uarmu && uarm) otmp = uarm; X#endif Xgotobj: X if(otmp->o_id == stealoid) return(0); X X#ifdef WALKIES X if(otmp->otyp == LEASH && otmp->leashmon) o_unleash(otmp); X#endif X X if((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))){ X switch(otmp->olet) { X case TOOL_SYM: X Blindf_off(otmp); X break; X case AMULET_SYM: X Amulet_off(); X break; X case RING_SYM: X Ring_gone(otmp); X break; X case ARMOR_SYM: X /* Stop putting on armor which has been stolen. */ X if (donning(otmp)) { X cancel_don(); X if (otmp == uarm) (void) Armor_off(); X /* else if (otmp == uarmc) (void) Cloak_off(); */ X else if (otmp == uarmf) (void) Boots_off(); X else if (otmp == uarmg) (void) Gloves_off(); X else if (otmp == uarmh) (void) Helmet_off(); X /* else if (otmp == uarms) (void) Shield_off(); */ X else setworn((struct obj *)0, otmp->owornmask & W_ARMOR); X break; X } X { int curssv = otmp->cursed; X otmp->cursed = 0; X stop_occupation(); X if(flags.female) X pline("%s charms you. You gladly %s your %s.", X Blind ? "She" : Monnam(mtmp), X curssv ? "let her take" : "hand over", X equipname(otmp)); X else X pline("%s seduces you and %s off your %s.", X Blind ? "It" : Amonnam(mtmp, "beautiful"), X curssv ? "helps you to take" : "you start taking", X equipname(otmp)); X named++; X /* the following is to set multi for later on */ X (void) nomul(-objects[otmp->otyp].oc_delay); X X if (otmp == uarm) (void) Armor_off(); X else if (otmp == uarmc) (void) Cloak_off(); X else if (otmp == uarmf) (void) Boots_off(); X else if (otmp == uarmg) (void) Gloves_off(); X else if (otmp == uarmh) (void) Helmet_off(); X else if (otmp == uarms) (void) Shield_off(); X else setworn((struct obj *)0, otmp->owornmask & W_ARMOR); X otmp->cursed = curssv; X if(multi < 0){ X /* X multi = 0; X nomovemsg = 0; X afternmv = 0; X */ X stealoid = otmp->o_id; X stealmid = mtmp->m_id; X afternmv = stealarm; X return(0); X } X break; X } X default: X impossible("Tried to steal a strange worn thing."); X } X } X else if(otmp == uwep) uwepgone(); X X if(otmp == uball) unpunish(); X X freeinv(otmp); X pline("%s stole %s.", named ? "She" : (Blind ? "It" : Monnam(mtmp)), doname(otmp)); X mpickobj(mtmp,otmp); X if (otmp->otyp == CORPSE && otmp->corpsenm == PM_COCKATRICE X && !resists_ston(mtmp->data)) { X pline("%s turns to stone.", Blind ? "It" : Monnam(mtmp)); X stoned = TRUE; X xkilled(mtmp, 0); X return -1; X } X return((multi < 0) ? 0 : 1); X} X X#endif /* OVLB */ X#ifdef OVL1 X Xvoid Xmpickobj(mtmp,otmp) Xregister struct monst *mtmp; Xregister struct obj *otmp; X{ X otmp->nobj = mtmp->minvent; X mtmp->minvent = otmp; X} X X#endif /* OVL1 */ X#ifdef OVLB X Xvoid Xstealamulet(mtmp) Xregister struct monst *mtmp; X{ X register struct obj *otmp; X X for(otmp = invent; otmp; otmp = otmp->nobj) { X if(otmp->otyp == AMULET_OF_YENDOR) { X /* might be an imitation one */ X setnotworn(otmp); X freeinv(otmp); X mpickobj(mtmp,otmp); X pline("%s stole %s!", Blind ? "It":Monnam(mtmp), doname(otmp)); X rloc(mtmp); X return; X } X } X} X X#endif /* OVLB */ X#ifdef OVL0 X X/* release the objects the killed animal has stolen */ Xvoid Xrelobj(mtmp,show) Xregister struct monst *mtmp; Xregister int show; X{ X register struct obj *otmp, *otmp2; X X for(otmp = mtmp->minvent; otmp; otmp = otmp2){ X otmp2 = otmp->nobj; X if (flooreffects(otmp,mtmp->mx,mtmp->my)) continue; X place_object(otmp, mtmp->mx, mtmp->my); X otmp->nobj = fobj; X fobj = otmp; X stackobj(fobj); X if(show & cansee(mtmp->mx,mtmp->my)) X atl(otmp->ox,otmp->oy,Hallucination?rndobjsym() : otmp->olet); X } X mtmp->minvent = (struct obj *) 0; X if(mtmp->mgold || mtmp->data->mlet == S_LEPRECHAUN) { X register long tmp; X X tmp = (mtmp->mgold > 10000) ? 10000 : mtmp->mgold; X mkgold((long)(tmp + d(dlevel,30)), mtmp->mx, mtmp->my); X if(show & cansee(mtmp->mx,mtmp->my)) X atl(mtmp->mx,mtmp->my, Hallucination ? rndobjsym() : GOLD_SYM); X } X} X X#endif /* OVL0 */ END_OF_FILE if test 7653 -ne `wc -c <'src/steal.c'`; then echo shar: \"'src/steal.c'\" unpacked with wrong size! fi # end of 'src/steal.c' fi echo shar: End of archive 44 \(of 56\). cp /dev/null ark44isdone 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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 56 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone echo Building monst.c from monst.c1 and monst.c2 cat src/monst.c1 src/monst.c2 > src/monst.c else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0