billr@saab.CNA.TEK.COM (Bill Randle) (07/25/89)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 7, Issue 83
Archive-name: NetHack3/Part28
#! /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 28 (of 38)."
# Contents: src/attrib.c src/dothrow.c src/end.c src/termcap.c
# src/worm.c
# Wrapped by billr@saab on Sun Jul 23 21:33:11 1989
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'\" \(11413 characters\)
sed "s/^X//" >'src/attrib.c' <<'END_OF_FILE'
X/*
X * attrib.c - attribute modification routines.
X *
X * Copyright 1988, M. Stephenson
X */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
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 char *gainstr, *losestr;
X} a_abil[] = { { 0, &(Stealth), "", "" },
X { 0, &(Fast), "", "" },
X { 10, &(Searching), "perceptive", "" },
X { 0, 0, 0, 0 } },
X
X b_abil[] = { { 0, &(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[] = { { 0, &(Fast), "", "" },
X { 0, &(HSee_invisible), "", "" },
X { 0, &(Searching), "", "" },
X { 0, &(HSleep_resistance), "", "" },
X { 0, 0, 0, 0 } },
X
X h_abil[] = { { 0, &(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[] = { { 0, &(Stealth), "", "" },
X { 10, &(Searching), "perceptive", "" },
X { 0, 0, 0, 0 } },
X
X s_abil[] = { { 0, &(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[] = { { 0, &(HCold_resistance), "", "" },
X { 0, &(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 (i.e. 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 struct innate *abil;
X} a_attr = { { 6, 9, 9, 6, 6, 6 }, /* Archeologist */
X { 20, 20, 20, 10, 20, 10 },
X 10, 1, 13, 10, 14, 2, a_abil },
X
X b_attr = { { 15, 6, 6, 14, 15, 5 }, /* Barbarian */
X { 30, 6, 7, 20, 30, 7 },
X 10, -1, 16, 12, 10, 3, b_abil },
X
X c_attr = { { 9, 6, 6, 6, 7, 5 }, /* 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 = { { 12, 12, 12, 8, 12, 6 }, /* Elf (ranger) */
X { 30, 10, 10, 20, 20, 10 },
X 10, 1, 15, 10, 11, 2, e_abil },
X
X h_attr = { { 6, 6, 12, 6, 10, 15 }, /* Healer (druid) */
X { 15, 20, 20, 15, 25, 10 },
X 10, 1, 13, 10, 20, 2, h_abil },
X
X k_attr = { { 12, 6, 13, 6, 9, 17 }, /* Knight (paladin) */
X { 20, 15, 15, 10, 20, 10 },
X 10, 1, 16, 10, 10, 3, k_abil },
X
X p_attr = { { 6, 6, 9, 6, 6, 6 }, /* Priest (cleric) */
X { 15, 10, 30, 15, 20, 10 },
X 0, 0, 14, 10, 10, 2, p_abil },
X
X r_attr = { { 6, 6, 6, 9, 6, 5 }, /* Rogue (thief) */
X { 20, 10, 10, 30, 20, 10 },
X 10, -1, 12, 10, 11, 2, r_abil },
X
X s_attr = { { 9, 6, 6, 9, 17, 5 }, /* Samurai (fighter/thief) */
X { 30, 10, 10, 30, 14, 10 },
X 10, 1, 15, 10, 11, 2, s_abil },
X
X t_attr = { { 6, 9, 5, 6, 6, 9 }, /* Tourist */
X { 15, 10, 10, 15, 30, 20 },
X 0, 0, 10, 10, 14, 1, t_abil },
X
X v_attr = { { 9, 6, 6, 6, 9, 6 }, /* Valkyrie (fighter) */
X { 30, 6, 7, 20, 30, 7 },
X 0, -1, 16, 10, 10, 3, v_abil },
X
X w_attr = { { 6, 9, 6, 6, 6, 6 }, /* 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
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 -= 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
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
Xstatic struct clattr *
Xclx() {
X
X register 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 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 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
X#ifdef POLYSELF
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#endif
X
Xvoid
Xadjabil(flag)
X
X int flag; /* +ve/-ve = gain/lose */
X{
X register struct clattr *attr = clx();
X register struct innate *abil = attr->abil;
X
X if(abil) {
X
X for(; abil->ability; abil++) {
X if ((flag>0 && u.ulevel >= abil->ulevel) ||
X (flag<0 && u.ulevel < abil->ulevel)) {
X if(flag > 0) {
X if(!(*(abil->ability) & INTRINSIC)) {
X *(abil->ability) |= INTRINSIC;
X if(strlen(abil->gainstr))
X You("feel %s!", abil->gainstr);
X }
X } else {
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}
X
Xint
Xnewhp() {
X register 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
Xschar
Xacurr(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/* 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}
END_OF_FILE
if test 11413 -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'\" \(11169 characters\)
sed "s/^X//" >'src/dothrow.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)dothrow.c 3.0 88/10/22
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 gem_accept P((struct monst *, struct obj *));
Xstatic int throw_gold P((struct obj *));
Xstatic const char 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 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(obj->otyp == PICK_AXE && 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 tmp_at(-3, (int)AT_OBJ);
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->ox = bhitpos.x;
X obj->oy = bhitpos.y;
X obj->nobj = fobj;
X fobj = obj;
X levl[bhitpos.x][bhitpos.y].omask = 1;
X if(obj->unpaid && costly_spot(bhitpos.x, bhitpos.y))
X subfrombill(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, "thrown ball");
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->mfroz) {
X tmp += 4;
X if(!rn2(10)) mon->mfroz = 0;
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 else {
X kludge("%s catches the %s.", Monnam(mon), xname(obj));
X gem_accept(mon, obj);
X }
X return(1);
X }
X if(obj->olet == WEAPON_SYM || obj->otyp == ROCK || obj->olet == GEM_SYM) {
X if(obj->otyp < DART || obj->otyp == ROCK || 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 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 &&
X (mon->data->mlet == S_DOG || mon->data->mlet == S_FELINE))
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 nogood[] = " is not interested in your junk.";
X static const char maybeluck[] = " hesitatingly accepts your gift.";
X static const char 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_GREY_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 pline("The gold disappears in the %s's entrails.",
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 11169 -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/end.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/end.c'\"
else
echo shar: Extracting \"'src/end.c'\" \(11591 characters\)
sed "s/^X//" >'src/end.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)end.c 3.0 88/05/03
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#ifndef TOS
X#include <signal.h>
X#endif
X
X/* block some unused #defines to avoid overloading some cpp's */
X#define MONATTK_H
X#include "hack.h"
X
X#include "eshk.h"
X
Xvoid end_box_display();
X
Xint
Xdone1()
X{
X#ifndef TOS
X (void) signal(SIGINT,SIG_IGN);
X#endif
X if(flags.ignintr) {
X#ifndef TOS
X (void) signal(SIGINT, (SIG_RET_TYPE) done1);
X#endif
X clrlin();
X curs_on_u();
X (void) fflush(stdout);
X if(multi > 0) nomul(0);
X return 0;
X }
X return done2();
X}
X
Xint
Xdone2()
X{
X pline("Really quit? ");
X if(yn() == 'n') {
X#ifndef TOS
X (void) signal(SIGINT, (SIG_RET_TYPE) done1);
X#endif
X clrlin();
X curs_on_u();
X (void) fflush(stdout);
X if(multi > 0) nomul(0);
X return 0;
X }
X#if defined(WIZARD) && defined(UNIX)
X if(wizard) {
X pline("Dump core? ");
X if(yn() == 'y') {
X (void) signal(SIGINT, (SIG_RET_TYPE) done1);
X settty(NULL);
X#ifdef SYSV
X (void)
X#endif
X abort();
X }
X }
X#endif
X#ifndef LINT
X done("quit");
X#endif
X return 0;
X}
X
Xstatic
Xint
Xdone_intr(){
X done_stopprint++;
X#ifndef TOS
X (void) signal(SIGINT, SIG_IGN);
X#ifdef UNIX
X (void) signal(SIGQUIT, SIG_IGN);
X#endif
X#endif /* TOS /* */
X return 0;
X}
X
X#ifdef UNIX
Xstatic
Xint
Xdone_hangup(){
X done_hup++;
X (void)signal(SIGHUP, SIG_IGN);
X (void)done_intr();
X return 0;
X}
X#endif
X
Xvoid
Xdone_in_by(mtmp)
Xregister struct monst *mtmp;
X{
X char buf[BUFSZ];
X
X You("die...");
X buf[0] = '\0';
X if (mtmp->minvis)
X Sprintf(eos(buf), "invisible ");
X if (Hallucination)
X Sprintf(eos(buf), "hallucinogen-distorted ");
X
X if(mtmp->data->mlet == S_GHOST) {
X register char *gn = (char *) mtmp->mextra;
X if (!Hallucination && !mtmp->minvis && *gn)
X Sprintf(eos(buf), "the ");
X Sprintf(eos(buf), (*gn ? "ghost of %s" : "ghost%s"), gn);
X } else if(mtmp->isshk) {
X Sprintf(eos(buf), "%s %s, the shopkeeper",
X (ESHK(mtmp)->ismale ? "Mr." : "Ms."), shkname(mtmp));
X } else if (mtmp->iswiz)
X Sprintf(eos(buf), "the %s", mons[PM_WIZARD_OF_YENDOR].mname);
X else Sprintf(eos(buf), "%s", mtmp->data->mname);
X if (mtmp->mnamelth) Sprintf(eos(buf), " called %s", NAME(mtmp));
X killer = buf;
X if (mtmp->data->mlet == S_WRAITH)
X u.ugrave_arise = PM_WRAITH;
X else if (mtmp->data->mlet == S_MUMMY)
X u.ugrave_arise = (pl_character[0]=='E') ?
X PM_ELF_MUMMY : PM_HUMAN_MUMMY;
X else if (mtmp->data->mlet == S_VAMPIRE)
X u.ugrave_arise = PM_VAMPIRE;
X if (u.ugrave_arise > -1 && (mons[u.ugrave_arise].geno & G_GENOD))
X u.ugrave_arise = -1;
X if (mtmp->data->mlet == S_COCKATRICE)
X done("stoned");
X else
X done("died");
X return;
X}
X
X/*VARARGS1*/
Xboolean panicking;
Xextern boolean hu; /* from save.c */
X
Xvoid
Xpanic(str,a1,a2,a3,a4,a5,a6)
Xchar *str;
X{
X if(panicking++)
X#ifdef SYSV
X (void)
X#endif
X abort(); /* avoid loops - this should never happen*/
X /* was exit(1) */
X home(); cls();
X (void) puts(" Suddenly, the dungeon collapses.");
X#ifdef WIZARD
X# ifndef MSDOS
X if(!wizard) {
X pline("Report error to %s and it may be possible to rebuild.",WIZARD);
X more();
X }
X Sprintf (SAVEF, "%s.e", SAVEF);
X hu = FALSE;
X (void) dosave0();
X# endif
X#endif
X (void) fputs(" ERROR: ", stdout);
X Printf(str,a1,a2,a3,a4,a5,a6);
X more(); /* contains a fflush() */
X#ifdef WIZARD
X# ifdef UNIX
X if (wizard)
X# ifdef SYSV
X (void)
X# endif
X abort(); /* generate core dump */
X# endif
X#endif
X done("panicked");
X}
X
X/* called with arg "died", "drowned", "escaped", "quit", "choked", "panicked",
X "burned", "starved", "stoned", or "tricked" */
X/* Be careful not to call panic from here! */
Xvoid
Xdone(st1)
Xregister char *st1;
X{
X struct permonst *upmon;
X char buf[BUFSZ], buf1[BUFSZ], buf2[BUFSZ];
X char c;
X boolean taken;
X#ifdef WIZARD
X if (wizard && *st1=='t') {
X You("are a very tricky wizard, it seems.");
X return;
X }
X#endif
X if(Lifesaved && index("bcds", *st1)){
X u.uswldtim = 0;
X if(u.uhpmax < 0) u.uhpmax = 10; /* arbitrary */
X u.uhp = u.uhpmax;
X adjattrib(A_CON, -1, TRUE);
X pline("But wait...");
X makeknown(AMULET_OF_LIFE_SAVING);
X Your("medallion %s!",
X !Blind ? "begins to glow" : "feels warm");
X You("feel much better!");
X pline("The medallion crumbles to dust!");
X useup(uamul);
X Lifesaved = 0;
X if (u.uhunger < 500) u.uhunger = 500;
X nomovemsg = "You survived that attempt on your life.";
X curs_on_u();
X flags.move = 0;
X if(multi > 0) multi = 0; else multi = -1;
X flags.botl = 1;
X u.ugrave_arise = -1;
X if (!strncmp(killer, "genocide", 8)) {
X pline("Unfortunately you are still genocided...");
X done("died");
X }
X return;
X }
X#if defined(WIZARD) || defined(EXPLORE_MODE)
X if((wizard || discover) && index("bcds", *st1)){
X pline("Die? ");
X if(yn() == 'y') goto die;
X u.uswldtim = 0;
X if(u.uhpmax < 0) u.uhpmax = 100; /* arbitrary */
X u.uhp = u.uhpmax;
X if (u.uhunger < 500) u.uhunger = 500;
X pline("Ok, so you don't die.");
X nomovemsg = "You survived that attempt on your life.";
X curs_on_u();
X flags.move = 0;
X if(multi > 0) multi = 0; else multi = -1;
X flags.botl = 1;
X u.ugrave_arise = -1;
X return;
X }
X#endif /* WIZARD || EXPLORE_MODE */
Xdie:
X#ifndef TOS
X (void) signal(SIGINT, (SIG_RET_TYPE) done_intr);
X#ifdef UNIX
X (void) signal(SIGQUIT, (SIG_RET_TYPE) done_intr);
X (void) signal(SIGHUP, (SIG_RET_TYPE) done_hangup);
X#endif
X#endif /* TOS /* */
X upmon = player_mon();
X if(u.ugrave_arise > -1) /* create no corpse */ ;
X else if(*st1 == 's' && st1[2] == 'o')
X (mk_named_object(STATUE, upmon, u.ux, u.uy, plname,
X strlen(plname)))->spe = 0;
X else
X (void) mk_named_object(CORPSE, upmon, u.ux, u.uy, plname,
X strlen(plname));
X if(*st1 == 'q' && u.uhp < 1){
X st1 = "died";
X killer = "quit while already on Charon's boat";
X }
X if(*st1 == 's' && st1[2] == 'a') killer = "starvation"; else
X if(*st1 == 'd' && st1[1] == 'r') killer = "drowning"; else
X if(*st1 == 'p') killer = "panic"; else
X if(*st1 == 't') killer = "trickery"; else
X if(!index("bcds", *st1)) killer = st1;
X taken = paybill();
X paygd();
X clearlocks();
X if(flags.toplin == 1) more();
X
X if(invent) {
X if(taken)
X pline("Do you want to see what you had when you %s? ",
X (*st1=='q') ? "quit" : "died");
X else
X pline("Do you want your possessions identified? ");
X /* New dump format by maartenj@cs.vu.nl */
X if ((c = yn_function(ynqchars,'y')) == 'y') {
X struct obj *obj;
X
X for(obj = invent; obj && !done_stopprint; obj = obj->nobj) {
X makeknown(obj->otyp);
X obj->known = obj->bknown = obj->dknown = 1;
X }
X doinv(NULL);
X end_box_display();
X }
X if (c == 'q') done_stopprint++;
X if (taken) {
X /* paybill has already given the inventory locations in the shop
X * and put it on the main object list
X */
X struct obj *obj;
X
X for(obj = invent; obj; obj = obj->nobj) {
X obj->owornmask = 0;
X if(rn2(5)) curse(obj);
X }
X invent = (struct obj *) 0;
X }
X }
X
X if(index("bcds", *st1)){
X#ifdef WIZARD
X if(wizard) {
X pline("Save bones? ");
X if(yn() == 'y') savebones();
X } else
X#endif
X savebones();
X if(!flags.notombstone) outrip();
X }
X if(*st1 == 'c') killer = st1; /* after outrip() */
X if(*st1 == 's' && st1[2] == 'o') {
X Sprintf(buf, "turned to stone by %s",killer);
X /* No a or an; topten.c will do that. */
X killer = buf;
X st1 = "turned to stone";
X }
X Strcpy(buf1, st1);
X if(u.uhave_amulet) Strcat(killer," (with the Amulet)");
X settty(NULL); /* does a clear_screen() */
X Strcpy(buf2, plname);
X if('a' <= buf2[0] && buf2[0] <= 'z') buf2[0] += 'A'-'a';
X if(!done_stopprint)
X Printf("Goodbye %s the %s...\n\n", buf2,
X#ifdef ENDGAME
X *st1 != 'a' ? pl_character : "Demigod");
X#else
X pl_character);
X#endif
X { long int tmp;
X tmp = u.ugold - u.ugold0;
X if(tmp < 0)
X tmp = 0;
X if(*st1 == 'd' || *st1 == 'b')
X tmp -= tmp/10;
X u.urexp += tmp;
X u.urexp += 50 * maxdlevel;
X if(maxdlevel > 20)
X u.urexp += 1000*((maxdlevel > 30) ? 10 : maxdlevel - 20);
X#ifdef ENDGAME
X if(*st1 == 'a') u.urexp *= 2;
X#endif
X }
X if(*st1 == 'e') {
X register struct monst *mtmp;
X register struct obj *otmp;
X long i;
X register unsigned int worthlessct = 0;
X
X killer = st1;
X keepdogs();
X mtmp = mydogs;
X if(mtmp) {
X if(!done_stopprint) Printf("You");
X while(mtmp) {
X if(!done_stopprint)
X Printf(" and %s", mon_nam(mtmp));
X if(mtmp->mtame)
X u.urexp += mtmp->mhp;
X mtmp = mtmp->nmon;
X }
X if(!done_stopprint)
X Printf("\nescaped from the dungeon with %ld points,\n",
X u.urexp);
X } else
X if(!done_stopprint)
X Printf("You escaped from the dungeon with %ld points,\n",
X u.urexp);
X get_all_from_box(); /* don't forget things in boxes and bags */
X for(otmp = invent; otmp; otmp = otmp->nobj) {
X if(otmp->olet == GEM_SYM && otmp->otyp < LUCKSTONE) {
X makeknown(otmp->otyp);
X i = (long) otmp->quan *
X objects[otmp->otyp].g_val;
X if(i == 0) {
X worthlessct += otmp->quan;
X continue;
X }
X u.urexp += i;
X Printf(" %s (worth %ld Zorkmids),\n",
X doname(otmp), i);
X } else if(otmp->olet == AMULET_SYM) {
X otmp->known = 1;
X i = (otmp->spe < 0) ? 2 :
X otmp->otyp == AMULET_OF_YENDOR ?
X 5000 : 500;
X u.urexp += i;
X Printf(" %s (worth %ld Zorkmids),\n",
X doname(otmp), i);
X }
X }
X if(worthlessct)
X Printf(" %u worthless piece%s of colored glass,\n",
X worthlessct, plur((long)worthlessct));
X if(u.uhave_amulet) killer = "escaped (with Amulet)";
X else killer = "escaped";
X } else
X if(!done_stopprint) {
X Printf("You %s ",
X !strcmp(st1, "tricked") ? "were tricked" : st1);
X#ifdef ENDGAME
X if (*st1 != 'a') {
X if(dlevel == ENDLEVEL)
X Printf("in the endgame ");
X else Printf("on dungeon level %d ", dlevel);
X }
X#else
X Printf("on dungeon level %d ", dlevel);
X#endif
X Printf("with %ld points,\n", u.urexp);
X }
X if(!done_stopprint)
X Printf("and %ld piece%s of gold, after %ld move%s.\n",
X u.ugold, plur(u.ugold), moves, plur(moves));
X if(!done_stopprint)
X Printf("You were level %u with a maximum of %d hit points when you %s.\n",
X u.ulevel, u.uhpmax, buf1);
X if(*st1 == 'e' && !done_stopprint){
X getret(); /* all those pieces of coloured glass ... */
X cls();
X }
X#if defined(WIZARD) || defined(EXPLORE_MODE)
X if(wizard || discover)
X Printf("\nSince you were in %s mode, the score list \
Xwill not be checked.\n", wizard ? "wizard" : "discover");
X else
X#endif
X topten();
X/* "So when I die, the first thing I will see in Heaven is a score list?" */
X if(done_stopprint) Printf("\n\n");
X#ifdef APOLLO
X getret();
X#endif
X exit(0);
X}
X
Xvoid
Xclearlocks(){
X#if defined(DGK) && !defined(TOS)
X eraseall(levels, alllevels);
X if (ramdisk)
X eraseall(permbones, alllevels);
X#else
X#if defined(UNIX) || (defined(MSDOS) && !defined(TOS))
X register int x;
X#ifdef UNIX
X (void) signal(SIGHUP,SIG_IGN);
X#endif
X for(x = maxdlevel; x >= 0; x--) {
X glo(x);
X (void) unlink(lock); /* not all levels need be present */
X }
X#endif
X#endif
X}
X
X#ifdef NOSAVEONHANGUP
Xint
Xhangup()
X{
X (void) signal(SIGINT, SIG_IGN);
X clearlocks();
X exit(1);
X}
X#endif
X
Xvoid
Xend_box_display()
X{
X register struct obj *box, *obj;
X char buf[BUFSZ];
X
X for(box=invent; box; box=box->nobj) {
X if (Is_container(box) && box->otyp != BAG_OF_TRICKS) {
X int cnt=0;
X
X for(obj=fcobj; obj; obj=obj->nobj) {
X if (obj->cobj == box) {
X if (!cnt) {
X Sprintf(buf, "Contents of the %s:",xname(box));
X cornline(0, buf);
X }
X makeknown(obj->otyp);
X obj->known = obj->bknown = obj->dknown = 1;
X cornline(1,doname(obj));
X cnt++;
X }
X }
X if (!cnt) pline("The %s is empty.", xname(box));
X else cornline(2,"");
X }
X }
X}
END_OF_FILE
if test 11591 -ne `wc -c <'src/end.c'`; then
echo shar: \"'src/end.c'\" unpacked with wrong size!
fi
# end of 'src/end.c'
fi
if test -f 'src/termcap.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/termcap.c'\"
else
echo shar: Extracting \"'src/termcap.c'\" \(11334 characters\)
sed "s/^X//" >'src/termcap.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)termcap.c 3.0 88/11/20
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include <ctype.h> /* for isdigit() */
X
X/* block some unused #defines to avoid overloading some cpp's */
X#define MONATTK_H
X#include "hack.h" /* for ROWNO, COLNO, *HI, *HE, *AS, *AE */
X
X#if !defined(SYSV) || defined(TOS) || defined(UNIXPC)
X# ifndef LINT
Xextern /* it is defined in libtermlib (libtermcap) */
X# endif
X short ospeed; /* terminal baudrate; used by tputs */
X#else
Xshort ospeed = 0; /* gets around "not defined" error message */
X#endif
X
Xstatic void nocmov();
X#ifdef MSDOSCOLOR
Xstatic void init_hilite();
X#endif /* MSDOSCOLOR */
X
Xstatic char tbuf[512];
Xstatic char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE;
Xstatic char *VS, *VE, *US, *UE;
Xstatic char *MR, *ME;
X#if 0
Xstatic char *MB, *MD, *MH;
X#endif
Xstatic int SG;
Xstatic char PC = '\0';
X
X#if defined(MSDOS) && !defined(TERMLIB)
Xstatic char tgotobuf[20];
X#ifdef TOS
X#define tgoto(fmt, x, y) (Sprintf(tgotobuf, fmt, y+' ', x+' '), tgotobuf)
X#else
X#define tgoto(fmt, x, y) (Sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf)
X#endif
X#endif /* MSDOS /**/
X
Xvoid
Xstartup()
X{
X#ifdef TOS
X HO = "\033H";
X CL = "\033E"; /* the VT52 termcap */
X CE = "\033K";
X UP = "\033A";
X CM = "\033Y%c%c"; /* used with function tgoto() */
X ND = "\033C";
X XD = "\033B";
X BC = "\033D";
X SO = "\033p";
X SE = "\033q";
X HI = "\033p";
X HE = "\033q";
X#else
X register char *term;
X register char *tptr;
X char *tbufptr, *pc;
X register int i;
X
X tptr = (char *) alloc(1024);
X
X tbufptr = tbuf;
X if(!(term = getenv("TERM")))
X# ifdef ANSI_DEFAULT
X {
X HO = "\033[H";
X CL = "\033[2J"; /* the ANSI termcap */
X/* CD = "\033[J"; */
X CE = "\033[K";
X CM = "\033[%i%d;%dH";
X UP = "\033[A";
X ND = "\033[C";
X XD = "\033[B";
X BC = "\033[D";
X HI = SO = "\033[1m";
X US = "\033[4m";
X TI = HE = SE = UE = "\033[0m";
X /* strictly, SE should be 2, and UE should be 24,
X but we can't trust all ANSI emulators to be
X that complete. -3. */
X AS = "\016";
X AE = "\017";
X VS = VE = "";
X } else {
X# else
X error("Can't get TERM.");
X# endif
X if(!strncmp(term, "5620", 4))
X flags.nonull = 1; /* this should be a termcap flag */
X if(tgetent(tptr, term) < 1)
X error("Unknown terminal type: %s.", term);
X if(pc = tgetstr("pc", &tbufptr))
X PC = *pc;
X#ifdef TERMINFO
X if(!(BC = tgetstr("le", &tbufptr))) {
X#else
X if(!(BC = tgetstr("bc", &tbufptr))) {
X#endif
X#if !defined(MINIMAL_TERM) && !defined(HISX)
X if(!tgetflag("bs"))
X error("Terminal must backspace.");
X#endif
X BC = tbufptr;
X tbufptr += 2;
X *BC = '\b';
X }
X#ifdef MINIMAL_TERM
X HO = NULL;
X#else
X HO = tgetstr("ho", &tbufptr);
X#endif
X CO = tgetnum("co");
X LI = tgetnum("li");
X if(CO < COLNO || LI < ROWNO+2)
X setclipped();
X if(!(CL = tgetstr("cl", &tbufptr)))
X error("Hack needs CL.");
X ND = tgetstr("nd", &tbufptr);
X if(tgetflag("os"))
X error("Hack can't have OS.");
X CE = tgetstr("ce", &tbufptr);
X UP = tgetstr("up", &tbufptr);
X /* It seems that xd is no longer supported, and we should use
X a linefeed instead; unfortunately this requires resetting
X CRMOD, and many output routines will have to be modified
X slightly. Let's leave that till the next release. */
X XD = tgetstr("xd", &tbufptr);
X/* not: XD = tgetstr("do", &tbufptr); */
X if(!(CM = tgetstr("cm", &tbufptr))) {
X if(!UP && !HO)
X error("Hack needs CM or UP or HO.");
X Printf("Playing hack on terminals without cm is suspect...\n");
X getret();
X }
X SO = tgetstr("so", &tbufptr);
X SE = tgetstr("se", &tbufptr);
X US = tgetstr("us", &tbufptr);
X UE = tgetstr("ue", &tbufptr);
X SG = tgetnum("sg"); /* -1: not fnd; else # of spaces left by so */
X if(!SO || !SE || (SG > 0)) SO = SE = US = UE = "";
X TI = tgetstr("ti", &tbufptr);
X TE = tgetstr("te", &tbufptr);
X VS = VE = "";
X#if 0
X MB = tgetstr("mb", &tbufptr); /* blink */
X MD = tgetstr("md", &tbufptr); /* boldface */
X MH = tgetstr("mh", &tbufptr); /* dim */
X#endif
X MR = tgetstr("mr", &tbufptr); /* reverse */
X ME = tgetstr("me", &tbufptr);
X
X /* Get rid of padding numbers for HI and HE. Hope they
X * aren't really needed!!! HI and HE are ouputted to the
X * pager as a string - so how can you send it NULLS???
X * -jsb
X */
X HI = (char *) alloc((unsigned)(strlen(SO)+1));
X HE = (char *) alloc((unsigned)(strlen(SE)+1));
X i = 0;
X while(isdigit(SO[i])) i++;
X Strcpy(HI, &SO[i]);
X i = 0;
X while(isdigit(SE[i])) i++;
X Strcpy(HE, &SE[i]);
X AS = tgetstr("as", &tbufptr);
X AE = tgetstr("ae", &tbufptr);
X CD = tgetstr("cd", &tbufptr);
X# ifdef ANSI_DEFAULT
X }
X# endif
X set_whole_screen(); /* uses LI and CD */
X if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n");
X free((genericptr_t)tptr);
X#ifdef MSDOSCOLOR
X init_hilite();
X#endif
X#endif /* TOS /* */
X}
X
Xvoid
Xstart_screen()
X{
X xputs(TI);
X xputs(VS);
X#ifdef DECRAINBOW
X /* Select normal ASCII and line drawing character sets.
X */
X if (flags.DECRainbow) {
X xputs("\033(B\033)0");
X if (!AS) {
X AS = "\016";
X AE = "\017";
X }
X }
X#endif /* DECRAINBOW */
X}
X
Xvoid
Xend_screen()
X{
X clear_screen();
X xputs(VE);
X xputs(TE);
X}
X
X/* Cursor movements */
X
Xvoid
Xcurs(x, y)
Xregister int x, y; /* not xchar: perhaps xchar is unsigned and
X curx-x would be unsigned as well */
X{
X
X if (y == cury && x == curx)
X return;
X if(!ND && (curx != x || x <= 3)) { /* Extremely primitive */
X cmov(x, y); /* bunker!wtm */
X return;
X }
X if(abs(cury-y) <= 3 && abs(curx-x) <= 3)
X nocmov(x, y);
X else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) {
X (void) putchar('\r');
X curx = 1;
X nocmov(x, y);
X } else if(!CM) {
X nocmov(x, y);
X } else
X cmov(x, y);
X}
X
Xstatic void
Xnocmov(x, y)
X{
X if (cury > y) {
X if(UP) {
X while (cury > y) { /* Go up. */
X xputs(UP);
X cury--;
X }
X } else if(CM) {
X cmov(x, y);
X } else if(HO) {
X home();
X curs(x, y);
X } /* else impossible("..."); */
X } else if (cury < y) {
X if(XD) {
X while(cury < y) {
X xputs(XD);
X cury++;
X }
X } else if(CM) {
X cmov(x, y);
X } else {
X while(cury < y) {
X xputc('\n');
X curx = 1;
X cury++;
X }
X }
X }
X if (curx < x) { /* Go to the right. */
X if(!ND) cmov(x, y); else /* bah */
X /* should instead print what is there already */
X while (curx < x) {
X xputs(ND);
X curx++;
X }
X } else if (curx > x) {
X while (curx > x) { /* Go to the left. */
X xputs(BC);
X curx--;
X }
X }
X}
X
Xvoid
Xcmov(x, y)
Xregister int x, y;
X{
X xputs(tgoto(CM, x-1, y-1));
X cury = y;
X curx = x;
X}
X
Xvoid
Xxputc(c)
Xchar c;
X{
X (void) fputc(c, stdout);
X}
X
Xvoid
Xxputs(s)
Xchar *s;
X{
X#if defined(MSDOS) && !defined(TERMLIB)
X (void) fputs(s, stdout);
X#else
X# ifdef __STDC__
X tputs(s, 1, (int (*)())xputc);
X# else
X tputs(s, 1, xputc);
X# endif
X#endif
X}
X
Xvoid
Xcl_end() {
X if(CE)
X xputs(CE);
X else { /* no-CE fix - free after Harold Rynes */
X /* this looks terrible, especially on a slow terminal
X but is better than nothing */
X register int cx = curx, cy = cury;
X
X while(curx < COLNO) {
X xputc(' ');
X curx++;
X }
X curs(cx, cy);
X }
X}
X
Xvoid
Xclear_screen() {
X xputs(CL);
X home();
X}
X
Xvoid
Xhome()
X{
X if(HO)
X xputs(HO);
X else if(CM)
X xputs(tgoto(CM, 0, 0));
X else
X curs(1, 1); /* using UP ... */
X curx = cury = 1;
X}
X
Xvoid
Xstandoutbeg()
X{
X if(SO) xputs(SO);
X}
X
Xvoid
Xstandoutend()
X{
X if(SE) xputs(SE);
X}
X
Xvoid
Xrevbeg()
X{
X if(MR) xputs(MR);
X}
X
X#if 0 /* if you need one of these, uncomment it (here and in extern.h) */
Xvoid
Xboldbeg()
X{
X if(MD) xputs(MD);
X}
X
Xvoid
Xblinkbeg()
X{
X if(MB) xputs(MB);
X}
X
Xvoid
Xdimbeg()
X/* not in most termcap entries */
X{
X if(MH) xputs(MH);
X}
X#endif
X
Xvoid
Xm_end()
X{
X if(ME) xputs(ME);
X}
X
Xvoid
Xbacksp()
X{
X xputs(BC);
X}
X
Xvoid
Xbell()
X{
X if (flags.silent) return;
X (void) putchar('\007'); /* curx does not change */
X (void) fflush(stdout);
X}
X
Xvoid
Xgraph_on() {
X if (AS) xputs(AS);
X}
X
Xvoid
Xgraph_off() {
X if (AE) xputs(AE);
X}
X
X#ifndef MSDOS
Xstatic const short tmspc10[] = { /* from termcap */
X 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
X};
X#endif
X
Xvoid
Xdelay_output() {
X /* delay 50 ms - could also use a 'nap'-system call */
X /* BUG: if the padding character is visible, as it is on the 5620
X then this looks terrible. */
X#ifdef MSDOS
X /* simulate the delay with "cursor here" */
X register int i;
X for (i = 0; i < 3; i++) {
X cmov(curx, cury);
X (void) fflush(stdout);
X }
X#else /* MSDOS /**/
X if(!flags.nonull)
X#ifdef TERMINFO
X /* cbosgd!cbcephus!pds for SYS V R2 */
X# ifdef __STDC__
X tputs("$<50>", 1, (int (*)())xputc);
X# else
X tputs("$<50>", 1, xputc);
X# endif
X#else
X tputs("50", 1, xputs);
X#endif
X
X else if(ospeed > 0 || ospeed < SIZE(tmspc10)) if(CM) {
X /* delay by sending cm(here) an appropriate number of times */
X register int cmlen = strlen(tgoto(CM, curx-1, cury-1));
X register int i = 500 + tmspc10[ospeed]/2;
X
X while(i > 0) {
X cmov(curx, cury);
X i -= cmlen*tmspc10[ospeed];
X }
X }
X#endif /* MSDOS /**/
X}
X
Xvoid
Xcl_eos() /* free after Robert Viduya */
X{ /* must only be called with curx = 1 */
X
X if(CD)
X xputs(CD);
X else {
X register int cx = curx, cy = cury;
X while(cury <= LI-2) {
X cl_end();
X xputc('\n');
X curx = 1;
X cury++;
X }
X cl_end();
X curs(cx, cy);
X }
X}
X
X#ifdef MSDOSCOLOR
X/* Sets up highlighting, using ANSI escape sequences, for monsters,
X * objects, and gold (highlight code found in pri.c).
X * The termcap entry for HI (from SO) is scanned to find the background
X * color. If everything is OK, monsters are displayed in the color
X * used to define HILITE_MONSTER, objects are displayed in the color
X * used to define HILITE_OBJECT, and gold is displayed in the color
X * used to define HILITE_GOLD. -3. */
X
X#define ESC 0x1b
X#define NONE 0
X#define HIGH_INTENSITY 1
X#define BLACK 0
X#define RED 1
X#define GREEN 2
X#define YELLOW 3
X#define BLUE 4
X#define MAGENTA 5
X#define CYAN 6
X#define WHITE 7
X
X#define HILITE_ATTRIB HIGH_INTENSITY
X
Xstatic void
Xinit_hilite()
X{
X int backg = BLACK, foreg = WHITE, len;
X register int c, color;
X
X HI_RED = HI_YELLOW = HI_GREEN = HI_BLUE = HI_WHITE = HI;
X
X /* find the background color, HI[len] == 'm' */
X len = strlen(HI) - 1;
X
X if (HI[len] != 'm' || len < 3) return;
X
X c = 2;
X while (c < len) {
X if ((color = atoi(&HI[c])) == 0) {
X /* this also catches errors */
X foreg = WHITE; backg = BLACK;
X } else if (color >= 30 && color <= 37) {
X foreg = color - 30;
X } else if (color >= 40 && color <= 47) {
X backg = color - 40;
X }
X while (isdigit(HI[++c]));
X c++;
X }
X
X /* avoid invisibility */
X if (foreg != RED && backg != RED) {
X HI_RED = (char *) alloc(sizeof("E[0;33;44;54m"));
X Sprintf(HI_RED, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,
X RED, backg);
X }
X
X if (foreg != YELLOW && backg != YELLOW) {
X HI_YELLOW = (char *) alloc(sizeof("E[0;33;44;54m"));
X Sprintf(HI_YELLOW, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,
X YELLOW, backg);
X }
X
X if (foreg != GREEN && backg != GREEN) {
X HI_GREEN = (char *) alloc(sizeof("E[0;33;44;54m"));
X Sprintf(HI_GREEN, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,
X GREEN, backg);
X }
X
X if (foreg != BLUE && backg != BLUE) {
X HI_BLUE = (char *) alloc(sizeof("E[0;33;44;54m"));
X Sprintf(HI_BLUE, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,
X BLUE, backg);
X }
X
X if (foreg != WHITE && backg != WHITE) {
X HI_WHITE = (char *) alloc(sizeof("E[0;33;44;54m"));
X Sprintf(HI_WHITE, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,
X WHITE, backg);
X }
X}
X
X#endif
END_OF_FILE
if test 11334 -ne `wc -c <'src/termcap.c'`; then
echo shar: \"'src/termcap.c'\" unpacked with wrong size!
fi
# end of 'src/termcap.c'
fi
if test -f 'src/worm.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/worm.c'\"
else
echo shar: Extracting \"'src/worm.c'\" \(4990 characters\)
sed "s/^X//" >'src/worm.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)worm.c 3.0 88/11/11
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
X#ifdef WORM
X#include "wseg.h"
X
Xstruct wseg *wsegs[32] = DUMMY, *wheads[32] = DUMMY, *m_atseg = 0;
Xlong wgrowtime[32] = DUMMY;
X
Xint
Xgetwn(mtmp)
Xstruct monst *mtmp;
X{
X register int tmp;
X
X for(tmp = 1; tmp < 32; tmp++)
X if(!wsegs[tmp]) {
X mtmp->wormno = tmp;
X return(1);
X }
X return(0); /* level infested with worms */
X}
X
X/* called to initialize a worm unless cut in half */
Xvoid
Xinitworm(mtmp)
Xstruct monst *mtmp;
X{
X register struct wseg *wtmp;
X register int tmp = mtmp->wormno;
X
X if(!tmp) return;
X wheads[tmp] = wsegs[tmp] = wtmp = newseg();
X wgrowtime[tmp] = 0;
X wtmp->wx = mtmp->mx;
X wtmp->wy = mtmp->my;
X/* wtmp->wdispl = 0; */
X wtmp->nseg = 0;
X}
X
Xstatic void
Xremseg(mtmp,wtmp)
Xstruct monst *mtmp;
Xregister struct wseg *wtmp;
X{
X if (mtmp->mx != wtmp->wx || mtmp->my != wtmp->wy)
X levl[wtmp->wx][wtmp->wy].mmask = 0;
X if(wtmp->wdispl) newsym(wtmp->wx, wtmp->wy);
X free((genericptr_t) wtmp);
X}
X
Xvoid
Xworm_move(mtmp)
Xstruct monst *mtmp;
X{
X register struct wseg *wtmp, *whd;
X register int tmp = mtmp->wormno;
X
X wtmp = newseg();
X wtmp->wx = mtmp->mx;
X wtmp->wy = mtmp->my;
X wtmp->nseg = 0;
X/* wtmp->wdispl = 0; */
X (whd = wheads[tmp])->nseg = wtmp;
X wheads[tmp] = wtmp;
X if(cansee(whd->wx,whd->wy)){
X unpmon(mtmp);
X atl(whd->wx, whd->wy, S_WORM_TAIL);
X whd->wdispl = 1;
X } else whd->wdispl = 0;
X if(wgrowtime[tmp] <= moves) {
X if(!wgrowtime[tmp]) wgrowtime[tmp] = moves + rnd(5);
X else wgrowtime[tmp] += 2+rnd(15);
X mtmp->mhp += 3;
X if (mtmp->mhp > MHPMAX) mtmp->mhp = MHPMAX;
X if (mtmp->mhp > mtmp->mhpmax) mtmp->mhpmax = mtmp->mhp;
X return;
X }
X whd = wsegs[tmp];
X wsegs[tmp] = whd->nseg;
X remseg(mtmp, whd);
X}
X
Xvoid
Xworm_nomove(mtmp)
Xregister struct monst *mtmp;
X{
X register int tmp;
X register struct wseg *wtmp;
X
X tmp = mtmp->wormno;
X wtmp = wsegs[tmp];
X if(wtmp == wheads[tmp]) return;
X if(wtmp == 0 || wtmp->nseg == 0) panic("worm_nomove?");
X wsegs[tmp] = wtmp->nseg;
X remseg(mtmp, wtmp);
X if (mtmp->mhp > 3) mtmp->mhp -= 3; /* mhpmax not changed ! */
X else mtmp->mhp = 1;
X}
X
Xvoid
Xwormdead(mtmp)
Xregister struct monst *mtmp;
X{
X register int tmp = mtmp->wormno;
X register struct wseg *wtmp, *wtmp2;
X
X if(!tmp) return;
X mtmp->wormno = 0;
X for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
X wtmp2 = wtmp->nseg;
X remseg(mtmp, wtmp);
X }
X wsegs[tmp] = 0;
X}
X
Xvoid
Xwormhit(mtmp)
Xregister struct monst *mtmp;
X{
X register int tmp = mtmp->wormno;
X register struct wseg *wtmp;
X
X if(!tmp) return; /* worm without tail */
X for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg)
X if (dist(wtmp->wx, wtmp->wy) < 3) (void) mattacku(mtmp);
X}
X
Xvoid
Xwormsee(tmp)
Xregister unsigned int tmp;
X{
X register struct wseg *wtmp = wsegs[tmp];
X
X if(!wtmp) panic("wormsee: wtmp==0");
X
X for(; wtmp->nseg; wtmp = wtmp->nseg)
X if(!cansee(wtmp->wx,wtmp->wy) && wtmp->wdispl) {
X newsym(wtmp->wx, wtmp->wy);
X wtmp->wdispl = 0;
X }
X}
X
Xvoid
Xcutworm(mtmp, x, y, weptyp)
Xregister struct monst *mtmp;
Xregister xchar x,y;
Xregister unsigned weptyp; /* uwep->otyp or 0 */
X{
X register struct wseg *wtmp, *wtmp2;
X register struct monst *mtmp2;
X register int tmp, tmp2;
X
X if(mtmp->mx == x && mtmp->my == y) return; /* hit headon */
X
X /* cutting goes best with axe or sword */
X tmp = rnd(20);
X if(weptyp >= SHORT_SWORD && weptyp <= KATANA ||
X weptyp == AXE)
X tmp += 5;
X
X if(tmp < 12) return;
X
X /* if tail then worm just loses a tail segment */
X tmp = mtmp->wormno;
X wtmp = wsegs[tmp];
X if(wtmp->wx == x && wtmp->wy == y){
X wsegs[tmp] = wtmp->nseg;
X remseg(mtmp, wtmp);
X return;
X }
X
X /* cut the worm in two halves */
X mtmp2 = newmonst(0);
X *mtmp2 = *mtmp;
X mtmp2->mxlth = mtmp2->mnamelth = 0;
X
X /* sometimes the tail end dies */
X if(rn2(3) || !getwn(mtmp2)){
X monfree(mtmp2);
X levl[mtmp2->mx][mtmp2->my].mmask = 1;
X /* since mtmp is still on that spot */
X tmp2 = 0;
X } else {
X tmp2 = mtmp2->wormno;
X wsegs[tmp2] = wsegs[tmp];
X wgrowtime[tmp2] = 0;
X }
X do {
X if(wtmp->nseg->wx == x && wtmp->nseg->wy == y){
X if(tmp2) wheads[tmp2] = wtmp;
X wsegs[tmp] = wtmp->nseg->nseg;
X remseg(mtmp, wtmp->nseg);
X wtmp->nseg = 0;
X if(tmp2) {
X You("cut the worm in half.");
X /* devalue the monster level of both halves of the worm */
X mtmp->m_lev = (mtmp->m_lev <= 2) ? 2 : mtmp->m_lev - 2;
X mtmp2->m_lev = mtmp->m_lev;
X /* calculate the mhp on the new (lower) monster level */
X mtmp2->mhpmax = mtmp2->mhp = d((int)mtmp2->m_lev, 8);
X mtmp2->mx = wtmp->wx;
X mtmp2->my = wtmp->wy;
X levl[mtmp2->mx][mtmp2->my].mmask = 1;
X mtmp2->nmon = fmon;
X fmon = mtmp2;
X mtmp2->mdispl = 0;
X pmon(mtmp2);
X } else {
X You("cut off part of the worm's tail.");
X remseg(mtmp, wtmp);
X }
X mtmp->mhp /= 2;
X return;
X }
X wtmp2 = wtmp->nseg;
X if(!tmp2) remseg(mtmp, wtmp);
X wtmp = wtmp2;
X } while(wtmp->nseg);
X panic("Cannot find worm segment");
X}
X
X#endif /* WORM /**/
END_OF_FILE
if test 4990 -ne `wc -c <'src/worm.c'`; then
echo shar: \"'src/worm.c'\" unpacked with wrong size!
fi
# end of 'src/worm.c'
fi
echo shar: End of archive 28 \(of 38\).
cp /dev/null ark28isdone
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