From 673bdae75485d14f759af597c3c62b99601f9a43 Mon Sep 17 00:00:00 2001 From: peterb12 Date: Thu, 21 Jul 2005 02:34:44 +0000 Subject: Initial revision git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3 c06c8d41-db1a-0410-9941-cceddc491573 --- trunk/source/view.cc | 3524 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3524 insertions(+) create mode 100644 trunk/source/view.cc (limited to 'trunk/source/view.cc') diff --git a/trunk/source/view.cc b/trunk/source/view.cc new file mode 100644 index 0000000000..0e2fccd58e --- /dev/null +++ b/trunk/source/view.cc @@ -0,0 +1,3524 @@ +/* + * File: view.cc + * Summary: Misc function used to render the dungeon. + * Written by: Linley Henzell + * + * Change History (most recent first): + * + * <10> 29 Jul 00 JDJ show_map iterates horizontally to 79 instead of 80. + * item no longer indexes past the end of environ::grid. + * <9> 19 Jun 00 GDL Complete rewrite of LOS code + * <8> 11/23/99 LRH Added colour-coded play-screen map & clean_map + * init options + * <7> 9/29/99 BCR Removed first argument from draw_border + * <6> 9/11/99 LRH Added calls to overmap functions + * <5> 6/22/99 BWR Fixed and improved the stealth + * <4> 5/20/99 BWR show_map colours all portals, + * exits from subdungeons now + * look like up stairs. + * <3> 5/09/99 JDJ show_map draws shops in yellow. + * <2> 5/09/99 JDJ show_map accepts '\r' along with '.'. + * <1> -/--/-- LRH Created + */ + +#include "AppHdr.h" +#include "view.h" + +#include + +#ifdef DOS +#include +#endif + +#include "externs.h" + +#include "debug.h" +#include "insult.h" +#include "macro.h" +#include "monstuff.h" +#include "mon-util.h" +#include "overmap.h" +#include "player.h" +#include "skills2.h" +#include "stuff.h" +#include "spells4.h" + + +unsigned char your_sign; // accessed as extern in transfor.cc and acr.cc +unsigned char your_colour; // accessed as extern in transfor.cc and acr.cc + +FixedArray < unsigned int, 20, 19 > show_backup; + +unsigned char show_green; +extern int stealth; // defined in acr.cc +extern FixedVector Visible_Statue; // defined in acr.cc + +// char colour_code_map(unsigned char map_value); +char colour_code_map( int x, int y ); + +unsigned char (*mapch) (unsigned char); +unsigned char (*mapch2) (unsigned char); +unsigned char mapchar(unsigned char ldfk); +unsigned char mapchar2(unsigned char ldfk); +unsigned char mapchar3(unsigned char ldfk); +unsigned char mapchar4(unsigned char ldfk); +void cloud_grid(void); +void monster_grid(bool do_updates); + +//--------------------------------------------------------------- +// +// get_number_of_lines +// +// Made this a function instead of a #define. This should help +// considering the fact that the curses version is a macro +// (curses tends to be implemented with a large number of +// preprocessor macros, which can wreak havoc with things +// like the C++ string class, so we want to isolate that +// away to keep portability up). +// +// Other OSes might want to hook into reading system environment +// variables or player set options to determine the screen size +// (see the Options and SysEnv structures, as well as initfile.cc). +// +// This might be better to move to the lib*.cc files, but we +// don't really have a standard API defined for them, or the +// all important libdos.cc. It would be a good idea to eventually +// head that way. -- bwr +// +//--------------------------------------------------------------- +int get_number_of_lines(void) +{ +#ifdef LINUX + return (get_number_of_lines_from_curses()); +#elif MAC + return (MAC_NUMBER_OF_LINES); +#else + return (25); +#endif +} + + +//--------------------------------------------------------------- +// +// get_ibm_symbol +// +// Returns the DOS character code and color for everything drawn +// with the IBM graphics option. +// +//--------------------------------------------------------------- +static void get_ibm_symbol(unsigned int object, unsigned short *ch, + unsigned short *color) +{ + ASSERT(color != NULL); + ASSERT(ch != NULL); + + switch (object) + { + case DNGN_UNSEEN: + *ch = 0; + break; + + case DNGN_ROCK_WALL: + case DNGN_PERMAROCK_WALL: + *color = env.rock_colour; + *ch = 177; + break; // remember earth elementals + + // stone in the realm of Zot is coloured the same as rock + case DNGN_STONE_WALL: + *color = (player_in_branch( BRANCH_HALL_OF_ZOT ) ? env.rock_colour + : LIGHTGREY); + *ch = 177; + break; + + case DNGN_CLOSED_DOOR: + *ch = 254; + break; + + case DNGN_METAL_WALL: + *ch = 177; + *color = CYAN; + break; + + case DNGN_SECRET_DOOR: + *ch = 177; + *color = env.rock_colour; + break; + + case DNGN_GREEN_CRYSTAL_WALL: + *ch = 177; + *color = GREEN; + break; + + case DNGN_ORCISH_IDOL: + *ch = '8'; + *color = DARKGREY; + break; + + case DNGN_WAX_WALL: + *ch = 177; + *color = YELLOW; + break; // wax wall + /* Anything added here must also be added to the PLAIN_TERMINAL + viewwindow2 below */ + + case DNGN_SILVER_STATUE: + *ch = '8'; + *color = WHITE; + Visible_Statue[ STATUE_SILVER ] = 1; + break; + + case DNGN_GRANITE_STATUE: + *ch = '8'; + *color = LIGHTGREY; + break; + + case DNGN_ORANGE_CRYSTAL_STATUE: + *ch = '8'; + *color = LIGHTRED; + Visible_Statue[ STATUE_ORANGE_CRYSTAL ] = 1; + break; + + case DNGN_LAVA: + *ch = 247; + *color = RED; + break; + + case DNGN_DEEP_WATER: + *ch = 247; // this wavy thing also used for water elemental + *color = BLUE; + break; + + case DNGN_SHALLOW_WATER: + *ch = 247; // this wavy thing also used for water elemental + *color = CYAN; + break; + + case DNGN_FLOOR: + *color = env.floor_colour; + *ch = 249; + break; + + case DNGN_ENTER_HELL: + *ch = 239; + *color = RED; + seen_other_thing(object); + break; + + case DNGN_OPEN_DOOR: + *ch = 39; + break; + + case DNGN_BRANCH_STAIRS: + *ch = 240; + *color = BROWN; + break; + + case DNGN_TRAP_MECHANICAL: + *color = LIGHTCYAN; + *ch = 94; + break; + + case DNGN_TRAP_MAGICAL: + *color = MAGENTA; + *ch = 94; + break; + + case DNGN_TRAP_III: + *color = LIGHTGREY; + *ch = 94; + break; + + case DNGN_UNDISCOVERED_TRAP: + *ch = 249; + *color = env.floor_colour; + break; + + case DNGN_ENTER_SHOP: + *ch = 239; + *color = YELLOW; + + seen_other_thing(object); + break; + // if I change anything above here, must also change magic mapping! + + case DNGN_ENTER_LABYRINTH: + *ch = 239; + *color = LIGHTGREY; + seen_other_thing(object); + break; + + // not sure why we have "odd" here, but "ladders" are special in + // that they all lead to the first staircase of the next level + // (and returning from there will take you somewhere different) + // ... that's why they're brown... it's a warning -- bwr + case DNGN_ROCK_STAIRS_DOWN: + *color = BROWN; // ladder // odd {dlb} + case DNGN_STONE_STAIRS_DOWN_I: + case DNGN_STONE_STAIRS_DOWN_II: + case DNGN_STONE_STAIRS_DOWN_III: + *ch = '>'; + break; + + case DNGN_ROCK_STAIRS_UP: + *color = BROWN; // ladder // odd {dlb} + case DNGN_STONE_STAIRS_UP_I: + case DNGN_STONE_STAIRS_UP_II: + case DNGN_STONE_STAIRS_UP_III: + *ch = '<'; + break; + + case DNGN_ENTER_DIS: + *color = CYAN; + *ch = 239; + break; + + case DNGN_ENTER_GEHENNA: + *color = RED; + *ch = 239; + break; + + case DNGN_ENTER_COCYTUS: + *color = LIGHTCYAN; + *ch = 239; + break; + + case DNGN_ENTER_TARTARUS: + *color = DARKGREY; + *ch = 239; + break; + + case DNGN_ENTER_ABYSS: + *color = random2(16); + *ch = 239; + seen_other_thing(object); + break; + + case DNGN_EXIT_ABYSS: + *color = random2(16); + *ch = 239; + break; + + case DNGN_STONE_ARCH: + *color = LIGHTGREY; + *ch = 239; + break; + + case DNGN_ENTER_PANDEMONIUM: + *color = LIGHTBLUE; + *ch = 239; + seen_other_thing(object); + break; + + case DNGN_EXIT_PANDEMONIUM: + *color = LIGHTBLUE; + *ch = 239; + break; + + case DNGN_TRANSIT_PANDEMONIUM: + *color = LIGHTGREEN; + *ch = 239; + break; + + case DNGN_ENTER_ORCISH_MINES: + case DNGN_ENTER_HIVE: + case DNGN_ENTER_LAIR: + case DNGN_ENTER_SLIME_PITS: + case DNGN_ENTER_VAULTS: + case DNGN_ENTER_CRYPT: + case DNGN_ENTER_HALL_OF_BLADES: + case DNGN_ENTER_TEMPLE: + case DNGN_ENTER_SNAKE_PIT: + case DNGN_ENTER_ELVEN_HALLS: + case DNGN_ENTER_TOMB: + case DNGN_ENTER_SWAMP: + case 123: + case 124: + case 125: + case 126: + *color = YELLOW; + *ch = '>'; + seen_staircase(object); + break; + + case DNGN_ENTER_ZOT: + *color = MAGENTA; + *ch = 239; + seen_staircase(object); + break; + + case DNGN_RETURN_FROM_ORCISH_MINES: + case DNGN_RETURN_FROM_HIVE: + case DNGN_RETURN_FROM_LAIR: + case DNGN_RETURN_FROM_SLIME_PITS: + case DNGN_RETURN_FROM_VAULTS: + case DNGN_RETURN_FROM_CRYPT: + case DNGN_RETURN_FROM_HALL_OF_BLADES: + case DNGN_RETURN_FROM_TEMPLE: + case DNGN_RETURN_FROM_SNAKE_PIT: + case DNGN_RETURN_FROM_ELVEN_HALLS: + case DNGN_RETURN_FROM_TOMB: + case DNGN_RETURN_FROM_SWAMP: + case 143: + case 144: + case 145: + case 146: + *color = YELLOW; + *ch = '<'; + break; + + case DNGN_RETURN_FROM_ZOT: + *color = MAGENTA; + *ch = 239; + break; + + case DNGN_ALTAR_ZIN: + *color = WHITE; + *ch = 220; + seen_altar(GOD_ZIN); + break; + + case DNGN_ALTAR_SHINING_ONE: + *color = YELLOW; + *ch = 220; + seen_altar(GOD_SHINING_ONE); + break; + + case DNGN_ALTAR_KIKUBAAQUDGHA: + *color = DARKGREY; + *ch = 220; + seen_altar(GOD_KIKUBAAQUDGHA); + break; + + case DNGN_ALTAR_YREDELEMNUL: + *color = ((one_chance_in(3)) ? RED : DARKGREY); + *ch = 220; + seen_altar(GOD_YREDELEMNUL); + break; + + case DNGN_ALTAR_XOM: + *color = random_colour(); + *ch = 220; + seen_altar(GOD_XOM); + break; + + case DNGN_ALTAR_VEHUMET: + *color = LIGHTBLUE; + if (one_chance_in(3)) + *color = LIGHTMAGENTA; + if (one_chance_in(3)) + *color = LIGHTRED; + *ch = 220; + seen_altar(GOD_VEHUMET); + break; + + case DNGN_ALTAR_OKAWARU: + *color = CYAN; + *ch = 220; + seen_altar(GOD_OKAWARU); + break; + + case DNGN_ALTAR_MAKHLEB: + *color = RED; + if (one_chance_in(3)) + *color = LIGHTRED; + if (one_chance_in(3)) + *color = YELLOW; + *ch = 220; + seen_altar(GOD_MAKHLEB); + break; + + case DNGN_ALTAR_SIF_MUNA: + *color = BLUE; + *ch = 220; + seen_altar(GOD_SIF_MUNA); + break; + + case DNGN_ALTAR_TROG: + *color = RED; + *ch = 220; + seen_altar(GOD_TROG); + break; + + case DNGN_ALTAR_NEMELEX_XOBEH: + *color = LIGHTMAGENTA; + *ch = 220; + seen_altar(GOD_NEMELEX_XOBEH); + break; + + case DNGN_ALTAR_ELYVILON: + *color = LIGHTGREY; + *ch = 220; + seen_altar(GOD_ELYVILON); + break; + + case DNGN_BLUE_FOUNTAIN: + *color = BLUE; + *ch = 159; + break; + + case DNGN_SPARKLING_FOUNTAIN: + *color = LIGHTBLUE; + *ch = 159; + break; + + case DNGN_DRY_FOUNTAIN_I: + case DNGN_DRY_FOUNTAIN_II: + case DNGN_PERMADRY_FOUNTAIN: + *color = LIGHTGREY; + *ch = 159; + break; + + case 256: + *ch = '0'; + break; + + case 257: + *color = CYAN; + *ch = '~'; + break; /* Invis creature walking through water */ + + case 258: + *ch = ')'; + break; // weapon ) + + case 259: + *ch = '['; + break; // armour [ + + case 260: + *ch = '/'; + break; // wands, etc. + + case 261: + *ch = '%'; + break; // food + + case 262: + *ch = '+'; + break; // books + + + case 263: + *ch = '?'; + break; // scroll ? + + case 264: + *ch = '='; + break; // ring = etc + + case 265: + *ch = '!'; + break; // potions ! + + case 266: + *ch = '('; + break; // stones + + case 267: + *ch = '+'; + break; // book + + + case 268: + *ch = '%'; + break; // corpses part 1 + + case 269: + *ch = '\\'; + break; // magical staves + + case 270: + *ch = '}'; + break; // gems + + case 271: + *ch = '%'; + break; // don't know ? + + case 272: + *ch = '$'; + break; // $ gold + + case 273: + *ch = '"'; + break; // amulet + + default: + *ch = ((object >= 297) ? mons_char(object - 297) : object); + break; + } +} // end get_ibm_symbol() + + +//--------------------------------------------------------------- +// +// viewwindow2 +// +// Draws the main window using the extended IBM character set. +// +// This function should not interfer with the game condition, +// unless do_updates is set (ie. stealth checks for visible +// monsters). +// +//--------------------------------------------------------------- +void viewwindow2(char draw_it, bool do_updates) +{ + const long BUFFER_SIZE = 1550; +#ifdef DOS_TERM + // DOS functions like gettext() and puttext() can only + // work with arrays of characters, not shorts. + FixedVector < unsigned char, BUFFER_SIZE > buffy; //[800]; //392]; +#else + FixedVector < unsigned short, BUFFER_SIZE > buffy; //[800]; //392]; +#endif + + unsigned short ch, color; + + losight(env.show, grd, you.x_pos, you.y_pos); + + int count_x, count_y; + + for (count_x = 0; count_x < 18; count_x++) + { + for (count_y = 0; count_y < 18; count_y++) + { + env.show_col[count_x][count_y] = LIGHTGREY; + show_backup[count_x][count_y] = 0; + } + } + + item(); + cloud_grid(); + monster_grid(do_updates); + int bufcount = 0; + + if (draw_it == 1) + { + _setcursortype(_NOCURSOR); + for (count_y = you.y_pos - 8; count_y < you.y_pos + 9; count_y++) + { + bufcount += 16; + + for (count_x = you.x_pos - 8; count_x < you.x_pos + 9; count_x++) + { + // may be overriden by the code below + color = env.show_col[ count_x - you.x_pos + 9 ] + [ count_y - you.y_pos + 9 ]; + + unsigned int object = env.show[ count_x - you.x_pos + 9 ] + [ count_y - you.y_pos + 9 ]; + + get_ibm_symbol(object, &ch, &color); + + if (count_x == you.x_pos && count_y == you.y_pos) + { + ch = your_sign; + + if (player_is_swimming()) + { + color = (grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER) + ? BLUE : CYAN; + } + else + { + color = your_colour; + } + } + + ASSERT(bufcount + 1 < BUFFER_SIZE); + buffy[bufcount] = ch; + buffy[bufcount + 1] = color; + + bufcount += 2; + } + + bufcount += 16; + } + + if (you.level_type != LEVEL_LABYRINTH && you.level_type != LEVEL_ABYSS) + { + bufcount = 0; + + for (count_y = 0; count_y < 17; count_y++) + { + bufcount += 16; + + for (count_x = 0; count_x < 17; count_x++) + { + ASSERT(bufcount < BUFFER_SIZE); + + if (buffy[bufcount] != 0) + { + env.map[ count_x + you.x_pos - 9 ] + [ count_y + you.y_pos - 9 ] = buffy[bufcount]; + } + + if (Options.clean_map == 1 + && show_backup[count_x + 1][count_y + 1] != 0) + { + get_ibm_symbol(show_backup[count_x + 1][count_y + 1], + &ch, &color); + env.map[ count_x + you.x_pos - 9 ] + [ count_y + you.y_pos - 9 ] = ch; + } + bufcount += 2; + } + bufcount += 16; + } + } + + bufcount = 0; + for (count_y = 0; count_y < 17; count_y++) + { + for (count_x = 0; count_x < 33; count_x++) + { + if (count_x + you.x_pos - 17 < 3 + || count_y + you.y_pos - 9 < 3 + || count_x + you.x_pos - 14 > 77 + || count_y + you.y_pos - 9 > 67) + { + ASSERT(bufcount < BUFFER_SIZE); + buffy[bufcount] = 0; + bufcount++; + buffy[bufcount] = 0; + bufcount++; + continue; + } + + if (count_x >= 8 && count_x <= 24 && count_y >= 0 + && count_y <= 16 && buffy[bufcount] != 0) + { + bufcount += 2; + continue; + } + + ASSERT(bufcount + 1 < BUFFER_SIZE); + + buffy[bufcount] = env.map[ count_x + you.x_pos - 17 ] + [ count_y + you.y_pos - 9 ]; + + buffy[bufcount + 1] = DARKGREY; + if (Options.colour_map) + { + if (env.map[ count_x + you.x_pos - 16 ] + [ count_y + you.y_pos - 8 ] != 0) + { + buffy[bufcount + 1] + = colour_code_map( count_x + you.x_pos - 17, + count_y + you.y_pos - 9 ); + } + } + bufcount += 2; + } + } + + if (you.berserker) + { + for (count_x = 1; count_x < 1400; count_x += 2) + { + if (buffy[count_x] != DARKGREY) + buffy[count_x] = RED; + } + } + + if (show_green != BLACK) + { + for (count_x = 1; count_x < 1400; count_x += 2) + { + if (buffy[count_x] != DARKGREY) + buffy[count_x] = show_green; + } + + show_green = BLACK; + + if (you.special_wield == SPWLD_SHADOW) + show_green = DARKGREY; + } + +#ifdef DOS_TERM + puttext(2, 1, 34, 17, buffy.buffer()); +#endif + +#ifdef PLAIN_TERM + gotoxy(2, 1); + bufcount = 0; + + // following lines are purely optional. + // if used, players will 'jump' move. + // Resting will be a LOT faster too. + if (you.running == 0) + { + for (count_x = 0; count_x < 1120; count_x += 2) + { // 1056 + ch = buffy[count_x]; + color = buffy[count_x + 1]; +// ASSERT(color < 16); + ASSERT(ch < 255); + + textcolor(color); + putch(ch); + + if (count_x % 66 == 64 && count_x > 0) + gotoxy(2, wherey() + 1); + } + // remember to comment out the line below if you comment out jump move. + } + _setcursortype(_NORMALCURSOR); +#endif + } +} // end viewwindow2() + +char colour_code_map( int x, int y ) +{ + // XXX: Yes, the map array and the grid array are off by one. -- bwr + const int map_value = env.map[x][y]; + const int grid_value = grd[x + 1][y + 1]; + + // XXX: Yeah, this is ugly, but until we have stored layers in the + // map we can't tell if we've seen a square, detected it, or just + // detected the item or monster on top... giving colour here will + // result in detect creature/item detecting features like stairs. -- bwr + if (map_value != mapch2( grid_value )) + return (DARKGREY); + + switch (grid_value) + { + case DNGN_TRAP_MECHANICAL: + return (LIGHTCYAN); + + case DNGN_TRAP_MAGICAL: + case DNGN_TRAP_III: + return (MAGENTA); + + case DNGN_ENTER_SHOP: + return (YELLOW); + + case DNGN_ENTER_DIS: + return (CYAN); + + case DNGN_ENTER_HELL: + case DNGN_ENTER_GEHENNA: + return (RED); + + case DNGN_ENTER_COCYTUS: + return (LIGHTCYAN); + + case DNGN_ENTER_ABYSS: + return random2(16); // so it can be black - is this right? {dlb} + + case DNGN_ENTER_LABYRINTH: + case DNGN_STONE_ARCH: + return (LIGHTGREY); + + case DNGN_ENTER_PANDEMONIUM: + return (LIGHTBLUE); + + case DNGN_EXIT_PANDEMONIUM: + // Exit pandemonium gates won't show up on the map as light blue + // unless the character has the "gate to pandemonium" demonspawn + // mutation. This is so that the player can't quickly use a + // crystal ball to find their way out. -- bwr + return (you.mutation[MUT_PANDEMONIUM] ? LIGHTBLUE : LIGHTGREEN); + + case DNGN_TRANSIT_PANDEMONIUM: + return (LIGHTGREEN); + + case DNGN_ENTER_ZOT: + case DNGN_RETURN_FROM_ZOT: + return (MAGENTA); + + case DNGN_STONE_STAIRS_DOWN_I: + case DNGN_STONE_STAIRS_DOWN_II: + case DNGN_STONE_STAIRS_DOWN_III: + case DNGN_ROCK_STAIRS_DOWN: + return (RED); + + case DNGN_STONE_STAIRS_UP_I: + case DNGN_STONE_STAIRS_UP_II: + case DNGN_STONE_STAIRS_UP_III: + case DNGN_ROCK_STAIRS_UP: + return (BLUE); + + case DNGN_ENTER_ORCISH_MINES: + case DNGN_ENTER_HIVE: + case DNGN_ENTER_LAIR: + case DNGN_ENTER_SLIME_PITS: + case DNGN_ENTER_VAULTS: + case DNGN_ENTER_CRYPT: + case DNGN_ENTER_HALL_OF_BLADES: + case DNGN_ENTER_TEMPLE: + case DNGN_ENTER_SNAKE_PIT: + case DNGN_ENTER_ELVEN_HALLS: + case DNGN_ENTER_TOMB: + case DNGN_ENTER_SWAMP: + case 123: + case 124: + case 125: + case 126: + return (LIGHTRED); + + case DNGN_RETURN_FROM_ORCISH_MINES: + case DNGN_RETURN_FROM_HIVE: + case DNGN_RETURN_FROM_LAIR: + case DNGN_RETURN_FROM_SLIME_PITS: + case DNGN_RETURN_FROM_VAULTS: + case DNGN_RETURN_FROM_CRYPT: + case DNGN_RETURN_FROM_HALL_OF_BLADES: + case DNGN_RETURN_FROM_TEMPLE: + case DNGN_RETURN_FROM_SNAKE_PIT: + case DNGN_RETURN_FROM_ELVEN_HALLS: + case DNGN_RETURN_FROM_TOMB: + case DNGN_RETURN_FROM_SWAMP: + case 143: + case 144: + case 145: + case 146: + return (LIGHTBLUE); + + default: + break; + } + + return (DARKGREY); +} + + +void monster_grid(bool do_updates) +{ + struct monsters *monster = 0; // NULL {dlb} + + for (int s = 0; s < MAX_MONSTERS; s++) + { + monster = &menv[s]; + + if (monster->type != -1 && mons_near(monster)) + { + if (do_updates + && (monster->behaviour == BEH_SLEEP + || monster->behaviour == BEH_WANDER) + && check_awaken(s)) + { + behaviour_event( monster, ME_ALERT, MHITYOU ); + + if (you.turn_is_over == 1 + && mons_shouts(monster->type) > 0 + && random2(30) >= you.skills[SK_STEALTH]) + { + int noise_level = 8; + + if (!mons_friendly(monster) + && (!silenced(you.x_pos, you.y_pos) + && !silenced(monster->x, monster->y))) + { + if (mons_is_demon( monster->type ) && coinflip()) + { + if (monster->type == MONS_IMP + || monster->type == MONS_WHITE_IMP + || monster->type == MONS_SHADOW_IMP) + { + imp_taunt( monster ); + } + else + { + demon_taunt( monster ); + } + } + else + { + int the_shout = mons_shouts(monster->type); + + strcpy(info, "You hear "); + switch (the_shout) + { + case S_SILENT: + default: + strcat(info, "buggy behaviour!"); + break; + case S_SHOUT: + strcat(info, "a shout!"); + break; + case S_BARK: + strcat(info, "a bark!"); + break; + case S_SHOUT2: + strcat(info, "two shouts!"); + noise_level = 12; + break; + case S_ROAR: + strcat(info, "a roar!"); + noise_level = 12; + break; + case S_SCREAM: + strcat(info, "a hideous shriek!"); + break; + case S_BELLOW: + strcat(info, "a bellow!"); + break; + case S_SCREECH: + strcat(info, "a screech!"); + break; + case S_BUZZ: + strcat(info, "an angry buzzing noise."); + break; + case S_MOAN: + strcat(info, "a chilling moan."); + break; + case S_WHINE: + strcat(info, + "an irritating high-pitched whine."); + break; + case S_CROAK: + if (coinflip()) + strcat(info, "a loud, deep croak!"); + else + strcat(info, "a croak."); + break; + case S_GROWL: + strcat(info, "an angry growl!"); + break; + case S_HISS: + strcat(info, "an angry hiss!"); + noise_level = 4; // not very loud -- bwr + break; + } + + mpr(info); + } + } + + noisy( noise_level, monster->x, monster->y ); + } + } + + if (!player_monster_visible( monster )) + { + // ripple effect? + if (grd[monster->x][monster->y] == DNGN_SHALLOW_WATER + && !mons_flies(monster)) + { + show_backup[ monster->x - you.x_pos + 9 ] + [ monster->y - you.y_pos + 9] + = env.show[ monster->x - you.x_pos + 9 ] + [ monster->y - you.y_pos + 9 ]; + env.show[monster->x - you.x_pos + 9] + [monster->y - you.y_pos + 9] = 257; + } + continue; + } + else if (!mons_friendly( monster ) + && !mons_is_mimic( monster->type ) + && !mons_flag( monster->type, M_NO_EXP_GAIN ) + && you.running > 0) + { + // Friendly monsters, mimics, or harmless monsters + // don't disturb the player's running/resting. + // + // Doing it this way causes players in run mode 2 + // to move one square, and in mode 1 to stop. This + // means that the character will run one square if + // a monster is in sight... we automatically jump + // to zero if we're resting. -- bwr + if (you.run_x == 0 && you.run_y == 0) + you.running = 0; + else + you.running--; + } + + // mimics are always left on map + if (!mons_is_mimic( monster->type )) + { + show_backup[monster->x - you.x_pos + 9] + [monster->y - you.y_pos + 9] + = env.show[monster->x - you.x_pos + 9] + [monster->y - you.y_pos + 9]; + } + + env.show[monster->x - you.x_pos + 9] + [monster->y - you.y_pos + 9] = monster->type + 297; + + env.show_col[monster->x - you.x_pos + 9] + [monster->y - you.y_pos + 9] + = ((mcolour[monster->type] == BLACK) + ? monster->number : mcolour[monster->type]); +#ifdef USE_COLOUR_OPTS + if (mons_friendly(monster)) + { + env.show_col[monster->x - you.x_pos + 9] + [monster->y - you.y_pos + 9] + |= COLFLAG_FRIENDLY_MONSTER; + } +#endif + } // end "if (monster->type != -1 && mons_ner)" + } // end "for s" +} // end monster_grid() + + +bool check_awaken(int mons_aw) +{ + int mons_perc = 0; + struct monsters *monster = &menv[mons_aw]; + const int mon_holy = mons_holiness( monster->type ); + + // berserkers aren't really concerned about stealth + if (you.berserker) + return (true); + + // Repel undead is a holy aura, to which evil creatures are sensitive. + // Note that even though demons aren't affected by repel undead, they + // do sense this type of divine aura. -- bwr + if (you.duration[DUR_REPEL_UNDEAD] + && (mon_holy == MH_UNDEAD || mon_holy == MH_DEMONIC)) + { + return (true); + } + + // I assume that creatures who can see invisible are very perceptive + mons_perc = 10 + (mons_intel(monster->type) * 4) + monster->hit_dice + + mons_see_invis(monster) * 5; + + // critters that are wandering still have MHITYOU as their foe are + // still actively on guard for the player, even if they can't see + // him. Give them a large bonus (handle_behaviour() will nuke 'foe' + // after a while, removing this bonus. + if (monster->behaviour == BEH_WANDER && monster->foe == MHITYOU) + mons_perc += 15; + + if (!mons_player_visible(monster)) + mons_perc -= 75; + + if (monster->behaviour == BEH_SLEEP) + { + if (mon_holy == MH_NATURAL) + { + // monster is "hibernating"... reduce chance of waking + if (mons_has_ench( monster, ENCH_SLEEP_WARY )) + mons_perc -= 10; + } + else // unnatural creature + { + // Unnatural monsters don't actually "sleep", they just + // haven't noticed an intruder yet... we'll assume that + // they're diligently on guard. + mons_perc += 10; + } + } + + // glowing with magical contamination isn't very stealthy + if (you.magic_contamination > 10) + mons_perc += you.magic_contamination - 10; + + if (mons_perc < 0) + mons_perc = 0; + + return (random2(stealth) <= mons_perc); +} // end check_awaken() + + +void item() +{ + char count_x, count_y; + + for (count_y = (you.y_pos - 8); (count_y < you.y_pos + 9); count_y++) + { + for (count_x = (you.x_pos - 8); (count_x < you.x_pos + 9); count_x++) + { + if (count_x >= 0 && count_x < GXM && count_y >= 0 && count_y < GYM) + { + if (igrd[count_x][count_y] != NON_ITEM) + { + if (env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] != 0) + { + if (grd[count_x][count_y] == DNGN_SHALLOW_WATER) + { + env.show_col[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = CYAN; + } + else + { + env.show_col[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] + = mitm[igrd[count_x][count_y]].colour; + } + + switch (mitm[igrd[count_x][count_y]].base_type) + { + case OBJ_ORBS: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 256; + break; + // need + 6 because show is 0 - 12, not -6 - +6 + case OBJ_WEAPONS: + case OBJ_MISSILES: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 258; + break; + case OBJ_ARMOUR: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 259; + break; + case OBJ_WANDS: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 260; + break; + case OBJ_FOOD: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 261; + break; + case OBJ_UNKNOWN_I: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 262; + break; + case OBJ_SCROLLS: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 263; + break; + + case OBJ_JEWELLERY: + if (mitm[igrd[count_x][count_y]].sub_type >= AMU_RAGE) + { + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 273; + } + else + { + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 264; + } + break; + + case OBJ_POTIONS: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 265; + break; + case OBJ_UNKNOWN_II: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 266; + break; + case OBJ_BOOKS: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 267; + break; + case OBJ_STAVES: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 269; + break; + case OBJ_MISCELLANY: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 270; + break; + case OBJ_CORPSES: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 271; + break; + + case OBJ_GOLD: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = 272; + + env.show_col[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = YELLOW; + break; + + default: + env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9] = '8'; + break; + } + } + } + } + } // end of "for count_y, count_x" + } +} // end item() + + +void cloud_grid(void) +{ + int mnc = 0; + + // btw, this is also the 'default' color {dlb} + unsigned char which_color = LIGHTGREY; + + for (int s = 0; s < MAX_CLOUDS; s++) + { + // can anyone explain this??? {dlb} + // its an optimization to avoid looking past the last cloud -bwr + if (mnc > env.cloud_no) + break; + + if (env.cloud[s].type != CLOUD_NONE) + { + mnc++; + + if (see_grid(env.cloud[s].x, env.cloud[s].y)) + { + show_backup[env.cloud[s].x - you.x_pos + 9] + [env.cloud[s].y - you.y_pos + 9] + = env.show[env.cloud[s].x - you.x_pos + 9] + [env.cloud[s].y - you.y_pos + 9]; + + env.show[env.cloud[s].x - you.x_pos + 9] + [env.cloud[s].y - you.y_pos + 9] = '#'; + + switch (env.cloud[s].type) + { + case CLOUD_FIRE: + case CLOUD_FIRE_MON: + if (env.cloud[s].decay <= 20) + which_color = RED; + else if (env.cloud[s].decay <= 40) + which_color = LIGHTRED; + else if (one_chance_in(4)) + which_color = RED; + else if (one_chance_in(4)) + which_color = LIGHTRED; + else + which_color = YELLOW; + break; + + case CLOUD_STINK: + case CLOUD_STINK_MON: + which_color = GREEN; + break; + + case CLOUD_COLD: + case CLOUD_COLD_MON: + if (env.cloud[s].decay <= 20) + which_color = BLUE; + else if (env.cloud[s].decay <= 40) + which_color = LIGHTBLUE; + else if (one_chance_in(4)) + which_color = BLUE; + else if (one_chance_in(4)) + which_color = LIGHTBLUE; + else + which_color = WHITE; + break; + + case CLOUD_POISON: + case CLOUD_POISON_MON: + which_color = (one_chance_in(3) ? LIGHTGREEN : GREEN); + break; + + case CLOUD_BLUE_SMOKE: + case CLOUD_BLUE_SMOKE_MON: + which_color = LIGHTBLUE; + break; + + case CLOUD_PURP_SMOKE: + case CLOUD_PURP_SMOKE_MON: + which_color = MAGENTA; + break; + + case CLOUD_MIASMA: + case CLOUD_MIASMA_MON: + case CLOUD_BLACK_SMOKE: + case CLOUD_BLACK_SMOKE_MON: + which_color = DARKGREY; + break; + + default: + which_color = LIGHTGREY; + break; + } + + env.show_col[env.cloud[s].x - you.x_pos + 9] + [env.cloud[s].y - you.y_pos + 9] = which_color; + } + } // end 'if != CLOUD_NONE' + } // end 'for s' loop +} // end cloud_grid() + + +void noisy( int loudness, int nois_x, int nois_y ) +{ + int p; + struct monsters *monster = 0; // NULL {dlb} + + if (silenced( nois_x, nois_y )) + return; + + int dist = loudness * loudness; + + for (p = 0; p < MAX_MONSTERS; p++) + { + monster = &menv[p]; + + if (monster->type < 0) + continue; + + if (distance(monster->x, monster->y, nois_x, nois_y) <= dist + && !silenced(monster->x, monster->y)) + { + // If the noise came from the character, any nearby monster + // will be jumping on top of them. + if (nois_x == you.x_pos && nois_y == you.y_pos) + behaviour_event( monster, ME_ALERT, MHITYOU ); + else + behaviour_event( monster, ME_DISTURB, MHITNOT, nois_x, nois_y ); + } + } +} // end noisy() + +/* ======================================================================== + * brand new LOS code + * ======================================================================== + * The new LOS works via a new (I think) shadow casting algorithm, + * plus an esthetic tweak for more pleasing corner illumination. More + * detail can be had by contacting its author, Gordon Lipford. */ + +#define MAX_LIGHT_RADIUS 20 +#define CIRC_MAX 32000 +#define BIG_SHADOW 32000 + +// the following two constants represent the 'middle' of the sh array. +// since the current shown area is 19x19, centering the view at (9,9) +// means it will be exactly centered. +// This is done to accomodate possible future changes in viewable screen +// area - simply change sh_xo and sh_yo to the new view center. + +const int sh_xo = 9; // X and Y origins for the sh array +const int sh_yo = 9; + +// the Cell class, used in the shadow-casting LOS algorithm +class Cell +{ + +public: + int up_count; + int up_max; + int low_count; + int low_max; + bool lit; + bool lit_delay; + bool visible; // for blockers only + void init(); + bool reachedLower(); + bool reachedUpper(); + + Cell() + { + init(); + }; +}; + +void Cell::init() +{ + up_count = 0; + up_max = 0; + low_count = 0; + low_max = 0; + lit = true; + visible = true; + lit_delay = false; +} + +bool Cell::reachedLower() +{ + // integer math: a 'step' has a value of 10 + // see if we're within a half step of the max. VERY important + // to use 'half step' or else things look really stupid. + if (low_max != 0 && low_count + 5 >= low_max && low_count - 5 < low_max) + return true; + + return false; +} + +bool Cell::reachedUpper() +{ + // see if we're within a half step of the max. VERY important + // to use 'half step' or else things look really stupid. + if (up_max != 0 && up_count + 5 >= up_max && up_count - 5 < up_max) + return true; + + return false; +} + +// the cell array +static FixedVector < Cell, MAX_LIGHT_RADIUS + 1 > cells; + +// the 'circle' array. For any given row, we won't check higher than +// this given cell. +static FixedVector < int, MAX_LIGHT_RADIUS + 1 > circle; + +// current light radius +static int LR = 0; + +// View constant +const int view = 2; // 1=widest LOS .. 5=narrowest + +// initialize LOS code for a given light radius +extern void setLOSRadius(int newLR) +{ + int i, j; + + // sanity check - also allows multiple calls w/out performance loss + if (LR == newLR) + return; + + LR = newLR; + // cells should already be initted. calculate the circle array. + + // note that rows 0 and 1 will always go to infinity. + circle[0] = circle[1] = CIRC_MAX; + + // for the rest, simply calculate max height based on light rad. + for (i = 2; i <= LR; i++) + { + // check top + if (2 * i * i <= LR * LR) + { + circle[i] = CIRC_MAX; + continue; + } + + for (j = i - 1; j >= 0; j--) + { + // check that Distance (I^2 + J^2) is no more than (R+0.5)^2 + // this rounding allows for *much* better looking circles. + if (i * i + j * j <= LR * LR + LR) + { + circle[i] = j; + break; + } + } + } +} + +static int calcUpper(int bX, int bY) +{ + // got a blocker at row bX, cell bY. do all values + // and scale by a factor of 10 for the integer math. + int upper; + + upper = (10 * (10 * bX - view)) / (10 * bY + view); + if (upper < 10) // upper bound for blocker on diagonal + upper = 10; + + return upper; +} + +static int calcLower(int bX, int bY) +{ + // got a blocker at row bX, cell bY. do all values + // and scale by a factor of 10 for the integer math. + + if (bY == 0) + return BIG_SHADOW; + + return (10 * (10 * bX + view)) / (10 * bY - view); +} + +// for easy x,y octant translation +static int xxcomp[8] = { 1, 0, 0, -1, -1, 0, 0, 1 }; +static int xycomp[8] = { 0, 1, -1, 0, 0, -1, 1, 0 }; +static int yxcomp[8] = { 0, 1, 1, 0, 0, -1, -1, 0 }; +static int yycomp[8] = { 1, 0, 0, 1, -1, 0, 0, -1 }; + +static void los_octant(int o, FixedArray < unsigned int, 19, 19 > &sh, + FixedArray < unsigned char, 80, 70 > &gr, int x_p, + int y_p) +{ + int row, cell, top, south; + int tx, ty; // translated x, y deltas for this octant + unsigned char gv; // grid value + bool row_dark, all_dark; + bool blocker, vis_corner; + int up_inc, low_inc; + + // leave [0,0] alone, because the old LOS code seems to. + + // init cell[0]. this is the only one that needs clearing. + cells[0].init(); + all_dark = false; + vis_corner = false; + + // loop through each row + for (row = 1; row <= LR; row++) + { + row_dark = true; + + // loop through each cell, up to the max allowed by circle[] + top = circle[row]; + if (top > row) + top = row; + + for (cell = 0; cell <= top; cell++) + { + // translate X,Y co'ord + bounds check + tx = row * xxcomp[o] + cell * xycomp[o]; + ty = row * yxcomp[o] + cell * yycomp[o]; + + if (x_p + tx < 0 || x_p + tx > 79 || y_p + ty < 0 || y_p + ty > 69) + continue; + + // check for all_dark - we've finished the octant but + // have yet to fill in '0' for the rest of the sight grid + if (all_dark == true) + { + sh[sh_xo + tx][sh_yo + ty] = 0; + continue; + } + + // get grid value.. see if it blocks LOS + gv = gr[x_p + tx][y_p + ty]; + blocker = (gv < MINSEE); + + // init some other variables + up_inc = 10; + low_inc = 10; + south = cell - 1; + + // STEP 1 - inherit values from immediate West, if possible + if (cell < row) + { + // check for delayed lighting + if (cells[cell].lit_delay) + { + if (!blocker) + { // blockers don't light up with lit_delay. + if (cells[south].lit) + { + if (cells[south].low_max != 0) + { + cells[cell].lit = false; + // steal lower values + cells[cell].low_max = cells[south].low_max; + cells[cell].low_count = cells[south].low_count; + cells[south].low_count = 0; + cells[south].low_max = 0; + low_inc = 0; // avoid double-inc. + } + else + cells[cell].lit = true; + } + } + cells[cell].lit_delay = false; + } + } + else + { + // initialize new cell. + cells[cell].init(); + } + + // STEP 2 - check for blocker + // a dark blocker in shadow's edge will be visible + if (blocker) + { + if (cells[cell].lit || (cell != 0 && cells[south].lit) + || vis_corner) + { + // hack: make 'corners' visible + vis_corner = cells[cell].lit; + + cells[cell].lit = false; + cells[cell].visible = true; + + int upper = calcUpper(row, cell); + int lower = calcLower(row, cell); + + if (upper < cells[cell].up_max || cells[cell].up_max == 0) + { + // new upper shadow + cells[cell].up_max = upper; + cells[cell].up_count = 0; + up_inc = 0; + } + + if (lower > cells[cell].low_max || cells[cell].low_max == 0) + { + // new lower shadow + cells[cell].low_max = lower; + cells[cell].low_count = -10; + low_inc = 0; + if (lower <= 30) // somewhat arbitrary + cells[cell].lit_delay = true; + // set dark_delay if lower > 20?? how to decide? + } + } + else + { + cells[cell].visible = false; + } + } + else + { + cells[cell].visible = false; // special flags for blockers + } + + // STEP 3 - add increments to upper, lower counts + cells[cell].up_count += up_inc; + cells[cell].low_count += low_inc; + + // STEP 4 - check south for dark + if (south >= 0) + if (cells[south].reachedUpper() == true) + { + if (cells[cell].reachedUpper() == false) + { + cells[cell].up_max = cells[south].up_max; + cells[cell].up_count = cells[south].up_count; + cells[cell].up_count -= cells[south].up_max; + } + cells[cell].lit = false; + cells[cell].visible = false; + } + + // STEP 5 - nuke lower if south lower + if (south >= 0) + { + if (cells[south].reachedLower()) + { + cells[cell].low_max = cells[south].low_max; + cells[cell].low_count = cells[south].low_count; + cells[cell].low_count -= cells[south].low_max; + cells[south].low_count = cells[south].low_max = 0; + } + + if (cells[south].low_max != 0 + || (cells[south].lit == false + && cells[south].low_max == 0)) + { + cells[cell].low_count = cells[cell].low_max + 10; + } + } + + // STEP 6 - light up if we've reached lower bound + if (cells[cell].reachedLower() == true) + cells[cell].lit = true; + + // now place appropriate value in sh + if (cells[cell].lit == true + || (blocker == true && cells[cell].visible == true)) + { + sh[sh_xo + tx][sh_yo + ty] = gv; + } + else + sh[sh_xo + tx][sh_yo + ty] = 0; + + if (cells[cell].lit == true) + row_dark = false; + } // end for - cells + + vis_corner = false; // don't carry over to next row. :) + if (row_dark == true) + all_dark = true; + } // end for - rows +} + +void losight(FixedArray < unsigned int, 19, 19 > &sh, + FixedArray < unsigned char, 80, 70 > &gr, int x_p, int y_p) +{ + int o; + + for (o = 0; o < 8; o++) + los_octant(o, sh, gr, x_p, y_p); +} + + +void draw_border(void) +{ + textcolor( BORDER_COLOR ); + clrscr(); + redraw_skill( you.your_name, player_title() ); + + gotoxy(40, 2); + cprintf( "%s %s", species_name( you.species, you.experience_level ), + (you.wizard ? "*WIZARD*" : "" ) ); + + gotoxy(40, 3); cprintf("HP:"); + gotoxy(40, 4); cprintf("Magic:"); + gotoxy(40, 5); cprintf("AC:"); + gotoxy(40, 6); cprintf("EV:"); + gotoxy(40, 7); cprintf("Str:"); + gotoxy(40, 8); cprintf("Int:"); + gotoxy(40, 9); cprintf("Dex:"); + gotoxy(40, 10); cprintf("Gold:"); + gotoxy(40, 11); cprintf("Experience:"); + gotoxy(40, 12); cprintf("Level"); +} // end draw_border() + +// show_map() now centers the known map along x or y. This prevents +// the player from getting "artificial" location clues by using the +// map to see how close to the end they are. They'll need to explore +// to get that. This function is still a mess, though. -- bwr +void show_map( FixedVector &spec_place ) +{ + int i, j; + + int bufcount2 = 0; + + char move_x = 0; + char move_y = 0; + char getty = 0; + +#ifdef DOS_TERM + char buffer[4800]; +#endif + + // buffer2[GYM * GXM * 2] segfaults my box {dlb} + char buffer2[GYM * GXM * 2]; + + char min_x = 80, max_x = 0, min_y = 0, max_y = 0; + bool found_y = false; + + const int num_lines = get_number_of_lines(); + const int half_screen = num_lines / 2 - 1; + + for (j = 0; j < GYM; j++) + { + for (i = 0; i < GXM; i++) + { + if (env.map[i][j]) + { + if (!found_y) + { + found_y = true; + min_y = j; + } + + max_y = j; + + if (i < min_x) + min_x = i; + + if (i > max_x) + max_x = i; + } + } + } + + const int map_lines = max_y - min_y + 1; + + const int start_x = min_x + (max_x - min_x + 1) / 2 - 40; // no x scrolling + int start_y; // y does scroll + + int screen_y = you.y_pos; + + // if close to top of known map, put min_y on top + // else if close to bottom of known map, put max_y on bottom. + // + // The num_lines comparisons are done to keep things neat, by + // keeping things at the top of the screen. By shifting an + // additional one in the num_lines > map_lines case, we can + // keep the top line clear... which makes things look a whole + // lot better for small maps. + if (num_lines > map_lines) + screen_y = min_y + half_screen - 1; + else if (num_lines == map_lines || screen_y - half_screen < min_y) + screen_y = min_y + half_screen; + else if (screen_y + half_screen > max_y) + screen_y = max_y - half_screen; + + int curs_x = you.x_pos - start_x; + int curs_y = you.y_pos - screen_y + half_screen; + +#ifdef DOS_TERM + gettext(1, 1, 80, 25, buffer); + window(1, 1, 80, 25); +#endif + + clrscr(); + textcolor(DARKGREY); + + put_screen: + bufcount2 = 0; + + _setcursortype(_NOCURSOR); + +#ifdef PLAIN_TERM + gotoxy(1, 1); +#endif + + start_y = screen_y - half_screen; + + for (j = 0; j < num_lines; j++) + { + for (i = 0; i < 80; i++) + { + if (start_y + j >= 65 || start_y + j <= 3 + || start_x + i < 0 || start_x + i >= GXM - 1) + { + buffer2[bufcount2 + 1] = DARKGREY; + buffer2[bufcount2] = 0; + bufcount2 += 2; + +#ifdef PLAIN_TERM + goto print_it; +#endif + +#ifdef DOS_TERM + continue; +#endif + + } + + buffer2[bufcount2 + 1] = colour_code_map(start_x + i, start_y + j); + + if (start_x + i + 1 == you.x_pos && start_y + j + 1 == you.y_pos) + buffer2[bufcount2 + 1] = WHITE; + + buffer2[bufcount2] = env.map[start_x + i][start_y + j]; + bufcount2 += 2; + +#ifdef PLAIN_TERM + + print_it: + // avoid line wrap + if (i == 79) + continue; + + // newline + if (i == 0 && j > 0) + gotoxy( 1, j + 1 ); + + textcolor( buffer2[bufcount2 - 1] ); + putch( buffer2[bufcount2 - 2] ); +#endif + } + } + +#ifdef DOS_TERM + puttext(1, 1, 80, 25, buffer2); +#endif + + _setcursortype(_NORMALCURSOR); + gotoxy(curs_x, curs_y); + + gettything: + getty = getch(); + + if (spec_place[0] == 0 && getty != 0 && getty != '+' && getty != '-' + && getty != 'h' && getty != 'j' && getty != 'k' && getty != 'l' + && getty != 'y' && getty != 'u' && getty != 'b' && getty != 'n' +#ifdef LINUX + && getty != 'H' && getty != 'J' && getty != 'K' && getty != 'L' + && getty != 'Y' && getty != 'U' && getty != 'B' && getty != 'N' +#endif + && (getty < '0' || getty > '9')) + { + goto putty; + } + + if (spec_place[0] == 1 && getty != 0 && getty != '+' && getty != '-' + && getty != 'h' && getty != 'j' && getty != 'k' && getty != 'l' + && getty != 'y' && getty != 'u' && getty != 'b' && getty != 'n' +#ifdef LINUX + && getty != 'H' && getty != 'J' && getty != 'K' && getty != 'L' + && getty != 'Y' && getty != 'U' && getty != 'B' && getty != 'N' +#endif + && getty != '.' && getty != 'S' && (getty < '0' || getty > '9')) + { + goto gettything; + } + + if (getty == 0) + getty = getch(); + + switch (getty) + { + case 'b': + case '1': + move_x = -1; + move_y = 1; + break; + + case 'j': + case '2': + move_y = 1; + move_x = 0; + break; + + case 'u': + case '9': + move_x = 1; + move_y = -1; + break; + + case 'k': + case '8': + move_y = -1; + move_x = 0; + break; + + case 'y': + case '7': + move_y = -1; + move_x = -1; + break; + + case 'h': + case '4': + move_x = -1; + move_y = 0; + break; + + case 'n': + case '3': + move_y = 1; + move_x = 1; + break; + + case 'l': + case '6': + move_x = 1; + move_y = 0; + break; + +#ifndef LINUX + // This is old DOS keypad support + case 'H': + move_y = -1; + move_x = 0; + break; + case 'P': + move_y = 1; + move_x = 0; + break; + case 'K': + move_x = -1; + move_y = 0; + break; + case 'M': + move_x = 1; + move_y = 0; + break; + case 'O': + move_x = -1; + move_y = 1; + break; + case 'I': + move_x = 1; + move_y = -1; + break; + case 'G': + move_y = -1; + move_x = -1; + break; + case 'Q': + move_y = 1; + move_x = 1; + break; + +#else + + case 'B': + move_x = -10; + move_y = 10; + break; + + case 'J': + move_y = 10; + move_x = 0; + break; + + case 'U': + move_x = 10; + move_y = -10; + break; + + case 'K': + move_y = -10; + move_x = 0; + break; + + case 'Y': + move_y = -10; + move_x = -10; + break; + + case 'H': + move_x = -10; + move_y = 0; + break; + + case 'N': + move_y = 10; + move_x = 10; + break; + + case 'L': + move_x = 10; + move_y = 0; + break; + +#endif + + case '+': + move_y = 20; + move_x = 0; + break; + case '-': + move_y = -20; + move_x = 0; + break; + case '.': + case '\r': + case 'S': + spec_place[0] = start_x + curs_x; + spec_place[1] = start_y + curs_y; + goto putty; + + default: + move_x = 0; + move_y = 0; + break; + } + + if (curs_x + move_x < 1 || curs_x + move_x > 80) + move_x = 0; + + curs_x += move_x; + + if (num_lines < map_lines) + { + // Scrolling only happens when we don't have a large enough + // display to show the known map. + if (getty == '-' || getty == '+') + { + if (getty == '-') + screen_y -= 20; + + if (screen_y <= min_y + half_screen) + screen_y = min_y + half_screen; + + if (getty == '+') + screen_y += 20; + + if (screen_y >= max_y - half_screen) + screen_y = max_y - half_screen; + + goto put_screen; + } + + if (curs_y + move_y < 1) + { + // screen_y += (curs_y + move_y) - 1; + screen_y += move_y; + + if (screen_y < min_y + half_screen) + screen_y = min_y + half_screen; + + move_y = 0; + } + + if (curs_y + move_y > num_lines - 1) + { + // screen_y += (curs_y + move_y) - num_lines + 1; + screen_y += move_y; + + if (screen_y > max_y - half_screen) + screen_y = max_y - half_screen; + + move_y = 0; + } + } + + if (curs_y + move_y < 1 || curs_y + move_y > num_lines) + move_y = 0; + + curs_y += move_y; + goto put_screen; + + putty: + +#ifdef DOS_TERM + puttext(1, 1, 80, 25, buffer); +#endif + + return; +} // end show_map() + + +void magic_mapping(int map_radius, int proportion) +{ + int i, j, k, l, empty_count; + + if (map_radius > 50) + map_radius = 50; + + for (i = you.x_pos - map_radius; i < you.x_pos + map_radius; i++) + { + for (j = you.y_pos - map_radius; j < you.y_pos + map_radius; j++) + { + if (random2(100) > proportion) + continue; // note that proportion can be over 100 + + if (i < 5 || j < 5 || i > (GXM - 5) || j > (GYM - 5)) + continue; + + if (env.map[i][j] == mapch2(grd[i + 1][j + 1])) + continue; + + empty_count = 8; + + if (grd[i][j] < DNGN_LAVA && grd[i][j] != DNGN_CLOSED_DOOR) + { + for (k = 0; k < 3; k++) + { + for (l = 0; l < 3; l++) + { + if (k == 1 && l == 1) + continue; + + if (grd[i + k][j + l] <= 60 + && grd[i + k][j + l] != DNGN_CLOSED_DOOR) + { + empty_count--; + } + } + } + } + + if (empty_count > 0) + env.map[i][j] = mapch(grd[i + 1][j + 1]); + } + } +} // end magic_mapping() + + +/* mapchars 3 & 4 are for non-ibm char sets */ +unsigned char mapchar(unsigned char ldfk) +{ + unsigned char showed = 0; + + switch (ldfk) + { + case DNGN_UNSEEN: + showed = 0; + break; + + case DNGN_SECRET_DOOR: + case DNGN_ROCK_WALL: + case DNGN_PERMAROCK_WALL: + case DNGN_STONE_WALL: + case DNGN_METAL_WALL: + case DNGN_GREEN_CRYSTAL_WALL: + case DNGN_WAX_WALL: + showed = 176; + break; + + case DNGN_CLOSED_DOOR: + showed = 206; + break; + + case 20: // orcish idol + case 24: // ??? + case 25: // ??? + case DNGN_SILVER_STATUE: + case DNGN_GRANITE_STATUE: + case DNGN_ORANGE_CRYSTAL_STATUE: + showed = '8'; + break; + + case DNGN_LAVA_X: + case DNGN_WATER_X: + case DNGN_LAVA: + case DNGN_DEEP_WATER: + case DNGN_SHALLOW_WATER: + showed = 247; + break; + + case DNGN_FLOOR: + case DNGN_UNDISCOVERED_TRAP: + showed = 250; + break; + + //case 68: showed = '>'; break; // < (60) + + case DNGN_OPEN_DOOR: + showed = 39; + break; + + //case 72: showed = '<'; break; + + case DNGN_TRAP_MECHANICAL: + case DNGN_TRAP_MAGICAL: + case DNGN_TRAP_III: + showed = '^'; + break; + + case DNGN_STONE_STAIRS_DOWN_I: + case DNGN_STONE_STAIRS_DOWN_II: + case DNGN_STONE_STAIRS_DOWN_III: + case DNGN_ROCK_STAIRS_DOWN: + case DNGN_ENTER_ORCISH_MINES: + case DNGN_ENTER_HIVE: + case DNGN_ENTER_LAIR: + case DNGN_ENTER_SLIME_PITS: + case DNGN_ENTER_VAULTS: + case DNGN_ENTER_CRYPT: + case DNGN_ENTER_HALL_OF_BLADES: + case DNGN_ENTER_TEMPLE: + case DNGN_ENTER_SNAKE_PIT: + case DNGN_ENTER_ELVEN_HALLS: + case DNGN_ENTER_TOMB: + case DNGN_ENTER_SWAMP: + case 123: + case 124: + case 125: + case 126: + showed = '>'; + break; + + case DNGN_STONE_STAIRS_UP_I: + case DNGN_STONE_STAIRS_UP_II: + case DNGN_STONE_STAIRS_UP_III: + case DNGN_ROCK_STAIRS_UP: + case DNGN_RETURN_FROM_ORCISH_MINES: + case DNGN_RETURN_FROM_HIVE: + case DNGN_RETURN_FROM_LAIR: + case DNGN_RETURN_FROM_SLIME_PITS: + case DNGN_RETURN_FROM_VAULTS: + case DNGN_RETURN_FROM_CRYPT: + case DNGN_RETURN_FROM_HALL_OF_BLADES: + case DNGN_RETURN_FROM_TEMPLE: + case DNGN_RETURN_FROM_SNAKE_PIT: + case DNGN_RETURN_FROM_ELVEN_HALLS: + case DNGN_RETURN_FROM_TOMB: + case DNGN_RETURN_FROM_SWAMP: + case 143: + case 144: + case 145: + case 146: + showed = '<'; + break; + + case DNGN_ENTER_HELL: + case DNGN_ENTER_LABYRINTH: + case DNGN_ENTER_SHOP: + case DNGN_ENTER_DIS: + case DNGN_ENTER_GEHENNA: + case DNGN_ENTER_COCYTUS: + case DNGN_ENTER_TARTARUS: + case DNGN_ENTER_ABYSS: + case DNGN_EXIT_ABYSS: + case DNGN_STONE_ARCH: + case DNGN_ENTER_PANDEMONIUM: + case DNGN_EXIT_PANDEMONIUM: + case DNGN_TRANSIT_PANDEMONIUM: + case DNGN_ENTER_ZOT: + case DNGN_RETURN_FROM_ZOT: + showed = 239; + break; + + case DNGN_ALTAR_ZIN: + case DNGN_ALTAR_SHINING_ONE: + case DNGN_ALTAR_KIKUBAAQUDGHA: + case DNGN_ALTAR_YREDELEMNUL: + case DNGN_ALTAR_XOM: + case DNGN_ALTAR_VEHUMET: + case DNGN_ALTAR_OKAWARU: + case DNGN_ALTAR_MAKHLEB: + case DNGN_ALTAR_SIF_MUNA: + case DNGN_ALTAR_TROG: + case DNGN_ALTAR_NEMELEX_XOBEH: + case DNGN_ALTAR_ELYVILON: + showed = 220; + break; + + case DNGN_BLUE_FOUNTAIN: + case DNGN_DRY_FOUNTAIN_I: + case DNGN_SPARKLING_FOUNTAIN: + case DNGN_DRY_FOUNTAIN_II: + case DNGN_DRY_FOUNTAIN_III: + case DNGN_DRY_FOUNTAIN_IV: + case DNGN_DRY_FOUNTAIN_V: + case DNGN_DRY_FOUNTAIN_VI: + case DNGN_DRY_FOUNTAIN_VII: + case DNGN_DRY_FOUNTAIN_VIII: + case DNGN_PERMADRY_FOUNTAIN: + showed = 159; + break; + + default: + showed = 0; + break; + } + + return showed; +} + + +unsigned char mapchar2(unsigned char ldfk) +{ + unsigned char showed = 0; + + switch (ldfk) + { + case DNGN_UNSEEN: + showed = 0; + break; + + case DNGN_SECRET_DOOR: + case DNGN_ROCK_WALL: + case DNGN_PERMAROCK_WALL: + case DNGN_STONE_WALL: + case DNGN_METAL_WALL: + case DNGN_GREEN_CRYSTAL_WALL: + case DNGN_WAX_WALL: + showed = 177; + break; + + case DNGN_CLOSED_DOOR: + showed = 254; + break; + + //case DNGN_LAVA_X: showed = 247; break; // deprecated? {dlb} + //case DNGN_WATER_X: showed = 247; break; // deprecated? {dlb} + + case 20: // orcish idol + case 24: // ??? + case 25: // ??? + case DNGN_SILVER_STATUE: + case DNGN_GRANITE_STATUE: + case DNGN_ORANGE_CRYSTAL_STATUE: + showed = '8'; + break; + + case DNGN_LAVA: + case DNGN_DEEP_WATER: + case DNGN_SHALLOW_WATER: + showed = 247; + break; + + case DNGN_FLOOR: + case DNGN_UNDISCOVERED_TRAP: + showed = 249; + break; + + case 68: + showed = '>'; + break; // < + + case DNGN_OPEN_DOOR: + showed = 39; + break; + + case 72: + showed = '<'; + break; // < + + case DNGN_TRAP_MECHANICAL: + case DNGN_TRAP_MAGICAL: + case DNGN_TRAP_III: + showed = '^'; + break; + + case DNGN_STONE_STAIRS_DOWN_I: + case DNGN_STONE_STAIRS_DOWN_II: + case DNGN_STONE_STAIRS_DOWN_III: + case DNGN_ROCK_STAIRS_DOWN: + case DNGN_ENTER_ORCISH_MINES: + case DNGN_ENTER_HIVE: + case DNGN_ENTER_LAIR: + case DNGN_ENTER_SLIME_PITS: + case DNGN_ENTER_VAULTS: + case DNGN_ENTER_CRYPT: + case DNGN_ENTER_HALL_OF_BLADES: + case DNGN_ENTER_TEMPLE: + case DNGN_ENTER_SNAKE_PIT: + case DNGN_ENTER_ELVEN_HALLS: + case DNGN_ENTER_TOMB: + case DNGN_ENTER_SWAMP: + case 123: + case 124: + case 125: + case 126: + showed = '>'; + break; + + case DNGN_STONE_STAIRS_UP_I: + case DNGN_STONE_STAIRS_UP_II: + case DNGN_STONE_STAIRS_UP_III: + case DNGN_ROCK_STAIRS_UP: + case DNGN_RETURN_FROM_ORCISH_MINES: + case DNGN_RETURN_FROM_HIVE: + case DNGN_RETURN_FROM_LAIR: + case DNGN_RETURN_FROM_SLIME_PITS: + case DNGN_RETURN_FROM_VAULTS: + case DNGN_RETURN_FROM_CRYPT: + case DNGN_RETURN_FROM_HALL_OF_BLADES: + case DNGN_RETURN_FROM_TEMPLE: + case DNGN_RETURN_FROM_SNAKE_PIT: + case DNGN_RETURN_FROM_ELVEN_HALLS: + case DNGN_RETURN_FROM_TOMB: + case DNGN_RETURN_FROM_SWAMP: + case 143: + case 144: + case 145: + case 146: + showed = '<'; + break; + + case DNGN_ENTER_HELL: + case DNGN_ENTER_LABYRINTH: + case DNGN_ENTER_SHOP: + case DNGN_ENTER_DIS: + case DNGN_ENTER_GEHENNA: + case DNGN_ENTER_COCYTUS: + case DNGN_ENTER_TARTARUS: + case DNGN_ENTER_ABYSS: + case DNGN_EXIT_ABYSS: + case DNGN_STONE_ARCH: + case DNGN_ENTER_PANDEMONIUM: + case DNGN_EXIT_PANDEMONIUM: + case DNGN_TRANSIT_PANDEMONIUM: + case DNGN_ENTER_ZOT: + case DNGN_RETURN_FROM_ZOT: + showed = 239; + break; + + case DNGN_ALTAR_ZIN: + case DNGN_ALTAR_SHINING_ONE: + case DNGN_ALTAR_KIKUBAAQUDGHA: + case DNGN_ALTAR_YREDELEMNUL: + case DNGN_ALTAR_XOM: + case DNGN_ALTAR_VEHUMET: + case DNGN_ALTAR_OKAWARU: + case DNGN_ALTAR_MAKHLEB: + case DNGN_ALTAR_SIF_MUNA: + case DNGN_ALTAR_TROG: + case DNGN_ALTAR_NEMELEX_XOBEH: + case DNGN_ALTAR_ELYVILON: + showed = 220; + break; + + case DNGN_BLUE_FOUNTAIN: + case DNGN_DRY_FOUNTAIN_I: + case DNGN_SPARKLING_FOUNTAIN: + case DNGN_DRY_FOUNTAIN_II: + case DNGN_DRY_FOUNTAIN_III: + case DNGN_DRY_FOUNTAIN_IV: + case DNGN_DRY_FOUNTAIN_V: + case DNGN_DRY_FOUNTAIN_VI: + case DNGN_DRY_FOUNTAIN_VII: + case DNGN_DRY_FOUNTAIN_VIII: + case DNGN_PERMADRY_FOUNTAIN: + showed = 159; + break; + default: + showed = 0; + break; + } + + return showed; +} + + +// realize that this is simply a repackaged version of +// stuff::see_grid() -- make certain they correlate {dlb}: +bool mons_near(struct monsters *monster, unsigned int foe) +{ + // early out -- no foe! + if (foe == MHITNOT) + return (false); + + if (foe == MHITYOU) + { + if (monster->x > you.x_pos - 9 && monster->x < you.x_pos + 9 + && monster->y > you.y_pos - 9 && monster->y < you.y_pos + 9) + { + if (env.show[monster->x - you.x_pos + 9][monster->y - you.y_pos + 9]) + return (true); + } + return (false); + } + + // must be a monster + struct monsters *myFoe = &menv[foe]; + if (myFoe->type >= 0) + { + if (monster->x > myFoe->x - 9 && monster->x < myFoe->x + 9 + && monster->y > myFoe->y - 9 && monster->y < myFoe->y + 9) + { + return (true); + } + } + + return (false); +} // end mons_near() + + +//--------------------------------------------------------------- +// +// get_non_ibm_symbol +// +// Returns the character code and color for everything drawn +// without the IBM graphics option. +// +//--------------------------------------------------------------- +static void get_non_ibm_symbol(unsigned int object, unsigned short *ch, + unsigned short *color) +{ + ASSERT(color != NULL); + ASSERT(ch != NULL); + + switch (object) + { + + case DNGN_UNSEEN: + *ch = 0; + break; + + case DNGN_ROCK_WALL: + case DNGN_PERMAROCK_WALL: + *color = env.rock_colour; + *ch = '#'; + break; + + case DNGN_STONE_WALL: + if (player_in_branch( BRANCH_HALL_OF_ZOT )) + *color = env.rock_colour; + else + *color = LIGHTGREY; + *ch = '#'; + break; + + case DNGN_CLOSED_DOOR: + *ch = '+'; + break; + + case DNGN_METAL_WALL: + *ch = '#'; + *color = CYAN; + break; + + case DNGN_SECRET_DOOR: + *ch = '#'; + *color = env.rock_colour; + break; + + case DNGN_GREEN_CRYSTAL_WALL: + *ch = '#'; + *color = GREEN; + break; + + case DNGN_ORCISH_IDOL: + *ch = '8'; + *color = DARKGREY; + break; + + case DNGN_WAX_WALL: + *ch = '#'; + *color = YELLOW; + break; + + case DNGN_SILVER_STATUE: + *ch = '8'; + *color = WHITE; + Visible_Statue[ STATUE_SILVER ] = 1; + break; + + case DNGN_GRANITE_STATUE: + *ch = '8'; + *color = LIGHTGREY; + break; + + case DNGN_ORANGE_CRYSTAL_STATUE: + *ch = '8'; + *color = LIGHTRED; + Visible_Statue[ STATUE_ORANGE_CRYSTAL ] = 1; + break; + + case DNGN_LAVA: + *ch = '{'; + *color = RED; + break; + + case DNGN_DEEP_WATER: + *ch = '{'; + // this wavy thing also used for water elemental + // note that some monsters which use IBM graphics aren't set + // for this function - too tricky for now. + *color = BLUE; + break; + + case DNGN_SHALLOW_WATER: + *color = CYAN; + *ch = '{'; + break; + + case DNGN_FLOOR: + *color = env.floor_colour; + *ch = '.'; + break; + + case DNGN_ENTER_HELL: + *color = RED; + *ch = '\\'; + seen_other_thing(DNGN_ENTER_HELL); + break; + + case DNGN_OPEN_DOOR: + *ch = '\''; + break; + + case DNGN_BRANCH_STAIRS: + *color = BROWN; + *ch = '>'; + break; + + case DNGN_TRAP_MECHANICAL: + *color = 11; + *ch = '^'; + break; + + case DNGN_TRAP_MAGICAL: + *color = MAGENTA; + *ch = '^'; + break; + + case DNGN_TRAP_III: + *color = LIGHTGREY; + *ch = '^'; + break; + + case DNGN_UNDISCOVERED_TRAP: + *color = env.floor_colour; + *ch = '.'; + break; + + case DNGN_ENTER_SHOP: + *color = YELLOW; + *ch = '\\'; + seen_other_thing(DNGN_ENTER_SHOP); + break; +// if I change anything above here, must also change magic mapping! + + case DNGN_ENTER_LABYRINTH: + *color = LIGHTGREY; + *ch = '\\'; + seen_other_thing(DNGN_ENTER_LABYRINTH); + break; + + case DNGN_ROCK_STAIRS_DOWN: + *color = BROWN; // ladder + case DNGN_STONE_STAIRS_DOWN_I: + case DNGN_STONE_STAIRS_DOWN_II: + case DNGN_STONE_STAIRS_DOWN_III: + *ch = '>'; + break; + + case DNGN_ROCK_STAIRS_UP: + *color = BROWN; // ladder + case DNGN_STONE_STAIRS_UP_I: + case DNGN_STONE_STAIRS_UP_II: + case DNGN_STONE_STAIRS_UP_III: + *ch = '<'; + break; + + case DNGN_ENTER_DIS: + *color = CYAN; + *ch = '\\'; + break; + + case DNGN_ENTER_GEHENNA: + *color = RED; + *ch = '\\'; + break; + + case DNGN_ENTER_COCYTUS: + *color = LIGHTCYAN; + *ch = '\\'; + break; + + case DNGN_ENTER_TARTARUS: + *color = DARKGREY; + *ch = '\\'; + break; + + case DNGN_ENTER_ABYSS: + *color = random2(16); + *ch = '\\'; + seen_other_thing(DNGN_ENTER_ABYSS); + break; + + case DNGN_EXIT_ABYSS: + *color = random2(16); + *ch = '\\'; + break; + + case DNGN_STONE_ARCH: + *color = LIGHTGREY; + *ch = '\\'; + break; + + case DNGN_ENTER_PANDEMONIUM: + *color = LIGHTBLUE; + *ch = '\\'; + seen_other_thing(DNGN_ENTER_PANDEMONIUM); + break; + + case DNGN_EXIT_PANDEMONIUM: + *color = LIGHTBLUE; + *ch = '\\'; + break; + + case DNGN_TRANSIT_PANDEMONIUM: + *color = LIGHTGREEN; + *ch = '\\'; + break; // gate to other part of pandemonium + + case DNGN_ENTER_ORCISH_MINES: + case DNGN_ENTER_HIVE: + case DNGN_ENTER_LAIR: + case DNGN_ENTER_SLIME_PITS: + case DNGN_ENTER_VAULTS: + case DNGN_ENTER_CRYPT: + case DNGN_ENTER_HALL_OF_BLADES: + case DNGN_ENTER_TEMPLE: + case DNGN_ENTER_SNAKE_PIT: + case DNGN_ENTER_ELVEN_HALLS: + case DNGN_ENTER_TOMB: + case DNGN_ENTER_SWAMP: + case 123: + case 124: + case 125: + case 126: + *color = YELLOW; + *ch = '>'; + seen_staircase(object); + break; + + case DNGN_ENTER_ZOT: + *color = MAGENTA; + *ch = '\\'; + seen_staircase(object); + break; + + case DNGN_RETURN_FROM_ORCISH_MINES: + case DNGN_RETURN_FROM_HIVE: + case DNGN_RETURN_FROM_LAIR: + case DNGN_RETURN_FROM_SLIME_PITS: + case DNGN_RETURN_FROM_VAULTS: + case DNGN_RETURN_FROM_CRYPT: + case DNGN_RETURN_FROM_HALL_OF_BLADES: + case DNGN_RETURN_FROM_TEMPLE: + case DNGN_RETURN_FROM_SNAKE_PIT: + case DNGN_RETURN_FROM_ELVEN_HALLS: + case DNGN_RETURN_FROM_TOMB: + case DNGN_RETURN_FROM_SWAMP: + case 143: + case 144: + case 145: + case 146: + *color = YELLOW; + *ch = '<'; + break; + + case DNGN_RETURN_FROM_ZOT: + *color = MAGENTA; + *ch = '\\'; + break; + + case DNGN_ALTAR_ZIN: + *color = WHITE; + *ch = '_'; + seen_altar(GOD_ZIN); + break; + + case DNGN_ALTAR_SHINING_ONE: + *color = YELLOW; + *ch = '_'; + seen_altar(GOD_SHINING_ONE); + break; + + case DNGN_ALTAR_KIKUBAAQUDGHA: + *color = DARKGREY; + *ch = '_'; + seen_altar(GOD_KIKUBAAQUDGHA); + break; + + case DNGN_ALTAR_YREDELEMNUL: + *color = DARKGREY; + if (one_chance_in(3)) + *color = RED; + *ch = '_'; + seen_altar(GOD_YREDELEMNUL); + break; + + case DNGN_ALTAR_XOM: + *color = random_colour(); + *ch = '_'; + seen_altar(GOD_XOM); + break; + + case DNGN_ALTAR_VEHUMET: + *color = LIGHTBLUE; + if (one_chance_in(3)) + *color = LIGHTMAGENTA; + if (one_chance_in(3)) + *color = LIGHTRED; + *ch = '_'; + seen_altar(GOD_VEHUMET); + break; + + case DNGN_ALTAR_OKAWARU: + *color = CYAN; + *ch = '_'; + seen_altar(GOD_OKAWARU); + break; + + case DNGN_ALTAR_MAKHLEB: + *color = RED; + if (one_chance_in(3)) + *color = LIGHTRED; + if (one_chance_in(3)) + *color = YELLOW; + *ch = '_'; + seen_altar(GOD_MAKHLEB); + break; + + case DNGN_ALTAR_SIF_MUNA: + *color = BLUE; + *ch = '_'; + seen_altar(GOD_SIF_MUNA); + break; + + case DNGN_ALTAR_TROG: + *color = RED; + *ch = '_'; + seen_altar(GOD_TROG); + break; + + case DNGN_ALTAR_NEMELEX_XOBEH: + *color = LIGHTMAGENTA; + *ch = '_'; + seen_altar(GOD_NEMELEX_XOBEH); + break; + + case DNGN_ALTAR_ELYVILON: + *color = LIGHTGREY; + *ch = '_'; + seen_altar(GOD_ELYVILON); + break; + + case DNGN_BLUE_FOUNTAIN: + *color = BLUE; + *ch = '}'; + break; + + case DNGN_SPARKLING_FOUNTAIN: + *color = LIGHTBLUE; + *ch = '}'; + break; + + case DNGN_DRY_FOUNTAIN_I: + case DNGN_DRY_FOUNTAIN_II: + case DNGN_PERMADRY_FOUNTAIN: + *color = LIGHTGREY; + *ch = '}'; + break; + + case 256: + *ch = '0'; + break; + + case 257: + *color = CYAN; + *ch = '~'; + break; /* Invis creature walking through water */ + + case 258: + *ch = ')'; + break; // weapon ) + + case 259: + *ch = '['; + break; // armour [ + + case 260: + *ch = '/'; + break; // wands, etc. + + case 261: + *ch = '%'; + break; // food + + case 262: + *ch = '+'; + break; // books + + + case 263: + *ch = '?'; + break; // scroll ? + + case 264: + *ch = '='; + break; // ring = etc + + case 265: + *ch = '!'; + break; // potions ! + + case 266: + *ch = '('; + break; // stones + + case 267: + *ch = ':'; + break; // book + + + case 268: + *ch = '%'; + break; // corpses part 1 + + case 269: + *ch = '|'; + break; // magical staves + + case 270: + *ch = '}'; + break; // gems + + case 271: + *ch = '%'; + break; // don't know ? + + case 272: + *ch = '$'; + break; // $ gold + + case 273: + *ch = '"'; + break; // amulet + + default: + int mnr = object; + *ch = ((mnr >= 297) ? mons_char(mnr - 297) : object); // yeah + break; + } +} + + +/* + This is the viewwindow function for computers without IBM graphic displays. + It is activated by a command line argument, which sets a function pointer. + */ +void viewwindow3(char draw_it, bool do_updates) +{ + int bufcount = 0; + FixedVector < unsigned short, 1500 > buffy; //[800]; //392]; + + unsigned short ch, color; + + int count_x, count_y; + + losight(env.show, grd, you.x_pos, you.y_pos); + + for (count_x = 0; count_x < 18; count_x++) + { + for (count_y = 0; count_y < 18; count_y++) + { + env.show_col[count_x][count_y] = LIGHTGREY; + show_backup[count_x][count_y] = 0; + } + } + + item(); + cloud_grid(); + monster_grid(do_updates); + bufcount = 0; + + if (draw_it == 1) + { + _setcursortype(_NOCURSOR); + for (count_y = (you.y_pos - 8); (count_y < you.y_pos + 9); count_y++) + { + bufcount += 16; + + for (count_x = (you.x_pos - 8); (count_x < you.x_pos + 9); count_x++) + { + color = env.show_col[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9]; + + if (count_x == you.x_pos && count_y == you.y_pos) + { + ch = your_sign; + + if (player_is_swimming()) + { + color = (grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER) + ? BLUE : CYAN; + } + else + { + color = your_colour; + } + } + else + { + unsigned int object = env.show[count_x - you.x_pos + 9] + [count_y - you.y_pos + 9]; + + get_non_ibm_symbol(object, &ch, &color); + } + + buffy[bufcount] = ch; //showed; + buffy[bufcount + 1] = color; + bufcount += 2; + } + + bufcount += 16; + } + + bufcount = 0; + + if (you.level_type != LEVEL_LABYRINTH + && you.level_type != LEVEL_ABYSS) + { + for (count_y = 0; count_y < 17; count_y++) + { + bufcount += 16; + for (count_x = 0; count_x < 17; count_x++) + { + if (buffy[bufcount] != 0 + && (count_x + you.x_pos - 9) >= 0 + && (count_y + you.y_pos - 9) >= 0) + { + env.map[count_x + you.x_pos - 9] + [count_y + you.y_pos - 9] = buffy[bufcount]; + } + + if (Options.clean_map == 1 + && show_backup[count_x + 1][count_y + 1] != 0 + && (count_x + you.x_pos - 9) >= 0 + && (count_y + you.y_pos - 9) >= 0) + { + get_non_ibm_symbol( show_backup[count_x + 1] + [count_y + 1], + &ch, &color ); + env.map[count_x + you.x_pos - 9] + [count_y + you.y_pos - 9] = ch; + } + bufcount += 2; + } + bufcount += 16; + } + } + + bufcount = 0; + + for (count_y = 0; count_y < 17; count_y++) + { + for (count_x = 0; count_x < 33; count_x++) + { + if (count_x + you.x_pos - 17 < 3 + || count_y + you.y_pos - 9 < 3 + || count_x + you.x_pos - 14 > (GXM - 3) + || count_y + you.y_pos - 9 > (GYM - 3)) + { + buffy[bufcount] = 0; + bufcount++; + buffy[bufcount] = 0; + bufcount++; + continue; + } + + if (count_x >= 8 && count_x <= 24 && count_y >= 0 + && count_y <= 16 && buffy[bufcount] != 0) + { + bufcount += 2; + continue; + } + + buffy[bufcount] = env.map[count_x + you.x_pos - 17] + [count_y + you.y_pos - 9]; + + buffy[bufcount + 1] = DARKGREY; + + if (Options.colour_map) + { + if (env.map[count_x + you.x_pos - 16] + [count_y + you.y_pos - 8] != 0) + { + buffy[bufcount + 1] + = colour_code_map( count_x + you.x_pos - 17, + count_y + you.y_pos - 9 ); + } + } + + bufcount += 2; + } + } + + if (you.berserker) + { + for (count_x = 1; count_x < 1400; count_x += 2) + { + if (buffy[count_x] != DARKGREY) + buffy[count_x] = RED; + } + } + + if (show_green != BLACK) + { + for (count_x = 1; count_x < 1400; count_x += 2) + { + if (buffy[count_x] != DARKGREY) + buffy[count_x] = show_green; + } + + show_green = ((you.special_wield == SPWLD_SHADOW) ? DARKGREY + : BLACK); + } + +#ifdef DOS_TERM + puttext(2, 1, 34, 17, buffy.buffer()); +#endif + +#ifdef PLAIN_TERM + gotoxy(2, 1); + bufcount = 0; + + if (you.running == 0) // this line is purely optional + { + for (count_x = 0; count_x < 1120; count_x += 2) // 1056 + { + textcolor(buffy[count_x + 1]); + putch(buffy[count_x]); + + if (count_x % 66 == 64 && count_x > 0) +#ifdef DOS_TERM + cprintf(EOL " "); +#endif + +#ifdef PLAIN_TERM + gotoxy(2, wherey() + 1); +#endif + } + } +#endif + _setcursortype(_NORMALCURSOR); + } // end of (if brek...) +} // end viewwindow3() + + +unsigned char mapchar3(unsigned char ldfk) +{ + unsigned char showed = 0; + + switch (ldfk) + { + case DNGN_UNSEEN: + showed = 0; + break; + + case DNGN_SECRET_DOOR: + case DNGN_ROCK_WALL: + case DNGN_PERMAROCK_WALL: + case DNGN_STONE_WALL: + case DNGN_METAL_WALL: + case DNGN_GREEN_CRYSTAL_WALL: + case DNGN_WAX_WALL: + showed = '*'; + break; + + case DNGN_CLOSED_DOOR: + showed = '+'; + break; + + case 20: // orcish idol + case 24: // ??? + case 25: // ??? + case DNGN_SILVER_STATUE: + case DNGN_GRANITE_STATUE: + case DNGN_ORANGE_CRYSTAL_STATUE: + showed = '8'; + break; + + case DNGN_LAVA_X: + case DNGN_WATER_X: + case DNGN_LAVA: + case DNGN_DEEP_WATER: + case DNGN_SHALLOW_WATER: + showed = '{'; + break; + + case DNGN_FLOOR: + case DNGN_UNDISCOVERED_TRAP: + showed = ','; + break; + + //case 68: showed = '>'; break; // < (60) + + case DNGN_OPEN_DOOR: + showed = 39; + break; // open door + + //case 72: showed = '<'; break; + + case DNGN_TRAP_MECHANICAL: + case DNGN_TRAP_MAGICAL: + case DNGN_TRAP_III: + showed = '^'; + break; + + case DNGN_STONE_STAIRS_DOWN_I: + case DNGN_STONE_STAIRS_DOWN_II: + case DNGN_STONE_STAIRS_DOWN_III: + case DNGN_ROCK_STAIRS_DOWN: + case DNGN_ENTER_ORCISH_MINES: + case DNGN_ENTER_HIVE: + case DNGN_ENTER_LAIR: + case DNGN_ENTER_SLIME_PITS: + case DNGN_ENTER_VAULTS: + case DNGN_ENTER_CRYPT: + case DNGN_ENTER_HALL_OF_BLADES: + case DNGN_ENTER_TEMPLE: + case DNGN_ENTER_SNAKE_PIT: + case DNGN_ENTER_ELVEN_HALLS: + case DNGN_ENTER_TOMB: + case DNGN_ENTER_SWAMP: + case 123: + case 124: + case 125: + case 126: + showed = '>'; + break; + + case DNGN_STONE_STAIRS_UP_I: + case DNGN_STONE_STAIRS_UP_II: + case DNGN_STONE_STAIRS_UP_III: + case DNGN_ROCK_STAIRS_UP: + case DNGN_RETURN_FROM_ORCISH_MINES: + case DNGN_RETURN_FROM_HIVE: + case DNGN_RETURN_FROM_LAIR: + case DNGN_RETURN_FROM_SLIME_PITS: + case DNGN_RETURN_FROM_VAULTS: + case DNGN_RETURN_FROM_CRYPT: + case DNGN_RETURN_FROM_HALL_OF_BLADES: + case DNGN_RETURN_FROM_TEMPLE: + case DNGN_RETURN_FROM_SNAKE_PIT: + case DNGN_RETURN_FROM_ELVEN_HALLS: + case DNGN_RETURN_FROM_TOMB: + case DNGN_RETURN_FROM_SWAMP: + case 143: + case 144: + case 145: + case 146: + showed = '<'; + break; + + case DNGN_ENTER_HELL: + case DNGN_ENTER_LABYRINTH: + case DNGN_ENTER_SHOP: + case DNGN_ENTER_DIS: + case DNGN_ENTER_GEHENNA: + case DNGN_ENTER_COCYTUS: + case DNGN_ENTER_TARTARUS: + case DNGN_ENTER_ABYSS: + case DNGN_EXIT_ABYSS: + case DNGN_STONE_ARCH: + case DNGN_ENTER_PANDEMONIUM: + case DNGN_EXIT_PANDEMONIUM: + case DNGN_TRANSIT_PANDEMONIUM: + case DNGN_ENTER_ZOT: + case DNGN_RETURN_FROM_ZOT: + showed = '\\'; + break; + + case DNGN_ALTAR_ZIN: + case DNGN_ALTAR_SHINING_ONE: + case DNGN_ALTAR_KIKUBAAQUDGHA: + case DNGN_ALTAR_YREDELEMNUL: + case DNGN_ALTAR_XOM: + case DNGN_ALTAR_VEHUMET: + case DNGN_ALTAR_OKAWARU: + case DNGN_ALTAR_MAKHLEB: + case DNGN_ALTAR_SIF_MUNA: + case DNGN_ALTAR_TROG: + case DNGN_ALTAR_NEMELEX_XOBEH: + case DNGN_ALTAR_ELYVILON: + showed = '_'; + break; + + case DNGN_BLUE_FOUNTAIN: + case DNGN_DRY_FOUNTAIN_I: + case DNGN_SPARKLING_FOUNTAIN: + case DNGN_DRY_FOUNTAIN_II: + case DNGN_DRY_FOUNTAIN_III: + case DNGN_DRY_FOUNTAIN_IV: + case DNGN_DRY_FOUNTAIN_V: + case DNGN_DRY_FOUNTAIN_VI: + case DNGN_DRY_FOUNTAIN_VII: + case DNGN_DRY_FOUNTAIN_VIII: + case DNGN_PERMADRY_FOUNTAIN: + showed = '}'; + break; + + default: + showed = 0; + break; + } + + return showed; +} + + +unsigned char mapchar4(unsigned char ldfk) +{ + unsigned char showed = 0; + + switch (ldfk) + { + case DNGN_UNSEEN: + showed = 0; + break; + + case DNGN_CLOSED_DOOR: + showed = '+'; + break; + + case DNGN_SECRET_DOOR: + case DNGN_ROCK_WALL: + case DNGN_PERMAROCK_WALL: + case DNGN_STONE_WALL: + case DNGN_METAL_WALL: + case DNGN_GREEN_CRYSTAL_WALL: + case DNGN_WAX_WALL: + showed = '#'; + break; + + case 20: // orcish idol + case 24: // ??? + case 25: // ??? + case DNGN_SILVER_STATUE: + case DNGN_GRANITE_STATUE: + case DNGN_ORANGE_CRYSTAL_STATUE: + showed = '8'; + break; + + case DNGN_LAVA_X: + case DNGN_WATER_X: + case DNGN_LAVA: + case DNGN_DEEP_WATER: + case DNGN_SHALLOW_WATER: + showed = '{'; + break; + + case DNGN_FLOOR: + case DNGN_UNDISCOVERED_TRAP: + showed = '.'; + break; + + case 68: + showed = '>'; // < + break; + + case DNGN_OPEN_DOOR: + showed = 39; + break; + + case 72: + showed = '<'; + break; + + case DNGN_TRAP_MECHANICAL: + case DNGN_TRAP_MAGICAL: + case DNGN_TRAP_III: + showed = '^'; + break; + + case DNGN_STONE_STAIRS_DOWN_I: + case DNGN_STONE_STAIRS_DOWN_II: + case DNGN_STONE_STAIRS_DOWN_III: + case DNGN_ROCK_STAIRS_DOWN: + case DNGN_ENTER_ORCISH_MINES: + case DNGN_ENTER_HIVE: + case DNGN_ENTER_LAIR: + case DNGN_ENTER_SLIME_PITS: + case DNGN_ENTER_VAULTS: + case DNGN_ENTER_CRYPT: + case DNGN_ENTER_HALL_OF_BLADES: + case DNGN_ENTER_TEMPLE: + case DNGN_ENTER_SNAKE_PIT: + case DNGN_ENTER_ELVEN_HALLS: + case DNGN_ENTER_TOMB: + case DNGN_ENTER_SWAMP: + case 123: + case 124: + case 125: + case 126: + showed = '>'; + break; + + case DNGN_STONE_STAIRS_UP_I: + case DNGN_STONE_STAIRS_UP_II: + case DNGN_STONE_STAIRS_UP_III: + case DNGN_ROCK_STAIRS_UP: + case DNGN_RETURN_FROM_ORCISH_MINES: + case DNGN_RETURN_FROM_HIVE: + case DNGN_RETURN_FROM_LAIR: + case DNGN_RETURN_FROM_SLIME_PITS: + case DNGN_RETURN_FROM_VAULTS: + case DNGN_RETURN_FROM_CRYPT: + case DNGN_RETURN_FROM_HALL_OF_BLADES: + case DNGN_RETURN_FROM_TEMPLE: + case DNGN_RETURN_FROM_SNAKE_PIT: + case DNGN_RETURN_FROM_ELVEN_HALLS: + case DNGN_RETURN_FROM_TOMB: + case DNGN_RETURN_FROM_SWAMP: + case 143: + case 144: + case 145: + case 146: + showed = '<'; + break; + + case DNGN_ENTER_HELL: + case DNGN_ENTER_LABYRINTH: + case DNGN_ENTER_SHOP: + case DNGN_ENTER_DIS: + case DNGN_ENTER_GEHENNA: + case DNGN_ENTER_COCYTUS: + case DNGN_ENTER_TARTARUS: + case DNGN_ENTER_ABYSS: + case DNGN_EXIT_ABYSS: + case DNGN_STONE_ARCH: + case DNGN_ENTER_PANDEMONIUM: + case DNGN_EXIT_PANDEMONIUM: + case DNGN_TRANSIT_PANDEMONIUM: + case DNGN_ENTER_ZOT: + case DNGN_RETURN_FROM_ZOT: + showed = '\\'; + break; + + case DNGN_ALTAR_ZIN: + case DNGN_ALTAR_SHINING_ONE: + case DNGN_ALTAR_KIKUBAAQUDGHA: + case DNGN_ALTAR_YREDELEMNUL: + case DNGN_ALTAR_XOM: + case DNGN_ALTAR_VEHUMET: + case DNGN_ALTAR_OKAWARU: + case DNGN_ALTAR_MAKHLEB: + case DNGN_ALTAR_SIF_MUNA: + case DNGN_ALTAR_TROG: + case DNGN_ALTAR_NEMELEX_XOBEH: + case DNGN_ALTAR_ELYVILON: + showed = '_'; + break; + + case DNGN_BLUE_FOUNTAIN: + case DNGN_DRY_FOUNTAIN_I: + case DNGN_SPARKLING_FOUNTAIN: + case DNGN_DRY_FOUNTAIN_II: + case DNGN_DRY_FOUNTAIN_III: + case DNGN_DRY_FOUNTAIN_IV: + case DNGN_DRY_FOUNTAIN_V: + case DNGN_DRY_FOUNTAIN_VI: + case DNGN_DRY_FOUNTAIN_VII: + case DNGN_DRY_FOUNTAIN_VIII: + case DNGN_PERMADRY_FOUNTAIN: + showed = '}'; + break; + + default: + showed = 0; + break; + } + + return showed; +} -- cgit v1.2.3-54-g00ecf