#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh README.OLD <<'END_OF_README.OLD' X NetHack V1.0 README X X This file contains information on NetHack, it's history, features, Xand installation proceedures. X X For a detailed history of the game, see the README.ORIG file, which Xcontains three separate readme files, dating back to the original release of Xthe game (then named hack) by Jay Fenlason. X X History: X ========== X X NetHack is the product of literally dozens of people's work. I have Xa list of *some* of those who made major additions to the game which appears Xbelow: X XJay Fenlason wrote the original release of "Hack", with help from X Kenny Woodland, Mike Thome and Jon Payne. X XAndries Brouwer did a major re-write on the program and publshed (at least) X two versions to the Usenet. X XDon Kneller ported the 1.0.3 version of Hack to the PC, creating PC-Hack. X X The following folks didn't actually re-write the game, or port it to Xa new machine, but have made significant contributions to the playability of Xthe game: X Xins_akaa@jhunix.UUCP (Ken Arromdee) X X New character classes. X New weapons code. X Armor weights implemented. X New tools code. X Polymorph self code. X additional bug fixes. X Xsrt@ucla-cs (Scott R. Turner) X X Rockmole & Keystone Kops code. X Squeeky Board & Magic traps. X Fountain code. X more bug fixes. X Xgil@cornell.UUCP (Gil Neiger) X X Magic Marker code. X Fountain code enhancements. X Enhancements to dozens of routines. X more bug fixes (esp. in hack.zap.c) X Xericb@hplsla.UUCP (Eric Backus) X X #dip mods to fountain code. X yet more bug fixes. X X As for myself, I have added new character classes and traps, the XThrone Room, spellbooks and spellcasting, implemented code for praying and Xmade some enhancements to the endgame. X X NetHack is an integrated version of two major "flavors" of Hack, XUnix and PC Hack. It is designed so that you should be able to compile it Xin either one of the target enviornments. The filenames of all modules have Xbeen modified to correspond with the PC-Hack standards implemented by Don XKneller. X X config.h X ========== X X As distributed, it is set up to compile on my machine (a Pyramid 98xe Xin the Berkeley universe). Due to the large number of "features" in NetHack, Xthe config file (config.h) is used to select the target options. X X Here is a list of the currently supported options: X XSPELLS Spell casting code XPRAYERS Prayer code XKAA Various changes made by Ken Arromdee XMARKER Magic marker modification XNEWCLASS New classes, traps, and Throne Rooms. XSAFE_ATTACK Safe attack code XPROBING Wand of probing code XDIAGS Diagnostics after death/quit XSORTING Sorted inventory XDGK Additional features by Don Kneller (PC specific) XDGKMOD Additional features by Don Kneller (Non-PC specific) XREDO support for redoing last command XHARD Enhanced wizard code among other things. XNEWTRAPS Magic and Squeeky board traps XFREEHAND Cannot use Pick-axe without wielding it. XSPIDERS Spiders and webs XFOUNTAINS Fountain code XKOPS Keystone Kops XROCKMOLE Rockmoles X XStatus Line options: X XGOLD_ON_BOTL XEXP_ON_BOTL X X In a number of cases, code written for one specific version of Hack Xor another was separated out and given it's own designation (eg. REDO has Xbeen moved out of DGKMOD which was moved out of DGK from PC-HACK). X X Some New Features: X ==================== X X Some of the old code (eg. KOPS) has been enhanced to allow for more Xfunctionality. Here's a couple of examples - you can find out the rest for Xyourself in the traditional Hack style :-) X X Kops now throw cream pies (thank/blame KAA for the suggestion). X X The wizard may not stay dead!!! X X There are a couple of new types of demons. X X Demons may not be aggressive. X X There are lots more of these little gems, with sufficient hints in Xvarious fortune cookies to give away enough clues. X X Makefiles: X ============ X X The Unix "Makefile" has been enhanced to make installation cleaner Xand also to allow "initialization" of the play directories (WARNING: this Xwill destroy old score files!!!). The PC Makefile hasn't been upgraded in Xthis respect. X X The program "makedefs" has been modified in order to allow limited Xuse of "#ifdef/#else/#endif" sets in objects.h. Makedefs will only generate Xone #define for any number of ocurrences of a given object name string. In Xaddition, "makedefs" also generates alternate defines for "DEAD_xxxxx" in Xthose cases where a monster has been given an alternate identity. X X Makedefs has also been modified in order that it may be used to Xinitialize the following variable def files: X X objects.h -o option, see above. X trap.h -t option, trap type defines. X date.h -d option, date string. X data -D option, optional monster names. X rumors -r option, optional rumor addition. X X To compile the program on any 4.n or Sys V system, you should only Xneed to copy "Makefile.unix" to "Makefile", set up "Makefile" and "config.h", Xthen type "make". On a Xenix system, use "Makefile.xenix" and similarly set Xup "Makefile" and "config.h", with "STUPID" defined. At this point in time, XI can get the Xenix version to build, but it will immediately dump core on Xinvocation. X X Known Problems: X ================= X X There are several known problem areas and deficiencies in the code Xwhich I haven't yet addressed, prefering to get the really fatal bugs out of Xthe way. Here's a short list of things someone out there might want to work Xon (and it is by no means complete): X X - The WALKIES code is really crude. Fido get's mnexto()'d you when X he gets out of the effective leash range. I haven't yet been able X to integrate leashed movement into dogmove(). You might just want X to comment out the #define in config.h. X X - ROCKMOLES have some problems with screen updating. I didn't make X any changes to the code I received, and have noticed some distinct X problems with walls not being set to "door" until the rockmole X moves off the cell. X X - There are some problems in the item selection code, the usual effect X of which is to leave the cursor sitting at some arbitrary point on X the screen instead of returning it to the upper left hand corner or X onto the "@". This doesn't affect the screen updating, so I have X ignored it up to now. X X - REDO may not be completely implemented. I am still working on it X here but would appreciate any help anyone out there might want to X give. X X I fully expect that about one week's worth of play on the net will Xresult in a couple dozen bugs being discovered. I would like to keep a lid Xon the potential explosion of different sub-versions of the game, so if you Xpossibly can, please send me the bug reports, instead of releasing them to Xthe general public. I will apply them to my code here, and will generate an Xupdate to the release when the mass of fixes (or mass * severity factor) gets Xlarge enough. This way, we should be able to keep most of the net up to a Xcertain level - this may turn out to be the first truely net maintained Xgame. Unless circumstances change, I will continue to consolidate fixes and Xmodifications to the game, and will continue to post to the net through Xcomp.sources.games, with notices of new patches/fixes/mods going out through Xrec.games.hack. X X Making Bug Reports: X ===================== X X To send bug reports, just E-Mail me at any one of the following net Xaddresses (in order of connectivity): X X seismo!mnetor!genat!mike X utzoo!mnetor!genat!mike X pyramid!pyrnj!genat!mike X utzoo!utgpu!genat!mike X X When you send in a bug report, please keep your code fragments as Xsmall as possible. Remember that each site along the way is paying for the Xtransmission of the code. X X Mike Stephenson X XMail: Genamation Inc. Phone: (416) 475-9434 X 351 Steelcase Rd. W X Markham, Ontario. UUCP: {seismo, utzoo}!mnetor!genat!mike X Canada L3R 3W1 END_OF_README.OLD if test 7714 -ne `wc -c engrave.c <<'END_OF_engrave.c' X/* SCCS Id: @(#)engrave.c 2.3 88/02/11 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include "hack.h" X Xextern char *nomovemsg; Xextern char nul[]; Xextern struct obj zeroobj; X#ifdef KAA Xextern char *xname(); X#endif Xstruct engr { X struct engr *nxt_engr; X char *engr_txt; X xchar engr_x, engr_y; X unsigned engr_lth; /* for save & restore; not length of text */ X long engr_time; /* moment engraving was (will be) finished */ X xchar engr_type; X#define DUST 1 X#define ENGRAVE 2 X#define BURN 3 X#ifdef MARKER X#define MARK 4 X#define POLY 5 /* temporary type - for polymorphing engraving */ X#else X#define POLY 4 /* temporary type - for polymorphing engraving */ X#endif X} *head_engr; X X/* random engravings */ X#ifdef KAA Xchar *random_engr[] = X#else Xchar random_engr[][30] = X#endif X {"Elbereth", "ad ae?ar um", X#ifdef NEWCLASS X "?la? ?as he??", X#endif X /* more added by Eric Backus */ X "?ilroy wa? h?re", "?ala??iel", "Aba?don H?pe...", X "Fo? a ?ood time c?ll 6?6-4311"}; X#ifdef NEWCLASS X#define RAND_ENGRS 7 X#else X#define RAND_ENGRS 6 X#endif X Xstruct engr * Xengr_at(x,y) register xchar x,y; { Xregister struct engr *ep = head_engr; X while(ep) { X if(x == ep->engr_x && y == ep->engr_y) X return(ep); X ep = ep->nxt_engr; X } X return((struct engr *) 0); X} X Xsengr_at(s,x,y) register char *s; register xchar x,y; { Xregister struct engr *ep = engr_at(x,y); Xregister char *t; Xregister int n; X if(ep && ep->engr_time <= moves) { X t = ep->engr_txt; X/* X if(!strcmp(s,t)) return(1); X*/ X n = strlen(s); X while(*t) { X if(!strncmp(s,t,n)) return(1); X t++; X } X } X return(0); X} X Xu_wipe_engr(cnt) Xregister int cnt; X{ X if(!u.uswallow && !Levitation) X wipe_engr_at(u.ux, u.uy, cnt); X} X Xwipe_engr_at(x,y,cnt) register xchar x,y,cnt; { Xregister struct engr *ep = engr_at(x,y); Xregister int lth,pos; Xchar ch; X if(ep){ X if(ep->engr_type != BURN) { X if(ep->engr_type != DUST) { X cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; X } X lth = strlen(ep->engr_txt); X if(lth && cnt > 0 ) { X while(cnt--) { X pos = rn2(lth); X if((ch = ep->engr_txt[pos]) == ' ') X continue; X ep->engr_txt[pos] = (ch != '?') ? '?' : ' '; X } X } X while(lth && ep->engr_txt[lth-1] == ' ') X ep->engr_txt[--lth] = 0; X while(ep->engr_txt[0] == ' ') X ep->engr_txt++; X if(!ep->engr_txt[0]) del_engr(ep); X } X } X} X Xread_engr_at(x,y) register int x,y; { Xregister struct engr *ep = engr_at(x,y); Xregister int canfeel; X if(ep && ep->engr_txt[0]) { X switch(ep->engr_type) { X case DUST: X if(!Blind) pline("Something is written here in the dust."); X canfeel = 0; X break; X case ENGRAVE: X pline("Something is engraved here on the floor."); X canfeel = 1; X break; X case BURN: X pline("Some text has been burned here in the floor."); X canfeel = 1; X break; X#ifdef MARKER X case MARK: X if(!Blind) pline("There's some graffiti here on the floor."); X canfeel = 0; X break; X#endif X default: X impossible("Something is written in a very strange way."); X canfeel = 1; X } X if (canfeel || !Blind) X pline("You %s: \"%s\".", X (Blind) ? "feel the words" : "read", ep->engr_txt); X } X} X Xmake_engr_at(x,y,s) Xregister int x,y; Xregister char *s; X{ X register struct engr *ep; X X if(ep = engr_at(x,y)) X del_engr(ep); X ep = (struct engr *) X alloc((unsigned)(sizeof(struct engr) + strlen(s) + 1)); X ep->nxt_engr = head_engr; X head_engr = ep; X ep->engr_x = x; X ep->engr_y = y; X ep->engr_txt = (char *)(ep + 1); X (void) strcpy(ep->engr_txt, s); X ep->engr_time = 0; X ep->engr_type = DUST; X ep->engr_lth = strlen(s) + 1; X} X/* X * freehand - returns true if player has a free hand X */ Xint Xfreehand(){ X X return(!uwep || X !uwep->cursed || X (uwep->otyp != TWO_HANDED_SWORD && (!uarms || !uarms->cursed))); X/* if ((uwep && uwep->otyp == TWO_HANDED_SWORD) || X (uwep && uarms)) X return(0); X else X return(1);*/ X} X X X Xdoengrave(){ Xregister int len, tmp; Xregister char *sp, *sptmp; Xregister struct engr *ep, *oep = engr_at(u.ux,u.uy); Xchar buf[BUFSZ]; Xxchar type; Xint spct; /* number of leading spaces */ Xregister struct obj *otmp; X multi = 0; X X if(u.uswallow) { X pline("You're joking. Hahaha!"); /* riv05!a3 */ X return(0); X } X X /* one may write with finger, weapon or wand */ X /* edited by GAN 10/20/86 so as not to change X * weapon wielded. X */ X otmp = getobj("#-()/", "write with"); X if(!otmp) return(0); X X#ifdef FREEHAND /* There's no reason you should be able to write with a wand X * while both your hands are tied up. Also, it's necessary to X * prevent engraving with "worn" objects other than weapons. X */ X if (!freehand() && otmp != uwep) { X#else X /* added by GAN 10/20/86 to require you to need a hand to X write with. X */ X if(!(otmp->owornmask || otmp->olet == WAND_SYM) && !freehand()) { X#endif X pline("You have no free hand to write with!"); X return(0); X } X#ifdef KAA X if (cantwield(u.usym)) { X pline("You can't even hold anything!"); X return(0); X } X if(otmp != &zeroobj && index("][0`",otmp->olet)) { X pline("You can't engrave with such a large object!"); X return(1); X } X#endif X X if(Levitation && otmp->olet != WAND_SYM){ /* riv05!a3 */ X pline("You can't reach the floor!"); X return(0); X } X X if(otmp == &zeroobj) { X pline("You write in the dust with your fingers."); X type = DUST; X } else if(otmp->olet == WAND_SYM && zappable(otmp)) { X /* changed so any wand gets zapped out, but fire X * wands become known. X */ X if((objects[otmp->otyp].bits & NODIR)) { X zapnodir(otmp); X type = DUST; X } else { X switch(otmp->otyp) { X case WAN_LIGHTNING: X if(!objects[otmp->otyp].oc_name_known) { X pline("The %s is a wand of lightning!", X xname(otmp)); X objects[otmp->otyp].oc_name_known = 1; X more_experienced(0,10); X } X type = BURN; X break; X case WAN_FIRE: X if(!objects[otmp->otyp].oc_name_known) { X pline("The %s is a wand of fire!", X xname(otmp)); X objects[otmp->otyp].oc_name_known = 1; X more_experienced(0,10); X } X type = BURN; X break; X case WAN_DIGGING: X if(!objects[otmp->otyp].oc_name_known) { X pline("The %s is a wand of digging!", X xname(otmp)); X objects[otmp->otyp].oc_name_known = 1; X more_experienced(0,10); X } X type = ENGRAVE; X break; X case WAN_POLYMORPH: X if(oep) { X del_engr(oep); X oep = 0; X type = POLY; X } else X type = DUST; X break; X case WAN_COLD: X type = DUST; X if(!oep || (oep->engr_type != BURN)) X break; X case WAN_CANCELLATION: X case WAN_MAKE_INVISIBLE: X if(!oep) { /* Eric Backus */ X type = DUST; X break; X } X del_engr(oep); X pline("The engraving on the floor vanishes!"); X return(1); X break; X case WAN_TELEPORTATION: X if(!oep) X type = DUST; X else { X register tx,ty; X X do { X tx = rn1(COLNO-3,2); X ty = rn2(ROWNO); X } while(!goodpos(tx,ty)); X oep->engr_x = tx; X oep->engr_y = ty; X pline("The engraving on the floor vanishes!"); X return(1); X } X break; X default: X type = DUST; X } X } X if(type == DUST) X pline("You write in the dust with %s.", X doname(otmp)); X X } else { X if(otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD || X otmp->otyp == CRYSKNIFE || otmp->otyp == KATANA || X otmp->otyp == SCIMITAR || otmp->otyp == BROAD_SWORD || X otmp->otyp == SHORT_SWORD || X otmp->otyp == LONG_SWORD || otmp->otyp == AXE) { X type = ENGRAVE; X if((int)otmp->spe <= -3) { X pline("Your %s too dull for engraving.", X aobjnam(otmp, "are")); X type = DUST; X /* following messaged added 10/20/86 - GAN */ X pline("You write in the dust with %s.", X doname(otmp)); X } else X pline("You engrave with %s.", doname(otmp)); X#ifdef MARKER X } else if(otmp->otyp == MAGIC_MARKER) { X if(otmp->spe <= 0) { X pline("Your marker is dried out."); X pline("You write in the dust with the marker."); X type = DUST; X } else { X pline("You write with %s.", doname(otmp)); X type = MARK; X } X#endif X } else { X pline("You write in the dust with %s.", X doname(otmp)); X type = DUST; X } X } X X if(type != POLY && oep && oep->engr_type == DUST){ X pline("You wipe out the message that was written here."); X del_engr(oep); X oep = 0; X } X if(type == DUST && oep){ X pline("You cannot wipe out the message that is %s in the rock.", X (oep->engr_type == BURN) ? "burned" : (oep->engr_type == ENGRAVE)? "engraved" : "scribbled"); X return(1); X } X if(type == POLY) { X#ifdef MARKER X type = rnd(4); X#else X type = rnd(3); X#endif X strcpy(buf,random_engr[rn2(RAND_ENGRS)]); X switch(type){ X case DUST: X pline("\"%s\" is now written on the ground.",buf); X break; X case ENGRAVE: X pline("\"%s\" is now engraved in the rock.",buf); X break; X case BURN: X pline("\"%s\" is now burned in the rock.",buf); X break; X#ifdef MARKER X case MARK: X pline("\"%s\" is now scribbled on the rock.",buf); X break; X#endif X default: X impossible("\"%s\" is now written in a very strange way.", X buf); X } X } else { X pline("What do you want to %s on the floor here? ", X (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write"); X getlin(buf); X clrlin(); X } X spct = 0; X sp = buf; X while(*sp == ' ') spct++, sp++; X len = strlen(sp); X if(!len || *buf == '\033') { X /* changed by GAN 11/01/86 to not recharge wand */ X return(1); X } X if(otmp->otyp == WAN_FIRE) { X if (!Blind) pline("Flames fly from the wand."); X else pline("You feel the wand heat up."); X } else if(otmp->otyp == WAN_LIGHTNING) { X if (!Blind) { X pline("Sparks fly from the wand."); X pline("You are blinded by the flashing!"); X Blinded += rnd(50); X seeoff(0); X } else pline("You hear crackling!"); X } else if(otmp->otyp == WAN_DIGGING) { X if (!Blind) pline("Gravel flies up from the floor."); X else pline("You hear drilling!"); X } X /* kludge by stewr 870708 */ X for (sptmp = sp, tmp=0; !(tmp == len); sptmp++,tmp++) { X if (((type == DUST) && !rn2(25)) X || (Blind && !rn2(12)) X || (Confusion && !rn2(3))) { X *sptmp = '!' + rn2(93); /* ASCII-code only */ X } X } X X switch(type) { X case DUST: X case BURN: X if(len > 15) { X multi = -(len/10); X nomovemsg = "You finished writing."; X } X break; X case ENGRAVE: X#ifdef MARKER X case MARK: X { int len2; X X if(type == ENGRAVE) X len2 = (otmp->spe + 3) * 2 + 1; X else X len2 = (otmp->spe) * 2; X nomovemsg = "You finished writing."; X if(type != MARK) X#else X { int len2 = (otmp->spe + 3) * 2 + 1; X#endif X nomovemsg = "You finished engraving."; X if(otmp->olet != WAND_SYM) { X if(otmp->olet == WEAPON_SYM) X pline("Your %s dull.", X aobjnam(otmp, "get")); X if(len2 < len) { X len = len2; X sp[len] = 0; X if(type == ENGRAVE) { X otmp->spe = -3; X } else { X pline("Your marker dries out!"); X otmp->spe = 0; X } X /* next line added by GAN 10/20/86 */ X pline("You only write \"%s\".", sp); X nomovemsg = "You cannot write more."; X } else X otmp->spe -= len/2; X#ifdef MARKER X if(type == MARK) X multi = -(len/10); X else X#endif X multi = -len; X } else X multi = -(len/10); X } X break; X } X if(oep) len += strlen(oep->engr_txt) + spct; X ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1)); X ep->nxt_engr = head_engr; X head_engr = ep; X ep->engr_x = u.ux; X ep->engr_y = u.uy; X sp = (char *)(ep + 1); /* (char *)ep + sizeof(struct engr) */ X ep->engr_txt = sp; X if(oep) { X (void) strcpy(sp, oep->engr_txt); X (void) strcat(sp, buf); X del_engr(oep); X } else X (void) strcpy(sp, buf); X ep->engr_lth = len+1; X ep->engr_type = type; X ep->engr_time = moves-multi; X X /* kludge to protect pline against excessively long texts */ X if(len > BUFSZ-20) sp[BUFSZ-20] = 0; X X /* cute messages for odd wands */ X switch(otmp->otyp) { X case WAN_SLOW_MONSTER: X pline("The bugs on the ground slow down!"); X break; X case WAN_SPEED_MONSTER: X pline("The bugs on the ground speed up!"); X break; X case WAN_MAGIC_MISSILE: X pline("The ground is riddled by bullet holes!"); X break; X case WAN_SLEEP: X case WAN_DEATH: /* can't tell sleep from death - Eric Backus */ X pline("The bugs on the ground stop moving!"); X break; X case WAN_COLD: X pline("A few ice cubes drop from your %s.",xname(otmp)); X break; X case WAN_STRIKING: X pline("The %s unsuccessfully fights your attempt to write!",xname(otmp)); X } X X return(1); X} X Xsave_engravings(fd) int fd; { Xregister struct engr *ep = head_engr; X while(ep) { X if(!ep->engr_lth || !ep->engr_txt[0]){ X ep = ep->nxt_engr; X continue; X } X bwrite(fd, (char *) & (ep->engr_lth), sizeof(ep->engr_lth)); X bwrite(fd, (char *) ep, sizeof(struct engr) + ep->engr_lth); X ep = ep->nxt_engr; X } X bwrite(fd, (char *) nul, sizeof(unsigned)); X#ifdef DGK X if (!count_only) X#endif X head_engr = 0; X} X Xrest_engravings(fd) int fd; { Xregister struct engr *ep; Xunsigned lth; X head_engr = 0; X while(1) { X mread(fd, (char *) <h, sizeof(unsigned)); X if(lth == 0) return; X ep = (struct engr *) alloc(sizeof(struct engr) + lth); X mread(fd, (char *) ep, sizeof(struct engr) + lth); X ep->nxt_engr = head_engr; X ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */ X head_engr = ep; X } X} X Xdel_engr(ep) register struct engr *ep; { Xregister struct engr *ept; X if(ep == head_engr) X head_engr = ep->nxt_engr; X else { X for(ept = head_engr; ept; ept = ept->nxt_engr) { X if(ept->nxt_engr == ep) { X ept->nxt_engr = ep->nxt_engr; X goto fnd; X } X } X impossible("Error in del_engr?"); X return; X fnd: ; X } X free((char *) ep); X} END_OF_engrave.c if test 13501 -ne `wc -c objnam.c <<'END_OF_objnam.c' X/* SCCS Id: @(#)objnam.c 2.3 88/01/21 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include "hack.h" X#define Sprintf (void) sprintf X#define Strcat (void) strcat X#define Strcpy (void) strcpy X#define PREFIX 15 Xextern char *eos(); Xextern int bases[]; X Xchar * Xstrprepend(s,pref) register char *s, *pref; { Xregister int i = strlen(pref); X if(i > PREFIX) { X pline("WARNING: prefix too short."); X return(s); X } X s -= i; X (void) strncpy(s, pref, i); /* do not copy trailing 0 */ X return(s); X} X Xchar * Xsitoa(a) int a; { Xstatic char buf[13]; X Sprintf(buf, (a < 0) ? "%d" : "+%d", a); X return(buf); X} X Xchar * Xtypename(otyp) Xregister int otyp; X{ Xstatic char buf[BUFSZ]; Xregister struct objclass *ocl = &objects[otyp]; Xregister char *an = ocl->oc_name; Xregister char *dn = ocl->oc_descr; Xregister char *un = ocl->oc_uname; Xregister int nn = ocl->oc_name_known; X switch(ocl->oc_olet) { X case POTION_SYM: X Strcpy(buf, "potion"); X break; X case SCROLL_SYM: X Strcpy(buf, "scroll"); X break; X case WAND_SYM: X Strcpy(buf, "wand"); X break; X#ifdef SPELLS X case SPBOOK_SYM: X Strcpy(buf, "spellbook"); X break; X#endif X case RING_SYM: X Strcpy(buf, "ring"); X break; X default: X if(nn) { X Strcpy(buf, an); X if(otyp >= TURQUOISE && otyp <= JADE) X Strcat(buf, " stone"); X if(un) X Sprintf(eos(buf), " called %s", un); X if(dn) X Sprintf(eos(buf), " (%s)", dn); X } else { X Strcpy(buf, dn ? dn : an); X if(ocl->oc_olet == GEM_SYM) X Strcat(buf, " gem"); X if(un) X Sprintf(eos(buf), " called %s", un); X } X return(buf); X } X /* here for ring/scroll/potion/wand */ X if(nn) X Sprintf(eos(buf), " of %s", an); X if(un) X Sprintf(eos(buf), " called %s", un); X if(dn) X Sprintf(eos(buf), " (%s)", dn); X return(buf); X} X Xchar * Xxname(obj) Xregister struct obj *obj; X{ Xstatic char bufr[BUFSZ]; Xregister char *buf = &(bufr[PREFIX]); /* leave room for "17 -3 " */ Xregister int nn = objects[obj->otyp].oc_name_known; Xregister char *an = objects[obj->otyp].oc_name; Xregister char *dn = objects[obj->otyp].oc_descr; Xregister char *un = objects[obj->otyp].oc_uname; Xregister int pl = (obj->quan != 1); X#ifdef KAA X if(!obj->dknown && !Blind && obj->olet != WEAPON_SYM) obj->dknown=1; X#else X if(!obj->dknown && !Blind) obj->dknown = 1; /* %% doesnt belong here */ X#endif X switch(obj->olet) { X case AMULET_SYM: X Strcpy(buf, (obj->spe < 0 && obj->known) X ? "cheap plastic imitation of the " : ""); X Strcat(buf,"Amulet of Yendor"); X break; X case TOOL_SYM: X if(!nn) { X Strcpy(buf, dn); X break; X } X Strcpy(buf,an); X break; X case FOOD_SYM: X if(obj->otyp == DEAD_HOMUNCULUS && pl) { X pl = 0; X Strcpy(buf, "dead homunculi"); X break; X } X /* fungis ? */ X#ifdef KAA /* The fungus mistake was a D&D holdover. */ X if(obj->otyp == DEAD_VIOLET_FUNGUS && pl) { X pl = 0; X Strcpy(buf, "dead violet fungi"); X break; X } X#endif X /* fall into next case */ X case WEAPON_SYM: X if(obj->otyp == WORM_TOOTH && pl) { X pl = 0; X Strcpy(buf, "worm teeth"); X break; X } X if(obj->otyp == CRYSKNIFE && pl) { X pl = 0; X Strcpy(buf, "crysknives"); X break; X } X /* fall into next case */ X case ARMOR_SYM: X case CHAIN_SYM: X case ROCK_SYM: X Strcpy(buf,an); X break; X case BALL_SYM: X Sprintf(buf, "%sheavy iron ball", X (obj->owt > objects[obj->otyp].oc_weight) ? "very " : ""); X break; X case POTION_SYM: X if(nn || un || !obj->dknown) { X Strcpy(buf, "potion"); X if(pl) { X pl = 0; X Strcat(buf, "s"); X } X if(!obj->dknown) break; X if(un) { X Strcat(buf, " called "); X Strcat(buf, un); X } else { X Strcat(buf, " of "); X Strcat(buf, an); X } X } else { X Strcpy(buf, dn); X Strcat(buf, " potion"); X } X break; X case SCROLL_SYM: X Strcpy(buf, "scroll"); X if(pl) { X pl = 0; X Strcat(buf, "s"); X } X if(!obj->dknown) break; X if(nn) { X Strcat(buf, " of "); X Strcat(buf, an); X } else if(un) { X Strcat(buf, " called "); X Strcat(buf, un); X } else { X Strcat(buf, " labeled "); X Strcat(buf, dn); X } X break; X case WAND_SYM: X if(!obj->dknown) X Sprintf(buf, "wand"); X else if(nn) X Sprintf(buf, "wand of %s", an); X else if(un) X Sprintf(buf, "wand called %s", un); X else X Sprintf(buf, "%s wand", dn); X break; X#ifdef SPELLS X case SPBOOK_SYM: X if(!obj->dknown) X Sprintf(buf, "spellbook"); X else if(nn) X Sprintf(buf, "spellbook of %s", an); X else if(un) X Sprintf(buf, "spellbook called %s", un); X else X Sprintf(buf, "%s spellbook", dn); X break; X#endif X case RING_SYM: X if(!obj->dknown) X Sprintf(buf, "ring"); X else if(nn) X Sprintf(buf, "ring of %s", an); X else if(un) X Sprintf(buf, "ring called %s", un); X else X Sprintf(buf, "%s ring", dn); X break; X case GEM_SYM: X if(!obj->dknown) { X Strcpy(buf, "gem"); X break; X } X if(!nn) { X#ifdef KAA X if(un) { X if (!pl) Sprintf(buf,"gem called %s",un); X else Sprintf(buf,"gems called %s",un); X pl=0; X } else X#endif X Sprintf(buf, "%s gem", dn); X break; X } X Strcpy(buf, an); X if(obj->otyp >= TURQUOISE && obj->otyp <= JADE) X Strcat(buf, " stone"); X break; X default: X Sprintf(buf,"glorkum %c (0%o) %u %d", X obj->olet,obj->olet,obj->otyp,obj->spe); X } X if(pl) { X register char *p; X X for(p = buf; *p; p++) { X if(!strncmp(" of ", p, 4)) { X /* pieces of, cloves of, lumps of */ X register int c1, c2 = 's'; X X do { X c1 = c2; c2 = *p; *p++ = c1; X } while(c1); X goto nopl; X } X } X p = eos(buf)-1; X if(*p == 's' || *p == 'z' || *p == 'x' || X (*p == 'h' && p[-1] == 's')) X Strcat(buf, "es"); /* boxes */ X else if(*p == 'y' && !index(vowels, p[-1])) X Strcpy(p, "ies"); /* rubies, zruties */ X else X Strcat(buf, "s"); X } Xnopl: X if(obj->onamelth) { X Strcat(buf, " named "); X Strcat(buf, ONAME(obj)); X } X return(buf); X} X Xchar * Xdoname(obj) Xregister struct obj *obj; X{ Xchar prefix[PREFIX]; Xregister char *bp = xname(obj); X if(obj->quan != 1) X Sprintf(prefix, "%u ", obj->quan); X else X Strcpy(prefix, "a "); X if((obj->cursed && obj->known)) X Strcat(prefix, "cursed "); X switch(obj->olet) { X case AMULET_SYM: X if(strncmp(bp, "cheap ", 6)) X Strcpy(prefix, "the "); X break; X case ARMOR_SYM: X if(obj->owornmask & W_ARMOR) X Strcat(bp, " (being worn)"); X /* fall into next case */ X case WEAPON_SYM: X if(obj->known) { X#ifdef KAA X /* dknown is special for weapons */ X if(obj->dknown && obj->olet == WEAPON_SYM) X Strcat(prefix,"blessed "); X#endif X Strcat(prefix, sitoa(obj->spe)); X Strcat(prefix, " "); X } X break; X#ifdef MARKER X case TOOL_SYM: /* temp. hack by GAN 11/18/86 */ X if(obj->owornmask & W_TOOL) { /* blindfold or badge */ X Strcat(bp, " (being worn)"); X break; X } X if(!(obj->otyp == MAGIC_MARKER || obj->otyp == LAMP)) break; X /* if marker or lamp fall trough to show charges */ X#endif X case WAND_SYM: X if(obj->known) X Sprintf(eos(bp), " (%d)", obj->spe); X break; X case RING_SYM: X if(obj->owornmask & W_RINGR) Strcat(bp, " (on right "); X if(obj->owornmask & W_RINGL) Strcat(bp, " (on left "); X if(obj->owornmask & W_RING) { X if (humanoid(u.usym)) Strcat(bp, "hand)"); X else Strcat(bp, "paw)"); X } X if(obj->known && (objects[obj->otyp].bits & SPEC)) { X Strcat(prefix, sitoa(obj->spe)); X Strcat(prefix, " "); X } X break; X } X if(obj->owornmask & W_WEP) { X Strcat(bp, " (weapon in "); X if (humanoid(u.usym)) Strcat(bp, "hand)"); X else Strcat(bp, "paw)"); X } X if(obj->unpaid) X Strcat(bp, " (unpaid)"); X if(!strcmp(prefix, " a ") && index(vowels, *bp)) X Strcpy(prefix, " an "); X bp = strprepend(bp, prefix); X return(bp); X} X X/* used only in fight.c (thitu) */ Xsetan(str,buf) Xregister char *str,*buf; X{ X if(index(vowels,*str)) X Sprintf(buf, "an %s", str); X else X Sprintf(buf, "a %s", str); X} X Xchar * Xaobjnam(otmp,verb) register struct obj *otmp; register char *verb; { Xregister char *bp = xname(otmp); Xchar prefix[PREFIX]; X if(otmp->quan != 1) { X Sprintf(prefix, "%u ", otmp->quan); X bp = strprepend(bp, prefix); X } X X if(verb) { X /* verb is given in plural (i.e., without trailing s) */ X Strcat(bp, " "); X if(otmp->quan != 1) X Strcat(bp, verb); X else if(!strcmp(verb, "are")) X Strcat(bp, "is"); X else { X Strcat(bp, verb); X Strcat(bp, "s"); X } X } X return(bp); X} X Xchar * XDoname(obj) Xregister struct obj *obj; X{ X register char *s = doname(obj); X X if('a' <= *s && *s <= 'z') *s -= ('a' - 'A'); X return(s); X} X Xchar *wrp[] = { "wand", "ring", "potion", "scroll", "gem" X#ifdef SPELLS X , "spellbook" X#endif X }; Xchar wrpsym[] = { WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM X#ifdef SPELLS X , SPBOOK_SYM X#endif X }; X Xstruct obj * Xreadobjnam(bp) register char *bp; { Xregister char *p; Xregister int i; Xint cnt, spe, spesgn, typ, heavy; Xchar let; Xchar *un, *dn, *an; X#ifdef KAA Xint blessed=0; X#endif X/* int the = 0; char *oname = 0; */ X cnt = spe = spesgn = typ = heavy = 0; X let = 0; X an = dn = un = 0; X for(p = bp; *p; p++) /* set the string to lower case */ X if('A' <= *p && *p <= 'Z') *p += 'a'-'A'; X if(!strncmp(bp, "the ", 4)){ X/* the = 1; */ X bp += 4; X } else if(!strncmp(bp, "an ", 3)){ X cnt = 1; X bp += 3; X } else if(!strncmp(bp, "a ", 2)){ X cnt = 1; X bp += 2; X } X if(!cnt && digit(*bp)){ X cnt = atoi(bp); X while(digit(*bp)) bp++; X while(*bp == ' ') bp++; X } X if(!cnt) cnt = 1; /* %% what with "gems" etc. ? */ X#ifdef KAA X if(!strncmp(bp, "blessed ",8)) { X blessed=1; X bp += 8; X } X#endif X if(*bp == '+' || *bp == '-'){ X spesgn = (*bp++ == '+') ? 1 : -1; X spe = atoi(bp); X while(digit(*bp)) bp++; X while(*bp == ' ') bp++; X } else { X p = rindex(bp, '('); X if(p) { X if(p > bp && p[-1] == ' ') p[-1] = 0; X else *p = 0; X p++; X spe = atoi(p); X while(digit(*p)) p++; X if(strcmp(p, ")")) spe = 0; X else spesgn = 1; X } X } X /* now we have the actual name, as delivered by xname, say X green potions called whisky X scrolls labeled "QWERTY" X egg X dead zruties X fortune cookies X very heavy iron ball named hoei X wand of wishing X elven cloak X */ X for(p = bp; *p; p++) if(!strncmp(p, " named ", 7)) { X *p = 0; X/* oname = p+7; */ X } X for(p = bp; *p; p++) if(!strncmp(p, " called ", 8)) { X *p = 0; X un = p+8; X } X for(p = bp; *p; p++) if(!strncmp(p, " labeled ", 9)) { X *p = 0; X dn = p+9; X } X X /* first change to singular if necessary */ X if(cnt != 1) { X /* find "cloves of garlic", "worthless pieces of blue glass" */ X for(p = bp; *p; p++) if(!strncmp(p, "s of ", 5)){ X while(*p = p[1]) p++; X goto sing; X } X /* remove -s or -es (boxes) or -ies (rubies, zruties) */ X p = eos(bp); X if(p[-1] == 's') { X if(p[-2] == 'e') { X if(p[-3] == 'i') { X#ifdef KAA X if(!strcmp(p-7, "cookies") || !strcmp(p-4, "pies")) X#else X if(!strcmp(p-7, "cookies")) X#endif X goto mins; X Strcpy(p-3, "y"); X goto sing; X } X X /* note: cloves / knives from clove / knife */ X if(!strcmp(p-6, "knives")) { X Strcpy(p-3, "fe"); X goto sing; X } X X /* note: nurses, axes but boxes */ X if(!strcmp(p-5, "boxes")) { X p[-2] = 0; X goto sing; X } X } X mins: X p[-1] = 0; X } else { X if(!strcmp(p-9, "homunculi") X#ifdef KAA X || !strcmp(p-5, "fungi") X#endif X ) { X Strcpy(p-1, "us"); /* !! makes string longer */ X goto sing; X } X if(!strcmp(p-5, "teeth")) { X Strcpy(p-5, "tooth"); X goto sing; X } X /* here we cannot find the plural suffix */ X } X } Xsing: X if(!strcmp(bp, "amulet of yendor")) { X typ = AMULET_OF_YENDOR; X goto typfnd; X } X if(!strcmp(bp, "ring mail")){ /* Note: ring mail is not a ring ! */ X let = ARMOR_SYM; X an = bp; X goto srch; X } X X#ifdef SHIRT X if (!strcmp(bp, "hawaiian shirt")) { X *(bp) = 'H'; X an = bp; X goto srch; X } X#endif X p = eos(bp); X#if defined(KOPS) && !defined(KJSMODS) X if (!strcmp(p-3, "kop")) { X *(p-3) = 'K'; X an = bp; X goto srch; X } X#endif X for(i = 0; i < sizeof(wrpsym); i++) { X register int j = strlen(wrp[i]); X if(!strncmp(bp, wrp[i], j)){ X let = wrpsym[i]; X bp += j; X if(!strncmp(bp, " of ", 4)) an = bp+4; X /* else if(*bp) ?? */ X goto srch; X } X if(!strcmp(p-j, wrp[i])){ X let = wrpsym[i]; X p -= j; X *p = 0; X if(p[-1] == ' ') p[-1] = 0; X dn = bp; X goto srch; X } X } X if(!strcmp(p-6, " stone")){ X p[-6] = 0; X let = GEM_SYM; X an = bp; X goto srch; X } X#ifdef KAA X if(!strcmp(p-10, "gold piece") || !strcmp(p-7, "zorkmid")) { X if (cnt > 5000) cnt=5000; X if (cnt < 1) cnt=1; X pline("%d gold piece%s.", cnt, cnt==1 ? "" : "s"); X u.ugold += cnt; X flags.botl=1; X return(0); X } X#endif X if(!strcmp(bp, "very heavy iron ball")){ X heavy = 1; X typ = HEAVY_IRON_BALL; X goto typfnd; X } X an = bp; Xsrch: X if(!an && !dn && !un) X goto any; X i = 1; X if(let) i = bases[letindex(let)]; X while(i <= NROFOBJECTS && (!let || objects[i].oc_olet == let)){ X register char *zn = objects[i].oc_name; X X if(!zn) goto nxti; X if(an && strcmp(an, zn)) X goto nxti; X if(dn && (!(zn = objects[i].oc_descr) || strcmp(dn, zn))) X goto nxti; X if(un && (!(zn = objects[i].oc_uname) || strcmp(un, zn))) X goto nxti; X typ = i; X goto typfnd; X nxti: X i++; X } Xany: X if(!let) let = wrpsym[rn2(sizeof(wrpsym))]; X typ = probtype(let); Xtypfnd: X { register struct obj *otmp; X extern struct obj *mksobj(); X let = objects[typ].oc_olet; X otmp = mksobj(typ); X if(heavy) otmp->owt += 15; X X if(cnt > 0 && index("%?!*)", let) && X (cnt < rnd(6) || X#ifdef WIZARD X wizard || X#endif X#ifdef KAA X (let == WEAPON_SYM && typ <= ROCK && cnt <= 20) X#else X (let == WEAPON_SYM && typ <= ROCK && cnt < 20) X#endif X )) otmp->quan = cnt; X X if(spe > rnd(5) && spe > otmp->spe) { X#ifdef WIZARD X if(!wizard) X#endif X spe = 0; X } else if(let == WAND_SYM) X spe = otmp->spe; X#ifdef KAA X if(let==WEAPON_SYM && blessed) { X if(u.uluck < 0) otmp->cursed=1; X else otmp->dknown=1; X } X#endif X if(spe > 2 && u.uluck < 0) X spesgn = -1; X if(let != WAND_SYM && spesgn == -1) X spe = -spe; X if(let == BALL_SYM) X spe = 0; X else if(let == AMULET_SYM) X spe = -1; X else if(typ == WAN_WISHING && rn2(10)) X spe = (rn2(10) ? -1 : 0); X#ifdef MARKER X else if(typ == MAGIC_MARKER) X spe = rn1(50,50); X#endif X else if(typ == LAMP) X spe = rnd(10); X else if(typ == MAGIC_LAMP) X spe = 1; X otmp->spe = spe; X X if(spesgn == -1) X otmp->cursed = 1; X X return(otmp); X } X} END_OF_objnam.c if test 14057 -ne `wc -c pcmain.c <<'END_OF_pcmain.c' X/* SCCS Id: @(#)pcmain.c 2.3 87/12/12 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* main.c - (PC) version */ X X#include X#include X#include "hack.h" X X#ifdef QUEST X#define gamename "PC NetQuest" X#else X#define gamename "PC NetHack" X#endif X Xchar orgdir[PATHLEN], *getcwd(); X Xextern struct permonst mons[CMNUM+2]; Xextern char genocided[], fut_geno[]; Xextern char *getlogin(), *getenv(); Xextern char plname[PL_NSIZ], pl_character[PL_CSIZ]; X Xint (*afternmv)(), done1(), (*occupation)(); X Xchar SAVEF[FILENAME]; Xchar *hname = gamename; Xchar obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */ Xint hackpid; /* not used anymore, but kept in for save files */ X Xextern char *nomovemsg; Xextern long wailmsg; X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X register int fd; X register char *dir; X extern struct monst *makedog(); X#ifdef MSDOS X static void moveloop(); /* a helper function for MSC optimizer */ X X /* Save current directory and make sure it gets restored when X * the game is exited. X */ X int (*funcp)(); X X if (getcwd(orgdir, sizeof orgdir) == NULL) { X xputs("NetHack: current directory path too long\n"); X _exit(1); X } X funcp = exit; /* Kludge to get around LINT_ARGS of signal. X * This will produce a compiler warning, but that's OK. X */ X signal(SIGINT, funcp); /* restore original directory */ X#endif X X#ifdef GRAPHICS X /* Set the default values of the presentation characters */ X memcpy((char *) &showsyms, (char *) &defsyms, sizeof(struct symbols)); X#endif X#ifdef DGK X if ((dir = getenv("HACKDIR")) != (char *) NULL) { X (void) strcpy(hackdir, dir); X chdirx (dir, 1); X } X zero_finfo(); X initoptions(); X if (!hackdir[0]) X (void) strcpy(hackdir, orgdir); X dir = hackdir; X#else X dir = getenv("HACKDIR"); X if(argc > 1 && !strncmp(argv[1], "-d", 2)) { X argc--; X argv++; X dir = argv[0]+2; X if(*dir == '=' || *dir == ':') dir++; X if(!*dir && argc > 1) { X argc--; X argv++; X dir = argv[0]; X } X if(!*dir) X error("Flag -d must be followed by a directory name."); X } X#endif /* DGK */ X X /* X * Now we know the directory containing 'record' and X * may do a prscore(). X */ X if(argc > 1 && !strncmp(argv[1], "-s", 2)) { X chdirx(dir,0); X prscore(argc, argv); X exit(0); X } X X /* X * It seems he really wants to play. X * Remember tty modes, to be restored on exit. X */ X gettty(); X setbuf(stdout,obuf); X setrandom(); X startup(); X init_corpses(); /* initialize optional corpse names */ X cls(); X u.uhp = 1; /* prevent RIP on early quits */ X u.ux = FAR; /* prevent nscr() */ X X /* X * We cannot do chdir earlier, otherwise gethdate will fail. X */ X chdirx(dir,1); X X /* X * Process options. X */ X while(argc > 1 && argv[1][0] == '-'){ X argv++; X argc--; X switch(argv[0][1]){ X#ifdef WIZARD X case 'D': X# ifdef MSDOS X wizard = TRUE; X# else X if(!strcmp(getlogin(), WIZARD)) X wizard = TRUE; X else { X settty("Sorry, you can't operate in debug mode.\n"); X clearlocks(); X exit(0); X } X# endif X break; X#endif X case 'u': X if(argv[0][2]) X (void) strncpy(plname, argv[0]+2, sizeof(plname)-1); X else if(argc > 1) { X argc--; X argv++; X (void) strncpy(plname, argv[0], sizeof(plname)-1); X } else X printf("Player name expected after -u\n"); X break; X#ifdef DGK X /* Person does not want to use a ram disk X */ X case 'R': X ramdisk = FALSE; X break; X#endif X default: X /* allow -T for Tourist, etc. */ X (void) strncpy(pl_character, argv[0]+1, X sizeof(pl_character)-1); X X /* printf("Unknown option: %s\n", *argv); */ X } X } X X#ifdef DGK X set_lock_and_bones(); X copybones(FROMPERM); X#endif X#ifdef WIZARD X if (wizard) X (void) strcpy(plname, "wizard"); X else X#endif X if (!*plname) X askname(); X plnamesuffix(); /* strip suffix from name; calls askname() */ X /* again if suffix was whole name */ X /* accepts any suffix */ X#ifdef WIZARD X if(wizard) { X register char *sfoo; X# ifndef DGK X /* lock is set in read_config_file */ X (void) strcpy(lock,plname); X# endif X if(sfoo = getenv("MAGIC")) X while(*sfoo) { X switch(*sfoo++) { X case 'n': (void) srand(*sfoo++); X break; X } X } X if(sfoo = getenv("GENOCIDED")){ X if(*sfoo == '!'){ X register struct permonst *pm = mons; X register char *gp = genocided; X X while(pm < mons+CMNUM+2){ X if(!index(sfoo, pm->mlet)) X *gp++ = pm->mlet; X pm++; X } X *gp = 0; X } else X (void) strcpy(genocided, sfoo); X (void) strcpy(fut_geno, genocided); X } X } X#endif /* WIZARD */ X start_screen(); X#ifdef DGK X strncat(SAVEF, plname, 8); X strcat(SAVEF, ".sav"); X cls(); X if (saveDiskPrompt(1) && ((fd = open(SAVEF, 0)) >= 0) && X (uptodate(fd) || !unlink(SAVEF))) { X#else X (void) sprintf(SAVEF, "save/%d%s", getuid(), plname); X regularize(SAVEF+5); /* avoid . or / in name */ X if((fd = open(SAVEF,0)) >= 0 && X (uptodate(fd) || unlink(SAVEF) == 666)) { X#endif /* DGK */ X (void) signal(SIGINT,done1); X pline("Restoring old save file..."); X (void) fflush(stdout); X if(!dorecover(fd)) X goto not_recovered; X pline("Hello %s%s, welcome to %s!", X (Badged) ? "Officer " : "", plname, hname); X#ifdef WIZARD X if (wizard && dlevel == 1) X# ifdef STOOGES Xpline ("The wiz is at %d, the medusa is at %d, and the stooges are at %d", X u.wiz_level, u.medusa_level, u.stooge_level); X# else X pline ("The wiz is at %d, and the medusa at %d", X u.wiz_level, u.medusa_level); X# endif X#endif X flags.move = 0; X } else { Xnot_recovered: X#ifdef DGK X gameDiskPrompt(); X#endif X fobj = fcobj = invent = 0; X fmon = fallen_down = 0; X ftrap = 0; X fgold = 0; X flags.ident = 1; X init_objects(); X u_init(); X X (void) signal(SIGINT,done1); X mklev(); X u.ux = xupstair; X u.uy = yupstair; X (void) inshop(); X setsee(); X flags.botlx = 1; X /* Fix bug with dog not being made because a monster X * was on the level 1 staircase X */ X { X struct monst *mtmp; X X if (mtmp = m_at(u.ux, u.uy)) X mnexto(mtmp); X } X makedog(); X { register struct monst *mtmp; X if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp); /* riv05!a3 */ X } X seemons(); X docrt(); X X /* give welcome message before pickup messages */ X pline("Hello %s, welcome to %s!", plname, hname); X X pickup(1); X read_engr_at(u.ux,u.uy); X flags.move = 1; X } X flags.moonphase = phase_of_the_moon(); X if(flags.moonphase == FULL_MOON) { X pline("You are lucky! Full moon tonight."); X if(!u.uluck) change_luck(1); X } else if(flags.moonphase == NEW_MOON) { X pline("Be careful! New moon tonight."); X } X X initrack(); X (void) signal(SIGINT, SIG_IGN); X#ifdef MSDOS X /* Help for Microsoft optimizer. Otherwise main is too large -dgk*/ X moveloop(); X} X Xstatic void Xmoveloop() X{ X char ch; X int abort; X#endif /* MSDOS */ X for(;;) { X if(flags.move) { /* actual time passed */ X X settrack(); X X if(moves%2 == 0 || X (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) { X extern struct monst *makemon(); X movemon(); X#ifdef HARD X if(!rn2(u.udemigod?25:(dlevel>30)?50:70)) X#else X if(!rn2(70)) X#endif X (void) makemon((struct permonst *)0, 0, 0); X } X if(Glib) glibr(); X timeout(); X ++moves; X#ifdef PRAYERS X if (u.ublesscnt) u.ublesscnt--; X#endif X#ifndef DGK X if(flags.time) flags.botl = 1; X#endif X#ifdef KAA X if(u.mtimedone) X if(u.mh < 1) rehumanize(); X else X#endif X if(u.uhp < 1) { X pline("You die..."); X done("died"); X } X if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){ X wailmsg = moves; X#ifdef KAA X if(index("WEV", pl_character[0])) { X if (u.uhp == 1) X pline("%s is about to die.", pl_character); X else X pline("%s, your life force is running out.", X pl_character); X } else { X#endif X if(u.uhp == 1) X pline("You hear the wailing of the Banshee..."); X else X pline("You hear the howling of the CwnAnnwn..."); X#ifdef KAA X } X#endif X } X#ifdef KAA X if (u.mtimedone) { X if (u.mh < u.mhmax) { X if (Regeneration || !(moves%20)) { X flags.botl = 1; X u.mh++; X } X } X } X#endif X if(u.uhp < u.uhpmax) { X if(u.ulevel > 9) { X if(HRegeneration || !(moves%3)) { X flags.botl = 1; X u.uhp += rnd((int) u.ulevel-9); X if(u.uhp > u.uhpmax) X u.uhp = u.uhpmax; X } X } else if(HRegeneration || X (!(moves%(22-u.ulevel*2)))) { X flags.botl = 1; X u.uhp++; X } X } X#ifdef SPELLS X if ((u.uen u.uenmax) u.uen = u.uenmax; X flags.botl = 1; X } X#endif X if(Teleportation && !rn2(85)) tele(); X#if defined(KAA) && defined(BVH) X if(Polymorph && !rn2(100)) polyself(); X#endif X if(Searching && multi >= 0) (void) dosearch(); X gethungry(); X invault(); X amulet(); X#ifdef HARD X if (!rn2(50+(u.ulevel*3))) u_wipe_engr(rnd(3)); X if (u.udemigod) { X X u.udg_cnt--; X if(u.udg_cnt <= 0) { X X intervene(); X u.udg_cnt = rn1(200, 50); X } X } X#endif X } X if(multi < 0) { X if(!++multi){ X pline(nomovemsg ? nomovemsg : X "You can move again."); X nomovemsg = 0; X if(afternmv) (*afternmv)(); X afternmv = 0; X } X } X X find_ac(); X#ifndef QUEST X if(!flags.mv || Blind) X#endif X { X seeobjs(); X seemons(); X nscr(); X } X#ifdef DGK X if(flags.time) flags.botl = 1; X#endif X if(flags.botl || flags.botlx) bot(); X X flags.move = 1; X X if(multi >= 0 && occupation) { X#ifdef DGK X abort = 0; X if (kbhit()) { X if ((ch = getchar()) == ABORT) X abort++; X# ifdef REDO X else X pushch(ch); X# endif X } X if (abort || monster_nearby()) X stop_occupation(); X else if ((*occupation)() == 0) X occupation = 0; X if (!(++occtime % 7)) X (void) fflush(stdout); X#else X if (monster_nearby()) X stop_occupation(); X else if ((*occupation)() == 0) X occupation = 0; X#endif X continue; X } X X if(multi > 0) { X#ifdef QUEST X if(flags.run >= 4) finddir(); X#endif X lookaround(); X if(!multi) { /* lookaround may clear multi */ X flags.move = 0; X continue; X } X if(flags.mv) { X if(multi < COLNO && !--multi) X flags.mv = flags.run = 0; X domove(); X } else { X --multi; X rhack(save_cm); X } X } else if(multi == 0) { X rhack((char *) 0); X } X if(multi && multi%7 == 0) X (void) fflush(stdout); X } X} X X#ifndef DGK X/* This function is unnecessary and incompatible with the #define X * of glo(x) in config.h -dgk X */ Xglo(foo) Xregister foo; X{ X /* construct the string xlock.n */ X register char *tf; X X tf = lock; X while(*tf && *tf != '.') tf++; X (void) sprintf(tf, ".%d", foo); X} X#endif X X/* X * plname is filled either by an option (-u Player or -uPlayer) or X * explicitly (-w implies wizard) or by askname. X * It may still contain a suffix denoting pl_character. X */ Xaskname(){ Xregister int c,ct; X printf("\nWho are you? "); X (void) fflush(stdout); X ct = 0; X while((c = getchar()) != '\n'){ X#ifdef MSDOS X msmsg("%c", c); X#endif X if(c == EOF) error("End of input\n"); X /* some people get confused when their erase char is not ^H */ X if(c == '\010') { X if(ct) ct--; X continue; X } X if(c != '-') X if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_'; X if(ct < sizeof(plname)-1) plname[ct++] = c; X } X plname[ct] = 0; X if(ct == 0) askname(); X} X X/*VARARGS1*/ Ximpossible(s,x1,x2) Xregister char *s; X{ X pline(s,x1,x2); X pline("Program in disorder - perhaps you'd better Quit."); X} X X#ifdef CHDIR Xchdirx(dir, wr) Xchar *dir; Xboolean wr; X{ X X if(dir && chdir(dir) < 0) { X error("Cannot chdir to %s.", dir); X } X X#ifdef DGK X /* Change the default drive as well. X */ X chdrive(dir); X#endif X X /* warn the player if he cannot write the record file */ X /* perhaps we should also test whether . is writable */ X /* unfortunately the access systemcall is worthless */ X if(wr) { X register fd; X X if(dir == NULL) X dir = "."; X if((fd = open(RECORD, 2)) < 0) { X#ifdef DGK X char tmp[PATHLEN]; X X strcpy(tmp, dir); X append_slash(tmp); X msmsg("Warning: cannot write %s%s\n", tmp, RECORD); X getreturn("to continue"); X#else X printf("Warning: cannot write %s/%s", dir, RECORD); X getret(); X#endif X } else X (void) close(fd); X } X} X#endif /* CHDIR /**/ X Xstop_occupation() X{ X extern void pushch(); X X if(occupation) { X pline("You stop %s.", occtxt); X occupation = 0; X#ifdef REDO X multi = 0; X pushch(0); X#endif X } X} X X#ifdef DGK Xstruct finfo zfinfo = ZFINFO; X Xzero_finfo() { /* zero "fileinfo" array to prevent crashes on level change */ X int i; X X for (i = 0 ; i <= MAXLEVEL; i++) X fileinfo[i] = zfinfo; X} X#endif END_OF_pcmain.c if test 12382 -ne `wc -c pri.c <<'END_OF_pri.c' X/* SCCS Id: @(#)pri.c 2.3 87/12/12 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include X#include "hack.h" X#ifdef GENIX X#define void int /* jhn - mod to prevent compiler from bombing */ X#endif X#ifdef MSDOSCOLOR Xextern int hilite(); X#endif X Xxchar scrlx, scrhx, scrly, scrhy; /* corners of new area on screen */ X Xextern char *hu_stat[]; /* in eat.c */ Xextern char *CD; Xextern struct monst *makemon(); X Xswallowed() X{ X char *ulook = "|@|"; X ulook[1] = u.usym; X X cls(); X curs(u.ux-1, u.uy+1); X fputs("/-\\", stdout); X curx = u.ux+2; X curs(u.ux-1, u.uy+2); X fputs(ulook, stdout); X curx = u.ux+2; X curs(u.ux-1, u.uy+3); X fputs("\\-/", stdout); X curx = u.ux+2; X u.udispl = 1; X u.udisx = u.ux; X u.udisy = u.uy; X} X Xsetclipped(){ X error("Hack needs a screen of size at least %d by %d.\n", X ROWNO+2, COLNO); X} X X#ifdef DGK Xstatic int multipleAts; /* TRUE if we have many at()'s to do */ Xstatic int DECgraphics; /* The graphics mode toggle */ X X#define DECgraphicsON() ((void) putchar('\16'), DECgraphics = TRUE) X#define DECgraphicsOFF() ((void) putchar('\17'), DECgraphics = FALSE) X#endif X Xat(x,y,ch) Xregister xchar x,y; Xchar ch; X{ X#ifndef LINT X /* if xchar is unsigned, lint will complain about if(x < 0) */ X if(x < 0 || x > COLNO-1 || y < 0 || y > ROWNO-1) { X impossible("At gets 0%o at %d %d.", ch, x, y); X return; X } X#endif X if(!ch) { X impossible("At gets null at %d %d.", x, y); X return; X } X y += 2; X curs(x,y); X#ifdef DGK X if (flags.DECRainbow) { X /* If there are going to be many at()s in a row without X * intervention, only change the graphics mode when the X * character changes between graphic and regular. X */ X if (multipleAts) { X if (ch & 0x80) { X if (!DECgraphics) X DECgraphicsON(); X (void) putchar(ch ^ 0x80); /* Strip 8th bit */ X } else { X if (DECgraphics) X DECgraphicsOFF(); X (void) putchar(ch); X } X /* Otherwise, we don't know how many at()s will be happening X * before printing of normal strings, so change to graphics X * mode when necessary, then change right back. X */ X } else { X if (ch & 0x80) { X DECgraphicsON(); X (void) putchar(ch ^ 0x80); /* Strip 8th bit */ X DECgraphicsOFF(); X } else X (void) putchar(ch); X } X } else X#endif X#ifdef MSDOSCOLOR X hilite(ch); X#else X (void) putchar(ch); X#endif X curx++; X} X Xprme(){ X if(!Invisible) at(u.ux,u.uy,u.usym); X} X Xdoredraw() X{ X docrt(); X return(0); X} X Xdocrt() X{ X register x,y; X register struct rm *room; X register struct monst *mtmp; X X if(u.uswallow) { X swallowed(); X return; X } X cls(); X X/* Some ridiculous code to get display of @ and monsters (almost) right */ X if(!Invisible) { X levl[(u.udisx = u.ux)][(u.udisy = u.uy)].scrsym = u.usym; X levl[u.udisx][u.udisy].seen = 1; X u.udispl = 1; X } else u.udispl = 0; X X seemons(); /* reset old positions */ X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) X mtmp->mdispl = 0; X seemons(); /* force new positions to be shown */ X/* This nonsense should disappear soon --------------------------------- */ X X#if defined(DGK) && !defined(MSDOSCOLOR) X /* I don't know DEC Rainbows, but if HILITE_COLOR is applicable, X * the !defined(HILITE_COLOR) will have to be compensated for. X * -kjs */ X /* For DEC Rainbows, we must translate each character to strip X * out the 8th bit if necessary. X */ X if (flags.DECRainbow) { X multipleAts = TRUE; X for(y = 0; y < ROWNO; y++) X for(x = 0; x < COLNO; x++) X if((room = &levl[x][y])->new) { X room->new = 0; X at(x,y,room->scrsym); X } else if(room->seen) X at(x,y,room->scrsym); X multipleAts = FALSE; X if (DECgraphics) X DECgraphicsOFF(); X } else { X /* Otherwise, line buffer the output to do the redraw in X * about 2/3 of the time. X */ X for(y = 0; y < ROWNO; y++) { X char buf[COLNO+1]; X int start, end; X X memset(buf, ' ', COLNO); X for(x = 0, start = -1, end = -1; x < COLNO; x++) X if((room = &levl[x][y])->new) { X room->new = 0; X buf[x] = room->scrsym; X if (start < 0) X start = x; X end = x; X } else if(room->seen) { X buf[x] = room->scrsym; X if (start < 0) X start = x; X end = x; X } X if (end >= 0) { X buf[end + 1] = '\0'; X curs(start, y + 2); X fputs(buf + start, stdout); X curx = end + 1; X } X } X } X#else X for(y = 0; y < ROWNO; y++) X for(x = 0; x < COLNO; x++) X if((room = &levl[x][y])->new) { X room->new = 0; X at(x,y,room->scrsym); X } else if(room->seen) X at(x,y,room->scrsym); X#endif X scrlx = COLNO; X scrly = ROWNO; X scrhx = scrhy = 0; X flags.botlx = 1; X bot(); X} X Xdocorner(xmin,ymax) register xmin,ymax; { X register x,y; X register struct rm *room; X register struct monst *mtmp; X X if(u.uswallow) { /* Can be done more efficiently */ X swallowed(); X return; X } X X seemons(); /* reset old positions */ X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) X if(mtmp->mx >= xmin && mtmp->my < ymax) X mtmp->mdispl = 0; X seemons(); /* force new positions to be shown */ X X#ifdef DGK X if (flags.DECRainbow) X multipleAts = TRUE; X#endif X for(y = 0; y < ymax; y++) { X if(y > ROWNO && CD) break; X curs(xmin,y+2); X cl_end(); X if(y < ROWNO) { X for(x = xmin; x < COLNO; x++) { X if((room = &levl[x][y])->new) { X room->new = 0; X at(x,y,room->scrsym); X } else X if(room->seen) X at(x,y,room->scrsym); X } X } X } X#ifdef DGK X if (flags.DECRainbow) { X multipleAts = FALSE; X if (DECgraphics) X DECgraphicsOFF(); X } X#endif X if(ymax > ROWNO) { X cornbot(xmin-1); X if(ymax > ROWNO+1 && CD) { X curs(1,ROWNO+3); X cl_eos(); X } X } X} X X/* Trolls now regenerate thanks to KAA */ X Xseeobjs(){ Xregister struct obj *obj, *obj2; X for(obj = fobj; obj; obj = obj2) { X obj2 = obj->nobj; X if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE) { X X if (obj->otyp == DEAD_TROLL && obj->age + 20 < moves) { X delobj(obj); X if (cansee(obj->ox, obj->oy)) X pline("The troll rises from the dead!"); X (void) makemon(PM_TROLL,obj->ox, obj->oy); X } else if (obj->age + 250 < moves) delobj(obj); X } X } X X for(obj = invent; obj; obj = obj2) { X obj2 = obj->nobj; X if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE) { X X if (obj->otyp == DEAD_TROLL && obj->age + 20 < moves) { X if (obj == uwep) X pline("The dead troll writhes out of your grasp!"); X else X pline("You feel squirming in your backpack!"); X (void)makemon(PM_TROLL,u.ux,u.uy); X useup(obj); X } else if (obj->age + 250 < moves) useup(obj); X } X } X} X Xseemons(){ Xregister struct monst *mtmp; X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){ X if(mtmp->data->mlet == ';') X mtmp->minvis = (u.ustuck != mtmp && X levl[mtmp->mx][mtmp->my].typ == POOL); X pmon(mtmp); X#ifndef NOWORM X if(mtmp->wormno) wormsee(mtmp->wormno); X#endif X } X} X Xpmon(mon) register struct monst *mon; { Xregister int show = (Blind && Telepat) || canseemon(mon); X if(mon->mdispl){ X if(mon->mdx != mon->mx || mon->mdy != mon->my || !show) X unpmon(mon); X } X X/* If you're hallucinating, the monster must be redrawn even if it has X already been printed. Problem: the monster must also be redrawn right X after hallucination is over, so it looks normal again. Therefore X code similar to pmon is in timeout.c. */ X if(show && (!mon->mdispl || Hallucination)) { X if (Hallucination) X atl(mon->mx,mon->my, X (!mon->mimic || Protection_from_shape_changers) ? X rndmonsym() : X (mon->mappearance == DOOR_SYM) ? DOOR_SYM X : rndobjsym()); X else X X atl(mon->mx,mon->my, X (!mon->mappearance X || u.uprops[PROP(RIN_PROTECTION_FROM_SHAPE_CHAN)].p_flgs X ) ? mon->data->mlet : mon->mappearance); X mon->mdispl = 1; X mon->mdx = mon->mx; X mon->mdy = mon->my; X } X} X Xunpmon(mon) register struct monst *mon; { X if(mon->mdispl){ X newsym(mon->mdx, mon->mdy); X mon->mdispl = 0; X } X} X Xnscr() X{ X register x,y; X register struct rm *room; X X if(u.uswallow || u.ux == FAR || flags.nscrinh) return; X pru(); X for(y = scrly; y <= scrhy; y++) X for(x = scrlx; x <= scrhx; x++) X if((room = &levl[x][y])->new) { X room->new = 0; X at(x,y,room->scrsym); X } X scrhx = scrhy = 0; X scrlx = COLNO; X scrly = ROWNO; X} X X/* 100 suffices for bot(); no relation with COLNO */ Xchar oldbot[100], newbot[100]; Xcornbot(lth) Xregister int lth; X{ X if(lth < sizeof(oldbot)) { X oldbot[lth] = 0; X flags.botl = 1; X } X} X Xbot() X{ Xregister char *ob = oldbot, *nb = newbot; Xregister int i; Xextern char *eos(); X if(flags.botlx) *ob = 0; X flags.botl = flags.botlx = 0; X (void) sprintf(newbot, X#ifdef GOLD_ON_BOTL X# ifdef SPELLS X "Lev %-2d Gp %-5lu Hp %3d(%d) Ep %3d(%d) Ac %-2d ", X dlevel, u.ugold, X# ifdef KAA X u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax : u.uhpmax, X u.uen, u.uenmax, u.uac); X# else X u.uhp, u.uhpmax, u.uen, u.uenmax, u.uac); X# endif X# else X "Level %-2d Gold %-5lu Hp %3d(%d) Ac %-2d ", X dlevel, u.ugold, X# ifdef KAA X u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax : u.uhpmax, X u.uac); X# else X u.uhp, u.uhpmax, u.uac); X# endif X# endif X#else X# ifdef SPELLS X "Level %-2d Hp %3d(%d) Energy %3d(%d) Ac %-2d ", X dlevel, X# ifdef KAA X u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax, u.uhpmax, X u.uen, u.uenmax, u.uac); X# else X u.uhp, u.uhpmax, u.uen, u.uenmax, u.uac); X# endif X# else X "Level %-2d Hp %3d(%d) Ac %-2d ", X dlevel, X# ifdef KAA X u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax, u.uhpmax, X u.uac); X# else X u.uhp, u.uhpmax, u.uac); X# endif X# endif X#endif X#ifdef KAA X if (u.mtimedone) X (void) sprintf(eos(newbot), "HD %d", mons[u.umonnum].mlevel); X else X#endif X if(u.ustr>18) { X if(u.ustr>117) X (void) strcat(newbot,"Str 18/**"); X else X (void) sprintf(eos(newbot), "Str 18/%02d",u.ustr-18); X } else X (void) sprintf(eos(newbot), "Str %-2d ",u.ustr); X#ifdef EXP_ON_BOTL X (void) sprintf(eos(newbot), " Exp %2d/%-5lu ", u.ulevel,u.uexp); X#else X (void) sprintf(eos(newbot), " Exp %2u ", u.ulevel); X#endif X (void) strcat(newbot, hu_stat[u.uhs]); X if(flags.time) X (void) sprintf(eos(newbot), " %ld", moves); X#ifdef SCORE_ON_BOTL X (void) sprintf(eos(newbot)," S:%lu " X ,(u.ugold - u.ugold0 > 0 ? u.ugold - u.ugold0 : 0) X + u.urexp + (50 * maxdlevel) X + (maxdlevel > 20? 1000*((maxdlevel > 30) ? 10 : maxdlevel - 20) :0)); X#endif X if(strlen(newbot) >= COLNO) { X register char *bp0, *bp1; X bp0 = bp1 = newbot; X do { X if(*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ') X *bp1++ = *bp0; X } while(*bp0++); X } X for(i = 1; idata->mlevel, mtmp->mgold, mtmp->mhp, mtmp->mhpmax); X pline("Ac %-2d Dam %d %s %s", X mtmp->data->ac, (mtmp->data->damn + 1) * (mtmp->data->damd + 1), X mtmp->mcan ? ", cancelled" : "" ,mtmp->mtame ? " (tame)" : ""); X} X Xextern char plname[]; Xustatusline() { X pline("Status of %s%s ", (Badged) ? "Officer " : "", plname); X pline("Level %d, gold %lu, hit points %d(%d), AC %d.", X# ifdef KAA X u.ulevel, u.ugold, u.mtimedone ? u.mh : u.uhp, X u.mtimedone ? u.mhmax : u.uhpmax, u.uac); X# else X u.ulevel, u.ugold, u.uhp, u.uhpmax, u.uac); X# endif X} X#endif X Xcls(){ X if(flags.toplin == 1) X more(); X flags.toplin = 0; X X clear_screen(); X X flags.botlx = 1; X} X Xrndmonsym() { X register int x; X if((x=rn2(58)) < 26) X return('a'+x); X else if (x<52) X return('A'+x-26); X else switch(x) { X case 52: return(';'); X case 53: return('&'); X case 54: return(':'); X case 55: return('\''); X case 56: return(','); X case 57: return('9'); X default: impossible("Bad random monster %d",x); return('{'); X } X} X Xrndobjsym() { X char *rndsym=")[!?%/=*($`"; X return *(rndsym+rn2(11)); X} X Xchar *hcolors[] = { "ultraviolet","infrared","hot pink", "psychedelic", X"bluish-orange","reddish-green","dark white","light black","loud", X"salty","sweet","sour","bitter","luminescent","striped","polka-dotted", X"square","round","triangular","brilliant","navy blue","cerise", X"chartreuse","copper","sea green","spiral","swirly","blotchy", X"fluorescent green","burnt orange","indigo","amber","tan", X"sky blue-pink","lemon yellow" }; X Xchar * Xhcolor() { X return hcolors[rn2(35)]; X} X X#ifdef MSDOSCOLOR X/* what if a level character is the same as an object/monster? */ X Xextern char obj_symbols[]; X Xhilite(let) Xchar let; X{ X char *isobjct = index(obj_symbols, let); X int ismnst(); X X if (!HI || !HE) { X (void) putchar(let); X return; X } X if (isobjct != NULL || let == GOLD_SYM) { X /* is an object */ X printf("%s%c%s", HI_OBJ, let, HE); X } else if (ismnst(let)) { X /* is a monster */ X printf("%s%c%s", HI_MON, let, HE); X } else { X /* default */ X (void) putchar(let); X } X} X Xint Xismnst(let) Xchar let; X{ X register int ct; X register struct permonst *ptr; X X for (ct = 0 ; ct < CMNUM + 2 ; ct++) { X ptr = &mons[ct]; X if(ptr->mlet == let) return(1); X } X if (let == '1') return(1); X else if (let == '2') return(1); X else if (let == ';') return(1); X else return(0); X} X#endif END_OF_pri.c if test 12994 -ne `wc -c topten.c <<'END_OF_topten.c' X/* SCCS Id: @(#)topten.c 2.3 88/02/01 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include X#include "hack.h" X#ifdef GENIX X#define void int /* jhn - mod to prevent compiler from bombing */ X#endif X X#define Sprintf (void) sprintf Xextern char plname[], pl_character[]; X#ifndef MSC /* set by the Microsoft "C" compiler */ Xextern char *itoa(); X#endif Xextern char *ordin(), *eos(); Xextern int done_hup, done_stopprint; X X#define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry)) X#define NAMSZ 10 X#define DTHSZ 60 X#define PERSMAX 3 /* entries per name/uid per char. allowed */ X#define POINTSMIN 1 /* must be > 0 */ X#define ENTRYMAX 100 /* must be >= 10 */ X#ifndef MSDOS X#define PERS_IS_UID /* delete for PERSMAX per name; now per uid */ X#endif Xstruct toptenentry { X struct toptenentry *tt_next; X long int points; X int level,maxlvl,hp,maxhp; X int uid; X char plchar; X char sex; X char name[NAMSZ+1]; X char death[DTHSZ+1]; X char date[7]; /* yymmdd */ X} *tt_head; X Xtopten(){ X int uid = getuid(); X int rank, rank0 = -1, rank1 = 0; X int occ_cnt = PERSMAX; X register struct toptenentry *t0, *t1, *tprev; X char *recfile = RECORD; X#ifdef UNIX X char *reclock = "record_lock"; X#endif X int sleepct = 300; X FILE *rfile; X register flg = 0; X extern char *getdate(); X#ifdef LOGFILE X char *lgfile = LOGFILE; X FILE *lfile; X char *loglock = "logfile_lock"; X int sleeplgct = 30; X#endif X X#ifndef DGK X#define HUP if(!done_hup) X#else X#define HUP X#endif X X#ifdef UNIX X while(link(recfile, reclock) == -1) { X HUP perror(reclock); X if(!sleepct--) { X HUP puts("I give up. Sorry."); X HUP puts("Perhaps there is an old record_lock around?"); X return; X } X HUP printf("Waiting for access to record file. (%d)\n", X sleepct); X HUP (void) fflush(stdout); X sleep(1); X } X#endif X if(!(rfile = fopen(recfile,"r"))){ X HUP puts("Cannot open record file!"); X goto unlock; X } X HUP (void) putchar('\n'); X X /* create a new 'topten' entry */ X t0 = newttentry(); X t0->level = dlevel; X t0->maxlvl = maxdlevel; X t0->hp = u.uhp; X t0->maxhp = u.uhpmax; X t0->points = u.urexp; X t0->plchar = pl_character[0]; X t0->sex = (flags.female ? 'F' : 'M'); X t0->uid = uid; X (void) strncpy(t0->name, plname, NAMSZ); X (t0->name)[NAMSZ] = 0; X (void) strncpy(t0->death, killer, DTHSZ); X (t0->death)[DTHSZ] = 0; X (void) strcpy(t0->date, getdate()); X X /* assure minimum number of points */ X if(t0->points < POINTSMIN) X t0->points = 0; X#ifdef LOGFILE /* used for debugging (who dies of what, where) */ X while(link(lgfile, loglock) == -1) { X HUP perror(loglock); X if(!sleeplgct--) { X HUP puts("I give up. Sorry."); X HUP puts("Perhaps there is an old logfile_lock around?"); X goto lgend; X } X HUP printf("Waiting for access to log file. (%d)\n", X sleeplgct); X HUP (void) fflush(stdout); X sleep(1); X } X if(!(lfile = fopen(lgfile,"a"))){ X HUP puts("Cannot open log file!"); X goto lgend; X } X fprintf(lfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n", X t0->date, t0->uid, X t0->level, t0->maxlvl, X t0->hp, t0->maxhp, t0->points, X t0->plchar, t0->sex, t0->name, t0->death); X fclose(lfile); X (void) unlink(loglock); X lgend:; X#endif X X t1 = tt_head = newttentry(); X tprev = 0; X /* rank0: -1 undefined, 0 not_on_list, n n_th on list */ X for(rank = 1; ; ) { X if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]", X t1->date, &t1->uid, X &t1->level, &t1->maxlvl, X &t1->hp, &t1->maxhp, &t1->points, X &t1->plchar, &t1->sex, t1->name, t1->death) != 11 X || t1->points < POINTSMIN) X t1->points = 0; X if(rank0 < 0 && t1->points < t0->points) { X rank0 = rank++; X if(tprev == 0) X tt_head = t0; X else X tprev->tt_next = t0; X t0->tt_next = t1; X occ_cnt--; X flg++; /* ask for a rewrite */ X } else X tprev = t1; X if(t1->points == 0) break; X if( X#ifdef PERS_IS_UID X t1->uid == t0->uid && X#else X strncmp(t1->name, t0->name, NAMSZ) == 0 && X#endif X t1->plchar == t0->plchar && --occ_cnt <= 0){ X if(rank0 < 0){ X rank0 = 0; X rank1 = rank; X HUP printf("You didn't beat your previous score of %ld points.\n\n", X t1->points); X } X if(occ_cnt < 0){ X flg++; X continue; X } X } X if(rank <= ENTRYMAX){ X t1 = t1->tt_next = newttentry(); X rank++; X } X if(rank > ENTRYMAX){ X t1->points = 0; X break; X } X } X if(flg) { /* rewrite record file */ X (void) fclose(rfile); X if(!(rfile = fopen(recfile,"w"))){ X HUP puts("Cannot write record file\n"); X goto unlock; X } X X if(!done_stopprint) if(rank0 > 0){ X if(rank0 <= 10) X puts("You made the top ten list!\n"); X else X printf("You reached the %d%s place on the top %d list.\n\n", X rank0, ordin(rank0), ENTRYMAX); X } X } X if(rank0 == 0) rank0 = rank1; X if(rank0 <= 0) rank0 = rank; X if(!done_stopprint) outheader(); X t1 = tt_head; X for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) { X if(flg) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n", X t1->date, t1->uid, X t1->level, t1->maxlvl, X t1->hp, t1->maxhp, t1->points, X t1->plchar, t1->sex, t1->name, t1->death); X if(done_stopprint) continue; X if(rank > flags.end_top && X (rank < rank0-flags.end_around || rank > rank0+flags.end_around) X && (!flags.end_own || X#ifdef PERS_IS_UID X t1->uid != t0->uid X#else X strncmp(t1->name, t0->name, NAMSZ) X#endif X )) continue; X if(rank == rank0-flags.end_around && X rank0 > flags.end_top+flags.end_around+1 && X !flags.end_own) X (void) putchar('\n'); X if(rank != rank0) X (void) outentry(rank, t1, 0); X else if(!rank1) X (void) outentry(rank, t1, 1); X else { X int t0lth = outentry(0, t0, -1); X int t1lth = outentry(rank, t1, t0lth); X if(t1lth > t0lth) t0lth = t1lth; X (void) outentry(0, t0, t0lth); X } X } X if(rank0 >= rank) if(!done_stopprint) X (void) outentry(0, t0, 1); X (void) fclose(rfile); Xunlock: ; X#ifdef UNIX X (void) unlink(reclock); X#endif X} X Xoutheader() { Xchar linebuf[BUFSZ]; Xregister char *bp; X#ifdef KJSMODS X (void) strcpy(linebuf, " No Points Name"); X#else X (void) strcpy(linebuf, "Number Points Name"); X#endif X bp = eos(linebuf); X while(bp < linebuf + COLNO - 9) *bp++ = ' '; X (void) strcpy(bp, "Hp [max]"); X puts(linebuf); X} X X/* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */ Xint Xoutentry(rank,t1,so) register struct toptenentry *t1; { Xboolean quit = FALSE, killed = FALSE, starv = FALSE; Xchar linebuf[BUFSZ]; X linebuf[0] = 0; X if(rank) Sprintf(eos(linebuf), "%3d", rank); X else Sprintf(eos(linebuf), " "); X#ifdef KJSMODS X Sprintf(eos(linebuf), " %7ld %10s", t1->points, t1->name); X#else X# ifdef DGKMOD X Sprintf(eos(linebuf), " %6ld %10s", t1->points, t1->name); X# else X Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->name); X# endif X#endif X if(t1->plchar == 'X') Sprintf(eos(linebuf), " "); X else Sprintf(eos(linebuf), "-%c ", t1->plchar); X if(!strncmp("escaped", t1->death, 7)) { X if(!strcmp(" (with amulet)", t1->death+7)) X Sprintf(eos(linebuf), "escaped the dungeon with amulet"); X else X Sprintf(eos(linebuf), "escaped the dungeon [max level %d]", X t1->maxlvl); X } else { X if(!strncmp(t1->death,"quit",4)) { X quit = TRUE; X#ifndef KJSMODS X if(t1->maxhp < 3*t1->hp && t1->maxlvl < 4) X Sprintf(eos(linebuf), "cravenly gave up"); X else X#endif X Sprintf(eos(linebuf), "quit"); X } X else if(!strcmp(t1->death,"choked")) X Sprintf(eos(linebuf), "choked on %s food", X (t1->sex == 'F') ? "her" : "his"); X else if(!strncmp(t1->death,"starv",5)) X Sprintf(eos(linebuf), "starved to death"), starv = TRUE; X else Sprintf(eos(linebuf), ", killed"), killed = TRUE; X Sprintf(eos(linebuf), " on%s level %d", X (killed || starv) ? "" : " dungeon", t1->level); X if(t1->maxlvl != t1->level) X Sprintf(eos(linebuf), " [max %d]", t1->maxlvl); X if(quit && t1->death[4]) Sprintf(eos(linebuf), t1->death + 4); X } X if(killed) Sprintf(eos(linebuf), " by %s%s", X (!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4)) X ? "" : X index(vowels,*t1->death) ? "an " : "a ", X t1->death); X Sprintf(eos(linebuf), "."); X if(t1->maxhp) { X register char *bp = eos(linebuf); X char hpbuf[10]; X int hppos; X#ifdef KJSMODS X int lngr = strlen(linebuf); X#endif X Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-"); X hppos = COLNO - 7 - strlen(hpbuf); X#ifdef KJSMODS X if (lngr >= hppos) hppos = (2*COLNO) - 7 - strlen(hpbuf); X#endif X if(bp <= linebuf + hppos) { X /* pad any necessary blanks to the hit point entry */ X while(bp < linebuf + hppos) *bp++ = ' '; X (void) strcpy(bp, hpbuf); X Sprintf(eos(bp), " [%d]", t1->maxhp); X } X } X if(so == 0) puts(linebuf); X else if(so > 0) { X register char *bp = eos(linebuf); X if(so >= COLNO) so = COLNO-1; X while(bp < linebuf + so) *bp++ = ' '; X *bp = 0; X standoutbeg(); X fputs(linebuf,stdout); X standoutend(); X (void) putchar('\n'); X } X return(strlen(linebuf)); X} X Xchar * Xitoa(a) int a; { Xstatic char buf[12]; X Sprintf(buf,"%d",a); X return(buf); X} X Xchar * Xordin(n) int n; { Xregister int d = n%10; X return((d==0 || d>3 || n/10==1) ? "th" : (d==1) ? "st" : X (d==2) ? "nd" : "rd"); X} X Xchar * Xeos(s) Xregister char *s; X{ X while(*s) s++; X return(s); X} X X/* X * Called with args from main if argc >= 0. In this case, list scores as X * requested. Otherwise, find scores for the current player (and list them X * if argc == -1). X */ Xprscore(argc,argv) int argc; char **argv; { X extern char *hname; X char **players; X int playerct; X int rank; X register struct toptenentry *t1, *t2; X char *recfile = RECORD; X FILE *rfile; X register flg = 0; X register int i; X#ifdef nonsense X long total_score = 0L; X char totchars[10]; X int totcharct = 0; X#endif X int outflg = (argc >= -1); X#ifdef PERS_IS_UID X int uid = -1; X#else X char *player0; X#endif X X if(!(rfile = fopen(recfile,"r"))){ X puts("Cannot open record file!"); X return; X } X X if(argc > 1 && !strncmp(argv[1], "-s", 2)){ X if(!argv[1][2]){ X argc--; X argv++; X } else if(!argv[1][3] && index("CFKSTWX", argv[1][2])) { X argv[1]++; X argv[1][0] = '-'; X } else argv[1] += 2; X } X if(argc <= 1){ X#ifdef PERS_IS_UID X uid = getuid(); X playerct = 0; X#else X player0 = plname; X if(!*player0) X player0 = "hackplayer"; X playerct = 1; X players = &player0; X#endif X } else { X playerct = --argc; X players = ++argv; X } X if(outflg) putchar('\n'); X X t1 = tt_head = newttentry(); X for(rank = 1; ; rank++) { X if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]", X t1->date, &t1->uid, X &t1->level, &t1->maxlvl, X &t1->hp, &t1->maxhp, &t1->points, X &t1->plchar, &t1->sex, t1->name, t1->death) != 11) X t1->points = 0; X if(t1->points == 0) break; X#ifdef PERS_IS_UID X if(!playerct && t1->uid == uid) X flg++; X else X#endif X for(i = 0; i < playerct; i++){ X if(strcmp(players[i], "all") == 0 || X strncmp(t1->name, players[i], NAMSZ) == 0 || X (players[i][0] == '-' && X players[i][1] == t1->plchar && X players[i][2] == 0) || X (digit(players[i][0]) && rank <= atoi(players[i]))) X flg++; X } X t1 = t1->tt_next = newttentry(); X } X (void) fclose(rfile); X if(!flg) { X if(outflg) { X printf("Cannot find any entries for "); X if(playerct < 1) printf("you.\n"); X else { X if(playerct > 1) printf("any of "); X for(i=0; ipoints != 0; rank++, t1 = t2) { X t2 = t1->tt_next; X#ifdef PERS_IS_UID X if(!playerct && t1->uid == uid) X goto outwithit; X else X#endif X for(i = 0; i < playerct; i++){ X if(strcmp(players[i], "all") == 0 || X strncmp(t1->name, players[i], NAMSZ) == 0 || X (players[i][0] == '-' && X players[i][1] == t1->plchar && X players[i][2] == 0) || X (digit(players[i][0]) && rank <= atoi(players[i]))){ X outwithit: X if(outflg) X (void) outentry(rank, t1, 0); X#ifdef nonsense X total_score += t1->points; X if(totcharct < sizeof(totchars)-1) X totchars[totcharct++] = t1->plchar; X#endif X break; X } X } X free((char *) t1); X } X#ifdef nonsense X totchars[totcharct] = 0; X X /* We would like to determine whether he is experienced. However, X the information collected here only tells about the scores/roles X that got into the topten (top 100?). We should maintain a X .hacklog or something in his home directory. */ X flags.beginner = (total_score < 6000); X for(i=0; i<6; i++) X if(!index(totchars, "CFKSTWX"[i])) { X flags.beginner = 1; X if(!pl_character[0]) pl_character[0] = "CFKSTWX"[i]; X break; X } X#endif /* nonsense /**/ X} END_OF_topten.c if test 12536 -ne `wc -c u_init.c <<'END_OF_u_init.c' X/* SCCS Id: @(#)u_init.c 2.3 88/01/21 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include X#include X#include "hack.h" X#ifdef GENIX X#define void int X#endif X X#define Strcpy (void) strcpy X#define Strcat (void) strcat X#define UNDEF_TYP 0 X#define UNDEF_SPE '\177' Xextern struct obj *addinv(); Xextern char *eos(); Xextern char plname[]; X#define IS_MAGIC(x) ((x)->olet == WAND_SYM || (x)->olet == POTION_SYM || \ X (x)->olet == RING_SYM || (x)->olet == SCROLL_SYM || \ X (x)->olet == SPBOOK_SYM) X Xstruct you zerou; Xchar pl_character[PL_CSIZ]; Xchar *(roles[]) = { /* must all have distinct first letter */ X /* roles[4] & [7] may be changed for females */ X "Archeologist", "Tourist", "Barbarian", "Knight", "Cave-man", X#ifdef NEWCLASS X "Samurai", "Ninja", "Priest", X#endif X#ifdef KAA X "Valkyrie", "Elf", "Healer", X#endif X "Wizard" X}; X#define NR_OF_ROLES SIZE(roles) Xchar rolesyms[NR_OF_ROLES + 1]; /* filled by u_init() */ X Xstruct trobj { X unsigned short trotyp; X schar trspe; X char trolet; X Bitfield(trquan,6); X Bitfield(trknown,1); X}; X X#ifdef WIZARD Xstruct trobj Extra_objs[] = { X { 0, 0, 0, 0, 0 }, X { 0, 0, 0, 0, 0 } X}; X#endif X Xstruct trobj Cave_man[] = { X#define C_ARROWS 2 X { CLUB, 1, WEAPON_SYM, 1, 1 }, X { BOW, 1, WEAPON_SYM, 1, 1 }, X { ARROW, 0, WEAPON_SYM, 25, 1 }, /* quan is variable */ X { LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1 }, X { 0, 0, 0, 0, 0} X}; X Xstruct trobj Barbarian[] = { X { TWO_HANDED_SWORD, 0, WEAPON_SYM, 1, 1 }, X { RING_MAIL, 0, ARMOR_SYM, 1, 1 }, X { 0, 0, 0, 0, 0 } X}; X Xstruct trobj Knight[] = { X { LONG_SWORD, 0, WEAPON_SYM, 1, 1 }, X { SPEAR, 2, WEAPON_SYM, 1, 1 }, X { RING_MAIL, 1, ARMOR_SYM, 1, 1 }, X { HELMET, 0, ARMOR_SYM, 1, 1 }, X { SHIELD, 0, ARMOR_SYM, 1, 1 }, X { PAIR_OF_GLOVES, 0, ARMOR_SYM, 1, 1 }, X { 0, 0, 0, 0, 0 } X}; X X#ifdef KAA Xstruct trobj Elf[] = { X#define E_ARROWS 2 X#define E_ARMOR 3 X { SHORT_SWORD, 0, WEAPON_SYM, 1, 1 }, X { BOW, 0, WEAPON_SYM, 1, 1 }, X { ARROW, 0, WEAPON_SYM, 25, 1 }, X { UNDEF_TYP, 0, ARMOR_SYM, 1, 1 }, X { 0, 0, 0, 0, 0 } X}; X Xstruct trobj Valkyrie[] = { X { LONG_SWORD, 1, WEAPON_SYM, 1, 1 }, X { SHIELD, 3, ARMOR_SYM, 1, 1 }, X { FOOD_RATION, 0, FOOD_SYM, 1, 1 }, X { 0, 0, 0, 0, 0 } X}; X Xstruct trobj Healer[] = { X { STETHOSCOPE, 0, TOOL_SYM, 1, 0 }, X { POT_HEALING, 0, POTION_SYM, 4, 1 }, X { POT_EXTRA_HEALING, 0, POTION_SYM, 4, 1 }, X { APPLE, 0, FOOD_SYM, 5, 0 }, X { 0, 0, 0, 0, 0} X}; X#endif /* KAA /**/ X Xstruct trobj Archeologist[] = { X { STUDDED_LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1 }, X { UNDEF_TYP, 0, POTION_SYM, 2, 0 }, X { FOOD_RATION, 0, FOOD_SYM, 3, 1 }, X { PICK_AXE, UNDEF_SPE, TOOL_SYM, 1, 0 }, X { ICE_BOX, 0, TOOL_SYM, 1, 0 }, X { 0, 0, 0, 0, 0} X}; X Xstruct trobj Tinopener[] = { X { CAN_OPENER, 0, TOOL_SYM, 1, 1 }, X { 0, 0, 0, 0, 0 } X}; X X#ifdef MARKER Xstruct trobj Magicmarker[] = { X { MAGIC_MARKER, 50, TOOL_SYM, 1, 0 }, X { 0, 0, 0, 0, 0 } X}; X#endif X Xstruct trobj Lamp[] = { X { LAMP, 5, TOOL_SYM, 1, 0 }, X { 0, 0, 0, 0, 0 } X}; X X#ifdef WALKIES Xstruct trobj Leash[] = { X { LEASH, 0, TOOL_SYM, 1, 0 }, X { 0, 0, 0, 0, 0 } X}; X#endif X Xstruct trobj Blindfold[] = { X { BLINDFOLD, 0, TOOL_SYM, 1, 0 }, X { 0, 0, 0, 0, 0 } X}; X Xstruct trobj Tourist[] = { X#define T_DARTS 3 X { UNDEF_TYP, 0, FOOD_SYM, 10, 1 }, X { POT_EXTRA_HEALING, 0, POTION_SYM, 2, 0 }, X { EXPENSIVE_CAMERA, 0, TOOL_SYM, 1, 1 }, X { DART, 2, WEAPON_SYM, 25, 1 }, /* quan is variable */ X#ifdef SHIRT X { HAWAIIAN_SHIRT, 0, ARMOR_SYM, 1, 1 }, X#endif X { 0, 0, 0, 0, 0 } X}; X Xstruct trobj Wizard[] = { X#define W_MULTSTART 2 X#define W_MULTEND 6 X { ELVEN_CLOAK, 0, ARMOR_SYM, 1, 1 }, X { DAGGER, 0, WEAPON_SYM, 1, 1 }, /* for dealing with ghosts */ X { UNDEF_TYP, UNDEF_SPE, WAND_SYM, 2, 1 }, X { UNDEF_TYP, UNDEF_SPE, RING_SYM, 2, 1 }, X { UNDEF_TYP, UNDEF_SPE, POTION_SYM, 2, 1 }, X { UNDEF_TYP, UNDEF_SPE, SCROLL_SYM, 3, 1 }, X#ifdef SPELLS X { UNDEF_TYP, UNDEF_SPE, SPBOOK_SYM, 3, 1 }, X#endif X { 0, 0, 0, 0, 0 } X}; X X#ifdef NEWCLASS Xstruct trobj Samurai[] = { X#define S_ARROWS 3 X { KATANA, 0, WEAPON_SYM, 1, 1 }, X { SHORT_SWORD, 0, WEAPON_SYM, 1, 1 }, /* the wakizashi */ X { BOW, 1, WEAPON_SYM, 1, 1 }, X { ARROW, 0, WEAPON_SYM, 25, 1 }, /* quan is variable */ X { SPLINT_MAIL, 0, ARMOR_SYM, 1, 1}, X { 0, 0, 0, 0, 0 } X}; X Xstruct trobj Ninja[] = { X#define N_SHURIKEN 1 X { KATANA, 0, WEAPON_SYM, 1, 1 }, X { SHURIKEN, 0, WEAPON_SYM, 25, 1 }, /* quan is variable */ X { LEATHER_ARMOR, 1, ARMOR_SYM, 1, 1}, X { 0, 0, 0, 0, 0 } X}; X Xstruct trobj Priest[] = { X { CHAIN_MAIL, 0, ARMOR_SYM, 1, 1 }, X { SHIELD, 0, ARMOR_SYM, 1, 1 }, X { MACE, 1, WEAPON_SYM, 1, 1 }, X { POT_HOLY_WATER, 0, POTION_SYM, 4, 1 }, X#ifdef SPELLS X { UNDEF_TYP, UNDEF_SPE, SPBOOK_SYM, 2, 0 }, X#endif X { 0, 0, 0, 0, 0 } X}; X#endif /* NEWCLASS /**/ X Xu_init(){ Xregister int i; Xchar exper = 'y', pc; Xextern char readchar(); X if(flags.female) { /* should have been set in HACKOPTIONS */ X roles[4] = "Cave-woman"; X#ifdef NEWCLASS X roles[7] = "Priestess"; X#endif X } X for(i = 0; i < NR_OF_ROLES; i++) X rolesyms[i] = roles[i][0]; X rolesyms[i] = 0; X X if(pc = pl_character[0]) { X if('a' <= pc && pc <= 'z') pc += 'A'-'a'; X if((i = role_index(pc)) >= 0) X goto got_suffix; /* implies experienced */ X printf("\nUnknown role: %c\n", pc); X pl_character[0] = pc = 0; X } X X printf("\nShall I pick a character for you (yes, no, or quit) ? [ynq] "); X X while(!index("yYnNqQ", (exper = readchar()))) bell(); X X printf("%c\n", exper); /* echo */ X X if (index("qQ", exper)) { X clearlocks(); X settty((char *) 0); X exit(0); X } X X if(index("Yy", exper)) { X exper = 0; X goto beginner; X } X X printf("\n Tell me what kind of character you are:\n"); X printf(" Are you"); X for(i = 0; i < NR_OF_ROLES; i++) { X printf(" %s %s", index("AEIOU",roles[i][0]) ? "an" : "a", roles[i]); X if((((i + 1) % 4) == 0) && (i != NR_OF_ROLES -1)) printf(",\n "); X else if(i < NR_OF_ROLES - 2) printf(","); X if(i == NR_OF_ROLES - 2) printf(" or"); X } X printf("? [%s or q(quit)] ", rolesyms); X X while(pc = readchar()) { X if (pc == 'q' || pc == 'Q') { X X clearlocks(); X settty((char *) 0); X exit(0); X } X if('a' <= pc && pc <= 'z') pc += 'A'-'a'; X if((i = role_index(pc)) >= 0) { X printf("%c\n", pc); /* echo */ X (void) fflush(stdout); /* should be seen */ X break; X } X if(pc == '\n') break; X bell(); X } X if(pc == '\n') pc = 0; X Xbeginner: X if(!pc) { X i = rn2(NR_OF_ROLES); X pc = rolesyms[i]; X printf("\nThis game you will be %s %s%s.\n", X (exper || index("AEIOU", roles[i][0])) ? "an" : "a", X exper ? "experienced " : "", roles[i]); X getret(); X /* give him some feedback in case mklev takes much time */ X (void) putchar('\n'); X (void) fflush(stdout); X } X if(exper) { X roles[i][0] = pc; X } X Xgot_suffix: X X (void) strncpy(pl_character, roles[i], PL_CSIZ-1); X pl_character[PL_CSIZ-1] = 0; X flags.beginner = 1; X u = zerou; X u.usym = '@'; X u.ulevel = 1; X u.uluck = 0; X init_uhunger(); X uarm = uarm2 = uarmh = uarms = uarmg = uwep = X#ifdef SHIRT X uarmu = X#endif X uball = uchain = uleft = uright = 0; X X#ifdef SPELLS X u.uen = u.uenmax = 1; X for (i = 0; i <= MAXSPELL; i++) spl_book[i].sp_id = NO_SPELL; X#endif X#ifdef PRAYERS X u.ublesscnt = 300; /* no prayers just yet */ X u.ublessed = 0; /* not worthy yet */ X u.ugangr = 0; /* gods not angry */ X#endif X#ifdef HARD X u.udemigod = u.udg_cnt = 0; /* not a demi-god yet... */ X#endif X#ifdef KAA X u.mh = u.mhmax = u.umonnum = u.mtimedone = 0; X#endif X#ifdef QUEST X u.uhorizon = 6; X#endif X switch(pc) { X case 'c': X case 'C': X Cave_man[C_ARROWS].trquan = 12 + rnd(9)*rnd(9); X u.uhp = u.uhpmax = 16; X u.ustr = u.ustrmax = 18; X ini_inv(Cave_man); X break; X case 't': X case 'T': X#ifdef KAA X objects[POT_EXTRA_HEALING].oc_name_known=1; X#endif X Tourist[T_DARTS].trquan = 20 + rnd(20); X u.ugold = u.ugold0 = rnd(1000); X u.uhp = u.uhpmax = 10; X u.ustr = u.ustrmax = 8; X ini_inv(Tourist); X if(!rn2(25)) ini_inv(Tinopener); X else if(!rn2(4)) ini_inv(Lamp); X#ifdef MARKER X else if(!rn2(25)) ini_inv(Magicmarker); X#endif X#ifdef WALKIES X else if(!rn2(25)) ini_inv(Leash); X#endif X break; X case 'w': X case 'W': X for(i = W_MULTSTART; i <= W_MULTEND; i++) X if(!rn2(5)) X Wizard[i].trquan += rn2(3) - 1; X u.uhp = u.uhpmax = 15; X u.ustr = u.ustrmax = 16; X#ifdef SPELLS X u.uen = u.uenmax += rn2(4); X#endif X ini_inv(Wizard); X#ifdef MARKER X if(!rn2(5)) ini_inv(Magicmarker); X#endif X if(!rn2(5)) ini_inv(Blindfold); X break; X case 'a': X case 'A': X Fast = INTRINSIC; X Stealth = INTRINSIC; X u.uhp = u.uhpmax = 12; X u.ustr = u.ustrmax = 10; X ini_inv(Archeologist); X if(!rn2(10)) ini_inv(Tinopener); X#ifdef MARKER X else if(!rn2(10)) ini_inv(Magicmarker); X#endif X break; X#ifdef KAA X case 'e': X case 'E': X Elf[E_ARROWS].trquan = 15+rnd(20); X Elf[E_ARMOR].trotyp = (rn2(2) ? ELFIN_CHAIN_MAIL : ELVEN_CLOAK); X Fast = INTRINSIC; X HSee_invisible = INTRINSIC; X u.uhp = u.uhpmax = 16; X u.ustr = u.ustrmax = 16; X ini_inv(Elf); X if(!rn2(5)) ini_inv(Blindfold); X else if(!rn2(6)) ini_inv(Lamp); X break; X case 'v': X case 'V': X Stealth = INTRINSIC; X HCold_resistance = INTRINSIC; X flags.female = TRUE; X u.uhp = u.uhpmax = 16; X u.ustr = u.ustrmax = 17; X ini_inv(Valkyrie); X if(!rn2(6)) ini_inv(Lamp); X break; X case 'h': X case 'H': X objects[POT_HEALING].oc_name_known=1; X objects[POT_EXTRA_HEALING].oc_name_known=1; X HPoison_resistance = INTRINSIC; X u.uhp = u.uhpmax = 16; X u.ustr = u.ustrmax = 15; X ini_inv(Healer); X if(!rn2(25)) ini_inv(Lamp); X break; X#endif X case 'k': X case 'K': X u.uhp = u.uhpmax = 12; X u.ustr = u.ustrmax = 10; X ini_inv(Knight); X break; X case 'b': X case 'B': X u.uhp = u.uhpmax = 14; X u.ustr = u.ustrmax = 17; X ini_inv(Barbarian); X if(!rn2(6)) ini_inv(Lamp); X break; X#ifdef NEWCLASS X case 's': X case 'S': X Fast = INTRINSIC; X u.uhp = u.uhpmax = 16; X u.ustr = u.ustrmax = 16; X Samurai[S_ARROWS].trquan = 12 + rnd(9)*rnd(9); X ini_inv(Samurai); X break; X case 'n': X case 'N': X Fast = INTRINSIC; X Stealth = INTRINSIC; X u.uhp = u.uhpmax = 15; X u.ustr = u.ustrmax = 10; X Ninja[N_SHURIKEN].trquan = 12 + rnd(9)*rnd(9); X ini_inv(Ninja); X if(!rn2(5)) ini_inv(Blindfold); X break; X case 'p': X case 'P': X u.uhp = u.uhpmax = 13; X u.ustr = u.ustrmax = 15; X# ifdef SPELLS X u.uen = u.uenmax += rn2(4); X# endif X ini_inv(Priest); X# ifdef KAA X uwep->dknown = 1; /* bless his primary weapon */ X# endif X# ifdef MARKER X if(!rn2(10)) ini_inv(Magicmarker); X# endif X else if(!rn2(10)) ini_inv(Lamp); X objects[POT_HOLY_WATER].oc_name_known = 1; X break; X#endif /* NEWCLASS /**/ X default: /* impossible */ X u.uhp = u.uhpmax = 12; X u.ustr = u.ustrmax = 16; X } X find_ac(); X if(!rn2(20)) { X register int d = rn2(7) - 2; /* biased variation */ X u.ustr += d; X u.ustrmax += d; X } X X#ifdef WIZARD X wiz_inv(); X#endif X /* make sure he can carry all he has - especially for T's */ X while(inv_weight() > 0 && u.ustr < 118) X u.ustr++, u.ustrmax++; X} X Xini_inv(trop) register struct trobj *trop; { Xregister struct obj *obj; Xextern struct obj *mkobj(); X while(trop->trolet) { X obj = mkobj(trop->trolet); X obj->known = trop->trknown; X /* not obj->dknown = 1; - let him look at it at least once */ X obj->cursed = 0; X if(obj->olet == WEAPON_SYM){ X obj->quan = trop->trquan; X trop->trquan = 1; X } X if(trop->trspe != UNDEF_SPE) X obj->spe = trop->trspe; X if(trop->trotyp != UNDEF_TYP) X obj->otyp = trop->trotyp; X else X if(obj->otyp == WAN_WISHING) /* gitpyr!robert */ X obj->otyp = WAN_DEATH; X obj->owt = weight(obj); /* defined after setting otyp+quan */ X obj = addinv(obj); X X /* X * if a magic item's 'known' bit is on, set its name known X */ X if (IS_MAGIC(obj) && obj->known) X objects[obj->otyp].oc_name_known=1; X X if(obj->olet == ARMOR_SYM){ X switch(obj->otyp){ X case SHIELD: X if(!uarms) setworn(obj, W_ARMS); X break; X case HELMET: X if(!uarmh) setworn(obj, W_ARMH); X break; X case PAIR_OF_GLOVES: X if(!uarmg) setworn(obj, W_ARMG); X break; X#ifdef SHIRT X case HAWAIIAN_SHIRT: X if(!uarmu) setworn(obj, W_ARMU); X break; X#endif X case ELVEN_CLOAK: X if(!uarm2) X setworn(obj, W_ARM); X break; X default: X if(!uarm) setworn(obj, W_ARM); X } X } X /* below changed by GAN 01/09/87 to allow wielding of X * pick-axe or can-opener if there is no weapon X */ X if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE || X obj->otyp == CAN_OPENER) X if(!uwep) setuwep(obj); X#ifndef PYRAMID_BUG X if(--trop->trquan) continue; /* make a similar object */ X#else X if(trop->trquan) { /* check if zero first */ X --trop->trquan; X if(trop->trquan) X continue; /* make a similar object */ X } X#endif X trop++; X } X} X X#ifdef WIZARD Xwiz_inv(){ Xregister struct trobj *trop = &Extra_objs[0]; Xextern char *getenv(); Xregister char *ep = getenv("INVENT"); Xregister int type; X while(ep && *ep) { X type = atoi(ep); X ep = index(ep, ','); X if(ep) while(*ep == ',' || *ep == ' ') ep++; X if(type <= 0 || type > NROFOBJECTS) continue; X trop->trotyp = type; X trop->trolet = objects[type].oc_olet; X trop->trspe = 4; X trop->trknown = 1; X trop->trquan = 1; X ini_inv(trop); X } X} X#endif /* WIZARD /**/ X Xplnamesuffix() { Xregister char *p; X if(p = rindex(plname, '-')) { X *p = 0; X pl_character[0] = p[1]; X pl_character[1] = 0; X if(!plname[0]) { X askname(); X plnamesuffix(); X } X } X} X Xrole_index(pc) Xchar pc; X{ /* must be called only from u_init() */ X /* so that rolesyms[] is defined */ X register char *cp; X X if(cp = index(rolesyms, pc)) X return(cp - rolesyms); X return(-1); X} END_OF_u_init.c if test 13336 -ne `wc -c unixmain.c <<'END_OF_unixmain.c' X/* SCCS Id: @(#)unixmain.c 2.3 88/01/21 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* main.c - (Unix) version */ X X#include X#include X#include "hack.h" X X#ifdef QUEST X#define gamename "NetQuest" X#else X#define gamename "NetHack" X#endif X Xextern char *getlogin(), *getenv(); Xextern char plname[PL_NSIZ], pl_character[PL_CSIZ]; X Xint (*afternmv)(); Xint (*occupation)(); X Xint done1(); Xint hangup(); X Xint hackpid; /* current pid */ Xint locknum; /* max num of players */ X#ifdef DEF_PAGER Xchar *catmore; /* default pager */ X#endif Xchar SAVEF[PL_NSIZ + 11] = "save/"; /* save/99999player */ Xchar *hname; /* name of the game (argv[0] of call) */ Xchar obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */ X Xextern char *nomovemsg; Xextern long wailmsg; X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X register int fd; X#ifdef CHDIR X register char *dir; X#endif X X hname = argv[0]; X hackpid = getpid(); X X#ifdef CHDIR /* otherwise no chdir() */ X /* X * See if we must change directory to the playground. X * (Perhaps hack runs suid and playground is inaccessible X * for the player.) X * The environment variable HACKDIR is overridden by a X * -d command line option (must be the first option given) X */ X X dir = getenv("HACKDIR"); X if(argc > 1 && !strncmp(argv[1], "-d", 2)) { X argc--; X argv++; X dir = argv[0]+2; X if(*dir == '=' || *dir == ':') dir++; X if(!*dir && argc > 1) { X argc--; X argv++; X dir = argv[0]; X } X if(!*dir) X error("Flag -d must be followed by a directory name."); X } X#endif /* CHDIR /**/ X#ifdef GRAPHICS X /* Set the default values of the presentation characters */ X memcpy((char *) &showsyms, (char *) &defsyms, sizeof(struct symbols)); X#endif X#ifdef HACKOPTIONS X initoptions(); X#endif X whoami(); X /* X * Now we know the directory containing 'record' and X * may do a prscore(). X */ X if(argc > 1 && !strncmp(argv[1], "-s", 2)) { X#ifdef CHDIR X chdirx(dir,0); X#endif X prscore(argc, argv); X exit(0); X } X X /* X * It seems he really wants to play. X * Remember tty modes, to be restored on exit. X */ X gettty(); X setbuf(stdout,obuf); X setrandom(); X startup(); X init_corpses(); /* initialize optional corpse names */ X cls(); X u.uhp = 1; /* prevent RIP on early quits */ X u.ux = FAR; /* prevent nscr() */ X (void) signal(SIGHUP, hangup); X X /* X * Find the creation date of this game, X * so as to avoid restoring outdated savefiles. X */ X gethdate(hname); X X /* X * We cannot do chdir earlier, otherwise gethdate will fail. X */ X#ifdef CHDIR X chdirx(dir,1); X#endif X X /* X * Process options. X */ X while(argc > 1 && argv[1][0] == '-'){ X argv++; X argc--; X switch(argv[0][1]){ X#ifdef WIZARD X case 'D': X if(!strcmp(getlogin(), WIZARD)) X wizard = TRUE; X else { X settty("Sorry, you can't operate in debug mode.\n"); X clearlocks(); X exit(0); X } X break; X#endif X#ifdef NEWS X case 'n': X flags.nonews = TRUE; X break; X#endif X case 'u': X if(argv[0][2]) X (void) strncpy(plname, argv[0]+2, sizeof(plname)-1); X else if(argc > 1) { X argc--; X argv++; X (void) strncpy(plname, argv[0], sizeof(plname)-1); X } else X printf("Player name expected after -u\n"); X break; X default: X /* allow -T for Tourist, etc. */ X (void) strncpy(pl_character, argv[0]+1, X sizeof(pl_character)-1); X X /* printf("Unknown option: %s\n", *argv); */ X } X } X X if(argc > 1) X locknum = atoi(argv[1]); X#ifdef MAX_NR_OF_PLAYERS X if(!locknum || locknum > MAX_NR_OF_PLAYERS) X locknum = MAX_NR_OF_PLAYERS; X#endif X#ifdef DEF_PAGER X if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER"))) X catmore = DEF_PAGER; X#endif X#ifdef MAIL X getmailstatus(); X#endif X#ifdef WIZARD X if(wizard) (void) strcpy(plname, "wizard"); else X#endif X if(!*plname || !strncmp(plname, "player", 4) X || !strncmp(plname, "games", 4)) X askname(); X plnamesuffix(); /* strip suffix from name; calls askname() */ X /* again if suffix was whole name */ X /* accepts any suffix */ X#ifdef WIZARD X if(!wizard) { X#endif X /* X * check for multiple games under the same name X * (if !locknum) or check max nr of players (otherwise) X */ X (void) signal(SIGQUIT,SIG_IGN); X (void) signal(SIGINT,SIG_IGN); X if(!locknum) X (void) strcpy(lock,plname); X getlock(); /* sets lock if locknum != 0 */ X#ifdef WIZARD X } else { X register char *sfoo; X extern char genocided[], fut_geno[]; X (void) strcpy(lock,plname); X if(sfoo = getenv("MAGIC")) X while(*sfoo) { X switch(*sfoo++) { X case 'n': (void) srand(*sfoo++); X break; X } X } X if(sfoo = getenv("GENOCIDED")){ X if(*sfoo == '!'){ X extern struct permonst mons[CMNUM+2]; X register struct permonst *pm = mons; X register char *gp = genocided; X X while(pm < mons+CMNUM+2){ X if(!index(sfoo, pm->mlet)) X *gp++ = pm->mlet; X pm++; X } X *gp = 0; X } else X (void) strcpy(genocided, sfoo); X (void) strcpy(fut_geno, genocided); X } X } X#endif /* WIZARD /**/ X setftty(); X (void) sprintf(SAVEF, "save/%d%s", getuid(), plname); X regularize(SAVEF+5); /* avoid . or / in name */ X if((fd = open(SAVEF,0)) >= 0 && X (uptodate(fd) || unlink(SAVEF) == 666)) { X (void) signal(SIGINT,done1); X pline("Restoring old save file..."); X (void) fflush(stdout); X if(!dorecover(fd)) X goto not_recovered; X pline("Hello %s%s, welcome to %s!", X (Badged) ? "Officer " : "", plname, gamename); X flags.move = 0; X } else { Xnot_recovered: X newgame(); X /* give welcome message before pickup messages */ X pline("Hello %s, welcome to %s!", plname, gamename); X#ifdef WIZARD X if (wizard && dlevel == 1) X# ifdef STOOGES Xpline ("The wiz is at %d, the medusa is at %d, and the stooges are at %d", X u.wiz_level, u.medusa_level, u.stooge_level); X# else X pline ("The wiz is at %d, and the medusa at %d", X u.wiz_level, u.medusa_level); X# endif X#endif X pickup(1); X read_engr_at(u.ux,u.uy); X flags.move = 1; X } X X flags.moonphase = phase_of_the_moon(); X if(flags.moonphase == FULL_MOON) { X pline("You are lucky! Full moon tonight."); X if(!u.uluck) change_luck(1); X } else if(flags.moonphase == NEW_MOON) { X pline("Be careful! New moon tonight."); X } X X initrack(); X X for(;;) { X if(flags.move) { /* actual time passed */ X X settrack(); X X if(moves%2 == 0 || X (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) { X extern struct monst *makemon(); X movemon(); X#ifdef HARD X if(!rn2(u.udemigod?25:(dlevel>30)?50:70)) X#else X if(!rn2(70)) X#endif X (void) makemon((struct permonst *)0, 0, 0); X } X if(Glib) glibr(); X timeout(); X ++moves; X#ifdef PRAYERS X if (u.ublesscnt) u.ublesscnt--; X#endif X if(flags.time) flags.botl = 1; X#ifdef KAA X if(u.mtimedone) X if(u.mh < 1) rehumanize(); X else X#endif X if(u.uhp < 1) { X pline("You die..."); X done("died"); X } X if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){ X wailmsg = moves; X#ifdef KAA X if(index("WEV", pl_character[0])) { X if (u.uhp == 1) X pline("%s is about to die.", pl_character); X else X pline("%s, your life force is running out.", X pl_character); X } else { X#endif X if(u.uhp == 1) X pline("You hear the wailing of the Banshee..."); X else X pline("You hear the howling of the CwnAnnwn..."); X#ifdef KAA X } X#endif X } X#ifdef KAA X if (u.mtimedone) { X if (u.mh < u.mhmax) { X if (Regeneration || !(moves%20)) { X flags.botl = 1; X u.mh++; X } X } X } X#endif X if(u.uhp < u.uhpmax) { X if(u.ulevel > 9) { X if(HRegeneration || !(moves%3)) { X flags.botl = 1; X u.uhp += rnd((int) u.ulevel-9); X if(u.uhp > u.uhpmax) X u.uhp = u.uhpmax; X } X } else if(HRegeneration || X (!(moves%(22-u.ulevel*2)))) { X flags.botl = 1; X u.uhp++; X } X } X#ifdef SPELLS X if ((u.uen u.uenmax) u.uen = u.uenmax; X flags.botl = 1; X } X#endif X if(Teleportation && !rn2(85)) tele(); X#if defined(KAA) && defined(BVH) X if(Polymorph && !rn2(100)) polyself(); X#endif X if(Searching && multi >= 0) (void) dosearch(); X gethungry(); X invault(); X amulet(); X#ifdef HARD X if (!rn2(50+(u.ulevel*3))) u_wipe_engr(rnd(3)); X if (u.udemigod) { X X u.udg_cnt--; X if(u.udg_cnt <= 0) { X X intervene(); X u.udg_cnt = rn1(200, 50); X } X } X#endif X } X if(multi < 0) { X if(!++multi){ X pline(nomovemsg ? nomovemsg : X "You can move again."); X nomovemsg = 0; X if(afternmv) (*afternmv)(); X afternmv = 0; X } X } X X find_ac(); X#ifndef QUEST X if(!flags.mv || Blind) X#endif X { X seeobjs(); X seemons(); X nscr(); X } X#ifdef DGK X if(flags.time) flags.botl = 1; X#endif X if(flags.botl || flags.botlx) bot(); X X flags.move = 1; X X if(multi >= 0 && occupation) { X X if (monster_nearby()) X stop_occupation(); X else if ((*occupation)() == 0) X occupation = 0; X continue; X } X X if(multi > 0) { X#ifdef QUEST X if(flags.run >= 4) finddir(); X#endif X lookaround(); X if(!multi) { /* lookaround may clear multi */ X flags.move = 0; X continue; X } X if(flags.mv) { X if(multi < COLNO && !--multi) X flags.mv = flags.run = 0; X domove(); X } else { X --multi; X rhack(save_cm); X } X } else if(multi == 0) { X#ifdef MAIL X ckmailstatus(); X#endif X rhack((char *) 0); X } X if(multi && multi%7 == 0) X (void) fflush(stdout); X } X} X Xglo(foo) Xregister foo; X{ X /* construct the string xlock.n */ X register char *tf; X X tf = lock; X while(*tf && *tf != '.') tf++; X (void) sprintf(tf, ".%d", foo); X} X X/* X * plname is filled either by an option (-u Player or -uPlayer) or X * explicitly (-w implies wizard) or by askname. X * It may still contain a suffix denoting pl_character. X */ Xaskname(){ Xregister int c,ct; X printf("\nWho are you? "); X (void) fflush(stdout); X ct = 0; X while((c = getchar()) != '\n'){ X if(c == EOF) error("End of input\n"); X /* some people get confused when their erase char is not ^H */ X if(c == '\010') { X if(ct) ct--; X continue; X } X if(c != '-') X if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_'; X if(ct < sizeof(plname)-1) plname[ct++] = c; X } X plname[ct] = 0; X if(ct == 0) askname(); X} X X/*VARARGS1*/ Ximpossible(s,x1,x2) Xregister char *s; X{ X pline(s,x1,x2); X pline("Program in disorder - perhaps you'd better Quit."); X} X X#ifdef CHDIR Xstatic Xchdirx(dir, wr) Xchar *dir; Xboolean wr; X{ X X# ifdef SECURE X if(dir /* User specified directory? */ X# ifdef HACKDIR X && strcmp(dir, HACKDIR) /* and not the default? */ X# endif X ) { X (void) setuid(getuid()); /* Ron Wessels */ X (void) setgid(getgid()); X } X# endif X X# ifdef HACKDIR X if(dir == NULL) X dir = HACKDIR; X# endif X X if(dir && chdir(dir) < 0) { X perror(dir); X error("Cannot chdir to %s.", dir); X } X X /* warn the player if he cannot write the record file */ X /* perhaps we should also test whether . is writable */ X /* unfortunately the access systemcall is worthless */ X if(wr) { X register fd; X X if(dir == NULL) X dir = "."; X if((fd = open(RECORD, 2)) < 0) { X printf("Warning: cannot write %s/%s", dir, RECORD); X getret(); X } else X (void) close(fd); X } X} X#endif /* CHDIR /**/ X Xstop_occupation() X{ X extern void pushch(); X X if(occupation) { X pline("You stop %s.", occtxt); X occupation = 0; X#ifdef REDO X multi = 0; X pushch(0); X#endif X } X} X Xwhoami() { X /* X * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS X * 2. Use $USER or $LOGNAME (if 1. fails) X * 3. Use getlogin() (if 2. fails) X * The resulting name is overridden by command line options. X * If everything fails, or if the resulting name is some generic X * account like "games", "play", "player", "hack" then eventually X * we'll ask him. X * Note that we trust him here; it is possible to play under X * somebody else's name. X */ X register char *s; X X#ifndef DGKMOD X initoptions(); X#endif X if(!*plname && (s = getenv("USER"))) X (void) strncpy(plname, s, sizeof(plname)-1); X if(!*plname && (s = getenv("LOGNAME"))) X (void) strncpy(plname, s, sizeof(plname)-1); X if(!*plname && (s = getlogin())) X (void) strncpy(plname, s, sizeof(plname)-1); X} X Xnewgame() { X extern struct monst *makedog(); X X fobj = fcobj = invent = 0; X fmon = fallen_down = 0; X ftrap = 0; X fgold = 0; X flags.ident = 1; X init_objects(); X u_init(); X X (void) signal(SIGINT,done1); X mklev(); X u.ux = xupstair; X u.uy = yupstair; X (void) inshop(); X setsee(); X flags.botlx = 1; X { X register struct monst *mtmp; X X /* Move the monster from under you or else X * makedog() will fail when it calls makemon(). X * - ucsfcgl!kneller X */ X if (mtmp = m_at(u.ux, u.uy)) mnexto(mtmp); X } X (void) makedog(); X seemons(); X#ifdef NEWS X if(flags.nonews || !readnews()) X /* after reading news we did docrt() already */ X#endif X docrt(); X return(0); X} X X#ifdef GENIX Xjhndist(x1,y1,x2,y2) X{ X int x,y; X x=x1-x2; X y=y1-y2; X return (x*x + y*y); X} X#endif END_OF_unixmain.c if test 12801 -ne `wc -c