Source:NetHack 2.2a/save.c

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

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

1.   /*	SCCS Id: @(#)save.c	2.1	87/10/07 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.     4.    #include   5.    #include   6.    #include "hack.h"  7.    extern char genocided[60];		/* defined in Decl.c */ 8.   extern char fut_geno[60];		/* idem */ 9.   extern struct permonst	pm_wizard;	/* since the wizard evolves */ 10.   11.   extern char SAVEF[], nul[]; 12.  extern char pl_character[PL_CSIZ]; 13.  extern long lseek; 14.  extern struct obj *restobjchn; 15.  extern struct monst *restmonchn; 16.   17.   dosave{ 18.  	clear_screen; 19.  	fflush(stdout); 20.  	if(dosave0(0)) { 21.  		settty("Be seeing you ...\n"); 22.  		exit(0); 23.  	}  24.   #ifdef LINT 25.  	return(0); 26.  #endif 27.  }  28.    29.   #ifndef NOSAVEONHANGUP 30.  hangup{ 31.  	(void) dosave0(1); 32.  	exit(1); 33.  }  34.   #endif 35.   36.   /* returns 1 if save successful */ 37.  dosave0(hu) int hu; { 38.  	register fd, ofd; 39.  	int tmp;		/* not register ! */ 40.   #ifdef DGK 41.  	long fds, needed; 42.  	extern long bytes_counted; 43.  	int mode; 44.  #endif 45.  #ifdef UNIX 46.  	(void) signal(SIGHUP, SIG_IGN); 47.  #endif 48.  #ifndef __TURBOC__ 49.  	(void) signal(SIGINT, SIG_IGN); 50.  #endif 51.  #ifdef DGK 52.  	if (!saveDiskPrompt(0)) 53.  		return 0; 54.  	fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT, FMASK); 55.  #else 56.  	fd = creat(SAVEF, FMASK); 57.  #endif 58.  	if(fd < 0) { 59.  		if(!hu) pline("Cannot open save file. (Continue or Quit)"); 60.  		(void) unlink(SAVEF);		/* ab@unido */ 61.  		return(0); 62.  	}  63.   	if(flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */ 64.  		u.uluck--;			/* and unido!ab */ 65.  #ifdef DGKMOD 66.  	home; 67.  	cl_end; 68.  #endif 69.  #ifdef DGK 70.  	msmsg("Saving: "); 71.  	mode = COUNT; 72.  again: 73.  	savelev(fd, dlevel, mode); 74.  	/* count_only will be set properly by savelev */ 75.  #else 76.  	savelev(fd,dlevel); 77.  #endif 78.  	saveobjchn(fd, invent); 79.  	saveobjchn(fd, fcobj); 80.  	savemonchn(fd, fallen_down); 81.  	tmp = getuid; 82.  	bwrite(fd, (char *) &tmp, sizeof tmp); 83.  	bwrite(fd, (char *) &flags, sizeof(struct flag)); 84.  	bwrite(fd, (char *) &dlevel, sizeof dlevel); 85.  	bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel); 86.  	bwrite(fd, (char *) &moves, sizeof moves); 87.  	bwrite(fd, (char *) &u, sizeof(struct you)); 88.  #ifdef SPELLS 89.  	bwrite(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); 90.  #endif 91.  	if(u.ustuck) 92.  		bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id); 93.  	bwrite(fd, (char *) pl_character, sizeof pl_character); 94.  	bwrite(fd, (char *) genocided, sizeof genocided); 95.  	bwrite(fd, (char *) fut_geno, sizeof fut_geno); 96.  #ifdef HARD 97.  	bwrite(fd, (char *) &pm_wizard, sizeof(struct permonst)); 98.  #endif 99.  	savenames(fd); 100. #ifdef DGK 101. 	if (mode == COUNT) { 102. 		/* make sure there is enough disk space */ 103. 		needed = bytes_counted; 104. 		for (tmp = 1; tmp <= maxdlevel; tmp++) 105. 			if (tmp != dlevel && fileinfo[tmp].where) 106. 				needed += fileinfo[tmp].size + (sizeof tmp); 107. 		fds = freediskspace(SAVEF); 108. 		if (needed > fds) { 109. 			pline("There is insufficient space on SAVE disk."); 110. 			pline("Require %ld bytes but only have %ld.", needed,  111.  				fds); 112. 			flushout; 113. 			(void) close(fd); 114. 			(void) unlink(SAVEF); 115. 			return 0; 116. 		}  117.  		mode = WRITE; 118. 		goto again; 119. 	}  120.  #endif 121. 	for(tmp = 1; tmp <= maxdlevel; tmp++) { 122. 		extern int hackpid; 123. #ifdef DGK 124. 		if (tmp == dlevel || !fileinfo[tmp].where) continue; 125. 		if (fileinfo[tmp].where != ACTIVE) 126. 			swapin_file(tmp); 127. #else 128. 		extern boolean level_exists[]; 129.  130.  		if(tmp == dlevel || !level_exists[tmp]) continue; 131. #endif 132. 		glo(tmp); 133. #ifdef DGK 134. 		msmsg("."); 135. #endif 136. 		if((ofd = open(lock, 0)) < 0) { 137. 		    if(!hu) pline("Error while saving: cannot read %s.", lock); 138. 		    (void) close(fd); 139. 		    (void) unlink(SAVEF); 140. 		    if(!hu) done("tricked"); 141. 		    return(0); 142. 		}  143.  		getlev(ofd, hackpid, tmp); 144. 		(void) close(ofd); 145. 		bwrite(fd, (char *) &tmp, sizeof tmp);	/* level number */ 146. #ifdef DGK 147. 		savelev(fd,tmp,WRITE);			/* actual level */ 148. #else 149. 		savelev(fd,tmp);			/* actual level */ 150. #endif 151. 		(void) unlink(lock); 152. 	}  153.  	(void) close(fd); 154. 	glo(dlevel); 155. 	(void) unlink(lock);	/* get rid of current level --jgm */ 156. 	glo(0); 157. 	(void) unlink(lock); 158. 	return(1); 159. }  160.   161.  dorecover(fd) 162. register fd; 163. {  164.  	register nfd; 165. 	int tmp;		/* not a register ! */ 166.  	unsigned mid;		/* idem */ 167. 	struct obj *otmp; 168. 	extern boolean restoring; 169. #ifdef DGK 170. 	struct flag oldflags; 171.  172.  	oldflags = flags;	/* Save flags set in the config file */ 173. #endif 174. 	restoring = TRUE; 175. 	getlev(fd, 0, 0); 176. 	invent = restobjchn(fd); 177. 	for(otmp = invent; otmp; otmp = otmp->nobj) 178. 		if(otmp->owornmask) 179. 			setworn(otmp, otmp->owornmask); 180. 	fcobj = restobjchn(fd); 181. 	fallen_down = restmonchn(fd); 182. 	mread(fd, (char *) &tmp, sizeof tmp); 183. #ifdef WIZARD 184. 	if(!wizard) 185. #endif 186. 	    if(tmp != getuid) {		/* strange ... */ 187.  		(void) close(fd); 188. 		(void) unlink(SAVEF); 189. 		puts("Saved game was not yours."); 190. 		restoring = FALSE; 191. 		return(0); 192. 	    }  193.  	mread(fd, (char *) &flags, sizeof(struct flag)); 194. #ifdef DGK 195. 	/* Some config file OPTIONS take precedence over those in save file. 196. 	 */  197.  	flags.rawio = oldflags.rawio; 198. 	flags.DECRainbow = oldflags.DECRainbow; 199. 	flags.IBMBIOS = oldflags.IBMBIOS; 200. #endif 201. 	mread(fd, (char *) &dlevel, sizeof dlevel); 202. 	mread(fd, (char *) &maxdlevel, sizeof maxdlevel); 203. 	mread(fd, (char *) &moves, sizeof moves); 204. 	mread(fd, (char *) &u, sizeof(struct you)); 205. #ifdef SPELLS 206. 	mread(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); 207. #endif 208. 	if(u.ustuck) 209. 		mread(fd, (char *) &mid, sizeof mid); 210. 	mread(fd, (char *) pl_character, sizeof pl_character); 211. 	mread(fd, (char *) genocided, sizeof genocided); 212. 	mread(fd, (char *) fut_geno, sizeof fut_geno); 213. #ifdef HARD 214. 	mread(fd, (char *) &pm_wizard, sizeof(struct permonst)); 215. #endif 216. 	restnames(fd); 217. #ifdef DGK 218. 	msmsg("\n"); 219. 	cl_end; 220. 	msmsg("You got as far as level %d%s.\n", maxdlevel,  221.  		flags.debug ? " in WIZARD mode" : ""); 222. 	cl_end; 223. 	msmsg("Restoring: "); 224. #endif 225. 	while(1) { 226. 		if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp) 227. 			break; 228. 		getlev(fd, 0, tmp); 229. 		glo(tmp); 230. #ifdef DGK 231. 		msmsg("."); 232. 		nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK); 233. #else 234. 		nfd = creat(lock, FMASK); 235. #endif 236. 		if (nfd < 0)	panic("Cannot open temp file %s!\n", lock); 237. #ifdef DGK 238. 		if (!savelev(nfd, tmp, COUNT | WRITE)) { 239.  240.  			/* The savelev can't proceed because the size required 241. 			 * is greater than the available disk space. 242. 			 */  243.  			msmsg("\nNot enough space on `%s' to restore your game.\n",  244.  				levels); 245.  246.  			/* Remove levels and bones that may have been created. 247. 			 */  248.  			(void) close(nfd); 249. 			eraseall(levels, alllevels); 250. 			eraseall(levels, allbones); 251.  252.  			/* Perhaps the person would like to play without a  253. * RAMdisk. 254. 			 */  255.  			if (ramdisk) { 256. 				/* PlaywoRAMdisk may not return, but if it does 257. 				 * it is certain that ramdisk will be 0. 258. 				 */  259.  				playwoRAMdisk; 260. 				(void) lseek(fd, 0L, 0); /* Rewind save file */ 261. 				return dorecover(fd);	 /* and try again */ 262. 			} else { 263. 				msmsg("Be seeing you ...\n"); 264. 				exit(0); 265. 			}  266.  		}  267.  #else 268. 		savelev(nfd,tmp); 269. #endif 270. 		(void) close(nfd); 271. 	}  272.  	(void) lseek(fd, 0L, 0); 273. 	getlev(fd, 0, 0); 274. 	(void) close(fd); 275. 	(void) unlink(SAVEF); 276. 	if(Punished) { 277. 		for(otmp = fobj; otmp; otmp = otmp->nobj) 278. 			if(otmp->olet == CHAIN_SYM) goto chainfnd; 279. 		panic("Cannot find the iron chain?"); 280. 	chainfnd: 281. 		uchain = otmp; 282. 		if(!uball){ 283. 			for(otmp = fobj; otmp; otmp = otmp->nobj) 284. 				if(otmp->olet == BALL_SYM && otmp->spe) 285. 					goto ballfnd; 286. 			panic("Cannot find the iron ball?"); 287. 		ballfnd: 288. 			uball = otmp; 289. 		}  290.  	}  291.  	if(u.ustuck) { 292. 		register struct monst *mtmp; 293.  294.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 295. 			if(mtmp->m_id == mid) goto monfnd; 296. 		panic("Cannot find the monster ustuck."); 297. 	monfnd: 298. 		u.ustuck = mtmp; 299. 	}  300.  #ifndef QUEST 301. 	setsee;  /* only to recompute seelx etc. - these weren't saved */ 302. #endif 303. #ifdef DGK 304. 	gameDiskPrompt; 305. #endif 306. 	docrt; 307. 	restoring = FALSE; 308. 	return(1); 309. }  310.   311.  struct obj * 312. restobjchn(fd) 313. register fd; 314. {  315.  	register struct obj *otmp, *otmp2; 316. 	register struct obj *first = 0; 317. 	int xl; 318. #ifdef LINT 319. 	/* suppress "used before set" warning from lint */ 320. 	otmp2 = 0; 321. #endif 322. 	while(1) { 323. 		mread(fd, (char *) &xl, sizeof(xl)); 324. 		if(xl == -1) break; 325. 		otmp = newobj(xl); 326. 		if(!first) first = otmp; 327. 		else otmp2->nobj = otmp; 328. 		mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj)); 329. 		if(!otmp->o_id) otmp->o_id = flags.ident++; 330. 		otmp2 = otmp; 331. 	}  332.  	if(first && otmp2->nobj){ 333. 		impossible("Restobjchn: error reading objchn."); 334. 		otmp2->nobj = 0; 335. 	}  336.  	return(first); 337. }  338.  #ifdef MSDOS 339. struct monst * 340. restmonchn(fd) 341. register fd; 342. {  343.  	register struct monst *mtmp, *mtmp2; 344. 	register struct monst *first = 0; 345. 	int xl; 346. 	int monsindex, mi; 347. 	extern struct permonst li_dog, dog, la_dog; 348. #ifdef KAA 349. 	extern struct permonst hell_hound; 350. # ifdef HARD 351. 	extern struct permonst d_lord, d_prince; 352. # endif 353. # ifdef KJSMODS 354. 	extern struct permonst pm_guard, pm_ghost, pm_eel; 355. # endif 356. #endif 357.  358.  #ifdef lint 359. 	/* suppress "used before set" warning from lint */ 360. 	mtmp2 = 0; 361. #endif /* lint /**/ 362. 	while(1) { 363. 		mread(fd, (char *) &xl, sizeof(xl)); 364. 		if(xl == -1) break; 365. 		mtmp = newmonst(xl); 366. 		if(!first) first = mtmp; 367. 		else mtmp2->nmon = mtmp; 368. 		mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); 369. 		if(!mtmp->m_id) 370. 			mtmp->m_id = flags.ident++; 371. 		monsindex = *((int *)&mtmp->data); 372. 		if (monsindex == (mi = -1))	/* Special fake index */ 373. 			mtmp->data = &li_dog; 374. 		else if (monsindex == --mi)	/* Special fake index */ 375. 			mtmp->data = &dog; 376. 		else if (monsindex == --mi)	/* Special fake index */ 377. 			mtmp->data = &la_dog; 378. #ifdef KAA 379. 		else if (monsindex == --mi) 380. 			mtmp->data = &hell_hound; 381. # ifdef HARD 382. 		else if (monsindex == --mi) 383. 			mtmp->data = &d_lord; 384.  385.  		else if (monsindex == --mi) 386. 			mtmp->data = &d_prince; 387. # endif 388. # ifdef KJSMODS 389. 		else if (monsindex == --mi) 390. 			mtmp->data = &pm_guard; 391.  392.  		else if (monsindex == --mi) 393. 			mtmp->data = &pm_ghost; 394.  395.  		else if (monsindex == --mi) 396. 			mtmp->data = &pm_eel; 397. # endif 398. #endif 399. 		else 400. 			mtmp->data = &mons[monsindex]; 401. 		if(mtmp->minvent) 402. 			mtmp->minvent = restobjchn(fd); 403. 		mtmp2 = mtmp; 404. 	}  405.  	if(first && mtmp2->nmon){ 406. 		impossible("Restmonchn: error reading monchn."); 407. 		mtmp2->nmon = 0; 408. 	}  409.  	return(first); 410. }  411.  #else 412. struct monst * 413. restmonchn(fd) 414. register fd; 415. {  416.  	register struct monst *mtmp, *mtmp2; 417. 	register struct monst *first = 0; 418. 	int xl; 419.  420.  	struct permonst *monbegin; 421. 	long differ; 422.  423.  	mread(fd, (char *)&monbegin, sizeof(monbegin)); 424. 	differ = (char *)(&mons[0]) - (char *)(monbegin); 425.  426.  #ifdef LINT 427. 	/* suppress "used before set" warning from lint */ 428. 	mtmp2 = 0; 429. #endif 430. 	while(1) { 431. 		mread(fd, (char *) &xl, sizeof(xl)); 432. 		if(xl == -1) break; 433. 		mtmp = newmonst(xl); 434. 		if(!first) first = mtmp; 435. 		else mtmp2->nmon = mtmp; 436. 		mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); 437. 		if(!mtmp->m_id) 438. 			mtmp->m_id = flags.ident++; 439. 		mtmp->data = (struct permonst *) 440. 			((char *) mtmp->data + differ); 441. 		if(mtmp->minvent) 442. 			mtmp->minvent = restobjchn(fd); 443. 		mtmp2 = mtmp; 444. 	}  445.  	if(first && mtmp2->nmon){ 446. 		impossible("Restmonchn: error reading monchn."); 447. 		mtmp2->nmon = 0; 448. 	}  449.  	return(first); 450. }  451.  #endif