Source:NetHack 1.3d/save.c

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