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