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