# 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 #include #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; ipoints != 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 *) <h, 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 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 and define the same constants, and the C preprocessor complains. */ #include #include "config.h" #ifdef BSD #include struct ltchars ltchars, ltchars0; #else #include /* also includes part of */ struct termio termio; #endif BSD getioctls() { #ifdef BSD (void) ioctl(fileno(stdin), (int) TIOCGLTC, (char *) <chars); (void) ioctl(fileno(stdin), (int) TIOCSLTC, (char *) <chars0); #else (void) ioctl(fileno(stdin), (int) TCGETA, &termio); #endif BSD } setioctls() { #ifdef BSD (void) ioctl(fileno(stdin), (int) TIOCSLTC, (char *) <chars); #else (void) ioctl(fileno(stdin), (int) TCSETA, &termio); #endif BSD } #ifdef SUSPEND /* implies BSD */ dosuspend() { #include #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