/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.lev.c - version 1.0.3 */ /* $FreeBSD: src/games/hack/hack.lev.c,v 1.4 1999/11/16 10:26:36 marcel Exp $ */ /* $DragonFly: src/games/hack/hack.lev.c,v 1.4 2006/08/21 19:45:32 pavalos Exp $ */ #include "hack.h" extern struct obj *billobjs; extern char SAVEF[]; extern char nul[]; #ifndef NOWORM extern struct wseg *wsegs[32], *wheads[32]; extern long wgrowtime[32]; #endif /* NOWORM */ boolean level_exists[MAXLEVEL+1]; static void savegoldchn(int, struct gold *); static void savetrapchn(int, struct trap *); void savelev(int fd, xchar lev) { #ifndef NOWORM struct wseg *wtmp, *wtmp2; int tmp; #endif /* NOWORM */ if(fd < 0) panic("Save on bad file!"); /* impossible */ if(lev >= 0 && lev <= MAXLEVEL) level_exists[lev] = TRUE; bwrite(fd,(char *) &hackpid,sizeof(hackpid)); bwrite(fd,(char *) &lev,sizeof(lev)); bwrite(fd,(char *) levl,sizeof(levl)); bwrite(fd,(char *) &moves,sizeof(long)); bwrite(fd,(char *) &xupstair,sizeof(xupstair)); bwrite(fd,(char *) &yupstair,sizeof(yupstair)); bwrite(fd,(char *) &xdnstair,sizeof(xdnstair)); bwrite(fd,(char *) &ydnstair,sizeof(ydnstair)); savemonchn(fd, fmon); savegoldchn(fd, fgold); savetrapchn(fd, ftrap); saveobjchn(fd, fobj); saveobjchn(fd, billobjs); billobjs = 0; save_engravings(fd); #ifndef QUEST bwrite(fd,(char *) rooms,sizeof(rooms)); bwrite(fd,(char *) doors,sizeof(doors)); #endif /* QUEST */ fgold = 0; ftrap = 0; fmon = 0; fobj = 0; #ifndef NOWORM bwrite(fd,(char *) wsegs,sizeof(wsegs)); for(tmp=1; tmp<32; tmp++){ for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){ wtmp2 = wtmp->nseg; bwrite(fd,(char *) wtmp,sizeof(struct wseg)); } wsegs[tmp] = 0; } bwrite(fd,(char *) wgrowtime,sizeof(wgrowtime)); #endif /* NOWORM */ } void bwrite(int fd, char *loc, unsigned int num) { /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */ if(write(fd, loc, (int) num) != (int)num) panic("cannot write %u bytes to file #%d", num, fd); } void saveobjchn(int fd, struct obj *otmp) { struct obj *otmp2; unsigned xl; int minusone = -1; while(otmp) { otmp2 = otmp->nobj; xl = otmp->onamelth; bwrite(fd, (char *) &xl, sizeof(int)); bwrite(fd, (char *) otmp, xl + sizeof(struct obj)); free((char *) otmp); otmp = otmp2; } bwrite(fd, (char *) &minusone, sizeof(int)); } void savemonchn(int fd, struct monst *mtmp) { struct monst *mtmp2; unsigned xl; int minusone = -1; struct permonst *monbegin = &mons[0]; bwrite(fd, (char *) &monbegin, sizeof(monbegin)); while(mtmp) { mtmp2 = mtmp->nmon; xl = mtmp->mxlth + mtmp->mnamelth; bwrite(fd, (char *) &xl, sizeof(int)); bwrite(fd, (char *) mtmp, xl + sizeof(struct monst)); if(mtmp->minvent) saveobjchn(fd,mtmp->minvent); free((char *) mtmp); mtmp = mtmp2; } bwrite(fd, (char *) &minusone, sizeof(int)); } static void savegoldchn(int fd, struct gold *gold) { struct gold *gold2; while(gold) { gold2 = gold->ngold; bwrite(fd, (char *) gold, sizeof(struct gold)); free((char *) gold); gold = gold2; } bwrite(fd, nul, sizeof(struct gold)); } static void savetrapchn(int fd, struct trap *trap) { struct trap *trap2; while(trap) { trap2 = trap->ntrap; bwrite(fd, (char *) trap, sizeof(struct trap)); free((char *) trap); trap = trap2; } bwrite(fd, nul, sizeof(struct trap)); } void getlev(int fd, int pid, xchar lev) { struct gold *gold; struct trap *trap; #ifndef NOWORM struct wseg *wtmp; #endif /* NOWORM */ int tmp; long omoves; int hpid; xchar dlvl; /* First some sanity checks */ mread(fd, (char *) &hpid, sizeof(hpid)); mread(fd, (char *) &dlvl, sizeof(dlvl)); if((pid && pid != hpid) || (lev && dlvl != lev)) { pline("Strange, this map is not as I remember it."); pline("Somebody is trying some trickery here ..."); pline("This game is void ..."); done("tricked"); } fgold = 0; ftrap = 0; mread(fd, (char *) levl, sizeof(levl)); mread(fd, (char *)&omoves, sizeof(omoves)); mread(fd, (char *)&xupstair, sizeof(xupstair)); mread(fd, (char *)&yupstair, sizeof(yupstair)); mread(fd, (char *)&xdnstair, sizeof(xdnstair)); mread(fd, (char *)&ydnstair, sizeof(ydnstair)); fmon = restmonchn(fd); /* regenerate animals while on another level */ { long tmoves = (moves > omoves) ? moves-omoves : 0; struct monst *mtmp, *mtmp2; for(mtmp = fmon; mtmp; mtmp = mtmp2) { long newhp; /* tmoves may be very large */ mtmp2 = mtmp->nmon; if(index(genocided, mtmp->data->mlet)) { mondead(mtmp); continue; } if(mtmp->mtame && tmoves > 250) { mtmp->mtame = 0; mtmp->mpeaceful = 0; } newhp = mtmp->mhp + (index(MREGEN, mtmp->data->mlet) ? tmoves : tmoves/20); if(newhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax; else mtmp->mhp = newhp; } } setgd(); gold = newgold(); mread(fd, (char *)gold, sizeof(struct gold)); while(gold->gx) { gold->ngold = fgold; fgold = gold; gold = newgold(); mread(fd, (char *)gold, sizeof(struct gold)); } free((char *) gold); trap = newtrap(); mread(fd, (char *)trap, sizeof(struct trap)); while(trap->tx) { trap->ntrap = ftrap; ftrap = trap; trap = newtrap(); mread(fd, (char *)trap, sizeof(struct trap)); } free((char *) trap); fobj = restobjchn(fd); billobjs = restobjchn(fd); rest_engravings(fd); #ifndef QUEST mread(fd, (char *)rooms, sizeof(rooms)); mread(fd, (char *)doors, sizeof(doors)); #endif /* QUEST */ #ifndef NOWORM mread(fd, (char *)wsegs, sizeof(wsegs)); for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){ wheads[tmp] = wsegs[tmp] = wtmp = newseg(); while(1) { mread(fd, (char *)wtmp, sizeof(struct wseg)); if(!wtmp->nseg) break; wheads[tmp]->nseg = wtmp = newseg(); wheads[tmp] = wtmp; } } mread(fd, (char *)wgrowtime, sizeof(wgrowtime)); #endif /* NOWORM */ } void mread(int fd, char *buf, unsigned int len) { int rlen; rlen = read(fd, buf, (int) len); if(rlen != (int)len){ pline("Read %d instead of %u bytes.\n", rlen, len); if(restoring) { unlink(SAVEF); error("Error restoring old game."); } panic("Error reading level file."); } } void mklev(void) { if(getbones()) return; in_mklev = TRUE; makelevel(); in_mklev = FALSE; }