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