home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume3 / nethack2.2 / part13 / save.c < prev    next >
C/C++ Source or Header  |  1987-12-02  |  11KB  |  452 lines

  1. /*    SCCS Id: @(#)save.c    2.1    87/10/07
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  
  4. #include <signal.h>
  5. #include <stdio.h>
  6. #include "hack.h"
  7. extern char genocided[60];        /* defined in Decl.c */
  8. extern char fut_geno[60];        /* idem */
  9. extern struct permonst    pm_wizard;    /* since the wizard evolves */
  10.  
  11. extern char SAVEF[], nul[];
  12. extern char pl_character[PL_CSIZ];
  13. extern long lseek();
  14. extern struct obj *restobjchn();
  15. extern struct monst *restmonchn();
  16.  
  17. dosave(){
  18.     clear_screen();
  19.     fflush(stdout);
  20.     if(dosave0(0)) {
  21.         settty("Be seeing you ...\n");
  22.         exit(0);
  23.     }
  24. #ifdef LINT
  25.     return(0);
  26. #endif
  27. }
  28.  
  29. #ifndef NOSAVEONHANGUP
  30. hangup(){
  31.     (void) dosave0(1);
  32.     exit(1);
  33. }
  34. #endif
  35.  
  36. /* returns 1 if save successful */
  37. dosave0(hu) int hu; {
  38.     register fd, ofd;
  39.     int tmp;        /* not register ! */
  40. #ifdef DGK
  41.     long fds, needed;
  42.     extern long bytes_counted;
  43.     int mode;
  44. #endif
  45. #ifdef UNIX
  46.     (void) signal(SIGHUP, SIG_IGN);
  47. #endif
  48. #ifndef __TURBOC__
  49.     (void) signal(SIGINT, SIG_IGN);
  50. #endif
  51. #ifdef DGK
  52.     if (!saveDiskPrompt(0))
  53.         return 0;
  54.     fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT, FMASK);
  55. #else
  56.     fd = creat(SAVEF, FMASK);
  57. #endif
  58.     if(fd < 0) {
  59.         if(!hu) pline("Cannot open save file. (Continue or Quit)");
  60.         (void) unlink(SAVEF);        /* ab@unido */
  61.         return(0);
  62.     }
  63.     if(flags.moonphase == FULL_MOON)    /* ut-sally!fletcher */
  64.         u.uluck--;            /* and unido!ab */
  65. #ifdef DGKMOD
  66.     home();
  67.     cl_end();
  68. #endif
  69. #ifdef DGK
  70.     msmsg("Saving: ");
  71.     mode = COUNT;
  72. again:
  73.     savelev(fd, dlevel, mode);
  74.     /* count_only will be set properly by savelev */
  75. #else
  76.     savelev(fd,dlevel);
  77. #endif
  78.     saveobjchn(fd, invent);
  79.     saveobjchn(fd, fcobj);
  80.     savemonchn(fd, fallen_down);
  81.     tmp = getuid();
  82.     bwrite(fd, (char *) &tmp, sizeof tmp);
  83.     bwrite(fd, (char *) &flags, sizeof(struct flag));
  84.     bwrite(fd, (char *) &dlevel, sizeof dlevel);
  85.     bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel);
  86.     bwrite(fd, (char *) &moves, sizeof moves);
  87.     bwrite(fd, (char *) &u, sizeof(struct you));
  88. #ifdef SPELLS
  89.     bwrite(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1));
  90. #endif
  91.     if(u.ustuck)
  92.         bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
  93.     bwrite(fd, (char *) pl_character, sizeof pl_character);
  94.     bwrite(fd, (char *) genocided, sizeof genocided);
  95.     bwrite(fd, (char *) fut_geno, sizeof fut_geno);
  96. #ifdef HARD
  97.     bwrite(fd, (char *) &pm_wizard, sizeof(struct permonst));
  98. #endif
  99.     savenames(fd);
  100. #ifdef DGK
  101.     if (mode == COUNT) {
  102.         /* make sure there is enough disk space */
  103.         needed = bytes_counted;
  104.         for (tmp = 1; tmp <= maxdlevel; tmp++)
  105.             if (tmp != dlevel && fileinfo[tmp].where)
  106.                 needed += fileinfo[tmp].size + (sizeof tmp);
  107.         fds = freediskspace(SAVEF);
  108.         if (needed > fds) {
  109.             pline("There is insufficient space on SAVE disk.");
  110.             pline("Require %ld bytes but only have %ld.", needed,
  111.                 fds);
  112.             flushout();
  113.             (void) close(fd);
  114.             (void) unlink(SAVEF);
  115.             return 0;
  116.         }
  117.         mode = WRITE;
  118.         goto again;
  119.     }
  120. #endif
  121.     for(tmp = 1; tmp <= maxdlevel; tmp++) {
  122.         extern int hackpid;
  123. #ifdef DGK
  124.         if (tmp == dlevel || !fileinfo[tmp].where) continue;
  125.         if (fileinfo[tmp].where != ACTIVE)
  126.             swapin_file(tmp);
  127. #else
  128.         extern boolean level_exists[];
  129.  
  130.         if(tmp == dlevel || !level_exists[tmp]) continue;
  131. #endif
  132.         glo(tmp);
  133. #ifdef DGK
  134.         msmsg(".");
  135. #endif
  136.         if((ofd = open(lock, 0)) < 0) {
  137.             if(!hu) pline("Error while saving: cannot read %s.", lock);
  138.             (void) close(fd);
  139.             (void) unlink(SAVEF);
  140.             if(!hu) done("tricked");
  141.             return(0);
  142.         }
  143.         getlev(ofd, hackpid, tmp);
  144.         (void) close(ofd);
  145.         bwrite(fd, (char *) &tmp, sizeof tmp);    /* level number */
  146. #ifdef DGK
  147.         savelev(fd,tmp,WRITE);            /* actual level */
  148. #else
  149.         savelev(fd,tmp);            /* actual level */
  150. #endif
  151.         (void) unlink(lock);
  152.     }
  153.     (void) close(fd);
  154.     glo(dlevel);
  155.     (void) unlink(lock);    /* get rid of current level --jgm */
  156.     glo(0);
  157.     (void) unlink(lock);
  158.     return(1);
  159. }
  160.  
  161. dorecover(fd)
  162. register fd;
  163. {
  164.     register nfd;
  165.     int tmp;        /* not a register ! */
  166.     unsigned mid;        /* idem */
  167.     struct obj *otmp;
  168.     extern boolean restoring;
  169. #ifdef DGK
  170.     struct flag oldflags;
  171.  
  172.     oldflags = flags;    /* Save flags set in the config file */
  173. #endif
  174.     restoring = TRUE;
  175.     getlev(fd, 0, 0);
  176.     invent = restobjchn(fd);
  177.     for(otmp = invent; otmp; otmp = otmp->nobj)
  178.         if(otmp->owornmask)
  179.             setworn(otmp, otmp->owornmask);
  180.     fcobj = restobjchn(fd);
  181.     fallen_down = restmonchn(fd);
  182.     mread(fd, (char *) &tmp, sizeof tmp);
  183. #ifdef WIZARD
  184.     if(!wizard)
  185. #endif
  186.         if(tmp != getuid()) {        /* strange ... */
  187.         (void) close(fd);
  188.         (void) unlink(SAVEF);
  189.         puts("Saved game was not yours.");
  190.         restoring = FALSE;
  191.         return(0);
  192.         }
  193.     mread(fd, (char *) &flags, sizeof(struct flag));
  194. #ifdef DGK
  195.     /* Some config file OPTIONS take precedence over those in save file.
  196.      */
  197.     flags.rawio = oldflags.rawio;
  198.     flags.DECRainbow = oldflags.DECRainbow;
  199.     flags.IBMBIOS = oldflags.IBMBIOS;
  200. #endif
  201.     mread(fd, (char *) &dlevel, sizeof dlevel);
  202.     mread(fd, (char *) &maxdlevel, sizeof maxdlevel);
  203.     mread(fd, (char *) &moves, sizeof moves);
  204.     mread(fd, (char *) &u, sizeof(struct you));
  205. #ifdef SPELLS
  206.     mread(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1));
  207. #endif
  208.     if(u.ustuck)
  209.         mread(fd, (char *) &mid, sizeof mid);
  210.     mread(fd, (char *) pl_character, sizeof pl_character);
  211.     mread(fd, (char *) genocided, sizeof genocided);
  212.     mread(fd, (char *) fut_geno, sizeof fut_geno);
  213. #ifdef HARD
  214.     mread(fd, (char *) &pm_wizard, sizeof(struct permonst));
  215. #endif
  216.     restnames(fd);
  217. #ifdef DGK
  218.     msmsg("\n");
  219.     cl_end();
  220.     msmsg("You got as far as level %d%s.\n", maxdlevel,
  221.         flags.debug ? " in WIZARD mode" : "");
  222.     cl_end();
  223.     msmsg("Restoring: ");
  224. #endif
  225.     while(1) {
  226.         if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp)
  227.             break;
  228.         getlev(fd, 0, tmp);
  229.         glo(tmp);
  230. #ifdef DGK
  231.         msmsg(".");
  232.         nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK);
  233. #else
  234.         nfd = creat(lock, FMASK);
  235. #endif
  236.         if (nfd < 0)    panic("Cannot open temp file %s!\n", lock);
  237. #ifdef DGK
  238.         if (!savelev(nfd, tmp, COUNT | WRITE)) {
  239.  
  240.             /* The savelev can't proceed because the size required
  241.              * is greater than the available disk space.
  242.              */
  243.             msmsg("\nNot enough space on `%s' to restore your game.\n",
  244.                 levels);
  245.  
  246.             /* Remove levels and bones that may have been created.
  247.              */
  248.             (void) close(nfd);
  249.             eraseall(levels, alllevels);
  250.             eraseall(levels, allbones);
  251.  
  252.             /* Perhaps the person would like to play without a
  253.              * RAMdisk.
  254.              */
  255.             if (ramdisk) {
  256.                 /* PlaywoRAMdisk may not return, but if it does
  257.                  * it is certain that ramdisk will be 0.
  258.                  */
  259.                 playwoRAMdisk();
  260.                 (void) lseek(fd, 0L, 0); /* Rewind save file */
  261.                 return dorecover(fd);     /* and try again */
  262.             } else {
  263.                 msmsg("Be seeing you ...\n");
  264.                 exit(0);
  265.             }
  266.         }
  267. #else
  268.         savelev(nfd,tmp);
  269. #endif
  270.         (void) close(nfd);
  271.     }
  272.     (void) lseek(fd, 0L, 0);
  273.     getlev(fd, 0, 0);
  274.     (void) close(fd);
  275.     (void) unlink(SAVEF);
  276.     if(Punished) {
  277.         for(otmp = fobj; otmp; otmp = otmp->nobj)
  278.             if(otmp->olet == CHAIN_SYM) goto chainfnd;
  279.         panic("Cannot find the iron chain?");
  280.     chainfnd:
  281.         uchain = otmp;
  282.         if(!uball){
  283.             for(otmp = fobj; otmp; otmp = otmp->nobj)
  284.                 if(otmp->olet == BALL_SYM && otmp->spe)
  285.                     goto ballfnd;
  286.             panic("Cannot find the iron ball?");
  287.         ballfnd:
  288.             uball = otmp;
  289.         }
  290.     }
  291.     if(u.ustuck) {
  292.         register struct monst *mtmp;
  293.  
  294.         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  295.             if(mtmp->m_id == mid) goto monfnd;
  296.         panic("Cannot find the monster ustuck.");
  297.     monfnd:
  298.         u.ustuck = mtmp;
  299.     }
  300. #ifndef QUEST
  301.     setsee();  /* only to recompute seelx etc. - these weren't saved */
  302. #endif
  303. #ifdef DGK
  304.     gameDiskPrompt();
  305. #endif
  306.     docrt();
  307.     restoring = FALSE;
  308.     return(1);
  309. }
  310.  
  311. struct obj *
  312. restobjchn(fd)
  313. register fd;
  314. {
  315.     register struct obj *otmp, *otmp2;
  316.     register struct obj *first = 0;
  317.     int xl;
  318. #ifdef LINT
  319.     /* suppress "used before set" warning from lint */
  320.     otmp2 = 0;
  321. #endif
  322.     while(1) {
  323.         mread(fd, (char *) &xl, sizeof(xl));
  324.         if(xl == -1) break;
  325.         otmp = newobj(xl);
  326.         if(!first) first = otmp;
  327.         else otmp2->nobj = otmp;
  328.         mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj));
  329.         if(!otmp->o_id) otmp->o_id = flags.ident++;
  330.         otmp2 = otmp;
  331.     }
  332.     if(first && otmp2->nobj){
  333.         impossible("Restobjchn: error reading objchn.");
  334.         otmp2->nobj = 0;
  335.     }
  336.     return(first);
  337. }
  338. #ifdef MSDOS
  339. struct monst *
  340. restmonchn(fd)
  341. register fd;
  342. {
  343.     register struct monst *mtmp, *mtmp2;
  344.     register struct monst *first = 0;
  345.     int xl;
  346.     int monsindex, mi;
  347.     extern struct permonst li_dog, dog, la_dog;
  348. #ifdef KAA
  349.     extern struct permonst hell_hound;
  350. # ifdef HARD
  351.     extern struct permonst d_lord, d_prince;
  352. # endif
  353. # ifdef KJSMODS
  354.     extern struct permonst pm_guard, pm_ghost, pm_eel;
  355. # endif
  356. #endif
  357.  
  358. #ifdef lint
  359.     /* suppress "used before set" warning from lint */
  360.     mtmp2 = 0;
  361. #endif /* lint /**/
  362.     while(1) {
  363.         mread(fd, (char *) &xl, sizeof(xl));
  364.         if(xl == -1) break;
  365.         mtmp = newmonst(xl);
  366.         if(!first) first = mtmp;
  367.         else mtmp2->nmon = mtmp;
  368.         mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
  369.         if(!mtmp->m_id)
  370.             mtmp->m_id = flags.ident++;
  371.         monsindex = *((int *)&mtmp->data);
  372.         if (monsindex == (mi = -1))    /* Special fake index */
  373.             mtmp->data = &li_dog;
  374.         else if (monsindex == --mi)    /* Special fake index */
  375.             mtmp->data = &dog;
  376.         else if (monsindex == --mi)    /* Special fake index */
  377.             mtmp->data = &la_dog;
  378. #ifdef KAA
  379.         else if (monsindex == --mi)
  380.             mtmp->data = &hell_hound;
  381. # ifdef HARD
  382.         else if (monsindex == --mi)
  383.             mtmp->data = &d_lord;
  384.  
  385.         else if (monsindex == --mi)
  386.             mtmp->data = &d_prince;
  387. # endif
  388. # ifdef KJSMODS
  389.         else if (monsindex == --mi)
  390.             mtmp->data = &pm_guard;
  391.  
  392.         else if (monsindex == --mi)
  393.             mtmp->data = &pm_ghost;
  394.  
  395.         else if (monsindex == --mi)
  396.             mtmp->data = &pm_eel;
  397. # endif
  398. #endif
  399.         else
  400.             mtmp->data = &mons[monsindex];
  401.         if(mtmp->minvent)
  402.             mtmp->minvent = restobjchn(fd);
  403.         mtmp2 = mtmp;
  404.     }
  405.     if(first && mtmp2->nmon){
  406.         impossible("Restmonchn: error reading monchn.");
  407.         mtmp2->nmon = 0;
  408.     }
  409.     return(first);
  410. }
  411. #else
  412. struct monst *
  413. restmonchn(fd)
  414. register fd;
  415. {
  416.     register struct monst *mtmp, *mtmp2;
  417.     register struct monst *first = 0;
  418.     int xl;
  419.  
  420.     struct permonst *monbegin;
  421.     long differ;
  422.  
  423.     mread(fd, (char *)&monbegin, sizeof(monbegin));
  424.     differ = (char *)(&mons[0]) - (char *)(monbegin);
  425.  
  426. #ifdef LINT
  427.     /* suppress "used before set" warning from lint */
  428.     mtmp2 = 0;
  429. #endif
  430.     while(1) {
  431.         mread(fd, (char *) &xl, sizeof(xl));
  432.         if(xl == -1) break;
  433.         mtmp = newmonst(xl);
  434.         if(!first) first = mtmp;
  435.         else mtmp2->nmon = mtmp;
  436.         mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
  437.         if(!mtmp->m_id)
  438.             mtmp->m_id = flags.ident++;
  439.         mtmp->data = (struct permonst *)
  440.             ((char *) mtmp->data + differ);
  441.         if(mtmp->minvent)
  442.             mtmp->minvent = restobjchn(fd);
  443.         mtmp2 = mtmp;
  444.     }
  445.     if(first && mtmp2->nmon){
  446.         impossible("Restmonchn: error reading monchn.");
  447.         mtmp2->nmon = 0;
  448.     }
  449.     return(first);
  450. }
  451. #endif
  452.