OSDN Git Service

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