Commit | Line | Data |
---|---|---|
b3afadef KB |
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 | #ifndef lint | |
14 | static char sccsid[] = "@(#)room.c 5.1 (Berkeley) %G%"; | |
15 | #endif /* not lint */ | |
16 | ||
17 | #include "rogue.h" | |
18 | ||
19 | room rooms[MAXROOMS]; | |
20 | boolean rooms_visited[MAXROOMS]; | |
21 | ||
22 | extern short blind; | |
23 | extern boolean detect_monster, jump, passgo, no_skull, ask_quit; | |
24 | extern char *nick_name, *fruit, *save_file, *press_space; | |
25 | ||
26 | #define NOPTS 7 | |
27 | ||
28 | struct option { | |
29 | char *prompt; | |
30 | boolean is_bool; | |
31 | char **strval; | |
32 | boolean *bval; | |
33 | } options[NOPTS] = { | |
34 | { | |
35 | "Show position only at end of run (\"jump\"): ", | |
36 | 1, (char **) 0, &jump | |
37 | }, | |
38 | { | |
39 | "Follow turnings in passageways (\"passgo\"): ", | |
40 | 1, (char **) 0, &passgo | |
41 | }, | |
42 | { | |
43 | "Don't print skull when killed (\"noskull\" or \"notombstone\"): ", | |
44 | 1, (char **) 0, &no_skull | |
45 | }, | |
46 | { | |
47 | "Ask player before saying 'Okay, bye-bye!' (\"askquit\"): ", | |
48 | 1, (char **) 0, &ask_quit | |
49 | }, | |
50 | { | |
51 | "Name (\"name\"): ", | |
52 | 0, &nick_name | |
53 | }, | |
54 | { | |
55 | "Fruit (\"fruit\"): ", | |
56 | 0, &fruit | |
57 | }, | |
58 | { | |
59 | "Save file (\"file\"): ", | |
60 | 0, &save_file | |
61 | } | |
62 | }; | |
63 | ||
64 | light_up_room(rn) | |
65 | int rn; | |
66 | { | |
67 | short i, j; | |
68 | ||
69 | if (!blind) { | |
70 | for (i = rooms[rn].top_row; | |
71 | i <= rooms[rn].bottom_row; i++) { | |
72 | for (j = rooms[rn].left_col; | |
73 | j <= rooms[rn].right_col; j++) { | |
74 | if (dungeon[i][j] & MONSTER) { | |
75 | object *monster; | |
76 | ||
77 | if (monster = object_at(&level_monsters, i, j)) { | |
78 | dungeon[monster->row][monster->col] &= (~MONSTER); | |
79 | monster->trail_char = | |
80 | get_dungeon_char(monster->row, monster->col); | |
81 | dungeon[monster->row][monster->col] |= MONSTER; | |
82 | } | |
83 | } | |
84 | mvaddch(i, j, get_dungeon_char(i, j)); | |
85 | } | |
86 | } | |
87 | mvaddch(rogue.row, rogue.col, rogue.fchar); | |
88 | } | |
89 | } | |
90 | ||
91 | light_passage(row, col) | |
92 | { | |
93 | short i, j, i_end, j_end; | |
94 | ||
95 | if (blind) { | |
96 | return; | |
97 | } | |
98 | i_end = (row < (DROWS-2)) ? 1 : 0; | |
99 | j_end = (col < (DCOLS-1)) ? 1 : 0; | |
100 | ||
101 | for (i = ((row > MIN_ROW) ? -1 : 0); i <= i_end; i++) { | |
102 | for (j = ((col > 0) ? -1 : 0); j <= j_end; j++) { | |
103 | if (can_move(row, col, row+i, col+j)) { | |
104 | mvaddch(row+i, col+j, get_dungeon_char(row+i, col+j)); | |
105 | } | |
106 | } | |
107 | } | |
108 | } | |
109 | ||
110 | darken_room(rn) | |
111 | short rn; | |
112 | { | |
113 | short i, j; | |
114 | ||
115 | for (i = rooms[rn].top_row + 1; i < rooms[rn].bottom_row; i++) { | |
116 | for (j = rooms[rn].left_col + 1; j < rooms[rn].right_col; j++) { | |
117 | if (blind) { | |
118 | mvaddch(i, j, ' '); | |
119 | } else { | |
120 | if (!(dungeon[i][j] & (OBJECT | STAIRS)) && | |
121 | !(detect_monster && (dungeon[i][j] & MONSTER))) { | |
122 | if (!imitating(i, j)) { | |
123 | mvaddch(i, j, ' '); | |
124 | } | |
125 | if ((dungeon[i][j] & TRAP) && (!(dungeon[i][j] & HIDDEN))) { | |
126 | mvaddch(i, j, '^'); | |
127 | } | |
128 | } | |
129 | } | |
130 | } | |
131 | } | |
132 | } | |
133 | ||
134 | get_dungeon_char(row, col) | |
135 | register row, col; | |
136 | { | |
137 | register unsigned short mask = dungeon[row][col]; | |
138 | ||
139 | if (mask & MONSTER) { | |
140 | return(gmc_row_col(row, col)); | |
141 | } | |
142 | if (mask & OBJECT) { | |
143 | object *obj; | |
144 | ||
145 | obj = object_at(&level_objects, row, col); | |
146 | return(get_mask_char(obj->what_is)); | |
147 | } | |
148 | if (mask & (TUNNEL | STAIRS | HORWALL | VERTWALL | FLOOR | DOOR)) { | |
149 | if ((mask & (TUNNEL| STAIRS)) && (!(mask & HIDDEN))) { | |
150 | return(((mask & STAIRS) ? '%' : '#')); | |
151 | } | |
152 | if (mask & HORWALL) { | |
153 | return('-'); | |
154 | } | |
155 | if (mask & VERTWALL) { | |
156 | return('|'); | |
157 | } | |
158 | if (mask & FLOOR) { | |
159 | if (mask & TRAP) { | |
160 | if (!(dungeon[row][col] & HIDDEN)) { | |
161 | return('^'); | |
162 | } | |
163 | } | |
164 | return('.'); | |
165 | } | |
166 | if (mask & DOOR) { | |
167 | if (mask & HIDDEN) { | |
168 | if (((col > 0) && (dungeon[row][col-1] & HORWALL)) || | |
169 | ((col < (DCOLS-1)) && (dungeon[row][col+1] & HORWALL))) { | |
170 | return('-'); | |
171 | } else { | |
172 | return('|'); | |
173 | } | |
174 | } else { | |
175 | return('+'); | |
176 | } | |
177 | } | |
178 | } | |
179 | return(' '); | |
180 | } | |
181 | ||
182 | get_mask_char(mask) | |
183 | register unsigned short mask; | |
184 | { | |
185 | switch(mask) { | |
186 | case SCROL: | |
187 | return('?'); | |
188 | case POTION: | |
189 | return('!'); | |
190 | case GOLD: | |
191 | return('*'); | |
192 | case FOOD: | |
193 | return(':'); | |
194 | case WAND: | |
195 | return('/'); | |
196 | case ARMOR: | |
197 | return(']'); | |
198 | case WEAPON: | |
199 | return(')'); | |
200 | case RING: | |
201 | return('='); | |
202 | case AMULET: | |
203 | return(','); | |
204 | default: | |
205 | return('~'); /* unknown, something is wrong */ | |
206 | } | |
207 | } | |
208 | ||
209 | gr_row_col(row, col, mask) | |
210 | short *row, *col; | |
211 | unsigned short mask; | |
212 | { | |
213 | short rn; | |
214 | short r, c; | |
215 | ||
216 | do { | |
217 | r = get_rand(MIN_ROW, DROWS-2); | |
218 | c = get_rand(0, DCOLS-1); | |
219 | rn = get_room_number(r, c); | |
220 | } while ((rn == NO_ROOM) || | |
221 | (!(dungeon[r][c] & mask)) || | |
222 | (dungeon[r][c] & (~mask)) || | |
223 | (!(rooms[rn].is_room & (R_ROOM | R_MAZE))) || | |
224 | ((r == rogue.row) && (c == rogue.col))); | |
225 | ||
226 | *row = r; | |
227 | *col = c; | |
228 | } | |
229 | ||
230 | gr_room() | |
231 | { | |
232 | short i; | |
233 | ||
234 | do { | |
235 | i = get_rand(0, MAXROOMS-1); | |
236 | } while (!(rooms[i].is_room & (R_ROOM | R_MAZE))); | |
237 | ||
238 | return(i); | |
239 | } | |
240 | ||
241 | party_objects(rn) | |
242 | { | |
243 | short i, j, nf = 0; | |
244 | object *obj; | |
245 | short n, N, row, col; | |
246 | boolean found; | |
247 | ||
248 | N = ((rooms[rn].bottom_row - rooms[rn].top_row) - 1) * | |
249 | ((rooms[rn].right_col - rooms[rn].left_col) - 1); | |
250 | n = get_rand(5, 10); | |
251 | if (n > N) { | |
252 | n = N - 2; | |
253 | } | |
254 | for (i = 0; i < n; i++) { | |
255 | for (j = found = 0; ((!found) && (j < 250)); j++) { | |
256 | row = get_rand(rooms[rn].top_row+1, | |
257 | rooms[rn].bottom_row-1); | |
258 | col = get_rand(rooms[rn].left_col+1, | |
259 | rooms[rn].right_col-1); | |
260 | if ((dungeon[row][col] == FLOOR) || (dungeon[row][col] == TUNNEL)) { | |
261 | found = 1; | |
262 | } | |
263 | } | |
264 | if (found) { | |
265 | obj = gr_object(); | |
266 | place_at(obj, row, col); | |
267 | nf++; | |
268 | } | |
269 | } | |
270 | return(nf); | |
271 | } | |
272 | ||
273 | get_room_number(row, col) | |
274 | register row, col; | |
275 | { | |
276 | short i; | |
277 | ||
278 | for (i = 0; i < MAXROOMS; i++) { | |
279 | if ((row >= rooms[i].top_row) && (row <= rooms[i].bottom_row) && | |
280 | (col >= rooms[i].left_col) && (col <= rooms[i].right_col)) { | |
281 | return(i); | |
282 | } | |
283 | } | |
284 | return(NO_ROOM); | |
285 | } | |
286 | ||
287 | is_all_connected() | |
288 | { | |
289 | short i, starting_room; | |
290 | ||
291 | for (i = 0; i < MAXROOMS; i++) { | |
292 | rooms_visited[i] = 0; | |
293 | if (rooms[i].is_room & (R_ROOM | R_MAZE)) { | |
294 | starting_room = i; | |
295 | } | |
296 | } | |
297 | ||
298 | visit_rooms(starting_room); | |
299 | ||
300 | for (i = 0; i < MAXROOMS; i++) { | |
301 | if ((rooms[i].is_room & (R_ROOM | R_MAZE)) && (!rooms_visited[i])) { | |
302 | return(0); | |
303 | } | |
304 | } | |
305 | return(1); | |
306 | } | |
307 | ||
308 | visit_rooms(rn) | |
309 | int rn; | |
310 | { | |
311 | short i; | |
312 | short oth_rn; | |
313 | ||
314 | rooms_visited[rn] = 1; | |
315 | ||
316 | for (i = 0; i < 4; i++) { | |
317 | oth_rn = rooms[rn].doors[i].oth_room; | |
318 | if ((oth_rn >= 0) && (!rooms_visited[oth_rn])) { | |
319 | visit_rooms(oth_rn); | |
320 | } | |
321 | } | |
322 | } | |
323 | ||
324 | draw_magic_map() | |
325 | { | |
326 | short i, j, ch, och; | |
327 | unsigned short mask = (HORWALL | VERTWALL | DOOR | TUNNEL | TRAP | STAIRS | | |
328 | MONSTER); | |
329 | unsigned short s; | |
330 | ||
331 | for (i = 0; i < DROWS; i++) { | |
332 | for (j = 0; j < DCOLS; j++) { | |
333 | s = dungeon[i][j]; | |
334 | if (s & mask) { | |
335 | if (((ch = mvinch(i, j)) == ' ') || | |
336 | ((ch >= 'A') && (ch <= 'Z')) || (s & (TRAP | HIDDEN))) { | |
337 | och = ch; | |
338 | dungeon[i][j] &= (~HIDDEN); | |
339 | if (s & HORWALL) { | |
340 | ch = '-'; | |
341 | } else if (s & VERTWALL) { | |
342 | ch = '|'; | |
343 | } else if (s & DOOR) { | |
344 | ch = '+'; | |
345 | } else if (s & TRAP) { | |
346 | ch = '^'; | |
347 | } else if (s & STAIRS) { | |
348 | ch = '%'; | |
349 | } else if (s & TUNNEL) { | |
350 | ch = '#'; | |
351 | } else { | |
352 | continue; | |
353 | } | |
354 | if ((!(s & MONSTER)) || (och == ' ')) { | |
355 | addch(ch); | |
356 | } | |
357 | if (s & MONSTER) { | |
358 | object *monster; | |
359 | ||
360 | if (monster = object_at(&level_monsters, i, j)) { | |
361 | monster->trail_char = ch; | |
362 | } | |
363 | } | |
364 | } | |
365 | } | |
366 | } | |
367 | } | |
368 | } | |
369 | ||
370 | dr_course(monster, entering, row, col) | |
371 | object *monster; | |
372 | boolean entering; | |
373 | short row, col; | |
374 | { | |
375 | short i, j, k, rn; | |
376 | short r, rr; | |
377 | ||
378 | monster->row = row; | |
379 | monster->col = col; | |
380 | ||
381 | if (mon_sees(monster, rogue.row, rogue.col)) { | |
382 | monster->trow = NO_ROOM; | |
383 | return; | |
384 | } | |
385 | rn = get_room_number(row, col); | |
386 | ||
387 | if (entering) { /* entering room */ | |
388 | /* look for door to some other room */ | |
389 | r = get_rand(0, MAXROOMS-1); | |
390 | for (i = 0; i < MAXROOMS; i++) { | |
391 | rr = (r + i) % MAXROOMS; | |
392 | if ((!(rooms[rr].is_room & (R_ROOM | R_MAZE))) || (rr == rn)) { | |
393 | continue; | |
394 | } | |
395 | for (k = 0; k < 4; k++) { | |
396 | if (rooms[rr].doors[k].oth_room == rn) { | |
397 | monster->trow = rooms[rr].doors[k].oth_row; | |
398 | monster->tcol = rooms[rr].doors[k].oth_col; | |
399 | if ((monster->trow == row) && | |
400 | (monster->tcol == col)) { | |
401 | continue; | |
402 | } | |
403 | return; | |
404 | } | |
405 | } | |
406 | } | |
407 | /* look for door to dead end */ | |
408 | for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) { | |
409 | for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) { | |
410 | if ((i != monster->row) && (j != monster->col) && | |
411 | (dungeon[i][j] & DOOR)) { | |
412 | monster->trow = i; | |
413 | monster->tcol = j; | |
414 | return; | |
415 | } | |
416 | } | |
417 | } | |
418 | /* return monster to room that he came from */ | |
419 | for (i = 0; i < MAXROOMS; i++) { | |
420 | for (j = 0; j < 4; j++) { | |
421 | if (rooms[i].doors[j].oth_room == rn) { | |
422 | for (k = 0; k < 4; k++) { | |
423 | if (rooms[rn].doors[k].oth_room == i) { | |
424 | monster->trow = rooms[rn].doors[k].oth_row; | |
425 | monster->tcol = rooms[rn].doors[k].oth_col; | |
426 | return; | |
427 | } | |
428 | } | |
429 | } | |
430 | } | |
431 | } | |
432 | /* no place to send monster */ | |
433 | monster->trow = NO_ROOM; | |
434 | } else { /* exiting room */ | |
435 | if (!get_oth_room(rn, &row, &col)) { | |
436 | monster->trow = NO_ROOM; | |
437 | } else { | |
438 | monster->trow = row; | |
439 | monster->tcol = col; | |
440 | } | |
441 | } | |
442 | } | |
443 | ||
444 | get_oth_room(rn, row, col) | |
445 | short rn, *row, *col; | |
446 | { | |
447 | short d = -1; | |
448 | ||
449 | if (*row == rooms[rn].top_row) { | |
450 | d = UPWARD/2; | |
451 | } else if (*row == rooms[rn].bottom_row) { | |
452 | d = DOWN/2; | |
453 | } else if (*col == rooms[rn].left_col) { | |
454 | d = LEFT/2; | |
455 | } else if (*col == rooms[rn].right_col) { | |
456 | d = RIGHT/2; | |
457 | } | |
458 | if ((d != -1) && (rooms[rn].doors[d].oth_room >= 0)) { | |
459 | *row = rooms[rn].doors[d].oth_row; | |
460 | *col = rooms[rn].doors[d].oth_col; | |
461 | return(1); | |
462 | } | |
463 | return(0); | |
464 | } | |
465 | ||
466 | edit_opts() | |
467 | { | |
468 | char save[NOPTS+1][DCOLS]; | |
469 | short i, j; | |
470 | short ch; | |
471 | boolean done = 0; | |
472 | char buf[MAX_OPT_LEN + 2]; | |
473 | ||
474 | for (i = 0; i < NOPTS+1; i++) { | |
475 | for (j = 0; j < DCOLS; j++) { | |
476 | save[i][j] = mvinch(i, j); | |
477 | } | |
478 | if (i < NOPTS) { | |
479 | opt_show(i); | |
480 | } | |
481 | } | |
482 | opt_go(0); | |
483 | i = 0; | |
484 | ||
485 | while (!done) { | |
486 | refresh(); | |
487 | ch = rgetchar(); | |
488 | CH: | |
489 | switch(ch) { | |
490 | case '\033': | |
491 | done = 1; | |
492 | break; | |
493 | case '\012': | |
494 | case '\015': | |
495 | if (i == (NOPTS - 1)) { | |
496 | mvaddstr(NOPTS, 0, press_space); | |
497 | refresh(); | |
498 | wait_for_ack(); | |
499 | done = 1; | |
500 | } else { | |
501 | i++; | |
502 | opt_go(i); | |
503 | } | |
504 | break; | |
505 | case '-': | |
506 | if (i > 0) { | |
507 | opt_go(--i); | |
508 | } else { | |
509 | sound_bell(); | |
510 | } | |
511 | break; | |
512 | case 't': | |
513 | case 'T': | |
514 | case 'f': | |
515 | case 'F': | |
516 | if (options[i].is_bool) { | |
517 | *(options[i].bval) = (((ch == 't') || (ch == 'T')) ? 1 : 0); | |
518 | opt_show(i); | |
519 | opt_go(++i); | |
520 | break; | |
521 | } | |
522 | default: | |
523 | if (options[i].is_bool) { | |
524 | sound_bell(); | |
525 | break; | |
526 | } | |
527 | j = 0; | |
528 | if ((ch == '\010') || ((ch >= ' ') && (ch <= '~'))) { | |
529 | opt_erase(i); | |
530 | do { | |
531 | if ((ch >= ' ') && (ch <= '~') && (j < MAX_OPT_LEN)) { | |
532 | buf[j++] = ch; | |
533 | buf[j] = '\0'; | |
534 | addch(ch); | |
535 | } else if ((ch == '\010') && (j > 0)) { | |
536 | buf[--j] = '\0'; | |
537 | move(i, j + strlen(options[i].prompt)); | |
538 | addch(' '); | |
539 | move(i, j + strlen(options[i].prompt)); | |
540 | } | |
541 | refresh(); | |
542 | ch = rgetchar(); | |
543 | } while ((ch != '\012') && (ch != '\015') && (ch != '\033')); | |
544 | if (j != 0) { | |
545 | (void) strcpy(*(options[i].strval), buf); | |
546 | } | |
547 | opt_show(i); | |
548 | goto CH; | |
549 | } else { | |
550 | sound_bell(); | |
551 | } | |
552 | break; | |
553 | } | |
554 | } | |
555 | ||
556 | for (i = 0; i < NOPTS+1; i++) { | |
557 | move(i, 0); | |
558 | for (j = 0; j < DCOLS; j++) { | |
559 | addch(save[i][j]); | |
560 | } | |
561 | } | |
562 | } | |
563 | ||
564 | opt_show(i) | |
565 | int i; | |
566 | { | |
567 | char *s; | |
568 | struct option *opt = &options[i]; | |
569 | ||
570 | opt_erase(i); | |
571 | ||
572 | if (opt->is_bool) { | |
573 | s = *(opt->bval) ? "True" : "False"; | |
574 | } else { | |
575 | s = *(opt->strval); | |
576 | } | |
577 | addstr(s); | |
578 | } | |
579 | ||
580 | opt_erase(i) | |
581 | int i; | |
582 | { | |
583 | struct option *opt = &options[i]; | |
584 | ||
585 | mvaddstr(i, 0, opt->prompt); | |
586 | clrtoeol(); | |
587 | } | |
588 | ||
589 | opt_go(i) | |
590 | int i; | |
591 | { | |
592 | move(i, strlen(options[i].prompt)); | |
593 | } | |
594 | ||
595 | do_shell() | |
596 | { | |
597 | #ifdef UNIX | |
598 | char *sh; | |
599 | ||
600 | md_ignore_signals(); | |
601 | if (!(sh = md_getenv("SHELL"))) { | |
602 | sh = "/bin/sh"; | |
603 | } | |
604 | move(LINES-1, 0); | |
605 | refresh(); | |
606 | stop_window(); | |
607 | printf("\nCreating new shell...\n"); | |
608 | md_shell(sh); | |
609 | start_window(); | |
610 | wrefresh(curscr); | |
611 | md_heed_signals(); | |
612 | #endif | |
613 | } |