hammer(8): adjust markup & improve wording
[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.4 2006/08/21 19:45:32 pavalos Exp $ */
5
6 #include "hack.h"
7
8 extern char SAVEF[], nul[];
9
10 static bool dosave0(int);
11
12 int
13 dosave(void)
14 {
15         if (dosave0(0)) {
16                 settty("Be seeing you ...\n");
17                 exit(0);
18         }
19         return (0);
20 }
21
22 #ifndef NOSAVEONHANGUP
23 void
24 hangup(int n __unused)
25 {
26         dosave0(1);
27         exit(1);
28 }
29 #endif /* NOSAVEONHANGUP */
30
31 /* returns 1 if save successful */
32 static bool
33 dosave0(int hu)
34 {
35         int fd, ofd;
36         int tmp;        /* not ! */
37
38         signal(SIGHUP, SIG_IGN);
39         signal(SIGINT, SIG_IGN);
40         if ((fd = creat(SAVEF, FMASK)) < 0) {
41                 if (!hu)
42                         pline("Cannot open save file. (Continue or Quit)");
43                 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                 if (tmp == dlevel || !level_exists[tmp])
67                         continue;
68                 glo(tmp);
69                 if ((ofd = open(lock, O_RDONLY)) < 0) {
70                         if (!hu)
71                                 pline("Error while saving: cannot read %s.", lock);
72                         close(fd);
73                         unlink(SAVEF);
74                         if (!hu)
75                                 done("tricked");
76                         return (0);
77                 }
78                 getlev(ofd, hackpid, tmp);
79                 close(ofd);
80                 bwrite(fd, (char *)&tmp, sizeof(tmp));  /* level number */
81                 savelev(fd, tmp);                       /* actual level */
82                 unlink(lock);
83         }
84         close(fd);
85         glo(dlevel);
86         unlink(lock);   /* get rid of current level --jgm */
87         glo(0);
88         unlink(lock);
89         return (1);
90 }
91
92 bool
93 dorecover(int fd)
94 {
95         int nfd;
96         int tmp;                /* not a ! */
97         unsigned mid;           /* idem */
98         struct obj *otmp;
99
100         restoring = TRUE;
101         getlev(fd, 0, 0);
102         invent = restobjchn(fd);
103         for (otmp = invent; otmp; otmp = otmp->nobj)
104                 if (otmp->owornmask)
105                         setworn(otmp, otmp->owornmask);
106         fcobj = restobjchn(fd);
107         fallen_down = restmonchn(fd);
108         mread(fd, (char *)&tmp, sizeof(tmp));
109         if (tmp != (int)getuid()) {     /* strange ... */
110                 close(fd);
111                 unlink(SAVEF);
112                 puts("Saved game was not yours.");
113                 restoring = FALSE;
114                 return (0);
115         }
116         mread(fd, (char *)&flags, sizeof(struct flag));
117         mread(fd, (char *)&dlevel, sizeof(dlevel));
118         mread(fd, (char *)&maxdlevel, sizeof(maxdlevel));
119         mread(fd, (char *)&moves, sizeof(moves));
120         mread(fd, (char *)&u, sizeof(struct you));
121         if (u.ustuck)
122                 mread(fd, (char *)&mid, sizeof(mid));
123         mread(fd, (char *)pl_character, sizeof(pl_character));
124         mread(fd, (char *)genocided, sizeof(genocided));
125         mread(fd, (char *)fut_geno, sizeof(fut_geno));
126         restnames(fd);
127         for (;;) {
128                 if (read(fd, (char *)&tmp, sizeof(tmp)) != sizeof(tmp))
129                         break;
130                 getlev(fd, 0, tmp);
131                 glo(tmp);
132                 if ((nfd = creat(lock, FMASK)) < 0)
133                         panic("Cannot open temp file %s!\n", lock);
134                 savelev(nfd, tmp);
135                 close(nfd);
136         }
137         lseek(fd, (off_t)0, SEEK_SET);
138         getlev(fd, 0, 0);
139         close(fd);
140         unlink(SAVEF);
141         if (Punished) {
142                 for (otmp = fobj; otmp; otmp = otmp->nobj)
143                         if (otmp->olet == CHAIN_SYM)
144                                 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)
162                                 goto monfnd;
163                 panic("Cannot find the monster ustuck.");
164 monfnd:
165                 u.ustuck = mtmp;
166         }
167 #ifndef QUEST
168         setsee();       /* only to recompute seelx etc. - these weren't saved */
169 #endif /* QUEST */
170         docrt();
171         restoring = FALSE;
172         return (1);
173 }
174
175 struct obj *
176 restobjchn(int fd)
177 {
178         struct obj *otmp, *otmp2;
179         struct obj *first = 0;
180         int xl;
181
182         /* suppress "used before set" warning from lint */
183         otmp2 = 0;
184         for (;;) {
185                 mread(fd, (char *)&xl, sizeof(xl));
186                 if (xl == -1)
187                         break;
188                 otmp = newobj(xl);
189                 if (!first)
190                         first = otmp;
191                 else
192                         otmp2->nobj = otmp;
193                 mread(fd, (char *)otmp, (unsigned)xl + sizeof(struct obj));
194                 if (!otmp->o_id) otmp->o_id = flags.ident++;
195                 otmp2 = otmp;
196         }
197         if (first && otmp2->nobj) {
198                 impossible("Restobjchn: error reading objchn.");
199                 otmp2->nobj = 0;
200         }
201         return (first);
202 }
203
204 struct monst *
205 restmonchn(int fd)
206 {
207         struct monst *mtmp, *mtmp2;
208         struct monst *first = 0;
209         int xl;
210         struct permonst *monbegin;
211         long differ;
212
213         mread(fd, (char *)&monbegin, sizeof(monbegin));
214         differ = (char *)(&mons[0]) - (char *)(monbegin);
215
216         /* suppress "used before set" warning from lint */
217         mtmp2 = 0;
218         for (;;) {
219                 mread(fd, (char *)&xl, sizeof(xl));
220                 if (xl == -1)
221                         break;
222                 mtmp = newmonst(xl);
223                 if (!first)
224                         first = mtmp;
225                 else
226                         mtmp2->nmon = mtmp;
227                 mread(fd, (char *)mtmp, (unsigned)xl + sizeof(struct monst));
228                 if (!mtmp->m_id)
229                         mtmp->m_id = flags.ident++;
230                 mtmp->data = (struct permonst *)
231                     ((char *)mtmp->data + differ);
232                 if (mtmp->minvent)
233                         mtmp->minvent = restobjchn(fd);
234                 mtmp2 = mtmp;
235         }
236         if (first && mtmp2->nmon) {
237                 impossible("Restmonchn: error reading monchn.");
238                 mtmp2->nmon = 0;
239         }
240         return (first);
241 }