1 /*
2  * Create the layout for the new level
3  *
4  * rooms.c	1.4 (A.I. Design)	12/16/84
5  */
6 
7 #include "rogue.h"
8 #include "curses.h"
9 
10 #define GOLDGRP 1
11 
12 /*
13  * do_rooms:
14  *	Create rooms and corridors with a connectivity graph
15  */
16 do_rooms()
17 {
18     register int i, rm;
19     struct room *rp;
20     register THING *tp;
21     int left_out;
22     coord top;
23     coord bsze;
24     coord mp;
25     int old_lev;
26     int endline;
27 
28 	endline = maxrow + 1;
29 
30     old_lev = level;
31     /*
32      * bsze is the maximum room size
33      */
34     bsze.x = COLS/3;
35     bsze.y = endline/3;
36     /*
37      * Clear things for a new level
38      */
39     for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
40 		rp->r_goldval = rp->r_nexits = rp->r_flags = 0;
41     /*
42      * Put the gone rooms, if any, on the level
43      */
44     left_out = rnd(4);
45     for (i = 0; i < left_out; i++) {
46 		do
47 		    rp = &rooms[(rm = rnd_room())];
48 		while (rp->r_flags & ISMAZE);
49 		rp->r_flags |= ISGONE;
50 #ifdef TEST
51 		if (rm > 2 && ((level > 10 && rnd(20) < level - 9) || istest()))
52 #else  TEST
53 		if (rm > 2 && level > 10 && rnd(20) < level - 9)
54 #endif TEST
55 		    rp->r_flags |= ISMAZE;
56     }
57     /*
58      * dig and populate all the rooms on the level
59      */
60     for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++) {
61 		/*
62 		 * Find upper left corner of box that this room goes in
63 		 */
64 		top.x = (i%3)*bsze.x + 1;
65 		top.y = i/3*bsze.y;
66 		if (rp->r_flags & ISGONE) {
67 		    /*
68 		     * If the gone room is a maze room, draw the maze and set the
69 		     * size equal to the maximum possible.
70 		     */
71 		    if (rp->r_flags&ISMAZE) {
72 				rp->r_pos.x = top.x;
73 				rp->r_pos.y = top.y;
74 				draw_maze(rp);
75 		    } else {
76 				/*
77 				 * Place a gone room.  Make certain that there is a blank line
78 				 * for passage drawing.
79 				 */
80 				do {
81 				    rp->r_pos.x = top.x + rnd(bsze.x-2) + 1;
82 				    rp->r_pos.y = top.y + rnd(bsze.y-2) + 1;
83 				    rp->r_max.x = -COLS;
84 				    rp->r_max.x = -endline;
85 				} while (!(rp->r_pos.y > 0 && rp->r_pos.y < endline-1));
86 		    }
87 		    continue;
88 		}
89 		if (rnd(10) < (level - 1))
90 		    rp->r_flags |= ISDARK;
91 		/*
92 		 * Find a place and size for a random room
93 		 */
94 		do {
95 		    rp->r_max.x = rnd(bsze.x - 4) + 4;
96 		    rp->r_max.y = rnd(bsze.y - 4) + 4;
97 		    rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
98 		    rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
99 		} while (rp->r_pos.y == 0);
100 		draw_room(rp);
101 		/*
102 		 * Put the gold in
103 		 */
104 		if ((rnd(2) == 0) && (!saw_amulet || (level >= max_level))) {
105 		    THING *gold;
106 
107 		    if ((gold = new_item()) != NULL) {
108 		    	gold->o_goldval = rp->r_goldval = GOLDCALC;
109 		    	while (1) {
110 					byte gch;
111 
112 				    rnd_pos(rp, &rp->r_gold);
113 					gch =  chat(rp->r_gold.y, rp->r_gold.x);
114 				    if (isfloor(gch))
115 				    	break;
116 		    	}
117 		    	bcopy(gold->o_pos,rp->r_gold);
118 		    	gold->o_flags = ISMANY;
119 		    	gold->o_group = GOLDGRP;
120 		    	gold->o_type = GOLD;
121 		    	attach(lvl_obj, gold);
122 		    	chat(rp->r_gold.y, rp->r_gold.x) = GOLD;
123 		    }
124 		}
125 		/*
126 		 * Put the monster in
127 		 */
128 		if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25)) {
129 		    if ((tp = new_item()) != NULL) {
130 				byte mch;
131 
132 		    	do {
133 				    rnd_pos(rp, &mp);
134 					mch = winat(mp.y, mp.x);
135 				} while (!isfloor(mch));
136 		    	new_monster(tp, randmonster(FALSE), &mp);
137 		    	give_pack(tp);
138 		    }
139 		}
140     }
141 }
142 
143 /*
144  * draw_room:
145  *	Draw a box around a room and lay down the floor
146  */
147 draw_room(rp)
148 struct room *rp;
149 {
150     register int y, x;
151 
152     /*
153      * Here we draw normal rooms, one side at a time
154      */
155     vert(rp, rp->r_pos.x);			/* Draw left side */
156     vert(rp, rp->r_pos.x + rp->r_max.x - 1);	/* Draw right side */
157     horiz(rp, rp->r_pos.y);			/* Draw top */
158     horiz(rp, rp->r_pos.y + rp->r_max.y - 1);	/* Draw bottom */
159 	chat(rp->r_pos.y,rp->r_pos.x) = ULWALL;
160 	chat(rp->r_pos.y,rp->r_pos.x+rp->r_max.x - 1) = URWALL;
161 	chat(rp->r_pos.y+rp->r_max.y-1,rp->r_pos.x) = LLWALL;
162 	chat(rp->r_pos.y+rp->r_max.y-1,rp->r_pos.x+rp->r_max.x - 1) = LRWALL;
163     /*
164      * Put the floor down
165      */
166     for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++)
167 		for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++)
168 		    chat(y, x) = FLOOR;
169 }
170 
171 /*
172  * vert:
173  *	Draw a vertical line
174  */
175 vert(rp, startx)
176 register struct room *rp;
177 register int startx;
178 {
179     register register int y;
180 
181     for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++)
182 		chat(y, startx) = VWALL;
183 }
184 
185 /*
186  * horiz:
187  *	Draw a horizontal line
188  */
189 horiz(rp, starty)
190 struct room *rp;
191 int starty;
192 {
193     register int x;
194 
195     for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++)
196 		chat(starty, x) = HWALL;
197 }
198 
199 /*
200  * rnd_pos:
201  *	Pick a random spot in a room
202  */
203 rnd_pos(rp, cp)
204 register struct room *rp;
205 register coord *cp;
206 {
207     cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
208     cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
209 }
210 
211 /*
212  * enter_room:
213  *	Code that is executed whenver you appear in a room
214  */
215 enter_room(cp)
216 register coord *cp;
217 {
218     register struct room *rp;
219     register int y, x;
220     register THING *tp;
221 
222     rp = proom = roomin(cp);
223     if (bailout || (rp->r_flags & ISGONE && (rp->r_flags & ISMAZE) == 0)) {
224 #ifdef DEBUG  
225 		msg("in a gone room");
226 #endif DEBUG
227 		return;
228     }
229     door_open(rp);
230     if (!(rp->r_flags&ISDARK) && !on(player,ISBLIND) && !(rp->r_flags&ISMAZE))
231 		for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++) {
232 		    move(y, rp->r_pos.x);
233 		    for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++) {
234 				/*
235 				 * Displaying monsters is all handled in the
236 				 * chase code now
237 				 */
238 				tp = moat(y, x);
239 				if (tp == NULL || !see_monst(tp))
240 				    addch(chat(y, x));
241 				else {
242 				    tp->t_oldch = chat(y,x);
243 				    addch(tp->t_disguise);
244 				}
245 		    }
246 		}
247 }
248 
249 /*
250  * leave_room:
251  *	Code for when we exit a room
252  */
253 leave_room(cp)
254 register coord *cp;
255 {
256     register int y, x;
257     register struct room *rp;
258     register byte floor;
259     register byte ch;
260 
261     rp = proom;
262     proom = &passages[flat(cp->y, cp->x) & F_PNUM];
263     floor = ((rp->r_flags & ISDARK) && !on(player, ISBLIND)) ? ' ' : FLOOR;
264     if (rp->r_flags & ISMAZE)
265     	floor = PASSAGE;
266     for (y = rp->r_pos.y + 1; y < rp->r_max.y + rp->r_pos.y - 1; y++)
267 		for (x = rp->r_pos.x + 1; x < rp->r_max.x + rp->r_pos.x - 1; x++)
268 		    switch (ch = mvinch(y, x)) {
269 			case ' ':
270 			case PASSAGE:
271 			case TRAP:
272 			case STAIRS:
273 			    break;
274 			case FLOOR:
275 			    if (floor == ' ')
276 					addch(' ');
277 			    break;
278 			default:
279 			    /*
280 			     * to check for monster, we have to strip out
281 			     * standout bit
282 			     */
283 			    if (isupper(toascii(ch)))
284 					if (on(player, SEEMONST)) {
285 					    standout();
286 					    addch(ch);
287 					    standend();
288 					    break;
289 					} else
290 					    moat(y, x)->t_oldch = '@';
291 				    addch(floor);
292 		    }
293 		    door_open(rp);
294 }
295 