diff options
-rw-r--r-- | crawl-ref/docs/crawl_options.txt | 109 | ||||
-rw-r--r-- | crawl-ref/init.txt | 24 | ||||
-rw-r--r-- | crawl-ref/source/abyss.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/acr.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/defines.h | 3 | ||||
-rw-r--r-- | crawl-ref/source/direct.cc | 55 | ||||
-rw-r--r-- | crawl-ref/source/direct.h | 17 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.h | 14 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 116 | ||||
-rw-r--r-- | crawl-ref/source/files.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/initfile.cc | 67 | ||||
-rw-r--r-- | crawl-ref/source/libdos.cc | 14 | ||||
-rw-r--r-- | crawl-ref/source/libunix.cc | 13 | ||||
-rw-r--r-- | crawl-ref/source/libw32c.cc | 34 | ||||
-rw-r--r-- | crawl-ref/source/message.cc | 10 | ||||
-rw-r--r-- | crawl-ref/source/monplace.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/output.cc | 44 | ||||
-rw-r--r-- | crawl-ref/source/player.cc | 22 | ||||
-rw-r--r-- | crawl-ref/source/spells1.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/spells3.cc | 8 | ||||
-rw-r--r-- | crawl-ref/source/spells4.cc | 8 | ||||
-rw-r--r-- | crawl-ref/source/stuff.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/tags.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/view.cc | 249 | ||||
-rw-r--r-- | crawl-ref/source/view.h | 2 |
25 files changed, 625 insertions, 224 deletions
diff --git a/crawl-ref/docs/crawl_options.txt b/crawl-ref/docs/crawl_options.txt index 48aad68b97..5be8d756c9 100644 --- a/crawl-ref/docs/crawl_options.txt +++ b/crawl-ref/docs/crawl_options.txt @@ -34,32 +34,37 @@ The contents of this text are: stair_item_brand 4-e Level Map Functions. level_map_cursor_step, level_map_title, item_colour -4-f Travel and Exploration. +4-f Viewport Display Options. + view_max_width, view_max_height, view_lock_x, + view_lock_y, view_lock, center_on_scroll, + symmetric_scroll, scroll_margin_x, scroll_margin_y, + scroll_margin +4-g Travel and Exploration. travel_delay, travel_avoid_terrain, travel_exclude_radius2, travel_stop_message, explore_greedy, explore_stop, runrest_ignore_message, runrest_ignore_poison, trapwalk_safe_hp, tc_reachable, tc_dangerous, tc_excluded, tc_exclude_circle -4-g Stashes. +4-h Stashes. stash_tracking, stash_filter -4-h Command Enhancements. +4-i Command Enhancements. auto_list, lowercase_invocations, easy_open, easy_butcher, easy_unequip, easy_confirm, easy_quit_item_prompts, easy_exit_menu, default_autoprayer, sort_menus -4-i Message and Display Improvements. +4-j Message and Display Improvements. hp_warning, mp_warning, hp_colour, mp_colour, always_greet, terse_hand, delay_message_clear, menu_colour, message_colour, increasing_skill_progress, show_inventory_weights, show_turns -4-j Missiles. +4-k Missiles. fire_items_start, fire_order -4-k Message Channels. +4-l Message Channels. plain, prompt, god, pray, duration, danger, food, warning, recovery, multiturn, talk, intrinsic_gain, mutation, monster_spell, monster_enchant, monster_damage, rotten_meat -4-l Inscriptions. +4-m Inscriptions. autoinscribe -4-m Macro related Options. +4-n Macro related Options. flush.failure, flush.command, flush.message 5- Character Dump. 5-a Items and Kills. @@ -481,7 +486,79 @@ item_colour = true Colours items on level-map. -4-f Travel and Exploration. +4-f Viewport Display Options +-------------------------------- + +The viewport is the portion of the map that is displayed during normal +play. The viewport is 33x17 by default, but if you use larger terminal +sizes, you can set these options to make the game show a larger +viewport. (These options are not fully available on DOS.) + +None of these options affects gameplay. In particular, your character's +line-of-sight is unaffected by these options. + +view_max_width = 33 + Sets the maximum width of the viewport (defaults to 33). + Making this larger will allow Crawl to show a wider viewport + on larger terminals. + +view_max_height = 17 + Similar to view_max_width, but sets the viewport's maximum + height. + +* Note that using large viewports can slow the game down. + +view_lock_x = true + Keeps the player character centered horizontally in the + viewport, continuously scrolling the viewport to match the + PC's movements. If this is not set, the player character can + move horizontally within the viewport, and the viewport will + scroll only when the character's line-of-sight reaches the + left or right edge. + +view_lock_y = true + Keeps the character centered vertically in the viewport. + +view_lock = true + Aliased option that sets both view_lock_x and view_lock_y. + +center_on_scroll = false + If this is set, the viewport centers on the player character + whenever it scrolls (this option is irrelevant if view_lock_x + and view_lock_y are set). + +symmetric_scroll = true + If this is set, the viewport will scroll in a manner consistent + with the character movement that caused the scroll. + + To illustrate, let's say the PC is at the lower edge of the + viewport, but is near the horizontal center. Now the PC moves + diagonally down and right, forcing the viewport to scroll up + one line. If symmetric_scroll is set, the viewport will also + scroll left one column to match the PC's diagonal movement. If + symmetric_scroll is not set, the viewport will only scroll up, + not horizontally. symmetric_scroll can be less disorienting + than free scrolling. + + This option is not relevant if view_lock or center_on_scroll + are set. + +scroll_margin_x = 4 + How far from the left or right edges scrolling starts. By + default, if the PC's circle of line-of-sight is closer than 4 + squares from the edge, the viewport scrolls. If set at zero, + the viewport scrolls only when the LOS circle reaches the + viewport edge. + +scroll_margin_y = 4 + How far from the top or bottom edges scrolling starts. + +scroll_margin = 4 + An aliased option that sets both scroll_margin_x and + scroll_margin_y. + + +4-g Travel and Exploration. ------------------------------- travel_delay = 20 @@ -580,7 +657,7 @@ tc_exclude_circle = red excluded_circle: the colour for travel exclusions apart from centre -4-g Stashes. +4-h Stashes. ---------------- stash_tracking = (all | explicit | dropped) @@ -604,7 +681,7 @@ stash_tracking = (all | explicit | dropped) squares. You can still use Ctrl-S and Ctrl-E as above. -4-h Command Enhancements. +4-i Command Enhancements. ----------------------------- auto_list = true @@ -741,7 +818,7 @@ sort_menus = [menu:](true | false | auto:X)[:sort_order] any: All menus; this is the default when unspecified. -4-i Messages and Display Enhancements. +4-j Messages and Display Enhancements. ------------------------------------------ hp_warning = 10 @@ -827,7 +904,7 @@ show_turns = false This option controls whether the turn counter (of turns elapsed) is displayed in the main view. -4-j Missiles. +4-k Missiles. ----------------- fire_items_start = a @@ -847,7 +924,7 @@ fire_order = launcher, dart, stone, dagger, spear, handaxe, club <See also pickup_thrown in A.4a.> -4-k Message Channels. +4-l Message Channels. ------------------------- Crawl communicates to the players with its message window. Every message @@ -892,7 +969,7 @@ Note that the template init.txt sets in order to help new players. You may want to comment out this option, if the messages are too verbose. -4-l Inscriptions. +4-m Inscriptions. --------------------- In Crawl, items can be manually inscribed with the '{' command. This adds a @@ -921,7 +998,7 @@ autoinscribe = <regex>:<inscription> autoinscribe = wand of healing:!z -4-m Macro related Options. +4-n Macro related Options. ------------------------------ flush.failure = true diff --git a/crawl-ref/init.txt b/crawl-ref/init.txt index 48ec5cdc6e..82e76b8e8c 100644 --- a/crawl-ref/init.txt +++ b/crawl-ref/init.txt @@ -111,7 +111,15 @@ stab_brand = hi:blue # level_map_title = false # item_colour = false -##### 4-f Travel and Exploration ################# +##### 4-f Viewport Options ################### +# view_max_width = 33 +# view_max_height = 17 +# view_lock = false +# center_on_scroll = true +# symmetric_scroll = false +# scroll_margin = 4 + +##### 4-g Travel and Exploration ################# # # travel_colour = false # travel_delay = 20 @@ -135,12 +143,12 @@ stab_brand = hi:blue # runrest_ignore_poison = 4:100 # trapwalk_safe_hp = dart:15, needle:25, spear:50 -##### 4-g Stashes ############################### +##### 4-h Stashes ############################### # # stash_tracking = (all | explicit | dropped) # stash_filter = 14, 4:21 -##### 4-h Command Enhancements ################## +##### 4-i Command Enhancements ################## # # auto_list = false # lowercase_invocations = false @@ -153,7 +161,7 @@ stab_brand = hi:blue # default_autoprayer = true # sort_menus = pickup: true : basename, qualname, curse, qty -##### 4-i Messages and Display Enhancements ##### +##### 4-j Messages and Display Enhancements ##### # # hp_warning = 10 # mp_warning = 10 @@ -187,20 +195,20 @@ message_colour = lightcyan:LOW MAGIC WARNING # message_colour = mute:(HP|Magic) restored # message_colour = mute:warning:Not with.*(in view|monsters around) -##### 4-j Firing Commands ####################### +##### 4-k Firing Commands ####################### # # fire_items_start = a # fire_order = launcher, dart, stone, dagger, spear, handaxe, club -##### 4-k Channels ############################## +##### 4-l Channels ############################## # # channel.multiturn = mute -##### 4-l Inscriptions ########################## +##### 4-m Inscriptions ########################## # # autoinscribe = royal jell:=g -##### 4-m Macro related Options ################# +##### 4-n Macro related Options ################# # # flush.failure = false # flush.command = true diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index 68b64edfcc..6dbf138ada 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -282,8 +282,7 @@ void area_shift(void) } } - you.x_pos = 45; - you.y_pos = 35; + you.moveto(45, 35); generate_area(5, 5, (GXM - 5), (GYM - 5)); @@ -331,8 +330,7 @@ void abyss_teleport( bool new_area ) if (i < 100) { - you.x_pos = x; - you.y_pos = y; + you.moveto(x, y); return; } } @@ -384,8 +382,7 @@ void abyss_teleport( bool new_area ) ASSERT( env.cloud_no == 0 ); - you.x_pos = 45; - you.y_pos = 35; + you.moveto(45, 35); generate_area( 10, 10, (GXM - 10), (GYM - 10) ); diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 67d99f71c9..9bb5a0abd7 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -894,7 +894,8 @@ static void input() handle_delay(); - gotoxy(VIEW_CX, VIEW_CY); + const coord_def cwhere = grid2view(you.pos()); + gotoxy(cwhere.x, cwhere.y); if ( you_are_delayed() ) { @@ -1127,6 +1128,7 @@ void process_command( command_type cmd ) { mpr("Clearing level map."); clear_map(); + crawl_view.set_player_at(you.pos(), true); } break; @@ -1347,6 +1349,7 @@ void process_command( command_type cmd ) #endif plox[0] = 0; show_map(plox, true); + crawl_view.set_player_at(you.pos(), true); redraw_screen(); if (plox[0] > 0) start_travel(plox[0], plox[1]); @@ -1450,7 +1453,7 @@ void process_command( command_type cmd ) #endif case CMD_SAVE_GAME: - if (yesno("Save game and exit?", true, 'n')) + if (yesno("Save game and exit? ", true, 'n')) save_game(true); break; diff --git a/crawl-ref/source/defines.h b/crawl-ref/source/defines.h index 9ce64087e6..5b8bb6200c 100644 --- a/crawl-ref/source/defines.h +++ b/crawl-ref/source/defines.h @@ -109,6 +109,9 @@ #define Y_ABYSS_WIDTH (Y_ABYSS_2 - Y_ABYSS_1 + 1) #define Y_ABYSS_CENTER (Y_ABYSS_1 + Y_ABYSS_WIDTH / 2) +#define LOS_RADIUS 8 +#define ENV_SHOW_OFFSET (LOS_RADIUS + 1) +#define ENV_SHOW_DIAMETER (ENV_SHOW_OFFSET * 2 + 1) #define LOS_SX 8 #define LOS_EX 25 #define LOS_SY 1 diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc index 59429c4349..5bf61db694 100644 --- a/crawl-ref/source/direct.cc +++ b/crawl-ref/source/direct.cc @@ -85,8 +85,8 @@ static char find_square_wrapper( int tx, int ty, bool wrap = false, int los = LOS_ANY); -static char find_square( unsigned char xps, unsigned char yps, - FixedVector<char, 2> &mfp, char direction, +static char find_square( int xps, int yps, + FixedVector<char, 2> &mfp, int direction, bool (*targ)(int, int, int), int mode = TARG_ANY, bool wrap = false, @@ -827,8 +827,9 @@ static void describe_oos_square(int x, int y) bool in_vlos(int x, int y) { - return in_los_bounds(x, y) - && (env.show[x - LOS_SX][y] || (x == VIEW_CX && y == VIEW_CY)); + return in_los_bounds(x, y) + && (env.show(view2show(coord_def(x, y))) + || coord_def(x, y) == grid2view(you.pos())); } bool in_vlos(const coord_def &pos) @@ -838,13 +839,7 @@ bool in_vlos(const coord_def &pos) bool in_los(int x, int y) { - const int tx = x + VIEW_CX - you.x_pos, - ty = y + VIEW_CY - you.y_pos; - - if (!in_los_bounds(tx, ty)) - return (false); - - return (x == you.x_pos && y == you.y_pos) || env.show[tx - LOS_SX][ty]; + return (in_vlos(grid2view(coord_def(x, y)))); } static bool find_monster( int x, int y, int mode ) @@ -929,12 +924,12 @@ static int next_los(int dir, int los, bool wrap) bool in_viewport_bounds(int x, int y) { - return (x >= VIEW_SX && x <= VIEW_EX && y >= VIEW_SY && y <= VIEW_EY); + return crawl_view.in_view_viewport(coord_def(x, y)); } bool in_los_bounds(int x, int y) { - return !(x > LOS_EX || x < LOS_SX || y > LOS_EY || y < LOS_SY); + return crawl_view.in_view_los(coord_def(x, y)); } //--------------------------------------------------------------- @@ -951,8 +946,8 @@ bool in_los_bounds(int x, int y) // monsters will be targeted. // //--------------------------------------------------------------- -static char find_square( unsigned char xps, unsigned char yps, - FixedVector<char, 2> &mfp, char direction, +static char find_square( int xps, int yps, + FixedVector<char, 2> &mfp, int direction, bool (*find_targ)( int x, int y, int mode ), int mode, bool wrap, int los ) { @@ -961,8 +956,8 @@ static char find_square( unsigned char xps, unsigned char yps, int temp_xps = xps; int temp_yps = yps; - char x_change = 0; - char y_change = 0; + int x_change = 0; + int y_change = 0; bool onlyVis = false, onlyHidden = false; @@ -977,8 +972,8 @@ static char find_square( unsigned char xps, unsigned char yps, { // We've been told to flip between visible/hidden, so we // need to find what we're currently on. - const bool vis = (env.show[xps - 8][yps] - || (xps == VIEW_CX && yps == VIEW_CY)); + const bool vis = (env.show(view2show(coord_def(xps, yps))) + || view2grid(coord_def(xps, yps)) == you.pos()); if (wrap && (vis != (los == LOS_FLIPVH)) == (direction == 1)) { @@ -1001,9 +996,17 @@ static char find_square( unsigned char xps, unsigned char yps, onlyVis = (los & LOS_VISIBLE); onlyHidden = (los & LOS_HIDDEN); - const int minx = VIEW_SX, maxx = VIEW_EX, - miny = VIEW_SY - VIEW_Y_DIFF, maxy = VIEW_EY + VIEW_Y_DIFF, - ctrx = VIEW_CX, ctry = VIEW_CY; + int radius = 0; + if (crawl_view.viewsz.x > crawl_view.viewsz.y) + radius = crawl_view.viewsz.x - LOS_RADIUS - 1; + else + radius = crawl_view.viewsz.y - LOS_RADIUS - 1; + + const coord_def vyou = grid2view(you.pos()); + + const int minx = vyou.x - radius, maxx = vyou.x + radius, + miny = vyou.y - radius, maxy = vyou.y + radius, + ctrx = vyou.x, ctry = vyou.y; while (temp_xps >= minx - 1 && temp_xps <= maxx && temp_yps <= maxy && temp_yps >= miny - 1) @@ -1135,17 +1138,17 @@ static char find_square( unsigned char xps, unsigned char yps, //if (!in_los_bounds(temp_xps, temp_yps)) // continue; - if (temp_xps < minx - 1 || temp_xps > maxx - || temp_yps < VIEW_SY || temp_yps > VIEW_EY) + if (!crawl_view.in_grid_viewport(coord_def(targ_x, targ_y))) continue; - if (targ_x < 1 || targ_x >= GXM || targ_y < 1 || targ_y >= GYM) + if (!in_bounds(targ_x, targ_y)) continue; if ((onlyVis || onlyHidden) && onlyVis != in_los(targ_x, targ_y)) continue; - if (find_targ(targ_x, targ_y, mode)) { + if (find_targ(targ_x, targ_y, mode)) + { mfp[0] = temp_xps; mfp[1] = temp_yps; return (1); diff --git a/crawl-ref/source/direct.h b/crawl-ref/source/direct.h index 460b14527a..973000e8de 100644 --- a/crawl-ref/source/direct.h +++ b/crawl-ref/source/direct.h @@ -42,32 +42,37 @@ std::vector<dungeon_feature_type> features_by_desc(const text_pattern &pattern); inline int view2gridX(int vx) { - return (you.x_pos + vx - VIEW_CX); + return (crawl_view.vgrdc.x + vx - crawl_view.view_centre().x); } inline int view2gridY(int vy) { - return (you.y_pos + vy - VIEW_CY); + return (crawl_view.vgrdc.y + vy - crawl_view.view_centre().y); } inline coord_def view2grid(const coord_def &pos) { - return coord_def( view2gridX(pos.x), view2gridY(pos.y) ); + return pos - crawl_view.view_centre() + crawl_view.vgrdc; } inline int grid2viewX(int gx) { - return (gx - you.x_pos + VIEW_CX); + return (gx - crawl_view.vgrdc.x + crawl_view.view_centre().x); } inline int grid2viewY(int gy) { - return (gy - you.y_pos + VIEW_CY); + return (gy - crawl_view.vgrdc.y + crawl_view.view_centre().y); } inline coord_def grid2view(const coord_def &pos) { - return coord_def( grid2viewX(pos.x), grid2viewY(pos.y) ); + return (pos - crawl_view.vgrdc + crawl_view.view_centre()); +} + +inline coord_def view2show(const coord_def &pos) +{ + return (pos - crawl_view.vlos1 + coord_def(1, 1)); } #endif diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h index 226be99c82..172cea7061 100644 --- a/crawl-ref/source/dungeon.h +++ b/crawl-ref/source/dungeon.h @@ -56,6 +56,11 @@ struct dgn_region return dgn_region(left, top, right - left + 1, bottom - top + 1); } + static dgn_region absolute(const coord_def &c1, const coord_def &c2) + { + return dgn_region(c1.x, c1.y, c2.x, c2.y); + } + static bool between(int val, int low, int high) { return (val >= low && val <= high); @@ -63,8 +68,13 @@ struct dgn_region bool contains(const coord_def &p) const { - return (p.x >= pos.x && p.x < pos.x + size.x - && p.y >= pos.y && p.y < pos.y + size.y); + return contains(p.x, p.y); + } + + bool contains(int xp, int yp) const + { + return (xp >= pos.x && xp < pos.x + size.x + && yp >= pos.y && yp < pos.y + size.y); } bool fully_contains(const coord_def &p) const diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index cc73ba5a5c..635d853f6a 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -277,19 +277,30 @@ struct coord_def y -= other.y; return (*this); } + + const coord_def &operator /= (int div) + { + x /= div; + y /= div; + return (*this); + } coord_def operator + (const coord_def &other) const { coord_def copy = *this; - copy += other; - return (copy); + return (copy += other); } coord_def operator - (const coord_def &other) const { coord_def copy = *this; - copy -= other; - return (copy); + return (copy -= other); + } + + coord_def operator / (int div) const + { + coord_def copy = *this; + return (copy /= div); } int abs() const @@ -756,6 +767,11 @@ public: bool operator < (const player &p) const; public: + // Low-level move the player to (x, y). Use these functions instead of + // changing x_pos and y_pos directly. + void moveto(int x, int y); + void moveto(const coord_def &c); + bool in_water() const; bool can_swim() const; bool is_levitating() const; @@ -1141,8 +1157,10 @@ struct crawl_environment FixedArray< unsigned short, GXM, GYM > map; // discovered terrain FixedArray< map_colour, GXM, GYM > map_col; // map colours - FixedArray< unsigned int, 19, 19> show; // view window char - FixedArray< unsigned short, 19, 19> show_col; // view window colour + FixedArray<unsigned, ENV_SHOW_DIAMETER, ENV_SHOW_DIAMETER> + show; // view window char + FixedArray<unsigned short, ENV_SHOW_DIAMETER, ENV_SHOW_DIAMETER> + show_col; // view window colour FixedVector< cloud_struct, MAX_CLOUDS > cloud; // cloud list unsigned char cloud_no; @@ -1227,6 +1245,72 @@ struct system_environment extern system_environment SysEnv; +struct crawl_view_geometry +{ +public: + coord_def termsz; // Size of the terminal. + coord_def viewp; // Left-top pos of viewport. + coord_def viewsz; // Size of the viewport (play area). + coord_def hudp; // Left-top pos of status area. + coord_def hudsz; // Size of the status area. + coord_def msgp; // Left-top pos of the message pane. + coord_def msgsz; // Size of the message pane. + + coord_def vgrdc; // What grid pos is at the centre of the view + // usually you.pos(). + + coord_def viewhalfsz; + + coord_def glos1, glos2; // LOS limit grid coords (inclusive) + coord_def vlos1, vlos2; // LOS limit viewport coords (inclusive) + + static const int message_min_lines = 7; + static const int hud_min_width = 41; + static const int hud_min_gutter = 3; + static const int hud_max_gutter = 6; + +private: + coord_def last_player_pos; + +public: + crawl_view_geometry(); + void init_geometry(); + + void init_view(); + void set_player_at(const coord_def &c, bool force_centre = false); + + coord_def view_centre() const + { + return viewp + viewhalfsz; + } + + bool in_grid_los(const coord_def &c) const + { + return (c.x >= glos1.x && c.x <= glos2.x + && c.y >= glos1.y && c.y <= glos2.y); + } + + bool in_view_los(const coord_def &c) const + { + return (c.x >= vlos1.x && c.x <= vlos2.x + && c.y >= vlos1.y && c.y <= vlos2.y); + } + + bool in_view_viewport(const coord_def &c) const + { + return (c.x >= viewp.x && c.y >= viewp.y + && c.x < viewp.x + viewsz.x + && c.y < viewp.y + viewsz.y); + } + + bool in_grid_viewport(const coord_def &c) const + { + return in_view_viewport(c - vgrdc + view_centre()); + } +}; + +extern crawl_view_geometry crawl_view; + struct message_filter { int channel; // Use -1 to match any channel. @@ -1349,6 +1433,26 @@ public: bool messaging; // Check for messages. #endif + int view_max_width; + int view_max_height; + + // The view lock variables force centering the viewport around the PC @ + // at all times (the default). If view locking is not enabled, the viewport + // scrolls only when the PC hits the edge of it. + bool view_lock_x; + bool view_lock_y; + + // For an unlocked viewport, this will center the viewport when scrolling. + bool center_on_scroll; + + // If symmetric_scroll is set, for diagonal moves, if the view + // scrolls at all, it'll scroll diagonally. + bool symmetric_scroll; + + // How far from the viewport edge is scrolling forced. + int scroll_margin_x; + int scroll_margin_y; + bool autopickup_on; bool autoprayer_on; diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 4a3c39c44d..2e4ec6c9d9 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -810,8 +810,7 @@ static void place_player_on_stair(branch_type old_branch, int stair_taken) } const coord_def where_to_go = find_nearby_stair(stair_taken, find_first); - you.x_pos = where_to_go.x; - you.y_pos = where_to_go.y; + you.moveto(where_to_go); } static void close_level_gates() @@ -999,9 +998,9 @@ bool load( int stair_taken, load_mode_type load_mode, bool was_a_labyrinth, } else if (load_mode != LOAD_RESTART_GAME && you.level_type == LEVEL_ABYSS) { - you.x_pos = 45; - you.y_pos = 35; + you.moveto(45, 35); } + crawl_view.set_player_at(you.pos(), true); // This should fix the "monster occuring under the player" bug? if (mgrd[you.x_pos][you.y_pos] != NON_MONSTER) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 401dfda212..30e9619699 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -555,6 +555,17 @@ void game_options::reset_options() messaging = true; #endif + view_max_width = VIEW_EX; + view_max_height = VIEW_EY; + + view_lock_x = true; + view_lock_y = true; + + center_on_scroll = false; + symmetric_scroll = true; + scroll_margin_x = 4; + scroll_margin_y = 4; + autopickup_on = true; autoprayer_on = false; @@ -1855,6 +1866,62 @@ void game_options::read_option_line(const std::string &str, bool runscript) messaging = read_bool(field, messaging); } #endif + else if (key == "view_max_width") + { + view_max_width = atoi(field.c_str()); + if (view_max_width < VIEW_EX) + view_max_width = VIEW_EX; + else if (view_max_width > GXM + 1) + view_max_width = GXM + 1; + } + else if (key == "view_max_height") + { + view_max_height = atoi(field.c_str()); + if (view_max_height < VIEW_EY) + view_max_height = VIEW_EY; + else if (view_max_height > GYM + 1) + view_max_height = GYM + 1; + } + else if (key == "view_lock_x") + { + view_lock_x = read_bool(field, view_lock_x); + } + else if (key == "view_lock_y") + { + view_lock_y = read_bool(field, view_lock_y); + } + else if (key == "view_lock") + { + const bool lock = read_bool(field, true); + view_lock_x = view_lock_y = lock; + } + else if (key == "center_on_scroll") + { + center_on_scroll = read_bool(field, center_on_scroll); + } + else if (key == "symmetric_scroll") + { + symmetric_scroll = read_bool(field, symmetric_scroll); + } + else if (key == "scroll_margin_x") + { + scroll_margin_x = atoi(field.c_str()); + if (scroll_margin_x < 0) + scroll_margin_x = 0; + } + else if (key == "scroll_margin_y") + { + scroll_margin_y = atoi(field.c_str()); + if (scroll_margin_y < 0) + scroll_margin_y = 0; + } + else if (key == "scroll_margin") + { + int scrollmarg = atoi(field.c_str()); + if (scrollmarg < 0) + scrollmarg = 0; + scroll_margin_x = scroll_margin_y = scrollmarg; + } else if (key == "use_notes") { use_notes = read_bool( field, use_notes ); diff --git a/crawl-ref/source/libdos.cc b/crawl-ref/source/libdos.cc index 2db3422868..8c197e1c8e 100644 --- a/crawl-ref/source/libdos.cc +++ b/crawl-ref/source/libdos.cc @@ -28,7 +28,8 @@ void init_libdos() void clear_message_window() { - window(1, VIEW_EY + 1, get_number_of_cols(), get_number_of_lines()); + window(crawl_view.msgp.x, crawl_view.msgp.y, + get_number_of_cols(), get_number_of_lines()); clrscr(); window(1, 1, get_number_of_cols(), get_number_of_lines()); } @@ -38,8 +39,9 @@ static void scroll_message_window() const int x = wherex(), y = wherey(); textcolor(LIGHTGREY); - movetext(1, VIEW_EY + 2, get_number_of_cols(), get_number_of_lines(), - 1, VIEW_EY + 1); + movetext(crawl_view.msgp.x, crawl_view.msgp.y + 1, + get_number_of_cols(), get_number_of_lines(), + crawl_view.msgp.x, crawl_view.msgp.y); gotoxy(1, get_number_of_lines()); clreol(); @@ -48,19 +50,19 @@ static void scroll_message_window() gotoxy(x, y - 1); } -extern int get_message_window_height(); void message_out(int which_line, int colour, const char *s, int firstcol, bool newline) { if (!firstcol) firstcol = Options.delay_message_clear? 2 : 1; - gotoxy(firstcol, which_line + VIEW_EY + 1); + gotoxy(firstcol + crawl_view.msgp.x - 1, + which_line + crawl_view.msgp.y); textcolor(colour); cprintf("%s", s); - if (newline && which_line == get_message_window_height() - 1) + if (newline && which_line == crawl_view.msgsz.y - 1) scroll_message_window(); } diff --git a/crawl-ref/source/libunix.cc b/crawl-ref/source/libunix.cc index 79f91d17b7..b9d9342e92 100644 --- a/crawl-ref/source/libunix.cc +++ b/crawl-ref/source/libunix.cc @@ -234,10 +234,8 @@ static void handle_hangup(int) static WINDOW *Message_Window; static void setup_message_window() { - extern int get_message_window_height(); - - Message_Window = newwin( get_message_window_height(), get_number_of_cols(), - VIEW_EY, 0 ); + Message_Window = newwin( crawl_view.msgsz.y, crawl_view.msgsz.x, + crawl_view.msgp.y - 1, crawl_view.msgp.x - 1 ); if (!Message_Window) { fprintf(stderr, "Unable to create message window!"); @@ -258,8 +256,6 @@ void clear_message_window() void message_out(int which_line, int color, const char *s, int firstcol, bool newline) { - extern int get_message_window_height(); - wattrset( Message_Window, curs_fg_attr(color) ); if (!firstcol) @@ -269,7 +265,7 @@ void message_out(int which_line, int color, const char *s, int firstcol, mvwaddstr(Message_Window, which_line, firstcol, s); - if (newline && which_line == get_message_window_height() - 1) + if (newline && which_line == crawl_view.msgsz.y - 1) { int x, y; getyx(Message_Window, y, x); @@ -282,7 +278,7 @@ void message_out(int which_line, int color, const char *s, int firstcol, { int x, y; getyx(Message_Window, y, x); - move(y + VIEW_EY, x); + move(y + crawl_view.msgp.y - 1, crawl_view.msgp.x - 1 + x); } wrefresh(Message_Window); @@ -327,6 +323,7 @@ void unixcurses_startup( void ) scrollok(stdscr, TRUE); + crawl_view.init_geometry(); setup_message_window(); } diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc index c111aa5251..2797568046 100644 --- a/crawl-ref/source/libw32c.cc +++ b/crawl-ref/source/libw32c.cc @@ -559,11 +559,12 @@ void textcolor(int c) void clear_message_window() { - PCHAR_INFO pci = screen + SCREENINDEX(0, VIEW_EY); + PCHAR_INFO pci = screen + SCREENINDEX(crawl_view.msgp.x - 1, + crawl_view.msgp.y - 1); const int ncols = get_number_of_cols(); for (int x = 0; x < ncols; x++) { - for (int y = 0; y < get_message_window_height(); y++) + for (int y = 0; y < crawl_view.msgsz.y; y++) { pci->Char.AsciiChar = ' '; pci->Attributes = 0; @@ -574,39 +575,37 @@ void clear_message_window() COORD source; SMALL_RECT target; - source.X = 0; - source.Y = VIEW_EY; - target.Left = 0; - target.Top = VIEW_EY; + source.X = crawl_view.msgp.x - 1; + source.Y = crawl_view.msgp.y - 1; + target.Left = crawl_view.msgp.x - 1; + target.Top = crawl_view.msgp.y - 1; target.Right = get_number_of_cols() - 1; target.Bottom = get_number_of_lines() - 1; WriteConsoleOutput(outbuf, screen, screensize, source, &target); } -extern int get_message_window_height(); static void scroll_message_buffer() { - memmove( screen + SCREENINDEX(0, VIEW_EY), - screen + SCREENINDEX(0, VIEW_EY + 1), - get_message_window_height() * get_number_of_cols() - * sizeof(*screen) ); + memmove( screen + SCREENINDEX(crawl_view.msgp.x - 1, crawl_view.msgp.y - 1), + screen + SCREENINDEX(crawl_view.msgp.x - 1, crawl_view.msgp.y), + crawl_view.msgsz.y * get_number_of_cols() * sizeof(*screen) ); } static void scroll_message_window() { SMALL_RECT scroll_rectangle, clip_rectangle; - scroll_rectangle.Left = 0; - scroll_rectangle.Top = VIEW_EY + 1; + scroll_rectangle.Left = crawl_view.msgp.x - 1; + scroll_rectangle.Top = crawl_view.msgp.y; scroll_rectangle.Right = get_number_of_cols() - 1; scroll_rectangle.Bottom = get_number_of_lines() - 1; clip_rectangle = scroll_rectangle; - clip_rectangle.Top = VIEW_EY; + clip_rectangle.Top = crawl_view.msgp.y - 1; COORD new_origin; - new_origin.X = 0; - new_origin.Y = VIEW_EY; + new_origin.X = crawl_view.msgp.x; + new_origin.Y = crawl_view.msgp.y - 1; CHAR_INFO fill; fill.Char.AsciiChar = ' '; @@ -629,7 +628,8 @@ void message_out(int which_line, int colour, const char *s, int firstcol, if (!firstcol) firstcol = Options.delay_message_clear? 2 : 1; - gotoxy(firstcol, which_line + VIEW_EY + 1); + gotoxy(firstcol - 1 + crawl_view.viewp.x, + which_line + crawl_view.viewp.y); textcolor(colour); cprintf("%s", s); diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index b0a1e98159..a82d5ffd07 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -459,7 +459,7 @@ static void mpr_check_patterns(const std::string& message, int channel, static void mpr_store_messages(const std::string& message, int channel, int param) { - const int num_lines = get_message_window_height(); + const int num_lines = crawl_view.msgsz.y; // Prompt lines are presumably shown to / seen by the player accompanied // by a request for input, which should do the equivalent of a more(); to @@ -516,7 +516,7 @@ static int prepare_message(const std::string& imsg, int channel, int param) { mpr_check_patterns(imsg, channel, param); flush_input_buffer( FLUSH_ON_MESSAGE ); - const int num_lines = get_message_window_height(); + const int num_lines = crawl_view.msgsz.y; if (New_Message_Count == num_lines - 1) more(); @@ -610,7 +610,7 @@ void formatted_message_history(const std::string st, int channel, int param) flush_input_buffer( FLUSH_ON_MESSAGE ); - const int num_lines = get_message_window_height(); + const int num_lines = crawl_view.msgsz.y; if (New_Message_Count == num_lines - 1) more(); @@ -652,13 +652,13 @@ void more(void) char keypress = 0; if (Options.tutorial_left) - message_out(get_message_window_height() - 1, + message_out(crawl_view.msgsz.y - 1, LIGHTGREY, "--more-- " "Press Ctrl-P to reread old messages", 2, false); else - message_out(get_message_window_height() - 1, + message_out(crawl_view.msgsz.y - 1, LIGHTGREY, "--more--", 2, false); do diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc index 41c23abd48..463217bd98 100644 --- a/crawl-ref/source/monplace.cc +++ b/crawl-ref/source/monplace.cc @@ -372,8 +372,7 @@ bool place_monster(int &id, int mon_type, int power, char behaviour, int tpy = py; px = you.x_pos; py = you.y_pos; - you.x_pos = tpx; - you.y_pos = tpy; + you.moveto(tpx, tpy); } proxOK = (pval > 0); diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index f113605a5b..9439c2f9e8 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -65,7 +65,7 @@ void update_message_status() { textcolor(LIGHTBLUE); - gotoxy(75, 2); + gotoxy(crawl_view.hudp.x + 35, 2); if (SysEnv.have_messages) cprintf("(msg)"); else @@ -88,7 +88,7 @@ void update_turn_count() // FIXME: Create some kind of layout manager class so we can // templatise the heads-up display layout and stop hardcoding // these coords. - gotoxy(61, 10); + gotoxy(crawl_view.hudp.x + 21, 10); textcolor(LIGHTGREY); // Show the turn count starting from 1. You can still quit on turn 0. @@ -99,6 +99,8 @@ void print_stats(void) { textcolor(LIGHTGREY); + const int xcol = crawl_view.hudp.x; + // Displayed evasion is now tied to dex. if (you.redraw_dexterity) you.redraw_evasion = true; @@ -122,7 +124,7 @@ void print_stats(void) } } - gotoxy(44, 3); + gotoxy(xcol + 4, 3); cprintf( "%d", you.hp ); @@ -157,7 +159,7 @@ void print_stats(void) break; } } - gotoxy(47, 4); + gotoxy(xcol + 7, 4); cprintf( "%d", you.magic_points); @@ -183,7 +185,7 @@ void print_stats(void) if (you.max_strength > 72) you.max_strength = 72; - gotoxy(45, 7); + gotoxy(xcol + 5, 7); if (you.might) textcolor(LIGHTBLUE); // no end of effect warning @@ -216,7 +218,7 @@ void print_stats(void) if (you.max_intel > 72) you.max_intel = 72; - gotoxy(45, 8); + gotoxy(xcol + 5, 8); if (you.intel < you.max_intel) textcolor(YELLOW); @@ -245,7 +247,7 @@ void print_stats(void) if (you.max_dex > 72) you.max_dex = 72; - gotoxy(45, 9); + gotoxy(xcol + 5, 9); if (you.dex < you.max_dex) textcolor(YELLOW); @@ -266,7 +268,7 @@ void print_stats(void) if (you.redraw_armour_class) { - gotoxy(44, 5); + gotoxy(xcol + 4, 5); if (you.duration[DUR_STONEMAIL]) dur_colour( BLUE, (you.duration[DUR_STONEMAIL] <= 6) ); @@ -276,7 +278,7 @@ void print_stats(void) cprintf( "%d ", player_AC() ); textcolor( LIGHTGREY ); - gotoxy(50, 5); + gotoxy(xcol + 10, 5); if (you.duration[DUR_CONDENSATION_SHIELD]) //jmf: added 24mar2000 textcolor( LIGHTBLUE ); // no end of effect warning @@ -289,7 +291,7 @@ void print_stats(void) if (you.redraw_evasion) { - gotoxy(44, 6); + gotoxy(xcol + 4, 6); if (you.duration[DUR_FORESCRY]) textcolor(LIGHTBLUE); // no end of effect warning @@ -302,14 +304,14 @@ void print_stats(void) if (you.redraw_gold) { - gotoxy(46, 10); + gotoxy(xcol + 6, 10); cprintf( "%-8d", you.gold ); you.redraw_gold = 0; } if (you.redraw_experience) { - gotoxy(52, 11); + gotoxy(xcol + 12, 11); #if DEBUG_DIAGNOSTICS cprintf( "%d/%lu (%d/%d)", @@ -330,14 +332,14 @@ void print_stats(void) if (you.wield_change) { - gotoxy(40, 13); + gotoxy(xcol, 13); #ifdef UNIX clear_to_end_of_line(); #else cprintf(" "); #endif - gotoxy(40, 13); + gotoxy(xcol, 13); if (you.equip[EQ_WEAPON] != -1) { @@ -381,13 +383,13 @@ void print_stats(void) if (you.redraw_status_flags & REDRAW_LINE_1_MASK) { - gotoxy(40, 14); + gotoxy(xcol, 14); #ifdef UNIX clear_to_end_of_line(); #else cprintf( " " ); - gotoxy(40, 14); + gotoxy(xcol, 14); #endif switch (you.burden_state) @@ -442,13 +444,13 @@ void print_stats(void) if (you.redraw_status_flags & REDRAW_LINE_2_MASK) { - gotoxy(40, 15); + gotoxy(xcol, 15); #ifdef UNIX clear_to_end_of_line(); #else cprintf( " " ); - gotoxy(40, 15); + gotoxy(xcol, 15); #endif // Max length of this line = 8 * 5 - 1 = 39 @@ -534,13 +536,13 @@ void print_stats(void) if (you.redraw_status_flags & REDRAW_LINE_3_MASK) { - gotoxy(40, 16); + gotoxy(xcol, 16); #ifdef UNIX clear_to_end_of_line(); #else cprintf( " " ); - gotoxy(40, 16); + gotoxy(xcol, 16); #endif // Max length of this line = 7 * 5 + 3 - 1 = 37 @@ -615,7 +617,7 @@ void print_stats(void) #if DEBUG_DIAGNOSTICS // debug mode GPS - gotoxy(40, 17); + gotoxy(xcol, 17); cprintf( "Position (%2d,%2d)", you.x_pos, you.y_pos ); #endif diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 2542bf2da0..175db38a74 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -221,8 +221,7 @@ bool move_player_to_grid( int x, int y, bool stepped, bool allow_shift, } // have to move now so fall_into_a_pool will work - you.x_pos = x; - you.y_pos = y; + you.moveto(x, y); viewwindow( true, false ); @@ -271,8 +270,7 @@ bool move_player_to_grid( int x, int y, bool stepped, bool allow_shift, } // move the player to location - you.x_pos = x; - you.y_pos = y; + you.moveto(x, y); viewwindow( true, false ); @@ -3248,7 +3246,7 @@ void redraw_skill(const char your_name[kNameLen], const char class_name[80]) print_it[40] = 0; - gotoxy(40, 1); + gotoxy(crawl_view.hudp.x, 1); textcolor( LIGHTGREY ); cprintf( "%s", print_it ); @@ -5253,3 +5251,17 @@ bool player::is_icy() const { return (attribute[ATTR_TRANSFORMATION] == TRAN_ICE_BEAST); } + +void player::moveto(int x, int y) +{ + x_pos = x; + y_pos = y; + crawl_view.set_player_at(coord_def(x, y)); +} + +void player::moveto(const coord_def &c) +{ + x_pos = c.x; + y_pos = c.y; + crawl_view.set_player_at(c); +} diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc index 555c81ebf1..536260e79a 100644 --- a/crawl-ref/source/spells1.cc +++ b/crawl-ref/source/spells1.cc @@ -152,8 +152,7 @@ void random_blink(bool allow_partial_control, bool override_abyss) mpr("You blink."); succ = true; - you.x_pos = tx; - you.y_pos = ty; + you.moveto(tx, ty); if (you.level_type == LEVEL_ABYSS) { diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc index 548aa5de9f..8394a1c4f6 100644 --- a/crawl-ref/source/spells3.cc +++ b/crawl-ref/source/spells3.cc @@ -662,8 +662,7 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) if (is_controlled) { - you.x_pos = plox[0]; - you.y_pos = plox[1]; + you.moveto(plox[0], plox[1]); if ((grd[you.x_pos][you.y_pos] != DNGN_FLOOR && grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER) @@ -693,7 +692,12 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) && grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER) || mgrd[you.x_pos][you.y_pos] != NON_MONSTER || env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD); + + // Necessary to update the view centre. + you.moveto(you.pos()); } + crawl_view.set_player_at(you.pos(), true); + return !is_controlled; } diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc index 55c9379973..2d19836752 100644 --- a/crawl-ref/source/spells4.cc +++ b/crawl-ref/source/spells4.cc @@ -1490,10 +1490,7 @@ static int spell_swap_func(int x, int y, int pow, int message) int old_y = defender->y; if (swap_places( defender )) - { - you.x_pos = old_x; - you.y_pos = old_y; - } + you.moveto(old_x, old_y); } return 1; @@ -3038,8 +3035,7 @@ static int quadrant_blink(int x, int y, int pow, int garbage) break; } - you.x_pos = tx; - you.y_pos = ty; + you.moveto(tx, ty); return 1; } diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index af677759ce..e948dbbcdd 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -334,6 +334,8 @@ void cio_init() init_libdos(); #endif + crawl_view.init_geometry(); + io_inited = true; } @@ -1050,9 +1052,9 @@ void zap_los_monsters() { losight(env.show, grd, you.x_pos, you.y_pos); - for (int y = LOS_SY; y <= LOS_EY; ++y) + for (int y = crawl_view.vlos1.y; y <= crawl_view.vlos2.y; ++y) { - for (int x = LOS_SX; x <= LOS_EX; ++x) + for (int x = crawl_view.vlos1.x; x <= crawl_view.vlos2.x; ++x) { if (!in_vlos(x, y)) continue; diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index d88f2dcda1..bbfc298549 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -1042,8 +1042,9 @@ static void tag_read_you(struct tagHeader &th, char minorVersion) you.base_magic_points = unmarshallShort(th); you.base_magic_points2 = unmarshallShort(th); - you.x_pos = unmarshallShort(th); - you.y_pos = unmarshallShort(th); + const int x = unmarshallShort(th); + const int y = unmarshallShort(th); + you.moveto(x, y); unmarshallString(th, you.class_name, 30); diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index d253e2349e..c03decd6ff 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -28,6 +28,7 @@ #include <string.h> #include <cmath> +#include <sstream> #ifdef DOS #include <conio.h> @@ -41,6 +42,7 @@ #include "debug.h" #include "delay.h" #include "direct.h" +#include "dungeon.h" #include "initfile.h" #include "insult.h" #include "itemprop.h" @@ -76,6 +78,7 @@ static FixedVector<feature_def, NUM_FEATURES> Feature; typedef unsigned short screen_buffer_t; +crawl_view_geometry crawl_view; FixedArray < unsigned int, 20, 19 > Show_Backup; unsigned char show_green; @@ -92,11 +95,6 @@ static int get_item_dngn_code(const item_def &item); static void set_show_backup( int ex, int ey ); static int get_viewobj_flags(int viewobj); -int get_message_window_height() -{ - return (get_number_of_lines() - VIEW_EY); -} - unsigned get_envmap_char(int x, int y) { return static_cast<unsigned char>( @@ -1977,25 +1975,27 @@ void draw_border(void) clrscr(); redraw_skill( you.your_name, player_title() ); - gotoxy(40, 2); + const int xcol = crawl_view.hudp.x; + + gotoxy(xcol, 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(xcol, 3); cprintf("HP:"); + gotoxy(xcol, 4); cprintf("Magic:"); + gotoxy(xcol, 5); cprintf("AC:"); + gotoxy(xcol, 6); cprintf("EV:"); + gotoxy(xcol, 7); cprintf("Str:"); + gotoxy(xcol, 8); cprintf("Int:"); + gotoxy(xcol, 9); cprintf("Dex:"); + gotoxy(xcol, 10); cprintf("Gold:"); if (Options.show_turns) { - gotoxy(55, 10); + gotoxy(xcol + 15, 10); cprintf("Turn:"); } - gotoxy(40, 11); cprintf("Experience:"); - gotoxy(40, 12); cprintf("Level"); + gotoxy(xcol, 11); cprintf("Experience:"); + gotoxy(xcol, 12); cprintf("Level"); } // end draw_border() // Determines if the given feature is present at (x, y) in _grid_ coordinates. @@ -3549,9 +3549,6 @@ std::string screenshot( bool fullscreen ) { UNUSED( fullscreen ); - const int X_SIZE = VIEW_WIDTH; - const int Y_SIZE = VIEW_HEIGHT; - // [ds] Screenshots need to be straight ASCII. We will now proceed to force // the char and feature tables back to ASCII. FixedVector<unsigned char, NUM_DCHAR_TYPES> char_table_bk; @@ -3564,35 +3561,32 @@ std::string screenshot( bool fullscreen ) int firstpopline = -1; int lastpopline = -1; - char lines[Y_SIZE][X_SIZE + 1]; - for (int count_y = 0; count_y < Y_SIZE; count_y++) + std::vector<std::string> lines(crawl_view.viewsz.y); + for (int count_y = 1; count_y <= crawl_view.viewsz.y; count_y++) { int lastnonspace = -1; - for (int count_x = 0; count_x < X_SIZE; count_x++) + for (int count_x = 1; count_x <= crawl_view.viewsz.x; count_x++) { // in grid coords - const int gx = count_x + you.x_pos - 16; - const int gy = count_y + you.y_pos - 8; - - int ch = (!map_bounds(gx, gy)) - ? 0 - : (count_x < 8 || count_x > 24) - ? get_envmap_char(gx, gy) - : (gx == you.x_pos && gy == you.y_pos) - ? you.symbol - : get_screen_glyph(gx, gy); + const coord_def gc = view2grid(coord_def(count_x, count_y)); + int ch = + (!map_bounds(gc)) ? 0 + : (!crawl_view.in_grid_los(gc)) ? get_envmap_char(gc.x, gc.y) + : (gc == you.pos()) ? you.symbol + : get_screen_glyph(gc.x, gc.y); + if (ch && !isprint(ch)) { // [ds] Evil hack time again. Peek at grid, use that character. - int object = grd[gx][gy]; + int object = grd(gc); unsigned short glych, glycol = 0; if (object == DNGN_SECRET_DOOR) - object = grid_secret_door_appearance( gx, gy ); + object = grid_secret_door_appearance( gc.x, gc.y ); - get_symbol( gx, gy, object, &glych, &glycol ); + get_symbol( gc.x, gc.y, object, &glych, &glycol ); ch = glych; } @@ -3612,17 +3606,17 @@ std::string screenshot( bool fullscreen ) firstpopline = count_y; } - lines[count_y][count_x] = ch; + lines[count_y - 1] += ch; } - lines[count_y][lastnonspace + 1] = 0; + lines[count_y - 1].erase(lastnonspace + 1); } // Restore char and feature tables Options.char_table = char_table_bk; init_feature_table(); - std::string ss; + std::ostringstream ss; if (firstpopline != -1 && lastpopline != -1) { if (firstnonspace == -1) @@ -3630,17 +3624,14 @@ std::string screenshot( bool fullscreen ) for (int i = firstpopline; i <= lastpopline; ++i) { - char *curr = lines[i]; - - while (*curr && curr - lines[i] < firstnonspace) - curr++; - - ss += curr; - ss += EOL; + const std::string &ref = lines[i - 1]; + if (firstnonspace < (int) ref.length()) + ss << ref.substr(firstnonspace); + ss << EOL; } } - return (ss); + return (ss.str()); } static int viewmap_flash_colour() @@ -3667,11 +3658,9 @@ static int viewmap_flash_colour() //--------------------------------------------------------------- void viewwindow(bool draw_it, bool do_updates) { - const int X_SIZE = VIEW_WIDTH; - const int Y_SIZE = VIEW_HEIGHT; - const int BUFFER_SIZE = 1550; - - FixedVector < screen_buffer_t, BUFFER_SIZE > buffy; + std::vector<screen_buffer_t> buffy( + crawl_view.viewsz.y * crawl_view.viewsz.x * 2); + int count_x, count_y; losight( env.show, grd, you.x_pos, you.y_pos ); // must be done first @@ -3700,31 +3689,32 @@ void viewwindow(bool draw_it, bool do_updates) if (flash_colour == BLACK) flash_colour = viewmap_flash_colour(); - for (count_y = 0; count_y < Y_SIZE; count_y++) + for (count_y = 1; count_y <= crawl_view.viewsz.y; count_y++) { - for (count_x = 0; count_x < X_SIZE; count_x++) + for (count_x = 1; count_x <= crawl_view.viewsz.x; count_x++) { // in grid coords - const int gx = count_x + you.x_pos - 16; - const int gy = count_y + you.y_pos - 8; + const int gx = view2gridX(count_x); + const int gy = view2gridY(count_y); if (Options.tutorial_left && in_bounds(gx, gy) - && count_x >= 8 && count_x <= 24) + && crawl_view.in_grid_los(coord_def(gx, gy))) { const int ex = gx - you.x_pos + 9; const int ey = gy - you.y_pos + 9; - int object = env.show[ex][ey]; - + const int object = env.show[ex][ey]; if (object) { if (is_feature('>',gx,gy)) learned_something_new(TUT_SEEN_STAIRS,gx,gy); else if (is_feature('_',gx,gy)) learned_something_new(TUT_SEEN_ALTAR,gx,gy); - else if (grd[gx][gy] == DNGN_CLOSED_DOOR && see_grid( gx, gy )) + else if (grd[gx][gy] == DNGN_CLOSED_DOOR + && see_grid( gx, gy )) learned_something_new(TUT_SEEN_DOOR,gx,gy); - else if (grd[gx][gy] == DNGN_ENTER_SHOP && see_grid( gx, gy )) + else if (grd[gx][gy] == DNGN_ENTER_SHOP + && see_grid( gx, gy )) learned_something_new(TUT_SEEN_SHOP,gx,gy); } } @@ -3736,7 +3726,7 @@ void viewwindow(bool draw_it, bool do_updates) buffy[bufcount] = 0; buffy[bufcount + 1] = DARKGREY; } - else if (count_x < 8 || count_x > 24) + else if (!crawl_view.in_grid_los(coord_def(gx, gy))) { // outside the env.show area buffy[bufcount] = get_envmap_char( gx, gy ); @@ -3875,12 +3865,11 @@ void viewwindow(bool draw_it, bool do_updates) // avoiding unneeded draws when running if (!you.running || (you.running < 0 && Options.travel_delay > -1)) { - gotoxy( 1, 1 ); - bufcount = 0; - for (count_y = 0; count_y < Y_SIZE; count_y++) + for (count_y = 0; count_y < crawl_view.viewsz.y; count_y++) { - for (count_x = 0; count_x < X_SIZE; count_x++) + gotoxy( crawl_view.viewp.x, crawl_view.viewp.y + count_y ); + for (count_x = 0; count_x < crawl_view.viewsz.x; count_x++) { #ifdef USE_CURSES buffy[bufcount] = cset_adjust( buffy[bufcount] ); @@ -3889,8 +3878,6 @@ void viewwindow(bool draw_it, bool do_updates) putch( buffy[bufcount] ); bufcount += 2; } - - gotoxy( 1, count_y + 2 ); } } @@ -3899,3 +3886,129 @@ void viewwindow(bool draw_it, bool do_updates) #endif } } // end viewwindow() + +////////////////////////////////////////////////////////////////////////////// +// crawl_view_geometry + +const int crawl_view_geometry::message_min_lines; +const int crawl_view_geometry::hud_min_width; +const int crawl_view_geometry::hud_min_gutter; +const int crawl_view_geometry::hud_max_gutter; + +crawl_view_geometry::crawl_view_geometry() + : termsz(80, 24), viewp(1, 1), viewsz(33, 17), + hudp(40, 1), hudsz(41, 17), + msgp(1, viewp.y + viewsz.y), msgsz(80, 7) +{ +} + +void crawl_view_geometry::init_view() +{ + set_player_at(you.pos(), true); +} + +void crawl_view_geometry::set_player_at(const coord_def &c, bool centre) +{ + if (centre) + { + vgrdc = c; + } + else + { + const coord_def oldc = vgrdc; + const int xmarg = + Options.scroll_margin_x + LOS_RADIUS <= viewhalfsz.x + ? Options.scroll_margin_x + : viewhalfsz.x - LOS_RADIUS; + const int ymarg = + Options.scroll_margin_y + LOS_RADIUS <= viewhalfsz.y + ? Options.scroll_margin_y + : viewhalfsz.y - LOS_RADIUS; + + if (Options.view_lock_x) + vgrdc.x = c.x; + else if (c.x - LOS_RADIUS < vgrdc.x - viewhalfsz.x + xmarg) + vgrdc.x = c.x - LOS_RADIUS + viewhalfsz.x - xmarg; + else if (c.x + LOS_RADIUS > vgrdc.x + viewhalfsz.x - xmarg) + vgrdc.x = c.x + LOS_RADIUS - viewhalfsz.x + xmarg; + + if (Options.view_lock_y) + vgrdc.y = c.y; + else if (c.y - LOS_RADIUS < vgrdc.y - viewhalfsz.y + ymarg) + vgrdc.y = c.y - LOS_RADIUS + viewhalfsz.y - ymarg; + else if (c.y + LOS_RADIUS > vgrdc.y + viewhalfsz.y - ymarg) + vgrdc.y = c.y + LOS_RADIUS - viewhalfsz.y + ymarg; + + if (vgrdc != oldc && Options.center_on_scroll) + vgrdc = c; + + if (!Options.center_on_scroll && Options.symmetric_scroll + && !Options.view_lock_x + && !Options.view_lock_y + && (c - last_player_pos).abs() == 2 + && (vgrdc - oldc).abs() == 1) + { + const coord_def dp = c - last_player_pos; + const coord_def dc = vgrdc - oldc; + if ((dc.x == dp.x) != (dc.y == dp.y)) + vgrdc = oldc + dp; + } + } + + glos1 = c - coord_def(LOS_RADIUS, LOS_RADIUS); + glos2 = c + coord_def(LOS_RADIUS, LOS_RADIUS); + + vlos1 = glos1 - vgrdc + view_centre(); + vlos2 = glos2 - vgrdc + view_centre(); + + last_player_pos = c; +} + +void crawl_view_geometry::init_geometry() +{ + termsz = coord_def( get_number_of_cols(), get_number_of_lines() ); + + // If the terminal is too small, exit with an error. + if (termsz.x < 80 || termsz.y < 24) + end(1, false, "Terminal too small (%d,%d), need at least (80,24)", + termsz.x, termsz.y); + + + int freeheight = termsz.y - message_min_lines; + + // Make the viewport as tall as possible. + viewsz.y = freeheight < Options.view_max_height? + freeheight : Options.view_max_height; + + // Make sure we're odd-sized. + if (!(viewsz.y % 2)) + --viewsz.y; + + // The message pane takes all lines not used by the viewport. + msgp = coord_def(1, viewsz.y + 1); + msgsz = coord_def(termsz.x, termsz.y - viewsz.y); + + int freewidth = termsz.x - (hud_min_width + hud_min_gutter); + // Make the viewport as wide as possible. + viewsz.x = freewidth < Options.view_max_width? + freewidth : Options.view_max_width; + + if (!(viewsz.x % 2)) + --viewsz.x; + + // The hud appears after the viewport + gutter. + hudp = coord_def(viewsz.x + 1 + hud_min_gutter, 1); + + // HUD size never changes, but we may increase the gutter size (up to + // the current max of 6). + if (hudp.x + hudsz.x - 1 < termsz.x) + { + const int hudmarg = termsz.x - (hudp.x + hudsz.x - 1); + const int hud_increase_max = hud_max_gutter - hud_min_gutter; + hudp.x += hudmarg > hud_increase_max? hud_increase_max : hudmarg; + } + + viewhalfsz = viewsz / 2; + + init_view(); +} diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h index c303619497..ce31141055 100644 --- a/crawl-ref/source/view.h +++ b/crawl-ref/source/view.h @@ -23,8 +23,6 @@ void init_char_table(char_set_type set); void init_feature_table(); -int get_message_window_height(); - /* *********************************************************************** * called from: dump_screenshot - chardump * *********************************************************************** */ |