About: Source:NetHack 3.1.0/mkmaze.c   Sponge Permalink

An Entity of Type : owl:Thing, within Data Space : 134.155.108.49:8890 associated with source dataset(s)

Below is the full text to mkmaze.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/mkmaze.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code

AttributesValues
rdfs:label
  • Source:NetHack 3.1.0/mkmaze.c
rdfs:comment
  • Below is the full text to mkmaze.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/mkmaze.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code
dcterms:subject
dbkwik:nethack/pro...iPageUsesTemplate
abstract
  • Below is the full text to mkmaze.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/mkmaze.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)mkmaze.c 3.1 93/01/17 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "sp_lev.h" 7. 8. #define UP 1 9. #define DOWN 0 10. 11. /* from sp_lev.c, for fixup_special() */ 12. extern char *lev_message; 13. extern lev_region *lregions; 14. extern int num_lregions; 15. 16. static int FDECL(iswall,(int,int)); 17. static boolean FDECL(okay,(int,int,int)); 18. static void FDECL(maze0xy,(coord *)); 19. static boolean FDECL(put_lregion_here,(XCHAR_P,XCHAR_P,XCHAR_P, 20. XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P,BOOLEAN_P,d_level *)); 21. static void NDECL(fixup_special); 22. static void NDECL(setup_waterlevel); 23. static void NDECL(unsetup_waterlevel); 24. 25. static int 26. iswall(x,y) 27. int x,y; 28. { 29. if (x<=0 || y<0 || x>COLNO-1 || y>ROWNO-1) 30. return 0; 31. return (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ) 32. || levl[x][y].typ == SDOOR); 33. } 34. 35. void 36. wallification(x1, y1, x2, y2) 37. int x1, y1, x2, y2; 38. { 39. uchar type; 40. short x,y; 41. register struct rm *lev; 42. 43. if (x1 < 0) x1 = 0; 44. if (x2 < x1) x2 = x1; 45. if (x2 > COLNO-1) x2 = COLNO-1; 46. if (x1 > x2) x1 = x2; 47. if (y1 < 0) y1 = 0; 48. if (y2 < y1) y2 = y1; 49. if (y2 > ROWNO-1) y2 = ROWNO-1; 50. if (y1 > y2) y1 = y2; 51. for(x = x1; x <= x2; x++) 52. for(y = y1; y <= y2; y++) { 53. lev = &levl[x][y]; 54. type = lev->typ; 55. if (iswall(x,y)) { 56. if (IS_DOOR(type) || type == SDOOR || type == DBWALL) 57. continue; 58. else 59. if (iswall(x,y-1)) 60. if (iswall(x,y+1)) 61. if (iswall(x-1,y)) 62. if (iswall(x+1,y)) 63. lev->typ = CROSSWALL; 64. else 65. lev->typ = TLWALL; 66. else 67. if (iswall(x+1,y)) 68. lev->typ = TRWALL; 69. else 70. lev->typ = VWALL; 71. else 72. if (iswall(x-1,y)) 73. if (iswall(x+1,y)) 74. lev->typ = TUWALL; 75. else 76. lev->typ = BRCORNER; 77. else 78. if (iswall(x+1,y)) 79. lev->typ = BLCORNER; 80. else 81. lev->typ = VWALL; 82. else 83. if (iswall(x,y+1)) 84. if (iswall(x-1,y)) 85. if (iswall(x+1,y)) 86. lev->typ = TDWALL; 87. else 88. lev->typ = TRCORNER; 89. else 90. if (iswall(x+1,y)) 91. lev->typ = TLCORNER; 92. else 93. lev->typ = VWALL; 94. else 95. lev->typ = HWALL; 96. } 97. } 98. } 99. 100. static boolean 101. okay(x,y,dir) 102. int x,y; 103. register int dir; 104. { 105. move(&x,&y,dir); 106. move(&x,&y,dir); 107. if(x<3 || y<3 || x>x_maze_max || y>y_maze_max || levl[x][y].typ != 0) 108. return(FALSE); 109. return(TRUE); 110. } 111. 112. static void 113. maze0xy(cc) /* find random starting point for maze generation */ 114. coord *cc; 115. { 116. cc->x = 3 + 2*rn2((x_maze_max>>1) - 1); 117. cc->y = 3 + 2*rn2((y_maze_max>>1) - 1); 118. return; 119. } 120. 121. /* 122. * Bad if: 123. * pos is occupied OR 124. * pos is inside restricted region (lx,ly,hx,hy) OR 125. * NOT (pos is corridor and a maze level OR pos is a room OR pos is air) 126. */ 127. boolean 128. bad_location(x, y, lx, ly, hx, hy) 129. xchar x, y; 130. xchar lx, ly, hx, hy; 131. { 132. return(occupied(x, y) || 133. ((x >= lx) && (x <= hx) && (y >= ly) && (y <= hy)) || 134. !((levl[x][y].typ == CORR && level.flags.is_maze_lev) || 135. levl[x][y].typ == ROOM || levl[x][y].typ == AIR)); 136. } 137. 138. /* pick a location in area (lx, ly, hx, hy) but not in (nlx, nly, nhx, nhy) */ 139. /* and place something (based on rtype) in that region */ 140. void 141. place_lregion(lx, ly, hx, hy, nlx, nly, nhx, nhy, rtype, lev) 142. xchar lx, ly, hx, hy; 143. xchar nlx, nly, nhx, nhy; 144. xchar rtype; 145. d_level *lev; 146. { 147. int trycnt; 148. boolean oneshot; 149. xchar x, y; 150. 151. if(!lx) { /* default to whole level */ 152. /* 153. * if there are rooms and this a branch, let place_branch choose 154. * the branch location (to avoid putting branches in corridors). 155. */ 156. if(rtype == LR_BRANCH && nroom) { 157. place_branch(Is_branchlev(&u.uz), 0, 0); 158. return; 159. } 160. 161. lx = 1; hx = COLNO-1; 162. ly = 1; hy = ROWNO-1; 163. } 164. 165. /* first a probabilistic approach */ 166. 167. oneshot = (lx == hx && ly == hy); 168. for(trycnt = 0; trycnt < 100; trycnt ++) { 169. 170. x = rn1((hx - lx) + 1, lx); 171. y = rn1((hy - ly) + 1, ly); 172. 173. if (put_lregion_here(x,y,nlx,nly,nhx,nhy,rtype,oneshot,lev)) 174. return; 175. } 176. 177. /* then a deterministic one */ 178. 179. oneshot = TRUE; 180. for (x = lx; x <= hx; x++) 181. for (y = ly; y <= hy; y++) 182. if (put_lregion_here(x,y,nlx,nly,nhx,nhy,rtype,oneshot,lev)) 183. return; 184. 185. impossible("Couldn't place lregion type %d!", rtype); 186. } 187. 188. static boolean 189. put_lregion_here(x,y,nlx,nly,nhx,nhy,rtype,oneshot,lev) 190. xchar x, y; 191. xchar nlx, nly, nhx, nhy; 192. xchar rtype; 193. boolean oneshot; 194. d_level *lev; 195. { 196. if(oneshot) { 197. /* must make due with the only location possible */ 198. /* avoid failure due to a misplaced trap */ 199. /* it might still fail if there's a dungeon feature here */ 200. struct trap *t = t_at(x,y); 201. if (t) deltrap(t); 202. } 203. if(bad_location(x, y, nlx, nly, nhx, nhy)) return(FALSE); 204. switch (rtype) { 205. case LR_TELE: 206. case LR_UPTELE: 207. case LR_DOWNTELE: 208. /* "something" means the player in this case */ 209. if(MON_AT(x, y)) { 210. /* move the monster if no choice, or just try again */ 211. if(oneshot) rloc(m_at(x,y)); 212. else return(FALSE); 213. } 214. u.ux = x; u.uy = y; 215. break; 216. case LR_PORTAL: 217. mkportal(x, y, lev->dnum, lev->dlevel); 218. break; 219. case LR_DOWNSTAIR: 220. case LR_UPSTAIR: 221. mkstairs(x, y, (char)rtype, (struct mkroom *)0); 222. break; 223. case LR_BRANCH: 224. place_branch(Is_branchlev(&u.uz), x, y); 225. break; 226. } 227. return(TRUE); 228. } 229. 230. static boolean was_waterlevel; /* ugh... this shouldn't be needed */ 231. 232. /* this is special stuff that the level compiler cannot (yet) handle */ 233. static void 234. fixup_special() 235. { 236. register lev_region *r = lregions; 237. struct d_level lev; 238. register int x, y; 239. struct mkroom *croom; 240. boolean added_branch = FALSE; 241. 242. if (was_waterlevel) { 243. was_waterlevel = FALSE; 244. u.uinwater = 0; 245. unsetup_waterlevel(); 246. } else if (Is_waterlevel(&u.uz)) { 247. level.flags.hero_memory = 0; 248. was_waterlevel = TRUE; 249. /* water level is an odd beast - it has to be set up 250. before calling place_lregions etc. */ 251. setup_waterlevel(); 252. } 253. for(x = 0; x < num_lregions; x++, r++) { 254. switch(r->rtype) { 255. case LR_BRANCH: 256. added_branch = TRUE; 257. goto place_it; 258. 259. case LR_PORTAL: 260. if(*r->rname >= '0' && *r->rname <= '9') { 261. /* "chutes and ladders" */ 262. lev = u.uz; 263. lev.dlevel = atoi(r->rname); 264. } else 265. lev = find_level(r->rname)->dlevel; 266. /* fall into... */ 267. 268. case LR_UPSTAIR: 269. case LR_DOWNSTAIR: 270. place_it: 271. place_lregion(r->inarea.x1, r->inarea.y1, 272. r->inarea.x2, r->inarea.y2, 273. r->delarea.x1, r->delarea.y1, 274. r->delarea.x2, r->delarea.y2, 275. r->rtype, &lev); 276. break; 277. 278. case LR_TELE: 279. case LR_UPTELE: 280. case LR_DOWNTELE: 281. /* save the region outlines for goto_level() */ 282. if(r->rtype == LR_TELE || r->rtype == LR_UPTELE) { 283. updest.lx = r->inarea.x1; updest.ly = r->inarea.y1; 284. updest.hx = r->inarea.x2; updest.hy = r->inarea.y2; 285. updest.nlx = r->delarea.x1; updest.nly = r->delarea.y1; 286. updest.nhx = r->delarea.x2; updest.nhy = r->delarea.y2; 287. } 288. if(r->rtype == LR_TELE || r->rtype == LR_DOWNTELE) { 289. dndest.lx = r->inarea.x1; dndest.ly = r->inarea.y1; 290. dndest.hx = r->inarea.x2; dndest.hy = r->inarea.y2; 291. dndest.nlx = r->delarea.x1; dndest.nly = r->delarea.y1; 292. dndest.nhx = r->delarea.x2; dndest.nhy = r->delarea.y2; 293. } 294. /* place_lregion gets called from goto_level() */ 295. break; 296. } 297. } 298. 299. /* place dungeon branch if not placed above */ 300. if (!added_branch && Is_branchlev(&u.uz)) { 301. place_lregion(0,0,0,0,0,0,0,0,LR_BRANCH,(d_level *)0); 302. } 303. 304. /* Still need to add some stuff to level file */ 305. if (Is_medusa_level(&u.uz)) { 306. struct obj *otmp; 307. int tryct; 308. 309. croom = &rooms[0]; /* only one room on the medusa level */ 310. for (tryct = rn1(1,3); tryct; tryct--) { 311. x = somex(croom); y = somey(croom); 312. if (goodpos(x, y, (struct monst *)0, (struct permonst *)0)) { 313. otmp = mk_tt_object(STATUE, x, y); 314. while (otmp && (poly_when_stoned(&mons[otmp->corpsenm]) || 315. resists_ston(&mons[otmp->corpsenm]))) { 316. otmp->corpsenm = rndmonnum(); 317. otmp->owt = weight(otmp); 318. } 319. } 320. } 321. 322. if (rn2(2)) 323. otmp = mk_tt_object(STATUE, somex(croom), somey(croom)); 324. else /* Medusa statues don't contain books */ 325. otmp = mkcorpstat(STATUE, (struct permonst *)0, 326. somex(croom), somey(croom), FALSE); 327. if (otmp) { 328. while (resists_ston(&mons[otmp->corpsenm]) 329. || poly_when_stoned(&mons[otmp->corpsenm])) { 330. otmp->corpsenm = rndmonnum(); 331. otmp->owt = weight(otmp); 332. } 333. } 334. } else if(Is_wiz1_level(&u.uz)) { 335. croom = search_special(MORGUE); 336. 337. create_secret_door(croom, W_SOUTH|W_EAST|W_WEST); 338. #ifdef MULDGN 339. } else if(Is_knox(&u.uz)) { 340. /* using an unfilled morgue for rm id */ 341. croom = search_special(MORGUE); 342. /* stock the main vault */ 343. for(x = croom->lx; x <= croom->hx; x++) 344. for(y = croom->ly; y <= croom->hy; y++) { 345. mkgold((long) rn1(300, 600), x, y); 346. if(!rn2(3) && !is_pool(x,y)) (void)maketrap(x, y, LANDMINE); 347. } 348. #endif 349. } else if(Is_sanctum(&u.uz)) { 350. croom = search_special(TEMPLE); 351. 352. create_secret_door(croom, W_ANY); 353. } else if(on_level(&u.uz, &orcus_level)) { 354. register struct monst *mtmp, *mtmp2; 355. 356. /* it's a ghost town, get rid of shopkeepers */ 357. for(mtmp = fmon; mtmp; mtmp = mtmp2) { 358. mtmp2 = mtmp->nmon; 359. if(mtmp->isshk) mongone(mtmp); 360. } 361. } 362. 363. if(lev_message) { 364. char *str, *nl; 365. for(str = lev_message; (nl = index(str, ' ')) != 0; str = nl+1) { 366. *nl = '\0'; 367. pline("%s", str); 368. } 369. if(*str) 370. pline("%s", str); 371. free((genericptr_t)lev_message); 372. lev_message = 0; 373. } 374. } 375. 376. void 377. makemaz(s) 378. register const char *s; 379. { 380. int x,y; 381. char protofile[20]; 382. s_level *sp = Is_special(&u.uz); 383. coord mm; 384. 385. if(*s) { 386. if(sp && sp->rndlevs) Sprintf(protofile, "%s-%d", s, 387. rnd((int) sp->rndlevs)); 388. else Strcpy(protofile, s); 389. } else if(*(dungeons[u.uz.dnum].proto)) { 390. if(dunlevs_in_dungeon(&u.uz) > 1) { 391. if(sp && sp->rndlevs) 392. Sprintf(protofile, "%s%d-%d", dungeons[u.uz.dnum].proto, 393. dunlev(&u.uz), 394. rnd((int) sp->rndlevs)); 395. else Sprintf(protofile, "%s%d", dungeons[u.uz.dnum].proto, 396. dunlev(&u.uz)); 397. } else if(sp && sp->rndlevs) { 398. Sprintf(protofile, "%s-%d", dungeons[u.uz.dnum].proto, 399. rnd((int) sp->rndlevs)); 400. } else Strcpy(protofile, dungeons[u.uz.dnum].proto); 401. 402. } else Strcpy(protofile, ""); 403. 404. if(*protofile) { 405. Strcat(protofile, LEV_EXT); 406. if(load_special(protofile)) { 407. fixup_special(); 408. return; /* no mazification right now */ 409. } 410. impossible("Couldn't load '%s' - making a maze.", protofile); 411. } 412. 413. level.flags.is_maze_lev = TRUE; 414. 415. #ifndef WALLIFIED_MAZE 416. for(x = 2; x < x_maze_max; x++) 417. for(y = 2; y < y_maze_max; y++) 418. levl[x][y].typ = STONE; 419. #else 420. for(x = 2; x <= x_maze_max; x++) 421. for(y = 2; y <= y_maze_max; y++) 422. levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL; 423. #endif 424. 425. maze0xy(&mm); 426. walkfrom((int) mm.x, (int) mm.y); 427. /* put a boulder at the maze center */ 428. (void) mksobj_at(BOULDER, (int) mm.x, (int) mm.y, TRUE); 429. 430. #ifdef WALLIFIED_MAZE 431. wallification(2, 2, x_maze_max, y_maze_max); 432. #else 433. for(x = 2; x < x_maze_max; x++) 434. for(y = 2; y < y_maze_max; y++) 435. levl[x][y].seen = 1; /* start out seen */ 436. #endif 437. if(Invocation_lev(&u.uz)) { 438. place_lregion(0,0,0,0, 30, 0, 46, ROWNO, UP, (d_level *)0); 439. do { 440. if(xupstair < 30) 441. x = rn1(COLNO-16-xupstair, xupstair+7); 442. else 443. x = rn1(xupstair-16, 9); 444. y = rn1(7, 8); 445. } while((levl[x][y].typ != CORR && levl[x][y].typ != ROOM) 446. || occupied(x,y)); 447. inv_pos.x = x; 448. inv_pos.y = y; 449. } else { 450. /* no regular up stairs on the first level of a dungeon) */ 451. if(u.uz.dlevel != 1) { 452. mazexy(&mm); 453. mkstairs(mm.x, mm.y, UP, (struct mkroom *)0); 454. } 455. 456. /* no regular down stairs on the last level of a dungeon */ 457. if(dunlev(&u.uz) != dunlevs_in_dungeon(&u.uz)) { 458. mazexy(&mm); 459. mkstairs(mm.x, mm.y, DOWN, (struct mkroom *)0); 460. } 461. } 462. 463. /* place branch stair or portal */ 464. place_branch(Is_branchlev(&u.uz), 0, 0); 465. 466. for(x = rn1(8,11); x; x--) { 467. mazexy(&mm); 468. (void) mkobj_at(rn2(2) ? GEM_CLASS : 0, mm.x, mm.y, TRUE); 469. } 470. for(x = rn1(10,2); x; x--) { 471. mazexy(&mm); 472. (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE); 473. } 474. mazexy(&mm); 475. (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y); 476. for(x = rn1(5,7); x; x--) { 477. mazexy(&mm); 478. (void) makemon((struct permonst *) 0, mm.x, mm.y); 479. } 480. for(x = rn1(6,7); x; x--) { 481. mazexy(&mm); 482. mkgold(0L,mm.x,mm.y); 483. } 484. for(x = rn1(6,7); x; x--) 485. mktrap(0,1,(struct mkroom *) 0, (coord*) 0); 486. } 487. 488. #ifdef MICRO 489. /* Make the mazewalk iterative by faking a stack. This is needed to 490. * ensure the mazewalk is successful in the limited stack space of 491. * the program. This iterative version uses the minimum amount of stack 492. * that is totally safe. 493. */ 494. void 495. walkfrom(x,y) 496. int x,y; 497. { 498. #define CELLS (ROWNO * COLNO) / 4 /* a maze cell is 4 squares */ 499. char mazex[CELLS + 1], mazey[CELLS + 1]; /* char's are OK */ 500. int q, a, dir, pos; 501. int dirs[4]; 502. 503. pos = 1; 504. mazex[pos] = (char) x; 505. mazey[pos] = (char) y; 506. while (pos) { 507. x = (int) mazex[pos]; 508. y = (int) mazey[pos]; 509. if(!IS_DOOR(levl[x][y].typ)) { 510. /* might still be on edge of MAP, so don't overwrite */ 511. #ifndef WALLIFIED_MAZE 512. levl[x][y].typ = CORR; 513. #else 514. levl[x][y].typ = ROOM; 515. #endif 516. levl[x][y].flags = 0; 517. } 518. q = 0; 519. for (a = 0; a < 4; a++) 520. if(okay(x, y, a)) dirs[q++]= a; 521. if (!q) 522. pos--; 523. else { 524. dir = dirs[rn2(q)]; 525. move(&x, &y, dir); 526. #ifndef WALLIFIED_MAZE 527. levl[x][y].typ = CORR; 528. #else 529. levl[x][y].typ = ROOM; 530. #endif 531. move(&x, &y, dir); 532. pos++; 533. if (pos > CELLS) 534. panic("Overflow in walkfrom"); 535. mazex[pos] = (char) x; 536. mazey[pos] = (char) y; 537. } 538. } 539. } 540. #else 541. 542. void 543. walkfrom(x,y) 544. int x,y; 545. { 546. register int q,a,dir; 547. int dirs[4]; 548. 549. if(!IS_DOOR(levl[x][y].typ)) { 550. /* might still be on edge of MAP, so don't overwrite */ 551. #ifndef WALLIFIED_MAZE 552. levl[x][y].typ = CORR; 553. #else 554. levl[x][y].typ = ROOM; 555. #endif 556. levl[x][y].flags = 0; 557. } 558. 559. while(1) { 560. q = 0; 561. for(a = 0; a < 4; a++) 562. if(okay(x,y,a)) dirs[q++]= a; 563. if(!q) return; 564. dir = dirs[rn2(q)]; 565. move(&x,&y,dir); 566. #ifndef WALLIFIED_MAZE 567. levl[x][y].typ = CORR; 568. #else 569. levl[x][y].typ = ROOM; 570. #endif 571. move(&x,&y,dir); 572. walkfrom(x,y); 573. } 574. } 575. #endif /* MICRO */ 576. 577. void 578. move(x,y,dir) 579. register int *x, *y; 580. register int dir; 581. { 582. switch(dir){ 583. case 0: --(*y); break; 584. case 1: (*x)++; break; 585. case 2: (*y)++; break; 586. case 3: --(*x); break; 587. } 588. } 589. 590. void 591. mazexy(cc) /* find random point in generated corridors, 592. so we don't create items in moats, bunkers, or walls */ 593. coord *cc; 594. { 595. int cpt=0; 596. 597. do { 598. cc->x = 3 + 2*rn2((x_maze_max>>1) - 1); 599. cc->y = 3 + 2*rn2((y_maze_max>>1) - 1); 600. cpt++; 601. } while (cpt < 100 && levl[cc->x][cc->y].typ != 602. #ifndef WALLIFIED_MAZE 603. CORR 604. #else 605. ROOM 606. #endif 607. ); 608. if (cpt >= 100) { 609. register int x, y; 610. /* last try */ 611. for (x = 0; x < (x_maze_max>>1) - 1; x++) 612. for (y = 0; y < (y_maze_max>>1) - 1; y++) { 613. cc->x = 3 + 2 * x; 614. cc->y = 3 + 2 * y; 615. if (levl[cc->x][cc->y].typ == 616. #ifndef WALLIFIED_MAZE 617. CORR 618. #else 619. ROOM 620. #endif 621. ) return; 622. } 623. panic("mazexy: can't find a place!"); 624. } 625. return; 626. } 627. 628. void 629. bound_digging() 630. /* put a non-diggable boundary around the initial portion of a level map. 631. * assumes that no level will initially put things beyond the isok() range. 632. * 633. * we can't bound unconditionally on the last line with something in it, 634. * because that something might be a niche which was already reachable, 635. * so the boundary would be breached 636. * 637. * we can't bound unconditionally on one beyond the last line, because 638. * that provides a window of abuse for WALLIFIED_MAZE special levels 639. */ 640. { 641. register int x,y; 642. register unsigned typ; 643. register struct rm *lev; 644. boolean found, nonwall; 645. int xmin,xmax,ymin,ymax; 646. 647. if(Is_earthlevel(&u.uz)) return; /* everything diggable here */ 648. 649. found = nonwall = FALSE; 650. for(xmin=0; !found; xmin++) { 651. lev = &levl[xmin][0]; 652. for(y=0; y<=ROWNO-1; y++, lev++) { 653. typ = lev->typ; 654. if(typ != STONE) { 655. found = TRUE; 656. if(!IS_WALL(typ)) nonwall = TRUE; 657. } 658. } 659. } 660. xmin -= (nonwall || !level.flags.is_maze_lev) ? 2 : 1; 661. if (xmin < 0) xmin = 0; 662. 663. found = nonwall = FALSE; 664. for(xmax=COLNO-1; !found; xmax--) { 665. lev = &levl[xmax][0]; 666. for(y=0; y<=ROWNO-1; y++, lev++) { 667. typ = lev->typ; 668. if(typ != STONE) { 669. found = TRUE; 670. if(!IS_WALL(typ)) nonwall = TRUE; 671. } 672. } 673. } 674. xmax += (nonwall || !level.flags.is_maze_lev) ? 2 : 1; 675. if (xmax >= COLNO) xmax = COLNO-1; 676. 677. found = nonwall = FALSE; 678. for(ymin=0; !found; ymin++) { 679. lev = &levl[xmin][ymin]; 680. for(x=xmin; x<=xmax; x++, lev += ROWNO) { 681. typ = lev->typ; 682. if(typ != STONE) { 683. found = TRUE; 684. if(!IS_WALL(typ)) nonwall = TRUE; 685. } 686. } 687. } 688. ymin -= (nonwall || !level.flags.is_maze_lev) ? 2 : 1; 689. 690. found = nonwall = FALSE; 691. for(ymax=ROWNO-1; !found; ymax--) { 692. lev = &levl[xmin][ymax]; 693. for(x=xmin; x<=xmax; x++, lev += ROWNO) { 694. typ = lev->typ; 695. if(typ != STONE) { 696. found = TRUE; 697. if(!IS_WALL(typ)) nonwall = TRUE; 698. } 699. } 700. } 701. ymax += (nonwall || !level.flags.is_maze_lev) ? 2 : 1; 702. 703. if(ymin >= 0) 704. for(x=xmin; x<=xmax; x++) levl[x][ymin].diggable = W_NONDIGGABLE; 705. if(ymax < ROWNO) 706. for(x=xmin; x<=xmax; x++) levl[x][ymax].diggable = W_NONDIGGABLE; 707. 708. /* Don't bound these until _after_ the previous loops to avoid "ice" */ 709. /* Normal rooms become ice by setting W_NONDIGGABLE -dlc */ 710. if (ymin < 0) ymin = 0; 711. if (ymax >= ROWNO) ymax = ROWNO-1; 712. 713. for(y=ymin; y<=ymax; y++) { 714. levl[xmin][y].diggable = W_NONDIGGABLE; 715. levl[xmax][y].diggable = W_NONDIGGABLE; 716. } 717. } 718. 719. void 720. mkportal(x, y, todnum, todlevel) 721. register xchar x, y, todnum, todlevel; 722. { 723. /* a portal "trap" must be matched by a */ 724. /* portal in the destination dungeon/dlevel */ 725. register struct trap *ttmp = maketrap(x, y, MAGIC_PORTAL); 726. 727. #ifdef DEBUG 728. pline("mkportal: at (%d,%d), to %s, level %d", 729. x, y, dungeons[todnum].dname, todlevel); 730. #endif 731. ttmp->dst.dnum = todnum; 732. ttmp->dst.dlevel = todlevel; 733. return; 734. } 735. 736. /* 737. * Special waterlevel stuff in endgame (TH). 738. * 739. * Some of these functions would probably logically belong to some 740. * other source files, but they are all so nicely encapsulated here. 741. */ 742. 743. /* to ease the work of debuggers at this stage */ 744. #define register 745. 746. struct container { 747. struct container *next; 748. xchar x, y; 749. short what; 750. genericptr_t list; 751. }; 752. #define CONS_OBJ 0 753. #define CONS_MON 1 754. #define CONS_HERO 2 755. #define CONS_TRAP 3 756. 757. static struct bubble { 758. xchar x, y; /* coordinates of the upper left corner */ 759. schar dx, dy; /* the general direction of the bubble's movement */ 760. uchar *bm; /* pointer to the bubble bit mask */ 761. struct bubble *prev, *next; /* need to traverse the list up and down */ 762. struct container *cons; 763. } *bbubbles, *ebubbles; 764. 765. static struct trap *wportal; 766. static int xmin, ymin, xmax, ymax; /* level boundaries */ 767. /* bubble movement boundaries */ 768. #define bxmin (xmin + 1) 769. #define bymin (ymin + 1) 770. #define bxmax (xmax - 1) 771. #define bymax (ymax - 1) 772. 773. static void NDECL(set_wportal); 774. static void FDECL(mk_bubble, (int,int,int)); 775. static void FDECL(mv_bubble, (struct bubble *,int,int,BOOLEAN_P)); 776. 777. void 778. movebubbles() 779. { 780. static boolean up; 781. register struct bubble *b; 782. register int x, y, i, j; 783. struct trap *btrap; 784. static const struct rm water_pos = 785. { cmap_to_glyph(S_water), WATER, 0, 0, 0, 0, 0, 0, 0 }; 786. 787. /* set up the portal the first time bubbles are moved */ 788. if (!wportal) set_wportal(); 789. 790. vision_recalc(2); 791. 792. /* 793. * Pick up everything inside of a bubble then fill all bubble 794. * locations. 795. */ 796. 797. for (b = up ? bbubbles : ebubbles; b; b = up ? b->next : b->prev) { 798. if (b->cons) panic("movebubbles: cons != null"); 799. for (i = 0, x = b->x; i < (int) b->bm[0]; i++, x++) 800. for (j = 0, y = b->y; j < (int) b->bm[1]; j++, y++) 801. if (b->bm[j + 2] & (1 << i)) { 802. if (!isok(x,y)) { 803. impossible("movebubbles: bad pos (%d,%d)", x,y); 804. continue; 805. } 806. 807. /* pick up objects, monsters, hero, and traps */ 808. if (OBJ_AT(x,y)) { 809. struct obj *olist = (struct obj *) 0, *otmp; 810. struct container *cons = (struct container *) 811. alloc(sizeof(struct container)); 812. 813. while ((otmp = level.objects[x][y]) != 0) { 814. remove_object(otmp); 815. otmp->ox = otmp->oy = 0; 816. otmp->nexthere = olist; 817. olist = otmp; 818. } 819. 820. cons->x = x; 821. cons->y = y; 822. cons->what = CONS_OBJ; 823. cons->list = (genericptr_t) olist; 824. cons->next = b->cons; 825. b->cons = cons; 826. } 827. if (MON_AT(x,y)) { 828. struct monst *mon = m_at(x,y); 829. struct container *cons = (struct container *) 830. alloc(sizeof(struct container)); 831. 832. cons->x = x; 833. cons->y = y; 834. cons->what = CONS_MON; 835. cons->list = (genericptr_t) mon; 836. 837. cons->next = b->cons; 838. b->cons = cons; 839. 840. if(mon->wormno) 841. remove_worm(mon); 842. else 843. remove_monster(x, y); 844. 845. newsym(x,y); /* clean up old position */ 846. mon->mx = mon->my = 0; 847. } 848. if (!u.uswallow && x == u.ux && y == u.uy) { 849. struct container *cons = (struct container *) 850. alloc(sizeof(struct container)); 851. 852. cons->x = x; 853. cons->y = y; 854. cons->what = CONS_HERO; 855. cons->list = (genericptr_t) 0; 856. 857. cons->next = b->cons; 858. b->cons = cons; 859. } 860. if ((btrap = t_at(x,y)) != 0) { 861. struct container *cons = (struct container *) 862. alloc(sizeof(struct container)); 863. 864. cons->x = x; 865. cons->y = y; 866. cons->what = CONS_TRAP; 867. cons->list = (genericptr_t) btrap; 868. 869. cons->next = b->cons; 870. b->cons = cons; 871. } 872. 873. levl[x][y] = water_pos; 874. block_point(x,y); 875. } 876. } 877. 878. /* 879. * Every second time traverse down. This is because otherwise 880. * all the junk that changes owners when bubbles overlap 881. * would eventually end up in the last bubble in the chain. 882. */ 883. 884. up = !up; 885. for (b = up ? bbubbles : ebubbles; b; b = up ? b->next : b->prev) { 886. register int rx = rn2(3), ry = rn2(3); 887. 888. mv_bubble(b,b->dx + 1 - (!b->dx ? rx : (rx ? 1 : 0)), 889. b->dy + 1 - (!b->dy ? ry : (ry ? 1 : 0)), 890. FALSE); 891. } 892. 893. vision_full_recalc = 1; 894. } 895. 896. void 897. water_friction() 898. { 899. register boolean eff = FALSE; 900. 901. if (u.dx && !rn2(3)) { 902. eff = TRUE; 903. u.dx = 0; 904. } 905. if (u.dy && !rn2(3)) { 906. eff = TRUE; 907. u.dy = 0; 908. } 909. if (eff) pline("Water turbulence affects your movements."); 910. } 911. 912. void 913. save_waterlevel(fd) 914. register int fd; 915. { 916. register struct bubble *b; 917. int n; 918. 919. if (!Is_waterlevel(&u.uz)) return; 920. 921. for (b = bbubbles, n = 0; b; b = b->next, n++) ; 922. bwrite(fd,(genericptr_t)&n,sizeof(int)); 923. bwrite(fd,(genericptr_t)&xmin,sizeof(int)); 924. bwrite(fd,(genericptr_t)&ymin,sizeof(int)); 925. bwrite(fd,(genericptr_t)&xmax,sizeof(int)); 926. bwrite(fd,(genericptr_t)&ymax,sizeof(int)); 927. for (b = bbubbles; b; b = b->next) 928. bwrite(fd,(genericptr_t)b,sizeof(struct bubble)); 929. } 930. 931. void 932. restore_waterlevel(fd) 933. register int fd; 934. { 935. register struct bubble *b = (struct bubble *)0, *btmp; 936. register int i; 937. int n; 938. 939. if (!Is_waterlevel(&u.uz)) return; 940. 941. set_wportal(); 942. mread(fd,(genericptr_t)&n,sizeof(int)); 943. mread(fd,(genericptr_t)&xmin,sizeof(int)); 944. mread(fd,(genericptr_t)&ymin,sizeof(int)); 945. mread(fd,(genericptr_t)&xmax,sizeof(int)); 946. mread(fd,(genericptr_t)&ymax,sizeof(int)); 947. for (i = 0; i < n; i++) { 948. btmp = b; 949. b = (struct bubble *)alloc(sizeof(struct bubble)); 950. mread(fd,(genericptr_t)b,sizeof(struct bubble)); 951. if (bbubbles) { 952. btmp->next = b; 953. b->prev = btmp; 954. } else { 955. bbubbles = b; 956. b->prev = (struct bubble *)0; 957. } 958. mv_bubble(b,0,0,TRUE); 959. } 960. ebubbles = b; 961. b->next = (struct bubble *)0; 962. was_waterlevel = TRUE; 963. } 964. 965. static void 966. set_wportal() 967. { 968. /* there better be only one magic portal on water level... */ 969. for (wportal = ftrap; wportal; wportal = wportal->ntrap) 970. if (wportal->ttyp == MAGIC_PORTAL) return; 971. impossible("set_wportal(): no portal!"); 972. } 973. 974. static void 975. setup_waterlevel() 976. { 977. register int x, y; 978. register int xskip, yskip; 979. register int water_glyph = cmap_to_glyph(S_water); 980. 981. /* ouch, hardcoded... */ 982. 983. xmin = 3; 984. ymin = 1; 985. xmax = 78; 986. ymax = 20; 987. 988. /* set hero's memory to water */ 989. 990. for (x = xmin; x <= xmax; x++) 991. for (y = ymin; y <= ymax; y++) 992. levl[x][y].glyph = water_glyph; 993. 994. /* make bubbles */ 995. 996. xskip = 10 + rn2(10); 997. yskip = 4 + rn2(4); 998. for (x = bxmin; x <= bxmax; x += xskip) 999. for (y = bymin; y <= bymax; y += yskip) 1000. mk_bubble(x,y,rn2(7)); 1001. } 1002. 1003. static void 1004. unsetup_waterlevel() 1005. { 1006. register struct bubble *b, *bb; 1007. 1008. /* free bubbles */ 1009. 1010. for (b = bbubbles; b; b = bb) { 1011. bb = b->next; 1012. free((genericptr_t)b); 1013. } 1014. bbubbles = ebubbles = (struct bubble *)0; 1015. } 1016. 1017. static void 1018. mk_bubble(x,y,n) 1019. register int x, y, n; 1020. { 1021. /* 1022. * These bit masks make visually pleasing bubbles on a normal aspect 1023. * 25x80 terminal, which naturally results in them being mathematically 1024. * anything but symmetric. For this reason they cannot be computed 1025. * in situ, either. The first two elements tell the dimensions of 1026. * the bubble's bounding box. 1027. */ 1028. static uchar 1029. bm2[] = {2,1,0x3}, 1030. bm3[] = {3,2,0x7,0x7}, 1031. bm4[] = {4,3,0x6,0xf,0x6}, 1032. bm5[] = {5,3,0xe,0x1f,0xe}, 1033. bm6[] = {6,4,0x1e,0x3f,0x3f,0x1e}, 1034. bm7[] = {7,4,0x3e,0x7f,0x7f,0x3e}, 1035. bm8[] = {8,4,0x7e,0xff,0xff,0x7e}, 1036. *bmask[] = {bm2,bm3,bm4,bm5,bm6,bm7,bm8}; 1037. 1038. register struct bubble *b; 1039. 1040. if (x >= bxmax || y >= bymax) return; 1041. if (n >= SIZE(bmask)) { 1042. impossible("n too large (mk_bubble)"); 1043. n = SIZE(bmask) - 1; 1044. } 1045. b = (struct bubble *)alloc(sizeof(struct bubble)); 1046. if ((x + (int) bmask[n][0] - 1) > bxmax) x = bxmax - bmask[n][0] + 1; 1047. if ((y + (int) bmask[n][1] - 1) > bymax) y = bymax - bmask[n][1] + 1; 1048. b->x = x; 1049. b->y = y; 1050. b->dx = 1 - rn2(3); 1051. b->dy = 1 - rn2(3); 1052. b->bm = bmask[n]; 1053. b->cons = 0; 1054. if (!bbubbles) bbubbles = b; 1055. if (ebubbles) { 1056. ebubbles->next = b; 1057. b->prev = ebubbles; 1058. } 1059. else 1060. b->prev = (struct bubble *)0; 1061. b->next = (struct bubble *)0; 1062. ebubbles = b; 1063. mv_bubble(b,0,0,TRUE); 1064. } 1065. 1066. /* 1067. * The player, the portal and all other objects and monsters 1068. * float along with their associated bubbles. Bubbles may overlap 1069. * freely, and the contents may get associated with other bubbles in 1070. * the process. Bubbles are "sticky", meaning that if the player is 1071. * in the immediate neighborhood of one, he/she may get sucked inside. 1072. * This property also makes leaving a bubble slightly difficult. 1073. */ 1074. static void 1075. mv_bubble(b,dx,dy,ini) 1076. register struct bubble *b; 1077. register int dx, dy; 1078. register boolean ini; 1079. { 1080. register int x, y, i, j, colli = 0; 1081. struct bubble ob; 1082. struct container *cons, *ctemp; 1083. 1084. /* some old data for reference */ 1085. 1086. ob.x = b->x; 1087. ob.y = b->y; 1088. ob.bm = b->bm; 1089. 1090. /* move bubble */ 1091. if (dx < -1 || dx > 1 || dy < -1 || dy > 1) { 1092. /* pline("mv_bubble: dx = %d, dy = %d", dx, dy); */ 1093. dx = sgn(dx); 1094. dy = sgn(dy); 1095. } 1096. 1097. /* 1098. * collision with level borders? 1099. * 1 = horizontal border, 2 = vertical, 3 = corner 1100. */ 1101. if (b->x <= bxmin) colli |= 2; 1102. if (b->y <= bymin) colli |= 1; 1103. if ((int) (b->x + b->bm[0] - 1) >= bxmax) colli |= 2; 1104. if ((int) (b->y + b->bm[1] - 1) >= bymax) colli |= 1; 1105. 1106. if (b->x < bxmin) { 1107. pline("bubble xmin: x = %d, xmin = %d", b->x, bxmin); 1108. b->x = bxmin; 1109. } 1110. if (b->y < bymin) { 1111. pline("bubble ymin: y = %d, ymin = %d", b->y, bymin); 1112. b->y = bymin; 1113. } 1114. if ((int) (b->x + b->bm[0] - 1) > bxmax) { 1115. pline("bubble xmax: x = %d, xmax = %d", 1116. b->x + b->bm[0] - 1, bxmax); 1117. b->x = bxmax - b->bm[0] + 1; 1118. } 1119. if ((int) (b->y + b->bm[1] - 1) > bymax) { 1120. pline("bubble ymax: y = %d, ymax = %d", 1121. b->y + b->bm[1] - 1, bymax); 1122. b->y = bymax - b->bm[1] + 1; 1123. } 1124. 1125. /* bounce if we're trying to move off the border */ 1126. if (b->x == bxmin && dx < 0) dx = -dx; 1127. if (b->x + b->bm[0] - 1 == bxmax && dx > 0) dx = -dx; 1128. if (b->y == bymin && dy < 0) dy = -dy; 1129. if (b->y + b->bm[1] - 1 == bymax && dy > 0) dy = -dy; 1130. 1131. b->x += dx; 1132. b->y += dy; 1133. 1134. /* void positions inside bubble */ 1135. 1136. for (i = 0, x = b->x; i < (int) b->bm[0]; i++, x++) 1137. for (j = 0, y = b->y; j < (int) b->bm[1]; j++, y++) 1138. if (b->bm[j + 2] & (1 << i)) { 1139. levl[x][y].typ = AIR; 1140. levl[x][y].lit = 1; 1141. unblock_point(x,y); 1142. } 1143. 1144. /* replace contents of bubble */ 1145. for (cons = b->cons; cons; cons = ctemp) { 1146. ctemp = cons->next; 1147. cons->x += dx; 1148. cons->y += dy; 1149. 1150. switch(cons->what) { 1151. case CONS_OBJ: { 1152. struct obj *olist, *otmp; 1153. 1154. for (olist=(struct obj *)cons->list; olist; olist=otmp) { 1155. otmp = olist->nexthere; 1156. place_object(olist, cons->x, cons->y); 1157. } 1158. break; 1159. } 1160. 1161. case CONS_MON: { 1162. struct monst *mon = (struct monst *) cons->list; 1163. (void) mnearto(mon, cons->x, cons->y, TRUE); 1164. break; 1165. } 1166. 1167. case CONS_HERO: { 1168. int ux0 = u.ux, uy0 = u.uy; 1169. 1170. /* change u.ux0 and u.uy0? */ 1171. u.ux = cons->x; 1172. u.uy = cons->y; 1173. newsym(ux0, uy0); /* clean up old position */ 1174. 1175. if (MON_AT(cons->x, cons->y)) { 1176. mnexto(m_at(cons->x,cons->y)); 1177. } 1178. if (Punished) placebc(); /* do this for now */ 1179. break; 1180. } 1181. 1182. case CONS_TRAP: { 1183. struct trap *btrap = (struct trap *) cons->list; 1184. btrap->tx = cons->x; 1185. btrap->ty = cons->y; 1186. break; 1187. } 1188. 1189. default: 1190. impossible("mv_bubble: unknown bubble contents"); 1191. break; 1192. } 1193. free((genericptr_t)cons); 1194. } 1195. b->cons = 0; 1196. 1197. /* boing? */ 1198. 1199. switch (colli) { 1200. case 1: b->dy = -b->dy; break; 1201. case 3: b->dy = -b->dy; /* fall through */ 1202. case 2: b->dx = -b->dx; break; 1203. default: 1204. /* sometimes alter direction for fun anyway 1205. (higher probability for stationary bubbles) */ 1206. if (!ini && ((b->dx || b->dy) ? !rn2(20) : !rn2(5))) { 1207. b->dx = 1 - rn2(3); 1208. b->dy = 1 - rn2(3); 1209. } 1210. } 1211. } 1212. 1213. 1214. /*mkmaze.c*/
Alternative Linked Data Views: ODE     Raw Data in: CXML | CSV | RDF ( N-Triples N3/Turtle JSON XML ) | OData ( Atom JSON ) | Microdata ( JSON HTML) | JSON-LD    About   
This material is Open Knowledge   W3C Semantic Web Technology [RDF Data] Valid XHTML + RDFa
OpenLink Virtuoso version 07.20.3217, on Linux (x86_64-pc-linux-gnu), Standard Edition
Data on this page belongs to its respective rights holders.
Virtuoso Faceted Browser Copyright © 2009-2012 OpenLink Software