1 /*
2  * room.c
3  *
4  * This source herein may be modified and/or distributed by anybody who
5  * so desires, with the following restrictions:
6  *    1.)  No portion of this notice shall be removed.
7  *    2.)  Credit shall not be taken for the creation of this source.
8  *    3.)  This code is not to be traded, sold, or used for personal
9  *         gain or profit.
10  *
11  */
12 
13 #include "rogue.h"
14 
15 room rooms[MAXROOMS];
16 boolean rooms_visited[MAXROOMS];
17 
18 extern short blind;
19 extern boolean detect_monster;
20 
light_up_room(rn)21 light_up_room(rn)
22 int rn;
23 {
24 	short i, j;
25 
26 	if (!blind) {
27 		for (i = rooms[rn].top_row;
28 			i <= rooms[rn].bottom_row; i++) {
29 			for (j = rooms[rn].left_col;
30 				j <= rooms[rn].right_col; j++) {
31 				if (dungeon[i][j] & MONSTER) {
32 					object *monster;
33 
34 					if (monster = object_at(&level_monsters, i, j)) {
35 						dungeon[monster->row][monster->col] &= (~MONSTER);
36 						monster->trail_char =
37 							get_dungeon_char(monster->row, monster->col);
38 						dungeon[monster->row][monster->col] |= MONSTER;
39 					}
40 				}
41 				mvaddch(i, j, colored(get_dungeon_char(i, j)));
42 			}
43 		}
44 		mvaddch(rogue.row, rogue.col, colored(rogue.fchar));
45 	}
46 }
47 
48 void
light_passage(row,col)49 light_passage(row, col)
50 {
51 	short i, j, i_end, j_end;
52 
53 	if (blind) {
54 		return;
55 	}
56 	i_end = (row < (DROWS-2)) ? 1 : 0;
57 	j_end = (col < (DCOLS-1)) ? 1 : 0;
58 
59 	for (i = ((row > MIN_ROW) ? -1 : 0); i <= i_end; i++) {
60 		for (j = ((col > 0) ? -1 : 0); j <= j_end; j++) {
61 			if (can_move(row, col, row+i, col+j)) {
62 				mvaddch(row+i, col+j, colored(get_dungeon_char(row+i, col+j)));
63 			}
64 		}
65 	}
66 }
67 
darken_room(rn)68 darken_room(rn)
69 short rn;
70 {
71 	short i, j;
72 
73 	for (i = rooms[rn].top_row + 1; i < rooms[rn].bottom_row; i++) {
74 		for (j = rooms[rn].left_col + 1; j < rooms[rn].right_col; j++) {
75 			if (blind) {
76 				mvaddch(i, j, colored(' '));
77 			} else {
78 				if (!(dungeon[i][j] & (OBJECT | STAIRS)) &&
79 					!(detect_monster && (dungeon[i][j] & MONSTER))) {
80 					if (!imitating(i, j)) {
81 						mvaddch(i, j, colored(' '));
82 					}
83 					if ((dungeon[i][j] & TRAP) && (!(dungeon[i][j] & HIDDEN))) {
84 						mvaddch(i, j, colored('^'));
85 					}
86 				}
87 			}
88 		}
89 	}
90 }
91 
get_dungeon_char(row,col)92 get_dungeon_char(row, col)
93 register row, col;
94 {
95 	register unsigned short mask = dungeon[row][col];
96 
97 	if (mask & MONSTER) {
98 		return(gmc_row_col(row, col));
99 	}
100 	if (mask & OBJECT) {
101 		object *obj;
102 
103 		obj = object_at(&level_objects, row, col);
104 		return(get_mask_char(obj->what_is));
105 	}
106 	if (mask & (TUNNEL | STAIRS | HORWALL | VERTWALL | FLOOR | DOOR)) {
107 		if ((mask & (TUNNEL| STAIRS)) && (!(mask & HIDDEN))) {
108 			return(((mask & STAIRS) ? '%' : '#'));
109 		}
110 		if (mask & HORWALL) {
111 			return('-');
112 		}
113 		if (mask & VERTWALL) {
114 			return('|');
115 		}
116 		if (mask & FLOOR) {
117 			if (mask & TRAP) {
118 				if (!(dungeon[row][col] & HIDDEN)) {
119 					return('^');
120 				}
121 			}
122 			return('.');
123 		}
124 		if (mask & DOOR) {
125 			if (mask & HIDDEN) {
126 				if (((col > 0) && (dungeon[row][col-1] & HORWALL)) ||
127 					((col < (DCOLS-1)) && (dungeon[row][col+1] & HORWALL))) {
128 					return('-');
129 				} else {
130 					return('|');
131 				}
132 			} else {
133 				return('+');
134 			}
135 		}
136 	}
137 	return(' ');
138 }
139 
get_mask_char(mask)140 get_mask_char(mask)
141 register unsigned short mask;
142 {
143 		switch(mask) {
144 		case SCROL:
145 			return('?');
146 		case POTION:
147 			return('!');
148 		case GOLD:
149 			return('*');
150 		case FOOD:
151 			return(':');
152 		case WAND:
153 			return('/');
154 		case ARMOR:
155 			return(']');
156 		case WEAPON:
157 			return(')');
158 		case RING:
159 			return('=');
160 		case AMULET:
161 			return(',');
162 		default:
163 			return('~');	/* unknown, something is wrong */
164 		}
165 }
166 
gr_row_col(row,col,mask)167 gr_row_col(row, col, mask)
168 short *row, *col;
169 unsigned short mask;
170 {
171 	short rn;
172 	short r, c;
173 
174 	do {
175 		r = get_rand(MIN_ROW, DROWS-2);
176 		c = get_rand(0, DCOLS-1);
177 		rn = get_room_number(r, c);
178 	} while ((rn == NO_ROOM) ||
179 		(!(dungeon[r][c] & mask)) ||
180 		(dungeon[r][c] & (~mask)) ||
181 		(!(rooms[rn].is_room & (R_ROOM | R_MAZE))) ||
182 		((r == rogue.row) && (c == rogue.col)));
183 
184 	*row = r;
185 	*col = c;
186 }
187 
gr_room()188 gr_room()
189 {
190 	short i;
191 
192 	do {
193 		i = get_rand(0, MAXROOMS-1);
194 	} while (!(rooms[i].is_room & (R_ROOM | R_MAZE)));
195 
196 	return(i);
197 }
198 
party_objects(rn)199 party_objects(rn)
200 {
201 	short i, j, nf = 0;
202 	object *obj;
203 	short n, N, row, col;
204 	boolean found;
205 
206 	N = ((rooms[rn].bottom_row - rooms[rn].top_row) - 1) *
207 		((rooms[rn].right_col - rooms[rn].left_col) - 1);
208 	n =  get_rand(5, 10);
209 	if (n > N) {
210 		n = N - 2;
211 	}
212 	for (i = 0; i < n; i++) {
213 		for (j = found = 0; ((!found) && (j < 250)); j++) {
214 			row = get_rand(rooms[rn].top_row+1,
215 					   rooms[rn].bottom_row-1);
216 			col = get_rand(rooms[rn].left_col+1,
217 					   rooms[rn].right_col-1);
218 			if ((dungeon[row][col] == FLOOR) || (dungeon[row][col] == TUNNEL)) {
219 				found = 1;
220 			}
221 		}
222 		if (found) {
223 			obj = gr_object();
224 			place_at(obj, row, col);
225 			nf++;
226 		}
227 	}
228 	return(nf);
229 }
230 
get_room_number(row,col)231 get_room_number(row, col)
232 register row, col;
233 {
234 	short i;
235 
236 	for (i = 0; i < MAXROOMS; i++) {
237 		if ((row >= rooms[i].top_row) && (row <= rooms[i].bottom_row) &&
238 			(col >= rooms[i].left_col) && (col <= rooms[i].right_col)) {
239 			return(i);
240 		}
241 	}
242 	return(NO_ROOM);
243 }
244 
is_all_connected()245 is_all_connected()
246 {
247 	short i, starting_room;
248 
249 	for (i = 0; i < MAXROOMS; i++) {
250 		rooms_visited[i] = 0;
251 		if (rooms[i].is_room & (R_ROOM | R_MAZE)) {
252 			starting_room = i;
253 		}
254 	}
255 
256 	visit_rooms(starting_room);
257 
258 	for (i = 0; i < MAXROOMS; i++) {
259 		if ((rooms[i].is_room & (R_ROOM | R_MAZE)) && (!rooms_visited[i])) {
260 			return(0);
261 		}
262 	}
263 	return(1);
264 }
265 
visit_rooms(rn)266 visit_rooms(rn)
267 int rn;
268 {
269 	short i;
270 	short oth_rn;
271 
272 	rooms_visited[rn] = 1;
273 
274 	for (i = 0; i < 4; i++) {
275 		oth_rn = rooms[rn].doors[i].oth_room;
276 		if ((oth_rn >= 0) && (!rooms_visited[oth_rn])) {
277 			visit_rooms(oth_rn);
278 		}
279 	}
280 }
281 
draw_magic_map()282 draw_magic_map()
283 {
284 	short i, j, ch, och;
285 	unsigned short mask = (HORWALL | VERTWALL | DOOR | TUNNEL | TRAP | STAIRS |
286 			MONSTER);
287 	unsigned short s;
288 
289 	for (i = 0; i < DROWS; i++) {
290 		for (j = 0; j < DCOLS; j++) {
291 			s = dungeon[i][j];
292 			if (s & mask) {
293 				if (((ch = mvinch(i, j)) == ' ') ||
294 					((ch >= 'A') && (ch <= 'Z')) || (s & (TRAP | HIDDEN))) {
295 					och = ch;
296 					dungeon[i][j] &= (~HIDDEN);
297 					if (s & HORWALL) {
298 						ch = '-';
299 					} else if (s & VERTWALL) {
300 						ch = '|';
301 					} else if (s & DOOR) {
302 						ch = '+';
303 					} else if (s & TRAP) {
304 						ch = '^';
305 					} else if (s & STAIRS) {
306 						ch = '%';
307 					} else if (s & TUNNEL) {
308 						ch = '#';
309 					} else {
310 						continue;
311 					}
312 					if ((!(s & MONSTER)) || (och == ' ')) {
313 						addch(colored(ch));
314 					}
315 					if (s & MONSTER) {
316 						object *monster;
317 
318 						if (monster = object_at(&level_monsters, i, j)) {
319 							monster->trail_char = ch;
320 						}
321 					}
322 				}
323 			}
324 		}
325 	}
326 }
327 
328 void
dr_course(monster,entering,row,col)329 dr_course(monster, entering, row, col)
330 object *monster;
331 boolean entering;
332 short row, col;
333 {
334 	short i, j, k, rn;
335 	short r, rr;
336 
337 	monster->row = row;
338 	monster->col = col;
339 
340 	if (mon_sees(monster, rogue.row, rogue.col)) {
341 		monster->trow = NO_ROOM;
342 		return;
343 	}
344 	rn = get_room_number(row, col);
345 
346 	if (entering) {		/* entering room */
347 		/* look for door to some other room */
348 		r = get_rand(0, MAXROOMS-1);
349 		for (i = 0; i < MAXROOMS; i++) {
350 			rr = (r + i) % MAXROOMS;
351 			if ((!(rooms[rr].is_room & (R_ROOM | R_MAZE))) || (rr == rn)) {
352 				continue;
353 			}
354 			for (k = 0; k < 4; k++) {
355 				if (rooms[rr].doors[k].oth_room == rn) {
356 					monster->trow = rooms[rr].doors[k].oth_row;
357 					monster->tcol = rooms[rr].doors[k].oth_col;
358 					if ((monster->trow == row) &&
359 						(monster->tcol == col)) {
360 						continue;
361 					}
362 					return;
363 				}
364 			}
365 		}
366 		/* look for door to dead end */
367 		for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) {
368 			for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) {
369 				if ((i != monster->row) && (j != monster->col) &&
370 					(dungeon[i][j] & DOOR)) {
371 					monster->trow = i;
372 					monster->tcol = j;
373 					return;
374 				}
375 			}
376 		}
377 		/* return monster to room that he came from */
378 		for (i = 0; i < MAXROOMS; i++) {
379 			for (j = 0; j < 4; j++) {
380 				if (rooms[i].doors[j].oth_room == rn) {
381 					for (k = 0; k < 4; k++) {
382 						if (rooms[rn].doors[k].oth_room == i) {
383 							monster->trow = rooms[rn].doors[k].oth_row;
384 							monster->tcol = rooms[rn].doors[k].oth_col;
385 							return;
386 						}
387 					}
388 				}
389 			}
390 		}
391 		/* no place to send monster */
392 		monster->trow = -1;
393 	} else {		/* exiting room */
394 		if (!get_oth_room(rn, &row, &col)) {
395 			monster->trow = NO_ROOM;
396 		} else {
397 			monster->trow = row;
398 			monster->tcol = col;
399 		}
400 	}
401 }
402 
get_oth_room(rn,row,col)403 get_oth_room(rn, row, col)
404 short rn, *row, *col;
405 {
406 	short d = -1;
407 
408 	if (*row == rooms[rn].top_row) {
409 		d = UPWARD/2;
410 	} else if (*row == rooms[rn].bottom_row) {
411 		d = DOWN/2;
412 	} else if (*col == rooms[rn].left_col) {
413 		d = LEFT/2;
414 	} else if (*col == rooms[rn].right_col) {
415 		d = RIGHT/2;
416 	}
417 	if ((d != -1) && (rooms[rn].doors[d].oth_room >= 0)) {
418 		*row = rooms[rn].doors[d].oth_row;
419 		*col = rooms[rn].doors[d].oth_col;
420 		return(1);
421 	}
422 	return(0);
423 }
424