Wikihack
Advertisement

Below is the full text to src/extralev.c from NetHack 3.4.3. To link to a particular line, write [[extralev.c#line123]], for example.

Top of file[]

1.    /*	SCCS Id: @(#)extralev.c	3.4	2001/09/06	*/
2.    /*	Copyright 1988, 1989 by Ken Arromdee				*/
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
5.    /*
6.     * Support code for "rogue"-style level.
7.     */
8.    
9.    #include "hack.h"
10.   
11.   #ifdef REINCARNATION
12.   
13.   struct rogueroom {
14.   	xchar rlx, rly;
15.   	xchar dx, dy;
16.   	boolean real;
17.   	uchar doortable;
18.   	int nroom; /* Only meaningful for "real" rooms */
19.   };
20.   #define UP 1
21.   #define DOWN 2
22.   #define LEFT 4
23.   #define RIGHT 8
24.   
25.   static NEARDATA struct rogueroom r[3][3];
26.   STATIC_DCL void FDECL(roguejoin,(int,int,int,int,int));
27.   STATIC_DCL void FDECL(roguecorr,(int,int,int));
28.   STATIC_DCL void FDECL(miniwalk,(int,int));
29.   

roguejoin[]

30.   STATIC_OVL
31.   void
32.   roguejoin(x1,y1,x2,y2, horiz)
33.   int x1,y1,x2,y2;
34.   int horiz;
35.   {
36.   	register int x,y,middle;
37.   #ifndef MAX
38.   #define MAX(a,b) (((a) > (b)) ? (a) : (b))
39.   #endif
40.   #ifndef MIN
41.   #define MIN(a,b) (((a) < (b)) ? (a) : (b))
42.   #endif
43.   	if (horiz) {
44.   		middle = x1 + rn2(x2-x1+1);
45.   		for(x=MIN(x1,middle); x<=MAX(x1,middle); x++)
46.   			corr(x, y1);
47.   		for(y=MIN(y1,y2); y<=MAX(y1,y2); y++)
48.   			corr(middle,y);
49.   		for(x=MIN(middle,x2); x<=MAX(middle,x2); x++)
50.   			corr(x, y2);
51.   	} else {
52.   		middle = y1 + rn2(y2-y1+1);
53.   		for(y=MIN(y1,middle); y<=MAX(y1,middle); y++)
54.   			corr(x1, y);
55.   		for(x=MIN(x1,x2); x<=MAX(x1,x2); x++)
56.   			corr(x, middle);
57.   		for(y=MIN(middle,y2); y<=MAX(middle,y2); y++)
58.   			corr(x2,y);
59.   	}
60.   }
61.   

roguecorr[]

62.   STATIC_OVL
63.   void
64.   roguecorr(x, y, dir)
65.   int x,y,dir;
66.   {
67.   	register int fromx, fromy, tox, toy;
68.   
69.   	if (dir==DOWN) {
70.   		r[x][y].doortable &= ~DOWN;
71.   		if (!r[x][y].real) {
72.   			fromx = r[x][y].rlx; fromy = r[x][y].rly;
73.   			fromx += 1 + 26*x; fromy += 7*y;
74.   		} else {
75.   			fromx = r[x][y].rlx + rn2(r[x][y].dx);
76.   			fromy = r[x][y].rly + r[x][y].dy;
77.   			fromx += 1 + 26*x; fromy += 7*y;
78.   			if (!IS_WALL(levl[fromx][fromy].typ))
79.   				impossible("down: no wall at %d,%d?",fromx,
80.   									fromy);
81.   			dodoor(fromx, fromy, &rooms[r[x][y].nroom]);
82.   			levl[fromx][fromy].doormask = D_NODOOR;
83.   			fromy++;
84.   		}
85.   		if(y >= 2) {
86.   			impossible("down door from %d,%d going nowhere?",x,y);
87.   			return;
88.   		}
89.   		y++;
90.   		r[x][y].doortable &= ~UP;
91.   		if (!r[x][y].real) {
92.   			tox = r[x][y].rlx; toy = r[x][y].rly;
93.   			tox += 1 + 26*x; toy += 7*y;
94.   		} else {
95.   			tox = r[x][y].rlx + rn2(r[x][y].dx);
96.   			toy = r[x][y].rly - 1;
97.   			tox += 1 + 26*x; toy += 7*y;
98.   			if (!IS_WALL(levl[tox][toy].typ))
99.   				impossible("up: no wall at %d,%d?",tox,toy);
100.  			dodoor(tox, toy, &rooms[r[x][y].nroom]);
101.  			levl[tox][toy].doormask = D_NODOOR;
102.  			toy--;
103.  		}
104.  		roguejoin(fromx, fromy, tox, toy, FALSE);
105.  		return;
106.  	} else if (dir == RIGHT) {
107.  		r[x][y].doortable &= ~RIGHT;
108.  		if (!r[x][y].real) {
109.  			fromx = r[x][y].rlx; fromy = r[x][y].rly;
110.  			fromx += 1 + 26*x; fromy += 7*y;
111.  		} else {
112.  			fromx = r[x][y].rlx + r[x][y].dx;
113.  			fromy = r[x][y].rly + rn2(r[x][y].dy);
114.  			fromx += 1 + 26*x; fromy += 7*y;
115.  			if (!IS_WALL(levl[fromx][fromy].typ))
116.  				impossible("down: no wall at %d,%d?",fromx,
117.  									fromy);
118.  			dodoor(fromx, fromy, &rooms[r[x][y].nroom]);
119.  			levl[fromx][fromy].doormask = D_NODOOR;
120.  			fromx++;
121.  		}
122.  		if(x >= 2) {
123.  			impossible("right door from %d,%d going nowhere?",x,y);
124.  			return;
125.  		}
126.  		x++;
127.  		r[x][y].doortable &= ~LEFT;
128.  		if (!r[x][y].real) {
129.  			tox = r[x][y].rlx; toy = r[x][y].rly;
130.  			tox += 1 + 26*x; toy += 7*y;
131.  		} else {
132.  			tox = r[x][y].rlx - 1;
133.  			toy = r[x][y].rly + rn2(r[x][y].dy);
134.  			tox += 1 + 26*x; toy += 7*y;
135.  			if (!IS_WALL(levl[tox][toy].typ))
136.  				impossible("left: no wall at %d,%d?",tox,toy);
137.  			dodoor(tox, toy, &rooms[r[x][y].nroom]);
138.  			levl[tox][toy].doormask = D_NODOOR;
139.  			tox--;
140.  		}
141.  		roguejoin(fromx, fromy, tox, toy, TRUE);
142.  		return;
143.  	} else impossible("corridor in direction %d?",dir);
144.  }
145.  

miniwalk[]

146.  /* Modified walkfrom() from mkmaze.c */
147.  STATIC_OVL
148.  void
149.  miniwalk(x, y)
150.  int x,y;
151.  {
152.  	register int q, dir;
153.  	int dirs[4];
154.  
155.  	while(1) {
156.  		q = 0;
157.  #define doorhere (r[x][y].doortable)
158.  		if (x>0 && (!(doorhere & LEFT)) &&
159.  					(!r[x-1][y].doortable || !rn2(10)))
160.  			dirs[q++] = 0;
161.  		if (x<2 && (!(doorhere & RIGHT)) &&
162.  					(!r[x+1][y].doortable || !rn2(10)))
163.  			dirs[q++] = 1;
164.  		if (y>0 && (!(doorhere & UP)) &&
165.  					(!r[x][y-1].doortable || !rn2(10)))
166.  			dirs[q++] = 2;
167.  		if (y<2 && (!(doorhere & DOWN)) &&
168.  					(!r[x][y+1].doortable || !rn2(10)))
169.  			dirs[q++] = 3;
170.  	/* Rogue levels aren't just 3 by 3 mazes; they have some extra
171.  	 * connections, thus that 1/10 chance
172.  	 */
173.  		if (!q) return;
174.  		dir = dirs[rn2(q)];
175.  		switch(dir) { /* Move in direction */
176.  			case 0: doorhere |= LEFT;
177.  				x--;
178.  				doorhere |= RIGHT;
179.  				break;
180.  			case 1: doorhere |= RIGHT;
181.  				x++;
182.  				doorhere |= LEFT;
183.  				break;
184.  			case 2: doorhere |= UP;
185.  				y--;
186.  				doorhere |= DOWN;
187.  				break;
188.  			case 3: doorhere |= DOWN;
189.  				y++;
190.  				doorhere |= UP;
191.  				break;
192.  		}
193.  		miniwalk(x,y);
194.  	}
195.  }
196.  

makeroguerooms[]

197.  void
198.  makeroguerooms() {
199.  	register int x,y;
200.  	/* Rogue levels are structured 3 by 3, with each section containing
201.  	 * a room or an intersection.  The minimum width is 2 each way.
202.  	 * One difference between these and "real" Rogue levels: real Rogue
203.  	 * uses 24 rows and NetHack only 23.  So we cheat a bit by making the
204.  	 * second row of rooms not as deep.
205.  	 *
206.  	 * Each normal space has 6/7 rows and 25 columns in which a room may
207.  	 * actually be placed.  Walls go from rows 0-5/6 and columns 0-24.
208.  	 * Not counting walls, the room may go in
209.  	 * rows 1-5 and columns 1-23 (numbering starting at 0).  A room
210.  	 * coordinate of this type may be converted to a level coordinate
211.  	 * by adding 1+28*x to the column, and 7*y to the row.  (The 1
212.  	 * is because column 0 isn't used [we only use 1-78]).
213.  	 * Room height may be 2-4 (2-5 on last row), length 2-23 (not
214.  	 * counting walls)
215.  	 */
216.  #define here r[x][y]
217.  
218.  	nroom = 0;
219.  	for(y=0; y<3; y++) for(x=0; x<3; x++) {
220.  		/* Note: we want to insure at least 1 room.  So, if the
221.  		 * first 8 are all dummies, force the last to be a room.
222.  		 */
223.  		if (!rn2(5) && (nroom || (x<2 && y<2))) {
224.  			/* Arbitrary: dummy rooms may only go where real
225.  			 * ones do.
226.  			 */
227.  			here.real = FALSE;
228.  			here.rlx = rn1(22, 2);
229.  			here.rly = rn1((y==2)?4:3, 2);
230.  		} else {
231.  			here.real = TRUE;
232.  			here.dx = rn1(22, 2); /* 2-23 long, plus walls */
233.  			here.dy = rn1((y==2)?4:3, 2); /* 2-5 high, plus walls */
234.  
235.  			/* boundaries of room floor */
236.  			here.rlx = rnd(23 - here.dx + 1);
237.  			here.rly = rnd(((y==2) ? 5 : 4)- here.dy + 1);
238.  			nroom++;
239.  		}
240.  		here.doortable = 0;
241.  	}
242.  	miniwalk(rn2(3), rn2(3));
243.  	nroom = 0;
244.  	for(y=0; y<3; y++) for(x=0; x<3; x++) {
245.  		if (here.real) { /* Make a room */
246.  			int lowx, lowy, hix, hiy;
247.  
248.  			r[x][y].nroom = nroom;
249.  			smeq[nroom] = nroom;
250.  
251.  			lowx = 1 + 26*x + here.rlx;
252.  			lowy = 7*y + here.rly;
253.  			hix = 1 + 26*x + here.rlx + here.dx - 1;
254.  			hiy = 7*y + here.rly + here.dy - 1;
255.  			/* Strictly speaking, it should be lit only if above
256.  			 * level 10, but since Rogue rooms are only
257.  			 * encountered below level 10, use !rn2(7).
258.  			 */
259.  			add_room(lowx, lowy, hix, hiy,
260.  				 (boolean) !rn2(7), OROOM, FALSE);
261.  		}
262.  	}
263.  
264.  	/* Now, add connecting corridors. */
265.  	for(y=0; y<3; y++) for(x=0; x<3; x++) {
266.  		if (here.doortable & DOWN)
267.  			roguecorr(x, y, DOWN);
268.  		if (here.doortable & RIGHT)
269.  			roguecorr(x, y, RIGHT);
270.  		if (here.doortable & LEFT)
271.  			impossible ("left end of %d, %d never connected?",x,y);
272.  		if (here.doortable & UP)
273.  			impossible ("up end of %d, %d never connected?",x,y);
274.  	}
275.  }
276.  

corr[]

277.  void
278.  corr(x,y)
279.  int x, y;
280.  {
281.  	if (rn2(50)) {
282.  		levl[x][y].typ = CORR;
283.  	} else {
284.  		levl[x][y].typ = SCORR;
285.  	}
286.  }
287.  

makerogueghost[]

288.  void
289.  makerogueghost()
290.  {
291.  	register struct monst *ghost;
292.  	struct obj *ghostobj;
293.  	struct mkroom *croom;
294.  	int x,y;
295.  
296.  	if (!nroom) return; /* Should never happen */
297.  	croom = &rooms[rn2(nroom)];
298.  	x = somex(croom); y = somey(croom);
299.  	if (!(ghost = makemon(&mons[PM_GHOST], x, y, NO_MM_FLAGS)))
300.  		return;
301.  	ghost->msleeping = 1;
302.  	ghost = christen_monst(ghost, roguename());
303.  
304.  	if (rn2(4)) {
305.  		ghostobj = mksobj_at(FOOD_RATION, x, y, FALSE, FALSE);
306.  		ghostobj->quan = (long) rnd(7);
307.  		ghostobj->owt = weight(ghostobj);
308.  	}
309.  	if (rn2(2)) {
310.  		ghostobj = mksobj_at(MACE, x, y, FALSE, FALSE);
311.  		ghostobj->spe = rnd(3);
312.  		if (rn2(4)) curse(ghostobj);
313.  	} else {
314.  		ghostobj = mksobj_at(TWO_HANDED_SWORD, x, y, FALSE, FALSE);
315.  		ghostobj->spe = rnd(5) - 2;
316.  		if (rn2(4)) curse(ghostobj);
317.  	}
318.  	ghostobj = mksobj_at(BOW, x, y, FALSE, FALSE);
319.  	ghostobj->spe = 1;
320.  	if (rn2(4)) curse(ghostobj);
321.  
322.  	ghostobj = mksobj_at(ARROW, x, y, FALSE, FALSE);
323.  	ghostobj->spe = 0;
324.  	ghostobj->quan = (long) rn1(10,25);
325.  	ghostobj->owt = weight(ghostobj);
326.  	if (rn2(4)) curse(ghostobj);
327.  
328.  	if (rn2(2)) {
329.  		ghostobj = mksobj_at(RING_MAIL, x, y, FALSE, FALSE);
330.  		ghostobj->spe = rn2(3);
331.  		if (!rn2(3)) ghostobj->oerodeproof = TRUE;
332.  		if (rn2(4)) curse(ghostobj);
333.  	} else {
334.  		ghostobj = mksobj_at(PLATE_MAIL, x, y, FALSE, FALSE);
335.  		ghostobj->spe = rnd(5) - 2;
336.  		if (!rn2(3)) ghostobj->oerodeproof = TRUE;
337.  		if (rn2(4)) curse(ghostobj);
338.  	}
339.  	if (rn2(2)) {
340.  		ghostobj = mksobj_at(FAKE_AMULET_OF_YENDOR, x, y, TRUE, FALSE);
341.  		ghostobj->known = TRUE;
342.  	}
343.  }
344.  #endif /* REINCARNATION */
345.  
346.  /*extralev.c*/
Advertisement