Source:NetHack 3.4.0/mkmap.c

Below is the full text to mkmap.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/mkmap.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)mkmap.c	3.4	1996/05/23	*/ 2.   /* Copyright (c) J. C. Collet, M. Stephenson and D. Cohrs, 1992   */ 3.   /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6.    #include "sp_lev.h"  7. 8.   #define HEIGHT	(ROWNO - 1) 9.   #define WIDTH	(COLNO - 2) 10.   11.   STATIC_DCL void FDECL(init_map,(SCHAR_P)); 12.  STATIC_DCL void FDECL(init_fill,(SCHAR_P,SCHAR_P)); 13.  STATIC_DCL schar FDECL(get_map,(int,int,SCHAR_P)); 14.  STATIC_DCL void FDECL(pass_one,(SCHAR_P,SCHAR_P)); 15.  STATIC_DCL void FDECL(pass_two,(SCHAR_P,SCHAR_P)); 16.  STATIC_DCL void FDECL(pass_three,(SCHAR_P,SCHAR_P)); 17.  STATIC_DCL void NDECL(wallify_map); 18.  STATIC_DCL void FDECL(join_map,(SCHAR_P,SCHAR_P)); 19.  STATIC_DCL void FDECL(finish_map,(SCHAR_P,SCHAR_P,XCHAR_P,XCHAR_P)); 20.  void FDECL(mkmap, (lev_init *)); 21.   22.   char *new_locations; 23.  int min_rx, max_rx, min_ry, max_ry; /* rectangle bounds for regions */ 24.  static int n_loc_filled; 25.   26.   STATIC_OVL void 27.  init_map(bg_typ) 28.  	schar	bg_typ; 29.  {  30.   	register int i,j; 31.   32.   	for(i=1; i<COLNO; i++) 33.  	    for(j=0; j<ROWNO; j++) 34.  		levl[i][j].typ = bg_typ; 35.  }  36.    37.   STATIC_OVL void 38.  init_fill(bg_typ, fg_typ) 39.  	schar	bg_typ, fg_typ; 40.  {  41.   	register int i,j; 42.  	long limit, count; 43.   44.   	limit = (WIDTH * HEIGHT * 2) / 5; 45.  	count = 0; 46.  	while(count < limit) { 47.  	    i = rn1(WIDTH-1, 2); 48.  	    j = rnd(HEIGHT-1); 49.  	    if (levl[i][j].typ == bg_typ) { 50.  		levl[i][j].typ = fg_typ; 51.  		count++; 52.  	    }  53.   	}  54.   }  55.    56.   STATIC_OVL schar 57.  get_map(col,row, bg_typ) 58.  	int col,row; 59.  	schar	bg_typ; 60.  {  61.   	if (col <= 0 || row < 0 || col > WIDTH || row >= HEIGHT) 62.  		return bg_typ; 63.  	return levl[col][row].typ; 64.  }  65.    66.   static int dirs[16] = { 67.      -1, -1 /**/, -1, 0 /**/, -1, 1 /**/,  68.        0, -1 /**/,              0, 1 /**/,  69.        1, -1 /**/,  1, 0 /**/,  1, 1};  70.    71.   STATIC_OVL void 72.  pass_one(bg_typ, fg_typ) 73.  	schar	bg_typ, fg_typ; 74.  {  75.   	register int i,j; 76.  	short count, dr; 77.   78.   	for(i=2; i<=WIDTH; i++) 79.  	    for(j=1; j<HEIGHT; j++) { 80.  		for(count=0, dr=0; dr < 8; dr++) 81.  		    if(get_map(i+dirs[dr*2], j+dirs[(dr*2)+1], bg_typ)  82.   								== fg_typ) 83.  			count++; 84.   85.   		switch(count) { 86.  		  case 0 : /* death */ 87.  		  case 1 : 88.  		  case 2: 89.  			  levl[i][j].typ = bg_typ; 90.  			  break; 91.  		  case 5: 92.  		  case 6: 93.  		  case 7: 94.  		  case 8: 95.  			  levl[i][j].typ = fg_typ; 96.  			  break; 97.  		  default: 98.  			  break; 99.  		  }  100.  	    }  101.  }  102.   103.  #define new_loc(i,j)	*(new_locations+ ((j)*(WIDTH+1)) + (i)) 104.  105.  STATIC_OVL void 106. pass_two(bg_typ, fg_typ) 107. 	schar	bg_typ, fg_typ; 108. {  109.  	register int i,j; 110. 	short count, dr; 111.  112.  	for(i=2; i<=WIDTH; i++) 113. 	    for(j=1; j<HEIGHT; j++) { 114. 		for(count=0, dr=0; dr < 8; dr++) 115. 		    if(get_map(i+dirs[dr*2], j+dirs[(dr*2)+1], bg_typ)  116.  								== fg_typ) 117. 			count++; 118. 		    if (count == 5) 119. 			new_loc(i,j) = bg_typ; 120. 		    else 121. 			new_loc(i,j) = get_map(i,j, bg_typ); 122. 	    }  123.   124.  	for(i=2; i<=WIDTH; i++) 125. 	    for(j=1; j<HEIGHT; j++) 126. 		levl[i][j].typ = new_loc(i,j); 127. }  128.   129.  STATIC_OVL void 130. pass_three(bg_typ, fg_typ) 131. 	schar	bg_typ, fg_typ; 132. {  133.  	register int i,j; 134. 	short count, dr; 135.  136.  	for(i=2; i<=WIDTH; i++) 137. 	    for(j=1; j<HEIGHT; j++) { 138. 		for(count=0, dr=0; dr < 8; dr++) 139. 		    if(get_map(i+dirs[dr*2], j+dirs[(dr*2)+1], bg_typ)  140.  								== fg_typ) 141. 			count++; 142. 		if (count < 3) 143. 		    new_loc(i,j) = bg_typ; 144. 		else 145. 		    new_loc(i,j) = get_map(i,j, bg_typ); 146. 	    }  147.   148.  	for(i=2; i<=WIDTH; i++) 149. 	    for(j=1; j<HEIGHT; j++) 150. 		levl[i][j].typ = new_loc(i,j); 151. }  152.   153.  /*  154.   * use a flooding algorithm to find all locations that should 155.  * have the same rm number as the current location. 156.  * if anyroom is TRUE, use IS_ROOM to check room membership instead of  157. * exactly matching levl[sx][sy].typ and walls are included as well. 158.  */  159.  void 160. flood_fill_rm(sx, sy, rmno, lit, anyroom) 161.     int sx; 162.     register int sy; 163.     register int rmno; 164.     boolean lit; 165.     boolean anyroom; 166. {  167.      register int i;  168. int nx; 169.     schar fg_typ = levl[sx][sy].typ; 170.  171.      /* back up to find leftmost uninitialized location */ 172.     while (sx > 0 &&  173.  	  (anyroom ? IS_ROOM(levl[sx][sy].typ) : levl[sx][sy].typ == fg_typ) && 174.  	  (int) levl[sx][sy].roomno != rmno) 175. 	sx--; 176.     sx++; /* compensate for extra decrement */ 177.  178.      /* assume sx,sy is valid */ 179.     if(sx < min_rx) min_rx = sx; 180.     if(sy < min_ry) min_ry = sy; 181.  182.      for(i=sx; i<=WIDTH && levl[i][sy].typ == fg_typ; i++) { 183. 	levl[i][sy].roomno = rmno; 184. 	levl[i][sy].lit = lit; 185. 	if(anyroom) { 186. 	    /* add walls to room as well */ 187. 	    register int ii,jj; 188. 	    for(ii= (i == sx ? i-1 : i); ii <= i+1; ii++) 189. 		for(jj = sy-1; jj <= sy+1; jj++) 190. 		    if(isok(ii,jj) &&  191.  		       (IS_WALL(levl[ii][jj].typ) || 192. 			IS_DOOR(levl[ii][jj].typ))) { 193. 			levl[ii][jj].edge = 1; 194. 			if(lit) levl[ii][jj].lit = lit; 195. 			if ((int) levl[ii][jj].roomno != rmno) 196. 			    levl[ii][jj].roomno = SHARED; 197. 		    }  198.  	}  199.  	n_loc_filled++; 200.     }  201.      nx = i;  202. 203.     if(isok(sx,sy-1)) { 204. 	for(i=sx; isx || isok(i-1,sy-1)) &&  210.  		      levl[i-1][sy-1].typ == fg_typ) { 211. 		    if ((int) levl[i-1][sy-1].roomno != rmno) 212. 			flood_fill_rm(i-1,sy-1,rmno,lit,anyroom); 213. 		}  214.  		if((isx || isok(i-1,sy+1)) &&  228.  		      levl[i-1][sy+1].typ == fg_typ) { 229. 		    if ((int) levl[i-1][sy+1].roomno != rmno) 230. 			flood_fill_rm(i-1,sy+1,rmno,lit,anyroom); 231. 		}  232.  		if((i max_rx) max_rx = nx - 1; /* nx is just past valid region */ 241.     if(sy > max_ry) max_ry = sy; 242. }  243.   244.  /*  245.   *	If we have drawn a map without walls, this allows us to  246. *	auto-magically wallify it. Taken from lev_main.c. 247. */ 248.  STATIC_OVL void 249. wallify_map 250. {  251.   252.      int x, y, xx, yy; 253.  254.      for(x = 1; x < COLNO; x++) 255. 	for(y = 0; y < ROWNO; y++) 256. 	    if(levl[x][y].typ == STONE) { 257. 		for(yy = y - 1; yy <= y+1; yy++) 258. 		    for(xx = x - 1; xx <= x+1; xx++) 259. 			if(isok(xx,yy) && levl[xx][yy].typ == ROOM) { 260. 			    if(yy != y)	levl[x][y].typ = HWALL; 261. 			    else	levl[x][y].typ = VWALL; 262. 			}  263.  	    }  264.  }  265.   266.  STATIC_OVL void 267. join_map(bg_typ, fg_typ) 268. 	schar	bg_typ, fg_typ; 269. {  270.      register struct mkroom *croom, *croom2; 271.  272.      register int i, j;  273. int sx, sy; 274.     coord sm, em; 275.  276.      /* first, use flood filling to find all of the regions that need joining */ 277.     for(i=2; i<=WIDTH; i++) 278. 	for(j=1; j 3) { 285. 		    add_room(min_rx, min_ry, max_rx, max_ry,  286.  			     FALSE, OROOM, TRUE); 287. 		    rooms[nroom-1].irregular = TRUE; 288. 		    if(nroom >= (MAXNROFROOMS*2)) 289. 			goto joinm; 290. 		} else { 291. 		    /*  292.  		     * it's a tiny hole; erase it from the map to avoid 293. 		     * having the player end up here with no way out. 294. 		     */  295.  		    for(sx = min_rx; sx<=max_rx; sx++) 296. 			for(sy = min_ry; sy<=max_ry; sy++) 297. 			    if ((int) levl[sx][sy].roomno ==  298.  				    nroom + ROOMOFFSET) { 299. 				levl[sx][sy].typ = bg_typ; 300. 				levl[sx][sy].roomno = NO_ROOM; 301. 			    }  302.  		}  303.  	    }  304.  	}  305.   306.  joinm: 307.     /*  308.       * Ok, now we can actually join the regions with fg_typ's.  309. * The rooms are already sorted due to the previous loop, 310.      * so don't call sort_rooms, which can screw up the roomno's  311. * validity in the levl structure. 312.      */  313.      for(croom = &rooms[0], croom2 = croom + 1; croom2 < &rooms[nroom]; ) { 314. 	/* pick random starting and end locations for "corridor" */ 315. 	if(!somexy(croom, &sm) || !somexy(croom2, &em)) { 316. 	    /* ack! -- the level is going to be busted */ 317. 	    /* arbitrarily pick centers of both rooms and hope for the best */ 318. 	    impossible("No start/end room loc in join_map."); 319. 	    sm.x = croom->lx + ((croom->hx - croom->lx) / 2); 320. 	    sm.y = croom->ly + ((croom->hy - croom->ly) / 2); 321. 	    em.x = croom2->lx + ((croom2->hx - croom2->lx) / 2); 322. 	    em.y = croom2->ly + ((croom2->hy - croom2->ly) / 2); 323. 	}  324.   325.  	(void) dig_corridor(&sm, &em, FALSE, fg_typ, bg_typ); 326.  327.  	/* choose next region to join */ 328. 	/* only increment croom if croom and croom2 are non-overlapping */ 329. 	if(croom2->lx > croom->hx ||  330.  	   ((croom2->ly > croom->hy || croom2->hy < croom->ly) && rn2(3))) { 331. 	    croom = croom2; 332. 	}  333.  	croom2++; /* always increment the next room */ 334.     }  335.  }  336.   337.  STATIC_OVL void 338. finish_map(fg_typ, bg_typ, lit, walled) 339. 	schar	fg_typ, bg_typ; 340. 	boolean	lit, walled; 341. {  342.  	int	i, j;  343. 344. 	if(walled) wallify_map; 345.  346.  	if(lit) { 347. 	    for(i=1; i<COLNO; i++) 348. 		for(j=0; j<ROWNO; j++) 349. 		    if((!IS_ROCK(fg_typ) && levl[i][j].typ == fg_typ) ||  350.  		       (!IS_ROCK(bg_typ) && levl[i][j].typ == bg_typ) ||  351.  		       (bg_typ == TREE && levl[i][j].typ == bg_typ) ||  352.  			(walled && IS_WALL(levl[i][j].typ))) 353. 			levl[i][j].lit = TRUE; 354. 	    for(i = 0; i < nroom; i++) 355. 		rooms[i].rlit = 1; 356. 	}  357.  	/* light lava even if everything's otherwise unlit */ 358. 	for(i=1; ibg, 374. 		fg_typ = init_lev->fg; 375. 	boolean smooth = init_lev->smoothed, 376. 		join = init_lev->joined; 377. 	xchar   lit = init_lev->lit, 378. 		walled = init_lev->walled; 379. 	int i;  380. 381. 	if(lit < 0) 382. 	    lit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? 1 : 0; 383.   384.  	new_locations = (char *)alloc((WIDTH+1) * HEIGHT); 385.  386.  	init_map(bg_typ); 387. 	init_fill(bg_typ, fg_typ); 388.  389.  	for(i = 0; i < N_P1_ITER; i++) 390. 	    pass_one(bg_typ, fg_typ); 391.  392.  	for(i = 0; i < N_P2_ITER; i++) 393. 	pass_two(bg_typ, fg_typ); 394.  395.  	if(smooth) 396. 	    for(i = 0; i < N_P3_ITER; i++) 397. 		pass_three(bg_typ, fg_typ); 398.  399.  	if(join) 400. 	    join_map(bg_typ, fg_typ); 401.  402.  	finish_map(fg_typ, bg_typ, (boolean)lit, (boolean)walled); 403. 	/* a walled, joined level is cavernous, not mazelike -dlc */ 404. 	if (walled && join) { 405. 	    level.flags.is_maze_lev = FALSE; 406. 	    level.flags.is_cavernous_lev = TRUE; 407. 	}  408.  	free(new_locations); 409. }  410.   411.  /*mkmap.c*/