home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!news.tek.com!master!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v16i062: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part54/108
- Message-ID: <4365@master.CNA.TEK.COM>
- Date: 1 Feb 93 19:43:32 GMT
- Sender: news@master.CNA.TEK.COM
- Lines: 2307
- Approved: billr@saab.CNA.TEK.COM
- Xref: uunet comp.sources.games:1612
-
- Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
- Posting-number: Volume 16, Issue 62
- Archive-name: nethack31/Part54
- Supersedes: nethack3p9: Volume 10, Issue 46-102
- Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
-
-
-
- #! /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 54 (of 108)."
- # Contents: src/mklev.c src/save.c
- # Wrapped by billr@saab on Wed Jan 27 16:09:07 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'src/mklev.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/mklev.c'\"
- else
- echo shar: Extracting \"'src/mklev.c'\" \(33549 characters\)
- sed "s/^X//" >'src/mklev.c' <<'END_OF_FILE'
- X/* SCCS Id: @(#)mklev.c 3.1 92/10/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/* #define DEBUG /* uncomment to enable code debugging */
- X
- X#ifdef DEBUG
- X# ifdef WIZARD
- X#define debugpline if (wizard) pline
- X# else
- X#define debugpline pline
- X# endif
- X#endif
- X
- X/* for UNIX, Rand #def'd to (long)lrand48() or (long)random() */
- X/* croom->lx etc are schar (width <= int), so % arith ensures that */
- X/* conversion of result to int is reasonable */
- X
- X
- Xstatic void FDECL(mkfount,(int,struct mkroom *));
- X#ifdef SINKS
- Xstatic void FDECL(mksink,(struct mkroom *));
- X#endif
- Xstatic void FDECL(mkaltar,(struct mkroom *));
- Xstatic void NDECL(makevtele);
- Xstatic void NDECL(clear_level_structures);
- Xstatic void NDECL(makelevel);
- Xstatic boolean FDECL(bydoor,(XCHAR_P,XCHAR_P));
- Xstatic struct mkroom *FDECL(find_branch_room, (coord *));
- Xstatic struct mkroom *FDECL(pos_to_room, (XCHAR_P, XCHAR_P));
- Xstatic boolean FDECL(place_niche,(struct mkroom *,int*,int*,int*));
- Xstatic void FDECL(makeniche,(int));
- Xstatic void NDECL(make_niches);
- XSTATIC_PTR int FDECL(do_comp,(const genericptr,const genericptr));
- Xstatic void FDECL(dosdoor,(XCHAR_P,XCHAR_P,struct mkroom *,int));
- Xstatic void FDECL(join,(int,int,BOOLEAN_P));
- Xstatic void FDECL(do_room_or_subroom, (struct mkroom *,int,int,int,int,
- X BOOLEAN_P,SCHAR_P,BOOLEAN_P,BOOLEAN_P));
- Xstatic void NDECL(makerooms);
- Xstatic void FDECL(finddpos,(coord *,XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P));
- Xstatic void FDECL(mkinvpos, (XCHAR_P,XCHAR_P,int));
- X#ifdef MULDGN
- Xstatic void FDECL(mk_knox_portal, (XCHAR_P,XCHAR_P));
- X#endif
- X
- X#define create_vault() create_room(-1, -1, 2, 2, -1, -1, VAULT, TRUE)
- X#define init_vault() vault_x = -1
- X#define do_vault() (vault_x != -1)
- Xstatic xchar vault_x, vault_y;
- Xboolean goldseen;
- Xstatic boolean made_branch; /* used only during level creation */
- X
- X/* Args must be (const genericptr) so that qsort will always be happy. */
- X
- XSTATIC_PTR int
- Xdo_comp(vx,vy)
- Xconst genericptr vx;
- Xconst genericptr vy;
- X{
- X#ifdef LINT
- X/* lint complains about possible pointer alignment problems, but we know
- X that vx and vy are always properly aligned. Hence, the following
- X bogus definition:
- X*/
- X return (vx == vy) ? 0 : -1;
- X#else
- X register const struct mkroom *x, *y;
- X
- X x = (const struct mkroom *)vx;
- X y = (const struct mkroom *)vy;
- X if(x->lx < y->lx) return(-1);
- X return(x->lx > y->lx);
- X#endif /* LINT */
- X}
- X
- Xstatic void
- Xfinddpos(cc, xl,yl,xh,yh)
- Xcoord *cc;
- Xxchar xl,yl,xh,yh;
- X{
- X register xchar x, y;
- X
- X x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
- X y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
- X if(okdoor(x, y))
- X goto gotit;
- X
- X for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
- X if(okdoor(x, y))
- X goto gotit;
- X
- X for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
- X if(IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR)
- X goto gotit;
- X /* cannot find something reasonable -- strange */
- X x = xl;
- X y = yh;
- Xgotit:
- X cc->x = x;
- X cc->y = y;
- X return;
- X}
- X
- Xvoid
- Xsort_rooms()
- X{
- X#if defined(SYSV) || defined(DGUX)
- X qsort((genericptr_t) rooms, (unsigned)nroom, sizeof(struct mkroom), do_comp);
- X#else
- X qsort((genericptr_t) rooms, nroom, sizeof(struct mkroom), do_comp);
- X#endif
- X}
- X
- Xstatic void
- Xdo_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special, is_room)
- X register struct mkroom *croom;
- X int lowx, lowy;
- X register int hix, hiy;
- X boolean lit;
- X schar rtype;
- X boolean special;
- X boolean is_room;
- X{
- X register int x, y;
- X struct rm *lev;
- X
- X /* locations might bump level edges in wall-less rooms */
- X /* add/subtract 1 to allow for edge locations */
- X if(!lowx) lowx++;
- X if(!lowy) lowy++;
- X if(hix >= COLNO-1) hix = COLNO-2;
- X if(hiy >= ROWNO-1) hiy = ROWNO-2;
- X
- X if(lit) {
- X for(x = lowx-1; x <= hix+1; x++) {
- X lev = &levl[x][max(lowy-1,0)];
- X for(y = lowy-1; y <= hiy+1; y++)
- X lev++->lit = 1;
- X }
- X croom->rlit = 1;
- X } else
- X croom->rlit = 0;
- X
- X croom->lx = lowx;
- X croom->hx = hix;
- X croom->ly = lowy;
- X croom->hy = hiy;
- X croom->rtype = rtype;
- X croom->doorct = 0;
- X /* if we're not making a vault, doorindex will still be 0
- X * if we are, we'll have problems adding niches to the previous room
- X * unless fdoor is at least doorindex
- X */
- X croom->fdoor = doorindex;
- X croom->irregular = FALSE;
- X
- X croom->nsubrooms = 0;
- X croom->sbrooms[0] = (struct mkroom *) 0;
- X if (!special) {
- X for(x = lowx-1; x <= hix+1; x++)
- X for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
- X levl[x][y].typ = HWALL;
- X levl[x][y].horizontal = 1; /* For open/secret doors. */
- X }
- X for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
- X for(y = lowy; y <= hiy; y++) {
- X levl[x][y].typ = VWALL;
- X levl[x][y].horizontal = 0; /* For open/secret doors. */
- X }
- X for(x = lowx; x <= hix; x++) {
- X lev = &levl[x][lowy];
- X for(y = lowy; y <= hiy; y++)
- X lev++->typ = ROOM;
- X }
- X if (is_room) {
- X levl[lowx-1][lowy-1].typ = TLCORNER;
- X levl[hix+1][lowy-1].typ = TRCORNER;
- X levl[lowx-1][hiy+1].typ = BLCORNER;
- X levl[hix+1][hiy+1].typ = BRCORNER;
- X } else { /* a subroom */
- X wallification(lowx-1, lowy-1, hix+1, hiy+1);
- X }
- X }
- X}
- X
- X
- Xvoid
- Xadd_room(lowx, lowy, hix, hiy, lit, rtype, special)
- Xregister int lowx, lowy, hix, hiy;
- Xboolean lit;
- Xschar rtype;
- Xboolean special;
- X{
- X register struct mkroom *croom;
- X
- X croom = &rooms[nroom];
- X do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit,
- X rtype, special, (boolean) TRUE);
- X croom++;
- X croom->hx = -1;
- X nroom++;
- X}
- X
- Xvoid
- Xadd_subroom(proom, lowx, lowy, hix, hiy, lit, rtype, special)
- Xstruct mkroom *proom;
- Xregister int lowx, lowy, hix, hiy;
- Xboolean lit;
- Xschar rtype;
- Xboolean special;
- X{
- X register struct mkroom *croom;
- X
- X croom = &subrooms[nsubroom];
- X do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit,
- X rtype, special, (boolean) FALSE);
- X proom->sbrooms[proom->nsubrooms++] = croom;
- X croom++;
- X croom->hx = -1;
- X nsubroom++;
- X}
- X
- Xstatic void
- Xmakerooms()
- X{
- X boolean tried_vault = FALSE;
- X
- X /* make rooms until satisfied */
- X /* rnd_rect() will returns 0 if no more rects are available... */
- X while(nroom < MAXNROFROOMS && rnd_rect()) {
- X if(nroom >= (MAXNROFROOMS/6) && rn2(2) && !tried_vault) {
- X tried_vault = TRUE;
- X if (create_vault()) {
- X vault_x = rooms[nroom].lx;
- X vault_y = rooms[nroom].ly;
- X rooms[nroom].hx = -1;
- X }
- X } else
- X if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1))
- X return;
- X }
- X return;
- X}
- X
- Xstatic void
- Xjoin(a,b,nxcor)
- Xregister int a, b;
- Xboolean nxcor;
- X{
- X coord cc,tt, org, dest;
- X register int tx, ty, xx, yy;
- X register struct mkroom *croom, *troom;
- X register int dx, dy;
- X
- X croom = &rooms[a];
- X troom = &rooms[b];
- X
- X /* find positions cc and tt for doors in croom and troom
- X and direction for a corridor between them */
- X
- X if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return;
- X if(troom->lx > croom->hx) {
- X dx = 1;
- X dy = 0;
- X xx = croom->hx+1;
- X tx = troom->lx-1;
- X finddpos(&cc, xx, croom->ly, xx, croom->hy);
- X finddpos(&tt, tx, troom->ly, tx, troom->hy);
- X } else if(troom->hy < croom->ly) {
- X dy = -1;
- X dx = 0;
- X yy = croom->ly-1;
- X finddpos(&cc, croom->lx, yy, croom->hx, yy);
- X ty = troom->hy+1;
- X finddpos(&tt, troom->lx, ty, troom->hx, ty);
- X } else if(troom->hx < croom->lx) {
- X dx = -1;
- X dy = 0;
- X xx = croom->lx-1;
- X tx = troom->hx+1;
- X finddpos(&cc, xx, croom->ly, xx, croom->hy);
- X finddpos(&tt, tx, troom->ly, tx, troom->hy);
- X } else {
- X dy = 1;
- X dx = 0;
- X yy = croom->hy+1;
- X ty = troom->ly-1;
- X finddpos(&cc, croom->lx, yy, croom->hx, yy);
- X finddpos(&tt, troom->lx, ty, troom->hx, ty);
- X }
- X xx = cc.x;
- X yy = cc.y;
- X tx = tt.x - dx;
- X ty = tt.y - dy;
- X if(nxcor && levl[xx+dx][yy+dy].typ)
- X return;
- X if (okdoor(xx,yy) || !nxcor)
- X dodoor(xx,yy,croom);
- X
- X org.x = xx+dx; org.y = yy+dy;
- X dest.x = tx; dest.y = ty;
- X
- X if (!dig_corridor(org, dest, nxcor, CORR, STONE))
- X return;
- X
- X /* we succeeded in digging the corridor */
- X if (okdoor(tt.x, tt.y) || !nxcor)
- X dodoor(tt.x, tt.y, troom);
- X
- X if(smeq[a] < smeq[b])
- X smeq[b] = smeq[a];
- X else
- X smeq[a] = smeq[b];
- X}
- X
- Xvoid
- Xmakecorridors()
- X{
- X int a, b, i;
- X boolean any = TRUE;
- X
- X for(a = 0; a < nroom-1; a++) {
- X join(a, a+1, FALSE);
- X if(!rn2(50)) break; /* allow some randomness */
- X }
- X for(a = 0; a < nroom-2; a++)
- X if(smeq[a] != smeq[a+2])
- X join(a, a+2, FALSE);
- X for(a = 0; any && a < nroom; a++) {
- X any = FALSE;
- X for(b = 0; b < nroom; b++)
- X if(smeq[a] != smeq[b]) {
- X join(a, b, FALSE);
- X any = TRUE;
- X }
- X }
- X if(nroom > 2)
- X for(i = rn2(nroom) + 4; i; i--) {
- X a = rn2(nroom);
- X b = rn2(nroom-2);
- X if(b >= a) b += 2;
- X join(a, b, TRUE);
- X }
- X}
- X
- Xvoid
- Xadd_door(x,y,aroom)
- Xregister int x, y;
- Xregister struct mkroom *aroom;
- X{
- X register struct mkroom *broom;
- X register int tmp;
- X
- X aroom->doorct++;
- X broom = aroom+1;
- X if(broom->hx < 0)
- X tmp = doorindex;
- X else
- X for(tmp = doorindex; tmp > broom->fdoor; tmp--)
- X doors[tmp] = doors[tmp-1];
- X doorindex++;
- X doors[tmp].x = x;
- X doors[tmp].y = y;
- X for( ; broom->hx >= 0; broom++) broom->fdoor++;
- X}
- X
- Xstatic void
- Xdosdoor(x,y,aroom,type)
- Xregister xchar x, y;
- Xregister struct mkroom *aroom;
- Xregister int type;
- X{
- X boolean shdoor = ((*in_rooms(x, y, SHOPBASE))? TRUE : FALSE);
- X
- X if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs on already made doors */
- X type = DOOR;
- X levl[x][y].typ = type;
- X if(type == DOOR) {
- X if(!rn2(3)) { /* is it a locked door, closed, or a doorway? */
- X if(!rn2(5))
- X levl[x][y].doormask = D_ISOPEN;
- X else if(!rn2(6))
- X levl[x][y].doormask = D_LOCKED;
- X else
- X levl[x][y].doormask = D_CLOSED;
- X
- X if (levl[x][y].doormask != D_ISOPEN && !shdoor && !rn2(25))
- X levl[x][y].doormask |= D_TRAPPED;
- X } else
- X#ifdef STUPID
- X if (shdoor)
- X levl[x][y].doormask = D_ISOPEN;
- X else
- X levl[x][y].doormask = D_NODOOR;
- X#else
- X levl[x][y].doormask = (shdoor ? D_ISOPEN : D_NODOOR);
- X#endif
- X if(levl[x][y].doormask & D_TRAPPED) {
- X struct monst *mtmp;
- X
- X if (level_difficulty() >= 9 && !rn2(5) &&
- X !((mons[PM_SMALL_MIMIC].geno & (G_GENOD | G_EXTINCT)) &&
- X (mons[PM_LARGE_MIMIC].geno & (G_GENOD | G_EXTINCT)) &&
- X (mons[PM_GIANT_MIMIC].geno & (G_GENOD | G_EXTINCT)))) {
- X /* make a mimic instead */
- X levl[x][y].doormask = D_NODOOR;
- X mtmp = makemon(mkclass(S_MIMIC,0), x, y);
- X if (mtmp)
- X set_mimic_sym(mtmp);
- X }
- X }
- X /* newsym(x,y); */
- X } else { /* SDOOR */
- X if(shdoor || !rn2(5)) levl[x][y].doormask = D_LOCKED;
- X else levl[x][y].doormask = D_CLOSED;
- X
- X if(!shdoor && !rn2(20)) levl[x][y].doormask |= D_TRAPPED;
- X }
- X
- X add_door(x,y,aroom);
- X}
- X
- Xstatic boolean
- Xplace_niche(aroom,dy,xx,yy)
- Xregister struct mkroom *aroom;
- Xint *dy, *xx, *yy;
- X{
- X coord dd;
- X
- X if(rn2(2)) {
- X *dy = 1;
- X finddpos(&dd, aroom->lx, aroom->hy+1, aroom->hx, aroom->hy+1);
- X } else {
- X *dy = -1;
- X finddpos(&dd, aroom->lx, aroom->ly-1, aroom->hx, aroom->ly-1);
- X }
- X *xx = dd.x;
- X *yy = dd.y;
- X return(isok(*xx,*yy+*dy) && levl[*xx][(*yy)+(*dy)].typ == STONE);
- X}
- X
- X/* there should be one of these per trap */
- Xconst char *trap_engravings[TRAPNUM] = {
- X "", "", "", "", "", "", "",
- X "", "", "", "", "", "",
- X "ad ae?ar um", "?la? ?as ?er?", "ad ae?ar um",
- X "", "", "", ""
- X#ifdef POLYSELF
- X ,""
- X#endif
- X };
- X
- Xstatic void
- Xmakeniche(trap_type)
- Xint trap_type;
- X{
- X register struct mkroom *aroom;
- X register struct rm *rm;
- X register int vct = 8;
- X int dy, xx, yy;
- X register struct trap *ttmp;
- X
- X if(doorindex < DOORMAX)
- X while(vct--) {
- X aroom = &rooms[rn2(nroom)];
- X if(aroom->rtype != OROOM) continue; /* not an ordinary room */
- X if(aroom->doorct == 1 && rn2(5)) continue;
- X if(!place_niche(aroom,&dy,&xx,&yy)) continue;
- X
- X rm = &levl[xx][yy+dy];
- X if(trap_type || !rn2(4)) {
- X
- X rm->typ = SCORR;
- X if(trap_type) {
- X if(trap_type == TRAPDOOR && !Can_fall_thru(&u.uz))
- X trap_type = ROCKTRAP;
- X ttmp = maketrap(xx, yy+dy, trap_type);
- X ttmp->once = 1;
- X if (*trap_engravings[trap_type])
- X make_engr_at(xx, yy-dy, trap_engravings[trap_type], 0L, DUST);
- X }
- X dosdoor(xx, yy, aroom, SDOOR);
- X } else {
- X rm->typ = CORR;
- X if(rn2(7))
- X dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
- X else {
- X (void) mksobj_at(SCR_TELEPORTATION, xx, yy+dy, TRUE);
- X if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy, TRUE);
- X }
- X }
- X return;
- X }
- X}
- X
- Xstatic void
- Xmake_niches()
- X{
- X register int ct = rnd((nroom>>1) + 1);
- X boolean ltptr = TRUE,
- X vamp = TRUE;
- X
- X while(ct--) {
- X
- X if(depth(&u.uz) > 15 && !rn2(6) && ltptr) {
- X ltptr = FALSE;
- X makeniche(LEVEL_TELEP);
- X } else if(depth(&u.uz) > 5 && depth(&u.uz) < 25
- X && !rn2(6) && vamp) {
- X vamp = FALSE;
- X makeniche(TRAPDOOR);
- X } else makeniche(NO_TRAP);
- X }
- X}
- X
- Xstatic void
- Xmakevtele()
- X{
- X makeniche(TELEP_TRAP);
- X}
- X
- X/* clear out various globals that keep information on the current level.
- X * some of this is only necessary for some types of levels (maze, normal,
- X * special) but it's easier to put it all in one place than make sure
- X * each type initializes what it needs to separately.
- X */
- Xstatic void
- Xclear_level_structures()
- X{
- X static struct rm zerorm = { cmap_to_glyph(S_stone),
- X 0, 0, 0, 0, 0, 0, 0, 0 };
- X register int x,y;
- X register struct rm *lev;
- X
- X for(x=0; x<COLNO; x++) {
- X lev = &levl[x][0];
- X for(y=0; y<ROWNO; y++) {
- X *lev++ = zerorm;
- X#ifdef MICROPORT_BUG
- X level.objects[x][y] = (struct obj *)0;
- X level.monsters[x][y] = (struct monst *)0;
- X#endif
- X }
- X }
- X#ifndef MICROPORT_BUG
- X (void) memset((genericptr_t)level.objects, 0, sizeof(level.objects));
- X (void) memset((genericptr_t)level.monsters, 0, sizeof(level.monsters));
- X#endif
- X level.flags.nfountains = 0;
- X level.flags.nsinks = 0;
- X level.flags.has_shop = 0;
- X level.flags.has_vault = 0;
- X level.flags.has_zoo = 0;
- X level.flags.has_court = 0;
- X level.flags.has_morgue = 0;
- X level.flags.has_beehive = 0;
- X#ifdef ARMY
- X level.flags.has_barracks = 0;
- X#endif
- X level.flags.has_temple = 0;
- X level.flags.has_swamp = 0;
- X level.flags.noteleport = 0;
- X level.flags.hardfloor = 0;
- X level.flags.nommap = 0;
- X level.flags.hero_memory = 1;
- X level.flags.shortsighted = 0;
- X level.flags.is_maze_lev = 0;
- X level.flags.is_cavernous_lev = 0;
- X
- X nroom = 0;
- X rooms[0].hx = -1;
- X nsubroom = 0;
- X doorindex = 0;
- X init_rect();
- X init_vault();
- X xdnstair = ydnstair = xupstair = yupstair = 0;
- X sstairs.sx = sstairs.sy = 0;
- X xdnladder = ydnladder = xupladder = yupladder = 0;
- X made_branch = FALSE;
- X}
- X
- Xstatic void
- Xmakelevel()
- X{
- X register struct mkroom *croom, *troom;
- X register int tryct;
- X register int x, y;
- X struct monst *tmonst; /* always put a web with a spider */
- X
- X if(wiz1_level.dlevel == 0) init_dungeons();
- X oinit(); /* assign level dependent obj probabilities */
- X clear_level_structures();
- X
- X {
- X register s_level *slev = Is_special(&u.uz);
- X
- X /* check for special levels */
- X#ifdef REINCARNATION
- X if (slev && !Is_rogue_level(&u.uz))
- X#else
- X if (slev)
- X#endif
- X {
- X makemaz(slev->proto);
- X return;
- X } else if (dungeons[u.uz.dnum].proto[0]) {
- X makemaz("");
- X return;
- X#ifdef MULDGN
- X } else if (In_mines(&u.uz)) {
- X makemaz("minefill");
- X return;
- X } else if (In_quest(&u.uz)) {
- X char fillname[9];
- X s_level *loc_lev;
- X
- X Sprintf(fillname, "%c-locate", pl_character[0]);
- X loc_lev = find_level(fillname);
- X
- X Sprintf(fillname, "%c-fill", pl_character[0]);
- X Strcat(fillname,
- X (u.uz.dlevel < loc_lev->dlevel.dlevel) ? "a" : "b");
- X makemaz(fillname);
- X return;
- X#endif
- X } else if(In_hell(&u.uz) ||
- X (rn2(5) && u.uz.dnum == medusa_level.dnum
- X && depth(&u.uz) > depth(&medusa_level))) {
- X makemaz("");
- X return;
- X }
- X }
- X
- X /* otherwise, fall through - it's a "regular" level. */
- X
- X#ifdef REINCARNATION
- X if (Is_rogue_level(&u.uz)) {
- X makeroguerooms();
- X makerogueghost();
- X } else
- X#endif
- X makerooms();
- X sort_rooms();
- X
- X /* construct stairs (up and down in different rooms if possible) */
- X croom = &rooms[rn2(nroom)];
- X if (!Is_botlevel(&u.uz))
- X mkstairs(somex(croom), somey(croom), 0, croom); /* down */
- X if (nroom > 1) {
- X troom = croom;
- X croom = &rooms[rn2(nroom-1)];
- X if (croom == troom) croom++;
- X }
- X
- X if (u.uz.dlevel != 1) {
- X xchar sx, sy;
- X do {
- X sx = somex(croom);
- X sy = somey(croom);
- X } while(occupied(sx, sy));
- X mkstairs(sx, sy, 1, croom); /* up */
- X }
- X
- X#ifdef REINCARNATION
- X if (Is_rogue_level(&u.uz)) goto skip0;
- X#endif
- X makecorridors();
- X make_niches();
- X
- X /* make a secret treasure vault, not connected to the rest */
- X if(do_vault()) {
- X xchar w,h;
- X#ifdef DEBUG
- X debugpline("trying to make a vault...");
- X#endif
- X w = 1;
- X h = 1;
- X if (check_room(&vault_x, &w, &vault_y, &h, TRUE)) {
- X fill_vault:
- X add_room(vault_x, vault_y, vault_x+w,
- X vault_y+h, TRUE, VAULT, FALSE);
- X level.flags.has_vault = 1;
- X fill_room(&rooms[nroom - 1], FALSE);
- X#ifdef MULDGN
- X mk_knox_portal(vault_x+w, vault_y+h);
- X#endif
- X if(!rn2(3)) makevtele();
- X } else if(rnd_rect() && create_vault()) {
- X vault_x = rooms[nroom].lx;
- X vault_y = rooms[nroom].ly;
- X if (check_room(&vault_x, &w, &vault_y, &h, TRUE))
- X goto fill_vault;
- X else
- X rooms[nroom].hx = -1;
- X }
- X }
- X
- X#ifdef WIZARD
- X if(wizard && getenv("SHOPTYPE")) mkroom(SHOPBASE); else
- X#endif
- X if(depth(&u.uz) > 1 &&
- X depth(&u.uz) < depth(&medusa_level) &&
- X rn2(depth(&u.uz)) < 3) mkroom(SHOPBASE);
- X else if(depth(&u.uz) > 4 && !rn2(6)) mkroom(COURT);
- X else if(depth(&u.uz) > 6 && !rn2(7)) mkroom(ZOO);
- X else if(depth(&u.uz) > 8 && !rn2(5)) mkroom(TEMPLE);
- X else if(depth(&u.uz) > 9 && !rn2(5) &&
- X !(mons[PM_KILLER_BEE].geno & (G_GENOD | G_EXTINCT))) mkroom(BEEHIVE);
- X else if(depth(&u.uz) > 11 && !rn2(6)) mkroom(MORGUE);
- X else
- X#ifdef ARMY
- X if(depth(&u.uz) > 14 && !rn2(4) &&
- X !(mons[PM_SOLDIER].geno & (G_GENOD | G_EXTINCT))) mkroom(BARRACKS);
- X else
- X#endif
- X if(depth(&u.uz) > 18 && !rn2(6)) mkroom(SWAMP);
- X
- X#ifdef REINCARNATION
- Xskip0:
- X#endif
- X /* Place multi-dungeon branch. */
- X place_branch(Is_branchlev(&u.uz), 0, 0);
- X
- X /* for each room: put things inside */
- X for(croom = rooms; croom->hx > 0; croom++) {
- X if(croom->rtype != OROOM) continue;
- X
- X /* put a sleeping monster inside */
- X /* Note: monster may be on the stairs. This cannot be
- X avoided: maybe the player fell through a trap door
- X while a monster was on the stairs. Conclusion:
- X we have to check for monsters on the stairs anyway. */
- X
- X if(u.uhave.amulet || !rn2(3)) {
- X x = somex(croom); y = somey(croom);
- X tmonst = makemon((struct permonst *) 0, x,y);
- X if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER] &&
- X !is_pool(x,y))
- X (void) maketrap (x,y,WEB);
- X }
- X /* put traps and mimics inside */
- X goldseen = FALSE;
- X x = 8 - (level_difficulty()/6);
- X if (x <= 1) x = 2;
- X while (!rn2(x))
- X mktrap(0,0,croom,(coord*)0);
- X if(!goldseen && !rn2(3)) mkgold(0L, somex(croom), somey(croom));
- X#ifdef REINCARNATION
- X if(Is_rogue_level(&u.uz)) goto skip_nonrogue;
- X#endif
- X if(!rn2(10)) mkfount(0,croom);
- X#ifdef SINKS
- X if(!rn2(60)) mksink(croom);
- X#endif
- X if(!rn2(60)) mkaltar(croom);
- X /* put statues inside */
- X if(!rn2(20))
- X (void) mkcorpstat(STATUE, (struct permonst *)0,
- X somex(croom), somey(croom), TRUE);
- X
- X /* put box/chest inside;
- X * 40% chance for at least 1 box, regardless of number
- X * of rooms; about 5 - 7.5% for 2 boxes, least likely
- X * when few rooms; chance for 3 or more is neglible.
- X */
- X if(!rn2(nroom * 5 / 2))
- X (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
- X somex(croom), somey(croom), TRUE);
- X
- X /* maybe make some graffiti */
- X if(!rn2(27 + 3 * depth(&u.uz))) {
- X const char *mesg = random_engraving();
- X if (mesg) {
- X do {
- X x = somex(croom); y = somey(croom);
- X } while(levl[x][y].typ != ROOM && !rn2(40));
- X if (!(IS_POOL(levl[x][y].typ) ||
- X IS_FURNITURE(levl[x][y].typ)))
- X make_engr_at(x, y, mesg, 0L, MARK);
- X }
- X }
- X
- X#ifdef REINCARNATION
- X skip_nonrogue:
- X#endif
- X if(!rn2(3)) {
- X (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
- X tryct = 0;
- X while(!rn2(5)) {
- X if(++tryct > 100) {
- X impossible("tryct overflow4");
- X break;
- X }
- X (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
- X }
- X }
- X }
- X}
- X
- Xvoid
- Xmklev()
- X{
- X struct mkroom *croom;
- X
- X if(getbones()) return;
- X in_mklev = TRUE;
- X makelevel();
- X bound_digging();
- X in_mklev = FALSE;
- X if(!level.flags.is_maze_lev) {
- X for (croom = &rooms[0]; croom != &rooms[nroom]; croom++)
- X#ifdef SPECIALIZATION
- X topologize(croom, FALSE);
- X#else
- X topologize(croom);
- X#endif
- X }
- X}
- X
- Xvoid
- X#ifdef SPECIALIZATION
- Xtopologize(croom, do_ordinary)
- Xregister struct mkroom *croom;
- Xboolean do_ordinary;
- X#else
- Xtopologize(croom)
- Xregister struct mkroom *croom;
- X#endif
- X{
- X register int x, y, roomno = (croom - rooms) + ROOMOFFSET;
- X register int lowx = croom->lx, lowy = croom->ly;
- X register int hix = croom->hx, hiy = croom->hy;
- X#ifdef SPECIALIZATION
- X register schar rtype = croom->rtype;
- X#endif
- X register int subindex, nsubrooms = croom->nsubrooms;
- X
- X /* skip the room if already done; i.e. a shop handled out of order */
- X /* also skip if this is non-rectangular (it _must_ be done already) */
- X if (levl[lowx][lowy].roomno == roomno || croom->irregular)
- X return;
- X#ifdef SPECIALIZATION
- X# ifdef REINCARNATION
- X if (Is_rogue_level(&u.uz))
- X do_ordinary = TRUE; /* vision routine helper */
- X# endif
- X if ((rtype != OROOM) || do_ordinary)
- X#endif
- X {
- X /* do innards first */
- X for(x = lowx; x <= hix; x++)
- X for(y = lowy; y <= hiy; y++)
- X#ifdef SPECIALIZATION
- X if (rtype == OROOM)
- X levl[x][y].roomno = NO_ROOM;
- X else
- X#endif
- X levl[x][y].roomno = roomno;
- X /* top and bottom edges */
- X for(x = lowx-1; x <= hix+1; x++)
- X for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
- X levl[x][y].edge = 1;
- X if (levl[x][y].roomno)
- X levl[x][y].roomno = SHARED;
- X else
- X levl[x][y].roomno = roomno;
- X }
- X /* sides */
- X for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
- X for(y = lowy; y <= hiy; y++) {
- X levl[x][y].edge = 1;
- X if (levl[x][y].roomno)
- X levl[x][y].roomno = SHARED;
- X else
- X levl[x][y].roomno = roomno;
- X }
- X }
- X /* subrooms */
- X for (subindex = 0; subindex < nsubrooms; subindex++)
- X#ifdef SPECIALIZATION
- X topologize(croom->sbrooms[subindex], (rtype != OROOM));
- X#else
- X topologize(croom->sbrooms[subindex]);
- X#endif
- X}
- X
- X/* Find an unused room for a branch location. */
- Xstatic struct mkroom *
- Xfind_branch_room(mp)
- X coord *mp;
- X{
- X struct mkroom *croom = 0;
- X
- X if (nroom == 0) {
- X mazexy(mp); /* already verifies location */
- X } else {
- X /* not perfect - there may be only one stairway */
- X if(nroom > 2) {
- X int tryct = 0;
- X
- X do
- X croom = &rooms[rn2(nroom)];
- X while((croom == dnstairs_room || croom == upstairs_room ||
- X croom->rtype != OROOM) && (++tryct < 100));
- X } else
- X croom = &rooms[rn2(nroom)];
- X
- X do {
- X if (!somexy(croom, mp))
- X impossible("Can't place branch!");
- X } while(occupied(mp->x, mp->y) ||
- X (levl[mp->x][mp->y].typ != CORR && levl[mp->x][mp->y].typ != ROOM));
- X }
- X return croom;
- X}
- X
- X/* Find the room for (x,y). Return NULL of not in a room. */
- Xstatic struct mkroom *
- Xpos_to_room(x, y)
- X xchar x, y;
- X{
- X int i;
- X struct mkroom *curr;
- X
- X for (curr = rooms, i = 0; i < nroom; curr++, i++)
- X if (inside_room(curr, x, y)) return curr;;
- X return (struct mkroom *) 0;
- X}
- X
- X
- X/* If given a branch, randomly place a special stair or portal. */
- Xvoid
- Xplace_branch(br, x, y)
- Xbranch *br; /* branch to place */
- Xxchar x, y; /* location */
- X{
- X coord m;
- X d_level *dest;
- X boolean make_stairs;
- X struct mkroom *br_room;
- X
- X /*
- X * Return immediately if there is no branch to make or we have
- X * already made one. This routine can be called twice when
- X * a special level is loaded that specifies an SSTAIR location
- X * as a favored spot for a branch.
- X */
- X if (!br || made_branch) return;
- X
- X if (!x) { /* find random coordinates for branch */
- X br_room = find_branch_room(&m);
- X x = m.x;
- X y = m.y;
- X } else {
- X br_room = pos_to_room(x, y);
- X }
- X
- X if (on_level(&br->end1, &u.uz)) {
- X /* we're on end1 */
- X make_stairs = br->type != BR_NO_END1;
- X dest = &br->end2;
- X } else {
- X /* we're on end2 */
- X make_stairs = br->type != BR_NO_END2;
- X dest = &br->end1;
- X }
- X
- X if (br->type == BR_PORTAL) {
- X mkportal(x, y, dest->dnum, dest->dlevel);
- X } else if (make_stairs) {
- X sstairs.sx = x;
- X sstairs.sy = y;
- X sstairs.up = (char) on_level(&br->end1, &u.uz) ?
- X br->end1_up : !br->end1_up;
- X assign_level(&sstairs.tolev, dest);
- X sstairs_room = br_room;
- X
- X levl[x][y].ladder = sstairs.up ? LA_UP : LA_DOWN;
- X levl[x][y].typ = STAIRS;
- X }
- X /*
- X * Set made_branch to TRUE even if we didn't make a stairwell (i.e.
- X * make_stairs is false) since there is currently only one branch
- X * per level, if we failed once, we're going to fail again on the
- X * next call.
- X */
- X made_branch = TRUE;
- X}
- X
- Xstatic boolean
- Xbydoor(x, y)
- Xregister xchar x, y;
- X{
- X register boolean tmp1, tmp2;
- X
- X /* break up large expression to help some compilers */
- X tmp1 = (IS_DOOR(levl[x+1][y].typ) || levl[x+1][y].typ == SDOOR ||
- X IS_DOOR(levl[x-1][y].typ) || levl[x-1][y].typ == SDOOR);
- X tmp2 = (IS_DOOR(levl[x][y+1].typ) || levl[x][y+1].typ == SDOOR ||
- X IS_DOOR(levl[x][y-1].typ) || levl[x][y-1].typ == SDOOR);
- X return(tmp1 || tmp2);
- X}
- X
- X/* see whether it is allowable to create a door at [x,y] */
- Xint
- Xokdoor(x,y)
- Xregister xchar x, y;
- X{
- X register boolean near_door = bydoor(x, y);
- X
- X return((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL) &&
- X doorindex < DOORMAX && !near_door);
- X}
- X
- Xvoid
- Xdodoor(x,y,aroom)
- Xregister int x, y;
- Xregister struct mkroom *aroom;
- X{
- X if(doorindex >= DOORMAX) {
- X impossible("DOORMAX exceeded?");
- X return;
- X }
- X
- X dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR);
- X}
- X
- Xboolean
- Xoccupied(x, y)
- Xregister xchar x, y;
- X{
- X return(t_at(x, y) || levl[x][y].typ == STAIRS
- X || IS_FOUNTAIN(levl[x][y].typ)
- X || IS_THRONE(levl[x][y].typ)
- X#ifdef SINKS
- X || IS_SINK(levl[x][y].typ)
- X#endif
- X || levl[x][y].typ == ALTAR
- X || is_lava(x,y)
- X || is_pool(x,y)
- X || invocation_pos(x,y)
- X );
- X}
- X
- X/* make a trap somewhere (in croom if mazeflag = 0 && !tm) */
- X/* if tm != NULL, make trap at that location */
- Xvoid
- Xmktrap(num, mazeflag, croom, tm)
- Xregister int num, mazeflag;
- Xregister struct mkroom *croom;
- Xcoord *tm;
- X{
- X register int kind;
- X coord m;
- X
- X /* no traps in pools */
- X if (tm && is_pool(tm->x,tm->y)) return;
- X
- X if (num > 0 && num < TRAPNUM) {
- X kind = num;
- X#ifdef REINCARNATION
- X } else if (Is_rogue_level(&u.uz)) {
- X switch (rn2(7)) {
- X default: kind = BEAR_TRAP; break; /* 0 */
- X case 1: kind = ARROW_TRAP; break;
- X case 2: kind = DART_TRAP; break;
- X case 3: kind = TRAPDOOR; break;
- X case 4: kind = PIT; break;
- X case 5: kind = SLP_GAS_TRAP; break;
- X case 6: kind = RUST_TRAP; break;
- X }
- X#endif
- X } else if (Inhell && !rn2(5)) {
- X /* bias the frequency of fire traps in Gehennom */
- X kind = FIRE_TRAP;
- X } else {
- X unsigned lvl = level_difficulty();
- X
- X do {
- X kind = rnd(TRAPNUM-1);
- X /* reject "too hard" traps */
- X switch (kind) {
- X case LEVEL_TELEP:
- X case LANDMINE:
- X if (lvl < 5) kind = NO_TRAP; break;
- X case SPIKED_PIT:
- X#ifdef POLYSELF
- X case POLY_TRAP:
- X#endif
- X if (lvl < 6) kind = NO_TRAP; break;
- X case WEB:
- X case STATUE_TRAP:
- X if (lvl < 7) kind = NO_TRAP; break;
- X case FIRE_TRAP:
- X if (!Inhell) kind = NO_TRAP; break;
- X }
- X } while (kind == NO_TRAP || kind == MAGIC_PORTAL);
- X }
- X
- X if (kind == TRAPDOOR && !Can_fall_thru(&u.uz)) kind = ROCKTRAP;
- X
- X if (tm)
- X m = *tm;
- X else {
- X register int tryct = 0;
- X
- X do {
- X if (++tryct > 200)
- X return;
- X if (mazeflag)
- X mazexy(&m);
- X else if (!somexy(croom,&m))
- X return;
- X } while (occupied(m.x, m.y) || is_pool(m.x,m.y) ||
- X (sobj_at(BOULDER, m.x, m.y) &&
- X (kind == PIT || kind == SPIKED_PIT ||
- X kind == TRAPDOOR)));
- X }
- X
- X (void) maketrap(m.x, m.y, kind);
- X if (kind == WEB) (void) makemon(&mons[PM_GIANT_SPIDER], m.x, m.y);
- X}
- X
- Xvoid
- Xmkstairs(x, y, up, croom)
- Xxchar x, y;
- Xchar up;
- Xstruct mkroom *croom;
- X{
- X if (! (x || y)) {
- X impossible("mkstairs: bogus stair attempt at (%d,%d)", x, y);
- X return;
- X }
- X
- X /*
- X * We can't make a regular stair off an end of the dungeon. This
- X * attempt can happen when a special level is placed at an end and
- X * has an up or down stair specified in its description file.
- X */
- X if ((dunlev(&u.uz) == 1 && up) ||
- X (dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz) && !up))
- X return;
- X
- X if(up) {
- X xupstair = x;
- X yupstair = y;
- X upstairs_room = croom;
- X } else {
- X xdnstair = x;
- X ydnstair = y;
- X dnstairs_room = croom;
- X }
- X
- X levl[x][y].typ = STAIRS;
- X levl[x][y].ladder = up ? LA_UP : LA_DOWN;
- X}
- X
- Xstatic
- Xvoid
- Xmkfount(mazeflag,croom)
- Xregister int mazeflag;
- Xregister struct mkroom *croom;
- X{
- X coord m;
- X register int tryct = 0;
- X
- X do {
- X if(++tryct > 200) return;
- X if(mazeflag)
- X mazexy(&m);
- X else
- X if (!somexy(croom, &m))
- X return;
- X } while(occupied(m.x, m.y) || bydoor(m.x, m.y));
- X
- X /* Put a fountain at m.x, m.y */
- X levl[m.x][m.y].typ = FOUNTAIN;
- X /* Is it a "blessed" fountain? (affects drinking from fountain) */
- X if(!rn2(7)) levl[m.x][m.y].blessedftn = 1;
- X
- X level.flags.nfountains++;
- X}
- X
- X#ifdef SINKS
- Xstatic void
- Xmksink(croom)
- Xregister struct mkroom *croom;
- X{
- X coord m;
- X register int tryct = 0;
- X
- X do {
- X if(++tryct > 200) return;
- X if (!somexy(croom, &m))
- X return;
- X } while(occupied(m.x, m.y) || bydoor(m.x, m.y));
- X
- X /* Put a sink at m.x, m.y */
- X levl[m.x][m.y].typ = SINK;
- X
- X level.flags.nsinks++;
- X}
- X#endif /* SINKS /**/
- X
- X
- Xstatic void
- Xmkaltar(croom)
- Xregister struct mkroom *croom;
- X{
- X coord m;
- X register int tryct = 0;
- X aligntyp al;
- X
- X if(croom->rtype != OROOM) return;
- X
- X do {
- X if(++tryct > 200) return;
- X if (!somexy(croom, &m))
- X return;
- X } while(occupied(m.x, m.y) || bydoor(m.x, m.y));
- X
- X /* Put an altar at m.x, m.y */
- X levl[m.x][m.y].typ = ALTAR;
- X
- X /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
- X al = rn2((int)A_LAWFUL+2) - 1;
- X levl[m.x][m.y].altarmask = Align2amask( al );
- X}
- X
- X/*
- X * Major level transmutation: add a set of stairs (to the Sanctum) after
- X * an earthquake that leaves behind a a new topology, centered at inv_pos.
- X * Assumes there are no rooms within the invocation area and that inv_pos
- X * is not too close to the edge of the map. Also assume the hero can see.
- X */
- Xvoid
- Xmkinvokearea()
- X{
- X int dist;
- X xchar xmin = inv_pos.x, xmax = inv_pos.x;
- X xchar ymin = inv_pos.y, ymax = inv_pos.y;
- X register xchar i;
- X
- X pline("The floor shakes violently under you!");
- X pline("The walls around you begin to move and fall down!");
- X display_nhwindow(WIN_MESSAGE, TRUE);
- X
- X for(dist = 1; dist < 7; dist++) {
- X xmin--; xmax++;
- X
- X /* top and bottom */
- X if(dist != 3) { /* the area is wider that it is high */
- X ymin--; ymax++;
- X for(i = xmin+1; i < xmax; i++) {
- X mkinvpos(i, ymin, dist);
- X mkinvpos(i, ymax, dist);
- X }
- X }
- X
- X /* left and right */
- X for(i = ymin; i <= ymax; i++) {
- X mkinvpos(xmin, i, dist);
- X mkinvpos(xmax, i, dist);
- X }
- X
- X flush_screen(1); /* make sure the new glyphs shows up */
- X delay_output();
- X }
- X
- X You("are standing at the top of a stairwell leading down!");
- X mkstairs(u.ux, u.uy, 0, (struct mkroom *)0); /* down */
- X newsym(u.ux, u.uy);
- X vision_full_recalc = 1; /* everything changed */
- X}
- X
- X/* Change level topology. Messes with vision tables and ignores things like
- X * boulders in the name of a nice effect. Vision will get fixed up again
- X * immediately after the effect is complete.
- X */
- Xstatic void
- Xmkinvpos(x,y,dist)
- Xxchar x,y;
- Xint dist;
- X{
- X struct trap *ttmp;
- X register struct rm *lev = &levl[x][y];
- X
- X unblock_point(x,y); /* make sure vision knows this location is open */
- X
- X /* fake out saved state */
- X lev->seen = FALSE;
- X lev->doormask = 0;
- X if(dist < 6) lev->lit = TRUE;
- X lev->waslit = TRUE;
- X lev->horizontal = FALSE;
- X viz_array[y][x] = (dist < 6 ) ?
- X (IN_SIGHT|COULD_SEE) : /* short-circuit vision recalc */
- X COULD_SEE;
- X
- X switch(dist) {
- X case 1: /* fire traps */
- X lev->typ = ROOM;
- X if (is_pool(x,y)) break;
- X ttmp = maketrap(x, y, FIRE_TRAP);
- X ttmp->tseen = TRUE;
- X break;
- X case 2: /* lit room locations */
- X case 3:
- X case 6:
- X if ((ttmp = t_at(x,y)) != 0) deltrap(ttmp);
- X lev->typ = ROOM;
- X break;
- X case 4: /* pools (aka a wide moat) */
- X case 5:
- X if ((ttmp = t_at(x,y)) != 0) deltrap(ttmp);
- X lev->typ = MOAT;
- X break;
- X default:
- X impossible("mkinvpos called with dist %d", dist);
- X break;
- X }
- X
- X /* display new value of position; could have a monster/object on it */
- X newsym(x,y);
- X}
- X
- X#ifdef MULDGN
- X/*
- X * The portal to Ludios is special. The entrance can only occur within a
- X * vault in the main dungeon at a depth greater than 10. The Ludios branch
- X * structure reflects this by having a bogus "source" dungeon: the value
- X * of n_dgns (thus, Is_branchlev() will never find it).
- X *
- X * Ludios will remain isolated until the branch is corrected by this function.
- X */
- Xstatic void
- Xmk_knox_portal(x, y)
- Xxchar x, y;
- X{
- X extern int n_dgns; /* from dungeon.c */
- X d_level *source;
- X branch *br;
- X xchar u_depth;
- X
- X br = dungeon_branch("Fort Ludios");
- X if (on_level(&knox_level, &br->end1)) {
- X source = &br->end2;
- X } else {
- X /* disallow Knox branch on a level with one branch already */
- X if(Is_branchlev(&u.uz))
- X return;
- X source = &br->end1;
- X }
- X
- X /* Already set or 2/3 chance of deferring until a later level. */
- X if (source->dnum < n_dgns || (rn2(3)
- X#ifdef WIZARD
- X && !wizard
- X#endif
- X )) return;
- X
- X if (! (u.uz.dnum == oracle_level.dnum /* in main dungeon */
- X && !at_dgn_entrance("The Quest") /* but not Quest's entry */
- X && (u_depth = depth(&u.uz)) > 10 /* beneath 10 */
- X && u_depth < depth(&medusa_level))) /* and above Medusa */
- X return;
- X
- X /* Adjust source to be current level and re-insert branch. */
- X *source = u.uz;
- X insert_branch(br, TRUE);
- X
- X# ifdef DEBUG
- X pline("Made knox portal.");
- X# endif
- X place_branch(br, x, y);
- X}
- X#endif
- X
- X/*mklev.c*/
- END_OF_FILE
- if test 33549 -ne `wc -c <'src/mklev.c'`; then
- echo shar: \"'src/mklev.c'\" unpacked with wrong size!
- fi
- # end of 'src/mklev.c'
- fi
- if test -f 'src/save.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/save.c'\"
- else
- echo shar: Extracting \"'src/save.c'\" \(19844 characters\)
- sed "s/^X//" >'src/save.c' <<'END_OF_FILE'
- X/* SCCS Id: @(#)save.c 3.1 93/01/07 */
- 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 "lev.h"
- X
- X#ifndef NO_SIGNAL
- X#include <signal.h>
- X#endif /* !NO_SIGNAL */
- X#if defined(EXPLORE_MODE) && !defined(LSC) && !defined(O_WRONLY) && !defined(AZTEC_C)
- X#include <fcntl.h>
- X#endif /* EXPLORE_MODE */
- X
- Xboolean hu; /* set during hang-up */
- X
- X#ifdef MULDGN
- X#include "quest.h"
- X#endif
- X
- X#ifdef MFLOPPY
- Xextern struct finfo fileinfo[];
- Xlong bytes_counted;
- Xstatic int count_only;
- X#else
- Xextern boolean level_exists[];
- X#endif
- X
- X#ifdef MICRO
- Xint dotcnt; /* also used in restore */
- X#endif
- X
- X#ifdef ZEROCOMP
- Xstatic void FDECL(bputc, (UCHAR_P));
- X#endif
- Xstatic void FDECL(savelevchn, (int, int));
- Xstatic void FDECL(savedamage, (int,struct damage *, int));
- Xstatic void FDECL(saveobjchn, (int,struct obj *, int));
- Xstatic void FDECL(savemonchn, (int,struct monst *, int));
- Xstatic void FDECL(savetrapchn, (int,struct trap *, int));
- Xstatic void FDECL(savegenoinfo, (int));
- Xstatic void FDECL(savegamestate, (int, int));
- X#ifdef MFLOPPY
- Xstatic void FDECL(savelev0, (int,XCHAR_P,int));
- Xstatic boolean NDECL(swapout_oldest);
- Xstatic void FDECL(copyfile, (char *,char *));
- X#endif /* MFLOPPY */
- X#ifdef GCC_WARN
- Xstatic long nulls[10];
- X#else
- X#define nulls nul
- X#endif
- X
- Xint
- Xdosave()
- X{
- X clear_nhwindow(WIN_MESSAGE);
- X if(yn("Really save?") == 'n') {
- X clear_nhwindow(WIN_MESSAGE);
- X if(multi > 0) nomul(0);
- X } else {
- X clear_nhwindow(WIN_MESSAGE);
- X pline("Saving...");
- X mark_synch(); /* flush output */
- X hu = FALSE;
- X if(dosave0()) {
- X /* make sure they see the Saving message */
- X display_nhwindow(WIN_MESSAGE, TRUE);
- X exit_nhwindows("Be seeing you...");
- X terminate(0);
- X } else (void)doredraw();
- X }
- X return 0;
- X}
- X
- X#ifndef NOSAVEONHANGUP
- Xint
- Xhangup() {
- X if(!hu) {
- X hu = TRUE;
- X (void) dosave0();
- X# ifndef VMS
- X terminate(1);
- X# endif
- X }
- X return 0;
- X}
- X#endif
- X
- X/* returns 1 if save successful */
- Xint
- Xdosave0()
- X{
- X register int fd, ofd;
- X xchar ltmp;
- X#ifdef MFLOPPY
- X long fds, needed;
- X#endif
- X
- X if (!SAVEF[0])
- X return 0;
- X
- X#if defined(UNIX) || defined(VMS)
- X (void) signal(SIGHUP, SIG_IGN);
- X#endif
- X#ifndef NO_SIGNAL
- X (void) signal(SIGINT, SIG_IGN);
- X#endif
- X
- X#if defined(MICRO) && defined(MFLOPPY)
- X if(!hu && !saveDiskPrompt(0)) return 0;
- X#endif
- X
- X#ifdef EXPLORE_MODE
- X if(!hu && flags.window_inited) {
- X fd = open_savefile();
- X if (fd > 0) {
- X (void) close(fd);
- X clear_nhwindow(WIN_MESSAGE);
- X pline("There seems to be an old save file.");
- X if (yn("Overwrite the old file?") == 'n') return 0;
- X }
- X }
- X#endif
- X
- X fd = create_savefile();
- X
- X if(fd < 0) {
- X if(!hu) pline("Cannot open save file.");
- X (void) delete_savefile(); /* ab@unido */
- X return(0);
- X }
- X if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */
- X change_luck(-1); /* and unido!ab */
- X if(flags.friday13)
- X change_luck(1);
- X if(flags.window_inited)
- X clear_nhwindow(WIN_MESSAGE);
- X
- X#ifdef MFLOPPY
- X if(!hu) {
- X dotcnt = 0;
- X curs(WIN_MAP, 1, 1);
- X putstr(WIN_MAP, 0, "Saving:");
- X }
- X /* make sure there is enough disk space */
- X savelev(fd, ledger_no(&u.uz), COUNT_SAVE);
- X savegamestate(fd, COUNT_SAVE);
- X needed = bytes_counted;
- X for (ltmp = 1; ltmp <= maxledgerno(); ltmp++)
- X if (ltmp != ledger_no(&u.uz) && fileinfo[ltmp].where)
- X needed += fileinfo[ltmp].size + (sizeof ltmp);
- X# ifdef AMIGA
- X needed+=ami_wbench_iconsize(SAVEF);
- X# endif
- X fds = freediskspace(SAVEF);
- X if(needed > fds) {
- X if(!hu) {
- X pline("There is insufficient space on SAVE disk.");
- X pline("Require %ld bytes but only have %ld.", needed, fds);
- X }
- X flushout();
- X (void) close(fd);
- X (void) delete_savefile();
- X return 0;
- X }
- X#endif /* MFLOPPY */
- X
- X bufon(fd);
- X savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
- X savegamestate(fd, WRITE_SAVE | FREE_SAVE);
- X
- X for(ltmp = (xchar)1; ltmp <= maxledgerno(); ltmp++) {
- X if (ltmp == ledger_no(&u.uz)) continue;
- X#ifdef MFLOPPY
- X if (!fileinfo[ltmp].where) continue;
- X#else
- X if(!level_exists[ltmp]) continue;
- X#endif
- X#ifdef MICRO
- X if(!hu) {
- X curs(WIN_MAP, 8 + dotcnt++, 1);
- X putstr(WIN_MAP, 0, ".");
- X }
- X#endif
- X ofd = open_levelfile(ltmp);
- X if(ofd < 0) {
- X if(!hu) pline("Cannot read level %d.", ltmp);
- X (void) close(fd);
- X (void) delete_savefile();
- X if(!hu) done(TRICKED);
- X return(0);
- X }
- X minit(); /* ZEROCOMP */
- X getlev(ofd, hackpid, ltmp, FALSE);
- X (void) close(ofd);
- X bwrite(fd, (genericptr_t) <mp, sizeof ltmp); /* level number*/
- X savelev(fd, ltmp, WRITE_SAVE | FREE_SAVE); /* actual level*/
- X delete_levelfile(ltmp);
- X }
- X bclose(fd);
- X
- X /* get rid of current level --jgm */
- X delete_levelfile(ledger_no(&u.uz));
- X delete_levelfile(0);
- X compress(SAVEF);
- X#ifdef AMIGA
- X ami_wbench_iconwrite(SAVEF);
- X#endif
- X return(1);
- X}
- X
- Xstatic void
- Xsavegamestate(fd, mode)
- Xregister int fd, mode;
- X{
- X int tmp; /* not register ! */
- X
- X#ifdef MFLOPPY
- X count_only = (mode & COUNT_SAVE);
- X#endif
- X saveobjchn(fd, invent, mode);
- X saveobjchn(fd, migrating_objs, mode);
- X savemonchn(fd, migrating_mons, mode);
- X savegenoinfo(fd);
- X tmp = getuid();
- X bwrite(fd, (genericptr_t) &tmp, sizeof tmp);
- X bwrite(fd, (genericptr_t) &flags, sizeof(struct flag));
- X bwrite(fd, (genericptr_t) &u, sizeof(struct you));
- X save_dungeon(fd);
- X bwrite(fd, (genericptr_t) &inv_pos, sizeof inv_pos);
- X savelevchn(fd, mode);
- X bwrite(fd, (genericptr_t) &moves, sizeof moves);
- X bwrite(fd, (genericptr_t) &monstermoves, sizeof monstermoves);
- X#ifdef MULDGN
- X bwrite(fd, (genericptr_t) &quest_status, sizeof(struct q_score));
- X#endif
- X bwrite(fd, (genericptr_t) spl_book,
- X sizeof(struct spell) * (MAXSPELL + 1));
- X save_artifacts(fd);
- X save_oracles(fd);
- X if(u.ustuck)
- X bwrite(fd, (genericptr_t) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
- X bwrite(fd, (genericptr_t) pl_character, sizeof pl_character);
- X#ifdef TUTTI_FRUTTI
- X bwrite(fd, (genericptr_t) pl_fruit, sizeof pl_fruit);
- X bwrite(fd, (genericptr_t) ¤t_fruit, sizeof current_fruit);
- X savefruitchn(fd, mode);
- X#endif
- X savenames(fd);
- X save_waterlevel(fd);
- X bflush(fd);
- X}
- X
- X#ifdef INSURANCE
- Xvoid
- Xsavestateinlock()
- X{
- X int fd, hpid;
- X static boolean havestate = TRUE;
- X
- X /* When checkpointing is on, the full state needs to be written
- X * on each checkpoint. When checkpointing is off, only the pid
- X * needs to be in the level.0 file, so it does not need to be
- X * constantly rewritten. When checkpointing is turned off during
- X * a game, however, the file has to be rewritten once to truncate
- X * it and avoid restoring from outdated information.
- X *
- X * Restricting havestate to this routine means that an additional
- X * noop pid rewriting will take place on the first "checkpoint" after
- X * the game is started or restored, if checkpointing is off.
- X */
- X if (flags.ins_chkpt || havestate) {
- X /* save the rest of the current game state in the lock file,
- X * following the original int pid, the current level number,
- X * and the current savefile name, which should not be subject
- X * to any internal compression schemes since they must be
- X * readable by an external utility
- X */
- X fd = open_levelfile(0);
- X if (fd < 0) {
- X pline("Cannot open level 0.");
- X pline("Probably someone removed it.");
- X done(TRICKED);
- X return;
- X }
- X
- X (void) read(fd, (genericptr_t) &hpid, sizeof(hpid));
- X if (hackpid != hpid) {
- X pline("Level 0 pid bad!");
- X done(TRICKED);
- X }
- X (void) close(fd);
- X
- X fd = create_levelfile(0);
- X if (fd < 0) {
- X pline("Cannot rewrite level 0.");
- X done(TRICKED);
- X return;
- X }
- X (void) write(fd, (genericptr_t) &hackpid, sizeof(hackpid));
- X if (flags.ins_chkpt) {
- X int currlev = ledger_no(&u.uz);
- X
- X (void) write(fd, (genericptr_t) &currlev, sizeof(currlev));
- X save_savefile_name(fd);
- X bufon(fd);
- X savegamestate(fd, WRITE_SAVE);
- X }
- X bclose(fd);
- X }
- X havestate = flags.ins_chkpt;
- X}
- X#endif
- X
- X#ifdef MFLOPPY
- Xboolean
- Xsavelev(fd, lev, mode)
- Xint fd;
- Xxchar lev;
- Xint mode;
- X{
- X if (mode & COUNT_SAVE) {
- X bytes_counted = 0;
- X savelev0(fd, lev, COUNT_SAVE);
- X while (bytes_counted > freediskspace(levels))
- X if (!swapout_oldest())
- X return FALSE;
- X }
- X if (mode & WRITE_SAVE) {
- X bytes_counted = 0;
- X /* mode is WRITE_SAVE and possibly FREE_SAVE */
- X savelev0(fd, lev, mode);
- X }
- X fileinfo[lev].where = ACTIVE;
- X fileinfo[lev].time = moves;
- X fileinfo[lev].size = bytes_counted;
- X return TRUE;
- X}
- X
- Xstatic void
- Xsavelev0(fd,lev,mode)
- X#else
- Xvoid
- Xsavelev(fd,lev,mode)
- X#endif
- Xint fd;
- Xxchar lev;
- Xint mode;
- X{
- X#ifdef TOS
- X short tlev;
- X#endif
- X
- X if(fd < 0) panic("Save on bad file!"); /* impossible */
- X#ifdef MFLOPPY
- X count_only = (mode & COUNT_SAVE);
- X#else
- X if(lev >= 0 && lev <= maxledgerno()) level_exists[lev] = TRUE;
- X#endif
- X bwrite(fd,(genericptr_t) &hackpid,sizeof(hackpid));
- X#ifdef TOS
- X tlev=lev; tlev &= 0x00ff;
- X bwrite(fd,(genericptr_t) &tlev,sizeof(tlev));
- X#else
- X bwrite(fd,(genericptr_t) &lev,sizeof(lev));
- X#endif
- X#ifdef RLECOMP
- X {
- X /* perform run-length encoding of rm structs */
- X struct rm *prm, *rgrm;
- X int x, y;
- X uchar match;
- X
- X rgrm = &levl[0][0]; /* start matching at first rm */
- X match = 0;
- X
- X for (y = 0; y < ROWNO; y++) {
- X for (x = 0; x < COLNO; x++) {
- X prm = &levl[x][y];
- X if (prm->glyph == rgrm->glyph
- X && prm->typ == rgrm->typ
- X && prm->seen == rgrm->seen
- X && prm->lit == rgrm->lit
- X && prm->doormask == rgrm->doormask
- X && prm->horizontal == rgrm->horizontal
- X && prm->waslit == rgrm->waslit
- X && prm->roomno == rgrm->roomno
- X && prm->edge == rgrm->edge) {
- X match++;
- X if (match > 254) {
- X match = 254; /* undo this match */
- X goto writeout;
- X }
- X } else {
- X /* the run has been broken,
- X * write out run-length encoding */
- X writeout:
- X bwrite(fd, (genericptr_t)&match, sizeof(uchar));
- X bwrite(fd, (genericptr_t)rgrm, sizeof(struct rm));
- X /* start encoding again. we have at least 1 rm
- X * in the next run, viz. this one. */
- X match = 1;
- X rgrm = prm;
- X }
- X }
- X }
- X if (match > 0) {
- X bwrite(fd, (genericptr_t)&match, sizeof(uchar));
- X bwrite(fd, (genericptr_t)rgrm, sizeof(struct rm));
- X }
- X }
- X#else
- X bwrite(fd,(genericptr_t) levl,sizeof(levl));
- X#endif /* RLECOMP */
- X
- X bwrite(fd,(genericptr_t) &monstermoves,sizeof(monstermoves));
- X bwrite(fd,(genericptr_t) &upstair,sizeof(stairway));
- X bwrite(fd,(genericptr_t) &dnstair,sizeof(stairway));
- X bwrite(fd,(genericptr_t) &upladder,sizeof(stairway));
- X bwrite(fd,(genericptr_t) &dnladder,sizeof(stairway));
- X bwrite(fd,(genericptr_t) &sstairs,sizeof(stairway));
- X bwrite(fd,(genericptr_t) &updest,sizeof(dest_area));
- X bwrite(fd,(genericptr_t) &dndest,sizeof(dest_area));
- X bwrite(fd,(genericptr_t) &level.flags,sizeof(level.flags));
- X savemonchn(fd, fmon, mode);
- X save_worm(fd, mode); /* save worm information */
- X savetrapchn(fd, ftrap, mode);
- X saveobjchn(fd, fobj, mode);
- X saveobjchn(fd, billobjs, mode);
- X
- X save_engravings(fd, mode);
- X save_rooms(fd);
- X bwrite(fd,(genericptr_t) doors,sizeof(doors));
- X savedamage(fd, level.damagelist, mode);
- X if (mode & FREE_SAVE) {
- X billobjs = 0;
- X ftrap = 0;
- X fmon = 0;
- X fobj = 0;
- X }
- X bflush(fd);
- X}
- X
- X#ifdef ZEROCOMP
- X/* The runs of zero-run compression are flushed after the game state or a
- X * level is written out. This adds a couple bytes to a save file, where
- X * the runs could be mashed together, but it allows gluing together game
- X * state and level files to form a save file, and it means the flushing
- X * does not need to be specifically called for every other time a level
- X * file is written out.
- X */
- X
- X#define RLESC '\0' /* Leading character for run of LRESC's */
- X#define flushoutrun(ln) (bputc(RLESC), bputc(ln), ln = -1)
- X
- X#ifndef ZEROCOMP_BUFSIZ
- X#define ZEROCOMP_BUFSIZ BUFSZ
- X#endif
- Xstatic unsigned char NEARDATA outbuf[ZEROCOMP_BUFSIZ];
- Xstatic unsigned short NEARDATA outbufp = 0;
- Xstatic short NEARDATA outrunlength = -1;
- Xstatic int NEARDATA bwritefd;
- X
- X/*dbg()
- X{
- X if(!hu) printf("outbufp %d outrunlength %d\n", outbufp,outrunlength);
- X}*/
- X
- Xstatic void
- Xbputc(c)
- Xunsigned char c;
- X{
- X#ifdef MFLOPPY
- X bytes_counted++;
- X if (count_only)
- X return;
- X#endif
- X if (outbufp >= sizeof outbuf) {
- X (void) write(bwritefd, outbuf, sizeof outbuf);
- X outbufp = 0;
- X }
- X outbuf[outbufp++] = c;
- X}
- X
- X/*ARGSUSED*/
- Xvoid
- Xbufon(fd)
- X int fd;
- X{
- X return;
- X}
- X
- Xvoid
- Xbflush(fd) /* flush run and buffer */
- Xregister int fd;
- X{
- X bwritefd = fd;
- X if (outrunlength >= 0) { /* flush run */
- X flushoutrun(outrunlength);
- X }
- X if (outbufp) {
- X#ifdef MFLOPPY
- X if (!count_only) /* flush buffer */
- X#endif
- X (void) write(fd, outbuf, outbufp);
- X outbufp = 0;
- X }
- X /*printf("bflush()"); getret();*/
- X}
- X
- Xvoid
- Xbwrite(fd, loc, num)
- Xregister int fd;
- Xgenericptr_t loc;
- Xregister unsigned num;
- X{
- X bwritefd = fd;
- X for (; num; num--, (*(char **)&loc)++) {
- X if (*((char *)loc) == RLESC) { /* One more char in run */
- X if (++outrunlength == 0xFF) {
- X flushoutrun(outrunlength);
- X }
- X } else { /* end of run */
- X if (outrunlength >= 0) { /* flush run */
- X flushoutrun(outrunlength);
- X }
- X bputc(*((char *)loc));
- X }
- X }
- X}
- X
- Xvoid
- Xbclose(fd)
- X int fd;
- X{
- X if (outbufp)
- X panic("closing file with buffered data still unwritten");
- X (void) close(fd);
- X}
- X
- X#else /* ZEROCOMP */
- X
- Xstatic int bw_fd = -1;
- Xstatic FILE *bw_FILE = 0;
- X
- Xvoid
- Xbufon(fd)
- X int fd;
- X{
- X#ifdef UNIX
- X if(bw_fd >= 0)
- X panic("double buffering unexpected");
- X bw_fd = fd;
- X if((bw_FILE = fdopen(fd, "w")) == 0)
- X panic("buffering of file %d failed", fd);
- X#endif
- X}
- X
- Xvoid
- Xbflush(fd)
- X int fd;
- X{
- X#ifdef UNIX
- X if(fd == bw_fd) {
- X if(fflush(bw_FILE) == EOF)
- X panic("flush of savefile failed!");
- X }
- X#endif
- X return;
- X}
- X
- Xvoid
- Xbwrite(fd,loc,num)
- Xregister int fd;
- Xregister genericptr_t loc;
- Xregister unsigned num;
- X{
- X#ifdef MFLOPPY
- X bytes_counted += num;
- X if (!count_only)
- X#endif
- X {
- X#ifdef UNIX
- X if(fd != bw_fd)
- X panic("unbuffered write to fd %d (!= %d)", fd, bw_fd);
- X
- X if(fwrite(loc, (int)num, 1, bw_FILE) != 1)
- X/* lint wants the 3rd arg of write to be an int; lint -p an unsigned */
- X#else
- X# if defined(BSD) || defined(ULTRIX)
- X if(write(fd, loc, (int)num) != (int)num)
- X# else /* e.g. SYSV, __TURBOC__ */
- X if(write(fd, loc, num) != num)
- X# endif
- X#endif
- X {
- X if(!hu) panic("cannot write %u bytes to file #%d", num, fd);
- X else terminate(1);
- X }
- X }
- X}
- X
- Xvoid
- Xbclose(fd)
- X int fd;
- X{
- X bflush(fd);
- X#ifdef UNIX
- X if (fd == bw_fd) {
- X (void) fclose(bw_FILE);
- X bw_fd = -1;
- X bw_FILE = 0;
- X return;
- X }
- X#endif
- X (void) close(fd);
- X}
- X#endif /* ZEROCOMP */
- X
- Xstatic void
- Xsavelevchn(fd, mode)
- Xregister int fd, mode;
- X{
- X int cnt = 0;
- X s_level *tmplev, *tmplev2;
- X
- X for(tmplev = sp_levchn; tmplev; tmplev = tmplev->next) cnt++;
- X bwrite(fd, (genericptr_t) &cnt, sizeof(int));
- X
- X for(tmplev = sp_levchn; tmplev; tmplev = tmplev2) {
- X
- X tmplev2 = tmplev->next;
- X bwrite(fd, (genericptr_t) tmplev, sizeof(s_level));
- X if (mode & FREE_SAVE)
- X free((genericptr_t) tmplev);
- X }
- X}
- X
- Xstatic void
- Xsavedamage(fd, damageptr, mode)
- Xregister int fd, mode;
- Xregister struct damage *damageptr;
- X{
- X register struct damage *tmp_dam;
- X unsigned int xl = 0;
- X
- X for (tmp_dam = damageptr; tmp_dam; tmp_dam = tmp_dam->next)
- X xl++;
- X bwrite(fd, (genericptr_t) &xl, sizeof(xl));
- X while (xl--) {
- X bwrite(fd, (genericptr_t) damageptr, sizeof(*damageptr));
- X tmp_dam = damageptr;
- X damageptr = damageptr->next;
- X if (mode & FREE_SAVE)
- X free((genericptr_t)tmp_dam);
- X }
- X if (mode & FREE_SAVE)
- X level.damagelist = 0;
- X}
- X
- Xstatic void
- Xsaveobjchn(fd,otmp,mode)
- Xregister int fd, mode;
- Xregister struct obj *otmp;
- X{
- X register struct obj *otmp2;
- X unsigned int xl;
- X int minusone = -1;
- X
- X while(otmp) {
- X otmp2 = otmp->nobj;
- X xl = otmp->onamelth;
- X bwrite(fd, (genericptr_t) &xl, sizeof(int));
- X bwrite(fd, (genericptr_t) otmp, xl + sizeof(struct obj));
- X
- X if (Is_container(otmp) || otmp->otyp == STATUE)
- X saveobjchn(fd,otmp->cobj,mode);
- X if (mode & FREE_SAVE)
- X dealloc_obj(otmp);
- X otmp = otmp2;
- X }
- X bwrite(fd, (genericptr_t) &minusone, sizeof(int));
- X}
- X
- Xstatic void
- Xsavemonchn(fd,mtmp,mode)
- Xregister int fd, mode;
- Xregister struct monst *mtmp;
- X{
- X register struct monst *mtmp2;
- X unsigned int xl;
- X int minusone = -1;
- X struct permonst *monbegin = &mons[0];
- X
- X bwrite(fd, (genericptr_t) &monbegin, sizeof(monbegin));
- X
- X while(mtmp) {
- X mtmp2 = mtmp->nmon;
- X#ifdef MUSE
- X if (mtmp->mw && mtmp->mw != mtmp->minvent) sort_mwep(mtmp);
- X#endif
- X xl = mtmp->mxlth + mtmp->mnamelth;
- X bwrite(fd, (genericptr_t) &xl, sizeof(int));
- X bwrite(fd, (genericptr_t) mtmp, xl + sizeof(struct monst));
- X if(mtmp->minvent) saveobjchn(fd,mtmp->minvent,mode);
- X if (mode & FREE_SAVE)
- X dealloc_monst(mtmp);
- X mtmp = mtmp2;
- X }
- X bwrite(fd, (genericptr_t) &minusone, sizeof(int));
- X}
- X
- Xstatic void
- Xsavetrapchn(fd,trap,mode)
- Xregister int fd,mode;
- Xregister struct trap *trap;
- X{
- X register struct trap *trap2;
- X while(trap) {
- X trap2 = trap->ntrap;
- X bwrite(fd, (genericptr_t) trap, sizeof(struct trap));
- X if (mode & FREE_SAVE)
- X dealloc_trap(trap);
- X trap = trap2;
- X }
- X bwrite(fd, (genericptr_t)nulls, sizeof(struct trap));
- X}
- X
- X#ifdef TUTTI_FRUTTI
- X/* save all the fruit names and ID's; this is used only in saving whole games
- X * (not levels) and in saving bones levels. When saving a bones level,
- X * we only want to save the fruits which exist on the bones level; the bones
- X * level routine marks nonexistent fruits by making the fid negative.
- X */
- Xvoid
- Xsavefruitchn(fd, mode)
- Xregister int fd, mode;
- X{
- X register struct fruit *f2, *f1;
- X
- X f1 = ffruit;
- X while(f1) {
- X f2 = f1->nextf;
- X if (f1->fid >= 0) {
- X bwrite(fd, (genericptr_t) f1, sizeof(struct fruit));
- X }
- X if (mode & FREE_SAVE)
- X dealloc_fruit(f1);
- X f1 = f2;
- X }
- X bwrite(fd, (genericptr_t)nulls, sizeof(struct fruit));
- X}
- X#endif
- X
- Xstatic void
- Xsavegenoinfo(fd)
- Xregister int fd;
- X{
- X register int i;
- X unsigned genolist[NUMMONS];
- X
- X for (i = 0; i < NUMMONS; i++)
- X genolist[i] = mons[i].geno;
- X
- X bwrite(fd, (genericptr_t) genolist, sizeof(genolist));
- X}
- X
- X#ifdef MFLOPPY
- Xboolean
- Xswapin_file(lev)
- Xint lev;
- X{
- X char to[PATHLEN], from[PATHLEN];
- X
- X Sprintf(from, "%s%s", permbones, alllevels);
- X Sprintf(to, "%s%s", levels, alllevels);
- X set_levelfile_name(from, lev);
- X set_levelfile_name(to, lev);
- X while (fileinfo[lev].size > freediskspace(to))
- X if (!swapout_oldest())
- X return FALSE;
- X# ifdef WIZARD
- X if (wizard) {
- X pline("Swapping in `%s'", from);
- X wait_synch();
- X }
- X# endif
- X copyfile(from, to);
- X (void) unlink(from);
- X fileinfo[lev].where = ACTIVE;
- X return TRUE;
- X}
- X
- Xstatic boolean
- Xswapout_oldest() {
- X char to[PATHLEN], from[PATHLEN];
- X int i, oldest;
- X long oldtime;
- X
- X if (!ramdisk)
- X return FALSE;
- X for (i = 1, oldtime = 0, oldest = 0; i <= maxledgerno(); i++)
- X if (fileinfo[i].where == ACTIVE
- X && (!oldtime || fileinfo[i].time < oldtime)) {
- X oldest = i;
- X oldtime = fileinfo[i].time;
- X }
- X if (!oldest)
- X return FALSE;
- X Sprintf(from, "%s%s", levels, alllevels);
- X Sprintf(to, "%s%s", permbones, alllevels);
- X set_levelfile_name(from, oldest);
- X set_levelfile_name(to, oldest);
- X# ifdef WIZARD
- X if (wizard) {
- X pline("Swapping out `%s'.", from);
- X wait_synch();
- X }
- X# endif
- X copyfile(from, to);
- X (void) unlink(from);
- X fileinfo[oldest].where = SWAPPED;
- X return TRUE;
- X}
- X
- Xstatic void
- Xcopyfile(from, to)
- Xchar *from, *to;
- X{
- X# ifdef TOS
- X
- X if (_copyfile(from, to))
- X panic("Can't copy %s to %s", from, to);
- X# else
- X char buf[BUFSIZ]; /* this is system interaction, therefore
- X * BUFSIZ instead of NetHack's BUFSZ */
- X int nfrom, nto, fdfrom, fdto;
- X
- X if ((fdfrom = open(from, O_RDONLY | O_BINARY, FCMASK)) < 0)
- X panic("Can't copy from %s !?", from);
- X if ((fdto = open(to, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK)) < 0)
- X panic("Can't copy to %s", to);
- X do {
- X nfrom = read(fdfrom, buf, BUFSIZ);
- X nto = write(fdto, buf, nfrom);
- X if (nto != nfrom)
- X panic("Copyfile failed!");
- X } while (nfrom == BUFSIZ);
- X (void) close(fdfrom);
- X (void) close(fdto);
- X# endif /* TOS */
- X}
- X
- Xvoid
- Xco_false() /* see comment in bones.c */
- X{
- X count_only = FALSE;
- X return;
- X}
- X
- X#endif /* MFLOPPY */
- X
- X/*save.c*/
- END_OF_FILE
- if test 19844 -ne `wc -c <'src/save.c'`; then
- echo shar: \"'src/save.c'\" unpacked with wrong size!
- fi
- # end of 'src/save.c'
- fi
- echo shar: End of archive 54 \(of 108\).
- cp /dev/null ark54isdone
- 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 39 40 \
- 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
- 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
- 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
- 101 102 103 104 105 106 107 108 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 108 archives.
- echo "Now execute 'rebuild.sh'"
- rm -f ark10[0-8]isdone 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
-