1 /*
2 * File: overmap.cc
3 * Idea: allow player to make notes about levels. I don't know how
4 * to do this (I expect it will require some kind of dynamic
5 * memory management thing). - LH
6 * Summary: Records location of stairs etc
7 * Written by: Linley Henzell
8 *
9 * Change History (most recent first):
10 *
11 * <3> 30/7/00 MV Made Over-map full-screen
12 * <2> 8/10/99 BCR Changed Linley's macros
13 * to an enum in overmap.h
14 * <1> 29/8/99 LRH Created
15 */
16
17 #include "AppHdr.h"
18 #include "overmap.h"
19
20 #include <string.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23
24 #include "externs.h"
25
26 // for #definitions of MAX_BRANCHES & MAX_LEVELS
27 #include "files.h"
28 // for #definitions of MAX_BRANCHES & MAX_LEVELS
29 #include "religion.h"
30 #include "stuff.h"
31 #include "view.h"
32
33 enum
34 {
35 NO_FEATURE = 0x00,
36 FEATURE_SHOP = 0x01,
37 FEATURE_LABYRINTH = 0x02,
38 FEATURE_HELL = 0x04,
39 FEATURE_ABYSS = 0x08,
40 FEATURE_PANDEMONIUM = 0x10
41 };
42
43 // These variables need to become part of the player struct
44 // and need to be stored in the .sav file:
45
46 // 0 == no altars;
47 // 100 == more than one altar; or
48 // # == which god for remaining numbers.
49
50 FixedArray<unsigned char, MAX_LEVELS, MAX_BRANCHES> altars_present;
51 FixedVector<char, MAX_BRANCHES> stair_level;
52 FixedArray<unsigned char, MAX_LEVELS, MAX_BRANCHES> feature;
53
54 int map_lines = 0; //mv: number of lines already printed on "over-map" screen
55
56 //mv: prints one line in specified colour
57 // void print_one_map_line( const char *line, int colour );
58 // void print_branch_entrance_line( const char *area );
59
60 void print_one_simple_line( const char *line, int colour );
61 void print_one_highlighted_line( const char *pre, const char *text,
62 const char *post, int colour );
63
64 static void print_level_name( int branch, int depth,
65 bool &printed_branch, bool &printed_level );
66
init_overmap(void)67 void init_overmap( void )
68 {
69 for (int i = 0; i < MAX_LEVELS; i++)
70 {
71 for (int j = 0; j < MAX_BRANCHES; j++)
72 {
73 altars_present[i][j] = 0;
74 feature[i][j] = 0;
75 }
76 }
77
78 for (int i = 0; i < MAX_BRANCHES; i++)
79 stair_level[i] = -1;
80 } // end init_overmap()
81
display_overmap(void)82 void display_overmap( void )
83 {
84 #ifdef DOS_TERM
85 char buffer[4800];
86
87 window(1, 1, 80, 25);
88 gettext(1, 1, 80, 25, buffer);
89 #endif
90
91 //mv: must be set to 0 so "More..." message appears really at the
92 // bottom of the screen
93 //Don't forget it could be changed since the last call of display_overmap
94 map_lines = 0;
95
96 clrscr();
97 bool pr_lev = false;
98 bool output = false;
99
100 print_one_simple_line(" Overview of the Dungeon", WHITE);
101
102 // This is a more sensible order than the order of the enums -- bwr
103 const int list_order[] =
104 {
105 BRANCH_MAIN_DUNGEON,
106 BRANCH_ECUMENICAL_TEMPLE,
107 BRANCH_ORCISH_MINES, BRANCH_ELVEN_HALLS,
108 BRANCH_LAIR, BRANCH_SWAMP, BRANCH_SLIME_PITS, BRANCH_SNAKE_PIT,
109 BRANCH_HIVE,
110 BRANCH_VAULTS, BRANCH_HALL_OF_BLADES, BRANCH_CRYPT, BRANCH_TOMB,
111 BRANCH_VESTIBULE_OF_HELL,
112 BRANCH_DIS, BRANCH_GEHENNA, BRANCH_COCYTUS, BRANCH_TARTARUS,
113 BRANCH_HALL_OF_ZOT
114 };
115
116 for (unsigned int index = 0; index < sizeof(list_order) / sizeof(int); index++)
117 {
118 const int i = list_order[index];
119 bool printed_branch = false;
120
121 for (int j = 0; j < MAX_LEVELS; j++)
122 {
123 bool printed_level = false;
124
125 if (altars_present[j][i] != 0)
126 {
127 print_level_name( i, j, printed_branch, printed_level );
128 output = true;
129
130 if (altars_present[j][i] == 100)
131 {
132 print_one_highlighted_line( " - some ",
133 "altars to the gods", ".",
134 WHITE );
135 }
136 else
137 {
138 snprintf( info, INFO_SIZE, "altar to %s",
139 god_name( altars_present[j][i] ) );
140
141 print_one_highlighted_line( " - an ", info, ".", WHITE );
142 }
143 }
144
145 if ( (feature[j][i] & FEATURE_SHOP) )
146 {
147 print_level_name( i, j, printed_branch, printed_level );
148
149 // print_one_simple_line(" - facilities for the purchase of goods.",LIGHTGREY);
150
151 print_one_highlighted_line( " - facilities for the ",
152 "purchase of goods", ".", LIGHTGREEN );
153 output = true;
154 }
155
156 if ( (feature[j][i] & FEATURE_ABYSS) )
157 {
158 print_level_name( i, j, printed_branch, printed_level );
159 // print_one_simple_line(" - a gateway into the Abyss.", LIGHTRED);
160 print_one_highlighted_line( " - a gateway into ",
161 "the Abyss", ".", MAGENTA );
162 output = true;
163 }
164
165 if ( (feature[j][i] & FEATURE_PANDEMONIUM) )
166 {
167 print_level_name( i, j, printed_branch, printed_level );
168 // print_one_simple_line(" - a link to Pandemonium.", LIGHTRED);
169
170 print_one_highlighted_line( " - a link to ", "Pandemonium",
171 ".", LIGHTBLUE );
172 output = true;
173 }
174
175 if ( (feature[j][i] & FEATURE_HELL) )
176 {
177 print_level_name( i, j, printed_branch, printed_level );
178 // print_one_simple_line(" - a mouth of Hell.", LIGHTRED);
179 print_one_highlighted_line( " - a mouth of ", "Hell", ".", RED );
180 output = true;
181 }
182
183 if ( (feature[j][i] & FEATURE_LABYRINTH) )
184 {
185 print_level_name( i, j, printed_branch, printed_level );
186 // print_one_simple_line(" - the entrance of a Labyrinth.", LIGHTRED);
187 print_one_highlighted_line( " - an entrance to ",
188 "a Labyrinth", ".", CYAN );
189 output = true;
190 }
191
192
193 // NB: k starts at 1 because there aren't any staircases
194 // to the main dungeon
195 for (int k = 1; k < MAX_BRANCHES; k++)
196 {
197 pr_lev = false;
198 // strcpy(info, " - a staircase leading to ");
199 info[0] = '\0';
200
201 if (stair_level[k] == j)
202 {
203 switch (i)
204 {
205 case BRANCH_LAIR:
206 switch (k)
207 {
208 case BRANCH_SLIME_PITS:
209 strcat(info, "the Slime Pits");
210 pr_lev = true;
211 break;
212 case BRANCH_SNAKE_PIT:
213 strcat(info, "the Snake Pit");
214 pr_lev = true;
215 break;
216 case BRANCH_SWAMP:
217 strcat(info, "the Swamp");
218 pr_lev = true;
219 break;
220 }
221 break;
222
223 case BRANCH_VAULTS:
224 switch (k)
225 {
226 case BRANCH_HALL_OF_BLADES:
227 strcat(info, "the Hall of Blades");
228 pr_lev = true;
229 break;
230 case BRANCH_CRYPT:
231 strcat(info, "the Crypt");
232 pr_lev = true;
233 break;
234 }
235 break;
236
237 case BRANCH_CRYPT:
238 switch (k)
239 {
240 case BRANCH_TOMB:
241 strcat(info, "the Tomb");
242 pr_lev = true;
243 break;
244 }
245 break;
246
247 case BRANCH_ORCISH_MINES:
248 switch (k)
249 {
250 case BRANCH_ELVEN_HALLS:
251 strcat(info, "the Elven Halls");
252 pr_lev = true;
253 break;
254 }
255 break;
256
257 case BRANCH_MAIN_DUNGEON:
258 switch (k)
259 {
260 case BRANCH_ORCISH_MINES:
261 strcat(info, "the Orcish Mines");
262 pr_lev = true;
263 break;
264 case BRANCH_HIVE:
265 strcat(info, "the Hive");
266 pr_lev = true;
267 break;
268 case BRANCH_LAIR:
269 strcat(info, "the Lair");
270 pr_lev = true;
271 break;
272 case BRANCH_VAULTS:
273 strcat(info, "the Vaults");
274 pr_lev = true;
275 break;
276 case BRANCH_HALL_OF_ZOT:
277 strcat(info, "the Hall of Zot");
278 pr_lev = true;
279 break;
280 case BRANCH_ECUMENICAL_TEMPLE:
281 strcat(info, "the Ecumenical Temple");
282 pr_lev = true;
283 break;
284 }
285 break;
286 }
287 }
288
289 if (pr_lev)
290 {
291 print_level_name( i, j, printed_branch, printed_level );
292 print_one_highlighted_line( " - the entrance to ", info,
293 ".", YELLOW );
294 output = true;
295 }
296 }
297 }
298 }
299
300 textcolor( LIGHTGREY );
301
302 if (!output)
303 cprintf( EOL "You have yet to discover anything worth noting." EOL );
304
305 getch();
306
307 redraw_screen();
308
309 #ifdef DOS_TERM
310 puttext(1, 1, 80, 25, buffer);
311 #endif
312 } // end display_overmap()
313
314
print_level_name(int branch,int depth,bool & printed_branch,bool & printed_level)315 static void print_level_name( int branch, int depth,
316 bool &printed_branch, bool &printed_level )
317 {
318 if (!printed_branch)
319 {
320 printed_branch = true;
321
322 print_one_simple_line( "", YELLOW );
323 print_one_simple_line(
324 (branch == BRANCH_MAIN_DUNGEON) ? "Main Dungeon" :
325 (branch == BRANCH_ORCISH_MINES) ? "The Orcish Mines" :
326 (branch == BRANCH_HIVE) ? "The Hive" :
327 (branch == BRANCH_LAIR) ? "The Lair" :
328 (branch == BRANCH_SLIME_PITS) ? "The Slime Pits" :
329 (branch == BRANCH_VAULTS) ? "The Vaults" :
330 (branch == BRANCH_CRYPT) ? "The Crypt" :
331 (branch == BRANCH_HALL_OF_BLADES) ? "The Hall of Blades" :
332 (branch == BRANCH_HALL_OF_ZOT) ? "The Hall of Zot" :
333 (branch == BRANCH_ECUMENICAL_TEMPLE) ? "The Ecumenical Temple" :
334 (branch == BRANCH_SNAKE_PIT) ? "The Snake Pit" :
335 (branch == BRANCH_ELVEN_HALLS) ? "The Elven Halls" :
336 (branch == BRANCH_TOMB) ? "The Tomb" :
337 (branch == BRANCH_SWAMP) ? "The Swamp" :
338
339 (branch == BRANCH_DIS) ? "The Iron City of Dis" :
340 (branch == BRANCH_GEHENNA) ? "Gehenna" :
341 (branch == BRANCH_VESTIBULE_OF_HELL) ? "The Vestibule of Hell" :
342 (branch == BRANCH_COCYTUS) ? "Cocytus" :
343 (branch == BRANCH_TARTARUS) ? "Tartarus"
344 : "Unknown Area",
345
346 YELLOW );
347 }
348
349 if (!printed_level)
350 {
351 printed_level = true;
352
353 if (branch == BRANCH_ECUMENICAL_TEMPLE
354 || branch == BRANCH_HALL_OF_BLADES
355 || branch == BRANCH_VESTIBULE_OF_HELL)
356 {
357 // these areas only have one level... let's save the space
358 return;
359 }
360
361 // we need our own buffer in here (info is used):
362 char buff[ INFO_SIZE ] = "\0";;
363
364 if (branch == BRANCH_MAIN_DUNGEON)
365 depth += 1;
366 else if (branch >= BRANCH_ORCISH_MINES && branch <= BRANCH_SWAMP)
367 depth -= you.branch_stairs[ branch - BRANCH_ORCISH_MINES ];
368 else // branch is in hell (all of which start at depth 28)
369 depth -= 26;
370
371 snprintf( buff, INFO_SIZE, " Level %d:", depth );
372 print_one_simple_line( buff, LIGHTRED );
373 }
374 }
375
seen_staircase(unsigned char which_staircase)376 void seen_staircase( unsigned char which_staircase )
377 {
378 // which_staircase holds the grid value of the stair, must be converted
379 // Only handles stairs, not gates or arches
380 // Don't worry about:
381 // - stairs returning to dungeon - predictable
382 // - entrances to the hells - always in vestibule
383
384 unsigned char which_branch = BRANCH_MAIN_DUNGEON;
385
386 switch ( which_staircase )
387 {
388 case DNGN_ENTER_ORCISH_MINES:
389 which_branch = BRANCH_ORCISH_MINES;
390 break;
391 case DNGN_ENTER_HIVE:
392 which_branch = BRANCH_HIVE;
393 break;
394 case DNGN_ENTER_LAIR:
395 which_branch = BRANCH_LAIR;
396 break;
397 case DNGN_ENTER_SLIME_PITS:
398 which_branch = BRANCH_SLIME_PITS;
399 break;
400 case DNGN_ENTER_VAULTS:
401 which_branch = BRANCH_VAULTS;
402 break;
403 case DNGN_ENTER_CRYPT:
404 which_branch = BRANCH_CRYPT;
405 break;
406 case DNGN_ENTER_HALL_OF_BLADES:
407 which_branch = BRANCH_HALL_OF_BLADES;
408 break;
409 case DNGN_ENTER_ZOT:
410 which_branch = BRANCH_HALL_OF_ZOT;
411 break;
412 case DNGN_ENTER_TEMPLE:
413 which_branch = BRANCH_ECUMENICAL_TEMPLE;
414 break;
415 case DNGN_ENTER_SNAKE_PIT:
416 which_branch = BRANCH_SNAKE_PIT;
417 break;
418 case DNGN_ENTER_ELVEN_HALLS:
419 which_branch = BRANCH_ELVEN_HALLS;
420 break;
421 case DNGN_ENTER_TOMB:
422 which_branch = BRANCH_TOMB;
423 break;
424 case DNGN_ENTER_SWAMP:
425 which_branch = BRANCH_SWAMP;
426 break;
427 default:
428 exit(-1); // shouldn't happen
429 }
430
431 stair_level[which_branch] = you.your_level;
432 } // end seen_staircase()
433
434
435 // if player has seen an altar; record it
seen_altar(unsigned char which_altar)436 void seen_altar( unsigned char which_altar )
437 {
438 // can't record in abyss or pan.
439 if ( you.level_type != LEVEL_DUNGEON )
440 return;
441
442 // portable; no point in recording
443 if ( which_altar == GOD_NEMELEX_XOBEH )
444 return;
445
446 // already seen
447 if ( altars_present[you.your_level][you.where_are_you] == which_altar )
448 return;
449
450 if ( altars_present[you.your_level][you.where_are_you] == 0 )
451 altars_present[you.your_level][you.where_are_you] = which_altar;
452 else
453 altars_present[you.your_level][you.where_are_you] = 100;
454 } // end seen_altar()
455
456
457 // if player has seen any other thing; record it
seen_other_thing(unsigned char which_thing)458 void seen_other_thing( unsigned char which_thing )
459 {
460 if ( you.level_type != LEVEL_DUNGEON ) // can't record in abyss or pan.
461 return;
462
463 switch ( which_thing )
464 {
465 case DNGN_ENTER_SHOP:
466 feature[you.your_level][you.where_are_you] |= FEATURE_SHOP;
467 break;
468 case DNGN_ENTER_LABYRINTH:
469 feature[you.your_level][you.where_are_you] |= FEATURE_LABYRINTH;
470 break;
471 case DNGN_ENTER_HELL:
472 feature[you.your_level][you.where_are_you] |= FEATURE_HELL;
473 break;
474 case DNGN_ENTER_ABYSS:
475 feature[you.your_level][you.where_are_you] |= FEATURE_ABYSS;
476 break;
477 case DNGN_ENTER_PANDEMONIUM:
478 feature[you.your_level][you.where_are_you] |= FEATURE_PANDEMONIUM;
479 break;
480 }
481 } // end seen_other_thing()
482
483
484 /* mv: this function prints one line at "Over-map screen" in specified colour.
485 * If map_lines = maximum number of lines (it means the screen is full) it
486 * prints "More..." message, read key, clear screen and after that prints new
487 * line
488 */
print_one_simple_line(const char * line,int colour)489 void print_one_simple_line( const char *line , int colour)
490 {
491 if (map_lines == (get_number_of_lines() - 2))
492 {
493 textcolor( LIGHTGREY );
494 cprintf(EOL);
495 cprintf("More...");
496 getch();
497 clrscr();
498 map_lines = 0;
499 }
500
501 textcolor( colour );
502 cprintf( line );
503 cprintf( EOL );
504
505 map_lines++;
506 }
507
print_one_highlighted_line(const char * pre,const char * text,const char * post,int colour)508 void print_one_highlighted_line( const char *pre, const char *text,
509 const char *post, int colour )
510 {
511 if (map_lines == (get_number_of_lines() - 2))
512 {
513 textcolor( LIGHTGREY );
514 cprintf(EOL);
515 cprintf("More...");
516 getch();
517 clrscr();
518 map_lines = 0;
519 }
520
521 if (pre[0] != '\0')
522 {
523 textcolor( LIGHTGREY );
524 cprintf( pre );
525 }
526
527 textcolor( colour );
528 cprintf( text );
529
530 if (post[0] != '\0')
531 {
532 textcolor( LIGHTGREY );
533 cprintf( post );
534 }
535
536 cprintf( EOL );
537
538 map_lines++;
539 }
540