Source:NetHack 3.0.0/mkmaze.c

Below is the full text to mkmaze.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.0	88/10/25 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   extern int x_maze_max, y_maze_max; 8.    9.    #if defined(WALLIFIED_MAZE) || defined(STRONGHOLD) 10.  static int 11.  iswall(x,y) 12.  int x,y; 13.  {  14.   # ifndef WALLIFIED_MAZE 15.  	if (x<0 || y<0 || x>COLNO-1 || y>ROWNO-1) 16.  # else 17.  	if (x<0 || y<0 || x>COLNO || y>ROWNO) 18.  # endif 19.  		return 0; 20.  	return (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)  21.   		|| levl[x][y].typ == SDOOR); 22.  }  23.    24.   void 25.  wallification(x1, y1, x2, y2, see) 26.  int x1, y1, x2, y2; 27.  boolean see; 28.  {  29.   	char type; 30.  	short x,y; 31.  	register struct rm *room; 32.   33.   	if (x1 < 0) x1 = 0; 34.  	if (x2 < x1) x2 = x1; 35.  	if (x2 > COLNO-1) x2 = COLNO-1; 36.  	if (x1 > x2) x1 = x2; 37.  	if (y1 < 0) y1 = 0; 38.  	if (y2 < y1) y2 = y1; 39.  	if (y2 > COLNO-1) y2 = ROWNO-1; 40.  	if (y1 > y2) y1 = y2; 41.  	for(x = x1; x <= x2; x++) 42.  	    for(y = y1; y <= y2; y++) { 43.  		room = &levl[x][y]; 44.  		type = room->typ; 45.  		if (iswall(x,y)) { 46.  		    if (IS_DOOR(type)) { 47.  			room->scrsym = DOOR_SYM; 48.  			continue; 49.  		    } else 50.  		    if (iswall(x,y-1)) 51.  			if (iswall(x,y+1)) 52.  			    if (iswall(x-1,y)) 53.  				if (iswall(x+1,y)) { 54.  					room->scrsym = CRWALL_SYM; /* -+- */ 55.  					room->typ = CROSSWALL; 56.  				} else { 57.  					room->scrsym = TLWALL_SYM; /* -| */ 58.  					room->typ = TLWALL; 59.  				}  60.   			    else 61.  				if (iswall(x+1,y)) { 62.  					room->scrsym = TRWALL_SYM; /* |- */ 63.  					room->typ = TRWALL; 64.  				} else { 65.  					room->typ = VWALL; 66.  #ifdef STRONGHOLD 67.  					if (is_drawbridge_wall(x,y) >= 0) 68.  					    room->scrsym = DB_VWALL_SYM; 69.  					else 70.  #endif 71.  					    room->scrsym = VWALL_SYM; /* | */ 72.  				}  73.   			else 74.  			    if (iswall(x-1,y)) 75.  				if (iswall(x+1,y)) { 76.  					room->scrsym = TUWALL_SYM;  /*  |  */ 77.  					room->typ = TUWALL;	    /* -+- */ 78.  				} else { 79.  					room->scrsym = BRCORN_SYM;  /*	| */ 80.  					room->typ = BRCORNER;	    /* -+ */ 81.  				}  82.   			    else 83.  				if (iswall(x+1,y)) { 84.  					room->scrsym = BLCORN_SYM;  /* |  */ 85.  					room->typ = BLCORNER;	    /* +- */ 86.  				} else { 87.  					room->typ = VWALL; 88.  #ifdef STRONGHOLD 89.  					if (is_drawbridge_wall(x,y) >= 0) 90.  					    room->scrsym = DB_VWALL_SYM; 91.  					else 92.  #endif 93.  					    room->scrsym = VWALL_SYM; /* | */ 94.  				}  95.   		    else 96.  			if (iswall(x,y+1)) 97.  			    if (iswall(x-1,y)) 98.  				if (iswall(x+1,y)) { 99.  					room->scrsym = TDWALL_SYM;  /* -+- */ 100. 					room->typ = TDWALL;	    /*	| */ 101. 				} else { 102. 					room->scrsym = TRCORN_SYM;  /* -+ */ 103. 					room->typ = TRCORNER;	    /*	| */ 104. 				}  105.  			    else 106. 				if (iswall(x+1,y)) { 107. 					room->scrsym = TLCORN_SYM;  /* +- */ 108. 					room->typ = TLCORNER;	    /* |  */ 109. 				} else { 110. 					room->typ = VWALL; 111. #ifdef STRONGHOLD 112. 					if (is_drawbridge_wall(x,y) >= 0) 113. 					    room->scrsym = DB_VWALL_SYM; 114. 					else 115. #endif 116. 					    room->scrsym = VWALL_SYM; /* | */ 117. 				}  118.  			else { 119. 				room->typ = HWALL; 120. #ifdef STRONGHOLD 121. 				if (is_drawbridge_wall(x,y) >= 0) 122. 				    room->scrsym = DB_HWALL_SYM; 123. 				else 124. #endif 125. 				    room->scrsym = HWALL_SYM; 126. 			}  127.  		    if (type == SDOOR) room->typ = type; 128. 		    if (see) room->seen = 0; 129. 		} else { 130. 		    switch(room->typ) { 131. 			case STONE: 132. 				room->scrsym = STONE_SYM; 133. 				break; 134. 			case CORR: 135. 				room->scrsym = CORR_SYM; 136. 				break; 137. 			case ROOM: 138. 				room->scrsym = ROOM_SYM; 139. 		    }  140.  		    if (see) room->seen = 0; 141. 		}  142.  	    }  143.  }  144.  #endif /* WALLIFIED_MAZE /**/ 145.  146.  static boolean 147. okay(x,y,dir) 148. int x,y; 149. register int dir; 150. {  151.  	move(&x,&y,dir); 152. 	move(&x,&y,dir); 153. 	if(x<3 || y<3 || x>x_maze_max || y>y_maze_max || levl[x][y].typ != 0) 154. 		return(FALSE); 155. 	return(TRUE); 156. }  157.   158.  static void 159. maze0xy(cc)	/* find random starting point for maze generation */ 160. 	coord	*cc; 161. {  162.  	cc->x = 3 + 2*rn2((x_maze_max>>1) - 1); 163. 	cc->y = 3 + 2*rn2((y_maze_max>>1) - 1); 164. 	return; 165. }  166.   167.  static const uchar tower[] = { 168. 	MOAT,	  MOAT,     MOAT,     MOAT,	MOAT,	  MOAT,     MOAT, 169. 	MOAT,	  MOAT,     TLCORNER, HWALL,	TRCORNER, MOAT,     MOAT, 170. 	MOAT,	  TLCORNER, BRCORNER, ROOM,	BLCORNER, TRCORNER, MOAT, 171. 	MOAT,	  VWALL,    ROOM,     ROOM,	ROOM,	  VWALL,    MOAT, 172. 	MOAT,	  BLCORNER, TRCORNER, ROOM,	TLCORNER, BRCORNER, MOAT, 173. 	MOAT,	  MOAT,     BLCORNER, HWALL,	BRCORNER, MOAT,     MOAT, 174. 	MOAT,	  MOAT,     MOAT,     MOAT,	MOAT,	  MOAT,     MOAT, 175. };  176.    177.  void 178. makemaz 179. {  180.  	int x,y; 181. 	register int zx,zy; 182. 	coord mm; 183. 	int i;  184. 185. 	is_maze_lev = TRUE; 186. #ifdef STRONGHOLD 187. 	xdnladder = ydnladder = xupladder = yupladder = 0; 188. 	if (dlevel == stronghold_level) { 189. 		if (load_special("castle")) { 190. 			xupstair = yupstair = 3; 191. 			levl[xupstair][yupstair].scrsym = UP_SYM; 192. 			levl[xupstair][yupstair].typ = STAIRS; 193. 			return; 194. 		}  195.  		impossible("Cannot build the STRONGHOLD!"); 196. 	}  197.  	if (dlevel == tower_level) { 198. 		if (load_special("tower1")) { 199. 			xupstair = yupstair = 3; 200. 			levl[xupstair][yupstair].scrsym = UP_SYM; 201. 			levl[xupstair][yupstair].typ = STAIRS; 202. 			return; 203. 		}  204.  		impossible("Cannot build the TOWER!"); 205. 	}  206.  	if (dlevel == tower_level+1) { 207. 		if (load_special("tower2")) { 208. 			xupstair = yupstair = 3; 209. 			levl[xupstair][yupstair].scrsym = UP_SYM; 210. 			levl[xupstair][yupstair].typ = STAIRS; 211. 			return; 212. 		}  213.  		impossible("Cannot build the TOWER!"); 214. 	}  215.  	if (dlevel == tower_level+2) { 216. 		if (load_special("tower3")) { 217. 			xupstair = yupstair = 3; 218. 			levl[xupstair][yupstair].scrsym = UP_SYM; 219. 			levl[xupstair][yupstair].typ = STAIRS; 220. 			return; 221. 		}  222.  		impossible("Cannot build the TOWER!"); 223. 	}  224.  # ifdef ENDGAME 225. 	if (dlevel == ENDLEVEL) {	/* EndGame level */ 226. 		if (load_special("endgame")) { 227. 			pline("Well done, mortal!"); 228. 			pline("But now thou must face the final Test..."); 229. 			pline("Prove thyself worthy or perish!"); 230. 			u.ux = x_maze_max - 1; 231. 			u.uy = y_maze_max - 1; 232. 			xupstair = yupstair = 0; 233. 			return; 234. 		}  235.  		impossible("Cannot build the EndGame Level!"); 236. 		done("escaped"); 237. 	}  238.  # endif 239. #endif 240. #ifndef WALLIFIED_MAZE 241. 	for(x = 2; x < x_maze_max; x++) 242. 		for(y = 2; y < y_maze_max; y++) 243. 			levl[x][y].typ = STONE; 244. #else 245. 	for(x = 2; x <= x_maze_max; x++) 246. 		for(y = 2; y <= y_maze_max; y++) 247. 			levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL; 248. #endif 249.  250.  	/* make decoy wizard levels */ 251. 	if((dlevel == wiz_level) ||  252.  #ifdef STRONGHOLD  253.  	   (!rn2(3) && (dlevel > stronghold_level+1))) { 254. #else 255. 	   (!rn2(3) && (dlevel > medusa_level+1))) {  256.  #endif  257.   258.  	    register struct monst *mtmp;  259.   260.  	    zx = x_maze_max / 2;  261.  	    zy = y_maze_max / 2;  262.  	    if (!(zx % 2)) zx++;  263.  	    if (!(zy % 2)) zy++;  264.  	    for(y = zy-3, i=0; y <= zy+3; y++)  265.  		for(x = zx-3; x <= zx+3; x++)  266.  		    levl[x][y].typ = tower[i++];  267.  	    walkfrom(zx+4, zy);  268.  	    if(mtmp = makemon(&mons[PM_HELL_HOUND], zx+1, zy))  269.  		mtmp->msleep = 1;  270.  	    (void) makemon(&mons[PM_KRAKEN], zx+2, zy+2);  271.  	    if (dlevel == wiz_level) {  272.   273.  		(void) mksobj_at(AMULET_OF_YENDOR, zx, zy);  274.  		flags.made_amulet = 1;  275.  #ifndef STRONGHOLD  276.  		if(mtmp = makemon(&mons[PM_VLAD_THE_IMPALER], zx-1, zy))  277.  			mtmp->msleep = 1;  278.  #endif  279.  		if(mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], zx, zy))  280.  			mtmp->msleep = 1; 281. 	    } else { 282. 		struct obj *ot; 283. 	    	/* make a cheap plastic imitation */ 284. 		if (ot = mksobj_at(AMULET_OF_YENDOR, zx, zy)) 285. 		    ot-> spe = -1; 286. #ifndef STRONGHOLD 287. 		if (mtmp = makemon(&mons[PM_VAMPIRE_LORD], zx-1, zy)) 288. 		    mtmp->msleep = 1; 289. #endif 290. 		(void) makemon(&mons[dprince], zx, zy); 291. 	    }  292.  	    /* they should wake up when we intrude */ 293. 	    (void) maketrap(zx-1, zy, SQBRD); 294. 	    (void) maketrap(zx+1, zy, SQBRD); 295. 	    (void) maketrap(zx, zy-1, SQBRD); 296. 	    (void) maketrap(zx, zy+1, SQBRD); 297. 	} else { 298. 	    maze0xy(&mm); 299. 	    zx = mm.x;  300. zy = mm.y; 301. walkfrom(zx,zy); 302. #ifndef STRONGHOLD	/* it's in the castle */ 303. # ifdef HARD		/* only one wand of wishing created */ 304. 	    if(!rn2(10) || (dlevel == medusa_level + 1)) 305. # endif 306. 		(void) mksobj_at(WAN_WISHING, zx, zy); 307. #endif 308. 	    (void) mksobj_at(BOULDER, zx, zy);  /* put a boulder on top of it */ 309. 	}  310.   311.  #ifdef WALLIFIED_MAZE 312. 	wallification(2, 2, x_maze_max, y_maze_max, TRUE); 313. #else 314. 	for(x = 2; x < x_maze_max; x++) 315. 		for(y = 2; y < y_maze_max; y++) { 316. 			switch(levl[x][y].typ) { 317. 			case STONE: 318. 				levl[x][y].scrsym = STONE_SYM; 319. 				break; 320. 			case CORR: 321. 				levl[x][y].scrsym = CORR_SYM; 322. 				break; 323. 			case ROOM: 324. 				levl[x][y].scrsym = ROOM_SYM; 325. 				break; 326. 			case HWALL: 327. 				levl[x][y].scrsym = HWALL_SYM; 328. 				break; 329. 			case VWALL: 330. 				levl[x][y].scrsym = VWALL_SYM; 331. 				break; 332. 			case TLCORNER: 333. 				levl[x][y].scrsym = TLCORN_SYM; 334. 				break; 335. 			case TRCORNER: 336. 				levl[x][y].scrsym = TRCORN_SYM; 337. 				break; 338. 			case BLCORNER: 339. 				levl[x][y].scrsym = BLCORN_SYM; 340. 				break; 341. 			case BRCORNER: 342. 				levl[x][y].scrsym = BRCORN_SYM; 343. 				break; 344. 			}  345.  		}  346.  #endif 347. 	mazexy(&mm); 348. 	levl[(xupstair = mm.x)][(yupstair = mm.y)].scrsym = UP_SYM; 349. 	levl[xupstair][yupstair].typ = STAIRS; 350. 	xdnstair = ydnstair = 0; 351. #ifdef STRONGHOLD 352. 	if (dlevel < stronghold_level) { 353. 		mazexy(&mm); 354. 		levl[(xdnstair = mm.x)][(ydnstair = mm.y)].scrsym = DN_SYM; 355. 		levl[xdnstair][ydnstair].typ = STAIRS; 356. 	}  357.  #endif 358. 	for(x = rn1(8,11); x; x--) { 359. 		mazexy(&mm); 360. 		(void) mkobj_at(rn2(2) ? GEM_SYM : 0, mm.x, mm.y); 361. 	}  362.  	for(x = rn1(10,2); x; x--) { 363. 		mazexy(&mm); 364. 		(void) mksobj_at(BOULDER, mm.x, mm.y); 365. 	}  366.  	mazexy(&mm); 367. 	(void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y); 368. 	for(x = rn1(5,7); x; x--) { 369. 		mazexy(&mm); 370. 		(void) makemon((struct permonst *) 0, mm.x, mm.y); 371. 	}  372.  	for(x = rn1(6,7); x; x--) { 373. 		mazexy(&mm); 374. 		mkgold(0L,mm.x,mm.y); 375. 	}  376.  	for(x = rn1(6,7); x; x--) 377. 		mktrap(0,1,(struct mkroom *) 0); 378. }  379.   380.  #ifdef MSDOS 381. /* Make the mazewalk iterative by faking a stack. This is needed to 382. * ensure the mazewalk is successful in the limited stack space of 383. * the program. This iterative version uses the mimumum amount of stack 384.  * that is totally safe. 385.  */  386.  void 387. walkfrom(x,y) 388. int x,y; 389. {  390.  #define CELLS (ROWNO * COLNO) / 4		/* a maze cell is 4 squares */ 391. 	char mazex[CELLS + 1], mazey[CELLS + 1];	/* char's are OK */ 392. 	int q, a, dir, pos; 393. 	int dirs[4]; 394.  395.  	pos = 1; 396. 	mazex[pos] = (char) x;  397. mazey[pos] = (char) y; 398. while (pos) { 399. 		x = (int) mazex[pos]; 400. 		y = (int) mazey[pos]; 401. #ifndef WALLIFIED_MAZE 402. 		levl[x][y].typ = CORR; 403. #else 404. 		levl[x][y].typ = ROOM; 405. #endif 406. 		q = 0; 407. 		for (a = 0; a < 4; a++) 408. 			if(okay(x, y, a)) dirs[q++]= a;  409. if (!q) 410. 			pos--; 411. 		else { 412. 			dir = dirs[rn2(q)]; 413. 			move(&x, &y, dir); 414. #ifndef WALLIFIED_MAZE 415. 			levl[x][y].typ = CORR; 416. #else 417. 			levl[x][y].typ = ROOM; 418. #endif 419. 			move(&x, &y, dir); 420. 			pos++; 421. 			if (pos > CELLS) 422. 				panic("Overflow in walkfrom"); 423. 			mazex[pos] = (char) x;  424. mazey[pos] = (char) y; 425. } 426.  	}  427.  }  428.  #else 429.  430.  void 431. walkfrom(x,y) int x,y; { 432. register int q,a,dir; 433. int dirs[4]; 434. #ifndef WALLIFIED_MAZE 435. 	levl[x][y].typ = CORR; 436. #else 437. 	levl[x][y].typ = ROOM; 438. #endif 439. 	while(1) { 440. 		q = 0; 441. 		for(a = 0; a < 4; a++) 442. 			if(okay(x,y,a)) dirs[q++]= a;  443. if(!q) return; 444. 		dir = dirs[rn2(q)]; 445. 		move(&x,&y,dir); 446. #ifndef WALLIFIED_MAZE 447. 		levl[x][y].typ = CORR; 448. #else 449. 		levl[x][y].typ = ROOM; 450. #endif 451. 		move(&x,&y,dir); 452. 		walkfrom(x,y); 453. 	}  454.  }  455.  #endif /* MSDOS */ 456.  457.  void 458. move(x,y,dir) 459. register int *x, *y; 460. register int dir; 461. {  462.  	switch(dir){ 463. 		case 0: --(*y); break; 464. 		case 1: (*x)++; break; 465. 		case 2: (*y)++; break; 466. 		case 3: --(*x); break; 467. 	}  468.  }  469.   470.  void 471. mazexy(cc)	/* find random point in generated corridors 472. 		   i.e., don't create items in moats, bunkers, or walls */ 473. 	coord	*cc; 474. {  475.  	int cpt=0; 476.  477.  	do { 478. 	    cc->x = 3 + 2*rn2((x_maze_max>>1) - 1); 479. 	    cc->y = 3 + 2*rn2((y_maze_max>>1) - 1); 480. 	    cpt++; 481. #ifndef WALLIFIED_MAZE 482. 	} while (cpt < 100 && levl[cc->x][cc->y].typ != CORR); 483. #else 484. 	} while (cpt < 100 && levl[cc->x][cc->y].typ != ROOM); 485. #endif 486. 	if (cpt >= 100) panic("mazexy: can't find a place!"); 487. 	return; 488. }  489.   490.  void 491. bound_digging 492. /* put a non-diggable boundary around the initial portion of a level map. 493.  * assumes that no level will initially put things beyond the isok range. 494.  */  495.  {  496.  	register int x,y; 497. 	register boolean found; 498. 	int xmin,xmax,ymin,ymax; 499.  500.  	found = FALSE; 501. 	for(xmin=1; !found; xmin++) 502. 		for(y=0; y<=ROWNO-1; y++) 503. 			if(levl[xmin][y].typ != STONE) found = TRUE; 504. 	xmin -= 2; 505.  506.  	found = FALSE; 507. 	for(xmax=COLNO-2; !found; xmax--) 508. 		for(y=0; y<=ROWNO-1; y++) 509. 			if(levl[xmax][y].typ != STONE) found = TRUE; 510. 	xmax += 2; 511.  512.  	found = FALSE; 513. 	for(ymin=1; !found; ymin++) 514. 		for(x=xmin; x<=xmax; x++) 515. 			if(levl[x][ymin].typ != STONE) found = TRUE; 516. 	ymin -= 2; 517.  518.  	found = FALSE; 519. 	for(ymax=ROWNO-2; !found; ymax--) 520. 		for(x=xmin; x<=xmax; x++) 521. 			if(levl[x][ymax].typ != STONE) found = TRUE; 522. 	ymax += 2; 523.  524.  	for(x=xmin; x<=xmax; x++) { 525. 		levl[x][ymin].diggable = W_NONDIGGABLE; 526. 		levl[x][ymax].diggable = W_NONDIGGABLE; 527. 	}  528.   529.  	for(y=ymin; y<=ymax; y++) { 530. 		levl[xmin][y].diggable = W_NONDIGGABLE; 531. 		levl[xmax][y].diggable = W_NONDIGGABLE; 532. 	}  533.  }