Source:NetHack 2.2a/lev.c

Below is the full text to lev.c from the source code of NetHack 2.2a. To link to a particular line, write [[NetHack 2.2a/lev.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

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