1/*	SCCS Id: @(#)bones.c	3.4	2003/09/06	*/
2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */
3/* NetHack may be freely redistributed.  See license for details. */
4
5#include "hack.h"
6#include "lev.h"
7
8extern char bones[];	/* from files.c */
9#ifdef MFLOPPY
10extern long bytes_counted;
11#endif
12
13STATIC_DCL boolean FDECL(no_bones_level, (d_level *));
14STATIC_DCL void FDECL(goodfruit, (int));
15STATIC_DCL void FDECL(resetobjs,(struct obj *,BOOLEAN_P));
16STATIC_DCL void FDECL(drop_upon_death, (struct monst *, struct obj *));
17
18STATIC_OVL boolean
19no_bones_level(lev)
20d_level *lev;
21{
22	extern d_level save_dlevel;		/* in do.c */
23	s_level *sptr;
24
25	if (ledger_no(&save_dlevel)) assign_level(lev, &save_dlevel);
26
27	return (boolean)(((sptr = Is_special(lev)) != 0 && !sptr->boneid)
28		|| !dungeons[lev->dnum].boneid
29		   /* no bones on the last or multiway branch levels */
30		   /* in any dungeon (level 1 isn't multiway).       */
31		|| Is_botlevel(lev) || (Is_branchlev(lev) && lev->dlevel > 1)
32		   /* no bones in the invocation level               */
33		|| (In_hell(lev) && lev->dlevel == dunlevs_in_dungeon(lev) - 1)
34		);
35}
36
37/* Call this function for each fruit object saved in the bones level: it marks
38 * that particular type of fruit as existing (the marker is that that type's
39 * ID is positive instead of negative).  This way, when we later save the
40 * chain of fruit types, we know to only save the types that exist.
41 */
42STATIC_OVL void
43goodfruit(id)
44int id;
45{
46	register struct fruit *f;
47
48	for(f=ffruit; f; f=f->nextf) {
49		if(f->fid == -id) {
50			f->fid = id;
51			return;
52		}
53	}
54}
55
56STATIC_OVL void
57resetobjs(ochain,restore)
58struct obj *ochain;
59boolean restore;
60{
61	struct obj *otmp;
62
63	for (otmp = ochain; otmp; otmp = otmp->nobj) {
64		if (otmp->cobj)
65		    resetobjs(otmp->cobj,restore);
66
67		if (((otmp->otyp != CORPSE || otmp->corpsenm < SPECIAL_PM)
68			&& otmp->otyp != STATUE)
69			&& (!otmp->oartifact ||
70			   (restore && (exist_artifact(otmp->otyp, ONAME(otmp))
71					|| is_quest_artifact(otmp))))) {
72			otmp->oartifact = 0;
73			otmp->onamelth = 0;
74			*ONAME(otmp) = '\0';
75		} else if (otmp->oartifact && restore)
76			artifact_exists(otmp,ONAME(otmp),TRUE);
77		if (!restore) {
78			/* do not zero out o_ids for ghost levels anymore */
79
80			if(objects[otmp->otyp].oc_uses_known) otmp->known = 0;
81			otmp->dknown = otmp->bknown = 0;
82			otmp->rknown = 0;
83			otmp->invlet = 0;
84			otmp->no_charge = 0;
85
86			if (otmp->otyp == SLIME_MOLD) goodfruit(otmp->spe);
87#ifdef MAIL
88			else if (otmp->otyp == SCR_MAIL) otmp->spe = 1;
89#endif
90			else if (otmp->otyp == EGG) otmp->spe = 0;
91			else if (otmp->otyp == TIN) {
92			    /* make tins of unique monster's meat be empty */
93			    if (otmp->corpsenm >= LOW_PM &&
94				    (mons[otmp->corpsenm].geno & G_UNIQ))
95				otmp->corpsenm = NON_PM;
96			} else if (otmp->otyp == AMULET_OF_YENDOR) {
97			    /* no longer the real Amulet */
98			    otmp->otyp = FAKE_AMULET_OF_YENDOR;
99			    curse(otmp);
100			} else if (otmp->otyp == CANDELABRUM_OF_INVOCATION) {
101			    if (otmp->lamplit)
102				end_burn(otmp, TRUE);
103			    otmp->otyp = WAX_CANDLE;
104			    otmp->age = 50L;  /* assume used */
105			    if (otmp->spe > 0)
106				otmp->quan = (long)otmp->spe;
107			    otmp->spe = 0;
108			    otmp->owt = weight(otmp);
109			    curse(otmp);
110			} else if (otmp->otyp == BELL_OF_OPENING) {
111			    otmp->otyp = BELL;
112			    curse(otmp);
113			} else if (otmp->otyp == SPE_BOOK_OF_THE_DEAD) {
114			    otmp->otyp = SPE_BLANK_PAPER;
115			    curse(otmp);
116			}
117		}
118	}
119}
120
121STATIC_OVL void
122drop_upon_death(mtmp, cont)
123struct monst *mtmp;
124struct obj *cont;
125{
126	struct obj *otmp;
127
128	uswapwep = 0; /* ensure curse() won't cause swapwep to drop twice */
129	while ((otmp = invent) != 0) {
130		obj_extract_self(otmp);
131		obj_no_longer_held(otmp);
132
133		otmp->owornmask = 0;
134		/* lamps don't go out when dropped */
135		if ((cont || artifact_light(otmp)) && obj_is_burning(otmp))
136		    end_burn(otmp, TRUE);	/* smother in statue */
137
138		if(otmp->otyp == SLIME_MOLD) goodfruit(otmp->spe);
139
140		if(rn2(5)) curse(otmp);
141		if (mtmp)
142			(void) add_to_minv(mtmp, otmp);
143		else if (cont)
144			(void) add_to_container(cont, otmp);
145		else
146			place_object(otmp, u.ux, u.uy);
147	}
148#ifndef GOLDOBJ
149	if(u.ugold) {
150		long ugold = u.ugold;
151		if (mtmp) mtmp->mgold = ugold;
152		else if (cont) (void) add_to_container(cont, mkgoldobj(ugold));
153		else (void)mkgold(ugold, u.ux, u.uy);
154		u.ugold = ugold;	/* undo mkgoldobj()'s removal */
155	}
156#endif
157	if (cont) cont->owt = weight(cont);
158}
159
160/* check whether bones are feasible */
161boolean
162can_make_bones()
163{
164	register struct trap *ttmp;
165
166	if (ledger_no(&u.uz) <= 0 || ledger_no(&u.uz) > maxledgerno())
167	    return FALSE;
168	if (no_bones_level(&u.uz))
169	    return FALSE;		/* no bones for specific levels */
170	if (u.uswallow) {
171	    return FALSE;		/* no bones when swallowed */
172	}
173	if (!Is_branchlev(&u.uz)) {
174	    /* no bones on non-branches with portals */
175	    for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
176		if (ttmp->ttyp == MAGIC_PORTAL) return FALSE;
177	}
178
179	if(depth(&u.uz) <= 0 ||		/* bulletproofing for endgame */
180	   (!rn2(1 + (depth(&u.uz)>>2))	/* fewer ghosts on low levels */
181#ifdef WIZARD
182		&& !wizard
183#endif
184		)) return FALSE;
185	/* don't let multiple restarts generate multiple copies of objects
186	 * in bones files */
187	if (discover) return FALSE;
188	return TRUE;
189}
190
191/* save bones and possessions of a deceased adventurer */
192void
193savebones(corpse)
194struct obj *corpse;
195{
196	int fd, x, y;
197	struct trap *ttmp;
198	struct monst *mtmp;
199	struct permonst *mptr;
200	struct fruit *f;
201	char c, *bonesid;
202	char whynot[BUFSZ];
203
204	/* caller has already checked `can_make_bones()' */
205
206	clear_bypasses();
207	fd = open_bonesfile(&u.uz, &bonesid);
208	if (fd >= 0) {
209		(void) close(fd);
210		compress_bonesfile();
211#ifdef WIZARD
212		if (wizard) {
213		    if (yn("Bones file already exists.  Replace it?") == 'y') {
214			if (delete_bonesfile(&u.uz)) goto make_bones;
215			else pline("Cannot unlink old bones.");
216		    }
217		}
218#endif
219		return;
220	}
221
222#ifdef WIZARD
223 make_bones:
224#endif
225	unleash_all();
226	/* in case these characters are not in their home bases */
227	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
228	    if (DEADMONSTER(mtmp)) continue;
229	    mptr = mtmp->data;
230	    if (mtmp->iswiz || mptr == &mons[PM_MEDUSA] ||
231		    mptr->msound == MS_NEMESIS || mptr->msound == MS_LEADER ||
232		    mptr == &mons[PM_VLAD_THE_IMPALER])
233		mongone(mtmp);
234	}
235#ifdef STEED
236	if (u.usteed) dismount_steed(DISMOUNT_BONES);
237#endif
238	dmonsfree();		/* discard dead or gone monsters */
239
240	/* mark all fruits as nonexistent; when we come to them we'll mark
241	 * them as existing (using goodfruit())
242	 */
243	for(f=ffruit; f; f=f->nextf) f->fid = -f->fid;
244
245	/* check iron balls separately--maybe they're not carrying it */
246	if (uball) uball->owornmask = uchain->owornmask = 0;
247
248	/* dispose of your possessions, usually cursed */
249	if (u.ugrave_arise == (NON_PM - 1)) {
250		struct obj *otmp;
251
252		/* embed your possessions in your statue */
253		otmp = mk_named_object(STATUE, &mons[u.umonnum],
254				       u.ux, u.uy, plname);
255
256		drop_upon_death((struct monst *)0, otmp);
257		if (!otmp) return;	/* couldn't make statue */
258		mtmp = (struct monst *)0;
259	} else if (u.ugrave_arise < LOW_PM) {
260		/* drop everything */
261		drop_upon_death((struct monst *)0, (struct obj *)0);
262		/* trick makemon() into allowing monster creation
263		 * on your location
264		 */
265		in_mklev = TRUE;
266		mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, MM_NONAME);
267		in_mklev = FALSE;
268		if (!mtmp) return;
269		mtmp = christen_monst(mtmp, plname);
270		if (corpse)
271			(void) obj_attach_mid(corpse, mtmp->m_id);
272	} else {
273		/* give your possessions to the monster you become */
274		in_mklev = TRUE;
275		mtmp = makemon(&mons[u.ugrave_arise], u.ux, u.uy, NO_MM_FLAGS);
276		in_mklev = FALSE;
277		if (!mtmp) {
278			drop_upon_death((struct monst *)0, (struct obj *)0);
279			return;
280		}
281		mtmp = christen_monst(mtmp, plname);
282		newsym(u.ux, u.uy);
283		Your("body rises from the dead as %s...",
284			an(mons[u.ugrave_arise].mname));
285		display_nhwindow(WIN_MESSAGE, FALSE);
286		drop_upon_death(mtmp, (struct obj *)0);
287		m_dowear(mtmp, TRUE);
288	}
289	if (mtmp) {
290		mtmp->m_lev = (u.ulevel ? u.ulevel : 1);
291		mtmp->mhp = mtmp->mhpmax = u.uhpmax;
292		mtmp->female = flags.female;
293		mtmp->msleeping = 1;
294	}
295	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
296		resetobjs(mtmp->minvent,FALSE);
297		/* do not zero out m_ids for bones levels any more */
298		mtmp->mlstmv = 0L;
299		if(mtmp->mtame) mtmp->mtame = mtmp->mpeaceful = 0;
300	}
301	for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
302		ttmp->madeby_u = 0;
303		ttmp->tseen = (ttmp->ttyp == HOLE);
304	}
305	resetobjs(fobj,FALSE);
306	resetobjs(level.buriedobjlist, FALSE);
307
308	/* Hero is no longer on the map. */
309	u.ux = u.uy = 0;
310
311	/* Clear all memory from the level. */
312	for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++) {
313	    levl[x][y].seenv = 0;
314	    levl[x][y].waslit = 0;
315	    levl[x][y].glyph = cmap_to_glyph(S_stone);
316	}
317
318	fd = create_bonesfile(&u.uz, &bonesid, whynot);
319	if(fd < 0) {
320#ifdef WIZARD
321		if(wizard)
322			pline("%s", whynot);
323#endif
324		/* bones file creation problems are silent to the player.
325		 * Keep it that way, but place a clue into the paniclog.
326		 */
327		paniclog("savebones", whynot);
328		return;
329	}
330	c = (char) (strlen(bonesid) + 1);
331
332#ifdef MFLOPPY  /* check whether there is room */
333	if (iflags.checkspace) {
334	    savelev(fd, ledger_no(&u.uz), COUNT_SAVE);
335	    /* savelev() initializes bytes_counted to 0, so it must come
336	     * first here even though it does not in the real save.  the
337	     * resulting extra bflush() at the end of savelev() may increase
338	     * bytes_counted by a couple over what the real usage will be.
339	     *
340	     * note it is safe to call store_version() here only because
341	     * bufon() is null for ZEROCOMP, which MFLOPPY uses -- otherwise
342	     * this code would have to know the size of the version
343	     * information itself.
344	     */
345	    store_version(fd);
346	    bwrite(fd, (genericptr_t) &c, sizeof c);
347	    bwrite(fd, (genericptr_t) bonesid, (unsigned) c);	/* DD.nnn */
348	    savefruitchn(fd, COUNT_SAVE);
349	    bflush(fd);
350	    if (bytes_counted > freediskspace(bones)) { /* not enough room */
351# ifdef WIZARD
352		if (wizard)
353			pline("Insufficient space to create bones file.");
354# endif
355		(void) close(fd);
356		cancel_bonesfile();
357		return;
358	    }
359	    co_false();	/* make sure stuff before savelev() gets written */
360	}
361#endif /* MFLOPPY */
362
363	store_version(fd);
364	bwrite(fd, (genericptr_t) &c, sizeof c);
365	bwrite(fd, (genericptr_t) bonesid, (unsigned) c);	/* DD.nnn */
366	savefruitchn(fd, WRITE_SAVE | FREE_SAVE);
367	update_mlstmv();	/* update monsters for eventual restoration */
368	savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
369	bclose(fd);
370	commit_bonesfile(&u.uz);
371	compress_bonesfile();
372}
373
374int
375getbones()
376{
377	register int fd;
378	register int ok;
379	char c, *bonesid, oldbonesid[10];
380
381	if(discover)		/* save bones files for real games */
382		return(0);
383
384	/* wizard check added by GAN 02/05/87 */
385	if(rn2(3)	/* only once in three times do we find bones */
386#ifdef WIZARD
387		&& !wizard
388#endif
389		) return(0);
390	if(no_bones_level(&u.uz)) return(0);
391	fd = open_bonesfile(&u.uz, &bonesid);
392	if (fd < 0) return(0);
393
394	if ((ok = uptodate(fd, bones)) == 0) {
395#ifdef WIZARD
396	    if (!wizard)
397#endif
398		pline("Discarding unuseable bones; no need to panic...");
399	} else {
400#ifdef WIZARD
401		if(wizard)  {
402			if(yn("Get bones?") == 'n') {
403				(void) close(fd);
404				compress_bonesfile();
405				return(0);
406			}
407		}
408#endif
409		mread(fd, (genericptr_t) &c, sizeof c);	/* length incl. '\0' */
410		mread(fd, (genericptr_t) oldbonesid, (unsigned) c); /* DD.nnn */
411		if (strcmp(bonesid, oldbonesid) != 0) {
412			char errbuf[BUFSZ];
413
414			Sprintf(errbuf, "This is bones level '%s', not '%s'!",
415				oldbonesid, bonesid);
416#ifdef WIZARD
417			if (wizard) {
418				pline("%s", errbuf);
419				ok = FALSE;	/* won't die of trickery */
420			}
421#endif
422			trickery(errbuf);
423		} else {
424			register struct monst *mtmp;
425
426			getlev(fd, 0, 0, TRUE);
427
428			/* Note that getlev() now keeps tabs on unique
429			 * monsters such as demon lords, and tracks the
430			 * birth counts of all species just as makemon()
431			 * does.  If a bones monster is extinct or has been
432			 * subject to genocide, their mhpmax will be
433			 * set to the magic DEFUNCT_MONSTER cookie value.
434			 */
435			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
436			    if (mtmp->mhpmax == DEFUNCT_MONSTER) {
437#if defined(DEBUG) && defined(WIZARD)
438				if (wizard)
439				    pline("Removing defunct monster %s from bones.",
440					mtmp->data->mname);
441#endif
442				mongone(mtmp);
443			    } else
444				/* to correctly reset named artifacts on the level */
445				resetobjs(mtmp->minvent,TRUE);
446			}
447			resetobjs(fobj,TRUE);
448			resetobjs(level.buriedobjlist,TRUE);
449		}
450	}
451	(void) close(fd);
452
453#ifdef WIZARD
454	if(wizard) {
455		if(yn("Unlink bones?") == 'n') {
456			compress_bonesfile();
457			return(ok);
458		}
459	}
460#endif
461	if (!delete_bonesfile(&u.uz)) {
462		/* When N games try to simultaneously restore the same
463		 * bones file, N-1 of them will fail to delete it
464		 * (the first N-1 under AmigaDOS, the last N-1 under UNIX).
465		 * So no point in a mysterious message for a normal event
466		 * -- just generate a new level for those N-1 games.
467		 */
468		/* pline("Cannot unlink bones."); */
469		return(0);
470	}
471	return(ok);
472}
473
474/*bones.c*/
475