Source:Hack 1.0/mklev.c

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

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

1.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ 2.     3.    #include   4.    #include "mklev.h"  5.    #include "def.trap.h"  6. 7.   extern char *getlogin; 8.   extern struct monst *makemon; 9.    10.   char *tfile,*tspe,**args; 11.  char nul[40]; 12.   13.   #include "savelev.h"  14. 15.  #ifdef WIZARD 16.  boolean wizard; 17.  #endif WIZARD 18.   19.    20.   #define somex ((rand%(croom->hx-croom->lx+1))+croom->lx) 21.  #define somey ((rand%(croom->hy-croom->ly+1))+croom->ly) 22.   23.   struct rm levl[COLNO][ROWNO]; 24.  struct monst *fmon; 25.  struct obj *fobj; 26.  struct gen *fgold, *ftrap; 27.   28.   char *fut_geno;		/* monsters that should not be created anymore */ 29.   30.   struct mkroom rooms[MAXNROFROOMS+1], *croom, *troom; 31.  coord doors[DOORMAX]; 32.  int doorindex = 0; 33.  int comp; 34.   35.   xchar dlevel; 36.  schar nxcor,xx,yy,dx,dy,tx,ty; /* for corridors and other things... */ 37.   boolean goldseen; 38.  int nroom; 39.   40.   xchar xdnstair,xupstair,ydnstair,yupstair; 41.   42.    43.   main(argc,argv) 44.  char *argv[]; 45.  {  46.   	register unsigned tryct; 47.   48.   	if(argc < 6) panic("Too few arguments!!"); 49.  	args = argv; 50.  	tfile = argv[1]; 51.  	tspe = argv[2]; 52.  	dlevel = atoi(argv[3]); 53.  	if(dlevel < 1) panic("Bad level"); 54.  	fut_geno = argv[4]; 55.  #ifdef WIZARD 56.  	wizard = (argv[5][0] == 'w'); 57.  #endif WIZARD 58.  	(void) srand(getpid); 59.  	init_objects; 60.  	rooms[0].hx = -1;	/* in case we are in a maze */ 61.   62.   	/* a: normal; b: maze */ 63.  	if(*tspe == 'b') { 64.  		makemaz; 65.  		savelev; 66.  		exit(0); 67.  	}  68.    69.   	/* construct the rooms */ 70.  	while(nroom < (MAXNROFROOMS/3)) { 71.  		croom = rooms; 72.  		nroom = 0; 73.  		(void) makerooms(0);		/* not secret */ 74.  	}  75.    76.   	/* for each room: put things inside */ 77.  	for(croom = rooms; croom->hx > 0; croom++) { 78.   79.   		/* put a sleeping monster inside */ 80.  		if(!rn2(3)) (void) 81.  			makemon((struct permonst *) 0, somex, somey); 82.   83.   		/* put traps and mimics inside */ 84.  		goldseen = FALSE; 85.  		while(!rn2(8-(dlevel/6))) mktrap(0,0); 86.  		if(!goldseen && !rn2(3)) mkgold(0,somex,somey); 87.  		if(!rn2(3)) { 88.  			mkobj_at(0, somex, somey); 89.  			tryct = 0; 90.  			while(!rn2(5)) { 91.  				if(++tryct > 100){ 92.  					printf("tryct overflow4\n"); 93.  					break; 94.  				}  95.    mkobj_at(0, somex, somey); 96.  			}  97.   		}  98.   	}  99.   	tryct = 0; 100. 	do { 101. 		if(++tryct > 1000) panic("Cannot make dnstairs\n"); 102. 		croom = &rooms[rn2(nroom)]; 103. 		xdnstair = somex; 104. 		ydnstair = somey; 105. 	} while((*tspe =='n' && (!(xdnstair%2) || !(ydnstair%2))) ||  106.  		g_at(xdnstair,ydnstair,ftrap)); 107. 	levl[xdnstair][ydnstair].scrsym ='>'; 108. 	levl[xdnstair][ydnstair].typ = STAIRS; 109. 	troom = croom; 110. 	do { 111. 		if(++tryct > 2000) panic("Cannot make upstairs\n"); 112. 		croom = &rooms[rn2(nroom)]; 113. 		xupstair = somex; 114. 		yupstair = somey; 115. 	} while(croom == troom || m_at(xupstair,yupstair) ||  116.  		g_at(xupstair,yupstair,ftrap)); 117. 	levl[xupstair][yupstair].scrsym ='<'; 118. 	levl[xupstair][yupstair].typ = STAIRS; 119.  120.  	qsort((char *) rooms, nroom, sizeof(struct mkroom), comp); 121. 	croom = rooms; 122. 	troom = croom+1; 123. 	nxcor = 0; 124. 	mkpos; 125. 	do makecor; 126. 	while (croom->hx > 0 && troom->hx > 0); 127.  128.  	/* make a secret treasure vault, not connected to the rest */ 129. 	if(nroom < (2*MAXNROFROOMS/3)) if(!rn2(3)) { 130. 		register int x,y; 131. 		troom = croom = &rooms[nroom]; 132. 		if(makerooms(1)) {		/* make secret room */ 133. 			troom->rtype = 6;		/* treasure vault */ 134. 			for(x = troom->lx; x <= troom->hx; x++) 135. 			for(y = troom->ly; y <= troom->hy; y++) 136. 				mkgold(rnd(dlevel*100) + 50, x, y); 137. 		}  138.  	}  139.   140.  #ifdef WIZARD 141. 	if(wizard){ 142. 		if(rn2(3)) mkshop; else mkzoo; 143. 	} else 144. #endif WIZARD 145.  	if(dlevel > 1 && dlevel < 20 && rn2(dlevel) < 2) mkshop; 146. 	else 147. 	if(dlevel > 6 && (!rn2(7) || !strcmp("david", getlogin))) 148. 		mkzoo; 149. 	savelev; 150. 	exit(0); 151. }  152.   153.  makerooms(secret) int secret; { 154. register int lowx, lowy; 155. register int tryct = 0; 156. 	while(nroom < (MAXNROFROOMS/2) || secret) 157. 	    for(lowy = rn1(3,3); lowy < ROWNO-7; lowy += rn1(2,4)) { 158. 		for(lowx = rn1(3,4); lowx < COLNO-10; lowx += rn1(2,7)) { 159. 			if(tryct++ > 10000) return(0); 160. 			if((lowy += (rn2(5)-2)) < 3) lowy = 3; 161. 			else if(lowy > ROWNO-6) lowy = ROWNO-6; 162. 			if(levl[lowx][lowy].typ) continue; 163. 			if((secret && maker(lowx, 1, lowy, 1)) ||  164.  			   (!secret && maker(lowx,rn1(9,2),lowy,rn1(4,2)) 165. 				&& nroom+2 > MAXNROFROOMS)) return(1); 166. 		}  167.  	}  168.   return(1); 169. }  170.   171.  comp(x,y) 172. register struct mkroom *x,*y; 173. {  174.  	if(x->lx < y->lx) return(-1); 175. 	return(x->lx > y->lx); 176. }  177.   178.  coord 179. finddpos(xl,yl,xh,yh) { 180. coord ff; 181. register x,y; 182. 	ff.x = (xl == xh) ? xl : (xl + rn2(xh-xl+1)); 183. 	ff.y = (yl == yh) ? yl : (yl + rn2(yh-yl+1)); 184. 	if(okdoor(ff.x, ff.y)) return(ff); 185. 	if(xl < xh) for(x = xl; x <= xh; x++) 186. 		if(okdoor(x, ff.y)){ 187. 			ff.x = x;  188. return(ff); 189. 		}  190.  	if(yl < yh) for(y = yl; y <= yh; y++) 191. 		if(okdoor(ff.x, y)){ 192. 			ff.y = y;  193. return(ff); 194. 		}  195.   return(ff); 196. }  197.   198.  /* when croom and troom exist, find position for a door in croom 199.    and direction for a corridor towards position [tx,ty] in the wall 200.    of troom */ 201. mkpos 202. {  203.  coord cc,tt; 204. 	if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return; 205. 	if(troom->lx > croom->hx) { 206. 		dx = 1; 207. 		dy = 0; 208. 		xx = croom->hx+1; 209. 		tx = troom->lx-1; 210. 		cc = finddpos(xx,croom->ly,xx,croom->hy); 211. 		tt = finddpos(tx,troom->ly,tx,troom->hy); 212. 	} else if(troom->hy < croom->ly) { 213. 		dy = -1; 214. 		dx = 0; 215. 		yy = croom->ly-1; 216. 		cc = finddpos(croom->lx,yy,croom->hx,yy); 217. 		ty = troom->hy+1; 218. 		tt = finddpos(troom->lx,ty,troom->hx,ty); 219. 	} else if(troom->hx < croom->lx) { 220. 		dx = -1; 221. 		dy = 0; 222. 		xx = croom->lx-1; 223. 		tx = troom->hx+1; 224. 		cc = finddpos(xx,croom->ly,xx,croom->hy); 225. 		tt = finddpos(tx,troom->ly,tx,troom->hy); 226. 	} else { 227. 		dy = 1; 228. 		dx = 0; 229. 		yy = croom->hy+1; 230. 		ty = troom->ly-1; 231. 		cc = finddpos(croom->lx,yy,croom->hx,yy); 232. 		tt = finddpos(troom->lx,ty,troom->hx,ty); 233. 	}  234.  	xx = cc.x;  235. yy = cc.y; 236. tx = tt.x; 237. ty = tt.y; 238. if(levl[xx+dx][yy+dy].typ) { 239. 		if(nxcor) newloc; 240. 		else { 241. 			dodoor(xx,yy,croom); 242. 			xx += dx; 243. 			yy += dy; 244. 		}  245.   return; 246. 	}  247.   dodoor(xx,yy,croom); 248. }  249.   250.  /* if allowable, create a door at [x,y] */ 251. okdoor(x,y) 252. register x,y; 253. {  254.  	if(levl[x-1][y].typ == DOOR || levl[x+1][y].typ == DOOR ||  255.  	   levl[x][y+1].typ == DOOR || levl[x][y-1].typ == DOOR ||  256.  	   levl[x-1][y].typ == SDOOR || levl[x+1][y].typ == SDOOR ||  257.  	   levl[x][y-1].typ == SDOOR || levl[x][y+1].typ == SDOOR ||  258.  	   (levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) ||  259.  	   doorindex >= DOORMAX) 260. 		return(0); 261. 	return(1); 262. }  263.   264.  dodoor(x,y,aroom) 265. register x,y; 266. register struct mkroom *aroom; 267. {  268.  	register struct mkroom *broom; 269. 	register tmp; 270. 	if(doorindex >= DOORMAX) panic("DOORMAX exceeded?"); 271. 	if(!okdoor(x,y) && nxcor) return; 272. 	if(!rn2(8)) levl[x][y].typ = SDOOR; 273. 	else { 274. 		levl[x][y].scrsym ='+'; 275. 		levl[x][y].typ = DOOR; 276. 	}  277.  	aroom->doorct++; 278. 	broom = aroom+1; 279. 	if(broom->hx < 0) tmp = doorindex; else 280. 	for(tmp = doorindex; tmp > broom->fdoor; tmp--) 281. 		doors[tmp] = doors[tmp-1]; 282. 	doorindex++; 283. 	doors[tmp].x = x;  284. doors[tmp].y = y; 285. for(broom->hx >= 0; broom++) broom->fdoor++; 286. }  287.   288.  newloc 289. {  290.  	register a,b; 291. 	register int tryct = 0; 292.  293.  	++croom; 294. 	++troom; 295. 	if(nxcor || croom->hx < 0 || troom->hx < 0) { 296. 		if(nxcor++ > rn1(nroom,4)) { 297. 			croom = &rooms[nroom]; 298. 			return; 299. 		}  300.  		do { 301. 			if(++tryct > 100){ 302. 				printf("tryct overflow5\n"); 303. 				croom = &rooms[nroom]; 304. 				return; 305. 			}  306.  			a = rn2(nroom); 307. 			b = rn2(nroom); 308. 			croom = &rooms[a]; 309. 			troom = &rooms[b]; 310. 		} while(croom == troom || (troom == croom+1 && !rn2(3))); 311. 	}  312.   mkpos; 313. }  314.   315.  /* make a trap somewhere (in croom if mazeflag = 0) */ 316. mktrap(num,mazeflag) 317. register num,mazeflag; 318. {  319.  	register struct gen *gtmp; 320. 	register int kind,nopierc,nomimic,fakedoor,fakegold,tryct = 0; 321. 	register xchar mx,my; 322.  323.  	if(!num || num >= TRAPNUM) { 324. 		nopierc = (dlevel < 4) ? 1 : 0; 325.  		nomimic = (dlevel < 9 || goldseen ) ? 1 : 0; 326.  		if(index(fut_geno, 'M')) nomimic = 1; 327. 		kind = rn2(TRAPNUM - nopierc - nomimic); 328. 		/* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */ 329. 	} else kind = num; 330.  331.  	if(kind == MIMIC) { 332. 		register struct monst *mtmp; 333.  334.  		fakedoor = (!rn2(3) && !mazeflag); 335. 		fakegold = (!fakedoor && !rn2(2)); 336. 		if(fakegold) goldseen = TRUE; 337. 		do { 338. 			if(++tryct > 200) return; 339. 			if(fakedoor) { 340. 				/* note: fakedoor maybe on actual door */ 341. 				if(rn2(2)){ 342. 					if(rn2(2)) 343. 						mx = croom->hx+1; 344. 					else mx = croom->lx-1; 345. 					my = somey; 346. 				} else { 347. 					if(rn2(2)) 348. 						my = croom->hy+1; 349. 					else my = croom->ly-1; 350. 					mx = somex; 351. 				}  352.  			} else if(mazeflag) { 353. 				extern coord mazexy; 354. 				coord mm; 355. 				mm = mazexy; 356. 				mx = mm.x;  357. my = mm.y; 358. } else { 359. 				mx = somex; 360. 				my = somey; 361. 			}  362.  		} while(m_at(mx,my)); 363. 		if(mtmp = makemon(PM_MIMIC,mx,my)) 364. 		    mtmp->mimic = 365. 			fakegold ? '$' : fakedoor ? '+' : 366.  			(mazeflag && rn2(2)) ? AMULET_SYM : 367. 			"=/)%?![<>" [ rn2(9) ];  368.  		return;  369.  	}  370.  	gtmp = newgen;  371.  	gtmp->gflag = kind;  372.  	do {  373.  		if(++tryct > 200){  374.  			printf("tryct overflow7\n");  375.  			free((char *) gtmp);  376.  			return;  377.  		}  378.  		if(mazeflag){  379.  			extern coord mazexy;  380.  			coord mm;  381.  			mm = mazexy;  382.  			gtmp->gx = mm.x;  383.  			gtmp->gy = mm.y;  384.  		} else {  385.  			gtmp->gx = somex;  386.  			gtmp->gy = somey;  387.  		}  388.  	} while(g_at(gtmp->gx, gtmp->gy, ftrap));  389.  	gtmp->ngen = ftrap;  390.  	ftrap = gtmp;  391.  	if(mazeflag && !rn2(10) && gtmp->gflag < PIERC) gtmp->gflag |= SEEN;  392.  }  393.   394.  /*VARARGS1*/  395.  panic(str,arg1,arg2,arg3)  396.  char *str,*arg1,*arg2,*arg3;  397.  {  398.  	char bufr[BUFSZ];  399.  	extern char *sprintf;  400.  	(void) sprintf(bufr,str,arg1,arg2,arg3);  401. (void) write(1,"\nMKLEV ERROR: ",15); 402. 	puts(bufr); 403. 	(void) fflush(stdout); 404. 	exit(1); 405. }  406.   407.  maker(lowx,ddx,lowy,ddy) 408. schar lowx,ddx,lowy,ddy; 409. {  410.  	register x, y, hix = lowx+ddx, hiy = lowy+ddy; 411.  412.  	if(nroom >= MAXNROFROOMS) return(0); 413. 	if(hix > COLNO-5) hix = COLNO-5; 414. 	if(hiy > ROWNO-4) hiy = ROWNO-4; 415. chk: 416. 	if(hix <= lowx || hiy <= lowy) return(0); 417.  418.  	/* check area around room (and make room smaller if necessary) */ 419. 	for(x = lowx-4; x <= hix+4; x++) 420. 		for(y = lowy-3; y <= hiy+3; y++) 421. 			if(levl[x][y].typ) { 422. 				if(rn2(3)) return(0); 423. 				lowx = x+5; 424. 				lowy = y+4; 425. 				goto chk; 426. 			}  427.   428.  	/* on low levels the room is lit (usually) */ 429. 	/* secret vaults are always lit */ 430. 	if((rnd(dlevel) < 10 && rn2(77)) || (ddx == 1 && ddy == 1)) 431. 		for(x = lowx-1; x <= hix+1; x++) 432. 			for(y = lowy-1; y <= hiy+1; y++) 433. 				levl[x][y].lit = 1; 434. 	croom->lx = lowx; 435. 	croom->hx = hix; 436. 	croom->ly = lowy; 437. 	croom->hy = hiy; 438. 	croom->rtype = croom->doorct = croom->fdoor = 0; 439. 	for(x = lowx-1; x <= hix+1; x++) 440. 	    for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) { 441. 		levl[x][y].scrsym = '-'; 442. 		levl[x][y].typ = HWALL; 443. 	}  444.  	for(x = lowx-1; x <= hix+1; x += (hix-lowx+2)) 445. 	    for(y = lowy; y <= hiy; y++) { 446. 		levl[x][y].scrsym = '|'; 447. 		levl[x][y].typ = VWALL; 448. 	}  449.  	for(x = lowx; x <= hix; x++) 450. 	    for(y = lowy; y <= hiy; y++) { 451. 		levl[x][y].scrsym = '.'; 452. 		levl[x][y].typ = ROOM; 453. 	}  454.  	croom++; 455. 	croom->hx = -1; 456. 	nroom++; 457. 	return(1); 458. }  459.   460.  makecor { 461. 	register nx, ny; 462. 	register struct rm *crm; 463. 	register dix, diy, secondtry = 0; 464.  465.  tryagain: 466. 	nx = xx + dx; 467. 	ny = yy + dy; 468.  469.  	if(nxcor && !rn2(35)) { 470. 		newloc; 471. 		return; 472. 	}  473.  	if(nx == COLNO-1 || nx == 0 || ny == 0 || ny == ROWNO-1) { 474. 		if(nxcor) { 475. 			newloc; 476. 			return; 477. 		} else { 478. 			printf("something went wrong. we try again...\n"); 479. 		execl("./mklev",args[0],tfile,tspe,args[3],args[4],args[5],0); 480. 			panic("cannot execute ./mklev\n"); 481. 		}  482.  	}  483.   484.  	dix = abs(nx-tx); 485. 	diy = abs(ny-ty); 486. 	if(dy && dix > diy) { 487. 		dy = 0; 488. 		dx = (nx > tx) ? -1 : 1; 489.  	} else if(dx && diy > dix) { 490. 		dx = 0; 491. 		dy = (ny > ty) ? -1 : 1; 492.  	}  493.   494.  	crm = &levl[nx][ny]; 495. 	if(!(crm->typ)) { 496. 		if(rn2(100)) { 497. 			crm->typ = CORR; 498. 			crm->scrsym = CORR_SYM; 499. 		} else { 500. 			crm->typ = SCORR; 501. 			crm->scrsym = ' '; 502. 		}  503.  		xx = nx; 504. 		yy = ny; 505. 		if(nxcor && !rn2(50)) { 506. 			mkobj_at(ROCK_SYM, nx, ny); 507. 		}  508.   return; 509. 	}  510.  	if(crm->typ == CORR || crm->typ == SCORR) { 511. 		xx = nx; 512. 		yy = ny; 513. 		return; 514. 	}  515.  	if(nx == tx && ny == ty) { 516. 		dodoor(nx,ny,troom); 517. 		newloc; 518. 		return; 519. 	}  520.  	if(!secondtry++ && (nx != xx+dx || ny != yy+dy)) 521. 		goto tryagain; 522. 	if(dx) { 523. 		if(ty < ny) dy = -1; 524. 		else dy = levl[nx+dx][ny-1].typ == ROOM?1:-1; 525. 		dx = 0; 526. 	} else { 527. 		if(tx < nx) dx = -1; 528. 		else dx = levl[nx-1][ny+dy].typ == ROOM?1:-1; 529. 		dy = 0; 530. 	}  531.  }  532.   533.  struct monst * 534. m_at(x,y) 535. register x,y; 536. {  537.  	register struct monst *mtmp; 538.  539.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 540. 		if(mtmp->mx == x && mtmp->my == y) return(mtmp); 541. 	return(0); 542. }  543.   544.  struct gen * 545. g_at(x,y,ptr) 546. register x,y; 547. register struct gen *ptr; 548. {  549.  	while(ptr) { 550. 		if(ptr->gx == x && ptr->gy == y) return(ptr); 551. 		ptr = ptr->ngen; 552. 	}  553.   return(0); 554. }