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