a199598a4648e1c5f49f8e1aa4146f71fafd8121
[dragonfly.git] / games / hack / hack.save.c
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.save.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.save.c,v 1.4 1999/11/16 10:26:37 marcel Exp $ */
4 /* $DragonFly: src/games/hack/hack.save.c,v 1.2 2003/06/17 04:25:24 dillon Exp $ */
5
6 #include "hack.h"
7 extern char genocided[60];      /* defined in Decl.c */
8 extern char fut_geno[60];       /* idem */
9 #include <signal.h>
10 #include <unistd.h>
11
12 extern char SAVEF[], nul[];
13 extern char pl_character[PL_CSIZ];
14 extern struct obj *restobjchn();
15 extern struct monst *restmonchn();
16
17 dosave(){
18         if(dosave0(0)) {
19                 settty("Be seeing you ...\n");
20                 exit(0);
21         }
22 #ifdef lint
23         return(0);
24 #endif lint
25 }
26
27 #ifndef NOSAVEONHANGUP
28 hangup(){
29         (void) dosave0(1);
30         exit(1);
31 }
32 #endif NOSAVEONHANGUP
33
34 /* returns 1 if save successful */
35 dosave0(hu) int hu; {
36         int fd, ofd;
37         int tmp;                /* not ! */
38
39         (void) signal(SIGHUP, SIG_IGN);
40         (void) signal(SIGINT, SIG_IGN);
41         if((fd = creat(SAVEF, FMASK)) < 0) {
42                 if(!hu) pline("Cannot open save file. (Continue or Quit)");
43                 (void) unlink(SAVEF);           /* ab@unido */
44                 return(0);
45         }
46         if(flags.moonphase == FULL_MOON)        /* ut-sally!fletcher */
47                 u.uluck--;                      /* and unido!ab */
48         savelev(fd,dlevel);
49         saveobjchn(fd, invent);
50         saveobjchn(fd, fcobj);
51         savemonchn(fd, fallen_down);
52         tmp = getuid();
53         bwrite(fd, (char *) &tmp, sizeof tmp);
54         bwrite(fd, (char *) &flags, sizeof(struct flag));
55         bwrite(fd, (char *) &dlevel, sizeof dlevel);
56         bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel);
57         bwrite(fd, (char *) &moves, sizeof moves);
58         bwrite(fd, (char *) &u, sizeof(struct you));
59         if(u.ustuck)
60                 bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
61         bwrite(fd, (char *) pl_character, sizeof pl_character);
62         bwrite(fd, (char *) genocided, sizeof genocided);
63         bwrite(fd, (char *) fut_geno, sizeof fut_geno);
64         savenames(fd);
65         for(tmp = 1; tmp <= maxdlevel; tmp++) {
66                 extern int hackpid;
67                 extern boolean level_exists[];
68
69                 if(tmp == dlevel || !level_exists[tmp]) continue;
70                 glo(tmp);
71                 if((ofd = open(lock, 0)) < 0) {
72                     if(!hu) pline("Error while saving: cannot read %s.", lock);
73                     (void) close(fd);
74                     (void) unlink(SAVEF);
75                     if(!hu) done("tricked");
76                     return(0);
77                 }
78                 getlev(ofd, hackpid, tmp);
79                 (void) close(ofd);
80                 bwrite(fd, (char *) &tmp, sizeof tmp);  /* level number */
81                 savelev(fd,tmp);                        /* actual level */
82                 (void) unlink(lock);
83         }
84         (void) close(fd);
85         glo(dlevel);
86         (void) unlink(lock);    /* get rid of current level --jgm */
87         glo(0);
88         (void) unlink(lock);
89         return(1);
90 }
91
92 dorecover(fd)
93 int fd;
94 {
95         int nfd;
96         int tmp;                /* not a ! */
97         unsigned mid;           /* idem */
98         struct obj *otmp;
99         extern boolean restoring;
100
101         restoring = TRUE;
102         getlev(fd, 0, 0);
103         invent = restobjchn(fd);
104         for(otmp = invent; otmp; otmp = otmp->nobj)
105                 if(otmp->owornmask)
106                         setworn(otmp, otmp->owornmask);
107         fcobj = restobjchn(fd);
108         fallen_down = restmonchn(fd);
109         mread(fd, (char *) &tmp, sizeof tmp);
110         if(tmp != getuid()) {           /* strange ... */
111                 (void) close(fd);
112                 (void) unlink(SAVEF);
113                 puts("Saved game was not yours.");
114                 restoring = FALSE;
115                 return(0);
116         }
117         mread(fd, (char *) &flags, sizeof(struct flag));
118         mread(fd, (char *) &dlevel, sizeof dlevel);
119         mread(fd, (char *) &maxdlevel, sizeof maxdlevel);
120         mread(fd, (char *) &moves, sizeof moves);
121         mread(fd, (char *) &u, sizeof(struct you));
122         if(u.ustuck)
123                 mread(fd, (char *) &mid, sizeof mid);
124         mread(fd, (char *) pl_character, sizeof pl_character);
125         mread(fd, (char *) genocided, sizeof genocided);
126         mread(fd, (char *) fut_geno, sizeof fut_geno);
127         restnames(fd);
128         while(1) {
129                 if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp)
130                         break;
131                 getlev(fd, 0, tmp);
132                 glo(tmp);
133                 if((nfd = creat(lock, FMASK)) < 0)
134                         panic("Cannot open temp file %s!\n", lock);
135                 savelev(nfd,tmp);
136                 (void) close(nfd);
137         }
138         (void) lseek(fd, (off_t)0, 0);
139         getlev(fd, 0, 0);
140         (void) close(fd);
141         (void) unlink(SAVEF);
142         if(Punished) {
143                 for(otmp = fobj; otmp; otmp = otmp->nobj)
144                         if(otmp->olet == CHAIN_SYM) goto chainfnd;
145                 panic("Cannot find the iron chain?");
146         chainfnd:
147                 uchain = otmp;
148                 if(!uball){
149                         for(otmp = fobj; otmp; otmp = otmp->nobj)
150                                 if(otmp->olet == BALL_SYM && otmp->spe)
151                                         goto ballfnd;
152                         panic("Cannot find the iron ball?");
153                 ballfnd:
154                         uball = otmp;
155                 }
156         }
157         if(u.ustuck) {
158                 struct monst *mtmp;
159
160                 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
161                         if(mtmp->m_id == mid) goto monfnd;
162                 panic("Cannot find the monster ustuck.");
163         monfnd:
164                 u.ustuck = mtmp;
165         }
166 #ifndef QUEST
167         setsee();  /* only to recompute seelx etc. - these weren't saved */
168 #endif QUEST
169         docrt();
170         restoring = FALSE;
171         return(1);
172 }
173
174 struct obj *
175 restobjchn(fd)
176 int fd;
177 {
178         struct obj *otmp, *otmp2;
179         struct obj *first = 0;
180         int xl;
181 #ifdef lint
182         /* suppress "used before set" warning from lint */
183         otmp2 = 0;
184 #endif lint
185         while(1) {
186                 mread(fd, (char *) &xl, sizeof(xl));
187                 if(xl == -1) break;
188                 otmp = newobj(xl);
189                 if(!first) first = otmp;
190                 else otmp2->nobj = otmp;
191                 mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj));
192                 if(!otmp->o_id) otmp->o_id = flags.ident++;
193                 otmp2 = otmp;
194         }
195         if(first && otmp2->nobj){
196                 impossible("Restobjchn: error reading objchn.");
197                 otmp2->nobj = 0;
198         }
199         return(first);
200 }
201
202 struct monst *
203 restmonchn(fd)
204 int fd;
205 {
206         struct monst *mtmp, *mtmp2;
207         struct monst *first = 0;
208         int xl;
209
210         struct permonst *monbegin;
211         long differ;
212
213         mread(fd, (char *)&monbegin, sizeof(monbegin));
214         differ = (char *)(&mons[0]) - (char *)(monbegin);
215
216 #ifdef lint
217         /* suppress "used before set" warning from lint */
218         mtmp2 = 0;
219 #endif lint
220         while(1) {
221                 mread(fd, (char *) &xl, sizeof(xl));
222                 if(xl == -1) break;
223                 mtmp = newmonst(xl);
224                 if(!first) first = mtmp;
225                 else mtmp2->nmon = mtmp;
226                 mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
227                 if(!mtmp->m_id)
228                         mtmp->m_id = flags.ident++;
229                 mtmp->data = (struct permonst *)
230                         ((char *) mtmp->data + differ);
231                 if(mtmp->minvent)
232                         mtmp->minvent = restobjchn(fd);
233                 mtmp2 = mtmp;
234         }
235         if(first && mtmp2->nmon){
236                 impossible("Restmonchn: error reading monchn.");
237                 mtmp2->nmon = 0;
238         }
239         return(first);
240 }