OSDN Git Service

397a25f2a6520a6022e335f4b3b8b05765d953c5
[hengbandforosx/hengbandosx.git] / src / window / main-window-util.cpp
1 #include "window/main-window-util.h"
2 #include "flavor/flavor-describer.h"
3 #include "flavor/object-flavor-types.h"
4 #include "floor/cave.h"
5 #include "floor/geometry.h"
6 #include "game-option/map-screen-options.h"
7 #include "game-option/special-options.h"
8 #include "grid/grid.h"
9 #include "monster-race/monster-race.h"
10 #include "player/player-status.h"
11 #include "system/floor-type-definition.h"
12 #include "system/monster-race-definition.h"
13 #include "system/object-type-definition.h"
14 #include "system/player-type-definition.h"
15 #include "term/gameterm.h"
16 #include "term/screen-processor.h"
17 #include "term/term-color-types.h"
18 #include "view/display-map.h"
19 #include "world/world.h"
20 #include <vector>
21
22 /*
23  * Dungeon size info
24  */
25 POSITION panel_row_min;
26 POSITION panel_row_max;
27 POSITION panel_col_min;
28 POSITION panel_col_max;
29 POSITION panel_col_prt;
30 POSITION panel_row_prt;
31
32 int match_autopick;
33 object_type *autopick_obj; /*!< 各種自動拾い処理時に使うオブジェクトポインタ */
34 int feat_priority; /*!< マップ縮小表示時に表示すべき地形の優先度を保管する */
35
36 static concptr simplify_list[][2] = {
37 #ifdef JP
38     { "の魔法書", "" }, { nullptr, nullptr }
39 #else
40     { "^Ring of ", "=" }, { "^Amulet of ", "\"" }, { "^Scroll of ", "?" }, { "^Scroll titled ", "?" }, { "^Wand of ", "-" }, { "^Rod of ", "-" },
41     { "^Staff of ", "_" }, { "^Potion of ", "!" }, { " Spellbook ", "" }, { "^Book of ", "" }, { " Magic [", "[" }, { " Book [", "[" }, { " Arts [", "[" },
42     { "^Set of ", "" }, { "^Pair of ", "" }, { nullptr, nullptr }
43 #endif
44 };
45
46 /*!
47  * @brief 画面左の能力値表示を行うために指定位置から13キャラ分を空白消去後指定のメッセージを明るい青で描画する /
48  * Print character info at given row, column in a 13 char field
49  * @param info 表示文字列
50  * @param row 描画列
51  * @param col 描画行
52  */
53 void print_field(concptr info, TERM_LEN row, TERM_LEN col)
54 {
55     c_put_str(TERM_WHITE, "             ", row, col);
56     c_put_str(TERM_L_BLUE, info, row, col);
57 }
58
59 /*
60  * Prints the map of the dungeon
61  *
62  * Note that, for efficiency, we contain an "optimized" version
63  * of both "lite_spot()" and "print_rel()", and that we use the
64  * "lite_spot()" function to display the player grid, if needed.
65  */
66 void print_map(player_type *player_ptr)
67 {
68     TERM_LEN wid, hgt;
69     term_get_size(&wid, &hgt);
70
71     wid -= COL_MAP + 2;
72     hgt -= ROW_MAP + 2;
73
74     int v;
75     (void)term_get_cursor(&v);
76
77     (void)term_set_cursor(0);
78
79     floor_type *floor_ptr = player_ptr->current_floor_ptr;
80     POSITION xmin = (0 < panel_col_min) ? panel_col_min : 0;
81     POSITION xmax = (floor_ptr->width - 1 > panel_col_max) ? panel_col_max : floor_ptr->width - 1;
82     POSITION ymin = (0 < panel_row_min) ? panel_row_min : 0;
83     POSITION ymax = (floor_ptr->height - 1 > panel_row_max) ? panel_row_max : floor_ptr->height - 1;
84
85     for (POSITION y = 1; y <= ymin - panel_row_prt; y++) {
86         term_erase(COL_MAP, y, wid);
87     }
88
89     for (POSITION y = ymax - panel_row_prt; y <= hgt; y++) {
90         term_erase(COL_MAP, y, wid);
91     }
92
93     for (POSITION y = ymin; y <= ymax; y++) {
94         for (POSITION x = xmin; x <= xmax; x++) {
95             TERM_COLOR a;
96             SYMBOL_CODE c;
97             TERM_COLOR ta;
98             SYMBOL_CODE tc;
99             map_info(player_ptr, y, x, &a, &c, &ta, &tc);
100             if (!use_graphics) {
101                 if (w_ptr->timewalk_m_idx)
102                     a = TERM_DARK;
103                 else if (is_invuln(player_ptr) || player_ptr->timewalk)
104                     a = TERM_WHITE;
105                 else if (player_ptr->wraith_form)
106                     a = TERM_L_DARK;
107             }
108
109             term_queue_bigchar(panel_col_of(x), y - panel_row_prt, a, c, ta, tc);
110         }
111     }
112
113     lite_spot(player_ptr, player_ptr->y, player_ptr->x);
114     (void)term_set_cursor(v);
115 }
116
117 static void display_shortened_item_name(player_type *player_ptr, object_type *o_ptr, int y)
118 {
119     char buf[MAX_NLEN];
120     describe_flavor(player_ptr, buf, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NAME_ONLY));
121     TERM_COLOR attr = tval_to_attr[enum2i(o_ptr->tval) % 128];
122
123     if (player_ptr->hallucinated) {
124         attr = TERM_WHITE;
125         strcpy(buf, _("何か奇妙な物", "something strange"));
126     }
127
128     char *c = buf;
129     for (c = buf; *c; c++) {
130         for (int i = 0; simplify_list[i][1]; i++) {
131             concptr org_w = simplify_list[i][0];
132
133             if (*org_w == '^') {
134                 if (c == buf)
135                     org_w++;
136                 else
137                     continue;
138             }
139
140             if (strncmp(c, org_w, strlen(org_w)))
141                 continue;
142
143             char *s = c;
144             concptr tmp = simplify_list[i][1];
145             while (*tmp)
146                 *s++ = *tmp++;
147             tmp = c + strlen(org_w);
148             while (*tmp)
149                 *s++ = *tmp++;
150             *s = '\0';
151         }
152     }
153
154     c = buf;
155     int len = 0;
156     /* 半角 12 文字分で切る */
157     while (*c) {
158 #ifdef JP
159         if (iskanji(*c)) {
160             if (len + 2 > 12)
161                 break;
162             c += 2;
163             len += 2;
164         } else
165 #endif
166         {
167             if (len + 1 > 12)
168                 break;
169             c++;
170             len++;
171         }
172     }
173
174     *c = '\0';
175     term_putstr(0, y, 12, attr, buf);
176 }
177
178 /*!
179  * @brief 縮小マップ表示 / Display a "small-scale" map of the dungeon in the active Term
180  * @param player_ptr プレイヤー情報への参照ポインタ
181  * @param cy 縮小マップ上のプレイヤーのy座標
182  * @param cx 縮小マップ上のプレイヤーのx座標
183  * @details
184  * メインウィンドウ('M'コマンド)、サブウィンドウ兼(縮小図)用。
185  * use_bigtile時に横の描画列数は1/2になる。
186  */
187 void display_map(player_type *player_ptr, int *cy, int *cx)
188 {
189     int i, j, x, y;
190
191     TERM_COLOR ta;
192     SYMBOL_CODE tc;
193
194     byte tp;
195
196     bool old_view_special_lite = view_special_lite;
197     bool old_view_granite_lite = view_granite_lite;
198
199     TERM_LEN border_width = use_bigtile ? 2 : 1; //!< @note 枠線幅
200     TERM_LEN hgt, wid, yrat, xrat;
201     term_get_size(&wid, &hgt);
202     hgt -= 2;
203     wid -= 12 + border_width * 2; //!< @note 描画桁数(枠線抜)
204     if (use_bigtile)
205         wid = wid / 2 - 1;
206
207     floor_type *floor_ptr = player_ptr->current_floor_ptr;
208     yrat = (floor_ptr->height + hgt - 1) / hgt;
209     xrat = (floor_ptr->width + wid - 1) / wid;
210     view_special_lite = false;
211     view_granite_lite = false;
212
213     using std::vector;
214     vector<vector<TERM_COLOR>> ma(hgt + 2, vector<TERM_COLOR>(wid + 2, TERM_WHITE));
215     vector<vector<SYMBOL_CODE>> mc(hgt + 2, vector<SYMBOL_CODE>(wid + 2, ' '));
216     vector<vector<byte>> mp(hgt + 2, vector<byte>(wid + 2, 0));
217     vector<vector<int>> match_autopick_yx(hgt + 2, vector<int>(wid + 2, -1));
218     vector<vector<object_type *>> object_autopick_yx(hgt + 2, vector<object_type *>(wid + 2, nullptr));
219
220     vector<vector<TERM_COLOR>> bigma(floor_ptr->height + 2, vector<TERM_COLOR>(floor_ptr->width + 2, TERM_WHITE));
221     vector<vector<SYMBOL_CODE>> bigmc(floor_ptr->height + 2, vector<SYMBOL_CODE>(floor_ptr->width + 2, ' '));
222     vector<vector<byte>> bigmp(floor_ptr->height + 2, vector<byte>(floor_ptr->width + 2, 0));
223
224     for (i = 0; i < floor_ptr->width; ++i) {
225         for (j = 0; j < floor_ptr->height; ++j) {
226             x = i / xrat + 1;
227             y = j / yrat + 1;
228
229             match_autopick = -1;
230             autopick_obj = nullptr;
231             feat_priority = -1;
232             map_info(player_ptr, j, i, &ta, &tc, &ta, &tc);
233             tp = (byte)feat_priority;
234             if (match_autopick != -1 && (match_autopick_yx[y][x] == -1 || match_autopick_yx[y][x] > match_autopick)) {
235                 match_autopick_yx[y][x] = match_autopick;
236                 object_autopick_yx[y][x] = autopick_obj;
237                 tp = 0x7f;
238             }
239
240             bigmc[j + 1][i + 1] = tc;
241             bigma[j + 1][i + 1] = ta;
242             bigmp[j + 1][i + 1] = tp;
243         }
244     }
245
246     for (j = 0; j < floor_ptr->height; ++j) {
247         for (i = 0; i < floor_ptr->width; ++i) {
248             x = i / xrat + 1;
249             y = j / yrat + 1;
250
251             tc = bigmc[j + 1][i + 1];
252             ta = bigma[j + 1][i + 1];
253             tp = bigmp[j + 1][i + 1];
254             if (mp[y][x] == tp) {
255                 int t;
256                 int cnt = 0;
257
258                 for (t = 0; t < 8; t++) {
259                     if (tc == bigmc[j + 1 + ddy_cdd[t]][i + 1 + ddx_cdd[t]] && ta == bigma[j + 1 + ddy_cdd[t]][i + 1 + ddx_cdd[t]])
260                         cnt++;
261                 }
262                 if (cnt <= 4)
263                     tp++;
264             }
265
266             if (mp[y][x] < tp) {
267                 mc[y][x] = tc;
268                 ma[y][x] = ta;
269                 mp[y][x] = tp;
270             }
271         }
272     }
273
274     x = wid + 1;
275     y = hgt + 1;
276
277     mc[0][0] = mc[0][x] = mc[y][0] = mc[y][x] = '+';
278     for (x = 1; x <= wid; x++)
279         mc[0][x] = mc[y][x] = '-';
280
281     for (y = 1; y <= hgt; y++)
282         mc[y][0] = mc[y][x] = '|';
283
284     for (y = 0; y < hgt + 2; ++y) {
285         term_gotoxy(COL_MAP, y);
286         for (x = 0; x < wid + 2; ++x) {
287             ta = ma[y][x];
288             tc = mc[y][x];
289             if (!use_graphics) {
290                 if (w_ptr->timewalk_m_idx)
291                     ta = TERM_DARK;
292                 else if (is_invuln(player_ptr) || player_ptr->timewalk)
293                     ta = TERM_WHITE;
294                 else if (player_ptr->wraith_form)
295                     ta = TERM_L_DARK;
296             }
297
298             term_add_bigch(ta, tc);
299         }
300     }
301
302     for (y = 1; y < hgt + 1; ++y) {
303         match_autopick = -1;
304         for (x = 1; x <= wid; x++) {
305             if (match_autopick_yx[y][x] != -1 && (match_autopick > match_autopick_yx[y][x] || match_autopick == -1)) {
306                 match_autopick = match_autopick_yx[y][x];
307                 autopick_obj = object_autopick_yx[y][x];
308             }
309         }
310
311         term_putstr(0, y, 12, 0, "            ");
312         if (match_autopick != -1)
313             display_shortened_item_name(player_ptr, autopick_obj, y);
314     }
315
316     (*cy) = player_ptr->y / yrat + 1 + ROW_MAP;
317     if (!use_bigtile)
318         (*cx) = player_ptr->x / xrat + 1 + COL_MAP;
319     else
320         (*cx) = (player_ptr->x / xrat + 1) * 2 + COL_MAP;
321
322     view_special_lite = old_view_special_lite;
323     view_granite_lite = old_view_granite_lite;
324 }
325
326 void set_term_color(player_type *player_ptr, POSITION y, POSITION x, TERM_COLOR *ap, SYMBOL_CODE *cp)
327 {
328     if (!player_bold(player_ptr, y, x))
329         return;
330
331     monster_race *r_ptr = &r_info[0];
332     *ap = r_ptr->x_attr;
333     *cp = r_ptr->x_char;
334     feat_priority = 31;
335 }
336
337 /*
338  * Calculate panel colum of a location in the map
339  */
340 int panel_col_of(int col)
341 {
342     col -= panel_col_min;
343     if (use_bigtile)
344         col *= 2;
345     return col + 13;
346 }