1*8041af98Sdholland /* $NetBSD: hack.lev.c,v 1.14 2011/08/06 20:32:25 dholland Exp $ */
23ea4a95cSchristos
302ded532Smycroft /*
41c7f94e5Sjsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm * Amsterdam
61c7f94e5Sjsm * All rights reserved.
71c7f94e5Sjsm *
81c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm * met:
111c7f94e5Sjsm *
121c7f94e5Sjsm * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm * this list of conditions and the following disclaimer.
141c7f94e5Sjsm *
151c7f94e5Sjsm * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm *
191c7f94e5Sjsm * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm * promote products derived from this software without specific prior
221c7f94e5Sjsm * written permission.
231c7f94e5Sjsm *
241c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm */
361c7f94e5Sjsm
371c7f94e5Sjsm /*
381c7f94e5Sjsm * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm * All rights reserved.
401c7f94e5Sjsm *
411c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm * modification, are permitted provided that the following conditions
431c7f94e5Sjsm * are met:
441c7f94e5Sjsm * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm * notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm * derived from this software without specific prior written permission.
511c7f94e5Sjsm *
521c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
551c7f94e5Sjsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6202ded532Smycroft */
6302ded532Smycroft
643ea4a95cSchristos #include <sys/cdefs.h>
6502ded532Smycroft #ifndef lint
66*8041af98Sdholland __RCSID("$NetBSD: hack.lev.c,v 1.14 2011/08/06 20:32:25 dholland Exp $");
6702ded532Smycroft #endif /* not lint */
6861f28255Scgd
693ea4a95cSchristos #include <stdlib.h>
703ea4a95cSchristos #include <unistd.h>
7161f28255Scgd #include "hack.h"
723ea4a95cSchristos #include "extern.h"
7361f28255Scgd #include "def.mkroom.h"
7461f28255Scgd
7561f28255Scgd #ifndef NOWORM
7661f28255Scgd #include "def.wseg.h"
773ea4a95cSchristos #endif /* NOWORM */
7861f28255Scgd
7961f28255Scgd boolean level_exists[MAXLEVEL + 1];
8061f28255Scgd
819b92b189Sdholland static void savegoldchn(int, struct gold *);
829b92b189Sdholland static void savetrapchn(int, struct trap *);
839b92b189Sdholland
843ea4a95cSchristos void
savelev(int fd,xchar lev)851fa8a9a6Sdholland savelev(int fd, xchar lev)
8661f28255Scgd {
8761f28255Scgd #ifndef NOWORM
883ea4a95cSchristos struct wseg *wtmp, *wtmp2;
893ea4a95cSchristos int tmp;
903ea4a95cSchristos #endif /* NOWORM */
9161f28255Scgd
923ea4a95cSchristos if (fd < 0)
933ea4a95cSchristos panic("Save on bad file!"); /* impossible */
9461f28255Scgd if (lev >= 0 && lev <= MAXLEVEL)
9561f28255Scgd level_exists[lev] = TRUE;
9661f28255Scgd
97*8041af98Sdholland bwrite(fd, &hackpid, sizeof(hackpid));
98*8041af98Sdholland bwrite(fd, &lev, sizeof(lev));
99*8041af98Sdholland bwrite(fd, levl, sizeof(levl));
100*8041af98Sdholland bwrite(fd, &moves, sizeof(long));
101*8041af98Sdholland bwrite(fd, &xupstair, sizeof(xupstair));
102*8041af98Sdholland bwrite(fd, &yupstair, sizeof(yupstair));
103*8041af98Sdholland bwrite(fd, &xdnstair, sizeof(xdnstair));
104*8041af98Sdholland bwrite(fd, &ydnstair, sizeof(ydnstair));
10561f28255Scgd savemonchn(fd, fmon);
10661f28255Scgd savegoldchn(fd, fgold);
10761f28255Scgd savetrapchn(fd, ftrap);
10861f28255Scgd saveobjchn(fd, fobj);
10961f28255Scgd saveobjchn(fd, billobjs);
11061f28255Scgd billobjs = 0;
11161f28255Scgd save_engravings(fd);
11261f28255Scgd #ifndef QUEST
113*8041af98Sdholland bwrite(fd, rooms, sizeof(rooms));
114*8041af98Sdholland bwrite(fd, doors, sizeof(doors));
1153ea4a95cSchristos #endif /* QUEST */
11661f28255Scgd fgold = 0;
11761f28255Scgd ftrap = 0;
11861f28255Scgd fmon = 0;
11961f28255Scgd fobj = 0;
12061f28255Scgd #ifndef NOWORM
121*8041af98Sdholland bwrite(fd, wsegs, sizeof(wsegs));
12261f28255Scgd for (tmp = 1; tmp < 32; tmp++) {
12361f28255Scgd for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
12461f28255Scgd wtmp2 = wtmp->nseg;
125*8041af98Sdholland bwrite(fd, wtmp, sizeof(struct wseg));
12661f28255Scgd }
12761f28255Scgd wsegs[tmp] = 0;
12861f28255Scgd }
129*8041af98Sdholland bwrite(fd, wgrowtime, sizeof(wgrowtime));
1303ea4a95cSchristos #endif /* NOWORM */
13161f28255Scgd }
13261f28255Scgd
1333ea4a95cSchristos void
bwrite(int fd,const void * loc,size_t num)1341fa8a9a6Sdholland bwrite(int fd, const void *loc, size_t num)
13561f28255Scgd {
13661f28255Scgd /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */
137c6144e48Slukem if ((size_t)write(fd, loc, num) != num)
138f341bbffStnn panic("cannot write %zu bytes to file #%d", num, fd);
13961f28255Scgd }
14061f28255Scgd
1413ea4a95cSchristos void
saveobjchn(int fd,struct obj * otmp)1421fa8a9a6Sdholland saveobjchn(int fd, struct obj *otmp)
14361f28255Scgd {
1443ea4a95cSchristos struct obj *otmp2;
14561f28255Scgd unsigned xl;
14661f28255Scgd int minusone = -1;
14761f28255Scgd
14861f28255Scgd while (otmp) {
14961f28255Scgd otmp2 = otmp->nobj;
15061f28255Scgd xl = otmp->onamelth;
151*8041af98Sdholland bwrite(fd, &xl, sizeof(int));
152*8041af98Sdholland bwrite(fd, otmp, xl + sizeof(struct obj));
1538e73b3adSdholland free(otmp);
15461f28255Scgd otmp = otmp2;
15561f28255Scgd }
156*8041af98Sdholland bwrite(fd, &minusone, sizeof(int));
15761f28255Scgd }
15861f28255Scgd
1593ea4a95cSchristos void
savemonchn(int fd,struct monst * mtmp)1601fa8a9a6Sdholland savemonchn(int fd, struct monst *mtmp)
16161f28255Scgd {
1623ea4a95cSchristos struct monst *mtmp2;
16361f28255Scgd unsigned xl;
16461f28255Scgd int minusone = -1;
165ab8b6343Sjsm const struct permonst *monbegin = &mons[0];
16661f28255Scgd
167ab8b6343Sjsm bwrite(fd, &monbegin, sizeof(monbegin));
16861f28255Scgd
16961f28255Scgd while (mtmp) {
17061f28255Scgd mtmp2 = mtmp->nmon;
17161f28255Scgd xl = mtmp->mxlth + mtmp->mnamelth;
172*8041af98Sdholland bwrite(fd, &xl, sizeof(int));
173*8041af98Sdholland bwrite(fd, mtmp, xl + sizeof(struct monst));
1743ea4a95cSchristos if (mtmp->minvent)
1753ea4a95cSchristos saveobjchn(fd, mtmp->minvent);
1768e73b3adSdholland free(mtmp);
17761f28255Scgd mtmp = mtmp2;
17861f28255Scgd }
179*8041af98Sdholland bwrite(fd, &minusone, sizeof(int));
18061f28255Scgd }
18161f28255Scgd
1829b92b189Sdholland static void
savegoldchn(int fd,struct gold * gold)1831fa8a9a6Sdholland savegoldchn(int fd, struct gold *gold)
18461f28255Scgd {
1853ea4a95cSchristos struct gold *gold2;
18661f28255Scgd while (gold) {
18761f28255Scgd gold2 = gold->ngold;
188*8041af98Sdholland bwrite(fd, gold, sizeof(struct gold));
1898e73b3adSdholland free(gold);
19061f28255Scgd gold = gold2;
19161f28255Scgd }
19261f28255Scgd bwrite(fd, nul, sizeof(struct gold));
19361f28255Scgd }
19461f28255Scgd
1959b92b189Sdholland static void
savetrapchn(int fd,struct trap * trap)1961fa8a9a6Sdholland savetrapchn(int fd, struct trap *trap)
19761f28255Scgd {
1983ea4a95cSchristos struct trap *trap2;
19961f28255Scgd while (trap) {
20061f28255Scgd trap2 = trap->ntrap;
201*8041af98Sdholland bwrite(fd, trap, sizeof(struct trap));
2028e73b3adSdholland free(trap);
20361f28255Scgd trap = trap2;
20461f28255Scgd }
20561f28255Scgd bwrite(fd, nul, sizeof(struct trap));
20661f28255Scgd }
20761f28255Scgd
2083ea4a95cSchristos void
getlev(int fd,int pid,xchar lev)2091fa8a9a6Sdholland getlev(int fd, int pid, xchar lev)
21061f28255Scgd {
2113ea4a95cSchristos struct gold *gold;
2123ea4a95cSchristos struct trap *trap;
21361f28255Scgd #ifndef NOWORM
2143ea4a95cSchristos struct wseg *wtmp;
2153ea4a95cSchristos #endif /* NOWORM */
2163ea4a95cSchristos int tmp;
21761f28255Scgd long omoves;
21861f28255Scgd int hpid;
21961f28255Scgd xchar dlvl;
22061f28255Scgd
22161f28255Scgd /* First some sanity checks */
22225ec2965Sdholland mread(fd, &hpid, sizeof(hpid));
22325ec2965Sdholland mread(fd, &dlvl, sizeof(dlvl));
22461f28255Scgd if ((pid && pid != hpid) || (lev && dlvl != lev)) {
22561f28255Scgd pline("Strange, this map is not as I remember it.");
22661f28255Scgd pline("Somebody is trying some trickery here ...");
22761f28255Scgd pline("This game is void ...");
22861f28255Scgd done("tricked");
22961f28255Scgd }
23061f28255Scgd fgold = 0;
23161f28255Scgd ftrap = 0;
23225ec2965Sdholland mread(fd, levl, sizeof(levl));
23325ec2965Sdholland mread(fd, &omoves, sizeof(omoves));
23425ec2965Sdholland mread(fd, &xupstair, sizeof(xupstair));
23525ec2965Sdholland mread(fd, &yupstair, sizeof(yupstair));
23625ec2965Sdholland mread(fd, &xdnstair, sizeof(xdnstair));
23725ec2965Sdholland mread(fd, &ydnstair, sizeof(ydnstair));
23861f28255Scgd
23961f28255Scgd fmon = restmonchn(fd);
24061f28255Scgd
24161f28255Scgd /* regenerate animals while on another level */
2423ea4a95cSchristos {
2433ea4a95cSchristos long tmoves = (moves > omoves) ? moves - omoves : 0;
2443ea4a95cSchristos struct monst *mtmp, *mtmp2;
24561f28255Scgd
24661f28255Scgd for (mtmp = fmon; mtmp; mtmp = mtmp2) {
24761f28255Scgd long newhp; /* tmoves may be very large */
24861f28255Scgd
24961f28255Scgd mtmp2 = mtmp->nmon;
2503ea4a95cSchristos if (strchr(genocided, mtmp->data->mlet)) {
25161f28255Scgd mondead(mtmp);
25261f28255Scgd continue;
25361f28255Scgd }
25461f28255Scgd if (mtmp->mtame && tmoves > 250) {
25561f28255Scgd mtmp->mtame = 0;
25661f28255Scgd mtmp->mpeaceful = 0;
25761f28255Scgd }
25861f28255Scgd newhp = mtmp->mhp +
2593ea4a95cSchristos (strchr(MREGEN, mtmp->data->mlet) ? tmoves : tmoves / 20);
26061f28255Scgd if (newhp > mtmp->mhpmax)
26161f28255Scgd mtmp->mhp = mtmp->mhpmax;
26261f28255Scgd else
26361f28255Scgd mtmp->mhp = newhp;
26461f28255Scgd }
26561f28255Scgd }
26661f28255Scgd
26761f28255Scgd setgd();
26861f28255Scgd gold = newgold();
26925ec2965Sdholland mread(fd, gold, sizeof(struct gold));
27061f28255Scgd while (gold->gx) {
27161f28255Scgd gold->ngold = fgold;
27261f28255Scgd fgold = gold;
27361f28255Scgd gold = newgold();
27425ec2965Sdholland mread(fd, gold, sizeof(struct gold));
27561f28255Scgd }
2768e73b3adSdholland free(gold);
27761f28255Scgd trap = newtrap();
27825ec2965Sdholland mread(fd, trap, sizeof(struct trap));
27961f28255Scgd while (trap->tx) {
28061f28255Scgd trap->ntrap = ftrap;
28161f28255Scgd ftrap = trap;
28261f28255Scgd trap = newtrap();
28325ec2965Sdholland mread(fd, trap, sizeof(struct trap));
28461f28255Scgd }
2858e73b3adSdholland free(trap);
28661f28255Scgd fobj = restobjchn(fd);
28761f28255Scgd billobjs = restobjchn(fd);
28861f28255Scgd rest_engravings(fd);
28961f28255Scgd #ifndef QUEST
29025ec2965Sdholland mread(fd, rooms, sizeof(rooms));
29125ec2965Sdholland mread(fd, doors, sizeof(doors));
2923ea4a95cSchristos #endif /* QUEST */
29361f28255Scgd #ifndef NOWORM
29425ec2965Sdholland mread(fd, wsegs, sizeof(wsegs));
2953ea4a95cSchristos for (tmp = 1; tmp < 32; tmp++)
2963ea4a95cSchristos if (wsegs[tmp]) {
29761f28255Scgd wheads[tmp] = wsegs[tmp] = wtmp = newseg();
29861f28255Scgd while (1) {
29925ec2965Sdholland mread(fd, wtmp, sizeof(struct wseg));
3003ea4a95cSchristos if (!wtmp->nseg)
3013ea4a95cSchristos break;
30261f28255Scgd wheads[tmp]->nseg = wtmp = newseg();
30361f28255Scgd wheads[tmp] = wtmp;
30461f28255Scgd }
30561f28255Scgd }
30625ec2965Sdholland mread(fd, wgrowtime, sizeof(wgrowtime));
3073ea4a95cSchristos #endif /* NOWORM */
30861f28255Scgd }
30961f28255Scgd
3103ea4a95cSchristos void
mread(int fd,void * buf,size_t len)31125ec2965Sdholland mread(int fd, void *buf, size_t len)
31261f28255Scgd {
31325ec2965Sdholland ssize_t rlen;
31461f28255Scgd
3153c439f43Sdholland rlen = read(fd, buf, len);
3163c439f43Sdholland if (rlen < 0 || (size_t)rlen != len) {
31725ec2965Sdholland pline("Read %zd instead of %zu bytes.\n", rlen, len);
31861f28255Scgd if (restoring) {
31961f28255Scgd (void) unlink(SAVEF);
32061f28255Scgd error("Error restoring old game.");
32161f28255Scgd }
32261f28255Scgd panic("Error reading level file.");
32361f28255Scgd }
32461f28255Scgd }
32561f28255Scgd
3263ea4a95cSchristos void
mklev(void)3271fa8a9a6Sdholland mklev(void)
32861f28255Scgd {
3293ea4a95cSchristos if (getbones())
3303ea4a95cSchristos return;
33161f28255Scgd
33261f28255Scgd in_mklev = TRUE;
33361f28255Scgd makelevel();
33461f28255Scgd in_mklev = FALSE;
33561f28255Scgd }
336