billr@saab.CNA.TEK.COM (Bill Randle) (07/25/89)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu> Posting-number: Volume 7, Issue 79 Archive-name: NetHack3/Part24 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 24 (of 38)." # Contents: Install.dos src/dokick.c src/mondata.c src/pager.c # Wrapped by billr@saab on Sun Jul 23 21:33:07 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Install.dos' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Install.dos'\" else echo shar: Extracting \"'Install.dos'\" \(6416 characters\) sed "s/^X//" >'Install.dos' <<'END_OF_FILE' XInstructions for installing NetHack 3.0 on an MS-DOS system X=========================================================== X X1. Make sure all the NetHack files are in the appropriate directory structure. X You should have a main directory with subdirectories src, include, auxil, X amiga, and others. If you do not follow this structure, the Makefile X will not function properly. All the UNIX .c files and the source Makefile X belong in src; all the PC .c files and Makefiles belong in others; all the X .h files belong in include; other assorted files belong in auxil. The X PC version does not use any files from the amiga directory. X X If you downloaded or ftp'd the sources from a UNIX system, the lines will X probably end in UNIX-style newlines, instead of DOS-style carriage return X and line feed pairs. Turbo C in particular does not like these; you will X have to run a program such as Rahul Dhesi's 'flip' to convert them. X X2. Move everything from the others directory to your src directory; you'll X be needing it, especially pc*.c. PC NetHack needs msdos.c, ST NetHack X needs tos.c. X X3. You should have several Makefiles in your src directory now. If you are X using Microsoft C, rename Makefile.pc to Makefile; if Turbo C, rename X Makefile.tcc to Makefile, and also rename Maketcc.ini to Make.ini. X NDMake can find Make.ini anywhere on your PATH, so you may relocate it X if you wish. If you are using another compiler, you will have to adapt X one of the Makefiles and the Make.ini file to your needs. Good luck. X X As for the other Makefiles, I would delete them to make space, but you may X want to keep them around for comparison in case something goes wrong. Two X other Makefiles we will not be using, Makefile.top and Makefile.auxil, X reside in the top and auxil directories. We won't need those either. X X4. Go to the include subdirectory and edit config.h according to the comments X to match your system and desired set of features. Similarly edit X pcconf.h. X X The base size of the executable, with no extra features, will be around X 520K in size. Anything over 540K is likely not to work. With MicroSoft X C, here is an incomplete list of the costs of various additional features X in terms of executable size: X X ALTARS 4K X ARMY 1K X COM_COMPL 1K X COMPRESS 2K X DGK 7K X ENDGAME 2K X EXPLORE_MODE 1K X FOUNTAINS 2K X GOLEMS 2K X HARD - SEDUCE 5K X MSDOSCOLOR 1K X MUSIC 6K X POLYSELF 31K X PROBING 0K X REDO 1K X REINCARNATION 7K X SINKS 5K X SOUNDS 6K X SPELLS 10K X STRONGHOLD 13K X THEOLOGY 11K X THRONES 3K X WALKIES 4K X WALLIFIED_MAZE 0K X WIZARD 3K X X I eked by with just DGK, MSDOSCOLOR, REDO, HARD, MEDUSA, EXPLORE_MODE, X and WIZARD, to give you an idea of just how little leeway you have for all X these nifty features. Maybe those of you with overlay linkers can get by X with more. X X5. If you want to, look through system.h. This file attempts to match the X types for system calls and library routines with various flavors of X operating systems. Leaving this file alone is unlikely to cause problems, X but if you're using a different compiler and get compile errors with X any functions in the standard library, it's worth checking the X declarations there. X X6. If you want to change the high score list behavior, go to the src X subdirectory and look at the top of topten.c. You may want to change the X definitions of PERSMAX, POINTSMIN, and ENTRYMAX. I set POINTSMIN of X 51 and ENTRYMAX of 50 to keep the size of the score list down. X X7. Edit the top section of the Makefile. (If you are doing a full X recompile, or if you got your files from someplace besides the official X distribution, type 'touch makedefs.c' to make sure certain files (onames.h, X pm.h) get remade instead of relying on the potentially troublesome X timestamps.) Be sure the directory you want the game installed in X actually exists. If you elected to use the high-quality BSD random X routines by defining RANDOM in pcconf.h, you will have to add random.c X to the dependency and link macros. If you elected to use Fred Fish's X termcap library (bundled in as termcap.arc), you will have to generate X termcap.lib from those sources (follow the comments therein, if you can). X X Now, type 'make all', and take a long siesta; your computer will be X occupied for a long time. If all goes well, you will get an executable. X If you tried to compile in too many features, you probably will not get X a working one, and have to start over. X X8. Edit NetHack.cnf to reflect your particular setup, following the comments. X Then move the file to your game directory, along with the termcap file. X X If your game directory is not on your PATH, you will want to 'set HACKDIR X =\games\nethack' (or whatever directory you want to use) now, and add it X to your autoexec.bat if you'll be playing often. X X Make sure the support files data, rumors, cmdhelp, opthelp, help, hh, X history, and license (and oracles, if you compiled in that feature) got X copied to the game directory. If not, move them there from the auxil X directory yourself. rumors can be created manually by typing 'makedefs X -r'; data by typing 'makedefs -d'. X X If you compiled in the special levels, make sure castle, tower?, and X perhaps endgame are there, too. lev_comp file.des will create these. X XNotes: X X1. No, your old save files and bones files will not work with NetHack 3.0. X Don't bother trying to keep them. The old score list will work fine, X but I recommend you delete it and create a new, empty one ('type record X >record' will do this nicely). It is a good deal harder to achieve the X same scores in this version. X X2. To install an update of this version of NetHack after changing something, X type 'make' from the src directory. If you created the new version X yourself, it should be safe to use 'make update' as long as you did not X add, delete, or reorder monsters or objects and you did not change X the format of saved level files. If you did any of these things, you X should also delete any saved games and bones levels. (Trying to use such X files often produces amusing but useless confusions on the game's part.) END_OF_FILE if test 6416 -ne `wc -c <'Install.dos'`; then echo shar: \"'Install.dos'\" unpacked with wrong size! fi # end of 'Install.dos' fi if test -f 'src/dokick.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/dokick.c'\" else echo shar: Extracting \"'src/dokick.c'\" \(15059 characters\) sed "s/^X//" >'src/dokick.c' <<'END_OF_FILE' X/* SCCS Id: @(#)dokick.c 3.0 89/6/9 X/* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" X#include "eshk.h" X X#define martial() ((pl_character[0] == 'S' || pl_character[0] == 'P')) X X#ifdef KICK X X# ifdef WORM Xextern boolean notonhead; X# endif X Xstatic void Xkickdmg(mon, clumsy) Xregister struct monst *mon; Xregister boolean clumsy; X{ X register int mdx, mdy; X register int dmg = (((uarmg && X uarmg->otyp == GAUNTLETS_OF_POWER) ? X 25 : ACURR(A_STR) > 18 ? 18 : ACURR(A_STR))+ X ACURR(A_DEX)+ACURR(A_CON))/15; X X /* excessive wt affects dex, so it affects dmg */ X if(clumsy) dmg = dmg/2; X X /* kicking a dragon or an elephant will not harm it */ X if(thick_skinned(mon->data)) dmg = 0; X X X /* squeeze some guilt feelings... */ X if(mon->mtame) { X# ifdef SOUNDS X if (rn2(10)) yelp(mon); X else growl(mon); /* give them a moment's worry */ X# endif X mon->mtame--; X mon->mflee = mon->mtame ? 1 : 0; X# ifdef HISX X mon->mfleetim = mon->mfleetim + (dmg ? rnd(dmg) : 1); X# else X mon->mfleetim += (dmg ? rnd(dmg) : 1); X# endif X } X X mon->mhp -= (!martial() ? rnd(dmg) : rnd(dmg)+rnd(ACURR(A_DEX)/2)); X if(mon->mhp < 1) { X killed(mon); X return; X } X if(martial() && !bigmonst(mon->data) && !rn2(3) && !mon->mfroz) { X /* see if the monster has a place to move into */ X mdx = mon->mx + u.dx; X mdy = mon->my + u.dy; X if(goodpos(mdx, mdy)) { X pline("%s reels from the blow.", Monnam(mon)); X levl[mon->mx][mon->my].mmask = 0; X levl[mdx][mdy].mmask = 1; X mon->mx = mdx; X mon->my = mdy; X pmon(mon); X set_apparxy(mon); X } X } X X/* it is unchivalrous to attack the defenseless or from behind */ X if (pl_character[0] == 'K' && u.ualigntyp == U_LAWFUL && X u.ualign > -10 && (mon->mfroz || mon->msleep || mon->mflee)) X adjalign(-1); X X} X Xstatic void Xkick_monster(x, y) Xregister int x, y; X{ X register boolean clumsy = FALSE; X register struct monst *mon = m_at(x, y); X register int i, j; X X /* no need to check POLYSELF since only ghosts, which you can't turn */ X /* into, are noncorporeal */ X if(noncorporeal(mon->data)) { X Your("kick passes through!"); X return; X } X X if(special_case(mon)) return; X X setmangry(mon); X X if(Levitation && !rn2(3) && verysmall(mon->data) && X !is_floater(mon->data) && !is_flyer(mon->data)) { X You("are floating in the air, and miss wildly!"); X return; X } X X i = abs(inv_weight()); X j = weight_cap(); X X if(i < (j*3)/10) { X if(!rn2((i < j/10) ? 2 : (i < j/5) ? 3 : 4)) { X if(martial() && !rn2(2)) goto doit; X Your("clumsy kick does no damage."); X return; X } X if(i < j/10) clumsy = TRUE; X else if(!rn2((i < j/5) ? 2 : 3)) clumsy = TRUE; X } X X if(Fumbling) clumsy = TRUE; X X else if(uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25)) X clumsy = TRUE; Xdoit: X kludge("You kick %s.", mon_nam(mon)); X if(!rn2(clumsy ? 3 : 4) && (clumsy || !bigmonst(mon->data)) && X mon->mcansee && !thick_skinned(mon->data) && X !mon->mfroz && !mon->mstun && !mon->mconf) { X mnexto(mon); X if(mon->mx != x || mon->my != y) { X kludge("%s jumps, %s evading your %skick.", Monnam(mon), X clumsy ? "easily" : "nimbly", X clumsy ? "clumsy " : ""); X return; X } /* else fall to the next case */ X } X kickdmg(mon, clumsy); X} X#endif /* KICK */ X X/* return TRUE if caught, FALSE otherwise */ Xboolean Xghitm(mtmp, amount) Xregister struct monst *mtmp; Xregister long amount; X{ X if(!likes_gold(mtmp->data) && !mtmp->isshk X#if defined(ALTARS) && defined(THEOLOGY) X && !mtmp->ispriest X#endif X ) X wakeup(mtmp); X else { X mtmp->msleep = 0; X mtmp->meating = 0; X if(!rn2(4)) setmangry(mtmp); /* not always pleasing */ X X /* greedy monsters catch gold */ X pline("%s catches the gold.", Monnam(mtmp)); X mtmp->mgold += amount; X if (mtmp->isshk) { X long robbed = ESHK(mtmp)->robbed; X X if (robbed) { X robbed -= amount; X if (robbed < 0) robbed = 0; X pline("The amount %scovers %s recent losses.", X !robbed ? "" : "partially ", X ESHK(mtmp)->ismale ? "his" : "her"); X ESHK(mtmp)->robbed = robbed; X if(!robbed) X make_happy_shk(mtmp); X } else { X if(mtmp->mpeaceful) { X ESHK(mtmp)->credit += amount; X You("have %ld zorkmids in credit.", X ESHK(mtmp)->credit); X } else verbalize("Thanks, scum!"); X } X } X#if defined(ALTARS) && defined(THEOLOGY) X else if(mtmp->ispriest) { X if(mtmp->mpeaceful) X verbalize("Thank you for your contribution."); X else verbalize("Thanks, scum!"); X } X#endif X return(1); X } X return(0); X X} X Xboolean Xbad_kick_throw_pos(x,y) Xxchar x,y; X{ X register struct rm *lvl = &(levl[x][y]); X X return(!ACCESSIBLE(lvl->typ) || lvl->typ == SDOOR || X (IS_DOOR(lvl->typ) && (lvl->doormask & (D_CLOSED | D_LOCKED))) ); X} X Xstruct monst * Xghit(ddx, ddy, range) Xregister int ddx, ddy, range; X{ X register struct monst *mtmp = (struct monst *) 0; X X bhitpos.x = u.ux; X bhitpos.y = u.uy; X X tmp_at(-1, GOLD_SYM); /* open call */ X tmp_at(-3, (int)AT_GLD); X while(range-- > 0) { X bhitpos.x += ddx; X bhitpos.y += ddy; X if(levl[bhitpos.x][bhitpos.y].mmask) { X mtmp = m_at(bhitpos.x,bhitpos.y); X tmp_at(-1, -1); /* close call */ X return(mtmp); X } X /* stop on a zorkmid */ X if(levl[bhitpos.x][bhitpos.y].gmask || X levl[bhitpos.x][bhitpos.y].omask) { X tmp_at(-1, -1); /* close call */ X return (struct monst *)0; X } X if(bad_kick_throw_pos(bhitpos.x,bhitpos.y)) { X bhitpos.x -= ddx; X bhitpos.y -= ddy; X break; X } X tmp_at(bhitpos.x, bhitpos.y); X } X tmp_at(-1, -1); X return(struct monst *)0; X} X X#ifdef KICK Xstatic int Xkick_object(x, y) Xregister int x, y; X{ X register int range, odx, ody, cnt = 0; X register struct monst *mon; X register struct gold *gold; X register struct obj *otmp, *obj; X register boolean costly = FALSE; X X /* if a pile, the "top" object gets kicked */ X for (otmp = fobj; otmp; otmp = otmp->nobj) X if(otmp->ox == x && otmp->oy == y) X if(!otmp->cobj) X if (otmp != uchain) { X cnt++; X if(cnt == 1) obj = otmp; X } X X /* range < 2 means the object will not move. */ X /* maybe dexterity should also figure here. */ X if(cnt) range = (int)((ACURR(A_STR) > 18 ? 20 : X ACURR(A_STR))/2 - obj->owt/4); X else range = rnd((int)ACURR(A_STR)); X X if(range < 1) range = 1; /* safety... */ X if(martial()) range = range + rnd(3); X X /* see if the object has a place to move into */ X odx = x + u.dx; X ody = y + u.dy; X if(bad_kick_throw_pos(odx,ody)) X range = 1; X X if(Fumbling && !rn2(3)) { X Your("clumsy kick missed."); X return(1); X } X X if(!cnt && levl[x][y].gmask) { X long zm; X gold = g_at(x, y); X zm = gold->amount; X if(range < 2 || zm > 300L) /* arbitrary */ X return(0); X else { X freegold(gold); X if(!levl[x][y].mmask) newsym(x, y); X if(mon = ghit(u.dx, u.dy, range)) { X setmangry(mon); /* not a means for payment to shk */ X if(ghitm(mon, zm)) /* was it caught? */ X return(1); X } X mkgold(zm, bhitpos.x, bhitpos.y); X if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y); X } X return(1); X } X X if(obj->otyp == BOULDER || obj == uball) X return(0); X X /* a box gets a chance of breaking open here */ X if(Is_box(obj)) { X boolean otrp = obj->otrapped; X X if (!obj->olocked && (!rn2(3) || X (martial() && !rn2(2)))) { X pline("The lid slams open, then falls shut."); X if(otrp) goto gotcha; X return(1); X } else if (obj->olocked && X (!rn2(5) || (martial() && !rn2(2)))) { X You("break open the lock!"); X obj->olocked = 0; X if(otrp) { Xgotcha: X chest_trap(obj, LEG); X } X return(1); X } X /* let it fall through to the next cases... */ X } X X if(Levitation && !rn2(3)) { X You("miss."); /* do not identify the object */ X return(1); X } X X /* fragile objects should not be kicked */ X if (breaks(obj, FALSE)) return(1); X X costly = costly_spot(x, y); X X /* potions get a chance of breaking here */ X if(obj->olet == POTION_SYM) { X if(rn2(2)) { X You("smash the %s!", xname(obj)); X if(costly) addtobill(obj, FALSE); X potionbreathe(obj); X delobj(obj); /* takes care of omask */ X return(1); X } X } X X /* too heavy to move. make sure not to call bhit */ X /* in this function when range < 2 (a display bug */ X /* results otherwise). */ X if(range <= 2) { X if(Is_box(obj)) pline("THUD!"); X else pline("Thump!"); X if(!rn2(3) || martial()) return(1); X return(0); X } X X if(cnt > 1) { X /* Needed to fool bhit's display-cleanup to show */ X /* immediately the next object in the pile. We */ X /* know here that the object will move, so there */ X /* is no need to worry about omask. */ X obj->ox = u.ux; X obj->oy = u.uy; X } else { X levl[x][y].omask = 0; X if(!levl[x][y].gmask) newsym(x, y); X } X X mon = bhit(u.dx, u.dy, range, obj->olet, X (int (*)()) 0, (int (*)()) 0, obj); X if(mon) { X# ifdef WORM X if (mon->mx != bhitpos.x || mon->my != bhitpos.y) X notonhead = TRUE; X# endif X /* awake monster if sleeping */ X wakeup(mon); X if(thitmonst(mon, obj)) return(1); X } X if(costly && !costly_spot(bhitpos.x,bhitpos.y)) addtobill(obj, FALSE); X obj->ox = bhitpos.x; X obj->oy = bhitpos.y; X levl[obj->ox][obj->oy].omask = 1; X stackobj(obj); X return(1); X} X#endif /* KICK */ X X Xint Xdokick() { /* try to kick the door down - noisy! */ X register int x, y; X register struct rm *maploc; X register int avrg_attrib = (ACURR(A_STR)+ACURR(A_DEX)+ACURR(A_CON))/3; X X#ifdef POLYSELF X if(nolimbs(uasmon)) { X You("have no legs to kick with."); X return(0); X } X if(verysmall(uasmon)) { X You("are too small to do any kicking."); X return(0); X } X#endif X if(Wounded_legs) { X Your("%s %s in no shape for kicking.", X ((Wounded_legs & BOTH_SIDES)==BOTH_SIDES) X ? makeplural(body_part(LEG)) : body_part(LEG), X ((Wounded_legs & BOTH_SIDES)==BOTH_SIDES) ? "are" : "is"); X return(0); X } X X if(inv_weight() > 0) { X Your("load is too heavy to balance yourself for a kick."); X return(0); X } X X if(u.utrap) { X switch (u.utraptype) { X case TT_PIT: X pline("There's nothing to kick down here."); X case TT_WEB: X case TT_BEARTRAP: X You("can't move your %s!", body_part(LEG)); X } X return(0); X } X X if(!getdir(1)) return(0); X if(!u.dx && !u.dy) return(0); X X x = u.ux + u.dx; X y = u.uy + u.dy; X X if(u.uswallow) { X switch(rn2(3)) { X case 0: You("can't move your %s!", body_part(LEG)); X break; X case 1: pline("%s burps loudly.", Monnam(u.ustuck)); break; X default: Your("feeble kick has no effect."); break; X } X return(1); X } X X wake_nearby(); X u_wipe_engr(2); X X maploc = &levl[x][y]; X X#ifdef KICK X /* The next four main loops should stay in */ X /* their present order: monsters, objects, */ X /* non-doors, doors. */ X X if(maploc->mmask) { X kick_monster(x, y); X return(1); X } X X if((maploc->omask || maploc->gmask) && !Levitation) { X if(kick_object(x, y)) return(1); X else goto ouch; X } X X if(!IS_DOOR(maploc->typ)) { X if(maploc->typ == SDOOR) { X if(rn2(30) < avrg_attrib) { X pline("Crash! You kick open a secret door!"); X maploc->typ = DOOR; X atl(x, y, (char) DOOR_SYM); X if(maploc->doormask & D_TRAPPED) { X b_trapped("door"); X maploc->doormask = D_NODOOR; X } else X maploc->doormask = D_ISOPEN; X return(1); X } else goto ouch; X } X if(maploc->typ == SCORR) { X if(rn2(30) < avrg_attrib) { X pline("Crash! You kick open a secret passage!"); X maploc->typ = CORR; X atl(x, y, (char) CORR_SYM); X return(1); X } else goto ouch; X } X# ifdef THRONES X if(IS_THRONE(maploc->typ)) { X register int i; X if((u.uluck < 0 || maploc->doormask) && !rn2(3)) { X pline("CRASH! You destroy the throne."); X maploc->typ = ROOM; X maploc->doormask = 0; /* don't leave loose ends.. */ X mkgold((long)rnd(200), x, y); X prl(x, y); X return(1); X } else if(u.uluck && !rn2(3) && !maploc->doormask) { X You("kick loose some ornamental coins and gems!"); X mkgold((300L+(long)rn2(201)), x, y); X i = u.uluck + 1; X if(i > 6) i = 6; X while(i--) (void) mkobj_at(GEM_SYM, x, y); X prl(x, y); X /* prevent endless milking */ X maploc->doormask = T_LOOTED; X return(1); X } else if (!rn2(4)) { X register struct trap *ttmp = X maketrap(u.ux,u.uy,TRAPDOOR); X dotrap(ttmp); X return(1); X } X goto ouch; X } X# endif X# ifdef ALTARS X if(IS_ALTAR(maploc->typ)) { X You("kick the altar."); X if(!rn2(3)) goto ouch; X# ifdef THEOLOGY X altar_wrath(x, y); X# endif X return(1); X } X# endif X# ifdef SINKS X if(IS_SINK(maploc->typ)) { X if(rn2(5)) { X if(flags.soundok) X pline("Klunk! The pipes vibrate noisily."); X else pline("Klunk!"); X return(1); X } else if(!rn2(3) && X !(mons[PM_BLACK_PUDDING].geno & G_GENOD)) { X pline("A %s ooze gushes up from the drain!", X Hallucination ? hcolor() : black); X pmon(makemon(&mons[PM_BLACK_PUDDING], x, y)); X return(1); X# ifdef HARD X } else if(!rn2(3) && X# ifndef POLYSELF X poly_gender() != 2 && X# endif X !(mons[poly_gender() == 1 ? PM_INCUBUS : PM_SUCCUBUS].geno & G_GENOD)) { X /* can't resist... */ X pline("The dish washer returns!"); X pmon(makemon(&mons[poly_gender() == 1 ? PM_INCUBUS : PM_SUCCUBUS], x, y)); X return(1); X# endif X } else if(!rn2(3)) { X pline("Flupp! Muddy waste pops up from the drain."); X if(!maploc->doormask) { /* only once per sink */ X if(!Blind) X You("see a ring shining in its midst."); X (void) mkobj_at(RING_SYM, x, y); X prl(x, y); X maploc->doormask = T_LOOTED; X } X return(1); X } X goto ouch; X } X# endif X if(maploc->typ == STAIRS X# ifdef STRONGHOLD X || maploc->typ == LADDER X# endif X ) goto ouch; X if(IS_STWALL(maploc->typ)) { Xouch: X pline("Ouch! That hurts!"); X if(!rn2(3)) set_wounded_legs(RIGHT_SIDE, 5 + rnd(5)); X losehp(rnd(ACURR(A_CON) > 15 ? 3 : 5), "dumb move"); X return(1); X } X# ifdef STRONGHOLD X if (is_drawbridge_wall(x,y) >= 0) { X pline("The drawbridge is unaffected."); X return(1); X } X# endif X goto dumb; X } X#endif /* KICK */ X X if(maploc->doormask == D_ISOPEN || X maploc->doormask == D_BROKEN || X maploc->doormask == D_NODOOR) { X#ifdef KICK Xdumb: X#endif X if (martial() || ACURR(A_DEX) >= 16) { X You("kick at empty space."); X } else { X pline("Dumb move! You strain a muscle."); X set_wounded_legs(RIGHT_SIDE, 5 + rnd(5)); X } X return(0); X } X X /* door is known to be CLOSED or LOCKED */ X if(rnl(35) < avrg_attrib + (!martial() ? 0 : ACURR(A_DEX))) { X /* break the door */ X if(maploc->doormask & D_TRAPPED) { X pline("As you kick the door, it explodes!"); X b_trapped("door"); X maploc->doormask = D_NODOOR; X } else if(ACURR(A_STR) > 18 && !rn2(5) && !in_shop(x, y)) { X pline("As you kick the door, it shatters to pieces!"); X maploc->doormask = D_NODOOR; X } else { X pline("As you kick the door, it crashes open!"); X maploc->doormask = D_BROKEN; X if(in_shop(x, y) && !in_shop(u.ux, u.uy)) X pay_for_door(x, y, "break"); X } X } else pline("WHAMMM!!!"); X X return(1); X} END_OF_FILE if test 15059 -ne `wc -c <'src/dokick.c'`; then echo shar: \"'src/dokick.c'\" unpacked with wrong size! fi # end of 'src/dokick.c' fi if test -f 'src/mondata.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/mondata.c'\" else echo shar: Extracting \"'src/mondata.c'\" \(14444 characters\) sed "s/^X//" >'src/mondata.c' <<'END_OF_FILE' X/* SCCS Id: @(#)mondata.c 3.0 89/01/10 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" X#include "eshk.h" X#include "epri.h" X X/* These routines provide basic data for any type of monster. */ X Xboolean Xattacktype(ptr, atyp) X register struct permonst *ptr; X register int atyp; X{ X int i; X X for(i = 0; i < NATTK; i++) X if(ptr->mattk[i].aatyp == atyp) return(TRUE); X X return(FALSE); X} X Xboolean Xresists_ston(ptr) /* returns TRUE if monster is petrify resistant */ X register struct permonst *ptr; X{ X return (ptr->mflags1 & M1_STON_RES || dmgtype(ptr, AD_STON) || X dmgtype(ptr, AD_ACID)); X} X Xboolean Xresists_drli(ptr) /* returns TRUE if monster is drain-life resistant */ X X register struct permonst *ptr; X{ X return(is_undead(ptr) || is_demon(ptr) || is_were(ptr)); X} X Xboolean Xranged_attk(ptr) /* returns TRUE if monster can attack at range */ X register struct permonst *ptr; X{ X return (attacktype(ptr, AT_BREA) || attacktype(ptr, AT_WEAP) || X attacktype(ptr, AT_SPIT) || attacktype(ptr, AT_GAZE) || X attacktype(ptr, AT_MAGC)); X} X Xboolean Xcan_track(ptr) /* returns TRUE if monster can track well */ X register struct permonst *ptr; X{ X#ifdef NAMED_ITEMS X if(uwep && !strcmp(ONAME(uwep), "Excalibur")) return TRUE; X#endif X return(haseyes(ptr)); X} X X#ifdef POLYSELF Xboolean Xbreakarm(ptr) /* creature will break out of armor */ X register struct permonst *ptr; X{ X return(bigmonst(ptr) || (!verysmall(ptr) && !humanoid(ptr)) X#ifdef HARD X || ptr == &mons[PM_MARILITH] X#endif X ); X /* Marilith is about the only case of a monster which is otherwise X * humanoid but cannot wear armor (too many arms). Centaurs would X * be another except that they are already accounted for by X * bigmonst. X */ X} X Xboolean Xsliparm(ptr) /* creature will slide out of armor */ X register struct permonst *ptr; X{ X return(!bigmonst(ptr) && (verysmall(ptr) || ptr == &mons[PM_GHOST])); X} X#endif X Xboolean Xsticks(ptr) /* creature sticks other creatures it hits */ X register struct permonst *ptr; X{ X return(dmgtype(ptr,AD_STCK) || dmgtype(ptr,AD_WRAP) || X attacktype(ptr,AT_HUGS)); X} X X/* not one hundred percent correct: now a snake may hide under an X * invisible object. X */ Xboolean Xcanseemon(mtmp) X register struct monst *mtmp; X{ X return((!mtmp->minvis || See_invisible) X && (!mtmp->mhide || X (levl[mtmp->mx][mtmp->my].omask == 0 && X levl[mtmp->mx][mtmp->my].gmask == 0)) X && cansee(mtmp->mx, mtmp->my)); X} X Xboolean Xdmgtype(ptr, dtyp) X register struct permonst *ptr; X register int dtyp; X{ X int i; X X for(i = 0; i < NATTK; i++) X if(ptr->mattk[i].adtyp == dtyp) return TRUE; X X return FALSE; X} X Xint Xmonsndx(ptr) /* return an index into the mons array */ X struct permonst *ptr; X{ X register int i; X register struct permonst *mdat; X X if(ptr == &playermon) return(-1); X X for(i = 0, mdat = &mons[0]; mdat->mlet; i++) X if(ptr == mdat++) return(i); X X panic("monsndx - could not index monster (%x)", ptr); X return FALSE; /* will not get here */ X} X Xint Xname_to_mon(str) Xchar *str; X{ X /* Be careful. We must check the entire string in case it was X * something such as "ettin zombie corpse". The calling routine X * doesn't know about the "corpse" until the monster name has X * already been taken off the front, so we have to be able to X * read the name with extraneous stuff such as "corpse" stuck on X * the end. X * This causes a problem for names which prefix other names such X * as "ettin" on "ettin zombie". In this case we want the _longest_ X * name which exists. X * This also permits plurals created by adding suffixes such as 's' X * or 'es'. Other plurals must still be handled explicitly. X */ X register int i; X register int mntmp = -1; X register char *s; X char buf[BUFSZ]; X int len=0; X X Strcpy(buf, str); X str = buf; X if (!strncmp(str, "a ", 2)) str += 2; X else if (!strncmp(str, "an ", 3)) str += 3; X X /* Some irregular plurals */ X#ifdef HARD X if (!strncmp(str, "incubi", 6)) return PM_INCUBUS; X if (!strncmp(str, "succubi", 7)) return PM_SUCCUBUS; X#endif X if (!strncmp(str, "violet fungi", 12)) return PM_VIOLET_FUNGUS; X if (!strncmp(str, "homunculi", 9)) return PM_HOMUNCULUS; X if (!strncmp(str, "baluchitheria", 13)) return PM_BALUCHITHERIUM; X if (!strncmp(str, "lurkers above", 13)) return PM_LURKER_ABOVE; X if (!strncmp(str, "cavemen", 7)) return PM_CAVEMAN; X if (!strncmp(str, "cavewomen", 9)) return PM_CAVEWOMAN; X if (!strncmp(str, "zruties", 7)) return PM_ZRUTY; X if (!strncmp(str, "djinn", 5)) return PM_DJINNI; X /* be careful with "ies"; "priest", "zombies" */ X for(s=str; *s; s++) { X if (!strncmp(s, "vortices", 8)) { X Strcpy(s+4, "ex"); X break; X } X if (!strncmp(s, "jellies", 7) || !strncmp(s, "mummies", 7)) { X Strcpy(s+4, "y"); X break; X } X if (!strncmp(s, "ves", 3)) { X /* luckily no monster names end in fe or ve with ves plurals */ X Strcpy(s, "f"); X break; X } X } X X for(i = 0; mons[i].mlet; i++) { X if(!strncmp(mons[i].mname, str, strlen(mons[i].mname))) { X if (strlen(mons[i].mname) > len) { X mntmp = i; X len = strlen(mons[i].mname); X } X } X } X return mntmp; X} X X#ifdef POLYSELF Xboolean Xwebmaker(ptr) /* creature can spin a web */ X register struct permonst *ptr; X{ X return (ptr->mlet == S_SPIDER && ptr != &mons[PM_SCORPION]); X} X#endif X Xboolean Xis_female(mtmp) X register struct monst *mtmp; X{ X if (mtmp->isshk) return !ESHK(mtmp)->ismale; X#if defined(ALTARS) && defined(THEOLOGY) X if (mtmp->ispriest) return !EPRI(mtmp)->ismale; X#endif X return !!(mtmp->data->mflags1 & M1_FEM); X} X X/* Gender function. Differs from is_female() in that 1) It allows the monster X * type of a polymorphed shopkeeper to override ESHK(mtmp)->ismale, and 2) X * it returns 3 values (0=male, 1=female, 2=none) instead of 2. X */ Xint Xgender(mtmp) X register struct monst *mtmp; X{ X if (!humanoid(mtmp->data)) return 2; X if (mtmp->data->mflags1 & M1_FEM) return 1; X if (mtmp->data == &mons[PM_CAVEMAN] X || mtmp->data == &mons[PM_PRIEST] X#ifdef HARD X || mtmp->data == &mons[PM_INCUBUS] X#endif X ) return 0; X#if defined(ALTARS) && defined(THEOLOGY) X if (mtmp->ispriest) return !EPRI(mtmp)->ismale; X#endif X if (mtmp->isshk) return !ESHK(mtmp)->ismale; X return 0; X} X Xboolean Xlevl_follower(mtmp) Xregister struct monst *mtmp; X{ X return (mtmp->mtame || (mtmp->data->mflags1 & M1_STALK) || is_fshk(mtmp) X || (mtmp->iswiz && !mon_has_amulet(mtmp))); X} X Xstruct permonst * Xplayer_mon() X{ X switch (pl_character[0]) { X case 'A': return &mons[PM_ARCHEOLOGIST]; X case 'B': return &mons[PM_BARBARIAN]; X case 'C': if (flags.female) return &mons[PM_CAVEWOMAN]; X else return &mons[PM_CAVEMAN]; X case 'E': return &mons[PM_ELF]; X case 'H': return &mons[PM_HEALER]; X case 'K': return &mons[PM_KNIGHT]; X case 'P': if (flags.female) return &mons[PM_PRIESTESS]; X else return &mons[PM_PRIEST]; X case 'R': return &mons[PM_ROGUE]; X case 'S': return &mons[PM_SAMURAI]; X case 'T': return &mons[PM_TOURIST]; X case 'V': return &mons[PM_VALKYRIE]; X case 'W': return &mons[PM_WIZARD]; X default: impossible("what are you?"); X return &mons[PM_HUMAN]; X } X} X Xconst int grownups[][2] = { {PM_LITTLE_DOG, PM_DOG}, {PM_DOG, PM_LARGE_DOG}, X {PM_HELL_HOUND_PUP, PM_HELL_HOUND}, {PM_KITTEN, PM_HOUSECAT}, X {PM_HOUSECAT, PM_LARGE_CAT}, {PM_BABY_GREY_DRAGON, PM_GREY_DRAGON}, X {PM_BABY_RED_DRAGON, PM_RED_DRAGON}, X {PM_BABY_WHITE_DRAGON, PM_WHITE_DRAGON}, X {PM_BABY_BLUE_DRAGON, PM_BLUE_DRAGON}, X {PM_BABY_GREEN_DRAGON, PM_GREEN_DRAGON}, X {PM_BABY_ORANGE_DRAGON, PM_ORANGE_DRAGON}, X {PM_BABY_BLACK_DRAGON, PM_BLACK_DRAGON}, X {PM_BABY_YELLOW_DRAGON, PM_YELLOW_DRAGON}, X {PM_RED_NAGA_HATCHLING, PM_RED_NAGA}, X {PM_BLACK_NAGA_HATCHLING, PM_BLACK_NAGA}, X {PM_GOLDEN_NAGA_HATCHLING, PM_GOLDEN_NAGA}, X {PM_GUARDIAN_NAGA_HATCHLING, PM_GUARDIAN_NAGA}, X {PM_BABY_PURPLE_WORM, PM_PURPLE_WORM}, X#ifdef WORM X {PM_BABY_LONG_WORM, PM_LONG_WORM}, X#endif X#ifdef ARMY X {PM_SOLDIER, PM_SERGEANT}, X {PM_SERGEANT, PM_LIEUTENANT}, X {PM_LIEUTENANT, PM_CAPTAIN}, X#endif X {-1,-1} X}; X Xint little_to_big(montype) Xint montype; X{ X register int *i; X X for(i=grownups[0]; *i >= 0; i++) X if(montype == *i) return *(i+1); X return montype; X} X Xint big_to_little(montype) Xint montype; X{ X register int *i; X X for(i=grownups[0]; *i >= 0; i++) X if(montype == *(i+1)) return *i; X return montype; X} X X X#ifdef STUPID_CPP /* otherwise these functions are macros in mondata.h */ X Xint Xbigmonst(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_BIG) != 0L); X} X Xint Xverysmall(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_VSMALL) != 0L); X} X Xint Xis_flyer(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_FLY) != 0L); X} X Xint Xis_floater(ptr) struct permonst *ptr; { X return(ptr->mlet == S_EYE); X} X Xint Xis_swimmer(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_SWIM) != 0L); X} X Xint Xpasses_walls(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_WALLWALK) != 0L); X} X Xint Xnoncorporeal(ptr) struct permonst *ptr; { X return(ptr->mlet == S_GHOST); X} X Xint Xis_animal(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_ANIMAL) != 0L); X} X Xint Xhumanoid(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_HUMANOID) != 0L); X} X Xint Xis_undead(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_UNDEAD) != 0L); X} X Xint Xis_were(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_WERE) != 0L); X} X Xint haseyes(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_NOEYES) == 0L); X} X Xint Xnohands(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_NOHANDS) != 0L); X} X Xint Xlays_eggs(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_EGGS) != 0L); X} X Xint Xpoisonous(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_POIS) != 0L); X} X Xint Xresists_poison(ptr) struct permonst *ptr; { X return((ptr->mflags1 & (M1_POIS | M1_POIS_RES)) != 0L); X} X Xint Xresists_fire(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_FIRE_RES) != 0L); X} X Xint Xresists_cold(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_COLD_RES) != 0L); X} X Xint Xresists_acid(ptr) struct permonst *ptr; { X return(dmgtype(ptr, AD_ACID)); X} X Xint Xresists_elec(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_ELEC_RES) != 0L); X} X Xint Xresists_sleep(ptr) struct permonst *ptr; { X return((ptr->mflags1 & (M1_SLEE_RES | M1_UNDEAD)) != 0L); X} X Xint Xresists_disint(ptr) struct permonst *ptr; { X return(ptr == &mons[PM_BLACK_DRAGON] || X ptr == &mons[PM_BABY_BLACK_DRAGON]); X} X Xint Xregenerates(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_REGEN) != 0L); X} X Xint Xperceives(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_SEE_INVIS) != 0L); X} X Xint Xcan_teleport(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_TPORT) != 0L); X} X Xint Xcontrol_teleport(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_TPORT_CONTROL) != 0L); X} X Xint Xis_armed(ptr) struct permonst *ptr; { X return(attacktype(ptr, AT_WEAP)); X} X Xint Xlikes_gold(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_GREEDY) != 0L); X} X Xint Xlikes_gems(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_JEWELS) != 0L); X} X Xint Xlikes_objs(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_COLLECT) != 0L || is_armed(ptr)); X} X Xint Xlikes_magic(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_MAGIC) != 0L); X} X Xint Xhides_under(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_CONCEAL) != 0L); X} X Xint Xis_hider(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_HIDE) != 0L); X} X X# ifdef POLYSELF Xint Xpolyok(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_NOPOLY) == 0L); X} X# endif /* POLYSELF */ X Xint Xtunnels(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_TUNNEL) != 0L); X} X Xint Xneedspick(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_NEEDPICK) != 0L); X} X Xint Xis_elf(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_ELF) != 0L); X} X Xint Xis_dwarf(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_DWARF) != 0L); X} X Xint Xis_giant(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_GIANT) != 0L); X} X X# ifdef GOLEMS Xint Xis_golem(ptr) struct permonst *ptr; { X return(ptr->mlet == S_GOLEM); X} X# endif /* GOLEMS */ X Xint Xis_orc(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_ORC) != 0L); X} X Xint Xis_human(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_HUMAN) != 0L); X} X Xint Xis_demon(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_DEMON) != 0L); X} X Xint Xis_mercenary(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_MERC) != 0L); X} X Xint Xthrows_rocks(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_ROCKTHROW) != 0L); X} X Xint Xis_wanderer(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_WANDER) != 0L); X} X Xint Xis_lord(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_LORD) != 0L); X} X Xint Xis_prince(ptr) struct permonst *ptr; { X return((ptr->mflags1 & M1_PRINCE) != 0L); X} X X# ifdef HARD Xint Xis_ndemon(ptr) struct permonst *ptr; { X return(is_demon(ptr) && X (ptr->mflags1 & (M1_LORD | M1_PRINCE)) == 0L); X} X# else /* HARD */ Xint Xis_ndemon(ptr) struct permonst *ptr; { X return(ptr == &mons[PM_DEMON]); X} X# endif /* HARD */ X Xint Xis_dlord(ptr) struct permonst *ptr; { X return(is_demon(ptr) && is_lord(ptr)); X} X Xint Xis_dprince(ptr) struct permonst *ptr; { X return(is_demon(ptr) && is_prince(ptr)); X} X Xint Xtype_is_pname(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_PNAME) != 0L); X} X Xint Xalways_hostile(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_HOSTILE) != 0L); X} X Xint Xalways_peaceful(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_PEACEFUL) != 0L); X} X Xint Xstrongmonst(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_STRONG) != 0L); X} X Xint Xextra_nasty(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_NASTY) != 0L); X} X X# ifdef POLYSELF Xint Xcan_breathe(ptr) struct permonst *ptr; { X return(attacktype(ptr, AT_BREA)); X} X Xint Xcantwield(ptr) struct permonst *ptr; { X return(nohands(ptr) || verysmall(ptr)); X} X Xint Xcantweararm(ptr) struct permonst *ptr; { X return(breakarm(ptr) || sliparm(ptr)); X} X Xint Xnolimbs(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_NOLIMBS) != 0L); X} X# endif /* POLYSELF */ X Xint Xcarnivorous(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_CARNIVORE) != 0L); X} X Xint Xherbivorous(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_HERBIVORE) != 0L); X} X Xint Xthick_skinned(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_THICK_HIDE) != 0L); X} X Xint Xamorphous(ptr) struct permonst *ptr; { X return((ptr->mflags2 & M2_AMORPHOUS) != 0L); X} X X#endif /* STUPID_CPP */ END_OF_FILE if test 14444 -ne `wc -c <'src/mondata.c'`; then echo shar: \"'src/mondata.c'\" unpacked with wrong size! fi # end of 'src/mondata.c' fi if test -f 'src/pager.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/pager.c'\" else echo shar: Extracting \"'src/pager.c'\" \(15100 characters\) sed "s/^X//" >'src/pager.c' <<'END_OF_FILE' X/* SCCS Id: @(#)pager.c 3.0 88/10/25 */ X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X/* This file contains the command routine dowhatis() and a pager. */ X/* Also readmail() and doshell(), and generally the things that X contact the outside world. */ X X/* block some unused #defines to avoid overloading some cpp's */ X#define MONATTK_H X#include "hack.h" X X#ifndef TOS X#include <signal.h> X#endif X#if defined(BSD) || defined(ULTRIX) X#include <sys/wait.h> X#endif X Xstatic char hc = 0; X Xstatic void page_more(); X Xint Xdowhatis() X{ X FILE *fp; X char bufr[BUFSZ+6]; X register char *buf = &bufr[6], *ep, q; X register struct monst *mtmp; X X if(!(fp = fopen(DATAFILE, "r"))) X pline("Cannot open data file!"); X else { X coord cc; X uchar r; X X pline ("Specify unknown object by cursor? "); X q = ynq(); X cc.x = cc.y = -1; X if (q == 'q') { X (void) fclose(fp); X return 0; X } else if (q == 'n') { X pline("Specify what? "); X r = readchar(); X } else { X if(flags.verbose) X pline("Please move the cursor to the unknown object."); X getpos(&cc, TRUE, "the unknown object"); X r = levl[cc.x][cc.y].scrsym; X } X X if (r == showsyms.stone) q = defsyms.stone; X else if (r == showsyms.vwall) q = defsyms.vwall; X else if (r == showsyms.hwall) q = defsyms.hwall; X else if (r == showsyms.tlcorn) q = defsyms.tlcorn; X else if (r == showsyms.trcorn) q = defsyms.trcorn; X else if (r == showsyms.blcorn) q = defsyms.blcorn; X else if (r == showsyms.brcorn) q = defsyms.brcorn; X else if (r == showsyms.crwall) q = defsyms.crwall; X else if (r == showsyms.tuwall) q = defsyms.tuwall; X else if (r == showsyms.tdwall) q = defsyms.tdwall; X else if (r == showsyms.tlwall) q = defsyms.tlwall; X else if (r == showsyms.trwall) q = defsyms.trwall; X else if (r == showsyms.door) q = defsyms.door; X else if (r == showsyms.room) q = defsyms.room; X else if (r == showsyms.corr) q = defsyms.corr; X else if (r == showsyms.upstair) q = defsyms.upstair; X else if (r == showsyms.dnstair) q = defsyms.dnstair; X else if (r == showsyms.trap) q = defsyms.trap; X#ifdef FOUNTAINS X else if (r == showsyms.pool) q = defsyms.pool; X else if (r == showsyms.fountain) q = defsyms.fountain; X#endif X#ifdef THRONES X else if (r == showsyms.throne) q = defsyms.throne; X#endif X else if (r == showsyms.web) q = defsyms.web; X#ifdef SINKS X else if (r == showsyms.sink) q = defsyms.sink; X#endif X#ifdef ALTARS X else if (r == showsyms.altar) q = defsyms.altar; X#endif X else X q = r; X if (index(quitchars, q)) { X (void) fclose(fp); /* sweet@scubed */ X return 0; X } X if(q == '%') { X pline("%% a piece of food"); X (void) fclose(fp); X return 0; X } X X if(q != '\t') X while(fgets(buf,BUFSZ,fp)) X if(*buf == q) { X ep = index(buf, '\n'); X if(ep) *ep = 0; X /* else: bad data file */ X /* Expand tab 'by hand' */ X if(buf[1] == '\t'){ X buf = bufr; X buf[0] = r; X (void) strncpy(buf+1, " ", 7); X } X pline(buf); X if(cc.x != -1 && IS_ALTAR(levl[cc.x][cc.y].typ)) { X int type = levl[u.ux][u.uy].altarmask & ~A_SHRINE; X pline("(%s)", (type==0) ? "chaotic" : X (type==1) ? "neutral" : "lawful"); X } X if (!Invisible && u.ux==cc.x && u.uy==cc.y) { X pline("(%s named %s)", X#ifdef POLYSELF X u.mtimedone ? mons[u.umonnum].mname : X#endif X pl_character, plname); X } else if((q >= 'A' && q <= 'z') || index(";:& @`",q)) { X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) X if(mtmp->mx == cc.x && mtmp->my == cc.y) { X pline("(%s%s)", X mtmp->mtame ? "tame " : X mtmp->mpeaceful ? "peaceful " : "", X strncmp(lmonnam(mtmp), "the ", 4) X ? lmonnam(mtmp) : lmonnam(mtmp)+4); X break; X } X } X if(ep[-1] == ';') { X pline("More info? "); X if(yn() == 'y') { X page_more(fp,1); /* does fclose() */ X return 0; X } X } X (void) fclose(fp); /* kopper@psuvax1 */ X return 0; X } X pline("I've never heard of such things."); X (void) fclose(fp); X } X return 0; X} X Xint Xdowhatdoes() X{ X FILE *fp; X char bufr[BUFSZ+6]; X register char *buf = &bufr[6], *ep, q, ctrl; X X if(!(fp = fopen(CMDHELPFILE, "r"))) { X pline("Cannot open data file!"); X return 0; X } X pline("What command? "); X#ifdef UNIX X introff(); X#endif X q = readchar(); X#ifdef UNIX X intron(); X#endif X if (q == '\033') ctrl = '['; X else if (q != unctrl(q)) ctrl = q - 1 + 'A'; X else ctrl = 0; X while(fgets(buf,BUFSZ,fp)) X if ((!ctrl && *buf==q) || (ctrl && *buf=='^' && *(buf+1)==ctrl)) { X ep = index(buf, '\n'); X if(ep) *ep = 0; X if(!ctrl && buf[1] == '\t'){ X buf = bufr; X buf[0] = q; X (void) strncpy(buf+1, " ", 7); X } else if (ctrl && buf[2] == '\t'){ X buf = bufr + 1; X buf[0] = '^'; X buf[1] = ctrl; X (void) strncpy(buf+2, " ", 6); X } X pline(buf); X (void) fclose(fp); X return 0; X } X pline("I've never heard of such commands."); X (void) fclose(fp); X return 0; X} X X/* make the paging of a file interruptible */ Xstatic int got_intrup; X X#if !defined(MSDOS) && !defined(TOS) Xstatic int Xintruph(){ X (void) signal(SIGINT, (SIG_RET_TYPE) intruph); X got_intrup++; X return 0; X} X#endif X X/* simple pager, also used from dohelp() */ Xstatic void Xpage_more(fp,strip) XFILE *fp; Xint strip; /* nr of chars to be stripped from each line (0 or 1) */ X{ X register char *bufr; X#if !defined(MSDOS) && !defined(MINIMAL_TERM) X register char *ep; X#endif X#if !defined(MSDOS) && !defined(TOS) X int (*prevsig)() = (int (*)())signal(SIGINT, (SIG_RET_TYPE) intruph); X#endif X#if defined(MSDOS) || defined(MINIMAL_TERM) X /* There seems to be a bug in ANSI.SYS The first tab character X * after a clear screen sequence is not expanded correctly. Thus X * expand the tabs by hand -dgk X */ X int tabstop = 8, spaces; X char buf[BUFSIZ], *bufp, *bufrp; X X set_pager(0); X bufr = (char *) alloc((unsigned) COLNO); X while (fgets(buf, BUFSIZ, fp) && (!strip || *buf == '\t')){ X bufp = buf; X bufrp = bufr; X while (*bufp && *bufp != '\n') { X if (*bufp == '\t') { X spaces = tabstop - (bufrp - bufr) % tabstop; X while (spaces--) X *bufrp++ = ' '; X bufp++; X } else X *bufrp++ = *bufp++; X } X *bufrp = '\0'; X#else /* MSDOS /**/ X set_pager(0); X bufr = (char *) alloc((unsigned) COLNO); X bufr[COLNO-1] = 0; X while(fgets(bufr,COLNO-1,fp) && (!strip || *bufr == '\t')){ X ep = index(bufr, '\n'); X if(ep) X *ep = 0; X#endif /* MSDOS /**/ X if(got_intrup || page_line(bufr+strip)) { X set_pager(2); X goto ret; X } X } X set_pager(1); Xret: X free((genericptr_t) bufr); X (void) fclose(fp); X#if !defined(MSDOS) && !defined(TOS) X (void) signal(SIGINT, (SIG_RET_TYPE) prevsig); X got_intrup = 0; X#endif X} X Xstatic boolean whole_screen = TRUE; X#define PAGMIN 12 /* minimum # of lines for page below level map */ X Xvoid Xset_whole_screen() { /* called in termcap as soon as LI is known */ X whole_screen = (LI-ROWNO-2 <= PAGMIN || !CD); X} X X#ifdef NEWS Xint Xreadnews() { X register int ret; X X whole_screen = TRUE; /* force a docrt(), our first */ X ret = page_file(NEWS, TRUE); X set_whole_screen(); X return(ret); /* report whether we did docrt() */ X} X#endif X Xvoid Xset_pager(mode) Xregister int mode; /* 0: open 1: wait+close 2: close */ X{ X#ifdef LINT /* lint may handle static decl poorly -- static boolean so; */ X boolean so; X#else X static boolean so; X#endif X if(mode == 0) { X if(!whole_screen) { X /* clear topline */ X clrlin(); X /* use part of screen below level map */ X curs(1, ROWNO+4); X } else { X cls(); X } X so = flags.standout; X flags.standout = 1; X } else { X if(mode == 1) { X curs(1, LI); X more(); X } X flags.standout = so; X if(whole_screen) X docrt(); X else { X curs(1, ROWNO+4); X cl_eos(); X } X } X} X Xint Xpage_line(s) /* returns 1 if we should quit */ Xregister char *s; X{ X if(cury == LI-1) { X if(!*s) X return(0); /* suppress blank lines at top */ X (void) putchar('\n'); X cury++; X cmore("q\033"); X if(morc) { X morc = 0; X return(1); X } X if(whole_screen) X cls(); X else { X curs(1, ROWNO+4); X cl_eos(); X } X } X#ifdef TERMINFO X xputs(s); xputc('\n'); X#else X (void) puts(s); X#endif X cury++; X return(0); X} X X/* X * Flexible pager: feed it with a number of lines and it will decide X * whether these should be fed to the pager above, or displayed in a X * corner. X * Call: X * cornline(0, title or 0) : initialize X * cornline(1, text) : add text to the chain of texts X * cornline(2, morcs) : output everything and cleanup X * cornline(3, 0) : cleanup X * cornline(-1,"") : special, for help menu mode only X */ X Xvoid Xcornline(mode, text) Xint mode; Xchar *text; X{ X static struct line { X struct line *next_line; X char *line_text; X } *texthead, *texttail; X static int maxlen; X static int linect; X register struct line *tl; X register boolean hmenu = FALSE; X X if(mode == -1) { /* help menu display only */ X mode = 2; X hmenu = TRUE; X } X if(mode == 0) { X texthead = 0; X maxlen = 0; X linect = 0; X if(text) { X cornline(1, text); /* title */ X cornline(1, ""); /* blank line */ X } X return; X } X X if(mode == 1) { X register int len; X X if(!text) return; /* superfluous, just to be sure */ X linect++; X len = strlen(text) + 1; /* allow for an extra leading space */ X if(len > maxlen) X maxlen = len; X tl = (struct line *) X alloc((unsigned)(len + sizeof(struct line) + 1)); X tl->next_line = 0; X tl->line_text = (char *)(tl + 1); X tl->line_text[0] = ' '; X tl->line_text[1] = '\0'; X Strcat(tl->line_text, text); X if(!texthead) X texthead = tl; X else X texttail->next_line = tl; X texttail = tl; X return; X } X X /* --- now we really do it --- */ X if(mode == 2 && linect == 1) /* topline only */ X pline(texthead->line_text); X else X if(mode == 2) { X register int curline, lth; X X if(flags.toplin == 1) more(); /* ab@unido */ X remember_topl(); X X lth = CO - maxlen - 2; /* Use full screen width */ X if (linect < LI && lth >= 10) { /* in a corner */ X home (); X cl_end (); X flags.toplin = 0; X curline = 1; X for (tl = texthead; tl; tl = tl->next_line) { X#if defined(MSDOS) && !defined(AMIGA) X cmov (lth, curline); X#else X curs (lth, curline); X#endif X if(curline > 1) X cl_end (); X xputs(tl->line_text); X curx = curx + strlen(tl->line_text); X curline++; X } X if(hmenu) hc = lowc(readchar()); /* help menu display */ X#if defined(MSDOS) && !defined(AMIGA) X cmov (lth, curline); X#else X curs (lth, curline); X#endif X cl_end (); X if (!hmenu) cmore (text); X home (); X cl_end (); X docorner (lth, curline-1); X } else { /* feed to pager */ X set_pager(0); X for (tl = texthead; tl; tl = tl->next_line) { X if (page_line (tl->line_text)) { X set_pager(2); X goto cleanup; X } X } X if(text) { X cgetret(text); X set_pager(2); X } else X set_pager(1); X } X } X Xcleanup: X while(tl = texthead) { X texthead = tl->next_line; X free((genericptr_t) tl); X } X} X X#ifdef WIZARD Xstatic Xvoid Xwiz_help() X{ X cornline(0, "Wizard-Mode Quick Reference:"); X cornline(1, "^E == detect secret doors and traps."); X cornline(1, "^F == do magic mapping."); X cornline(1, "^G == create monster."); X cornline(1, "^I == identify items in pack."); X cornline(1, "^O == tell locations of special levels."); X cornline(1, "^T == do intra-level teleport."); X cornline(1, "^V == do trans-level teleport."); X cornline(1, "^W == make wish."); X cornline(1, "^X == show intrinsic attributes."); X cornline(1, ""); X cornline(2, ""); X} X#endif X Xstatic void Xhelp_menu() { X cornline(0, "Information available:"); X cornline(1, "a. Long description of the game and commands."); X cornline(1, "b. List of game commands."); X cornline(1, "c. Concise history of NetHack."); X cornline(1, "d. Info on a character in the game display."); X cornline(1, "e. Info on what a given key does."); X cornline(1, "f. List of game options."); X cornline(1, "g. Longer explanation of game options."); X cornline(1, "h. List of extended commands."); X cornline(1, "i. The NetHack license."); X#ifdef WIZARD X if (wizard) X cornline(1, "j. List of wizard-mode commands."); X#endif X cornline(1, ""); X#ifdef WIZARD X if (wizard) X cornline(1, "Select one of a,b,c,d,e,f,g,h,i,j or ESC: "); X else X#endif X cornline(1, "Select one of a,b,c,d,e,f,g,h,i or ESC: "); X cornline(-1,""); X} X Xint Xdohelp() X{ X char c; X X do { X help_menu(); X c = hc; X#ifdef WIZARD X } while ((c < 'a' || c > (wizard ? 'j' : 'i')) && !index(quitchars,c)); X#else X } while ((c < 'a' || c > 'i') && !index(quitchars,c)); X#endif X if (!index(quitchars, c)) { X switch(c) { X case 'a': (void) page_file(HELP, FALSE); break; X case 'b': (void) page_file(SHELP, FALSE); break; X case 'c': (void) dohistory(); break; X case 'd': (void) dowhatis(); break; X case 'e': (void) dowhatdoes(); break; X case 'f': option_help(); break; X case 'g': (void) page_file(OPTIONFILE, FALSE); break; X case 'h': (void) doextlist(); break; X case 'i': (void) page_file(LICENSE, FALSE); break; X#ifdef WIZARD X case 'j': wiz_help(); break; X#endif X } X } X return 0; X} X Xint Xdohistory() X{ X (void) page_file(HISTORY, FALSE); X return 0; X} X Xint Xpage_file(fnam, silent) /* return: 0 - cannot open fnam; 1 - otherwise */ Xregister char *fnam; Xboolean silent; X{ X#ifdef DEF_PAGER /* this implies that UNIX is defined */ X { X /* use external pager; this may give security problems */ X X register int fd = open(fnam, 0); X X if(fd < 0) { X if(!silent) pline("Cannot open %s.", fnam); X return(0); X } X if(child(1)){ X /* Now that child() does a setuid(getuid()) and a chdir(), X we may not be able to open file fnam anymore, so make X it stdin. */ X (void) close(0); X if(dup(fd)) { X if(!silent) Printf("Cannot open %s as stdin.\n", fnam); X } else { X (void) execl(catmore, "page", NULL); X if(!silent) Printf("Cannot exec %s.\n", catmore); X } X exit(1); X } X (void) close(fd); X } X#else X { X FILE *f; /* free after Robert Viduya */ X X if ((f = fopen (fnam, "r")) == (FILE *) 0) { X if(!silent) { X home(); perror (fnam); flags.toplin = 1; X pline ("Cannot open %s.", fnam); X } X return(0); X } X page_more(f, 0); X } X#endif /* DEF_PAGER /**/ X X return(1); X} X X#ifdef UNIX X#ifdef SHELL Xint Xdosh(){ Xregister char *str; X if(child(0)) { X if(str = getenv("SHELL")) X (void) execl(str, str, NULL); X else X (void) execl("/bin/sh", "sh", NULL); X pline("sh: cannot execute."); X exit(1); X } X return 0; X} X#endif /* SHELL /**/ X Xint Xchild(wt) Xint wt; X{ Xregister int f = fork(); X if(f == 0){ /* child */ X settty(NULL); /* also calls end_screen() */ X (void) setgid(getgid()); X (void) setuid(getuid()); X#ifdef CHDIR X (void) chdir(getenv("HOME")); X#endif X return(1); X } X if(f == -1) { /* cannot fork */ X pline("Fork failed. Try again."); X return(0); X } X /* fork succeeded; wait for child to exit */ X (void) signal(SIGINT,SIG_IGN); X (void) signal(SIGQUIT,SIG_IGN); X (void) wait( X#if defined(BSD) || defined(ULTRIX) X (union wait *) X#else X (int *) X#endif X 0); X gettty(); X setftty(); X (void) signal(SIGINT, (SIG_RET_TYPE) done1); X#ifdef WIZARD X if(wizard) (void) signal(SIGQUIT,SIG_DFL); X#endif X if(wt) getret(); X docrt(); X return(0); X} X#endif /* UNIX /**/ END_OF_FILE if test 15100 -ne `wc -c <'src/pager.c'`; then echo shar: \"'src/pager.c'\" unpacked with wrong size! fi # end of 'src/pager.c' fi echo shar: End of archive 24 \(of 38\). cp /dev/null ark24isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 38 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0