OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / src / bones.c
1 /* NetHack 3.6  bones.c $NHDT-Date: 1449269914 2015/12/04 22:58:34 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.66 $ */
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 boolean FDECL(fixuporacle, (struct monst *));
17
18 STATIC_OVL boolean
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))
26         assign_level(lev, &save_dlevel);
27
28     return (boolean) (((sptr = Is_special(lev)) != 0 && !sptr->boneid)
29                       || !dungeons[lev->dnum].boneid
30                       /* no bones on the last or multiway branch levels
31                          in any dungeon (level 1 isn't multiway) */
32                       || Is_botlevel(lev)
33                       || (Is_branchlev(lev) && lev->dlevel > 1)
34                       /* no bones in the invocation level */
35                       || (In_hell(lev)
36                           && lev->dlevel == dunlevs_in_dungeon(lev) - 1));
37 }
38
39 /* Call this function for each fruit object saved in the bones level: it marks
40  * that particular type of fruit as existing (the marker is that that type's
41  * ID is positive instead of negative).  This way, when we later save the
42  * chain of fruit types, we know to only save the types that exist.
43  */
44 STATIC_OVL void
45 goodfruit(id)
46 int id;
47 {
48     register struct fruit *f;
49
50     for (f = ffruit; f; f = f->nextf) {
51         if (f->fid == -id) {
52             f->fid = id;
53             return;
54         }
55     }
56 }
57
58 STATIC_OVL void
59 resetobjs(ochain, restore)
60 struct obj *ochain;
61 boolean restore;
62 {
63     struct obj *otmp, *nobj;
64
65     for (otmp = ochain; otmp; otmp = nobj) {
66         nobj = otmp->nobj;
67         if (otmp->cobj)
68             resetobjs(otmp->cobj, restore);
69         if (otmp->in_use) {
70             obj_extract_self(otmp);
71             dealloc_obj(otmp);
72             continue;
73         }
74
75         if (restore) {
76             /* artifact bookkeeping needs to be done during
77                restore; other fixups are done while saving */
78             if (otmp->oartifact) {
79                 if (exist_artifact(otmp->otyp, safe_oname(otmp))
80                     || is_quest_artifact(otmp)) {
81                     /* prevent duplicate--revert to ordinary obj */
82                     otmp->oartifact = 0;
83                     if (has_oname(otmp))
84                         free_oname(otmp);
85                 } else {
86                     artifact_exists(otmp, safe_oname(otmp), TRUE);
87                 }
88             } else if (has_oname(otmp)) {
89                 sanitize_name(ONAME(otmp));
90             }
91         } else { /* saving */
92             /* do not zero out o_ids for ghost levels anymore */
93
94             if (objects[otmp->otyp].oc_uses_known)
95                 otmp->known = 0;
96             otmp->dknown = otmp->bknown = 0;
97             otmp->rknown = 0;
98             otmp->lknown = 0;
99             otmp->cknown = 0;
100             otmp->invlet = 0;
101             otmp->no_charge = 0;
102             otmp->was_thrown = 0;
103
104             /* strip user-supplied names */
105             /* Statue and some corpse names are left intact,
106                presumably in case they came from score file.
107                [TODO: this ought to be done differently--names
108                which came from such a source or came from any
109                stoned or killed monster should be flagged in
110                some manner; then we could just check the flag
111                here and keep "real" names (dead pets, &c) while
112                discarding player notes attached to statues.] */
113             if (has_oname(otmp)
114                 && !(otmp->oartifact || otmp->otyp == STATUE
115                      || otmp->otyp == SPE_NOVEL
116                      || (otmp->otyp == CORPSE
117                          && otmp->corpsenm >= SPECIAL_PM))) {
118                 free_oname(otmp);
119             }
120
121             if (otmp->otyp == SLIME_MOLD)
122                 goodfruit(otmp->spe);
123 #ifdef MAIL
124             else if (otmp->otyp == SCR_MAIL)
125                 otmp->spe = 1;
126 #endif
127             else if (otmp->otyp == EGG)
128                 otmp->spe = 0;
129             else if (otmp->otyp == TIN) {
130                 /* make tins of unique monster's meat be empty */
131                 if (otmp->corpsenm >= LOW_PM
132                     && unique_corpstat(&mons[otmp->corpsenm]))
133                     otmp->corpsenm = NON_PM;
134             } else if (otmp->otyp == CORPSE || otmp->otyp == STATUE) {
135                 int mnum = otmp->corpsenm;
136
137                 /* Discard incarnation details of unique
138                    monsters (by passing null instead of otmp
139                    for object), shopkeepers (by passing false
140                    for revival flag), temple priests, and
141                    vault guards in order to prevent corpse
142                    revival or statue reanimation. */
143                 if (has_omonst(otmp)
144                     && cant_revive(&mnum, FALSE, (struct obj *) 0)) {
145                     free_omonst(otmp);
146                     /* mnum is now either human_zombie or
147                        doppelganger; for corpses of uniques,
148                        we need to force the transformation
149                        now rather than wait until a revival
150                        attempt, otherwise eating this corpse
151                        would behave as if it remains unique */
152                     if (mnum == PM_DOPPELGANGER && otmp->otyp == CORPSE)
153                         set_corpsenm(otmp, mnum);
154                 }
155             } else if (otmp->otyp == AMULET_OF_YENDOR) {
156                 /* no longer the real Amulet */
157                 otmp->otyp = FAKE_AMULET_OF_YENDOR;
158                 curse(otmp);
159             } else if (otmp->otyp == CANDELABRUM_OF_INVOCATION) {
160                 if (otmp->lamplit)
161                     end_burn(otmp, TRUE);
162                 otmp->otyp = WAX_CANDLE;
163                 otmp->age = 50L; /* assume used */
164                 if (otmp->spe > 0)
165                     otmp->quan = (long) otmp->spe;
166                 otmp->spe = 0;
167                 otmp->owt = weight(otmp);
168                 curse(otmp);
169             } else if (otmp->otyp == BELL_OF_OPENING) {
170                 otmp->otyp = BELL;
171                 curse(otmp);
172             } else if (otmp->otyp == SPE_BOOK_OF_THE_DEAD) {
173                 otmp->otyp = SPE_BLANK_PAPER;
174                 curse(otmp);
175             }
176         }
177     }
178 }
179
180 /* while loading bones, strip out text possibly supplied by old player
181    that might accidentally or maliciously disrupt new player's display */
182 void
183 sanitize_name(namebuf)
184 char *namebuf;
185 {
186     int c;
187     boolean strip_8th_bit =
188         !strcmp(windowprocs.name, "tty") && !iflags.wc_eight_bit_input;
189
190     /* it's tempting to skip this for single-user platforms, since
191        only the current player could have left these bones--except
192        things like "hearse" and other bones exchange schemes make
193        that assumption false */
194     while (*namebuf) {
195         c = *namebuf & 0177;
196         if (c < ' ' || c == '\177') {
197             /* non-printable or undesirable */
198             *namebuf = '.';
199         } else if (c != *namebuf) {
200             /* expected to be printable if user wants such things */
201             if (strip_8th_bit)
202                 *namebuf = '_';
203         }
204         ++namebuf;
205     }
206 }
207
208 /* called by savebones(); also by finish_paybill(shk.c) */
209 void
210 drop_upon_death(mtmp, cont, x, y)
211 struct monst *mtmp;
212 struct obj *cont;
213 int x, y;
214 {
215     struct obj *otmp;
216
217     u.twoweap = 0; /* ensure curse() won't cause swapwep to drop twice */
218     while ((otmp = invent) != 0) {
219         obj_extract_self(otmp);
220         obj_no_longer_held(otmp);
221
222         otmp->owornmask = 0;
223         /* lamps don't go out when dropped */
224         if ((cont || artifact_light(otmp)) && obj_is_burning(otmp))
225             end_burn(otmp, TRUE); /* smother in statue */
226
227         if (otmp->otyp == SLIME_MOLD)
228             goodfruit(otmp->spe);
229
230         if (rn2(5))
231             curse(otmp);
232         if (mtmp)
233             (void) add_to_minv(mtmp, otmp);
234         else if (cont)
235             (void) add_to_container(cont, otmp);
236         else
237             place_object(otmp, x, y);
238     }
239     if (cont)
240         cont->owt = weight(cont);
241 }
242
243 /* possibly restore oracle's room and/or put her back inside it; returns
244    False if she's on the wrong level and should be removed, True otherwise */
245 STATIC_OVL boolean
246 fixuporacle(oracle)
247 struct monst *oracle;
248 {
249     coord cc;
250     int ridx, o_ridx;
251
252     /* oracle doesn't move, but knight's joust or monk's staggering blow
253        could push her onto a hole in the floor; at present, traps don't
254        activate in such situation hence she won't fall to another level;
255        however, that could change so be prepared to cope with such things */
256     if (!Is_oracle_level(&u.uz))
257         return FALSE;
258
259     oracle->mpeaceful = 1;
260     o_ridx = levl[oracle->mx][oracle->my].roomno - ROOMOFFSET;
261     if (o_ridx >= 0 && rooms[o_ridx].rtype == DELPHI)
262         return TRUE; /* no fixup needed */
263
264     /*
265      * The Oracle isn't in DELPHI room.  Either hero entered her chamber
266      * and got the one-time welcome message, converting it into an
267      * ordinary room, or she got teleported out, or both.  Try to put
268      * her back inside her room, if necessary, and restore its type.
269      */
270
271     /* find original delphi chamber; should always succeed */
272     for (ridx = 0; ridx < SIZE(rooms); ++ridx)
273         if (rooms[ridx].orig_rtype == DELPHI)
274             break;
275
276     if (o_ridx != ridx && ridx < SIZE(rooms)) {
277         /* room found and she's not not in it, so try to move her there */
278         cc.x = (rooms[ridx].lx + rooms[ridx].hx) / 2;
279         cc.y = (rooms[ridx].ly + rooms[ridx].hy) / 2;
280         if (enexto(&cc, cc.x, cc.y, oracle->data)) {
281             rloc_to(oracle, cc.x, cc.y);
282             o_ridx = levl[oracle->mx][oracle->my].roomno - ROOMOFFSET;
283         }
284         /* [if her room is already full, she might end up outside;
285            that's ok, next hero just won't get any welcome message,
286            same as used to happen before this fixup was introduced] */
287     }
288     if (ridx == o_ridx) /* if she's in her room, mark it as such */
289         rooms[ridx].rtype = DELPHI;
290     return TRUE; /* keep oracle in new bones file */
291 }
292
293 /* check whether bones are feasible */
294 boolean
295 can_make_bones()
296 {
297     register struct trap *ttmp;
298
299     if (!flags.bones)
300         return FALSE;
301     if (ledger_no(&u.uz) <= 0 || ledger_no(&u.uz) > maxledgerno())
302         return FALSE;
303     if (no_bones_level(&u.uz))
304         return FALSE; /* no bones for specific levels */
305     if (u.uswallow) {
306         return FALSE; /* no bones when swallowed */
307     }
308     if (!Is_branchlev(&u.uz)) {
309         /* no bones on non-branches with portals */
310         for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
311             if (ttmp->ttyp == MAGIC_PORTAL)
312                 return FALSE;
313     }
314
315     if (depth(&u.uz) <= 0                 /* bulletproofing for endgame */
316         || (!rn2(1 + (depth(&u.uz) >> 2)) /* fewer ghosts on low levels */
317             && !wizard))
318         return FALSE;
319     /* don't let multiple restarts generate multiple copies of objects
320        in bones files */
321     if (discover)
322         return FALSE;
323     return TRUE;
324 }
325
326 /* save bones and possessions of a deceased adventurer */
327 void
328 savebones(how, when, corpse)
329 int how;
330 time_t when;
331 struct obj *corpse;
332 {
333     int fd, x, y;
334     struct trap *ttmp;
335     struct monst *mtmp;
336     struct permonst *mptr;
337     struct fruit *f;
338     struct cemetery *newbones;
339     char c, *bonesid;
340     char whynot[BUFSZ];
341
342     /* caller has already checked `can_make_bones()' */
343
344     clear_bypasses();
345     fd = open_bonesfile(&u.uz, &bonesid);
346     if (fd >= 0) {
347         (void) nhclose(fd);
348         if (wizard) {
349             if (yn("Bones file already exists.  Replace it?") == 'y') {
350                 if (delete_bonesfile(&u.uz))
351                     goto make_bones;
352                 else
353                     pline("Cannot unlink old bones.");
354             }
355         }
356         /* compression can change the file's name, so must
357            wait until after any attempt to delete this file */
358         compress_bonesfile();
359         return;
360     }
361
362 make_bones:
363     unleash_all();
364     /* in case these characters are not in their home bases */
365     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
366         if (DEADMONSTER(mtmp))
367             continue;
368         mptr = mtmp->data;
369         if (mtmp->iswiz || mptr == &mons[PM_MEDUSA]
370             || mptr->msound == MS_NEMESIS || mptr->msound == MS_LEADER
371             || mptr == &mons[PM_VLAD_THE_IMPALER]
372             || (mptr == &mons[PM_ORACLE] && !fixuporacle(mtmp)))
373             mongone(mtmp);
374     }
375     if (u.usteed)
376         dismount_steed(DISMOUNT_BONES);
377     dmonsfree(); /* discard dead or gone monsters */
378
379     /* mark all fruits as nonexistent; when we come to them we'll mark
380      * them as existing (using goodfruit())
381      */
382     for (f = ffruit; f; f = f->nextf)
383         f->fid = -f->fid;
384
385     /* check iron balls separately--maybe they're not carrying it */
386     if (uball)
387         uball->owornmask = uchain->owornmask = 0;
388
389     /* dispose of your possessions, usually cursed */
390     if (u.ugrave_arise == (NON_PM - 1)) {
391         struct obj *otmp;
392
393         /* embed your possessions in your statue */
394         otmp = mk_named_object(STATUE, &mons[u.umonnum], u.ux, u.uy, plname);
395
396         drop_upon_death((struct monst *) 0, otmp, u.ux, u.uy);
397         if (!otmp)
398             return; /* couldn't make statue */
399         mtmp = (struct monst *) 0;
400     } else if (u.ugrave_arise < LOW_PM) {
401         /* drop everything */
402         drop_upon_death((struct monst *) 0, (struct obj *) 0, u.ux, u.uy);
403         /* trick makemon() into allowing monster creation
404          * on your location
405          */
406         in_mklev = TRUE;
407         mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, MM_NONAME);
408         in_mklev = FALSE;
409         if (!mtmp)
410             return;
411         mtmp = christen_monst(mtmp, plname);
412         if (corpse)
413             (void) obj_attach_mid(corpse, mtmp->m_id);
414     } else {
415         /* give your possessions to the monster you become */
416         in_mklev = TRUE; /* use <u.ux,u.uy> as-is */
417         mtmp = makemon(&mons[u.ugrave_arise], u.ux, u.uy, NO_MINVENT);
418         in_mklev = FALSE;
419         if (!mtmp) {
420             drop_upon_death((struct monst *) 0, (struct obj *) 0, u.ux, u.uy);
421             u.ugrave_arise = NON_PM; /* in case caller cares */
422             return;
423         }
424         /* give mummy-from-hero a wrapping unless hero already
425            carries one; don't bother forcing it to become worn */
426         if (mtmp->data->mlet == S_MUMMY && !carrying(MUMMY_WRAPPING))
427             (void) mongets(mtmp, MUMMY_WRAPPING);
428         mtmp = christen_monst(mtmp, plname);
429         newsym(u.ux, u.uy);
430         /* ["Your body rises from the dead as an <mname>..." used
431            to be given here, but it has been moved to done() so that
432            it gets delivered even when savebones() isn't called] */
433         drop_upon_death(mtmp, (struct obj *) 0, u.ux, u.uy);
434         m_dowear(mtmp, TRUE);
435     }
436     if (mtmp) {
437         mtmp->m_lev = (u.ulevel ? u.ulevel : 1);
438         mtmp->mhp = mtmp->mhpmax = u.uhpmax;
439         mtmp->female = flags.female;
440         mtmp->msleeping = 1;
441     }
442     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
443         resetobjs(mtmp->minvent, FALSE);
444         /* do not zero out m_ids for bones levels any more */
445         mtmp->mlstmv = 0L;
446         if (mtmp->mtame)
447             mtmp->mtame = mtmp->mpeaceful = 0;
448     }
449     for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
450         ttmp->madeby_u = 0;
451         ttmp->tseen = (ttmp->ttyp == HOLE);
452     }
453     resetobjs(fobj, FALSE);
454     resetobjs(level.buriedobjlist, FALSE);
455
456     /* Hero is no longer on the map. */
457     u.ux = u.uy = 0;
458
459     /* Clear all memory from the level. */
460     for (x = 1; x < COLNO; x++)
461         for (y = 0; y < ROWNO; y++) {
462             levl[x][y].seenv = 0;
463             levl[x][y].waslit = 0;
464             levl[x][y].glyph = cmap_to_glyph(S_stone);
465             lastseentyp[x][y] = 0;
466         }
467
468     /* Attach bones info to the current level before saving. */
469     newbones = (struct cemetery *) alloc(sizeof *newbones);
470     /* entries are '\0' terminated but have fixed length allocations,
471        so pre-fill with spaces to initialize any excess room */
472     (void) memset((genericptr_t) newbones, ' ', sizeof *newbones);
473     /* format name+role,&c, death reason, and date+time;
474        gender and alignment reflect final values rather than what the
475        character started out as, same as topten and logfile entries */
476     Sprintf(newbones->who, "%s-%.3s-%.3s-%.3s-%.3s", plname, urole.filecode,
477             urace.filecode, genders[flags.female].filecode,
478             aligns[1 - u.ualign.type].filecode);
479     formatkiller(newbones->how, sizeof newbones->how, how);
480     Strcpy(newbones->when, yyyymmddhhmmss(when));
481     /* final resting place, used to decide when bones are discovered */
482     newbones->frpx = u.ux, newbones->frpy = u.uy;
483     newbones->bonesknown = FALSE;
484     /* if current character died on a bones level, the cemetery list
485        will have multiple entries, most recent (this dead hero) first */
486     newbones->next = level.bonesinfo;
487     level.bonesinfo = newbones;
488     /* flag these bones if they are being created in wizard mode;
489        they might already be flagged as such, even when we're playing
490        in normal mode, if this level came from a previous bones file */
491     if (wizard)
492         level.flags.wizard_bones = 1;
493
494     fd = create_bonesfile(&u.uz, &bonesid, whynot);
495     if (fd < 0) {
496         if (wizard)
497             pline1(whynot);
498         /* bones file creation problems are silent to the player.
499          * Keep it that way, but place a clue into the paniclog.
500          */
501         paniclog("savebones", whynot);
502         return;
503     }
504     c = (char) (strlen(bonesid) + 1);
505
506 #ifdef MFLOPPY /* check whether there is room */
507     if (iflags.checkspace) {
508         savelev(fd, ledger_no(&u.uz), COUNT_SAVE);
509         /* savelev() initializes bytes_counted to 0, so it must come
510          * first here even though it does not in the real save.  the
511          * resulting extra bflush() at the end of savelev() may increase
512          * bytes_counted by a couple over what the real usage will be.
513          *
514          * note it is safe to call store_version() here only because
515          * bufon() is null for ZEROCOMP, which MFLOPPY uses -- otherwise
516          * this code would have to know the size of the version
517          * information itself.
518          */
519         store_version(fd);
520         store_savefileinfo(fd);
521         bwrite(fd, (genericptr_t) &c, sizeof c);
522         bwrite(fd, (genericptr_t) bonesid, (unsigned) c); /* DD.nnn */
523         savefruitchn(fd, COUNT_SAVE);
524         bflush(fd);
525         if (bytes_counted > freediskspace(bones)) { /* not enough room */
526             if (wizard)
527                 pline("Insufficient space to create bones file.");
528             (void) nhclose(fd);
529             cancel_bonesfile();
530             return;
531         }
532         co_false(); /* make sure stuff before savelev() gets written */
533     }
534 #endif /* MFLOPPY */
535
536     store_version(fd);
537     store_savefileinfo(fd);
538     bwrite(fd, (genericptr_t) &c, sizeof c);
539     bwrite(fd, (genericptr_t) bonesid, (unsigned) c); /* DD.nnn */
540     savefruitchn(fd, WRITE_SAVE | FREE_SAVE);
541     update_mlstmv(); /* update monsters for eventual restoration */
542     savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
543     bclose(fd);
544     commit_bonesfile(&u.uz);
545     compress_bonesfile();
546 }
547
548 int
549 getbones()
550 {
551     register int fd;
552     register int ok;
553     char c, *bonesid, oldbonesid[10];
554
555     if (discover) /* save bones files for real games */
556         return 0;
557
558     if (!flags.bones)
559         return 0;
560     /* wizard check added by GAN 02/05/87 */
561     if (rn2(3) /* only once in three times do we find bones */
562         && !wizard)
563         return 0;
564     if (no_bones_level(&u.uz))
565         return 0;
566     fd = open_bonesfile(&u.uz, &bonesid);
567     if (fd < 0)
568         return 0;
569
570     if (validate(fd, bones) != 0) {
571         if (!wizard)
572             pline("Discarding unuseable bones; no need to panic...");
573         ok = FALSE;
574     } else {
575         ok = TRUE;
576         if (wizard) {
577             if (yn("Get bones?") == 'n') {
578                 (void) nhclose(fd);
579                 compress_bonesfile();
580                 return 0;
581             }
582         }
583         mread(fd, (genericptr_t) &c, sizeof c); /* length incl. '\0' */
584         mread(fd, (genericptr_t) oldbonesid, (unsigned) c); /* DD.nnn */
585         if (strcmp(bonesid, oldbonesid) != 0) {
586             char errbuf[BUFSZ];
587
588             Sprintf(errbuf, "This is bones level '%s', not '%s'!", oldbonesid,
589                     bonesid);
590             if (wizard) {
591                 pline1(errbuf);
592                 ok = FALSE; /* won't die of trickery */
593             }
594             trickery(errbuf);
595         } else {
596             register struct monst *mtmp;
597
598             getlev(fd, 0, 0, TRUE);
599
600             /* Note that getlev() now keeps tabs on unique
601              * monsters such as demon lords, and tracks the
602              * birth counts of all species just as makemon()
603              * does.  If a bones monster is extinct or has been
604              * subject to genocide, their mhpmax will be
605              * set to the magic DEFUNCT_MONSTER cookie value.
606              */
607             for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
608                 if (has_mname(mtmp))
609                     sanitize_name(MNAME(mtmp));
610                 if (mtmp->mhpmax == DEFUNCT_MONSTER) {
611                     if (wizard) {
612                         debugpline1("Removing defunct monster %s from bones.",
613                                     mtmp->data->mname);
614                     }
615                     mongone(mtmp);
616                 } else
617                     /* to correctly reset named artifacts on the level */
618                     resetobjs(mtmp->minvent, TRUE);
619             }
620             resetobjs(fobj, TRUE);
621             resetobjs(level.buriedobjlist, TRUE);
622         }
623     }
624     (void) nhclose(fd);
625     sanitize_engravings();
626     u.uroleplay.numbones++;
627
628     if (wizard) {
629         if (yn("Unlink bones?") == 'n') {
630             compress_bonesfile();
631             return ok;
632         }
633     }
634     if (!delete_bonesfile(&u.uz)) {
635         /* When N games try to simultaneously restore the same
636          * bones file, N-1 of them will fail to delete it
637          * (the first N-1 under AmigaDOS, the last N-1 under UNIX).
638          * So no point in a mysterious message for a normal event
639          * -- just generate a new level for those N-1 games.
640          */
641         /* pline("Cannot unlink bones."); */
642         return 0;
643     }
644     return ok;
645 }
646
647 /*bones.c*/