1 /*	SCCS Id: @(#)bones.c	3.3	2000/05/28	*/
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 
8 extern char bones[];	/* from files.c */
9 #ifdef MFLOPPY
10 extern long bytes_counted;
11 #endif
12 
13 STATIC_DCL boolean FDECL(no_bones_level, (d_level *));
14 STATIC_DCL void FDECL(goodfruit, (int));
15 STATIC_DCL void FDECL(resetobjs,(struct obj *,BOOLEAN_P));
16 STATIC_DCL void FDECL(drop_upon_death, (struct monst *, struct obj *));
17 
18 STATIC_OVL boolean
no_bones_level(lev)19 no_bones_level(lev)
20 d_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  */
42 STATIC_OVL void
goodfruit(id)43 goodfruit(id)
44 int 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 
56 STATIC_OVL void
resetobjs(ochain,restore)57 resetobjs(ochain,restore)
58 struct obj *ochain;
59 boolean 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 			} else if (otmp->otyp == BELL_OF_OPENING) {
110 			    otmp->otyp = BELL;
111 			    curse(otmp);
112 			} else if (otmp->otyp == SPE_BOOK_OF_THE_DEAD) {
113 			    otmp->otyp = SPE_BLANK_PAPER;
114 			    curse(otmp);
115 			}
116 		}
117 	}
118 }
119 
120 STATIC_OVL void
drop_upon_death(mtmp,cont)121 drop_upon_death(mtmp, cont)
122 struct monst *mtmp;
123 struct obj *cont;
124 {
125 	struct obj *otmp;
126 
127 	while ((otmp = invent) != 0) {
128 		obj_extract_self(otmp);
129 
130 		otmp->owornmask = 0;
131 		/* lamps don't go out when dropped */
132 		if (cont && obj_is_burning(otmp))	/* smother in statue */
133 			end_burn(otmp, otmp->otyp != MAGIC_LAMP);
134 
135 		if(otmp->otyp == SLIME_MOLD) goodfruit(otmp->spe);
136 
137 		if(rn2(5)) curse(otmp);
138 		if (mtmp)
139 			(void) add_to_minv(mtmp, otmp);
140 		else if (cont)
141 			add_to_container(cont, otmp);
142 		else
143 			place_object(otmp, u.ux, u.uy);
144 	}
145 	if(u.ugold) {
146 		long ugold = u.ugold;
147 		if (mtmp) mtmp->mgold = ugold;
148 		else if (cont) add_to_container(cont, mkgoldobj(ugold));
149 		else (void)mkgold(ugold, u.ux, u.uy);
150 		u.ugold = ugold;	/* undo mkgoldobj()'s removal */
151 	}
152 }
153 
154 /* check whether bones are feasible */
155 boolean
can_make_bones()156 can_make_bones()
157 {
158 	register struct trap *ttmp;
159 
160 	if (ledger_no(&u.uz) <= 0 || ledger_no(&u.uz) > maxledgerno())
161 	    return FALSE;
162 	if (no_bones_level(&u.uz))
163 	    return FALSE;		/* no bones for specific levels */
164 	if (!Is_branchlev(&u.uz)) {
165 	    /* no bones on non-branches with portals */
166 	    for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
167 		if (ttmp->ttyp == MAGIC_PORTAL) return FALSE;
168 	}
169 
170 	if(depth(&u.uz) <= 0 ||		/* bulletproofing for endgame */
171 	   (!rn2(1 + (depth(&u.uz)>>2))	/* fewer ghosts on low levels */
172 #ifdef WIZARD
173 		&& !wizard
174 #endif
175 		)) return FALSE;
176 	/* don't let multiple restarts generate multiple copies of objects
177 	 * in bones files */
178 	if (discover) return FALSE;
179 	return TRUE;
180 }
181 
182 /* save bones and possessions of a deceased adventurer */
183 void
savebones(corpse)184 savebones(corpse)
185 struct obj *corpse;
186 {
187 	int fd, x, y;
188 	struct trap *ttmp;
189 	struct monst *mtmp;
190 	struct permonst *mptr;
191 	struct fruit *f;
192 	char c, *bonesid;
193 
194 	/* caller has already checked `can_make_bones()' */
195 
196 	fd = open_bonesfile(&u.uz, &bonesid);
197 	if (fd >= 0) {
198 		(void) close(fd);
199 		compress_bonesfile();
200 #ifdef WIZARD
201 		if (wizard) {
202 		    if (yn("Bones file already exists.  Replace it?") == 'y') {
203 			if (delete_bonesfile(&u.uz)) goto make_bones;
204 			else pline("Cannot unlink old bones.");
205 		    }
206 		}
207 #endif
208 		return;
209 	}
210 
211  make_bones:
212 	unleash_all();
213 	/* in case these characters are not in their home bases */
214 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
215 	    if (DEADMONSTER(mtmp)) continue;
216 	    mptr = mtmp->data;
217 	    if (mtmp->iswiz || mptr == &mons[PM_MEDUSA] ||
218 		    mptr->msound == MS_NEMESIS || mptr->msound == MS_LEADER ||
219 		    mptr == &mons[PM_VLAD_THE_IMPALER])
220 		mongone(mtmp);
221 	}
222 #ifdef STEED
223 	if (u.usteed) {
224 	    coord cc;
225 
226 	    /* Move the steed to an adjacent square */
227 	    if (enexto(&cc, u.ux, u.uy, u.usteed->data))
228 		rloc_to(u.usteed, cc.x, cc.y);
229 	    u.usteed = 0;
230 	}
231 #endif
232 	dmonsfree();		/* discard dead or gone monsters */
233 
234 	/* mark all fruits as nonexistent; when we come to them we'll mark
235 	 * them as existing (using goodfruit())
236 	 */
237 	for(f=ffruit; f; f=f->nextf) f->fid = -f->fid;
238 
239 	/* check iron balls separately--maybe they're not carrying it */
240 	if (uball) uball->owornmask = uchain->owornmask = 0;
241 
242 	/* dispose of your possessions, usually cursed */
243 	if (u.ugrave_arise == (NON_PM - 1)) {
244 		struct obj *otmp;
245 
246 		/* embed your possessions in your statue */
247 		otmp = mk_named_object(STATUE, &mons[u.umonnum],
248 				       u.ux, u.uy, plname);
249 
250 		drop_upon_death((struct monst *)0, otmp);
251 		if (!otmp) return;	/* couldn't make statue */
252 		mtmp = (struct monst *)0;
253 	} else if (u.ugrave_arise < LOW_PM) {
254 		/* drop everything */
255 		drop_upon_death((struct monst *)0, (struct obj *)0);
256 		/* trick makemon() into allowing monster creation
257 		 * on your location
258 		 */
259 		in_mklev = TRUE;
260 		mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, MM_NONAME);
261 		in_mklev = FALSE;
262 		if (!mtmp) return;
263 		mtmp = christen_monst(mtmp, plname);
264 		if (corpse)
265 			(void) obj_attach_mid(corpse, mtmp->m_id);
266 	} else {
267 		/* give your possessions to the monster you become */
268 		in_mklev = TRUE;
269 		mtmp = makemon(&mons[u.ugrave_arise], u.ux, u.uy, NO_MM_FLAGS);
270 		in_mklev = FALSE;
271 		if (!mtmp) {
272 			drop_upon_death((struct monst *)0, (struct obj *)0);
273 			return;
274 		}
275 		mtmp = christen_monst(mtmp, plname);
276 		newsym(u.ux, u.uy);
277 		Your("body rises from the dead as %s...",
278 			an(mons[u.ugrave_arise].mname));
279 		display_nhwindow(WIN_MESSAGE, FALSE);
280 		drop_upon_death(mtmp, (struct obj *)0);
281 		m_dowear(mtmp, TRUE);
282 	}
283 	if (mtmp) {
284 		mtmp->m_lev = (u.ulevel ? u.ulevel : 1);
285 		mtmp->mhp = mtmp->mhpmax = u.uhpmax;
286 		mtmp->female = flags.female;
287 		mtmp->msleeping = 1;
288 	}
289 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
290 		resetobjs(mtmp->minvent,FALSE);
291 		/* do not zero out m_ids for bones levels any more */
292 		mtmp->mlstmv = 0L;
293 		if(mtmp->mtame) mtmp->mtame = mtmp->mpeaceful = 0;
294 	}
295 	for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
296 		ttmp->madeby_u = 0;
297 		ttmp->tseen = (ttmp->ttyp == HOLE);
298 	}
299 	resetobjs(fobj,FALSE);
300 	resetobjs(level.buriedobjlist, FALSE);
301 
302 	/* Hero is no longer on the map. */
303 	u.ux = u.uy = 0;
304 
305 	/* Clear all memory from the level. */
306 	for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++) {
307 	    levl[x][y].seenv = 0;
308 	    levl[x][y].waslit = 0;
309 	    levl[x][y].glyph = cmap_to_glyph(S_stone);
310 	}
311 
312 	fd = create_bonesfile(&u.uz, &bonesid);
313 	if(fd < 0) {
314 #ifdef WIZARD
315 		if(wizard)
316 			pline("Cannot create bones file - create failed");
317 #endif
318 		return;
319 	}
320 	c = (char) (strlen(bonesid) + 1);
321 
322 #ifdef MFLOPPY  /* check whether there is room */
323 	if (iflags.checkspace) {
324 	    savelev(fd, ledger_no(&u.uz), COUNT_SAVE);
325 	    /* savelev() initializes bytes_counted to 0, so it must come
326 	     * first here even though it does not in the real save.  the
327 	     * resulting extra bflush() at the end of savelev() may increase
328 	     * bytes_counted by a couple over what the real usage will be.
329 	     *
330 	     * note it is safe to call store_version() here only because
331 	     * bufon() is null for ZEROCOMP, which MFLOPPY uses -- otherwise
332 	     * this code would have to know the size of the version
333 	     * information itself.
334 	     */
335 	    store_version(fd);
336 	    bwrite(fd, (genericptr_t) &c, sizeof c);
337 	    bwrite(fd, (genericptr_t) bonesid, (unsigned) c);	/* DD.nnn */
338 	    savefruitchn(fd, COUNT_SAVE);
339 	    bflush(fd);
340 	    if (bytes_counted > freediskspace(bones)) { /* not enough room */
341 # ifdef WIZARD
342 		if (wizard)
343 			pline("Insufficient space to create bones file.");
344 # endif
345 		(void) close(fd);
346 		cancel_bonesfile();
347 		return;
348 	    }
349 	    co_false();	/* make sure stuff before savelev() gets written */
350 	}
351 #endif /* MFLOPPY */
352 
353 	store_version(fd);
354 	bwrite(fd, (genericptr_t) &c, sizeof c);
355 	bwrite(fd, (genericptr_t) bonesid, (unsigned) c);	/* DD.nnn */
356 	savefruitchn(fd, WRITE_SAVE | FREE_SAVE);
357 	update_mlstmv();	/* update monsters for eventual restoration */
358 	savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
359 	bclose(fd);
360 	commit_bonesfile(&u.uz);
361 	compress_bonesfile();
362 }
363 
364 int
getbones()365 getbones()
366 {
367 	register int fd;
368 	register int ok;
369 	char c, *bonesid, oldbonesid[10];
370 
371 	if(discover)		/* save bones files for real games */
372 		return(0);
373 
374 	/* wizard check added by GAN 02/05/87 */
375 	if(rn2(3)	/* only once in three times do we find bones */
376 #ifdef WIZARD
377 		&& !wizard
378 #endif
379 		) return(0);
380 	if(no_bones_level(&u.uz)) return(0);
381 	fd = open_bonesfile(&u.uz, &bonesid);
382 	if (fd < 0) return(0);
383 
384 	if ((ok = uptodate(fd, bones)) == 0) {
385 #ifdef WIZARD
386 	    if (!wizard)
387 #endif
388 		pline("Discarding unuseable bones; no need to panic...");
389 	} else {
390 #ifdef WIZARD
391 		if(wizard)  {
392 			if(yn("Get bones?") == 'n') {
393 				(void) close(fd);
394 				compress_bonesfile();
395 				return(0);
396 			}
397 		}
398 #endif
399 		mread(fd, (genericptr_t) &c, sizeof c);	/* length incl. '\0' */
400 		mread(fd, (genericptr_t) oldbonesid, (unsigned) c); /* DD.nnn */
401 		if (strcmp(bonesid, oldbonesid)) {
402 #ifdef WIZARD
403 			if (wizard) {
404 				pline("This is bones level '%s', not '%s'!",
405 					oldbonesid, bonesid);
406 				ok = FALSE;	/* won't die of trickery */
407 			}
408 #endif
409 			trickery();
410 		} else {
411 			register struct monst *mtmp;
412 			int mndx;
413 
414 			getlev(fd, 0, 0, TRUE);
415 
416 			/* to correctly reset named artifacts on the level and
417 			   to keep tabs on unique monsters like demon lords */
418 			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
419 			    mndx = monsndx(mtmp->data);
420 			    if (mvitals[mndx].mvflags & G_EXTINCT) {
421 				mongone(mtmp);
422 			    } else {
423 				if (mons[mndx].geno & G_UNIQ)
424 				    mvitals[mndx].mvflags |= G_EXTINCT;
425 				resetobjs(mtmp->minvent,TRUE);
426 			    }
427 			}
428 			resetobjs(fobj,TRUE);
429 			resetobjs(level.buriedobjlist,TRUE);
430 		}
431 	}
432 	(void) close(fd);
433 
434 #ifdef WIZARD
435 	if(wizard) {
436 		if(yn("Unlink bones?") == 'n') {
437 			compress_bonesfile();
438 			return(ok);
439 		}
440 	}
441 #endif
442 	if (!delete_bonesfile(&u.uz)) {
443 		/* When N games try to simultaneously restore the same
444 		 * bones file, N-1 of them will fail to delete it
445 		 * (the first N-1 under AmigaDOS, the last N-1 under UNIX).
446 		 * So no point in a mysterious message for a normal event
447 		 * -- just generate a new level for those N-1 games.
448 		 */
449 		/* pline("Cannot unlink bones."); */
450 		return(0);
451 	}
452 	return(ok);
453 }
454 
455 /*bones.c*/
456