date and time created 88/07/22 16:08:01 by bostic
[unix-history] / usr / src / games / rogue / room.c
CommitLineData
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
14static char sccsid[] = "@(#)room.c 5.1 (Berkeley) %G%";
15#endif /* not lint */
16
17#include "rogue.h"
18
19room rooms[MAXROOMS];
20boolean rooms_visited[MAXROOMS];
21
22extern short blind;
23extern boolean detect_monster, jump, passgo, no_skull, ask_quit;
24extern char *nick_name, *fruit, *save_file, *press_space;
25
26#define NOPTS 7
27
28struct 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
64light_up_room(rn)
65int 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
91light_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
110darken_room(rn)
111short 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
134get_dungeon_char(row, col)
135register 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
182get_mask_char(mask)
183register 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
209gr_row_col(row, col, mask)
210short *row, *col;
211unsigned 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
230gr_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
241party_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
273get_room_number(row, col)
274register 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
287is_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
308visit_rooms(rn)
309int 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
324draw_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
370dr_course(monster, entering, row, col)
371object *monster;
372boolean entering;
373short 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
444get_oth_room(rn, row, col)
445short 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
466edit_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();
488CH:
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
564opt_show(i)
565int 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
580opt_erase(i)
581int i;
582{
583 struct option *opt = &options[i];
584
585 mvaddstr(i, 0, opt->prompt);
586 clrtoeol();
587}
588
589opt_go(i)
590int i;
591{
592 move(i, strlen(options[i].prompt));
593}
594
595do_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}