| 1 | /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ |
| 2 | /* hack.lev.c - version 1.0.3 */ |
| 3 | /* $FreeBSD: src/games/hack/hack.lev.c,v 1.4 1999/11/16 10:26:36 marcel Exp $ */ |
| 4 | |
| 5 | #include "hack.h" |
| 6 | extern struct obj *billobjs; |
| 7 | extern char SAVEF[]; |
| 8 | extern char nul[]; |
| 9 | |
| 10 | #ifndef NOWORM |
| 11 | extern struct wseg *wsegs[32], *wheads[32]; |
| 12 | extern long wgrowtime[32]; |
| 13 | #endif /* NOWORM */ |
| 14 | |
| 15 | boolean level_exists[MAXLEVEL+1]; |
| 16 | |
| 17 | static void savegoldchn(int, struct gold *); |
| 18 | static void savetrapchn(int, struct trap *); |
| 19 | |
| 20 | void |
| 21 | savelev(int fd, xchar lev) |
| 22 | { |
| 23 | #ifndef NOWORM |
| 24 | struct wseg *wtmp, *wtmp2; |
| 25 | int tmp; |
| 26 | #endif /* NOWORM */ |
| 27 | |
| 28 | if (fd < 0) |
| 29 | panic("Save on bad file!"); /* impossible */ |
| 30 | if (lev >= 0 && lev <= MAXLEVEL) |
| 31 | level_exists[lev] = TRUE; |
| 32 | |
| 33 | bwrite(fd, (char *)&hackpid, sizeof(hackpid)); |
| 34 | bwrite(fd, (char *)&lev, sizeof(lev)); |
| 35 | bwrite(fd, (char *)levl, sizeof(levl)); |
| 36 | bwrite(fd, (char *)&moves, sizeof(long)); |
| 37 | bwrite(fd, (char *)&xupstair, sizeof(xupstair)); |
| 38 | bwrite(fd, (char *)&yupstair, sizeof(yupstair)); |
| 39 | bwrite(fd, (char *)&xdnstair, sizeof(xdnstair)); |
| 40 | bwrite(fd, (char *)&ydnstair, sizeof(ydnstair)); |
| 41 | savemonchn(fd, fmon); |
| 42 | savegoldchn(fd, fgold); |
| 43 | savetrapchn(fd, ftrap); |
| 44 | saveobjchn(fd, fobj); |
| 45 | saveobjchn(fd, billobjs); |
| 46 | billobjs = NULL; |
| 47 | save_engravings(fd); |
| 48 | #ifndef QUEST |
| 49 | bwrite(fd, (char *)rooms, sizeof(rooms)); |
| 50 | bwrite(fd, (char *)doors, sizeof(doors)); |
| 51 | #endif /* QUEST */ |
| 52 | fgold = 0; |
| 53 | ftrap = 0; |
| 54 | fmon = 0; |
| 55 | fobj = 0; |
| 56 | #ifndef NOWORM |
| 57 | bwrite(fd, (char *)wsegs, sizeof(wsegs)); |
| 58 | for (tmp = 1; tmp < 32; tmp++) { |
| 59 | for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) { |
| 60 | wtmp2 = wtmp->nseg; |
| 61 | bwrite(fd, (char *)wtmp, sizeof(struct wseg)); |
| 62 | } |
| 63 | wsegs[tmp] = NULL; |
| 64 | } |
| 65 | bwrite(fd, (char *)wgrowtime, sizeof(wgrowtime)); |
| 66 | #endif /* NOWORM */ |
| 67 | } |
| 68 | |
| 69 | void |
| 70 | bwrite(int fd, char *loc, unsigned int num) |
| 71 | { |
| 72 | /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */ |
| 73 | if (write(fd, loc, (int)num) != (int)num) |
| 74 | panic("cannot write %u bytes to file #%d", num, fd); |
| 75 | } |
| 76 | |
| 77 | void |
| 78 | saveobjchn(int fd, struct obj *otmp) |
| 79 | { |
| 80 | struct obj *otmp2; |
| 81 | unsigned xl; |
| 82 | int minusone = -1; |
| 83 | |
| 84 | while (otmp) { |
| 85 | otmp2 = otmp->nobj; |
| 86 | xl = otmp->onamelth; |
| 87 | bwrite(fd, (char *)&xl, sizeof(int)); |
| 88 | bwrite(fd, (char *)otmp, xl + sizeof(struct obj)); |
| 89 | free(otmp); |
| 90 | otmp = otmp2; |
| 91 | } |
| 92 | bwrite(fd, (char *)&minusone, sizeof(int)); |
| 93 | } |
| 94 | |
| 95 | void |
| 96 | savemonchn(int fd, struct monst *mtmp) |
| 97 | { |
| 98 | struct monst *mtmp2; |
| 99 | unsigned xl; |
| 100 | int minusone = -1; |
| 101 | struct permonst *monbegin = &mons[0]; |
| 102 | |
| 103 | bwrite(fd, (char *)&monbegin, sizeof(monbegin)); |
| 104 | |
| 105 | while (mtmp) { |
| 106 | mtmp2 = mtmp->nmon; |
| 107 | xl = mtmp->mxlth + mtmp->mnamelth; |
| 108 | bwrite(fd, (char *)&xl, sizeof(int)); |
| 109 | bwrite(fd, (char *)mtmp, xl + sizeof(struct monst)); |
| 110 | if (mtmp->minvent) |
| 111 | saveobjchn(fd, mtmp->minvent); |
| 112 | free(mtmp); |
| 113 | mtmp = mtmp2; |
| 114 | } |
| 115 | bwrite(fd, (char *)&minusone, sizeof(int)); |
| 116 | } |
| 117 | |
| 118 | static void |
| 119 | savegoldchn(int fd, struct gold *gold) |
| 120 | { |
| 121 | struct gold *gold2; |
| 122 | |
| 123 | while (gold) { |
| 124 | gold2 = gold->ngold; |
| 125 | bwrite(fd, (char *)gold, sizeof(struct gold)); |
| 126 | free(gold); |
| 127 | gold = gold2; |
| 128 | } |
| 129 | bwrite(fd, nul, sizeof(struct gold)); |
| 130 | } |
| 131 | |
| 132 | static void |
| 133 | savetrapchn(int fd, struct trap *trap) |
| 134 | { |
| 135 | struct trap *trap2; |
| 136 | |
| 137 | while (trap) { |
| 138 | trap2 = trap->ntrap; |
| 139 | bwrite(fd, (char *)trap, sizeof(struct trap)); |
| 140 | free(trap); |
| 141 | trap = trap2; |
| 142 | } |
| 143 | bwrite(fd, nul, sizeof(struct trap)); |
| 144 | } |
| 145 | |
| 146 | void |
| 147 | getlev(int fd, int pid, xchar lev) |
| 148 | { |
| 149 | struct gold *gold; |
| 150 | struct trap *trap; |
| 151 | #ifndef NOWORM |
| 152 | struct wseg *wtmp; |
| 153 | #endif /* NOWORM */ |
| 154 | int tmp; |
| 155 | long omoves; |
| 156 | int hpid; |
| 157 | xchar dlvl; |
| 158 | |
| 159 | /* First some sanity checks */ |
| 160 | mread(fd, (char *)&hpid, sizeof(hpid)); |
| 161 | mread(fd, (char *)&dlvl, sizeof(dlvl)); |
| 162 | if ((pid && pid != hpid) || (lev && dlvl != lev)) { |
| 163 | pline("Strange, this map is not as I remember it."); |
| 164 | pline("Somebody is trying some trickery here ..."); |
| 165 | pline("This game is void ..."); |
| 166 | done("tricked"); |
| 167 | } |
| 168 | |
| 169 | fgold = 0; |
| 170 | ftrap = 0; |
| 171 | mread(fd, (char *)levl, sizeof(levl)); |
| 172 | mread(fd, (char *)&omoves, sizeof(omoves)); |
| 173 | mread(fd, (char *)&xupstair, sizeof(xupstair)); |
| 174 | mread(fd, (char *)&yupstair, sizeof(yupstair)); |
| 175 | mread(fd, (char *)&xdnstair, sizeof(xdnstair)); |
| 176 | mread(fd, (char *)&ydnstair, sizeof(ydnstair)); |
| 177 | |
| 178 | fmon = restmonchn(fd); |
| 179 | |
| 180 | /* regenerate animals while on another level */ |
| 181 | { |
| 182 | long tmoves = (moves > omoves) ? moves - omoves : 0; |
| 183 | struct monst *mtmp, *mtmp2; |
| 184 | |
| 185 | for (mtmp = fmon; mtmp; mtmp = mtmp2) { |
| 186 | long newhp; /* tmoves may be very large */ |
| 187 | |
| 188 | mtmp2 = mtmp->nmon; |
| 189 | if (strchr(genocided, mtmp->data->mlet)) { |
| 190 | mondead(mtmp); |
| 191 | continue; |
| 192 | } |
| 193 | |
| 194 | if (mtmp->mtame && tmoves > 250) { |
| 195 | mtmp->mtame = 0; |
| 196 | mtmp->mpeaceful = 0; |
| 197 | } |
| 198 | |
| 199 | newhp = mtmp->mhp + |
| 200 | (strchr(MREGEN, mtmp->data->mlet) ? tmoves : tmoves / 20); |
| 201 | if (newhp > mtmp->mhpmax) |
| 202 | mtmp->mhp = mtmp->mhpmax; |
| 203 | else |
| 204 | mtmp->mhp = newhp; |
| 205 | } |
| 206 | } |
| 207 | |
| 208 | setgd(); |
| 209 | gold = newgold(); |
| 210 | mread(fd, (char *)gold, sizeof(struct gold)); |
| 211 | while (gold->gx) { |
| 212 | gold->ngold = fgold; |
| 213 | fgold = gold; |
| 214 | gold = newgold(); |
| 215 | mread(fd, (char *)gold, sizeof(struct gold)); |
| 216 | } |
| 217 | free(gold); |
| 218 | trap = newtrap(); |
| 219 | mread(fd, (char *)trap, sizeof(struct trap)); |
| 220 | while (trap->tx) { |
| 221 | trap->ntrap = ftrap; |
| 222 | ftrap = trap; |
| 223 | trap = newtrap(); |
| 224 | mread(fd, (char *)trap, sizeof(struct trap)); |
| 225 | } |
| 226 | free(trap); |
| 227 | fobj = restobjchn(fd); |
| 228 | billobjs = restobjchn(fd); |
| 229 | rest_engravings(fd); |
| 230 | #ifndef QUEST |
| 231 | mread(fd, (char *)rooms, sizeof(rooms)); |
| 232 | mread(fd, (char *)doors, sizeof(doors)); |
| 233 | #endif /* QUEST */ |
| 234 | #ifndef NOWORM |
| 235 | mread(fd, (char *)wsegs, sizeof(wsegs)); |
| 236 | for (tmp = 1; tmp < 32; tmp++) |
| 237 | if (wsegs[tmp]) { |
| 238 | wheads[tmp] = wsegs[tmp] = wtmp = newseg(); |
| 239 | for (;;) { |
| 240 | mread(fd, (char *)wtmp, sizeof(struct wseg)); |
| 241 | if (!wtmp->nseg) |
| 242 | break; |
| 243 | wheads[tmp]->nseg = wtmp = newseg(); |
| 244 | wheads[tmp] = wtmp; |
| 245 | } |
| 246 | } |
| 247 | mread(fd, (char *)wgrowtime, sizeof(wgrowtime)); |
| 248 | #endif /* NOWORM */ |
| 249 | } |
| 250 | |
| 251 | void |
| 252 | mread(int fd, char *buf, unsigned int len) |
| 253 | { |
| 254 | int rlen; |
| 255 | |
| 256 | rlen = read(fd, buf, (int)len); |
| 257 | if (rlen != (int)len) { |
| 258 | pline("Read %d instead of %u bytes.\n", rlen, len); |
| 259 | if (restoring) { |
| 260 | unlink(SAVEF); |
| 261 | error("Error restoring old game."); |
| 262 | } |
| 263 | panic("Error reading level file."); |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | void |
| 268 | mklev(void) |
| 269 | { |
| 270 | if (getbones()) |
| 271 | return; |
| 272 | |
| 273 | in_mklev = TRUE; |
| 274 | makelevel(); |
| 275 | in_mklev = FALSE; |
| 276 | } |