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