pc-hack

PC HACK 3.61 source code (archival)
git clone http://frotz.net/git/pc-hack.git
Log | Files | Refs

lev.c (12779B)


      1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
      2 /* lev.c - version 1.0.3 */
      3 
      4 #include <stdio.h>
      5 #include "hack.h"
      6 #include "mkroom.h"
      7 
      8 extern struct monst *restmonchn();
      9 extern struct obj *restobjchn();
     10 extern struct obj *billobjs;
     11 extern char *itoa();
     12 extern int hackpid;
     13 extern xchar dlevel;
     14 extern char nul[], SAVEF[];
     15 
     16 #ifndef NOWORM
     17 #include	"wseg.h"
     18 extern struct wseg *wsegs[32], *wheads[32];
     19 extern long wgrowtime[32];
     20 #endif /* NOWORM /**/
     21 
     22 #ifdef DGK
     23 struct finfo fileinfo[MAXLEVEL+1];
     24 long bytes_counted;
     25 int count_only;
     26 #else
     27 boolean level_exists[MAXLEVEL+1];
     28 #endif
     29 
     30 #ifdef DGK
     31 savelev(fd, lev, mode)
     32 int fd, mode;
     33 xchar lev;
     34 {
     35 	if (mode & COUNT) {
     36 		count_only = TRUE;
     37 		bytes_counted = 0;
     38 		savelev0(fd, lev);
     39 		while (bytes_counted > freediskspace(levels))
     40 			if (!swapout_oldest())
     41 				return FALSE;
     42 	}
     43 	if (mode & WRITE) {
     44 		count_only = FALSE;
     45 		bytes_counted = 0;
     46 		savelev0(fd, lev);
     47 	}
     48 	fileinfo[lev].where = ACTIVE;
     49 	fileinfo[lev].time = moves;
     50 	fileinfo[lev].size = bytes_counted;
     51 	return TRUE;
     52 }
     53 
     54 savelev0(fd,lev)
     55 #else
     56 savelev(fd,lev)
     57 #endif
     58 int fd;
     59 xchar lev;
     60 {
     61 #ifndef NOWORM
     62 	register struct wseg *wtmp, *wtmp2;
     63 	register tmp;
     64 #endif /* NOWORM /**/
     65 
     66 	if(fd < 0) panic("Save on bad file!");	/* impossible */
     67 #ifndef DGK
     68 	if(lev >= 0 && lev <= MAXLEVEL)
     69 		level_exists[lev] = TRUE;
     70 #endif
     71 
     72 #ifdef DGK
     73 	bwrite(fd, (char *) &vmajor, sizeof(vmajor));
     74 	bwrite(fd, (char *) &vminor, sizeof(vminor));
     75 #endif
     76 	bwrite(fd,(char *) &hackpid,sizeof(hackpid));
     77 	bwrite(fd,(char *) &lev,sizeof(lev));
     78 	bwrite(fd,(char *) levl,sizeof(levl));
     79 #ifdef DGK
     80 	bwrite(fd, (char *) &symbol, sizeof(symbol));
     81 #endif
     82 	bwrite(fd,(char *) &moves,sizeof(long));
     83 	bwrite(fd,(char *) &xupstair,sizeof(xupstair));
     84 	bwrite(fd,(char *) &yupstair,sizeof(yupstair));
     85 	bwrite(fd,(char *) &xdnstair,sizeof(xdnstair));
     86 	bwrite(fd,(char *) &ydnstair,sizeof(ydnstair));
     87 	savemonchn(fd, fmon);
     88 	savegoldchn(fd, fgold);
     89 	savetrapchn(fd, ftrap);
     90 	saveobjchn(fd, fobj);
     91 	saveobjchn(fd, billobjs);
     92 	save_engravings(fd);
     93 	bwrite(fd,(char *) rooms,sizeof(rooms));
     94 	bwrite(fd,(char *) doors,sizeof(doors));
     95 #ifndef NOWORM
     96 	bwrite(fd,(char *) wsegs,sizeof(wsegs));
     97 	for(tmp=1; tmp<32; tmp++){
     98 		for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){
     99 			wtmp2 = wtmp->nseg;
    100 			bwrite(fd,(char *) wtmp,sizeof(struct wseg));
    101 		}
    102 #ifdef DGK
    103 		if (!count_only)
    104 #endif
    105 			wsegs[tmp] = 0;
    106 	}
    107 	bwrite(fd,(char *) wgrowtime,sizeof(wgrowtime));
    108 #endif /* NOWORM /**/
    109 #ifdef DGK
    110 	if (count_only)
    111 		return;
    112 #endif
    113 	billobjs = 0;
    114 	fgold = 0;
    115 	ftrap = 0;
    116 	fmon = 0;
    117 	fobj = 0;
    118 }
    119 
    120 bwrite(fd,loc,num)
    121 register fd;
    122 register char *loc;
    123 register unsigned num;
    124 {
    125 	
    126 	bytes_counted += num;
    127 #ifdef DGK
    128 	if (!count_only)
    129 #endif
    130 		if (write(fd, loc, (unsigned) num) != num)
    131 			panic("bwrite: disk error");
    132 }
    133 
    134 saveobjchn(fd,otmp)
    135 register fd;
    136 register struct obj *otmp;
    137 {
    138 	register struct obj *otmp2;
    139 	unsigned xl;
    140 	int minusone = -1;
    141 
    142 	while(otmp) {
    143 		otmp2 = otmp->nobj;
    144 		xl = otmp->onamelth;
    145 		bwrite(fd, (char *) &xl, sizeof(int));
    146 		bwrite(fd, (char *) otmp, xl + sizeof(struct obj));
    147 #ifdef DGK
    148 		if (!count_only)
    149 #endif
    150 			free((char *) otmp);
    151 		otmp = otmp2;
    152 	}
    153 	bwrite(fd, (char *) &minusone, sizeof(int));
    154 }
    155 
    156 #ifdef MSDOS
    157 /* We don't want to save any pointers in any files, so convert
    158  * the pointers to indices before writing the monsters to disk -dgk
    159  */
    160 savemonchn(fd,mtmp)
    161 register fd;
    162 register struct monst *mtmp;
    163 {
    164 	register struct monst *mtmp2;
    165 	unsigned xl;
    166 	int minusone = -1;
    167 	struct permonst *permonstp;
    168 	int monsindex;
    169 	extern struct permonst	li_dog, dog, la_dog, hell_hound, pm_guard;
    170 	extern struct permonst	pm_eel;
    171 
    172 	while(mtmp) {
    173 		mtmp2 = mtmp->nmon;
    174 		xl = mtmp->mxlth + mtmp->mnamelth;
    175 		bwrite(fd, (char *) &xl, sizeof(int));
    176 		/* store an index where the pointer used to be */
    177 		permonstp = mtmp->data;
    178 		if (permonstp == &li_dog)
    179 			monsindex = INDEX_LITTLEDOG;
    180 		else if (permonstp == &dog)
    181 			monsindex = INDEX_DOG;
    182 		else if (permonstp == &la_dog)
    183 			monsindex = INDEX_LARGEDOG;
    184 		else if (permonstp == &hell_hound)
    185 			monsindex = INDEX_HELLHOUND;
    186 		else if (permonstp == &pm_guard)
    187 			monsindex = INDEX_GUARD;
    188 		else if (permonstp > &pm_eel || permonstp < &mons[0]) {
    189 			msmsg("Unsupported monster pointer in savemonchn\n");
    190 			goto next;
    191 		} else
    192 			monsindex = permonstp - &mons[0];
    193 		*((int *)&mtmp->data) = monsindex;
    194 		bwrite(fd, (char *) mtmp, xl + sizeof(struct monst));
    195 		mtmp->data = permonstp;		/* restore the pointer */
    196 		if(mtmp->minvent) saveobjchn(fd,mtmp->minvent);
    197 #ifdef DGK
    198 		if (!count_only)
    199 #endif
    200 			free((char *) mtmp);
    201 next:
    202 		mtmp = mtmp2;
    203 	}
    204 	bwrite(fd, (char *) &minusone, sizeof(int));
    205 }
    206 #else
    207 
    208 savemonchn(fd,mtmp)
    209 register fd;
    210 register struct monst *mtmp;
    211 {
    212 	register struct monst *mtmp2;
    213 	unsigned xl;
    214 	int minusone = -1;
    215 	struct permonst *monbegin = &mons[0];
    216 
    217 	bwrite(fd, (char *) &monbegin, sizeof(monbegin));
    218 
    219 	while(mtmp) {
    220 		mtmp2 = mtmp->nmon;
    221 		xl = mtmp->mxlth + mtmp->mnamelth;
    222 		bwrite(fd, (char *) &xl, sizeof(int));
    223 		bwrite(fd, (char *) mtmp, xl + sizeof(struct monst));
    224 		if(mtmp->minvent) saveobjchn(fd,mtmp->minvent);
    225 		free((char *) mtmp);
    226 		mtmp = mtmp2;
    227 	}
    228 	bwrite(fd, (char *) &minusone, sizeof(int));
    229 }
    230 #endif
    231 
    232 savegoldchn(fd,gold)
    233 register fd;
    234 register struct gold *gold;
    235 {
    236 	register struct gold *gold2;
    237 	while(gold) {
    238 		gold2 = gold->ngold;
    239 		bwrite(fd, (char *) gold, sizeof(struct gold));
    240 #ifdef DGK
    241 		if (!count_only)
    242 #endif
    243 			free((char *) gold);
    244 		gold = gold2;
    245 	}
    246 	bwrite(fd, nul, sizeof(struct gold));
    247 }
    248 
    249 savetrapchn(fd,trap)
    250 register fd;
    251 register struct trap *trap;
    252 {
    253 	register struct trap *trap2;
    254 	while(trap) {
    255 		trap2 = trap->ntrap;
    256 		bwrite(fd, (char *) trap, sizeof(struct trap));
    257 #ifdef DGK
    258 		if (!count_only)
    259 #endif
    260 			free((char *) trap);
    261 		trap = trap2;
    262 	}
    263 	bwrite(fd, nul, sizeof(struct trap));
    264 }
    265 
    266 getlev(fd,pid,lev)
    267 int fd,pid;
    268 xchar lev;
    269 {
    270 	register struct gold *gold;
    271 	register struct trap *trap;
    272 #ifndef NOWORM
    273 	register struct wseg *wtmp;
    274 #endif /* NOWORM /**/
    275 	register tmp;
    276 	long omoves;
    277 	int hpid;
    278 	xchar dlvl;
    279 #ifdef DGK
    280 	struct symbols osymbol;
    281 	int ovmajor, ovminor, x, y, up, dn, lt, rt;
    282 	uchar osym, nsym;
    283 #endif
    284 
    285 #ifdef MSDOS
    286 	setmode(fd,O_BINARY);
    287 #endif
    288 #ifdef DGK
    289 	/* Not yet used */
    290 	mread(fd, (char *) &ovmajor, sizeof(ovmajor));
    291 	mread(fd, (char *) &ovminor, sizeof(ovminor));
    292 #endif
    293 	/* First some sanity checks */
    294 	mread(fd, (char *) &hpid, sizeof(hpid));
    295 	mread(fd, (char *) &dlvl, sizeof(dlvl));
    296 	if((pid && pid != hpid) || (lev && dlvl != lev)) {
    297 		pline("Strange, this map is not as I remember it.");
    298 		pline("Somebody is trying some trickery here ...");
    299 		pline("This game is void ...");
    300 		done("tricked");
    301 	}
    302 
    303 	fgold = 0;
    304 	ftrap = 0;
    305 	mread(fd, (char *) levl, sizeof(levl));
    306 #ifdef DGK
    307 	/* Corners are poorly implemented.  They only exist in the
    308 	 * scrsym field of each dungeon element.  So we have to go
    309 	 * through the previous level, looking for scrsym with the
    310 	 * old corner values, checking to make sure that they are
    311 	 * where corners should be, then replace them with the scrsym
    312 	 * of the new GRAPHICS character set.  Ugly.
    313 	 */
    314 	mread(fd, (char *) &osymbol, sizeof(osymbol));
    315 	if (memcmp((char *) &osymbol, (char *) &symbol, sizeof (symbol))) {
    316 		for (x = 0; x < COLNO; x++)
    317 			for (y = 0; y < ROWNO; y++) {
    318 				osym = levl[x][y].scrsym;
    319 				nsym = 0;
    320 				switch (levl[x][y].typ) {
    321 				case 0:
    322 				case SCORR:
    323 					break;
    324 				case ROOM:
    325 					if (osym == osymbol.room)
    326 						nsym = symbol.room;
    327 					break;
    328 				case DOOR:
    329 					if (osym == osymbol.door)
    330 						nsym = symbol.door;
    331 					break;
    332 				case CORR:
    333 					if (osym == osymbol.corr)
    334 						nsym = symbol.corr;
    335 					break;
    336 				case VWALL:
    337 					if (osym == osymbol.vwall)
    338 						nsym = symbol.vwall;
    339 					break;
    340 				case SDOOR:
    341 					if (osym == osymbol.vwall)
    342 						nsym = symbol.vwall;
    343 					else if (osym == osymbol.hwall)
    344 						nsym = symbol.hwall;
    345 					break;
    346 				/* Now the ugly stuff */
    347 				case HWALL:
    348 				  up = (y > 0) ? levl[x][y-1].typ : 0;
    349 				  dn = (y < ROWNO-1) ?levl[x][y+1].typ : 0;
    350 				  lt = (x > 0) ? levl[x-1][y].typ : 0;
    351 				  rt = (x < COLNO-1) ?levl[x+1][y].typ : 0;
    352 				  up = up && (up == VWALL || up == DOOR
    353 				  	|| up == SDOOR);
    354 				  dn = dn && (dn == VWALL || dn == DOOR
    355 				  	|| dn == SDOOR);
    356 				  lt = lt && (lt == HWALL || lt == DOOR
    357 				  	|| lt == SDOOR);
    358 				  rt = rt && (rt == HWALL || rt == DOOR
    359 				  	|| rt == SDOOR);
    360 				  if (rt && dn && osym == osymbol.tlcorn)
    361 				  	nsym = symbol.tlcorn;
    362 				  else if (lt && dn && osym == osymbol.trcorn)
    363 				  	nsym = symbol.trcorn;
    364 				  else if (rt && up && osym == osymbol.blcorn)
    365 				  	nsym = symbol.blcorn;
    366 				  else if (lt && up && osym == osymbol.brcorn)
    367 				  	nsym = symbol.brcorn;
    368 				  else if (osym == osymbol.hwall)
    369 				  	nsym = symbol.hwall;
    370 				  break;
    371 				default:
    372 					break;
    373 				}
    374 				if (nsym)
    375 					levl[x][y].scrsym = nsym;
    376 			}
    377 	}
    378 #endif
    379 	mread(fd, (char *)&omoves, sizeof(omoves));
    380 	mread(fd, (char *)&xupstair, sizeof(xupstair));
    381 	mread(fd, (char *)&yupstair, sizeof(yupstair));
    382 	mread(fd, (char *)&xdnstair, sizeof(xdnstair));
    383 	mread(fd, (char *)&ydnstair, sizeof(ydnstair));
    384 
    385 	fmon = restmonchn(fd);
    386 
    387 	/* regenerate animals while on another level */
    388 	{ long tmoves = (moves > omoves) ? moves-omoves : 0;
    389 	  register struct monst *mtmp, *mtmp2;
    390 	  extern char genocided[];
    391 
    392 	  for(mtmp = fmon; mtmp; mtmp = mtmp2) {
    393 		long newhp;		/* tmoves may be very large */
    394 
    395 		mtmp2 = mtmp->nmon;
    396 		if(index(genocided, mtmp->data->mlet)) {
    397 			mondead(mtmp);
    398 			continue;
    399 		}
    400 
    401 		if(mtmp->mtame && tmoves > 250) {
    402 			mtmp->mtame = 0;
    403 			mtmp->mpeaceful = 0;
    404 		}
    405 
    406 		newhp = mtmp->mhp +
    407 			(index(MREGEN, mtmp->data->mlet) ? tmoves : tmoves/20);
    408 		if(newhp > mtmp->mhpmax)
    409 			mtmp->mhp = mtmp->mhpmax;
    410 		else
    411 			mtmp->mhp = newhp;
    412 	  }
    413 	}
    414 
    415 	setgd();
    416 	gold = newgold();
    417 	mread(fd, (char *)gold, sizeof(struct gold));
    418 	while(gold->gx) {
    419 		gold->ngold = fgold;
    420 		fgold = gold;
    421 		gold = newgold();
    422 		mread(fd, (char *)gold, sizeof(struct gold));
    423 	}
    424 	free((char *) gold);
    425 	trap = newtrap();
    426 	mread(fd, (char *)trap, sizeof(struct trap));
    427 	while(trap->tx) {
    428 		trap->ntrap = ftrap;
    429 		ftrap = trap;
    430 		trap = newtrap();
    431 		mread(fd, (char *)trap, sizeof(struct trap));
    432 	}
    433 	free((char *) trap);
    434 	fobj = restobjchn(fd);
    435 	billobjs = restobjchn(fd);
    436 	rest_engravings(fd);
    437 	mread(fd, (char *)rooms, sizeof(rooms));
    438 	mread(fd, (char *)doors, sizeof(doors));
    439 #ifndef NOWORM
    440 	mread(fd, (char *)wsegs, sizeof(wsegs));
    441 	for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){
    442 		wheads[tmp] = wsegs[tmp] = wtmp = newseg();
    443 		while(1) {
    444 			mread(fd, (char *)wtmp, sizeof(struct wseg));
    445 			if(!wtmp->nseg) break;
    446 			wheads[tmp]->nseg = wtmp = newseg();
    447 			wheads[tmp] = wtmp;
    448 		}
    449 	}
    450 	mread(fd, (char *)wgrowtime, sizeof(wgrowtime));
    451 #endif /* NOWORM /**/
    452 }
    453 
    454 mread(fd, buf, len)
    455 register fd;
    456 register char *buf;
    457 register unsigned len;
    458 {
    459 	register int rlen;
    460 	extern boolean restoring;
    461 
    462 	rlen = read(fd, buf, (int) len);
    463 	if(rlen != len){
    464 		pline("Read %d instead of %u bytes.\n", rlen, len);
    465 		if(restoring) {
    466 			(void) unlink(SAVEF);
    467 			error("Error restoring old game.");
    468 		}
    469 		panic("Error reading level file.");
    470 	}
    471 }
    472 
    473 mklev()
    474 {
    475 	extern boolean in_mklev;
    476 
    477 	if(getbones()) return;
    478 
    479 	in_mklev = TRUE;
    480 	makelevel();
    481 	in_mklev = FALSE;
    482 }
    483 
    484 
    485 #ifdef DGK
    486 swapin_file(lev) {
    487 	char to[PATHLEN], from[PATHLEN];
    488 
    489 	sprintf(from, "%s%s", permbones, alllevels);
    490 	sprintf(to, "%s%s", levels, alllevels);
    491 	name_file(from, lev);
    492 	name_file(to, lev);
    493 	while (fileinfo[lev].size > freediskspace(to)) 
    494 		if (!swapout_oldest())
    495 			return FALSE;
    496 #ifdef WIZARD
    497 	if (wizard) {
    498 		pline("Swapping in `%s'", from);
    499 		fflush(stdout);
    500 	}
    501 #endif
    502 	copyfile(from, to);
    503 	(void) unlink(from);
    504 	fileinfo[lev].where = ACTIVE;
    505 	return TRUE;
    506 }
    507 
    508 
    509 swapout_oldest() {
    510 	char to[PATHLEN], from[PATHLEN];
    511 	int i, oldest;
    512 	long oldtime;
    513 
    514 	if (!ramdisk)
    515 		return FALSE;
    516 	for (i = 1, oldtime = 0, oldest = 0; i <= maxdlevel; i++)
    517 		if (fileinfo[i].where == ACTIVE
    518 		&& (!oldtime || fileinfo[i].time < oldtime)) {
    519 			oldest = i;
    520 			oldtime = fileinfo[i].time;
    521 		}
    522 	if (!oldest)
    523 		return FALSE;
    524 	sprintf(from, "%s%s", levels, alllevels);
    525 	sprintf(to, "%s%s", permbones, alllevels);
    526 	name_file(from, oldest);
    527 	name_file(to, oldest);
    528 #ifdef WIZARD
    529 	if (wizard) {
    530 		pline("Swapping out `%s'.", from);
    531 		fflush(stdout);
    532 	}
    533 #endif
    534 	copyfile(from, to);
    535 	unlink(from);
    536 	fileinfo[oldest].where = SWAPPED;
    537 	return TRUE;
    538 }
    539 
    540 copyfile(from, to)
    541 char *from, *to;
    542 {
    543 	char buf[BUFSIZ];
    544 	int nfrom, nto, fdfrom, fdto;
    545 
    546 	if ((fdfrom = open(from, O_RDONLY | O_BINARY | O_CREAT, FMASK)) < 0)
    547 		panic("Can't copy from %s !?", from);
    548 	if ((fdto = open(to, O_WRONLY | O_BINARY | O_CREAT, FMASK)) < 0)
    549 		panic("Can't copy to %s", to);
    550 	do {
    551 		nfrom = read(fdfrom, buf, BUFSIZ);
    552 		nto = write(fdto, buf, nfrom);
    553 		if (nto != nfrom)
    554 			panic("Copyfile failed!");
    555 	} while (nfrom == BUFSIZ);
    556 	close(fdfrom);
    557 	close(fdto);
    558 }
    559 #endif