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