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