Source:NetHack 3.6.0/src/restore.c

From NetHackWiki
Jump to: navigation, search

Below is the full text to restore.c from the source code of NetHack 3.6.0. To link to a particular line, write [[Source:NetHack 3.6.0/src/restore.c#line123]], for example.

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

Top of file

  1.  /* NetHack 3.6	restore.c	$NHDT-Date: 1446892455 2015/11/07 10:34:15 $  $NHDT-Branch: master $:$NHDT-Revision: 1.101 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5.  #include "hack.h"
  6.  #include "lev.h"
  7.  #include "tcap.h" /* for TERMLIB and ASCIIGRAPH */
  8.  
  9.  #if defined(MICRO)
  10.  extern int dotcnt; /* shared with save */
  11.  extern int dotrow; /* shared with save */
  12.  #endif
  13.  
  14.  #ifdef USE_TILES
  15.  extern void FDECL(substitute_tiles, (d_level *)); /* from tile.c */
  16.  #endif
  17.  
  18.  #ifdef ZEROCOMP
  19.  STATIC_DCL void NDECL(zerocomp_minit);
  20.  STATIC_DCL void FDECL(zerocomp_mread, (int, genericptr_t, unsigned int));
  21.  STATIC_DCL int NDECL(zerocomp_mgetc);
  22.  #endif
  23.  
  24.  STATIC_DCL void NDECL(def_minit);
  25.  STATIC_DCL void FDECL(def_mread, (int, genericptr_t, unsigned int));
  26.  
  27.  STATIC_DCL void NDECL(find_lev_obj);
  28.  STATIC_DCL void FDECL(restlevchn, (int));
  29.  STATIC_DCL void FDECL(restdamage, (int, BOOLEAN_P));
  30.  STATIC_DCL void FDECL(restobj, (int, struct obj *));
  31.  STATIC_DCL struct obj *FDECL(restobjchn, (int, BOOLEAN_P, BOOLEAN_P));
  32.  STATIC_OVL void FDECL(restmon, (int, struct monst *));
  33.  STATIC_DCL struct monst *FDECL(restmonchn, (int, BOOLEAN_P));
  34.  STATIC_DCL struct fruit *FDECL(loadfruitchn, (int));
  35.  STATIC_DCL void FDECL(freefruitchn, (struct fruit *));
  36.  STATIC_DCL void FDECL(ghostfruit, (struct obj *));
  37.  STATIC_DCL boolean
  38.  FDECL(restgamestate, (int, unsigned int *, unsigned int *));
  39.  STATIC_DCL void FDECL(restlevelstate, (unsigned int, unsigned int));
  40.  STATIC_DCL int FDECL(restlevelfile, (int, XCHAR_P));
  41.  STATIC_OVL void FDECL(restore_msghistory, (int));
  42.  STATIC_DCL void FDECL(reset_oattached_mids, (BOOLEAN_P));
  43.  STATIC_DCL void FDECL(rest_levl, (int, BOOLEAN_P));
  44.  
  45.  static struct restore_procs {
  46.      const char *name;
  47.      int mread_flags;
  48.      void NDECL((*restore_minit));
  49.      void FDECL((*restore_mread), (int, genericptr_t, unsigned int));
  50.      void FDECL((*restore_bclose), (int));
  51.  } restoreprocs = {
  52.  #if !defined(ZEROCOMP) || (defined(COMPRESS) || defined(ZLIB_COMP))
  53.      "externalcomp", 0, def_minit, def_mread, def_bclose,
  54.  #else
  55.      "zerocomp", 0, zerocomp_minit, zerocomp_mread, zerocomp_bclose,
  56.  #endif
  57.  };
  58.  
  59.  /*
  60.   * Save a mapping of IDs from ghost levels to the current level.  This
  61.   * map is used by the timer routines when restoring ghost levels.
  62.   */
  63.  #define N_PER_BUCKET 64
  64.  struct bucket {
  65.      struct bucket *next;
  66.      struct {
  67.          unsigned gid; /* ghost ID */
  68.          unsigned nid; /* new ID */
  69.      } map[N_PER_BUCKET];
  70.  };
  71.  
  72.  STATIC_DCL void NDECL(clear_id_mapping);
  73.  STATIC_DCL void FDECL(add_id_mapping, (unsigned, unsigned));
  74.  
  75.  static int n_ids_mapped = 0;
  76.  static struct bucket *id_map = 0;
  77.  
  78.  #ifdef AMII_GRAPHICS
  79.  void FDECL(amii_setpens, (int)); /* use colors from save file */
  80.  extern int amii_numcolors;
  81.  #endif
  82.  
  83.  #include "display.h"
  84.  
  85.  boolean restoring = FALSE;
  86.  static NEARDATA struct fruit *oldfruit;
  87.  static NEARDATA long omoves;
  88.  
  89.  #define Is_IceBox(o) ((o)->otyp == ICE_BOX ? TRUE : FALSE)
  90.  

find_level_obj

  1.  /* Recalculate level.objects[x][y], since this info was not saved. */
  2.  STATIC_OVL void
  3.  find_lev_obj()
  4.  {
  5.      register struct obj *fobjtmp = (struct obj *) 0;
  6.      register struct obj *otmp;
  7.      int x, y;
  8.  
  9.      for (x = 0; x < COLNO; x++)
  10.          for (y = 0; y < ROWNO; y++)
  11.              level.objects[x][y] = (struct obj *) 0;
  12.  
  13.      /*
  14.       * Reverse the entire fobj chain, which is necessary so that we can
  15.       * place the objects in the proper order.  Make all obj in chain
  16.       * OBJ_FREE so place_object will work correctly.
  17.       */
  18.      while ((otmp = fobj) != 0) {
  19.          fobj = otmp->nobj;
  20.          otmp->nobj = fobjtmp;
  21.          otmp->where = OBJ_FREE;
  22.          fobjtmp = otmp;
  23.      }
  24.      /* fobj should now be empty */
  25.  
  26.      /* Set level.objects (as well as reversing the chain back again) */
  27.      while ((otmp = fobjtmp) != 0) {
  28.          fobjtmp = otmp->nobj;
  29.          place_object(otmp, otmp->ox, otmp->oy);
  30.      }
  31.  }
  32.  

inven_inuse

  1.  /* Things that were marked "in_use" when the game was saved (ex. via the
  2.   * infamous "HUP" cheat) get used up here.
  3.   */
  4.  void
  5.  inven_inuse(quietly)
  6.  boolean quietly;
  7.  {
  8.      register struct obj *otmp, *otmp2;
  9.  
  10.      for (otmp = invent; otmp; otmp = otmp2) {
  11.          otmp2 = otmp->nobj;
  12.          if (otmp->in_use) {
  13.              if (!quietly)
  14.                  pline("Finishing off %s...", xname(otmp));
  15.              useup(otmp);
  16.          }
  17.      }
  18.  }
  19.  

restlevchn

  1.  STATIC_OVL void
  2.  restlevchn(fd)
  3.  register int fd;
  4.  {
  5.      int cnt;
  6.      s_level *tmplev, *x;
  7.  
  8.      sp_levchn = (s_level *) 0;
  9.      mread(fd, (genericptr_t) &cnt, sizeof(int));
  10.      for (; cnt > 0; cnt--) {
  11.          tmplev = (s_level *) alloc(sizeof(s_level));
  12.          mread(fd, (genericptr_t) tmplev, sizeof(s_level));
  13.          if (!sp_levchn)
  14.              sp_levchn = tmplev;
  15.          else {
  16.              for (x = sp_levchn; x->next; x = x->next)
  17.                  ;
  18.              x->next = tmplev;
  19.          }
  20.          tmplev->next = (s_level *) 0;
  21.      }
  22.  }
  23.  

restdamage

  1.  STATIC_OVL void
  2.  restdamage(fd, ghostly)
  3.  int fd;
  4.  boolean ghostly;
  5.  {
  6.      int counter;
  7.      struct damage *tmp_dam;
  8.  
  9.      mread(fd, (genericptr_t) &counter, sizeof(counter));
  10.      if (!counter)
  11.          return;
  12.      tmp_dam = (struct damage *) alloc(sizeof(struct damage));
  13.      while (--counter >= 0) {
  14.          char damaged_shops[5], *shp = (char *) 0;
  15.  
  16.          mread(fd, (genericptr_t) tmp_dam, sizeof(*tmp_dam));
  17.          if (ghostly)
  18.              tmp_dam->when += (monstermoves - omoves);
  19.          Strcpy(damaged_shops,
  20.                 in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE));
  21.          if (u.uz.dlevel) {
  22.              /* when restoring, there are two passes over the current
  23.               * level.  the first time, u.uz isn't set, so neither is
  24.               * shop_keeper().  just wait and process the damage on
  25.               * the second pass.
  26.               */
  27.              for (shp = damaged_shops; *shp; shp++) {
  28.                  struct monst *shkp = shop_keeper(*shp);
  29.  
  30.                  if (shkp && inhishop(shkp)
  31.                      && repair_damage(shkp, tmp_dam, TRUE))
  32.                      break;
  33.              }
  34.          }
  35.          if (!shp || !*shp) {
  36.              tmp_dam->next = level.damagelist;
  37.              level.damagelist = tmp_dam;
  38.              tmp_dam = (struct damage *) alloc(sizeof(*tmp_dam));
  39.          }
  40.      }
  41.      free((genericptr_t) tmp_dam);
  42.  }
  43.  

restobj

  1.  /* restore one object */
  2.  STATIC_OVL void
  3.  restobj(fd, otmp)
  4.  int fd;
  5.  struct obj *otmp;
  6.  {
  7.      int buflen;
  8.  
  9.      mread(fd, (genericptr_t) otmp, sizeof(struct obj));
  10.  
  11.      /* next object pointers are invalid; otmp->cobj needs to be left
  12.         as is--being non-null is key to restoring container contents */
  13.      otmp->nobj = otmp->nexthere = (struct obj *) 0;
  14.      /* non-null oextra needs to be reconstructed */
  15.      if (otmp->oextra) {
  16.          otmp->oextra = newoextra();
  17.  
  18.          /* oname - object's name */
  19.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  20.          if (buflen > 0) { /* includes terminating '\0' */
  21.              new_oname(otmp, buflen);
  22.              mread(fd, (genericptr_t) ONAME(otmp), buflen);
  23.          }
  24.          /* omonst - corpse or statue might retain full monster details */
  25.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  26.          if (buflen > 0) {
  27.              newomonst(otmp);
  28.              /* this is actually a monst struct, so we
  29.                 can just defer to restmon() here */
  30.              restmon(fd, OMONST(otmp));
  31.          }
  32.          /* omid - monster id number, connecting corpse to ghost */
  33.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  34.          if (buflen > 0) {
  35.              newomid(otmp);
  36.              mread(fd, (genericptr_t) OMID(otmp), buflen);
  37.          }
  38.          /* olong - temporary gold */
  39.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  40.          if (buflen > 0) {
  41.              newolong(otmp);
  42.              mread(fd, (genericptr_t) OLONG(otmp), buflen);
  43.          }
  44.          /* omailcmd - feedback mechanism for scroll of mail */
  45.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  46.          if (buflen > 0) {
  47.              char *omailcmd = (char *) alloc(buflen);
  48.  
  49.              mread(fd, (genericptr_t) omailcmd, buflen);
  50.              new_omailcmd(otmp, omailcmd);
  51.              free((genericptr_t) omailcmd);
  52.          }
  53.      }
  54.  }
  55.  

restobjchn

  1.  STATIC_OVL struct obj *
  2.  restobjchn(fd, ghostly, frozen)
  3.  register int fd;
  4.  boolean ghostly, frozen;
  5.  {
  6.      register struct obj *otmp, *otmp2 = 0;
  7.      register struct obj *first = (struct obj *) 0;
  8.      int buflen;
  9.  
  10.      while (1) {
  11.          mread(fd, (genericptr_t) &buflen, sizeof buflen);
  12.          if (buflen == -1)
  13.              break;
  14.  
  15.          otmp = newobj();
  16.          restobj(fd, otmp);
  17.          if (!first)
  18.              first = otmp;
  19.          else
  20.              otmp2->nobj = otmp;
  21.  
  22.          if (ghostly) {
  23.              unsigned nid = context.ident++;
  24.              add_id_mapping(otmp->o_id, nid);
  25.              otmp->o_id = nid;
  26.          }
  27.          if (ghostly && otmp->otyp == SLIME_MOLD)
  28.              ghostfruit(otmp);
  29.          /* Ghost levels get object age shifted from old player's clock
  30.           * to new player's clock.  Assumption: new player arrived
  31.           * immediately after old player died.
  32.           */
  33.          if (ghostly && !frozen && !age_is_relative(otmp))
  34.              otmp->age = monstermoves - omoves + otmp->age;
  35.  
  36.          /* get contents of a container or statue */
  37.          if (Has_contents(otmp)) {
  38.              struct obj *otmp3;
  39.              otmp->cobj = restobjchn(fd, ghostly, Is_IceBox(otmp));
  40.              /* restore container back pointers */
  41.              for (otmp3 = otmp->cobj; otmp3; otmp3 = otmp3->nobj)
  42.                  otmp3->ocontainer = otmp;
  43.          }
  44.          if (otmp->bypass)
  45.              otmp->bypass = 0;
  46.          if (!ghostly) {
  47.              /* fix the pointers */
  48.              if (otmp->o_id == context.victual.o_id)
  49.                  context.victual.piece = otmp;
  50.              if (otmp->o_id == context.tin.o_id)
  51.                  context.tin.tin = otmp;
  52.              if (otmp->o_id == context.spbook.o_id)
  53.                  context.spbook.book = otmp;
  54.          }
  55.          otmp2 = otmp;
  56.      }
  57.      if (first && otmp2->nobj) {
  58.          impossible("Restobjchn: error reading objchn.");
  59.          otmp2->nobj = 0;
  60.      }
  61.  
  62.      return first;
  63.  }
  64.  

restmon

  1.  /* restore one monster */
  2.  STATIC_OVL void
  3.  restmon(fd, mtmp)
  4.  int fd;
  5.  struct monst *mtmp;
  6.  {
  7.      int buflen;
  8.  
  9.      mread(fd, (genericptr_t) mtmp, sizeof(struct monst));
  10.  
  11.      /* next monster pointer is invalid */
  12.      mtmp->nmon = (struct monst *) 0;
  13.      /* non-null mextra needs to be reconstructed */
  14.      if (mtmp->mextra) {
  15.          mtmp->mextra = newmextra();
  16.  
  17.          /* mname - monster's name */
  18.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  19.          if (buflen > 0) { /* includes terminating '\0' */
  20.              new_mname(mtmp, buflen);
  21.              mread(fd, (genericptr_t) MNAME(mtmp), buflen);
  22.          }
  23.          /* egd - vault guard */
  24.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  25.          if (buflen > 0) {
  26.              newegd(mtmp);
  27.              mread(fd, (genericptr_t) EGD(mtmp), sizeof(struct egd));
  28.          }
  29.          /* epri - temple priest */
  30.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  31.          if (buflen > 0) {
  32.              newepri(mtmp);
  33.              mread(fd, (genericptr_t) EPRI(mtmp), sizeof(struct epri));
  34.          }
  35.          /* eshk - shopkeeper */
  36.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  37.          if (buflen > 0) {
  38.              neweshk(mtmp);
  39.              mread(fd, (genericptr_t) ESHK(mtmp), sizeof(struct eshk));
  40.          }
  41.          /* emin - minion */
  42.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  43.          if (buflen > 0) {
  44.              newemin(mtmp);
  45.              mread(fd, (genericptr_t) EMIN(mtmp), sizeof(struct emin));
  46.          }
  47.          /* edog - pet */
  48.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  49.          if (buflen > 0) {
  50.              newedog(mtmp);
  51.              mread(fd, (genericptr_t) EDOG(mtmp), sizeof(struct edog));
  52.          }
  53.          /* mcorpsenm - obj->corpsenm for mimic posing as corpse or
  54.             statue (inline int rather than pointer to something) */
  55.          mread(fd, (genericptr_t) &MCORPSENM(mtmp), sizeof MCORPSENM(mtmp));
  56.      } /* mextra */
  57.  }
  58.  

restmonchn

  1.  STATIC_OVL struct monst *
  2.  restmonchn(fd, ghostly)
  3.  register int fd;
  4.  boolean ghostly;
  5.  {
  6.      register struct monst *mtmp, *mtmp2 = 0;
  7.      register struct monst *first = (struct monst *) 0;
  8.      int offset, buflen;
  9.  
  10.      while (1) {
  11.          mread(fd, (genericptr_t) &buflen, sizeof(buflen));
  12.          if (buflen == -1)
  13.              break;
  14.  
  15.          mtmp = newmonst();
  16.          restmon(fd, mtmp);
  17.          if (!first)
  18.              first = mtmp;
  19.          else
  20.              mtmp2->nmon = mtmp;
  21.  
  22.          if (ghostly) {
  23.              unsigned nid = context.ident++;
  24.              add_id_mapping(mtmp->m_id, nid);
  25.              mtmp->m_id = nid;
  26.          }
  27.          offset = mtmp->mnum;
  28.          mtmp->data = &mons[offset];
  29.          if (ghostly) {
  30.              int mndx = monsndx(mtmp->data);
  31.              if (propagate(mndx, TRUE, ghostly) == 0) {
  32.                  /* cookie to trigger purge in getbones() */
  33.                  mtmp->mhpmax = DEFUNCT_MONSTER;
  34.              }
  35.          }
  36.          if (mtmp->minvent) {
  37.              struct obj *obj;
  38.              mtmp->minvent = restobjchn(fd, ghostly, FALSE);
  39.              /* restore monster back pointer */
  40.              for (obj = mtmp->minvent; obj; obj = obj->nobj)
  41.                  obj->ocarry = mtmp;
  42.          }
  43.          if (mtmp->mw) {
  44.              struct obj *obj;
  45.  
  46.              for (obj = mtmp->minvent; obj; obj = obj->nobj)
  47.                  if (obj->owornmask & W_WEP)
  48.                      break;
  49.              if (obj)
  50.                  mtmp->mw = obj;
  51.              else {
  52.                  MON_NOWEP(mtmp);
  53.                  impossible("bad monster weapon restore");
  54.              }
  55.          }
  56.  
  57.          if (mtmp->isshk)
  58.              restshk(mtmp, ghostly);
  59.          if (mtmp->ispriest)
  60.              restpriest(mtmp, ghostly);
  61.  
  62.          if (!ghostly) {
  63.              if (mtmp->m_id == context.polearm.m_id)
  64.                  context.polearm.hitmon = mtmp;
  65.          }
  66.          mtmp2 = mtmp;
  67.      }
  68.      if (first && mtmp2->nmon) {
  69.          impossible("Restmonchn: error reading monchn.");
  70.          mtmp2->nmon = 0;
  71.      }
  72.      return first;
  73.  }
  74.  

loadfruitchn

  1.  STATIC_OVL struct fruit *
  2.  loadfruitchn(fd)
  3.  int fd;
  4.  {
  5.      register struct fruit *flist, *fnext;
  6.  
  7.      flist = 0;
  8.      while (fnext = newfruit(), mread(fd, (genericptr_t) fnext, sizeof *fnext),
  9.             fnext->fid != 0) {
  10.          fnext->nextf = flist;
  11.          flist = fnext;
  12.      }
  13.      dealloc_fruit(fnext);
  14.      return flist;
  15.  }
  16.  

freefruitchn

  1.  STATIC_OVL void
  2.  freefruitchn(flist)
  3.  register struct fruit *flist;
  4.  {
  5.      register struct fruit *fnext;
  6.  
  7.      while (flist) {
  8.          fnext = flist->nextf;
  9.          dealloc_fruit(flist);
  10.          flist = fnext;
  11.      }
  12.  }
  13.  

ghostfruit

  1.  STATIC_OVL void
  2.  ghostfruit(otmp)
  3.  register struct obj *otmp;
  4.  {
  5.      register struct fruit *oldf;
  6.  
  7.      for (oldf = oldfruit; oldf; oldf = oldf->nextf)
  8.          if (oldf->fid == otmp->spe)
  9.              break;
  10.  
  11.      if (!oldf)
  12.          impossible("no old fruit?");
  13.      else
  14.          otmp->spe = fruitadd(oldf->fname, (struct fruit *) 0);
  15.  }
  16.  

restgamestate

  1.  #ifdef SYSCF
  2.  #define SYSOPT_CHECK_SAVE_UID sysopt.check_save_uid
  3.  #else
  4.  #define SYSOPT_CHECK_SAVE_UID TRUE
  5.  #endif
  6.  
  7.  STATIC_OVL
  8.  boolean
  9.  restgamestate(fd, stuckid, steedid)
  10.  register int fd;
  11.  unsigned int *stuckid, *steedid;
  12.  {
  13.      struct flag newgameflags;
  14.  #ifdef SYSFLAGS
  15.      struct sysflag newgamesysflags;
  16.  #endif
  17.      struct obj *otmp, *tmp_bc;
  18.      char timebuf[15];
  19.      unsigned long uid;
  20.  
  21.      mread(fd, (genericptr_t) &uid, sizeof uid);
  22.      if (SYSOPT_CHECK_SAVE_UID
  23.          && uid != (unsigned long) getuid()) { /* strange ... */
  24.          /* for wizard mode, issue a reminder; for others, treat it
  25.             as an attempt to cheat and refuse to restore this file */
  26.          pline("Saved game was not yours.");
  27.          if (!wizard)
  28.              return FALSE;
  29.      }
  30.      mread(fd, (genericptr_t) &context, sizeof(struct context_info));
  31.      if (context.warntype.speciesidx)
  32.          context.warntype.species = &mons[context.warntype.speciesidx];
  33.  
  34.      /* we want to be able to revert to command line/environment/config
  35.         file option values instead of keeping old save file option values
  36.         if partial restore fails and we resort to starting a new game */
  37.      newgameflags = flags;
  38.      mread(fd, (genericptr_t) &flags, sizeof(struct flag));
  39.      /* wizard and discover are actually flags.debug and flags.explore;
  40.         player might be overriding the save file values for them;
  41.         in the discover case, we don't want to set that for a normal
  42.         game until after the save file has been removed */
  43.      iflags.deferred_X = (newgameflags.explore && !discover);
  44.      if (newgameflags.debug) {
  45.          /* authorized by startup code; wizard mode exists and is allowed */
  46.          wizard = TRUE, discover = iflags.deferred_X = FALSE;
  47.      } else if (wizard) {
  48.          /* specified by save file; check authorization now */
  49.          set_playmode();
  50.      }
  51.  #ifdef SYSFLAGS
  52.      newgamesysflags = sysflags;
  53.      mread(fd, (genericptr_t) &sysflags, sizeof(struct sysflag));
  54.  #endif
  55.  
  56.      role_init(); /* Reset the initial role, race, gender, and alignment */
  57.  #ifdef AMII_GRAPHICS
  58.      amii_setpens(amii_numcolors); /* use colors from save file */
  59.  #endif
  60.      mread(fd, (genericptr_t) &u, sizeof(struct you));
  61.  
  62.  #define ReadTimebuf(foo)                   \
  63.      mread(fd, (genericptr_t) timebuf, 14); \
  64.      timebuf[14] = '\0';                    \
  65.      foo = time_from_yyyymmddhhmmss(timebuf);
  66.  
  67.      ReadTimebuf(ubirthday);
  68.      mread(fd, &urealtime.realtime, sizeof(urealtime.realtime));
  69.      ReadTimebuf(urealtime.restored);
  70.  #if defined(BSD) && !defined(POSIX_TYPES)
  71.      (void) time((long *) &urealtime.restored);
  72.  #else
  73.      (void) time(&urealtime.restored);
  74.  #endif
  75.  
  76.      set_uasmon();
  77.  #ifdef CLIPPING
  78.      cliparound(u.ux, u.uy);
  79.  #endif
  80.      if (u.uhp <= 0 && (!Upolyd || u.mh <= 0)) {
  81.          u.ux = u.uy = 0; /* affects pline() [hence You()] */
  82.          You("were not healthy enough to survive restoration.");
  83.          /* wiz1_level.dlevel is used by mklev.c to see if lots of stuff is
  84.           * uninitialized, so we only have to set it and not the other stuff.
  85.           */
  86.          wiz1_level.dlevel = 0;
  87.          u.uz.dnum = 0;
  88.          u.uz.dlevel = 1;
  89.          /* revert to pre-restore option settings */
  90.          iflags.deferred_X = FALSE;
  91.          flags = newgameflags;
  92.  #ifdef SYSFLAGS
  93.          sysflags = newgamesysflags;
  94.  #endif
  95.          return FALSE;
  96.      }
  97.      /* in case hangup save occurred in midst of level change */
  98.      assign_level(&u.uz0, &u.uz);
  99.  
  100.      /* this stuff comes after potential aborted restore attempts */
  101.      restore_killers(fd);
  102.      restore_timers(fd, RANGE_GLOBAL, FALSE, 0L);
  103.      restore_light_sources(fd);
  104.      invent = restobjchn(fd, FALSE, FALSE);
  105.      /* tmp_bc only gets set here if the ball & chain were orphaned
  106.         because you were swallowed; otherwise they will be on the floor
  107.         or in your inventory */
  108.      tmp_bc = restobjchn(fd, FALSE, FALSE);
  109.      if (tmp_bc) {
  110.          for (otmp = tmp_bc; otmp; otmp = otmp->nobj) {
  111.              if (otmp->owornmask)
  112.                  setworn(otmp, otmp->owornmask);
  113.          }
  114.          if (!uball || !uchain)
  115.              impossible("restgamestate: lost ball & chain");
  116.      }
  117.  
  118.      migrating_objs = restobjchn(fd, FALSE, FALSE);
  119.      migrating_mons = restmonchn(fd, FALSE);
  120.      mread(fd, (genericptr_t) mvitals, sizeof(mvitals));
  121.  
  122.      /*
  123.       * There are some things after this that can have unintended display
  124.       * side-effects too early in the game.
  125.       * Disable see_monsters() here, re-enable it at the top of moveloop()
  126.       */
  127.      defer_see_monsters = TRUE;
  128.  
  129.      /* this comes after inventory has been loaded */
  130.      for (otmp = invent; otmp; otmp = otmp->nobj)
  131.          if (otmp->owornmask)
  132.              setworn(otmp, otmp->owornmask);
  133.      /* reset weapon so that player will get a reminder about "bashing"
  134.         during next fight when bare-handed or wielding an unconventional
  135.         item; for pick-axe, we aren't able to distinguish between having
  136.         applied or wielded it, so be conservative and assume the former */
  137.      otmp = uwep;   /* `uwep' usually init'd by setworn() in loop above */
  138.      uwep = 0;      /* clear it and have setuwep() reinit */
  139.      setuwep(otmp); /* (don't need any null check here) */
  140.      if (!uwep || uwep->otyp == PICK_AXE || uwep->otyp == GRAPPLING_HOOK)
  141.          unweapon = TRUE;
  142.  
  143.      restore_dungeon(fd);
  144.      restlevchn(fd);
  145.      mread(fd, (genericptr_t) &moves, sizeof moves);
  146.      mread(fd, (genericptr_t) &monstermoves, sizeof monstermoves);
  147.      mread(fd, (genericptr_t) &quest_status, sizeof(struct q_score));
  148.      mread(fd, (genericptr_t) spl_book, sizeof(struct spell) * (MAXSPELL + 1));
  149.      restore_artifacts(fd);
  150.      restore_oracles(fd);
  151.      if (u.ustuck)
  152.          mread(fd, (genericptr_t) stuckid, sizeof(*stuckid));
  153.      if (u.usteed)
  154.          mread(fd, (genericptr_t) steedid, sizeof(*steedid));
  155.      mread(fd, (genericptr_t) pl_character, sizeof pl_character);
  156.  
  157.      mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit);
  158.      freefruitchn(ffruit); /* clean up fruit(s) made by initoptions() */
  159.      ffruit = loadfruitchn(fd);
  160.  
  161.      restnames(fd);
  162.      restore_waterlevel(fd);
  163.      restore_msghistory(fd);
  164.      /* must come after all mons & objs are restored */
  165.      relink_timers(FALSE);
  166.      relink_light_sources(FALSE);
  167.      return TRUE;
  168.  }
  169.  

restlevelstate

  1.  /* update game state pointers to those valid for the current level (so we
  2.   * don't dereference a wild u.ustuck when saving the game state, for instance)
  3.   */
  4.  STATIC_OVL void
  5.  restlevelstate(stuckid, steedid)
  6.  unsigned int stuckid, steedid;
  7.  {
  8.      register struct monst *mtmp;
  9.  
  10.      if (stuckid) {
  11.          for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  12.              if (mtmp->m_id == stuckid)
  13.                  break;
  14.          if (!mtmp)
  15.              panic("Cannot find the monster ustuck.");
  16.          u.ustuck = mtmp;
  17.      }
  18.      if (steedid) {
  19.          for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  20.              if (mtmp->m_id == steedid)
  21.                  break;
  22.          if (!mtmp)
  23.              panic("Cannot find the monster usteed.");
  24.          u.usteed = mtmp;
  25.          remove_monster(mtmp->mx, mtmp->my);
  26.      }
  27.  }
  28.  

restlevelfile

  1.  /*ARGSUSED*/
  2.  STATIC_OVL int
  3.  restlevelfile(fd, ltmp)
  4.  int fd; /* fd used in MFLOPPY only */
  5.  xchar ltmp;
  6.  {
  7.      int nfd;
  8.      char whynot[BUFSZ];
  9.  
  10.  #ifndef MFLOPPY
  11.      nhUse(fd);
  12.  #endif
  13.      nfd = create_levelfile(ltmp, whynot);
  14.      if (nfd < 0) {
  15.          /* BUG: should suppress any attempt to write a panic
  16.             save file if file creation is now failing... */
  17.          panic("restlevelfile: %s", whynot);
  18.      }
  19.  #ifdef MFLOPPY
  20.      if (!savelev(nfd, ltmp, COUNT_SAVE)) {
  21.          /* The savelev can't proceed because the size required
  22.           * is greater than the available disk space.
  23.           */
  24.          pline("Not enough space on `%s' to restore your game.", levels);
  25.  
  26.          /* Remove levels and bones that may have been created.
  27.           */
  28.          (void) nhclose(nfd);
  29.  #ifdef AMIGA
  30.          clearlocks();
  31.  #else /* !AMIGA */
  32.          eraseall(levels, alllevels);
  33.          eraseall(levels, allbones);
  34.  
  35.          /* Perhaps the person would like to play without a
  36.           * RAMdisk.
  37.           */
  38.          if (ramdisk) {
  39.              /* PlaywoRAMdisk may not return, but if it does
  40.               * it is certain that ramdisk will be 0.
  41.               */
  42.              playwoRAMdisk();
  43.              /* Rewind save file and try again */
  44.              (void) lseek(fd, (off_t) 0, 0);
  45.              (void) validate(fd, (char *) 0); /* skip version etc */
  46.              return dorecover(fd);            /* 0 or 1 */
  47.          }
  48.  #endif /* ?AMIGA */
  49.          pline("Be seeing you...");
  50.          terminate(EXIT_SUCCESS);
  51.      }
  52.  #endif /* MFLOPPY */
  53.      bufon(nfd);
  54.      savelev(nfd, ltmp, WRITE_SAVE | FREE_SAVE);
  55.      bclose(nfd);
  56.      return 2;
  57.  }
  58.  

dorecover

  1.  int
  2.  dorecover(fd)
  3.  register int fd;
  4.  {
  5.      unsigned int stuckid = 0, steedid = 0; /* not a register */
  6.      xchar ltmp;
  7.      int rtmp;
  8.      struct obj *otmp;
  9.  
  10.      restoring = TRUE;
  11.      get_plname_from_file(fd, plname);
  12.      getlev(fd, 0, (xchar) 0, FALSE);
  13.      if (!restgamestate(fd, &stuckid, &steedid)) {
  14.          display_nhwindow(WIN_MESSAGE, TRUE);
  15.          savelev(-1, 0, FREE_SAVE); /* discard current level */
  16.          (void) nhclose(fd);
  17.          (void) delete_savefile();
  18.          restoring = FALSE;
  19.          return 0;
  20.      }
  21.      restlevelstate(stuckid, steedid);
  22.  #ifdef INSURANCE
  23.      savestateinlock();
  24.  #endif
  25.      rtmp = restlevelfile(fd, ledger_no(&u.uz));
  26.      if (rtmp < 2)
  27.          return rtmp; /* dorecover called recursively */
  28.  
  29.      /* these pointers won't be valid while we're processing the
  30.       * other levels, but they'll be reset again by restlevelstate()
  31.       * afterwards, and in the meantime at least u.usteed may mislead
  32.       * place_monster() on other levels
  33.       */
  34.      u.ustuck = (struct monst *) 0;
  35.      u.usteed = (struct monst *) 0;
  36.  
  37.  #ifdef MICRO
  38.  #ifdef AMII_GRAPHICS
  39.      {
  40.          extern struct window_procs amii_procs;
  41.          if (windowprocs.win_init_nhwindows == amii_procs.win_init_nhwindows) {
  42.              extern winid WIN_BASE;
  43.              clear_nhwindow(WIN_BASE); /* hack until there's a hook for this */
  44.          }
  45.      }
  46.  #else
  47.          clear_nhwindow(WIN_MAP);
  48.  #endif
  49.      clear_nhwindow(WIN_MESSAGE);
  50.      You("return to level %d in %s%s.", depth(&u.uz),
  51.          dungeons[u.uz.dnum].dname,
  52.          flags.debug ? " while in debug mode"
  53.                      : flags.explore ? " while in explore mode" : "");
  54.      curs(WIN_MAP, 1, 1);
  55.      dotcnt = 0;
  56.      dotrow = 2;
  57.      if (strncmpi("X11", windowprocs.name, 3))
  58.          putstr(WIN_MAP, 0, "Restoring:");
  59.  #endif
  60.      restoreprocs.mread_flags = 1; /* return despite error */
  61.      while (1) {
  62.          mread(fd, (genericptr_t) &ltmp, sizeof ltmp);
  63.          if (restoreprocs.mread_flags == -1)
  64.              break;
  65.          getlev(fd, 0, ltmp, FALSE);
  66.  #ifdef MICRO
  67.          curs(WIN_MAP, 1 + dotcnt++, dotrow);
  68.          if (dotcnt >= (COLNO - 1)) {
  69.              dotrow++;
  70.              dotcnt = 0;
  71.          }
  72.          if (strncmpi("X11", windowprocs.name, 3)) {
  73.              putstr(WIN_MAP, 0, ".");
  74.          }
  75.          mark_synch();
  76.  #endif
  77.          rtmp = restlevelfile(fd, ltmp);
  78.          if (rtmp < 2)
  79.              return rtmp; /* dorecover called recursively */
  80.      }
  81.      restoreprocs.mread_flags = 0;
  82.  
  83.  #ifdef BSD
  84.      (void) lseek(fd, 0L, 0);
  85.  #else
  86.      (void) lseek(fd, (off_t) 0, 0);
  87.  #endif
  88.      (void) validate(fd, (char *) 0); /* skip version and savefile info */
  89.      get_plname_from_file(fd, plname);
  90.  
  91.      getlev(fd, 0, (xchar) 0, FALSE);
  92.      (void) nhclose(fd);
  93.  
  94.      /* Now set the restore settings to match the
  95.       * settings used by the save file output routines
  96.       */
  97.      reset_restpref();
  98.  
  99.      restlevelstate(stuckid, steedid);
  100.      program_state.something_worth_saving = 1; /* useful data now exists */
  101.  
  102.      if (!wizard && !discover)
  103.          (void) delete_savefile();
  104.      if (Is_rogue_level(&u.uz))
  105.          assign_graphics(ROGUESET);
  106.  #ifdef USE_TILES
  107.      substitute_tiles(&u.uz);
  108.  #endif
  109.  #ifdef MFLOPPY
  110.      gameDiskPrompt();
  111.  #endif
  112.      max_rank_sz(); /* to recompute mrank_sz (botl.c) */
  113.      /* take care of iron ball & chain */
  114.      for (otmp = fobj; otmp; otmp = otmp->nobj)
  115.          if (otmp->owornmask)
  116.              setworn(otmp, otmp->owornmask);
  117.  
  118.      /* in_use processing must be after:
  119.       *    + The inventory has been read so that freeinv() works.
  120.       *    + The current level has been restored so billing information
  121.       *      is available.
  122.       */
  123.      inven_inuse(FALSE);
  124.  
  125.      load_qtlist(); /* re-load the quest text info */
  126.      /* Set up the vision internals, after levl[] data is loaded
  127.         but before docrt(). */
  128.      reglyph_darkroom();
  129.      vision_reset();
  130.      vision_full_recalc = 1; /* recompute vision (not saved) */
  131.  
  132.      run_timers(); /* expire all timers that have gone off while away */
  133.      docrt();
  134.      restoring = FALSE;
  135.      clear_nhwindow(WIN_MESSAGE);
  136.  
  137.      /* Success! */
  138.      welcome(FALSE);
  139.      check_special_room(FALSE);
  140.      return 1;
  141.  }
  142.  

restcemetery

  1.  void
  2.  restcemetery(fd, cemeteryaddr)
  3.  int fd;
  4.  struct cemetery **cemeteryaddr;
  5.  {
  6.      struct cemetery *bonesinfo, **bonesaddr;
  7.      int flag;
  8.  
  9.      mread(fd, (genericptr_t) &flag, sizeof flag);
  10.      if (flag == 0) {
  11.          bonesaddr = cemeteryaddr;
  12.          do {
  13.              bonesinfo = (struct cemetery *) alloc(sizeof *bonesinfo);
  14.              mread(fd, (genericptr_t) bonesinfo, sizeof *bonesinfo);
  15.              *bonesaddr = bonesinfo;
  16.              bonesaddr = &(*bonesaddr)->next;
  17.          } while (*bonesaddr);
  18.      } else {
  19.          *cemeteryaddr = 0;
  20.      }
  21.  }
  22.  

rest_levl

  1.  /*ARGSUSED*/
  2.  STATIC_OVL void
  3.  rest_levl(fd, rlecomp)
  4.  int fd;
  5.  boolean rlecomp;
  6.  {
  7.  #ifdef RLECOMP
  8.      short i, j;
  9.      uchar len;
  10.      struct rm r;
  11.  
  12.      if (rlecomp) {
  13.          (void) memset((genericptr_t) &r, 0, sizeof(r));
  14.          i = 0;
  15.          j = 0;
  16.          len = 0;
  17.          while (i < ROWNO) {
  18.              while (j < COLNO) {
  19.                  if (len > 0) {
  20.                      levl[j][i] = r;
  21.                      len -= 1;
  22.                      j += 1;
  23.                  } else {
  24.                      mread(fd, (genericptr_t) &len, sizeof(uchar));
  25.                      mread(fd, (genericptr_t) &r, sizeof(struct rm));
  26.                  }
  27.              }
  28.              j = 0;
  29.              i += 1;
  30.          }
  31.          return;
  32.      }
  33.  #else /* !RLECOMP */
  34.      nhUse(rlecomp);
  35.  #endif /* ?RLECOMP */
  36.      mread(fd, (genericptr_t) levl, sizeof levl);
  37.  }
  38.  

trickery

  1.  void
  2.  trickery(reason)
  3.  char *reason;
  4.  {
  5.      pline("Strange, this map is not as I remember it.");
  6.      pline("Somebody is trying some trickery here...");
  7.      pline("This game is void.");
  8.      Strcpy(killer.name, reason ? reason : "");
  9.      done(TRICKED);
  10.  }
  11.  

getlev

  1.  void
  2.  getlev(fd, pid, lev, ghostly)
  3.  int fd, pid;
  4.  xchar lev;
  5.  boolean ghostly;
  6.  {
  7.      register struct trap *trap;
  8.      register struct monst *mtmp;
  9.      long elapsed;
  10.      branch *br;
  11.      int hpid;
  12.      xchar dlvl;
  13.      int x, y;
  14.  #ifdef TOS
  15.      short tlev;
  16.  #endif
  17.  
  18.      if (ghostly)
  19.          clear_id_mapping();
  20.  
  21.  #if defined(MSDOS) || defined(OS2)
  22.      setmode(fd, O_BINARY);
  23.  #endif
  24.      /* Load the old fruit info.  We have to do it first, so the
  25.       * information is available when restoring the objects.
  26.       */
  27.      if (ghostly)
  28.          oldfruit = loadfruitchn(fd);
  29.  
  30.      /* First some sanity checks */
  31.      mread(fd, (genericptr_t) &hpid, sizeof(hpid));
  32.  /* CHECK:  This may prevent restoration */
  33.  #ifdef TOS
  34.      mread(fd, (genericptr_t) &tlev, sizeof(tlev));
  35.      dlvl = tlev & 0x00ff;
  36.  #else
  37.      mread(fd, (genericptr_t) &dlvl, sizeof(dlvl));
  38.  #endif
  39.      if ((pid && pid != hpid) || (lev && dlvl != lev)) {
  40.          char trickbuf[BUFSZ];
  41.  
  42.          if (pid && pid != hpid)
  43.              Sprintf(trickbuf, "PID (%d) doesn't match saved PID (%d)!", hpid,
  44.                      pid);
  45.          else
  46.              Sprintf(trickbuf, "This is level %d, not %d!", dlvl, lev);
  47.          if (wizard)
  48.              pline1(trickbuf);
  49.          trickery(trickbuf);
  50.      }
  51.      restcemetery(fd, &level.bonesinfo);
  52.      rest_levl(fd,
  53.                (boolean) ((sfrestinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP));
  54.      mread(fd, (genericptr_t) lastseentyp, sizeof(lastseentyp));
  55.      mread(fd, (genericptr_t) &omoves, sizeof(omoves));
  56.      elapsed = monstermoves - omoves;
  57.      mread(fd, (genericptr_t) &upstair, sizeof(stairway));
  58.      mread(fd, (genericptr_t) &dnstair, sizeof(stairway));
  59.      mread(fd, (genericptr_t) &upladder, sizeof(stairway));
  60.      mread(fd, (genericptr_t) &dnladder, sizeof(stairway));
  61.      mread(fd, (genericptr_t) &sstairs, sizeof(stairway));
  62.      mread(fd, (genericptr_t) &updest, sizeof(dest_area));
  63.      mread(fd, (genericptr_t) &dndest, sizeof(dest_area));
  64.      mread(fd, (genericptr_t) &level.flags, sizeof(level.flags));
  65.      mread(fd, (genericptr_t) doors, sizeof(doors));
  66.      rest_rooms(fd); /* No joke :-) */
  67.      if (nroom)
  68.          doorindex = rooms[nroom - 1].fdoor + rooms[nroom - 1].doorct;
  69.      else
  70.          doorindex = 0;
  71.  
  72.      restore_timers(fd, RANGE_LEVEL, ghostly, elapsed);
  73.      restore_light_sources(fd);
  74.      fmon = restmonchn(fd, ghostly);
  75.  
  76.      rest_worm(fd); /* restore worm information */
  77.      ftrap = 0;
  78.      while (trap = newtrap(),
  79.             mread(fd, (genericptr_t) trap, sizeof(struct trap)),
  80.             trap->tx != 0) { /* need "!= 0" to work around DICE 3.0 bug */
  81.          trap->ntrap = ftrap;
  82.          ftrap = trap;
  83.      }
  84.      dealloc_trap(trap);
  85.      fobj = restobjchn(fd, ghostly, FALSE);
  86.      find_lev_obj();
  87.      /* restobjchn()'s `frozen' argument probably ought to be a callback
  88.         routine so that we can check for objects being buried under ice */
  89.      level.buriedobjlist = restobjchn(fd, ghostly, FALSE);
  90.      billobjs = restobjchn(fd, ghostly, FALSE);
  91.      rest_engravings(fd);
  92.  
  93.      /* reset level.monsters for new level */
  94.      for (x = 0; x < COLNO; x++)
  95.          for (y = 0; y < ROWNO; y++)
  96.              level.monsters[x][y] = (struct monst *) 0;
  97.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  98.          if (mtmp->isshk)
  99.              set_residency(mtmp, FALSE);
  100.          place_monster(mtmp, mtmp->mx, mtmp->my);
  101.          if (mtmp->wormno)
  102.              place_wsegs(mtmp);
  103.  
  104.          /* regenerate monsters while on another level */
  105.          if (!u.uz.dlevel)
  106.              continue;
  107.          if (ghostly) {
  108.              /* reset peaceful/malign relative to new character;
  109.                 shopkeepers will reset based on name */
  110.              if (!mtmp->isshk)
  111.                  mtmp->mpeaceful =
  112.                      (is_unicorn(mtmp->data)
  113.                       && sgn(u.ualign.type) == sgn(mtmp->data->maligntyp))
  114.                          ? TRUE
  115.                          : peace_minded(mtmp->data);
  116.              set_malign(mtmp);
  117.          } else if (elapsed > 0L) {
  118.              mon_catchup_elapsed_time(mtmp, elapsed);
  119.          }
  120.          /* update shape-changers in case protection against
  121.             them is different now than when the level was saved */
  122.          restore_cham(mtmp);
  123.          /* give hiders a chance to hide before their next move */
  124.          if (ghostly || elapsed > (long) rnd(10))
  125.              hide_monst(mtmp);
  126.      }
  127.  
  128.      restdamage(fd, ghostly);
  129.      rest_regions(fd, ghostly);
  130.      if (ghostly) {
  131.          /* Now get rid of all the temp fruits... */
  132.          freefruitchn(oldfruit), oldfruit = 0;
  133.  
  134.          if (lev > ledger_no(&medusa_level)
  135.              && lev < ledger_no(&stronghold_level) && xdnstair == 0) {
  136.              coord cc;
  137.  
  138.              mazexy(&cc);
  139.              xdnstair = cc.x;
  140.              ydnstair = cc.y;
  141.              levl[cc.x][cc.y].typ = STAIRS;
  142.          }
  143.  
  144.          br = Is_branchlev(&u.uz);
  145.          if (br && u.uz.dlevel == 1) {
  146.              d_level ltmp;
  147.  
  148.              if (on_level(&u.uz, &br->end1))
  149.                  assign_level(&ltmp, &br->end2);
  150.              else
  151.                  assign_level(&ltmp, &br->end1);
  152.  
  153.              switch (br->type) {
  154.              case BR_STAIR:
  155.              case BR_NO_END1:
  156.              case BR_NO_END2: /* OK to assign to sstairs if it's not used */
  157.                  assign_level(&sstairs.tolev, &ltmp);
  158.                  break;
  159.              case BR_PORTAL: /* max of 1 portal per level */
  160.                  for (trap = ftrap; trap; trap = trap->ntrap)
  161.                      if (trap->ttyp == MAGIC_PORTAL)
  162.                          break;
  163.                  if (!trap)
  164.                      panic("getlev: need portal but none found");
  165.                  assign_level(&trap->dst, &ltmp);
  166.                  break;
  167.              }
  168.          } else if (!br) {
  169.              struct trap *ttmp = 0;
  170.  
  171.              /* Remove any dangling portals. */
  172.              for (trap = ftrap; trap; trap = ttmp) {
  173.                  ttmp = trap->ntrap;
  174.                  if (trap->ttyp == MAGIC_PORTAL)
  175.                      deltrap(trap);
  176.              }
  177.          }
  178.      }
  179.  
  180.      /* must come after all mons & objs are restored */
  181.      relink_timers(ghostly);
  182.      relink_light_sources(ghostly);
  183.      reset_oattached_mids(ghostly);
  184.  
  185.      if (ghostly)
  186.          clear_id_mapping();
  187.  }
  188.  

get_plname_from_file

  1.  void
  2.  get_plname_from_file(fd, plbuf)
  3.  int fd;
  4.  char *plbuf;
  5.  {
  6.      int pltmpsiz = 0;
  7.      (void) read(fd, (genericptr_t) &pltmpsiz, sizeof(pltmpsiz));
  8.      (void) read(fd, (genericptr_t) plbuf, pltmpsiz);
  9.      return;
  10.  }
  11.  

restore_msghistory

  1.  STATIC_OVL void
  2.  restore_msghistory(fd)
  3.  register int fd;
  4.  {
  5.      int msgsize, msgcount = 0;
  6.      char msg[BUFSZ];
  7.  
  8.      while (1) {
  9.          mread(fd, (genericptr_t) &msgsize, sizeof(msgsize));
  10.          if (msgsize == -1)
  11.              break;
  12.          if (msgsize > (BUFSZ - 1))
  13.              panic("restore_msghistory: msg too big (%d)", msgsize);
  14.          mread(fd, (genericptr_t) msg, msgsize);
  15.          msg[msgsize] = '\0';
  16.          putmsghistory(msg, TRUE);
  17.          ++msgcount;
  18.      }
  19.      if (msgcount)
  20.          putmsghistory((char *) 0, TRUE);
  21.      debugpline1("Read %d messages from savefile.", msgcount);
  22.  }
  23.  

clear_id_mapping

  1.  /* Clear all structures for object and monster ID mapping. */
  2.  STATIC_OVL void
  3.  clear_id_mapping()
  4.  {
  5.      struct bucket *curr;
  6.  
  7.      while ((curr = id_map) != 0) {
  8.          id_map = curr->next;
  9.          free((genericptr_t) curr);
  10.      }
  11.      n_ids_mapped = 0;
  12.  }
  13.  

add_id_mapping

  1.  /* Add a mapping to the ID map. */
  2.  STATIC_OVL void
  3.  add_id_mapping(gid, nid)
  4.  unsigned gid, nid;
  5.  {
  6.      int idx;
  7.  
  8.      idx = n_ids_mapped % N_PER_BUCKET;
  9.      /* idx is zero on first time through, as well as when a new bucket is */
  10.      /* needed */
  11.      if (idx == 0) {
  12.          struct bucket *gnu = (struct bucket *) alloc(sizeof(struct bucket));
  13.          gnu->next = id_map;
  14.          id_map = gnu;
  15.      }
  16.  
  17.      id_map->map[idx].gid = gid;
  18.      id_map->map[idx].nid = nid;
  19.      n_ids_mapped++;
  20.  }
  21.  

lookup_id_mapping

  1.  /*
  2.   * Global routine to look up a mapping.  If found, return TRUE and fill
  3.   * in the new ID value.  Otherwise, return false and return -1 in the new
  4.   * ID.
  5.   */
  6.  boolean
  7.  lookup_id_mapping(gid, nidp)
  8.  unsigned gid, *nidp;
  9.  {
  10.      int i;
  11.      struct bucket *curr;
  12.  
  13.      if (n_ids_mapped)
  14.          for (curr = id_map; curr; curr = curr->next) {
  15.              /* first bucket might not be totally full */
  16.              if (curr == id_map) {
  17.                  i = n_ids_mapped % N_PER_BUCKET;
  18.                  if (i == 0)
  19.                      i = N_PER_BUCKET;
  20.              } else
  21.                  i = N_PER_BUCKET;
  22.  
  23.              while (--i >= 0)
  24.                  if (gid == curr->map[i].gid) {
  25.                      *nidp = curr->map[i].nid;
  26.                      return TRUE;
  27.                  }
  28.          }
  29.  
  30.      return FALSE;
  31.  }
  32.  

reset_oattached_mids

  1.  STATIC_OVL void
  2.  reset_oattached_mids(ghostly)
  3.  boolean ghostly;
  4.  {
  5.      struct obj *otmp;
  6.      unsigned oldid, nid;
  7.      for (otmp = fobj; otmp; otmp = otmp->nobj) {
  8.          if (ghostly && has_omonst(otmp)) {
  9.              struct monst *mtmp = OMONST(otmp);
  10.  
  11.              mtmp->m_id = 0;
  12.              mtmp->mpeaceful = mtmp->mtame = 0; /* pet's owner died! */
  13.          }
  14.          if (ghostly && has_omid(otmp)) {
  15.              (void) memcpy((genericptr_t) &oldid, (genericptr_t) OMID(otmp),
  16.                            sizeof(oldid));
  17.              if (lookup_id_mapping(oldid, &nid))
  18.                  (void) memcpy((genericptr_t) OMID(otmp), (genericptr_t) &nid,
  19.                                sizeof(nid));
  20.              else
  21.                  free_omid(otmp);
  22.          }
  23.      }
  24.  }
  25.  

restore_menu

  1.  #ifdef SELECTSAVED
  2.  /* put up a menu listing each character from this player's saved games;
  3.     returns 1: use plname[], 0: new game, -1: quit */
  4.  int
  5.  restore_menu(bannerwin)
  6.  winid bannerwin; /* if not WIN_ERR, clear window and show copyright in menu */
  7.  {
  8.      winid tmpwin;
  9.      anything any;
  10.      char **saved;
  11.      menu_item *chosen_game = (menu_item *) 0;
  12.      int k, clet, ch = 0; /* ch: 0 => new game */
  13.  
  14.      *plname = '\0';
  15.      saved = get_saved_games(); /* array of character names */
  16.      if (saved && *saved) {
  17.          tmpwin = create_nhwindow(NHW_MENU);
  18.          start_menu(tmpwin);
  19.          any = zeroany; /* no selection */
  20.          if (bannerwin != WIN_ERR) {
  21.              /* for tty; erase copyright notice and redo it in the menu */
  22.              clear_nhwindow(bannerwin);
  23.              /* COPYRIGHT_BANNER_[ABCD] */
  24.              for (k = 1; k <= 4; ++k)
  25.                  add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  26.                           copyright_banner_line(k), MENU_UNSELECTED);
  27.              add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
  28.                       MENU_UNSELECTED);
  29.          }
  30.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  31.                   "Select one of your saved games", MENU_UNSELECTED);
  32.          for (k = 0; saved[k]; ++k) {
  33.              any.a_int = k + 1;
  34.              add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, saved[k],
  35.                       MENU_UNSELECTED);
  36.          }
  37.          clet = (k <= 'n' - 'a') ? 'n' : 0; /* new game */
  38.          any.a_int = -1;                    /* not >= 0 */
  39.          add_menu(tmpwin, NO_GLYPH, &any, clet, 0, ATR_NONE,
  40.                   "Start a new character", MENU_UNSELECTED);
  41.          clet = (k + 1 <= 'q' - 'a') ? 'q' : 0; /* quit */
  42.          any.a_int = -2;
  43.          add_menu(tmpwin, NO_GLYPH, &any, clet, 0, ATR_NONE,
  44.                   "Never mind (quit)", MENU_SELECTED);
  45.          /* no prompt on end_menu, as we've done our own at the top */
  46.          end_menu(tmpwin, (char *) 0);
  47.          if (select_menu(tmpwin, PICK_ONE, &chosen_game) > 0) {
  48.              ch = chosen_game->item.a_int;
  49.              if (ch > 0)
  50.                  Strcpy(plname, saved[ch - 1]);
  51.              else if (ch < 0)
  52.                  ++ch; /* -1 -> 0 (new game), -2 -> -1 (quit) */
  53.              free((genericptr_t) chosen_game);
  54.          } else {
  55.              ch = -1; /* quit menu without making a selection => quit */
  56.          }
  57.          destroy_nhwindow(tmpwin);
  58.          if (bannerwin != WIN_ERR) {
  59.              /* for tty; clear the menu away and put subset of copyright back
  60.               */
  61.              clear_nhwindow(bannerwin);
  62.              /* COPYRIGHT_BANNER_A, preceding "Who are you?" prompt */
  63.              if (ch == 0)
  64.                  putstr(bannerwin, 0, copyright_banner_line(1));
  65.          }
  66.      }
  67.      free_saved_games(saved);
  68.      return (ch > 0) ? 1 : ch;
  69.  }
  70.  #endif /* SELECTSAVED */
  71.  

minit

  1.  void
  2.  minit()
  3.  {
  4.      (*restoreprocs.restore_minit)();
  5.      return;
  6.  }
  7.  

mread

  1.  void
  2.  mread(fd, buf, len)
  3.  register int fd;
  4.  register genericptr_t buf;
  5.  register unsigned int len;
  6.  {
  7.      (*restoreprocs.restore_mread)(fd, buf, len);
  8.      return;
  9.  }
  10.  

validate

  1.  /* examine the version info and the savefile_info data
  2.     that immediately follows it.
  3.     Return 0 if it passed the checks.
  4.     Return 1 if it failed the version check.
  5.     Return 2 if it failed the savefile feature check.
  6.     Return -1 if it failed for some unknown reason.
  7.   */
  8.  int
  9.  validate(fd, name)
  10.  int fd;
  11.  const char *name;
  12.  {
  13.      int rlen;
  14.      struct savefile_info sfi;
  15.      unsigned long compatible;
  16.      boolean verbose = name ? TRUE : FALSE, reslt = FALSE;
  17.  
  18.      if (!(reslt = uptodate(fd, name)))
  19.          return 1;
  20.  
  21.      rlen = read(fd, (genericptr_t) &sfi, sizeof sfi);
  22.      minit(); /* ZEROCOMP */
  23.      if (rlen == 0) {
  24.          if (verbose) {
  25.              pline("File \"%s\" is empty during save file feature check?",
  26.                    name);
  27.              wait_synch();
  28.          }
  29.          return -1;
  30.      }
  31.  
  32.      compatible = (sfi.sfi1 & sfcap.sfi1);
  33.  
  34.      if ((sfi.sfi1 & SFI1_ZEROCOMP) == SFI1_ZEROCOMP) {
  35.          if ((compatible & SFI1_ZEROCOMP) != SFI1_ZEROCOMP) {
  36.              if (verbose) {
  37.                  pline("File \"%s\" has incompatible ZEROCOMP compression.",
  38.                        name);
  39.                  wait_synch();
  40.              }
  41.              return 2;
  42.          } else if ((sfrestinfo.sfi1 & SFI1_ZEROCOMP) != SFI1_ZEROCOMP) {
  43.              set_restpref("zerocomp");
  44.          }
  45.      }
  46.  
  47.      if ((sfi.sfi1 & SFI1_EXTERNALCOMP) == SFI1_EXTERNALCOMP) {
  48.          if ((compatible & SFI1_EXTERNALCOMP) != SFI1_EXTERNALCOMP) {
  49.              if (verbose) {
  50.                  pline("File \"%s\" lacks required internal compression.",
  51.                        name);
  52.                  wait_synch();
  53.              }
  54.              return 2;
  55.          } else if ((sfrestinfo.sfi1 & SFI1_EXTERNALCOMP)
  56.                     != SFI1_EXTERNALCOMP) {
  57.              set_restpref("externalcomp");
  58.          }
  59.      }
  60.  
  61.      /* RLECOMP check must be last, after ZEROCOMP or INTERNALCOMP adjustments
  62.       */
  63.      if ((sfi.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP) {
  64.          if ((compatible & SFI1_RLECOMP) != SFI1_RLECOMP) {
  65.              if (verbose) {
  66.                  pline("File \"%s\" has incompatible run-length compression.",
  67.                        name);
  68.                  wait_synch();
  69.              }
  70.              return 2;
  71.          } else if ((sfrestinfo.sfi1 & SFI1_RLECOMP) != SFI1_RLECOMP) {
  72.              set_restpref("rlecomp");
  73.          }
  74.      }
  75.      /* savefile does not have RLECOMP level location compression, so adjust */
  76.      else
  77.          set_restpref("!rlecomp");
  78.  
  79.      return 0;
  80.  }
  81.  

reset_restpref

  1.  void
  2.  reset_restpref()
  3.  {
  4.  #ifdef ZEROCOMP
  5.      if (iflags.zerocomp)
  6.          set_restpref("zerocomp");
  7.      else
  8.  #endif
  9.          set_restpref("externalcomp");
  10.  #ifdef RLECOMP
  11.      if (iflags.rlecomp)
  12.          set_restpref("rlecomp");
  13.      else
  14.  #endif
  15.          set_restpref("!rlecomp");
  16.  }
  17.  

set_restpref

  1.  void
  2.  set_restpref(suitename)
  3.  const char *suitename;
  4.  {
  5.      if (!strcmpi(suitename, "externalcomp")) {
  6.          restoreprocs.name = "externalcomp";
  7.          restoreprocs.restore_mread = def_mread;
  8.          restoreprocs.restore_minit = def_minit;
  9.          sfrestinfo.sfi1 |= SFI1_EXTERNALCOMP;
  10.          sfrestinfo.sfi1 &= ~SFI1_ZEROCOMP;
  11.          def_minit();
  12.      }
  13.      if (!strcmpi(suitename, "!rlecomp")) {
  14.          sfrestinfo.sfi1 &= ~SFI1_RLECOMP;
  15.      }
  16.  #ifdef ZEROCOMP
  17.      if (!strcmpi(suitename, "zerocomp")) {
  18.          restoreprocs.name = "zerocomp";
  19.          restoreprocs.restore_mread = zerocomp_mread;
  20.          restoreprocs.restore_minit = zerocomp_minit;
  21.          sfrestinfo.sfi1 |= SFI1_ZEROCOMP;
  22.          sfrestinfo.sfi1 &= ~SFI1_EXTERNALCOMP;
  23.          zerocomp_minit();
  24.      }
  25.  #endif
  26.  #ifdef RLECOMP
  27.      if (!strcmpi(suitename, "rlecomp")) {
  28.          sfrestinfo.sfi1 |= SFI1_RLECOMP;
  29.      }
  30.  #endif
  31.  }
  32.  

zerocomp_mgetc

  1.  #ifdef ZEROCOMP
  2.  #define RLESC '\0' /* Leading character for run of RLESC's */
  3.  
  4.  #ifndef ZEROCOMP_BUFSIZ
  5.  #define ZEROCOMP_BUFSIZ BUFSZ
  6.  #endif
  7.  static NEARDATA unsigned char inbuf[ZEROCOMP_BUFSIZ];
  8.  static NEARDATA unsigned short inbufp = 0;
  9.  static NEARDATA unsigned short inbufsz = 0;
  10.  static NEARDATA short inrunlength = -1;
  11.  static NEARDATA int mreadfd;
  12.  
  13.  STATIC_OVL int
  14.  zerocomp_mgetc()
  15.  {
  16.      if (inbufp >= inbufsz) {
  17.          inbufsz = read(mreadfd, (genericptr_t) inbuf, sizeof inbuf);
  18.          if (!inbufsz) {
  19.              if (inbufp > sizeof inbuf)
  20.                  error("EOF on file #%d.\n", mreadfd);
  21.              inbufp = 1 + sizeof inbuf; /* exactly one warning :-) */
  22.              return -1;
  23.          }
  24.          inbufp = 0;
  25.      }
  26.      return inbuf[inbufp++];
  27.  }
  28.  

zerocomp_minit

  1.  STATIC_OVL void
  2.  zerocomp_minit()
  3.  {
  4.      inbufsz = 0;
  5.      inbufp = 0;
  6.      inrunlength = -1;
  7.  }
  8.  

zerocomp_mread

  1.  STATIC_OVL void
  2.  zerocomp_mread(fd, buf, len)
  3.  int fd;
  4.  genericptr_t buf;
  5.  register unsigned len;
  6.  {
  7.      /*register int readlen = 0;*/
  8.      if (fd < 0)
  9.          error("Restore error; mread attempting to read file %d.", fd);
  10.      mreadfd = fd;
  11.      while (len--) {
  12.          if (inrunlength > 0) {
  13.              inrunlength--;
  14.              *(*((char **) &buf))++ = '\0';
  15.          } else {
  16.              register short ch = zerocomp_mgetc();
  17.              if (ch < 0) {
  18.                  restoreprocs.mread_flags = -1;
  19.                  return;
  20.              }
  21.              if ((*(*(char **) &buf)++ = (char) ch) == RLESC) {
  22.                  inrunlength = zerocomp_mgetc();
  23.              }
  24.          }
  25.          /*readlen++;*/
  26.      }
  27.  }
  28.  #endif /* ZEROCOMP */
  29.  

def_minit

  1.  STATIC_OVL void
  2.  def_minit()
  3.  {
  4.      return;
  5.  }
  6.  

def_mread

  1.  STATIC_OVL void
  2.  def_mread(fd, buf, len)
  3.  register int fd;
  4.  register genericptr_t buf;
  5.  register unsigned int len;
  6.  {
  7.      register int rlen;
  8.  #if defined(BSD) || defined(ULTRIX)
  9.  #define readLenType int
  10.  #else /* e.g. SYSV, __TURBOC__ */
  11.  #define readLenType unsigned
  12.  #endif
  13.  
  14.      rlen = read(fd, buf, (readLenType) len);
  15.      if ((readLenType) rlen != (readLenType) len) {
  16.          if (restoreprocs.mread_flags == 1) { /* means "return anyway" */
  17.              restoreprocs.mread_flags = -1;
  18.              return;
  19.          } else {
  20.              pline("Read %d instead of %u bytes.", rlen, len);
  21.              if (restoring) {
  22.                  (void) nhclose(fd);
  23.                  (void) delete_savefile();
  24.                  error("Error restoring old game.");
  25.              }
  26.              panic("Error reading level file.");
  27.          }
  28.      }
  29.  }
  30.  
  31.  /*restore.c*/