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