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