2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)room.c 8.1 (Berkeley) 5/31/93
37 * $FreeBSD: src/games/rogue/room.c,v 1.7 1999/11/30 03:49:26 billf Exp $
38 * $DragonFly: src/games/rogue/room.c,v 1.3 2006/09/02 19:31:07 pavalos Exp $
44 * This source herein may be modified and/or distributed by anybody who
45 * so desires, with the following restrictions:
46 * 1.) No portion of this notice shall be removed.
47 * 2.) Credit shall not be taken for the creation of this source.
48 * 3.) This code is not to be traded, sold, or used for personal
56 boolean rooms_visited
[MAXROOMS
];
59 extern boolean detect_monster
, jump
, passgo
, no_skull
, ask_quit
, flush
;
60 extern char *nick_name
, *fruit
, *save_file
, *press_space
;
71 "Flush typeahead during battle (\"flush\"): ",
72 1, (char **) 0, &flush
75 "Show position only at end of run (\"jump\"): ",
79 "Follow turnings in passageways (\"passgo\"): ",
80 1, (char **) 0, &passgo
83 "Don't print skull when killed (\"noskull\" or \"notombstone\"): ",
84 1, (char **) 0, &no_skull
87 "Ask player before saying 'Okay, bye-bye!' (\"askquit\"): ",
88 1, (char **) 0, &ask_quit
95 "Fruit (\"fruit\"): ",
99 "Save file (\"file\"): ",
104 static void visit_rooms(int);
105 static boolean
get_oth_room(short, short *, short *);
106 static void opt_show(int);
107 static void opt_erase(int);
108 static void opt_go(int);
111 light_up_room(int rn
)
116 for (i
= rooms
[rn
].top_row
;
117 i
<= rooms
[rn
].bottom_row
; i
++) {
118 for (j
= rooms
[rn
].left_col
;
119 j
<= rooms
[rn
].right_col
; j
++) {
120 if (dungeon
[i
][j
] & MONSTER
) {
123 if ((monster
= object_at(&level_monsters
, i
, j
))) {
124 dungeon
[monster
->row
][monster
->col
] &= (~MONSTER
);
125 monster
->trail_char
=
126 get_dungeon_char(monster
->row
, monster
->col
);
127 dungeon
[monster
->row
][monster
->col
] |= MONSTER
;
130 mvaddch(i
, j
, get_dungeon_char(i
, j
));
133 mvaddch(rogue
.row
, rogue
.col
, rogue
.fchar
);
138 light_passage(int row
, int col
)
140 short i
, j
, i_end
, j_end
;
145 i_end
= (row
< (DROWS
-2)) ? 1 : 0;
146 j_end
= (col
< (DCOLS
-1)) ? 1 : 0;
148 for (i
= ((row
> MIN_ROW
) ? -1 : 0); i
<= i_end
; i
++) {
149 for (j
= ((col
> 0) ? -1 : 0); j
<= j_end
; j
++) {
150 if (can_move(row
, col
, row
+i
, col
+j
)) {
151 mvaddch(row
+i
, col
+j
, get_dungeon_char(row
+i
, col
+j
));
158 darken_room(short rn
)
162 for (i
= rooms
[rn
].top_row
+ 1; i
< rooms
[rn
].bottom_row
; i
++) {
163 for (j
= rooms
[rn
].left_col
+ 1; j
< rooms
[rn
].right_col
; j
++) {
167 if (!(dungeon
[i
][j
] & (OBJECT
| STAIRS
)) &&
168 !(detect_monster
&& (dungeon
[i
][j
] & MONSTER
))) {
169 if (!imitating(i
, j
)) {
172 if ((dungeon
[i
][j
] & TRAP
) && (!(dungeon
[i
][j
] & HIDDEN
))) {
182 get_dungeon_char(int row
, int col
)
184 unsigned short mask
= dungeon
[row
][col
];
186 if (mask
& MONSTER
) {
187 return(gmc_row_col(row
, col
));
192 obj
= object_at(&level_objects
, row
, col
);
193 return(get_mask_char(obj
->what_is
));
195 if (mask
& (TUNNEL
| STAIRS
| HORWALL
| VERTWALL
| FLOOR
| DOOR
)) {
196 if ((mask
& (TUNNEL
| STAIRS
)) && (!(mask
& HIDDEN
))) {
197 return(((mask
& STAIRS
) ? '%' : '#'));
199 if (mask
& HORWALL
) {
202 if (mask
& VERTWALL
) {
207 if (!(dungeon
[row
][col
] & HIDDEN
)) {
215 if (((col
> 0) && (dungeon
[row
][col
-1] & HORWALL
)) ||
216 ((col
< (DCOLS
-1)) && (dungeon
[row
][col
+1] & HORWALL
))) {
230 get_mask_char(unsigned short mask
)
252 return('~'); /* unknown, something is wrong */
257 gr_row_col(short *row
, short *col
, unsigned short mask
)
263 r
= get_rand(MIN_ROW
, DROWS
-2);
264 c
= get_rand(0, DCOLS
-1);
265 rn
= get_room_number(r
, c
);
266 } while ((rn
== NO_ROOM
) ||
267 (!(dungeon
[r
][c
] & mask
)) ||
268 (dungeon
[r
][c
] & (~mask
)) ||
269 (!(rooms
[rn
].is_room
& (R_ROOM
| R_MAZE
))) ||
270 ((r
== rogue
.row
) && (c
== rogue
.col
)));
282 i
= get_rand(0, MAXROOMS
-1);
283 } while (!(rooms
[i
].is_room
& (R_ROOM
| R_MAZE
)));
289 party_objects(short rn
)
293 short n
, N
, row
, col
;
296 N
= ((rooms
[rn
].bottom_row
- rooms
[rn
].top_row
) - 1) *
297 ((rooms
[rn
].right_col
- rooms
[rn
].left_col
) - 1);
302 for (i
= 0; i
< n
; i
++) {
303 for (j
= found
= 0; ((!found
) && (j
< 250)); j
++) {
304 row
= get_rand(rooms
[rn
].top_row
+1,
305 rooms
[rn
].bottom_row
-1);
306 col
= get_rand(rooms
[rn
].left_col
+1,
307 rooms
[rn
].right_col
-1);
308 if ((dungeon
[row
][col
] == FLOOR
) || (dungeon
[row
][col
] == TUNNEL
)) {
314 place_at(obj
, row
, col
);
322 get_room_number(int row
, int col
)
326 for (i
= 0; i
< MAXROOMS
; i
++) {
327 if ((row
>= rooms
[i
].top_row
) && (row
<= rooms
[i
].bottom_row
) &&
328 (col
>= rooms
[i
].left_col
) && (col
<= rooms
[i
].right_col
)) {
336 is_all_connected(void)
338 short i
, starting_room
= 0;
340 for (i
= 0; i
< MAXROOMS
; i
++) {
341 rooms_visited
[i
] = 0;
342 if (rooms
[i
].is_room
& (R_ROOM
| R_MAZE
)) {
347 visit_rooms(starting_room
);
349 for (i
= 0; i
< MAXROOMS
; i
++) {
350 if ((rooms
[i
].is_room
& (R_ROOM
| R_MAZE
)) && (!rooms_visited
[i
])) {
363 rooms_visited
[rn
] = 1;
365 for (i
= 0; i
< 4; i
++) {
366 oth_rn
= rooms
[rn
].doors
[i
].oth_room
;
367 if ((oth_rn
>= 0) && (!rooms_visited
[oth_rn
])) {
377 unsigned short mask
= (HORWALL
| VERTWALL
| DOOR
| TUNNEL
| TRAP
| STAIRS
|
381 for (i
= 0; i
< DROWS
; i
++) {
382 for (j
= 0; j
< DCOLS
; j
++) {
385 if (((ch
= mvinch(i
, j
)) == ' ') ||
386 ((ch
>= 'A') && (ch
<= 'Z')) || (s
& (TRAP
| HIDDEN
))) {
388 dungeon
[i
][j
] &= (~HIDDEN
);
391 } else if (s
& VERTWALL
) {
393 } else if (s
& DOOR
) {
395 } else if (s
& TRAP
) {
397 } else if (s
& STAIRS
) {
399 } else if (s
& TUNNEL
) {
404 if ((!(s
& MONSTER
)) || (och
== ' ')) {
410 if ((monster
= object_at(&level_monsters
, i
, j
))) {
411 monster
->trail_char
= ch
;
421 dr_course(object
*monster
, boolean entering
, short row
, short col
)
429 if (mon_sees(monster
, rogue
.row
, rogue
.col
)) {
430 monster
->trow
= NO_ROOM
;
433 rn
= get_room_number(row
, col
);
435 if (entering
) { /* entering room */
436 /* look for door to some other room */
437 r
= get_rand(0, MAXROOMS
-1);
438 for (i
= 0; i
< MAXROOMS
; i
++) {
439 rr
= (r
+ i
) % MAXROOMS
;
440 if ((!(rooms
[rr
].is_room
& (R_ROOM
| R_MAZE
))) || (rr
== rn
)) {
443 for (k
= 0; k
< 4; k
++) {
444 if (rooms
[rr
].doors
[k
].oth_room
== rn
) {
445 monster
->trow
= rooms
[rr
].doors
[k
].oth_row
;
446 monster
->tcol
= rooms
[rr
].doors
[k
].oth_col
;
447 if ((monster
->trow
== row
) &&
448 (monster
->tcol
== col
)) {
455 /* look for door to dead end */
456 for (i
= rooms
[rn
].top_row
; i
<= rooms
[rn
].bottom_row
; i
++) {
457 for (j
= rooms
[rn
].left_col
; j
<= rooms
[rn
].right_col
; j
++) {
458 if ((i
!= monster
->row
) && (j
!= monster
->col
) &&
459 (dungeon
[i
][j
] & DOOR
)) {
466 /* return monster to room that he came from */
467 for (i
= 0; i
< MAXROOMS
; i
++) {
468 for (j
= 0; j
< 4; j
++) {
469 if (rooms
[i
].doors
[j
].oth_room
== rn
) {
470 for (k
= 0; k
< 4; k
++) {
471 if (rooms
[rn
].doors
[k
].oth_room
== i
) {
472 monster
->trow
= rooms
[rn
].doors
[k
].oth_row
;
473 monster
->tcol
= rooms
[rn
].doors
[k
].oth_col
;
480 /* no place to send monster */
481 monster
->trow
= NO_ROOM
;
482 } else { /* exiting room */
483 if (!get_oth_room(rn
, &row
, &col
)) {
484 monster
->trow
= NO_ROOM
;
493 get_oth_room(short rn
, short *row
, short *col
)
497 if (*row
== rooms
[rn
].top_row
) {
499 } else if (*row
== rooms
[rn
].bottom_row
) {
501 } else if (*col
== rooms
[rn
].left_col
) {
503 } else if (*col
== rooms
[rn
].right_col
) {
506 if ((d
!= -1) && (rooms
[rn
].doors
[d
].oth_room
>= 0)) {
507 *row
= rooms
[rn
].doors
[d
].oth_row
;
508 *col
= rooms
[rn
].doors
[d
].oth_col
;
517 char save
[NOPTS
+1][DCOLS
];
521 char buf
[MAX_OPT_LEN
+ 2];
523 for (i
= 0; i
< NOPTS
+1; i
++) {
524 for (j
= 0; j
< DCOLS
; j
++) {
525 save
[i
][j
] = mvinch(i
, j
);
544 if (i
== (NOPTS
- 1)) {
545 mvaddstr(NOPTS
, 0, press_space
);
565 if (options
[i
].is_bool
) {
566 *(options
[i
].bval
) = (((ch
== 't') || (ch
== 'T')) ? 1 : 0);
572 if (options
[i
].is_bool
) {
577 if ((ch
== '\010') || ((ch
>= ' ') && (ch
<= '~'))) {
580 if ((ch
>= ' ') && (ch
<= '~') && (j
< MAX_OPT_LEN
)) {
584 } else if ((ch
== '\010') && (j
> 0)) {
586 move(i
, j
+ strlen(options
[i
].prompt
));
588 move(i
, j
+ strlen(options
[i
].prompt
));
592 } while ((ch
!= '\012') && (ch
!= '\015') && (ch
!= '\033'));
594 strcpy(*(options
[i
].strval
), buf
);
605 for (i
= 0; i
< NOPTS
+1; i
++) {
607 for (j
= 0; j
< DCOLS
; j
++) {
617 struct option
*opt
= &options
[i
];
622 s
= *(opt
->bval
) ? "True" : "False";
632 struct option
*opt
= &options
[i
];
634 mvaddstr(i
, 0, opt
->prompt
);
641 move(i
, strlen(options
[i
].prompt
));
651 if (!(sh
= md_getenv("SHELL"))) {
657 printf("\nCreating new shell...\n");