Source:NetHack 2.3e/save.c

Below is the full text to save.c from the source code of NetHack 2.3e. To link to a particular line, write [[NetHack 2.3e/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.3	88/01/24 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.     4.    #include   5.    #include   6.    #include "hack.h"  7. 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.  		change_luck(-1);		/* 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. #ifdef WIZARD 185. 	if(!wizard) 186. #endif 187. 	    if(tmp != getuid) {		/* strange ... */ 188.  		(void) close(fd); 189. 		(void) unlink(SAVEF); 190. 		puts("Saved game was not yours."); 191. 		restoring = FALSE; 192. 		return(0); 193. 	    }  194.  	mread(fd, (char *) &flags, sizeof(struct flag)); 195. #ifdef DGK 196. 	/* Some config file OPTIONS take precedence over those in save file. 197. 	 */  198.  	flags.rawio = oldflags.rawio; 199. 	flags.DECRainbow = oldflags.DECRainbow; 200. 	flags.IBMBIOS = oldflags.IBMBIOS; 201. #endif 202. 	mread(fd, (char *) &dlevel, sizeof dlevel); 203. 	mread(fd, (char *) &maxdlevel, sizeof maxdlevel); 204. 	mread(fd, (char *) &moves, sizeof moves); 205. 	mread(fd, (char *) &u, sizeof(struct you)); 206. #ifdef SPELLS 207. 	mread(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); 208. #endif 209. 	if(u.ustuck) 210. 		mread(fd, (char *) &mid, sizeof mid); 211. 	mread(fd, (char *) pl_character, sizeof pl_character); 212. 	mread(fd, (char *) genocided, sizeof genocided); 213. 	mread(fd, (char *) fut_geno, sizeof fut_geno); 214. #ifdef HARD 215. 	{  216.  	/* Save name pointer from being munged -- tom@uw-warp */ 217. 	char *name = pm_wizard.mname; 218. 	mread(fd, (char *) &pm_wizard, sizeof(struct permonst)); 219. 	pm_wizard.mname = name; 220. 	}  221.  #endif 222. 	restnames(fd); 223. #ifdef DGK 224. 	msmsg("\n"); 225. 	cl_end; 226. 	msmsg("You got as far as level %d%s.\n", maxdlevel,  227.  		flags.debug ? " in WIZARD mode" : ""); 228. 	cl_end; 229. 	msmsg("Restoring: "); 230. #endif 231. 	while(1) { 232. 		if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp) 233. 			break; 234. 		getlev(fd, 0, tmp); 235. 		glo(tmp); 236. #ifdef DGK 237. 		msmsg("."); 238. 		nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK); 239. #else 240. 		nfd = creat(lock, FMASK); 241. #endif 242. 		if (nfd < 0)	panic("Cannot open temp file %s!\n", lock); 243. #ifdef DGK 244. 		if (!savelev(nfd, tmp, COUNT | WRITE)) { 245.  246.  			/* The savelev can't proceed because the size required 247. 			 * is greater than the available disk space. 248. 			 */  249.  			msmsg("\nNot enough space on `%s' to restore your game.\n",  250.  				levels); 251.  252.  			/* Remove levels and bones that may have been created. 253. 			 */  254.  			(void) close(nfd); 255. 			eraseall(levels, alllevels); 256. 			eraseall(levels, allbones); 257.  258.  			/* Perhaps the person would like to play without a  259. * RAMdisk. 260. 			 */  261.  			if (ramdisk) { 262. 				/* PlaywoRAMdisk may not return, but if it does 263. 				 * it is certain that ramdisk will be 0. 264. 				 */  265.  				playwoRAMdisk; 266. 				(void) lseek(fd, 0L, 0); /* Rewind save file */ 267. 				return dorecover(fd);	 /* and try again */ 268. 			} else { 269. 				msmsg("Be seeing you ...\n"); 270. 				exit(0); 271. 			}  272.  		}  273.  #else 274. 		savelev(nfd,tmp); 275. #endif 276. 		(void) close(nfd); 277. 	}  278.  	(void) lseek(fd, 0L, 0); 279. 	getlev(fd, 0, 0); 280. 	(void) close(fd); 281. 	(void) unlink(SAVEF); 282. 	if(Punished) { 283. 		for(otmp = fobj; otmp; otmp = otmp->nobj) 284. 			if(otmp->olet == CHAIN_SYM) goto chainfnd; 285. 		panic("Cannot find the iron chain?"); 286. 	chainfnd: 287. 		uchain = otmp; 288. 		if(!uball){ 289. 			for(otmp = fobj; otmp; otmp = otmp->nobj) 290. 				if(otmp->olet == BALL_SYM && otmp->spe) 291. 					goto ballfnd; 292. 			panic("Cannot find the iron ball?"); 293. 		ballfnd: 294. 			uball = otmp; 295. 		}  296.  	}  297.  	if(u.ustuck) { 298. 		register struct monst *mtmp; 299.  300.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 301. 			if(mtmp->m_id == mid) goto monfnd; 302. 		panic("Cannot find the monster ustuck."); 303. 	monfnd: 304. 		u.ustuck = mtmp; 305. 	}  306.  #ifndef QUEST 307. 	setsee;  /* only to recompute seelx etc. - these weren't saved */ 308. #endif 309. #ifdef DGK 310. 	gameDiskPrompt; 311. #endif 312. 	docrt; 313. 	restoring = FALSE; 314. 	return(1); 315. }  316.   317.  struct obj * 318. restobjchn(fd) 319. register fd; 320. {  321.  	register struct obj *otmp, *otmp2; 322. 	register struct obj *first = 0; 323. 	int xl; 324. #ifdef LINT 325. 	/* suppress "used before set" warning from lint */ 326. 	otmp2 = 0; 327. #endif 328. 	while(1) { 329. 		mread(fd, (char *) &xl, sizeof(xl)); 330. 		if(xl == -1) break; 331. 		otmp = newobj(xl); 332. 		if(!first) first = otmp; 333. 		else otmp2->nobj = otmp; 334. 		mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj)); 335. 		if(!otmp->o_id) otmp->o_id = flags.ident++; 336. 		otmp2 = otmp; 337. 	}  338.  	if(first && otmp2->nobj){ 339. 		impossible("Restobjchn: error reading objchn."); 340. 		otmp2->nobj = 0; 341. 	}  342.  	return(first); 343. }  344.   345.  struct monst * 346. restmonchn(fd) 347. register fd; 348. {  349.  	register struct monst *mtmp, *mtmp2; 350. 	register struct monst *first = 0; 351. 	int xl; 352.  353.  	struct permonst *monbegin; 354. 	long differ; 355.  356.  	mread(fd, (char *)&monbegin, sizeof(monbegin)); 357. #ifndef MSDOS 358. 	differ = (char *)(&mons[0]) - (char *)(monbegin); 359. #else 360. 	differ = (long)(&mons[0]) - (long)(monbegin); 361. #endif 362.  363.  #ifdef LINT 364. 	/* suppress "used before set" warning from lint */ 365. 	mtmp2 = 0; 366. #endif 367. 	while(1) { 368. 		mread(fd, (char *) &xl, sizeof(xl)); 369. 		if(xl == -1) break; 370. 		mtmp = newmonst(xl); 371. 		if(!first) first = mtmp; 372. 		else mtmp2->nmon = mtmp; 373. 		mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); 374. 		if(!mtmp->m_id) 375. 			mtmp->m_id = flags.ident++; 376. #ifndef MSDOS 377. 		mtmp->data = (struct permonst *) 378. 			((char *) mtmp->data + differ); 379. #else 380. 		mtmp->data = (struct permonst *) 381. 			((long) mtmp->data + differ); 382. #endif 383. 		if(mtmp->minvent) 384. 			mtmp->minvent = restobjchn(fd); 385. 		mtmp2 = mtmp; 386. 	}  387.  	if(first && mtmp2->nmon){ 388. 		impossible("Restmonchn: error reading monchn."); 389. 		mtmp2->nmon = 0; 390. 	}  391.  	return(first); 392. }