This is restore.c in view mode; [Download] [Up]
/* SCCS Id: @(#)restore.c 3.0 88/10/25
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#include "lev.h"
#ifdef WORM
#include "wseg.h"
#endif
boolean restoring = FALSE;
#ifdef TUTTI_FRUTTI
static struct fruit *oldfruit;
#endif
static long omoves;
/*
* "stuff" objects back into containers (relink the fcobj list).
*/
static void
stuff_objs(cobj)
register struct obj *cobj;
{
register struct obj *otmp, *otmp2;
for(; cobj; cobj = cobj->nobj)
if(Is_container(cobj))
for(otmp = cobj->nobj;
otmp && otmp->cobj == (struct obj *) -1; otmp = otmp2) {
otmp2 = otmp->nobj;
otmp->cobj = cobj;
cobj->nobj = otmp2;
otmp->nobj = fcobj;
fcobj = otmp;
}
}
/* Recalculate level.objects[x][y], since this info was not saved. */
static void
find_lev_obj()
{
register struct obj *fobjtmp = (struct obj *)0;
register struct obj *otmp;
int x,y;
for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++)
level.objects[x][y] = (struct obj *)0;
/* Reverse the entire fobj chain, which is necessary so that we can
* place the objects in the proper order.
*/
while(otmp = fobj) {
fobj = otmp->nobj;
otmp->nobj = fobjtmp;
fobjtmp = otmp;
}
/* Set level.objects (as well as reversing the chain back again) */
while(otmp = fobjtmp) {
place_object(otmp, otmp->ox, otmp->oy);
fobjtmp = otmp->nobj;
otmp->nobj = fobj;
fobj = otmp;
}
}
#ifndef NO_SIGNAL
static void
inven_inuse()
/* Things that were marked "in_use" when the game was saved (ex. via the
* infamous "HUP" cheat) get used up here.
*/
{
register struct obj *otmp, *otmp2;
for(otmp = invent; otmp; otmp = otmp2) {
otmp2 = otmp->nobj;
if(otmp->olet != ARMOR_SYM && otmp->olet != WEAPON_SYM
&& otmp->otyp != PICK_AXE && otmp->otyp != UNICORN_HORN
&& otmp->in_use) {
pline("Finishing off %s...", xname(otmp));
useup(otmp);
}
}
}
#endif
static struct obj *
restobjchn(fd, ghostly)
register int fd;
boolean ghostly;
{
register struct obj *otmp, *otmp2;
register struct obj *first = 0;
#ifdef TUTTI_FRUTTI
register struct fruit *oldf;
#endif
int xl;
#if defined(LINT) || defined(__GNULINT__)
/* suppress "used before set" warning from lint */
otmp2 = 0;
#endif
while(1) {
mread(fd, (genericptr_t) &xl, sizeof(xl));
if(xl == -1) break;
otmp = newobj(xl);
if(!first) first = otmp;
else otmp2->nobj = otmp;
mread(fd, (genericptr_t) otmp, (unsigned) xl + sizeof(struct obj));
if(!otmp->o_id) otmp->o_id = flags.ident++;
#ifdef TUTTI_FRUTTI
if(ghostly && otmp->otyp == SLIME_MOLD) {
for(oldf=oldfruit; oldf; oldf=oldf->nextf)
if (oldf->fid == otmp->spe) break;
if(!oldf) impossible("no old fruit?");
else otmp->spe = fruitadd(oldf->fname);
}
#endif
/* Ghost levels get object age shifted from old player's clock to
* new player's clock. Assumption: new player arrived immediately
* after old player died.
*/
if (ghostly) otmp->age = monstermoves-omoves+otmp->age;
otmp2 = otmp;
}
if(first && otmp2->nobj){
impossible("Restobjchn: error reading objchn.");
otmp2->nobj = 0;
}
stuff_objs(first);
return(first);
}
static struct monst *
restmonchn(fd, ghostly)
register int fd;
boolean ghostly;
{
register struct monst *mtmp, *mtmp2;
register struct monst *first = 0;
int xl;
struct permonst *monbegin;
off_t differ;
mread(fd, (genericptr_t)&monbegin, sizeof(monbegin));
#if !defined(MSDOS) && !defined(M_XENIX) && !defined(THINKC4) && !defined(HPUX)
differ = (genericptr_t)(&mons[0]) - (genericptr_t)(monbegin);
#else
differ = (long)(&mons[0]) - (long)(monbegin);
#endif
#if defined(LINT) || defined(__GNULINT__)
/* suppress "used before set" warning from lint */
mtmp2 = 0;
#endif
while(1) {
mread(fd, (genericptr_t) &xl, sizeof(xl));
if(xl == -1) break;
mtmp = newmonst(xl);
if(!first) first = mtmp;
else mtmp2->nmon = mtmp;
mread(fd, (genericptr_t) mtmp, (unsigned) xl + sizeof(struct monst));
if(!mtmp->m_id)
mtmp->m_id = flags.ident++;
#if !defined(MSDOS) && !defined(M_XENIX) && !defined(THINKC4) && !defined(HPUX)
/* ANSI type for differ is ptrdiff_t --
* long may be wrong for segmented architecture --
* may be better to cast pointers to (struct permonst *)
* rather than (genericptr_t)
* this code handles save file -- so any bug should glow
* probably best not to keep lint from complaining
*/
/*#ifdef LINT /* possible compiler/hardware dependency - */
/* if (differ) mtmp->data = NULL;*/
/*#else*/
mtmp->data = (struct permonst *)
((genericptr_t)mtmp->data + differ);
/*#endif /*LINT*/
#else
mtmp->data = (struct permonst *)
((long) mtmp->data + differ);
#endif
if(mtmp->minvent)
mtmp->minvent = restobjchn(fd, ghostly);
mtmp2 = mtmp;
}
if(first && mtmp2->nmon){
impossible("Restmonchn: error reading monchn.");
mtmp2->nmon = 0;
}
return(first);
}
static void
restgenoinfo(fd)
register int fd;
{
register int i;
for (i = 0; i < NUMMONS; i++)
mread(fd, (genericptr_t) &(mons[i].geno), sizeof(unsigned));
}
int
dorecover(fd)
register int fd;
{
register int nfd;
int tmp; /* not a register ! */
xchar ltmp;
unsigned int mid; /* idem */
struct obj *otmp;
#ifdef TUTTI_FRUTTI
struct fruit *fruit;
#endif
#ifdef MSDOS
struct flag oldflags;
oldflags = flags; /* Save flags set in the config file */
#endif
#ifdef ZEROCOMP
minit();
#endif
restoring = TRUE;
getlev(fd, 0, (xchar)0, FALSE);
invent = restobjchn(fd, FALSE);
for(otmp = invent; otmp; otmp = otmp->nobj)
if(otmp->owornmask)
setworn(otmp, otmp->owornmask);
fallen_down = restmonchn(fd, FALSE);
restgenoinfo(fd);
mread(fd, (genericptr_t) &tmp, sizeof tmp);
#ifdef WIZARD
if(!wizard)
#endif
if(tmp != getuid()) { /* strange ... */
(void) close(fd);
(void) unlink(SAVEF);
#ifdef AMIGA_WBENCH
ami_wbench_unlink(SAVEF);
#endif
(void) puts("Saved game was not yours.");
restoring = FALSE;
return(0);
}
mread(fd, (genericptr_t) &flags, sizeof(struct flag));
/* Some config file OPTIONS take precedence over those in save file.
*/
#ifdef MSDOS
#ifdef DGK
flags.rawio = oldflags.rawio;
#ifdef DECRAINBOW
flags.DECRainbow = oldflags.DECRainbow;
#endif /* DECRAINBOW */
flags.IBMBIOS = oldflags.IBMBIOS;
#endif
#ifdef TEXTCOLOR
flags.use_color = oldflags.use_color;
#endif
#endif /* MSDOS */
mread(fd, (genericptr_t) &dlevel, sizeof dlevel);
mread(fd, (genericptr_t) &maxdlevel, sizeof maxdlevel);
mread(fd, (genericptr_t) &moves, sizeof moves);
mread(fd, (genericptr_t) &monstermoves, sizeof monstermoves);
mread(fd, (genericptr_t) &wiz_level, sizeof wiz_level);
mread(fd, (genericptr_t) &medusa_level, sizeof medusa_level);
mread(fd, (genericptr_t) &bigroom_level, sizeof bigroom_level);
#ifdef ORACLE
mread(fd, (genericptr_t) &oracle_level, sizeof oracle_level);
#endif
#ifdef REINCARNATION
mread(fd, (genericptr_t) &rogue_level, sizeof rogue_level);
if (dlevel==rogue_level)
(void) memcpy((genericptr_t)savesyms,
(genericptr_t)showsyms, sizeof savesyms);
#endif
#ifdef STRONGHOLD
mread(fd, (genericptr_t) &stronghold_level, sizeof stronghold_level);
mread(fd, (genericptr_t) &tower_level, sizeof tower_level);
mread(fd, (genericptr_t) tune, sizeof tune);
# ifdef MUSIC
mread(fd, (genericptr_t) &music_heard, sizeof music_heard);
# endif
#endif
mread(fd, (genericptr_t) &is_maze_lev, sizeof is_maze_lev);
mread(fd, (genericptr_t) &u, sizeof(struct you));
if(u.uhp <= 0) {
(void) close(fd);
(void) unlink(SAVEF);
#ifdef AMIGA_WBENCH
ami_wbench_unlink(SAVEF);
#endif
(void) puts("You were not healthy enough to survive restoration.");
restoring = FALSE;
return(0);
}
#ifdef SPELLS
mread(fd, (genericptr_t) spl_book,
sizeof(struct spell) * (MAXSPELL + 1));
#endif
#ifdef NAMED_ITEMS
mread(fd, (genericptr_t) artiexist,
(unsigned int)(sizeof(boolean) * artifact_num));
#endif
if(u.ustuck)
mread(fd, (genericptr_t) &mid, sizeof mid);
mread(fd, (genericptr_t) pl_character, sizeof pl_character);
#ifdef TUTTI_FRUTTI
mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit);
mread(fd, (genericptr_t) ¤t_fruit, sizeof current_fruit);
ffruit = 0;
while (fruit = newfruit(),
mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),
fruit->fid) {
fruit->nextf = ffruit;
ffruit = fruit;
}
free((genericptr_t) fruit);
#endif
restnames(fd);
#if defined(DGK) || defined(MACOS)
# ifdef MACOS
#define msmsg printf
# endif
msmsg("\n");
cl_end();
msmsg("You got as far as level %d%s.\n", maxdlevel,
flags.debug ? " in WIZARD mode" :
flags.explore ? " in discovery mode" : "");
cl_end();
msmsg("Restoring: ");
#endif
while(1) {
#ifdef ZEROCOMP
if(mread(fd, (genericptr_t) <mp, sizeof ltmp) < 0)
#else
if(read(fd, (genericptr_t) <mp, sizeof ltmp) != sizeof ltmp)
#endif
break;
getlev(fd, 0, ltmp, FALSE);
glo(ltmp);
#if defined(DGK) || defined(MACOS)
msmsg(".");
#endif
#if defined(MSDOS) && !defined(TOS)
nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
#else
# ifdef MACOS
{
Str255 fileName;
OSErr er;
struct term_info *t;
short oldVolume;
extern WindowPtr HackWindow;
t = (term_info *)GetWRefCon(HackWindow);
(void)GetVol(&fileName, &oldVolume);
(void)SetVol(0L, t->system.sysVRefNum);
fileName[0] = (uchar)strlen(lock);
Strcpy((char *)&fileName[1], lock);
if (er = Create(&fileName, 0, CREATOR, LEVEL_TYPE))
SysBeep(1);
msmsg(".");
nfd = open(lock, O_WRONLY | O_BINARY);
(void)SetVol(0L, oldVolume);
}
# else
nfd = creat(lock, FCMASK);
# endif /* MACOS */
#endif
if (nfd < 0) panic("Cannot open temp file %s!\n", lock);
#if defined(DGK)
if (!savelev(nfd, ltmp, COUNT | WRITE)) {
/* The savelev can't proceed because the size required
* is greater than the available disk space.
*/
msmsg("\nNot enough space on `%s' to restore your game.\n",
levels);
/* Remove levels and bones that may have been created.
*/
(void) close(nfd);
eraseall(levels, alllevels);
eraseall(levels, allbones);
/* Perhaps the person would like to play without a
* RAMdisk.
*/
if (ramdisk) {
/* PlaywoRAMdisk may not return, but if it does
* it is certain that ramdisk will be 0.
*/
playwoRAMdisk();
/* Rewind save file and try again */
(void) lseek(fd, (off_t)0, 0);
return dorecover(fd);
} else {
msmsg("Be seeing you...\n");
exit(0);
}
}
#else
savelev(nfd, ltmp);
#endif
#ifdef ZEROCOMP
bflush(nfd);
#endif
(void) close(nfd);
}
#ifdef BSD
(void) lseek(fd, 0L, 0);
#else
(void) lseek(fd, (off_t)0, 0);
#endif
#ifdef ZEROCOMP
minit();
#endif
getlev(fd, 0, (xchar)0, FALSE);
(void) close(fd);
#if defined(WIZARD) || defined(EXPLORE_MODE)
if(
# ifdef WIZARD
!wizard
# ifdef EXPLORE_MODE
&&
# endif
# endif
# ifdef EXPLORE_MODE
!discover
# endif
)
#endif
(void) unlink(SAVEF);
#ifdef AMIGA_WBENCH
ami_wbench_unlink(SAVEF);
#endif
#ifdef REINCARNATION
/* this can't be done earlier because we need to check the initial
* showsyms against the one saved in each of the non-rogue levels */
if (dlevel==rogue_level) {
(void) memcpy((genericptr_t)showsyms,
(genericptr_t)defsyms, sizeof showsyms);
showsyms[S_ndoor] = showsyms[S_vodoor] =
showsyms[S_hodoor] = '+';
}
#endif
if(u.ustuck) {
register struct monst *mtmp;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if(mtmp->m_id == mid) goto monfnd;
panic("Cannot find the monster ustuck.");
monfnd:
u.ustuck = mtmp;
}
setsee(); /* only to recompute seelx etc. - these weren't saved */
#ifdef DGK
gameDiskPrompt();
#endif
max_rank_sz(); /* to recompute mrank_sz (pri.c) */
#ifdef POLYSELF
set_uasmon();
#endif
/* take care of iron ball & chain */
for(otmp = fobj; otmp; otmp = otmp->nobj)
if(otmp->owornmask)
setworn(otmp, otmp->owornmask);
#ifndef NO_SIGNAL
/* in_use processing must be after:
* inven has been read so fcobj has been built and freeinv() works
* current level has been restored so billing information is available
*/
inven_inuse();
#endif
docrt();
restoring = FALSE;
return(1);
}
void
getlev(fd, pid, lev, ghostly)
int fd, pid;
xchar lev;
boolean ghostly;
{
register struct gold *gold;
register struct trap *trap;
register struct monst *mtmp;
#ifdef WORM
register struct wseg *wtmp;
register int tmp;
#endif
long nhp;
int hpid;
xchar dlvl;
symbol_array osymbol;
int x, y;
uchar osym, nsym;
#ifdef TOS
short tlev;
#endif
#if defined(MSDOS) && !defined(TOS) && !defined(LATTICE) && !defined(AZTEC_C)
setmode(fd, O_BINARY); /* is this required for TOS??? NO --ERS */
#endif
#ifdef TUTTI_FRUTTI
/* Load the old fruit info. We have to do it first, so the infor-
* mation is available when restoring the objects.
*/
if (ghostly) {
struct fruit *fruit;
oldfruit = 0;
while (fruit = newfruit(),
mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),
fruit->fid) {
fruit->nextf = oldfruit;
oldfruit = fruit;
}
free((genericptr_t) fruit);
}
#endif
/* First some sanity checks */
mread(fd, (genericptr_t) &hpid, sizeof(hpid));
#ifdef TOS
mread(fd, (genericptr_t) &tlev, sizeof(tlev));
dlvl=tlev&0x00ff;
#else
mread(fd, (genericptr_t) &dlvl, sizeof(dlvl));
#endif
if((pid && pid != hpid) || (lev && dlvl != lev)) {
#ifdef WIZARD
if (wizard) {
if (pid && pid != hpid)
pline("PID (%d) doesn't match saved PID (%d)!", hpid, pid);
else if (lev && dlvl != lev)
pline("This is level %d, not %d!", dlvl, lev);
}
#endif
pline("Strange, this map is not as I remember it.");
pline("Somebody is trying some trickery here...");
pline("This game is void.");
done(TRICKED);
}
#if defined(SMALLDATA) && defined(MACOS)
{
/* this assumes that the size of a row of struct rm's is <128 */
short i, length, j;
char *ptr, *src, *p, *d;
d = calloc(ROWNO*COLNO, sizeof(struct rm));
p = d;
mread(fd, (genericptr_t)&j, sizeof(short));
mread(fd, (genericptr_t)d, j);
for (i = 0; i < COLNO; i++) {
length = (short)(*p++);
ptr = p;
src = (char *)&levl[i][0];
UnpackBits(&ptr, &src, ROWNO * sizeof(struct rm));
if ((ptr - p) != length)
panic("restore - corrupted file on unpacking\n");
p = ptr;
}
free(d);
}
#else
mread(fd, (genericptr_t) levl, sizeof(levl));
#endif
mread(fd, (genericptr_t) osymbol, sizeof(osymbol));
#ifdef REINCARNATION
if (memcmp((genericptr_t) osymbol, ((dlevel==rogue_level)
? (genericptr_t)savesyms : (genericptr_t)showsyms),
sizeof (osymbol))
&& dlvl != rogue_level) {
/* rogue level always uses default syms. Although showsyms
* will be properly initialized from environment when restoring
* a game, this routine is called upon saving as well as
* restoring; when saving on the Rogue level, showsyms will
* be wrong, so use savesyms (which is always right, both on
* saving and restoring).
*/
#else
if (memcmp((genericptr_t) osymbol,
(genericptr_t) showsyms, sizeof (showsyms))) {
#endif
for (x = 0; x < COLNO; x++)
for (y = 0; y < ROWNO; y++) {
osym = levl[x][y].scrsym;
nsym = 0;
switch (levl[x][y].typ) {
case STONE:
case SCORR:
if (osym == osymbol[S_stone])
nsym = showsyms[S_stone];
break;
case ROOM:
#ifdef STRONGHOLD
case DRAWBRIDGE_DOWN:
#endif /* STRONGHOLD /**/
if (osym == osymbol[S_room])
nsym = showsyms[S_room];
break;
case DOOR:
if (osym == osymbol[S_ndoor])
nsym = showsyms[S_ndoor];
else if (osym == osymbol[S_vodoor])
nsym = showsyms[S_vodoor];
else if (osym == osymbol[S_hodoor])
nsym = showsyms[S_hodoor];
else if (osym == osymbol[S_cdoor])
nsym = showsyms[S_cdoor];
break;
case CORR:
if (osym == osymbol[S_corr])
nsym = showsyms[S_corr];
break;
case VWALL:
if (osym == osymbol[S_vwall])
nsym = showsyms[S_vwall];
#ifdef STRONGHOLD
else if (osym == osymbol[S_dbvwall])
nsym = showsyms[S_dbvwall];
#endif
break;
case HWALL:
if (osym == osymbol[S_hwall])
nsym = showsyms[S_hwall];
#ifdef STRONGHOLD
else if (osym == osymbol[S_dbhwall])
nsym = showsyms[S_dbhwall];
#endif
break;
case TLCORNER:
if (osym == osymbol[S_tlcorn])
nsym = showsyms[S_tlcorn];
break;
case TRCORNER:
if (osym == osymbol[S_trcorn])
nsym = showsyms[S_trcorn];
break;
case BLCORNER:
if (osym == osymbol[S_blcorn])
nsym = showsyms[S_blcorn];
break;
case BRCORNER:
if (osym == osymbol[S_brcorn])
nsym = showsyms[S_brcorn];
break;
case SDOOR:
if (osym == osymbol[S_vwall])
nsym = showsyms[S_vwall];
else if (osym == osymbol[S_hwall])
nsym = showsyms[S_hwall];
break;
case CROSSWALL:
if (osym == osymbol[S_crwall])
nsym = showsyms[S_crwall];
break;
case TUWALL:
if (osym == osymbol[S_tuwall])
nsym = showsyms[S_tuwall];
break;
case TDWALL:
if (osym == osymbol[S_tdwall])
nsym = showsyms[S_tdwall];
break;
case TLWALL:
if (osym == osymbol[S_tlwall])
nsym = showsyms[S_tlwall];
break;
case TRWALL:
if (osym == osymbol[S_trwall])
nsym = showsyms[S_trwall];
break;
case STAIRS:
if (osym == osymbol[S_upstair])
nsym = showsyms[S_upstair];
else if (osym == osymbol[S_dnstair])
nsym = showsyms[S_dnstair];
break;
#ifdef STRONGHOLD
case LADDER:
if (osym == osymbol[S_upladder])
nsym = showsyms[S_upladder];
else if (osym == osymbol[S_dnladder])
nsym = showsyms[S_dnladder];
break;
#endif /* STRONGHOLD /**/
case POOL:
case MOAT:
#ifdef STRONGHOLD
case DRAWBRIDGE_UP:
#endif /* STRONGHOLD /**/
if (osym == osymbol[S_pool])
nsym = showsyms[S_pool];
break;
#ifdef FOUNTAINS
case FOUNTAIN:
if (osym == osymbol[S_fountain])
nsym = showsyms[S_fountain];
break;
#endif /* FOUNTAINS /**/
#ifdef THRONES
case THRONE:
if (osym == osymbol[S_throne])
nsym = showsyms[S_throne];
break;
#endif /* THRONES /**/
#ifdef SINKS
case SINK:
if (osym == osymbol[S_sink])
nsym = showsyms[S_sink];
break;
#endif /* SINKS /**/
#ifdef ALTARS
case ALTAR:
if (osym == osymbol[S_altar])
nsym = showsyms[S_altar];
break;
#endif /* ALTARS /**/
default:
break;
}
if (nsym)
levl[x][y].scrsym = nsym;
}
}
mread(fd, (genericptr_t)&omoves, sizeof(omoves));
mread(fd, (genericptr_t)&xupstair, sizeof(xupstair));
mread(fd, (genericptr_t)&yupstair, sizeof(yupstair));
mread(fd, (genericptr_t)&xdnstair, sizeof(xdnstair));
mread(fd, (genericptr_t)&ydnstair, sizeof(ydnstair));
#ifdef STRONGHOLD
mread(fd, (genericptr_t)&xupladder, sizeof(xupladder));
mread(fd, (genericptr_t)&yupladder, sizeof(yupladder));
mread(fd, (genericptr_t)&xdnladder, sizeof(xdnladder));
mread(fd, (genericptr_t)&ydnladder, sizeof(ydnladder));
#endif
mread(fd, (genericptr_t)&fountsound, sizeof(fountsound));
mread(fd, (genericptr_t)&sinksound, sizeof(sinksound));
fmon = restmonchn(fd, ghostly);
/* regenerate animals while on another level */
{ long tmoves = (monstermoves > omoves) ? monstermoves-omoves : 0;
register struct monst *mtmp2;
for(mtmp = fmon; mtmp; mtmp = mtmp2) {
mtmp2 = mtmp->nmon;
if(mtmp->data->geno & G_GENOD) {
#ifdef KOPS
allow_kops = FALSE;
#endif
mondead(mtmp);
#ifdef KOPS
allow_kops = TRUE;
#endif
continue;
}
if (ghostly) {
/* reset peaceful/malign relative to new character */
if(!mtmp->isshk)
/* shopkeepers will reset based on name */
mtmp->mpeaceful = peace_minded(mtmp->data);
set_malign(mtmp);
} else if (mtmp->mtame && tmoves > 250)
mtmp->mtame = mtmp->mpeaceful = 0;
/* restore shape changers - Maarten Jan Huisjes */
if (mtmp->data == &mons[PM_CHAMELEON]
&& !Protection_from_shape_changers
&& !mtmp->cham)
mtmp->cham = 1;
else if(Protection_from_shape_changers) {
if (mtmp->cham) {
mtmp->cham = 0;
(void) newcham(mtmp, &mons[PM_CHAMELEON]);
} else if(is_were(mtmp->data) && !is_human(mtmp->data))
(void) new_were(mtmp);
}
if (!ghostly) {
nhp = mtmp->mhp +
(regenerates(mtmp->data) ? tmoves : tmoves/20);
if(!mtmp->mcansee && mtmp->mblinded) {
if (mtmp->mblinded < tmoves) mtmp->mblinded = 0;
else mtmp->mblinded -= tmoves;
}
if(!mtmp->mcanmove && mtmp->mfrozen) {
if (mtmp->mfrozen < tmoves) mtmp->mfrozen = 0;
else mtmp->mfrozen -= tmoves;
}
if(nhp > mtmp->mhpmax)
mtmp->mhp = mtmp->mhpmax;
else
#ifdef LINT /* (long)newhp -> (schar = short int) mhp; ok in context of text above */
mtmp->mhp = 0;
#else
mtmp->mhp = nhp;
#endif
}
}
}
fgold = 0;
while(gold = newgold(),
mread(fd, (genericptr_t)gold, sizeof(struct gold)),
gold->gx) {
gold->ngold = fgold;
fgold = gold;
}
free((genericptr_t) gold);
ftrap = 0;
while (trap = newtrap(),
mread(fd, (genericptr_t)trap, sizeof(struct trap)),
trap->tx) {
trap->ntrap = ftrap;
ftrap = trap;
}
free((genericptr_t) trap);
fobj = restobjchn(fd, ghostly);
find_lev_obj();
billobjs = restobjchn(fd, ghostly);
rest_engravings(fd);
mread(fd, (genericptr_t)rooms, sizeof(rooms));
mread(fd, (genericptr_t)doors, sizeof(doors));
#ifdef WORM
mread(fd, (genericptr_t)wsegs, sizeof(wsegs));
for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){
wheads[tmp] = wsegs[tmp] = wtmp = newseg();
while(1) {
mread(fd, (genericptr_t)wtmp, sizeof(struct wseg));
if(!wtmp->nseg) break;
wheads[tmp]->nseg = wtmp = newseg();
wheads[tmp] = wtmp;
}
}
mread(fd, (genericptr_t)wgrowtime, sizeof(wgrowtime));
#endif
/* reset level.monsters for new level */
for (x = 0; x < COLNO; x++)
for (y = 0; y < ROWNO; y++)
level.monsters[x][y] = (struct monst *) 0;
for (mtmp = level.monlist; mtmp; mtmp = mtmp->nmon)
place_monster(mtmp, mtmp->mx, mtmp->my);
#ifdef TUTTI_FRUTTI
/* Now get rid of all the temp fruits... */
if (ghostly) {
struct fruit *fruit;
while(oldfruit) {
fruit = oldfruit->nextf;
free((genericptr_t) oldfruit);
oldfruit = fruit;
}
}
#endif
}
#ifdef ZEROCOMP
#define RLESC '\0' /* Leading character for run of RLESC's */
static unsigned char inbuf[BUFSZ];
static unsigned short inbufp = 0;
static unsigned short inbufsz = 0;
static short inrunlength = -1;
static int mreadfd;
static int
mgetc()
{
if (inbufp >= inbufsz) {
inbufsz = read(mreadfd, (genericptr_t)inbuf, (int)sizeof inbuf);
if (!inbufsz) {
if (inbufp > sizeof inbuf)
error("EOF on file #%d.\n", mreadfd);
inbufp = 1 + sizeof inbuf; /* exactly one warning :-) */
return -1;
}
inbufp = 0;
}
return inbuf[inbufp++];
}
void
minit()
{
inbufsz = 0;
inbufp = 0;
inrunlength = -1;
}
int
mread(fd, buf, len)
int fd;
genericptr_t buf;
register unsigned len;
{
/*register int readlen = 0;*/
mreadfd = fd;
while (len--) {
if (inrunlength > 0) {
inrunlength--;
*(*((char **)&buf))++ = '\0';
} else {
register short ch = mgetc();
if (ch < 0) return -1; /*readlen;*/
if ((*(*(char **)&buf)++ = ch) == RLESC) {
inrunlength = mgetc();
}
}
/*readlen++;*/
}
return 0; /*readlen;*/
}
#else /* ZEROCOMP */
void
mread(fd, buf, len)
register int fd;
register genericptr_t buf;
register unsigned int len;
{
register int rlen;
#if defined(BSD) || defined(ULTRIX)
rlen = read(fd, buf, (int) len);
if(rlen != len){
#else /* e.g. SYSV, __TURBOC__ */
rlen = read(fd, buf, (unsigned) len);
if((unsigned)rlen != len){
#endif
pline("Read %d instead of %u bytes.\n", rlen, len);
if(restoring) {
(void) unlink(SAVEF);
#ifdef AMIGA_WBENCH
ami_wbench_unlink(SAVEF);
#endif
error("Error restoring old game.");
}
panic("Error reading level file.");
}
}
#endif /* ZEROCOMP */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.