Source:NetHack 1.4f/save.c

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