Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Hack 1.0.2 - part 4 of 10

1 view
Skip to first unread message

Andries Brouwer

unread,
Apr 6, 1985, 7:01:06 PM4/6/85
to

# This is a shell archive. Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file". (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# hack.eat.c hack.end.c hack.engrave.c hack.fight.c hack.invent.c hack.ioctl.c

echo x - hack.eat.c
cat > "hack.eat.c" << '//E*O*F hack.eat.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.eat.c - version 1.0.2 */

#include "hack.h"
char POISONOUS[] = "ADKSVabhks";
extern char *nomovemsg;
extern int (*afternmv)();
extern int (*occupation)();
extern char *occtxt;
extern struct obj *splitobj();

/* hunger texts used on bottom line (each 8 chars long) */
#define SATIATED 0
#define NOT_HUNGRY 1
#define HUNGRY 2
#define WEAK 3
#define FAINTING 4
#define FAINTED 5
#define STARVED 6

char *hu_stat[] = {
"Satiated",
" ",
"Hungry ",
"Weak ",
"Fainting",
"Fainted ",
"Starved "
};

init_uhunger(){
u.uhunger = 900;
u.uhs = NOT_HUNGRY;
}

#define TTSZ SIZE(tintxts)
struct { char *txt; int nut; } tintxts[] = {
"It contains first quality peaches - what a surprise!", 40,
"It contains salmon - not bad!", 60,
"It contains apple juice - perhaps not what you hoped for.", 20,
"It contains some nondescript substance, tasting awfully.", 500,
"It contains rotten meat. You vomit.", -50,
"It turns out to be empty.", 0
};

static struct {
struct obj *tin;
int usedtime, reqtime;
} tin;

opentin(){
register int r;

if(!carried(tin.tin)) /* perhaps it was stolen? */
return(0); /* %% probably we should use tinoid */
if(tin.usedtime++ >= 50) {
pline("You give up your attempt to open the tin.");
return(0);
}
if(tin.usedtime < tin.reqtime)
return(1); /* still busy */

pline("You succeed in opening the tin.");
useup(tin.tin);
r = rn2(2*TTSZ);
if(r < TTSZ){
pline(tintxts[r].txt);
lesshungry(tintxts[r].nut);
if(r == 1) /* SALMON */ {
Glib = rnd(15);
pline("Eating salmon made your fingers very slippery.");
}
} else {
pline("It contains spinach - this makes you feel like Popeye!");
lesshungry(600);
if(u.ustr < 118)
u.ustr += rnd( ((u.ustr < 17) ? 19 : 118) - u.ustr);
if(u.ustr > u.ustrmax) u.ustrmax = u.ustr;
flags.botl = 1;
}
return(0);
}

Meatdone(){
u.usym = '@';
prme();
}

doeat(){
register struct obj *otmp;
register struct objclass *ftmp;
register tmp;

/* Is there some food (probably a heavy corpse) here on the ground? */
for(otmp = fobj; otmp; otmp = otmp->nobj) {
if(otmp->ox == u.ux && otmp->oy == u.uy &&
otmp->olet == FOOD_SYM) {
pline("There %s %s here; eat %s? [ny] ",
(otmp->quan == 1) ? "is" : "are",
doname(otmp),
(otmp->quan == 1) ? "it" : "one");
if(readchar() == 'y') {
if(otmp->quan != 1)
(void) splitobj(otmp, 1);
freeobj(otmp);
otmp->nobj = invent;
invent = otmp;
goto gotit;
}
}
}
otmp = getobj("%", "eat");
if(!otmp) return(0);
gotit:
if(otmp->otyp == TIN){
if(uwep) {
switch(uwep->otyp) {
case CAN_OPENER:
tmp = 1;
break;
case DAGGER:
case CRYSKNIFE:
tmp = 3;
break;
case PICK_AXE:
case AXE:
tmp = 6;
break;
default:
goto no_opener;
}
pline("Using your %s you try to open the tin",
aobjnam(uwep, (char *) 0));
} else {
no_opener:
pline("It is not so easy to open this tin.");
if(Glib) {
pline("The tin slips out of your hands.");
if(otmp->quan > 1) {
register struct obj *obj;
extern struct obj *splitobj();

obj = splitobj(otmp, 1);
if(otmp == uwep) setuwep(obj);
}
dropx(otmp);
return(1);
}
tmp = 10 + rn2(1 + 500/((int)(u.ulevel + u.ustr)));
}
tin.reqtime = tmp;
tin.usedtime = 0;
tin.tin = otmp;
occupation = opentin;
occtxt = "opening the tin";
return(1);
}
ftmp = &objects[otmp->otyp];
multi = -ftmp->oc_delay;
if(otmp->otyp >= CORPSE && eatcorpse(otmp)) goto eatx;
if(!rn2(7) && otmp->otyp != FORTUNE_COOKIE) {
pline("Blecch! Rotten food!");
if(!rn2(4)) {
pline("You feel rather light headed.");
Confusion += d(2,4);
} else if(!rn2(4)&& !Blind) {
pline("Everything suddenly goes dark.");
Blind = d(2,10);
seeoff(0);
} else if(!rn2(3)) {
if(Blind)
pline("The world spins and you slap against the floor.");
else
pline("The world spins and goes dark.");
nomul(-rnd(10));
nomovemsg = "You are conscious again.";
}
lesshungry(ftmp->nutrition / 4);
} else {
if(u.uhunger >= 1500) {
pline("You choke over your food.");
pline("You die...");
killer = ftmp->oc_name;
done("choked");
}
switch(otmp->otyp){
case FOOD_RATION:
if(u.uhunger <= 200)
pline("That food really hit the spot!");
else if(u.uhunger <= 700)
pline("That satiated your stomach!");
else {
pline("You're having a hard time getting all that food down.");
multi -= 2;
}
lesshungry(ftmp->nutrition);
if(multi < 0) nomovemsg = "You finished your meal.";
break;
case TRIPE_RATION:
pline("Yak - dog food!");
more_experienced(1,0);
flags.botl = 1;
if(rn2(2)){
pline("You vomit.");
morehungry(20);
} else lesshungry(ftmp->nutrition);
break;
default:
if(otmp->otyp >= CORPSE)
pline("That %s tasted terrible!",ftmp->oc_name);
else
pline("That %s was delicious!",ftmp->oc_name);
lesshungry(ftmp->nutrition);
if(otmp->otyp == DEAD_LIZARD && (Confusion > 2))
Confusion = 2;
else
#ifdef QUEST
if(otmp->otyp == CARROT && !Blind){
u.uhorizon++;
setsee();
pline("Your vision improves.");
} else
#endif QUEST
if(otmp->otyp == FORTUNE_COOKIE) {
if(Blind) {
pline("This cookie has a scrap of paper inside!");
pline("What a pity, that you cannot read it!");
} else
outrumor();
} else
if(otmp->otyp == LUMP_OF_ROYAL_JELLY) {
/* This stuff seems to be VERY healthy! */
if(u.ustrmax < 118) u.ustrmax++;
if(u.ustr < u.ustrmax) u.ustr++;
u.uhp += rnd(20);
if(u.uhp > u.uhpmax) u.uhp = u.uhpmax;
Wounded_legs = 0;
}
break;
}
}
eatx:
if(multi<0 && !nomovemsg){
static char msgbuf[BUFSZ];
(void) sprintf(msgbuf, "You finished eating the %s.",
ftmp->oc_name);
nomovemsg = msgbuf;
}
useup(otmp);
return(1);
}

/* called in hack.main.c */
gethungry(){
--u.uhunger;
if((Regeneration || Hunger) && moves%2) u.uhunger--;
if(uleft && moves%20) u.uhunger--;
if(uright && moves%20) u.uhunger--;
newuhs(TRUE);
}

/* called after vomiting and after performing feats of magic */
morehungry(num) register num; {
u.uhunger -= num;
newuhs(TRUE);
}

/* called after eating something (and after drinking fruit juice) */
lesshungry(num) register num; {
u.uhunger += num;
newuhs(FALSE);
}

unfaint(){
u.uhs = FAINTING;
flags.botl = 1;
}

newuhs(incr) boolean incr; {
register int newhs, h = u.uhunger;

newhs = (h > 1000) ? SATIATED :
(h > 150) ? NOT_HUNGRY :
(h > 50) ? HUNGRY :
(h > 0) ? WEAK : FAINTING;

if(newhs == FAINTING) {
if(u.uhs == FAINTED)
newhs = FAINTED;
if(u.uhs <= WEAK || rn2(20-u.uhunger/10) >= 19) {
if(u.uhs != FAINTED && multi >= 0 /* %% */) {
pline("You faint from lack of food.");
nomul(-10+(u.uhunger/10));
nomovemsg = "You regain consciousness.";
afternmv = unfaint;
newhs = FAINTED;
}
} else
if(u.uhunger < -(int)(200 + 25*u.ulevel)) {
u.uhs = STARVED;
flags.botl = 1;
bot();
pline("You die from starvation.");
done("starved");
}
}

if(newhs != u.uhs) {
if(newhs >= WEAK && u.uhs < WEAK)
losestr(1); /* this may kill you -- see below */
else
if(newhs < WEAK && u.uhs >= WEAK && u.ustr < u.ustrmax)
losestr(-1);
switch(newhs){
case HUNGRY:
pline((!incr) ? "You only feel hungry now." :
(u.uhunger < 145) ? "You feel hungry." :
"You are beginning to feel hungry.");
break;
case WEAK:
pline((!incr) ? "You feel weak now." :
(u.uhunger < 45) ? "You feel weak." :
"You are beginning to feel weak.");
break;
}
u.uhs = newhs;
flags.botl = 1;
if(u.uhp < 1) {
pline("You die from hunger and exhaustion.");
killer = "exhaustion";
done("starved");
}
}
}

#define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\
? 'a' + (otyp - DEAD_ACID_BLOB)\
: '@' + (otyp - DEAD_HUMAN))
poisonous(otmp)
register struct obj *otmp;
{
return(index(POISONOUS, CORPSE_I_TO_C(otmp->otyp)) != 0);
}

/* returns 1 if some text was printed */
eatcorpse(otmp) register struct obj *otmp; {
register char let = CORPSE_I_TO_C(otmp->otyp);
register tp = 0;
if(moves > otmp->age + 50 + rn2(100)) {
tp++;
pline("Ulch -- that meat was tainted!");
pline("You get very sick.");
Sick = 10 + rn2(10);
u.usick_cause = objects[otmp->otyp].oc_name;
} else if(index(POISONOUS, let) && rn2(5)){
tp++;
pline("Ecch -- that must have been poisonous!");
if(!Poison_resistance){
losestr(rnd(4));
losehp(rnd(15), "poisonous corpse");
} else
pline("You don't seem affected by the poison.");
} else if(index("ELNOPQRUuxz", let) && rn2(5)){
tp++;
pline("You feel sick.");
losehp(rnd(8), "cadaver");
}
switch(let) {
case 'L':
case 'N':
case 't':
Teleportation |= INTRINSIC;
break;
case 'W':
pluslvl();
break;
case 'n':
u.uhp = u.uhpmax;
flags.botl = 1;
/* fall into next case */
case '@':
pline("You cannibal! You will be sorry for this!");
/* not tp++; */
/* fall into next case */
case 'd':
Aggravate_monster |= INTRINSIC;
break;
case 'I':
See_invisible |= INTRINSIC;
if(!Invis) newsym(u.ux, u.uy);
Invis += 50;
/* fall into next case */
case 'y':
#ifdef QUEST
u.uhorizon++;
#endif QUEST
/* fall into next case */
case 'B':
Confusion = 50;
break;
case 'D':
Fire_resistance |= INTRINSIC;
break;
case 'E':
Telepat |= INTRINSIC;
break;
case 'F':
case 'Y':
Cold_resistance |= INTRINSIC;
break;
case 'k':
case 's':
Poison_resistance |= INTRINSIC;
break;
case 'c':
pline("You turn to stone.");
killer = "dead cockatrice";
done("died");
case 'M':
pline("You cannot resist the temptation to mimic a treasure chest.");
tp++;
nomul(-30);
afternmv = Meatdone;
nomovemsg = "You now again prefer mimicking a human.";
u.usym = '$';
prme();
break;
}
return(tp);
}
//E*O*F hack.eat.c//

echo x - hack.end.c
cat > "hack.end.c" << '//E*O*F hack.end.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.end.c - version 1.0.2 */

#include "hack.h"
#include <stdio.h>
#include <signal.h>
#define Sprintf (void) sprintf
extern char plname[], pl_character[];
extern char *itoa(), *ordin(), *eos();
extern boolean female; /* should have been flags.female */

xchar maxdlevel = 1;

done1()
{
(void) signal(SIGINT,SIG_IGN);
pline("Really quit?");
if(readchar() != 'y') {
(void) signal(SIGINT,done1);
clrlin();
(void) fflush(stdout);
if(multi > 0) nomul(0);
return(0);
}
done("quit");
/* NOTREACHED */
}

int done_stopprint;
int done_hup;

done_intr(){
done_stopprint++;
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
}

done_hangup(){
done_hup++;
(void) signal(SIGHUP, SIG_IGN);
done_intr();
}

done_in_by(mtmp) register struct monst *mtmp; {
static char buf[BUFSZ];
pline("You die ...");
if(mtmp->data->mlet == ' '){
Sprintf(buf, "the ghost of %s", (char *) mtmp->mextra);
killer = buf;
} else if(mtmp->mnamelth) {
Sprintf(buf, "%s called %s",
mtmp->data->mname, NAME(mtmp));
killer = buf;
} else if(mtmp->minvis) {
Sprintf(buf, "invisible %s", mtmp->data->mname);
killer = buf;
} else killer = mtmp->data->mname;
done("died");
}

/* called with arg "died", "drowned", "escaped", "quit", "choked", "panicked",
"burned", "starved" or "tricked" */
/* Be careful not to call panic from here! */
done(st1)
register char *st1;
{

#ifdef WIZARD
if(wizard && *st1 == 'd'){
u.uswldtim = 0;
u.uhp = u.uhpmax;
pline("For some reason you are still alive.");
flags.move = 0;
if(multi > 0) multi = 0; else multi = -1;
flags.botl = 1;
return;
}
#endif WIZARD
(void) signal(SIGINT, done_intr);
(void) signal(SIGQUIT, done_intr);
(void) signal(SIGHUP, done_hangup);
if(*st1 == 'q' && u.uhp < 1){
st1 = "died";
killer = "quit while already on Charon's boat";
}
if(*st1 == 's') killer = "starvation"; else
if(*st1 == 'd' && st1[1] == 'r') killer = "drowning"; else
if(*st1 == 'p') killer = "panic"; else
if(*st1 == 't') killer = "trickery"; else
if(!index("bcd", *st1)) killer = st1;
paybill();
clearlocks();
if(flags.toplin == 1) more();
if(index("bcds", *st1)){
if(dlevel > 0 && dlevel < 30) /* soon superfluous */
savebones();
if(!flags.notombstone)
outrip();
}
if(*st1 == 'c') killer = st1; /* after outrip() */
settty((char *) 0); /* does a clear_screen() */
if(!done_stopprint)
printf("Goodbye %s %s...\n\n", pl_character, plname);
{ long int tmp;
tmp = u.ugold - u.ugold0;
if(tmp < 0)
tmp = 0;
if(*st1 == 'd' || *st1 == 'b')
tmp -= tmp/10;
u.urexp += tmp;
u.urexp += 50 * maxdlevel;
if(maxdlevel > 20)
u.urexp += 1000*((maxdlevel > 30) ? 10 : maxdlevel - 20);
}
if(*st1 == 'e') {
extern struct monst *mydogs;
register struct monst *mtmp;
register struct obj *otmp;
register int i;
register unsigned worthlessct = 0;
boolean has_amulet = FALSE;

killer = st1;
keepdogs();
mtmp = mydogs;
if(mtmp) {
if(!done_stopprint) printf("You");
while(mtmp) {
if(!done_stopprint)
printf(" and %s", monnam(mtmp));
if(mtmp->mtame)
u.urexp += mtmp->mhp;
mtmp = mtmp->nmon;
}
if(!done_stopprint)
printf("\nescaped from the dungeon with %ld points,\n",
u.urexp);
} else
if(!done_stopprint)
printf("You escaped from the dungeon with %ld points,\n",
u.urexp);
for(otmp = invent; otmp; otmp = otmp->nobj) {
if(otmp->olet == GEM_SYM){
objects[otmp->otyp].oc_name_known = 1;
i = otmp->quan*objects[otmp->otyp].g_val;
if(i == 0) {
worthlessct += otmp->quan;
continue;
}
u.urexp += i;
if(!done_stopprint)
printf("\t%s (worth %d Zorkmids),\n",
doname(otmp), i);
} else if(otmp->olet == AMULET_SYM) {
otmp->known = 1;
i = (otmp->spe < 0) ? 2 : 5000;
u.urexp += i;
if(!done_stopprint)
printf("\t%s (worth %d Zorkmids),\n",
doname(otmp), i);
if(otmp->spe >= 0) {
has_amulet = TRUE;
killer = "escaped (with amulet)";
}
}
}
if(worthlessct) if(!done_stopprint)
printf("\t%u worthless piece%s of coloured glass,\n",
worthlessct, plur(worthlessct));
if(has_amulet) u.urexp *= 2;
} else
if(!done_stopprint)
printf("You %s on dungeon level %d with %ld points,\n",
st1, dlevel, u.urexp);
if(!done_stopprint)
printf("and %ld piece%s of gold, after %ld move%s.\n",
u.ugold, plur(u.ugold), moves, plur(moves));
if(!done_stopprint)
printf("You were level %u with a maximum of %d hit points when you %s.\n",
u.ulevel, u.uhpmax, st1);
if(*st1 == 'e' && !done_stopprint){
getret(); /* all those pieces of coloured glass ... */
cls();
}
#ifdef WIZARD
if(!wizard)
#endif WIZARD
topten();
if(done_stopprint) printf("\n\n");
exit(0);
}

#define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
#define NAMSZ 8
#define DTHSZ 40
#define PERSMAX 1
#define POINTSMIN 1 /* must be > 0 */
#define ENTRYMAX 100 /* must be >= 10 */
#define PERS_IS_UID /* delete for PERSMAX per name; now per uid */
struct toptenentry {
struct toptenentry *tt_next;
long int points;
int level,maxlvl,hp,maxhp;
int uid;
char plchar;
char sex;
char name[NAMSZ+1];
char death[DTHSZ+1];
char date[7]; /* yymmdd */
} *tt_head;

topten(){
int uid = getuid();
int rank, rank0 = -1, rank1 = 0;
int occ_cnt = PERSMAX;
register struct toptenentry *t0, *t1, *tprev;
char *recfile = RECORD;
char *reclock = "record_lock";
int sleepct = 300;
FILE *rfile;
register flg = 0;
extern char *getdate();
#define HUP if(!done_hup)
while(link(recfile, reclock) == -1) {
HUP perror(reclock);
if(!sleepct--) {
HUP puts("I give up. Sorry.");
HUP puts("Perhaps there is an old record_lock around?");
return;
}
HUP printf("Waiting for access to record file. (%d)\n",
sleepct);
HUP (void) fflush(stdout);
sleep(1);
}
if(!(rfile = fopen(recfile,"r"))){
HUP puts("Cannot open record file!");
goto unlock;
}
HUP (void) putchar('\n');

/* create a new 'topten' entry */
t0 = newttentry();
t0->level = dlevel;
t0->maxlvl = maxdlevel;
t0->hp = u.uhp;
t0->maxhp = u.uhpmax;
t0->points = u.urexp;
t0->plchar = pl_character[0];
t0->sex = (female ? 'F' : 'M');
t0->uid = uid;
(void) strncpy(t0->name, plname, NAMSZ);
(t0->name)[NAMSZ] = 0;
(void) strncpy(t0->death, killer, DTHSZ);
(t0->death)[DTHSZ] = 0;
(void) strcpy(t0->date, getdate());

/* assure minimum number of points */
if(t0->points < POINTSMIN)
t0->points = 0;

t1 = tt_head = newttentry();
tprev = 0;
/* rank0: -1 undefined, 0 not_on_list, n n_th on list */
for(rank = 1; ; ) {
if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
t1->date, &t1->uid,
&t1->level, &t1->maxlvl,
&t1->hp, &t1->maxhp, &t1->points,
&t1->plchar, &t1->sex, t1->name, t1->death) != 11
|| t1->points < POINTSMIN)
t1->points = 0;
if(rank0 < 0 && t1->points < t0->points) {
rank0 = rank++;
if(tprev == 0)
tt_head = t0;
else
tprev->tt_next = t0;
t0->tt_next = t1;
occ_cnt--;
flg++; /* ask for a rewrite */
} else
tprev = t1;
if(t1->points == 0) break;
if(
#ifdef PERS_IS_UID
t1->uid == t0->uid &&
#else
strncmp(t1->name, t0->name, NAMSZ) == 0 &&
#endif PERS_IS_UID
t1->plchar == t0->plchar && --occ_cnt <= 0){
if(rank0 < 0){
rank0 = 0;
rank1 = rank;
HUP printf("You didn't beat your previous score of %ld points.\n\n",
t1->points);
}
if(occ_cnt < 0){
flg++;
continue;
}
}
if(rank <= ENTRYMAX){
t1 = t1->tt_next = newttentry();
rank++;
}
if(rank > ENTRYMAX){
t1->points = 0;
break;
}
}
if(flg) { /* rewrite record file */
(void) fclose(rfile);
if(!(rfile = fopen(recfile,"w"))){
HUP puts("Cannot write record file\n");
goto unlock;
}

if(!done_stopprint) if(rank0 > 0){
if(rank0 <= 10)
puts("You made the top ten list!\n");
else
printf("You reached the %d%s place on the top %d list.\n\n",
rank0, ordin(rank0), ENTRYMAX);
}
}
if(rank0 == 0) rank0 = rank1;
if(rank0 <= 0) rank0 = rank;
if(!done_stopprint) outheader();
t1 = tt_head;
for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
if(flg) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n",
t1->date, t1->uid,
t1->level, t1->maxlvl,
t1->hp, t1->maxhp, t1->points,
t1->plchar, t1->sex, t1->name, t1->death);
if(done_stopprint) continue;
if(rank > flags.end_top &&
(rank < rank0-flags.end_around || rank > rank0+flags.end_around)
&& (!flags.end_own ||
#ifdef PERS_IS_UID
t1->uid != t0->uid ))
#else
strncmp(t1->name, t0->name, NAMSZ)))
#endif PERS_IS_UID
continue;
if(rank == rank0-flags.end_around &&
rank0 > flags.end_top+flags.end_around+1 &&
!flags.end_own)
(void) putchar('\n');
if(rank != rank0)
(void) outentry(rank, t1, 0);
else if(!rank1)
(void) outentry(rank, t1, 1);
else {
int t0lth = outentry(0, t0, -1);
int t1lth = outentry(rank, t1, t0lth);
if(t1lth > t0lth) t0lth = t1lth;
(void) outentry(0, t0, t0lth);
}
}
if(rank0 >= rank) if(!done_stopprint)
(void) outentry(0, t0, 1);
(void) fclose(rfile);
unlock:
(void) unlink(reclock);
}

outheader() {
char linebuf[BUFSZ];
register char *bp;
(void) strcpy(linebuf, "Number Points Name");
bp = eos(linebuf);
while(bp < linebuf + COLNO - 9) *bp++ = ' ';
(void) strcpy(bp, "Hp [max]");
puts(linebuf);
}

/* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
int
outentry(rank,t1,so) register struct toptenentry *t1; {
boolean quit = FALSE, killed = FALSE, starv = FALSE;
char linebuf[BUFSZ];
linebuf[0] = 0;
if(rank) Sprintf(eos(linebuf), "%3d", rank);
else Sprintf(eos(linebuf), " ");
Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->name);
if(t1->plchar == 'X') Sprintf(eos(linebuf), " ");
else Sprintf(eos(linebuf), "-%c ", t1->plchar);
if(!strncmp("escaped", t1->death, 7)) {
if(!strcmp(" (with amulet)", t1->death+7))
Sprintf(eos(linebuf), "escaped the dungeon with amulet");
else
Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
t1->maxlvl);
} else {
if(!strncmp(t1->death,"quit",4))
Sprintf(eos(linebuf), "quit"), quit = TRUE;
else if(!strcmp(t1->death,"choked"))
Sprintf(eos(linebuf), "choked on %s food",
(t1->sex == 'F') ? "her" : "his");
else if(!strncmp(t1->death,"starv",5))
Sprintf(eos(linebuf), "starved to death"), starv = TRUE;
else Sprintf(eos(linebuf), "was killed"), killed = TRUE;
Sprintf(eos(linebuf), " on%s level %d",
(killed || starv) ? "" : " dungeon", t1->level);
if(t1->maxlvl != t1->level)
Sprintf(eos(linebuf), " [max %d]", t1->maxlvl);
if(quit && t1->death[4]) Sprintf(eos(linebuf), t1->death + 4);
}
if(killed) Sprintf(eos(linebuf), " by %s%s",
(!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4))
? "" :
index(vowels,*t1->death) ? "an " : "a ",
t1->death);
Sprintf(eos(linebuf), ".");
if(t1->maxhp) {
register char *bp = eos(linebuf);
char hpbuf[10];
int hppos;
Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-");
hppos = COLNO - 7 - strlen(hpbuf);
if(bp <= linebuf + hppos) {
while(bp < linebuf + hppos) *bp++ = ' ';
(void) strcpy(bp, hpbuf);
Sprintf(eos(bp), " [%d]", t1->maxhp);
}
}
if(so == 0) puts(linebuf);
else if(so > 0) {
register char *bp = eos(linebuf);
if(so >= COLNO) so = COLNO-1;
while(bp < linebuf + so) *bp++ = ' ';
*bp = 0;
standoutbeg();
fputs(linebuf,stdout);
standoutend();
(void) putchar('\n');
}
return(strlen(linebuf));
}

char *
itoa(a) int a; {
static char buf[12];
Sprintf(buf,"%d",a);
return(buf);
}

char *
ordin(n) int n; {
register int d = n%10;
return((d==0 || d>3 || n/10==1) ? "th" : (d==1) ? "st" :
(d==2) ? "nd" : "rd");
}

clearlocks(){
register x;
(void) signal(SIGHUP,SIG_IGN);
for(x = 1; x <= maxdlevel; x++) {
glo(x);
(void) unlink(lock); /* not all levels need be present */
}
glo(0);
(void) unlink(lock);
}

#ifdef NOSAVEONHANGUP
hangup()
{
(void) signal(SIGINT, SIG_IGN);
clearlocks();
exit(1);
}
#endif NOSAVEONHANGUP

char *
eos(s)
register char *s;
{
while(*s) s++;
return(s);
}

/* it is the callers responsibility to check that there is room for c */
charcat(s,c) register char *s, c; {
while(*s) s++;
*s++ = c;
*s = 0;
}

/*
* Called with args from main if argc >= 0. In this case, list scores as
* requested. Otherwise, find scores for the current player (and list them
* if argc == -1).
*/
prscore(argc,argv) int argc; char **argv; {
extern char *hname;
char *player0;
char **players;
int playerct;
int rank;
register struct toptenentry *t1, *t2;
char *recfile = RECORD;
FILE *rfile;
register flg = 0;
register int i;
#ifdef nonsense
long total_score = 0L;
char totchars[10];
int totcharct = 0;
#endif nonsense
int outflg = (argc >= -1);

if(!(rfile = fopen(recfile,"r"))){
puts("Cannot open record file!");
return;
}

if(argc > 1 && !strncmp(argv[1], "-s", 2)){
if(!argv[1][2]){
argc--;
argv++;
} else if(!argv[1][3] && index("CFKSTWX", argv[1][2])) {
argv[1]++;
argv[1][0] = '-';
} else argv[1] += 2;
}
if(argc <= 1){
player0 = plname;
if(!*player0)
player0 = "hackplayer";
playerct = 1;
players = &player0;
} else {
playerct = --argc;
players = ++argv;
}
if(outflg) putchar('\n');

t1 = tt_head = newttentry();
for(rank = 1; ; rank++) {
if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
t1->date, &t1->uid,
&t1->level, &t1->maxlvl,
&t1->hp, &t1->maxhp, &t1->points,
&t1->plchar, &t1->sex, t1->name, t1->death) != 11)
t1->points = 0;
if(t1->points == 0) break;
for(i = 0; i < playerct; i++){
if(strcmp(players[i], "all") == 0 ||
strncmp(t1->name, players[i], NAMSZ) == 0 ||
(players[i][0] == '-' &&
players[i][1] == t1->plchar &&
players[i][2] == 0) ||
(digit(players[i][0]) && rank <= atoi(players[i])))
flg++;
}
t1 = t1->tt_next = newttentry();
}
(void) fclose(rfile);
if(!flg) {
if(outflg) {
printf("Cannot find any entries for ");
if(playerct > 1) printf("any of ");
for(i=0; i<playerct; i++)
printf("%s%s", players[i], (i<playerct-1)?", ":".\n");
printf("Call is: %s -s [playernames]\n", hname);
}
return;
}

if(outflg) outheader();
t1 = tt_head;
for(rank = 1; t1->points != 0; rank++, t1 = t2) {
t2 = t1->tt_next;
for(i = 0; i < playerct; i++){
if(strcmp(players[i], "all") == 0 ||
strncmp(t1->name, players[i], NAMSZ) == 0 ||
(players[i][0] == '-' &&
players[i][1] == t1->plchar &&
players[i][2] == 0) ||
(digit(players[i][0]) && rank <= atoi(players[i]))){
if(outflg)
(void) outentry(rank, t1, 0);
#ifdef nonsense
total_score += t1->points;
if(totcharct < sizeof(totchars)-1)
totchars[totcharct++] = t1->plchar;
#endif nonsense
break;
}
}
free((char *) t1);
}
#ifdef nonsense
totchars[totcharct] = 0;

/* We would like to determine whether he is experienced. However,
the information collected here only tells about the scores/roles
that got into the topten (top 100?). We should maintain a
.hacklog or something in his home directory. */
flags.beginner = (total_score < 6000);
for(i=0; i<6; i++)
if(!index(totchars, "CFKSTWX"[i])) {
flags.beginner = 1;
if(!pl_character[0]) pl_character[0] = "CFKSTWX"[i];
break;
}
#endif nonsense
}
//E*O*F hack.end.c//

echo x - hack.engrave.c
cat > "hack.engrave.c" << '//E*O*F hack.engrave.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.engrave.c - version 1.0.2 */

#include "hack.h"

extern char *nomovemsg;
extern char nul[];
extern struct obj zeroobj;
struct engr {
struct engr *nxt_engr;
char *engr_txt;
xchar engr_x, engr_y;
unsigned engr_lth; /* for save & restore; not length of text */
long engr_time; /* moment engraving was (will be) finished */
xchar engr_type;
#define DUST 1
#define ENGRAVE 2
#define BURN 3
} *head_engr;

struct engr *
engr_at(x,y) register xchar x,y; {
register struct engr *ep = head_engr;
while(ep) {
if(x == ep->engr_x && y == ep->engr_y)
return(ep);
ep = ep->nxt_engr;
}
return((struct engr *) 0);
}

sengr_at(s,x,y) register char *s; register xchar x,y; {
register struct engr *ep = engr_at(x,y);
register char *t;
register int n;
if(ep && ep->engr_time <= moves) {
t = ep->engr_txt;
/*
if(!strcmp(s,t)) return(1);
*/
n = strlen(s);
while(*t) {
if(!strncmp(s,t,n)) return(1);
t++;
}
}
return(0);
}

wipe_engr_at(x,y,cnt) register xchar x,y,cnt; {
register struct engr *ep = engr_at(x,y);
register int lth,pos;
char ch;
if(ep){
if(ep->engr_type != DUST) {
cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1;
}
lth = strlen(ep->engr_txt);
if(lth && cnt > 0 ) {
while(cnt--) {
pos = rn2(lth);
if((ch = ep->engr_txt[pos]) == ' ')
continue;
ep->engr_txt[pos] = (ch != '?') ? '?' : ' ';
}
}
while(lth && ep->engr_txt[lth-1] == ' ')
ep->engr_txt[--lth] = 0;
while(ep->engr_txt[0] == ' ')
ep->engr_txt++;
if(!ep->engr_txt[0]) del_engr(ep);
}
}

read_engr_at(x,y) register int x,y; {
register struct engr *ep = engr_at(x,y);
if(ep && ep->engr_txt[0]) {
switch(ep->engr_type) {
case DUST:
pline("Something is written here in the dust.");
break;
case ENGRAVE:
pline("Something is engraved here on the floor.");
break;
case BURN:
pline("Some text has been burned here in the floor.");
break;
default:
impossible("Something is written in a very strange way.");
}
pline("You read: \"%s\".", ep->engr_txt);
}
}

make_engr_at(x,y,s)
register int x,y;
register char *s;
{
register struct engr *ep;

if(ep = engr_at(x,y))
del_engr(ep);
ep = (struct engr *)
alloc((unsigned)(sizeof(struct engr) + strlen(s) + 1));
ep->nxt_engr = head_engr;
head_engr = ep;
ep->engr_x = x;
ep->engr_y = y;
ep->engr_txt = (char *)(ep + 1);
(void) strcpy(ep->engr_txt, s);
ep->engr_time = 0;
ep->engr_type = DUST;
ep->engr_lth = strlen(s) + 1;
}

doengrave(){
register int len;
register char *sp;
register struct engr *ep, *oep = engr_at(u.ux,u.uy);
char buf[BUFSZ];
xchar type;
int spct; /* number of leading spaces */
register struct obj *otmp;
multi = 0;

if(u.uswallow) {
pline("You're joking. Hahaha!"); /* riv05!a3 */
return(0);
}

/* one may write with finger, weapon or wand */
otmp = getobj("#-)/", "write with");
if(!otmp) return(0);
if(otmp == &zeroobj) {
if(uwep) {
pline("You are now empty-handed.");
setuwep((struct obj *) 0);
}
type = DUST;
} else if(otmp->otyp == WAN_FIRE && otmp->spe) {
type = BURN;
otmp->spe--;
} else {
if(otmp != uwep) {
pline("You now wield %s.", doname(otmp));
setuwep(otmp);
}

if(otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD ||
otmp->otyp == CRYSKNIFE ||
otmp->otyp == LONG_SWORD || otmp->otyp == AXE) {
type = ENGRAVE;
if((int)otmp->spe <= -3) {
type = DUST;
pline("Your %s too dull for engraving.",
aobjnam(otmp, "are"));
if(oep && oep->engr_type != DUST) return(1);
}
} else type = DUST;
}
if(Levitation && type != BURN){ /* riv05!a3 */
pline("You can't reach the floor!");
return(1);
}
if(oep && oep->engr_type == DUST){
pline("You wipe out the message that was written here.");
del_engr(oep);
oep = 0;
}
if(type == DUST && oep){
pline("You cannot wipe out the message that is %s in the rock.",
(oep->engr_type == BURN) ? "burned" : "engraved");
return(1);
}

pline("What do you want to %s on the floor here? ",
(type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write");
getlin(buf);
clrlin();
spct = 0;
sp = buf;
while(*sp == ' ') spct++, sp++;
len = strlen(sp);
if(!len) {
if(type == BURN) otmp->spe++;
return(0);
}

switch(type) {
case DUST:
case BURN:
if(len > 15) {
multi = -(len/10);
nomovemsg = "You finished writing.";
}
break;
case ENGRAVE:
{ int len2 = (otmp->spe + 3) * 2 + 1;

pline("Your %s dull.", aobjnam(otmp, "get"));
if(len2 < len) {
len = len2;
sp[len] = 0;
otmp->spe = -3;
nomovemsg = "You cannot engrave more.";
} else {
otmp->spe -= len/2;
nomovemsg = "You finished engraving.";
}
multi = -len;
}
break;
}
if(oep) len += strlen(oep->engr_txt) + spct;
ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1));
ep->nxt_engr = head_engr;
head_engr = ep;
ep->engr_x = u.ux;
ep->engr_y = u.uy;
sp = (char *)(ep + 1); /* (char *)ep + sizeof(struct engr) */
ep->engr_txt = sp;
if(oep) {
(void) strcpy(sp, oep->engr_txt);
(void) strcat(sp, buf);
del_engr(oep);
} else
(void) strcpy(sp, buf);
ep->engr_lth = len+1;
ep->engr_type = type;
ep->engr_time = moves-multi;

/* kludge to protect pline against excessively long texts */
if(len > BUFSZ-20) sp[BUFSZ-20] = 0;

return(1);
}

save_engravings(fd) int fd; {
register struct engr *ep = head_engr;
while(ep) {
if(!ep->engr_lth || !ep->engr_txt[0]){
ep = ep->nxt_engr;
continue;
}
bwrite(fd, (char *) & (ep->engr_lth), sizeof(ep->engr_lth));
bwrite(fd, (char *) ep, sizeof(struct engr) + ep->engr_lth);
ep = ep->nxt_engr;
}
bwrite(fd, (char *) nul, sizeof(unsigned));
}

rest_engravings(fd) int fd; {
register struct engr *ep;
unsigned lth;
head_engr = 0;
while(1) {
mread(fd, (char *) &lth, sizeof(unsigned));
if(lth == 0) return;
ep = (struct engr *) alloc(sizeof(struct engr) + lth);
mread(fd, (char *) ep, sizeof(struct engr) + lth);
ep->nxt_engr = head_engr;
ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */
head_engr = ep;
}
}

del_engr(ep) register struct engr *ep; {
register struct engr *ept;
if(ep == head_engr)
head_engr = ep->nxt_engr;
else {
for(ept = head_engr; ept; ept = ept->nxt_engr) {
if(ept->nxt_engr == ep) {
ept->nxt_engr = ep->nxt_engr;
goto fnd;
}
}
impossible("Error in del_engr?");
return;
fnd: ;
}
free((char *) ep);
}
//E*O*F hack.engrave.c//

echo x - hack.fight.c
cat > "hack.fight.c" << '//E*O*F hack.fight.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.fight.c - version 1.0.2 */

#include "hack.h"
extern struct permonst li_dog, dog, la_dog;
extern char *exclam(), *xname();
extern struct obj *mkobj_at();

static boolean far_noise;
static long noisetime;

/* hitmm returns 0 (miss), 1 (hit), or 2 (kill) */
hitmm(magr,mdef) register struct monst *magr,*mdef; {
register struct permonst *pa = magr->data, *pd = mdef->data;
int hit;
schar tmp;
boolean vis;
if(index("Eauy", pa->mlet)) return(0);
if(magr->mfroz) return(0); /* riv05!a3 */
tmp = pd->ac + pa->mlevel;
if(mdef->mconf || mdef->mfroz || mdef->msleep){
tmp += 4;
if(mdef->msleep) mdef->msleep = 0;
}
hit = (tmp > rnd(20));
if(hit) mdef->msleep = 0;
vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my));
if(vis){
char buf[BUFSZ];
if(mdef->mimic) seemimic(mdef);
if(magr->mimic) seemimic(magr);
(void) sprintf(buf,"%s %s", Monnam(magr),
hit ? "hits" : "misses");
pline("%s %s.", buf, monnam(mdef));
} else {
boolean far = (dist(magr->mx, magr->my) > 15);
if(far != far_noise || moves-noisetime > 10) {
far_noise = far;
noisetime = moves;
pline("You hear some noises%s.",
far ? " in the distance" : "");
}
}
if(hit){
if(magr->data->mlet == 'c' && !magr->cham) {
magr->mhpmax += 3;
if(vis) pline("%s is turned to stone!", Monnam(mdef));
else if(mdef->mtame)
pline("You have a peculiarly sad feeling for a moment, then it passes.");
monstone(mdef);
hit = 2;
} else
if((mdef->mhp -= d(pa->damn,pa->damd)) < 1) {
magr->mhpmax += 1 + rn2(pd->mlevel+1);
if(magr->mtame && magr->mhpmax > 8*pa->mlevel){
if(pa == &li_dog) magr->data = pa = &dog;
else if(pa == &dog) magr->data = pa = &la_dog;
}
if(vis) pline("%s is killed!", Monnam(mdef));
else if(mdef->mtame)
pline("You have a sad feeling for a moment, then it passes.");
mondied(mdef);
hit = 2;
}
}
return(hit);
}

/* drop (perhaps) a cadaver and remove monster */
mondied(mdef) register struct monst *mdef; {
register struct permonst *pd = mdef->data;
if(letter(pd->mlet) && rn2(3)){
(void) mkobj_at(pd->mlet,mdef->mx,mdef->my);
if(cansee(mdef->mx,mdef->my)){
unpmon(mdef);
atl(mdef->mx,mdef->my,fobj->olet);
}
stackobj(fobj);
}
mondead(mdef);
}

/* drop a rock and remove monster */
monstone(mdef) register struct monst *mdef; {
extern char mlarge[];
if(index(mlarge, mdef->data->mlet))
mksobj_at(ENORMOUS_ROCK, mdef->mx, mdef->my);
else
mksobj_at(ROCK, mdef->mx, mdef->my);
if(cansee(mdef->mx, mdef->my)){
unpmon(mdef);
atl(mdef->mx,mdef->my,fobj->olet);
}
mondead(mdef);
}

fightm(mtmp) register struct monst *mtmp; {
register struct monst *mon;
for(mon = fmon; mon; mon = mon->nmon) if(mon != mtmp) {
if(DIST(mon->mx,mon->my,mtmp->mx,mtmp->my) < 3)
if(rn2(4))
return(hitmm(mtmp,mon));
}
return(-1);
}

/* u is hit by sth, but not a monster */
thitu(tlev,dam,name)
register tlev,dam;
register char *name;
{
char buf[BUFSZ];
setan(name,buf);
if(u.uac + tlev <= rnd(20)) {
if(Blind) pline("It misses.");
else pline("You are almost hit by %s!", buf);
return(0);
} else {
if(Blind) pline("You are hit!");
else pline("You are hit by %s!", buf);
losehp(dam,name);
return(1);
}
}

char mlarge[] = "bCDdegIlmnoPSsTUwY',&";

boolean
hmon(mon,obj,thrown) /* return TRUE if mon still alive */
register struct monst *mon;
register struct obj *obj;
register thrown;
{
register tmp;

if(!obj){
tmp = rnd(2); /* attack with bare hands */
if(mon->data->mlet == 'c' && !uarmg){
pline("You hit the cockatrice with your bare hands");
pline("You turn to stone ...");
done_in_by(mon);
}
} else if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE) {
if(obj == uwep && (obj->otyp > SPEAR || obj->otyp < BOOMERANG))
tmp = rnd(2);
else {
if(index(mlarge, mon->data->mlet)) {
tmp = rnd(objects[obj->otyp].wldam);
if(obj->otyp == TWO_HANDED_SWORD) tmp += d(2,6);
else if(obj->otyp == FLAIL) tmp += rnd(4);
} else {
tmp = rnd(objects[obj->otyp].wsdam);
}
tmp += obj->spe;
if(!thrown && obj == uwep && obj->otyp == BOOMERANG
&& !rn2(3)){
pline("As you hit %s, the boomerang breaks into splinters.",
monnam(mon));
freeinv(obj);
setworn((struct obj *) 0, obj->owornmask);
obfree(obj, (struct obj *) 0);
tmp++;
}
}
if(mon->data->mlet == 'O' && obj->otyp == TWO_HANDED_SWORD &&
!strcmp(ONAME(obj), "Orcrist"))
tmp += rnd(10);
} else switch(obj->otyp) {
case HEAVY_IRON_BALL:
tmp = rnd(25); break;
case EXPENSIVE_CAMERA:
pline("You succeed in destroying your camera. Congratulations!");
freeinv(obj);
if(obj->owornmask)
setworn((struct obj *) 0, obj->owornmask);
obfree(obj, (struct obj *) 0);
return(TRUE);
case DEAD_COCKATRICE:
pline("You hit %s with the cockatrice corpse",
monnam(mon));
if(mon->data->mlet == 'c') {
tmp = 1;
break;
}
pline("%s is turned to stone!", Monnam(mon));
killed(mon);
return(FALSE);
case CLOVE_OF_GARLIC: /* no effect against demons */
if(index(UNDEAD, mon->data->mlet))
mon->mflee = 1;
tmp = 1;
break;
default:
/* non-weapons can damage because of their weight */
/* (but not too much) */
tmp = obj->owt/10;
if(tmp < 1) tmp = 1;
else tmp = rnd(tmp);
if(tmp > 6) tmp = 6;
}

/****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */

tmp += u.udaminc + dbon();
if(u.uswallow) {
if((tmp -= u.uswldtim) <= 0) {
pline("Your arms are no longer able to hit.");
return(TRUE);
}
}
if(tmp < 1) tmp = 1;
mon->mhp -= tmp;
if(mon->mhp < 1) {
killed(mon);
return(FALSE);
}
if(mon->mtame && (!mon->mflee || mon->mfleetim)) {
mon->mflee = 1; /* Rick Richardson */
mon->mfleetim += 10*rnd(tmp);
}

if(thrown) { /* this assumes that we cannot throw plural things */
hit( xname(obj) /* or: objects[obj->otyp].oc_name */,
mon, exclam(tmp) );
return(TRUE);
}
if(Blind) pline("You hit it.");
else pline("You hit %s%s", monnam(mon), exclam(tmp));

if(u.umconf) {
if(!Blind) {
pline("Your hands stop glowing blue.");
if(!mon->mfroz && !mon->msleep)
pline("%s appears confused.",Monnam(mon));
}
mon->mconf = 1;
u.umconf = 0;
}
return(TRUE); /* mon still alive */
}

/* try to attack; return FALSE if monster evaded */
/* u.dx and u.dy must be set */
attack(mtmp)
register struct monst *mtmp;
{
schar tmp;
boolean malive = TRUE;
register struct permonst *mdat;
mdat = mtmp->data;

if(mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep &&
!mtmp->mconf && mtmp->mcansee && !rn2(7) &&
(m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */
mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy))
return(FALSE);

if(mtmp->mimic){
if(!u.ustuck && !mtmp->mflee) u.ustuck = mtmp;
switch(levl[u.ux+u.dx][u.uy+u.dy].scrsym){
case '+':
pline("The door actually was a Mimic.");
break;
case '$':
pline("The chest was a Mimic!");
break;
default:
pline("Wait! That's a Mimic!");
}
wakeup(mtmp); /* clears mtmp->mimic */
return(TRUE);
}

wakeup(mtmp);

if(mtmp->mhide && mtmp->mundetected){
register struct obj *obj;

mtmp->mundetected = 0;
if((obj = o_at(mtmp->mx,mtmp->my)) && !Blind)
pline("Wait! There's a %s hiding under %s!",
mdat->mname, doname(obj));
return(TRUE);
}

tmp = u.uluck + u.ulevel + mdat->ac + abon();
if(uwep) {
if(uwep->olet == WEAPON_SYM || uwep->otyp == PICK_AXE)
tmp += uwep->spe;
if(uwep->otyp == TWO_HANDED_SWORD) tmp -= 1;
else if(uwep->otyp == DAGGER) tmp += 2;
else if(uwep->otyp == CRYSKNIFE) tmp += 3;
else if(uwep->otyp == SPEAR &&
index("XDne", mdat->mlet)) tmp += 2;
}
if(mtmp->msleep) {
mtmp->msleep = 0;
tmp += 2;
}
if(mtmp->mfroz) {
tmp += 4;
if(!rn2(10)) mtmp->mfroz = 0;
}
if(mtmp->mflee) tmp += 2;
if(u.utrap) tmp -= 3;

/* with a lot of luggage, your agility diminishes */
tmp -= (inv_weight() + 40)/20;

if(tmp <= rnd(20) && !u.uswallow){
if(Blind) pline("You miss it.");
else pline("You miss %s.",monnam(mtmp));
} else {
/* we hit the monster; be careful: it might die! */

if((malive = hmon(mtmp,uwep,0)) == TRUE) {
/* monster still alive */
if(!rn2(25) && mtmp->mhp < mtmp->mhpmax/2) {
mtmp->mflee = 1;
if(!rn2(3)) mtmp->mfleetim = rnd(100);
if(u.ustuck == mtmp && !u.uswallow)
u.ustuck = 0;
}
#ifndef NOWORM
if(mtmp->wormno)
cutworm(mtmp, u.ux+u.dx, u.uy+u.dy,
uwep ? uwep->otyp : 0);
#endif NOWORM
}
if(mdat->mlet == 'a') {
if(rn2(2)) {
pline("You are splashed by the blob's acid!");
losehp_m(rnd(6), mtmp);
if(!rn2(30)) corrode_armor();
}
if(!rn2(6)) corrode_weapon();
}
}
if(malive && !Blind && !mtmp->minvis && mdat->mlet == 'E'
&& !mtmp->mcan && rn2(3)) {
if(mtmp->mcansee) {
pline("You are frozen by the floating eye's gaze!");
nomul((u.ulevel > 6 || rn2(4)) ? rn1(20,-21) : -200);
} else {
pline("The blinded floating eye cannot defend itself.");
if(!rn2(500)) u.uluck--;
}
}
return(TRUE);
}
//E*O*F hack.fight.c//

echo x - hack.invent.c
cat > "hack.invent.c" << '//E*O*F hack.invent.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.invent.c - version 1.0.2 */

#include "hack.h"
#include <stdio.h>
extern struct obj *splitobj();
extern struct obj zeroobj;
extern char morc;
extern char quitchars[];
char *xprname();
#ifndef NOWORM
#include "def.wseg.h"

extern struct wseg *wsegs[32];
#endif NOWORM

struct obj *
addinv(obj) register struct obj *obj; {
register struct obj *otmp;
for(otmp = invent; otmp; otmp = otmp->nobj) {
if(merged(otmp, obj, 0)) return(otmp);
if(!otmp->nobj) {
otmp->nobj = obj;
obj->nobj = 0;
return(obj);
}
}
invent = obj;
obj->nobj = 0;
return(obj);
}

useup(obj)
register struct obj *obj;
{
if(obj->quan > 1){
obj->quan--;
obj->owt = weight(obj);
} else {
setnotworn(obj);
freeinv(obj);
obfree(obj, (struct obj *) 0);
}
}

freeinv(obj) register struct obj *obj; {
register struct obj *otmp;
if(obj == invent) invent = invent->nobj;
else {
for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj)
if(!otmp->nobj) panic("freeinv");
otmp->nobj = obj->nobj;
}
}

/* destroy object in fobj chain (if unpaid, it remains on the bill) */
delobj(obj) register struct obj *obj; {
freeobj(obj);
unpobj(obj);
obfree(obj, (struct obj *) 0);
}

/* unlink obj from chain starting with fobj */
freeobj(obj) register struct obj *obj; {
register struct obj *otmp;

if(obj == fobj) fobj = fobj->nobj;
else {
for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj)
if(!otmp) panic("error in freeobj");
otmp->nobj = obj->nobj;
}
}

/* Note: freegold throws away its argument! */
freegold(gold) register struct gold *gold; {
register struct gold *gtmp;

if(gold == fgold) fgold = gold->ngold;
else {
for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold)
if(!gtmp) panic("error in freegold");
gtmp->ngold = gold->ngold;
}
free((char *) gold);
}

deltrap(trap)
register struct trap *trap;
{
register struct trap *ttmp;

if(trap == ftrap)
ftrap = ftrap->ntrap;
else {
for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
ttmp->ntrap = trap->ntrap;
}
free((char *) trap);
}

struct wseg *m_atseg;

struct monst *
m_at(x,y)
register x,y;
{
register struct monst *mtmp;
#ifndef NOWORM
register struct wseg *wtmp;
#endif NOWORM

m_atseg = 0;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
if(mtmp->mx == x && mtmp->my == y)
return(mtmp);
#ifndef NOWORM
if(mtmp->wormno){
for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg)
if(wtmp->wx == x && wtmp->wy == y){
m_atseg = wtmp;
return(mtmp);
}
}
#endif NOWORM
}
return(0);
}

struct obj *
o_at(x,y)
register x,y;
{
register struct obj *otmp;

for(otmp = fobj; otmp; otmp = otmp->nobj)
if(otmp->ox == x && otmp->oy == y) return(otmp);
return(0);
}

struct obj *
sobj_at(n,x,y)
register n,x,y;
{
register struct obj *otmp;

for(otmp = fobj; otmp; otmp = otmp->nobj)
if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)
return(otmp);
return(0);
}

carried(obj) register struct obj *obj; {
register struct obj *otmp;
for(otmp = invent; otmp; otmp = otmp->nobj)
if(otmp == obj) return(1);
return(0);
}

carrying(type)
register int type;
{
register struct obj *otmp;

for(otmp = invent; otmp; otmp = otmp->nobj)
if(otmp->otyp == type)
return(TRUE);
return(FALSE);
}

struct obj *
o_on(id, objchn) unsigned int id; register struct obj *objchn; {
while(objchn) {
if(objchn->o_id == id) return(objchn);
objchn = objchn->nobj;
}
return((struct obj *) 0);
}

struct trap *
t_at(x,y)
register x,y;
{
register struct trap *trap = ftrap;
while(trap) {
if(trap->tx == x && trap->ty == y) return(trap);
trap = trap->ntrap;
}
return(0);
}

struct gold *
g_at(x,y)
register x,y;
{
register struct gold *gold = fgold;
while(gold) {
if(gold->gx == x && gold->gy == y) return(gold);
gold = gold->ngold;
}
return(0);
}

/* make dummy object structure containing gold - for temporary use only */
struct obj *
mkgoldobj(q)
register long q;
{
register struct obj *otmp;

otmp = newobj(0);
/* should set o_id etc. but otmp will be freed soon */
otmp->olet = '$';
u.ugold -= q;
OGOLD(otmp) = q;
flags.botl = 1;
return(otmp);
}

/* getobj returns:
struct obj *xxx: object to do something with.
0 error return: no object.
&zeroobj explicitly no object (as in w-).
*/
struct obj *
getobj(let,word)
register char *let,*word;
{
register struct obj *otmp;
register char ilet,ilet1,ilet2;
char buf[BUFSZ];
char lets[BUFSZ];
register int foo = 0, foo2;
register char *bp = buf;
xchar allowcnt = 0; /* 0, 1 or 2 */
boolean allowgold = FALSE;
boolean allowall = FALSE;
boolean allownone = FALSE;
xchar foox = 0;
long cnt;

if(*let == '0') let++, allowcnt = 1;
if(*let == '$') let++, allowgold = TRUE;
if(*let == '#') let++, allowall = TRUE;
if(*let == '-') let++, allownone = TRUE;
if(allownone) *bp++ = '-';
if(allowgold) *bp++ = '$';
if(bp[-1] == '-') *bp++ = ' ';

ilet = 'a';
for(otmp = invent; otmp; otmp = otmp->nobj){
if(!*let || index(let, otmp->olet)) {
bp[foo++] = ilet;
/* ugly check: remove inappropriate things */
if((!strcmp(word, "take off") &&
!(otmp->owornmask & (W_ARMOR - W_ARM2)))
|| (!strcmp(word, "wear") &&
(otmp->owornmask & (W_ARMOR | W_RING)))
|| (!strcmp(word, "wield") &&
(otmp->owornmask & W_WEP))) {
foo--;
foox++;
}
}
if(ilet == 'z') ilet = 'A'; else ilet++;
}
bp[foo] = 0;
if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
(void) strcpy(lets, bp); /* necessary since we destroy buf */
if(foo > 5) { /* compactify string */
foo = foo2 = 1;
ilet2 = bp[0];
ilet1 = bp[1];
while(ilet = bp[++foo2] = bp[++foo]){
if(ilet == ilet1+1){
if(ilet1 == ilet2+1)
bp[foo2 - 1] = ilet1 = '-';
else if(ilet2 == '-') {
bp[--foo2] = ++ilet1;
continue;
}
}
ilet2 = ilet1;
ilet1 = ilet;
}
}
if(!foo && !allowall && !allowgold && !allownone) {
pline("You don't have anything %sto %s.",
foox ? "else " : "", word);
return(0);
}
for(;;) {
if(!buf[0])
pline("What do you want to %s [*]? ", word);
else
pline("What do you want to %s [%s or ?*]? ",
word, buf);

cnt = 0;
ilet = readchar();
while(digit(ilet) && allowcnt) {
cnt = 10*cnt + (ilet - '0');
allowcnt = 2; /* signal presence of cnt */
ilet = readchar();
}
if(digit(ilet)) {
pline("No count allowed with this command.");
continue;
}
if(index(quitchars,ilet))
return((struct obj *)0);
if(ilet == '-') {
return(allownone ? &zeroobj : (struct obj *) 0);
}
if(ilet == '$') {
if(!allowgold){
pline("You cannot %s gold.", word);
continue;
}
if(!(allowcnt == 2 && cnt < u.ugold))
cnt = u.ugold;
return(mkgoldobj(cnt));
}
if(ilet == '?') {
doinv(lets);
if(!(ilet = morc)) continue;
/* he typed a letter (not a space) to more() */
} else if(ilet == '*') {
doinv((char *) 0);
if(!(ilet = morc)) continue;
/* ... */
}
if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1;
ilet -= 'a';
for(otmp = invent; otmp && ilet; ilet--, otmp = otmp->nobj) ;
if(!otmp) {
pline("You don't have that object.");
continue;
}
if(cnt < 0 || otmp->quan < cnt) {
pline("You don't have that many! [You have %u]"
, otmp->quan);
continue;
}
break;
}
if(!allowall && let && !index(let,otmp->olet)) {
pline("That is a silly thing to %s.",word);
return(0);
}
if(allowcnt == 2) { /* cnt given */
if(cnt == 0) return(0);
if(cnt != otmp->quan) {
register struct obj *obj;
obj = splitobj(otmp, (int) cnt);
if(otmp == uwep) setuwep(obj);
}
}
return(otmp);
}

ckunpaid(otmp) register struct obj *otmp; {
return( otmp->unpaid );
}

/* interactive version of getobj - used for Drop and Identify */
/* return the number of times fn was called successfully */
ggetobj(word, fn, max)
char *word;
int (*fn)(), max;
{
char buf[BUFSZ];
register char *ip;
register char sym;
register int oletct = 0, iletct = 0;
register boolean allflag = FALSE;
char olets[20], ilets[20];
int (*ckfn)() = (int (*)()) 0;
xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */
if(!invent && !allowgold){
pline("You have nothing to %s.", word);
return(0);
} else {
register struct obj *otmp = invent;
register int uflg = 0;

if(allowgold) ilets[iletct++] = '$';
ilets[iletct] = 0;
while(otmp) {
if(!index(ilets, otmp->olet)){
ilets[iletct++] = otmp->olet;
ilets[iletct] = 0;
}
if(otmp->unpaid) uflg = 1;
otmp = otmp->nobj;
}
ilets[iletct++] = ' ';
if(uflg) ilets[iletct++] = 'u';
if(invent) ilets[iletct++] = 'a';
ilets[iletct] = 0;
}
pline("What kinds of thing do you want to %s? [%s] ",
word, ilets);
getlin(buf);
ip = buf;
olets[0] = 0;
while(sym = *ip++){
if(sym == ' ') continue;
if(sym == '$') {
if(allowgold == 1)
(*fn)(mkgoldobj(u.ugold));
else if(!u.ugold)
pline("You have no gold.");
allowgold = 2;
} else
if(sym == 'a') allflag = TRUE; else
if(sym == 'u') ckfn = ckunpaid; else
if(index("!%?[()=*/\"0", sym)){
if(!index(olets, sym)){
olets[oletct++] = sym;
olets[oletct] = 0;
}
}
else pline("You don't have any %c's.", sym);
}
if(allowgold == 2 && !oletct)
return(1); /* he dropped gold (or at least tried to) */
else
return(askchain(invent, olets, allflag, fn, ckfn, max));
}

/*
* Walk through the chain starting at objchn and ask for all objects
* with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL)
* whether the action in question (i.e., fn) has to be performed.
* If allflag then no questions are asked. Max gives the max nr of
* objects to be treated. Return the number of objects treated.
*/
askchain(objchn, olets, allflag, fn, ckfn, max)
struct obj *objchn;
register char *olets;
int allflag;
int (*fn)(), (*ckfn)();
int max;
{
register struct obj *otmp, *otmp2;
register char sym, ilet;
register int cnt = 0;
ilet = 'a'-1;
for(otmp = objchn; otmp; otmp = otmp2){
if(ilet == 'z') ilet = 'A'; else ilet++;
otmp2 = otmp->nobj;
if(olets && *olets && !index(olets, otmp->olet)) continue;
if(ckfn && !(*ckfn)(otmp)) continue;
if(!allflag) {
pline(xprname(otmp, ilet));
addtopl(" [nyaq]? ");
sym = readchar();
}
else sym = 'y';

switch(sym){
case 'a':
allflag = 1;
case 'y':
cnt += (*fn)(otmp);
if(--max == 0) goto ret;
case 'n':
default:
break;
case 'q':
goto ret;
}
}
pline(cnt ? "That was all." : "No applicable objects.");
ret:
return(cnt);
}

obj_to_let(obj)
register struct obj *obj;
{
register struct obj *otmp;
register char ilet = 'a';

for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj)
if(++ilet > 'z') ilet = 'A';
return(otmp ? ilet : 0);
}

prinv(obj)
register struct obj *obj;
{
pline(xprname(obj, obj_to_let(obj)));
}

static char *
xprname(obj,let)
register struct obj *obj;
register char let;
{
static char li[BUFSZ];

(void) sprintf(li, "%c - %s.", let, doname(obj));
return(li);
}

ddoinv()
{
doinv((char *) 0);
return(0);
}

/* called with 0 or "": all objects in inventory */
/* otherwise: all objects with (serial) letter in lets */
doinv(lets)
register char *lets;
{
register struct obj *otmp;
register char ilet;
int ct = 0;
char any[BUFSZ];

morc = 0; /* just to be sure */

if(!invent){
pline("Not carrying anything.");
return;
}

cornline(0, (char *) 0);
ilet = 'a';
for(otmp = invent; otmp; otmp = otmp->nobj) {
if(!lets || !*lets || index(lets, ilet)) {
cornline(1, xprname(otmp, ilet));
any[ct++] = ilet;
}
if(++ilet > 'z') ilet = 'A';
}
any[ct] = 0;
cornline(2, any);
}

dotypeinv () /* free after Robert Viduya */
/* Changed to one type only, so he doesnt have to type cr */
{
char c, ilet;
char stuff[BUFSZ];
register int stct;
register struct obj *otmp;
boolean billx = inshop() && doinvbill(0);
boolean unpd = FALSE;

if (!invent && !u.ugold && !billx) {
pline ("You aren't carrying anything.");
return(0);
}

stct = 0;
if(u.ugold) stuff[stct++] = '$';
stuff[stct] = 0;
for(otmp = invent; otmp; otmp = otmp->nobj) {
if (!index (stuff, otmp->olet)) {
stuff[stct++] = otmp->olet;
stuff[stct] = 0;
}
if(otmp->unpaid)
unpd = TRUE;
}
if(unpd) stuff[stct++] = 'u';
if(billx) stuff[stct++] = 'x';
stuff[stct] = 0;

if(stct > 1) {
pline ("What type of object [%s] do you want an inventory of? ",
stuff);
c = readchar();
if(index(quitchars,c)) return(0);
} else
c = stuff[0];

if(c == '$')
return(doprgold());

if(c == 'x') {
if(billx)
(void) doinvbill(1);
else
pline("No used-up objects on the shopping bill.");
return(0);
}

if(c == 'u' && !unpd) {
pline("You are not carrying any unpaid objects.");
return(0);
}

stct = 0;
ilet = 'a';
for (otmp = invent; otmp; otmp = otmp -> nobj) {
if (c == otmp -> olet || (c == 'u' && otmp -> unpaid))
stuff[stct++] = ilet;
if (ilet == 'z')
ilet = 'A';
else
ilet++;
}
stuff[stct] = '\0';
if(stct == 0)
pline("You have no such objects.");
else
doinv (stuff);

return(0);
}

/* look at what is here */
dolook() {
register struct obj *otmp, *otmp0;
register struct gold *gold;
char *verb = Blind ? "feel" : "see";
int ct = 0;

if(!u.uswallow) {
otmp0 = o_at(u.ux, u.uy);
gold = g_at(u.ux, u.uy);
}
if(u.uswallow || (!otmp0 && !gold)) {
pline("You %s no objects here.", verb);
return(!!Blind);
}

if(Blind) pline("You try to feel what is lying here on the floor.");
cornline(0, "Things that are here:");
for(otmp = otmp0; otmp; otmp = otmp->nobj) {
if(otmp->ox == u.ux && otmp->oy == u.uy) {
ct++;
cornline(1, doname(otmp));
if(Blind && otmp->otyp == DEAD_COCKATRICE && !uarmg) {
pline("Touching the dead cockatrice is a fatal mistake ...");
pline("You die ...");
killer = "dead cockatrice";
done("died");
}
}
}

if(gold) {
char gbuf[30];

(void) sprintf(gbuf, "%ld gold piece%s",
gold->amount, plur(gold->amount));
if(!ct++)
pline("You %s here %s.", verb, gbuf);
else
cornline(1, gbuf);
}

if(ct == 1 && !gold) {
pline("You %s here %s.", verb, doname(otmp0));
cornline(3, (char *) 0);
}
if(ct > 1)
cornline(2, (char *) 0);
return(!!Blind);
}

stackobj(obj) register struct obj *obj; {
register struct obj *otmp = fobj;
for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj)
if(otmp->ox == obj->ox && otmp->oy == obj->oy &&
merged(obj,otmp,1))
return;
}

/* merge obj with otmp and delete obj if types agree */
merged(otmp,obj,lose) register struct obj *otmp, *obj; {
if(otmp->otyp == obj->otyp &&
obj->unpaid == otmp->unpaid && obj->spe == otmp->spe &&
obj->known == otmp->known && obj->dknown == otmp->dknown &&
obj->cursed == otmp->cursed &&
((obj->olet == WEAPON_SYM && obj->otyp < BOOMERANG)
|| index("%?!*",otmp->olet))){
otmp->quan += obj->quan;
otmp->owt += obj->owt;
if(lose) freeobj(obj);
obfree(obj,otmp); /* free(obj), bill->otmp */
return(1);
} else return(0);
}

/*
* Gold is no longer displayed; in fact, when you have a lot of money,
* it may take a while before you have counted it all.
* [Bug: d$ and pickup still tell you how much it was.]
*/
extern int (*occupation)();
extern char *occtxt;
static long goldcounted;

countgold(){
if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) {
long eps = 0;
if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1));
pline("You probably have about %ld gold pieces.",
u.ugold + eps);
return(0); /* done */
}
return(1); /* continue */
}

doprgold(){
if(!u.ugold)
pline("You do not carry any gold.");
else if(u.ugold <= 500)
pline("You are carrying %ld gold pieces.", u.ugold);
else {
pline("You sit down in order to count your gold pieces.");
goldcounted = 500;
occupation = countgold;
occtxt = "counting your gold";
}
return(1);
}

/* --- end of gold counting section --- */

doprwep(){
if(!uwep) pline("You are empty handed.");
else prinv(uwep);
return(0);
}

doprarm(){
if(!uarm && !uarmg && !uarms && !uarmh)
pline("You are not wearing any armor.");
else {
char lets[6];
register int ct = 0;

if(uarm) lets[ct++] = obj_to_let(uarm);
if(uarm2) lets[ct++] = obj_to_let(uarm2);
if(uarmh) lets[ct++] = obj_to_let(uarmh);
if(uarms) lets[ct++] = obj_to_let(uarms);
if(uarmg) lets[ct++] = obj_to_let(uarmg);
lets[ct] = 0;
doinv(lets);
}
return(0);
}

doprring(){
if(!uleft && !uright)
pline("You are not wearing any rings.");
else {
char lets[3];
register int ct = 0;

if(uleft) lets[ct++] = obj_to_let(uleft);
if(uright) lets[ct++] = obj_to_let(uright);
lets[ct] = 0;
doinv(lets);
}
return(0);
}

digit(c) char c; {
return(c >= '0' && c <= '9');
}
//E*O*F hack.invent.c//

echo x - hack.ioctl.c
cat > "hack.ioctl.c" << '//E*O*F hack.ioctl.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.ioctl.c - version 1.0.2 */

/* This cannot be part of hack.tty.c (as it was earlier) since on some
systems (e.g. MUNIX) the include files <termio.h> and <sgtty.h>
define the same constants, and the C preprocessor complains. */
#include <stdio.h>
#include "config.h"
#ifdef BSD
#include <sgtty.h>
struct ltchars ltchars, ltchars0;
#else
#include <termio.h> /* also includes part of <sgtty.h> */
struct termio termio;
#endif BSD

getioctls() {
#ifdef BSD
(void) ioctl(fileno(stdin), (int) TIOCGLTC, (char *) &ltchars);
(void) ioctl(fileno(stdin), (int) TIOCSLTC, (char *) &ltchars0);
#else
(void) ioctl(fileno(stdin), (int) TCGETA, &termio);
#endif BSD
}

setioctls() {
#ifdef BSD
(void) ioctl(fileno(stdin), (int) TIOCSLTC, (char *) &ltchars);
#else
(void) ioctl(fileno(stdin), (int) TCSETA, &termio);
#endif BSD
}

#ifdef SUSPEND /* implies BSD */
dosuspend() {
#include <signal.h>
#ifdef SIGTSTP
if(signal(SIGTSTP, SIG_IGN) == SIG_DFL) {
settty((char *) 0);
(void) signal(SIGTSTP, SIG_DFL);
(void) kill(0, SIGTSTP);
gettty();
setftty();
docrt();
} else {
pline("I don't think your shell has job control.");
}
#else SIGTSTP
pline("Sorry, it seems we have no SIGTSTP here. Try ! or S.");
#endif SIGTSTP
return(0);
}
#endif SUSPEND
//E*O*F hack.ioctl.c//

exit 0

0 new messages