5 * @todo 1つ300行近い関数なので後ほど要分割
8 #include "autopick/autopick-describer.h"
9 #include "autopick/autopick-flags-table.h"
10 #include "autopick/autopick-key-flag-process.h"
11 #include "autopick/autopick-methods-table.h"
12 #include "autopick/autopick-util.h"
13 #include "system/angband.h"
14 #include "util/string-processor.h"
16 struct autopick_describer {
26 static void describe_autpick_jp(char *buff, const autopick_type &entry, autopick_describer *describer)
28 concptr before_str[100]{};
29 if (entry.has(FLG_COLLECTING)) {
30 before_str[describer->before_n++] = "収集中で既に持っているスロットにまとめられる";
33 if (entry.has(FLG_UNAWARE)) {
34 before_str[describer->before_n++] = "未鑑定でその効果も判明していない";
37 if (entry.has(FLG_UNIDENTIFIED)) {
38 before_str[describer->before_n++] = "未鑑定の";
41 if (entry.has(FLG_IDENTIFIED)) {
42 before_str[describer->before_n++] = "鑑定済みの";
45 if (entry.has(FLG_STAR_IDENTIFIED)) {
46 before_str[describer->before_n++] = "完全に鑑定済みの";
49 if (entry.has(FLG_BOOSTED)) {
50 before_str[describer->before_n++] = "ダメージダイスが通常より大きい";
51 describer->body_str = "武器";
54 if (entry.has(FLG_MORE_DICE)) {
55 static char more_than_desc_str[] = "___";
56 before_str[describer->before_n++] = "ダメージダイスの最大値が";
57 describer->body_str = "武器";
59 snprintf(more_than_desc_str, sizeof(more_than_desc_str), "%d", entry.dice);
60 before_str[describer->before_n++] = more_than_desc_str;
61 before_str[describer->before_n++] = "以上の";
64 if (entry.has(FLG_MORE_BONUS)) {
65 static char more_bonus_desc_str[] = "___";
66 before_str[describer->before_n++] = "修正値が(+";
68 snprintf(more_bonus_desc_str, sizeof(more_bonus_desc_str), "%d", entry.bonus);
69 before_str[describer->before_n++] = more_bonus_desc_str;
70 before_str[describer->before_n++] = ")以上の";
73 if (entry.has(FLG_WORTHLESS)) {
74 before_str[describer->before_n++] = "店で無価値と判定される";
77 if (entry.has(FLG_ARTIFACT)) {
78 before_str[describer->before_n++] = "アーティファクトの";
79 describer->body_str = "装備";
82 if (entry.has(FLG_EGO)) {
83 before_str[describer->before_n++] = "エゴアイテムの";
84 describer->body_str = "装備";
87 if (entry.has(FLG_GOOD)) {
88 before_str[describer->before_n++] = "上質の";
89 describer->body_str = "装備";
92 if (entry.has(FLG_NAMELESS)) {
93 before_str[describer->before_n++] = "エゴでもアーティファクトでもない";
94 describer->body_str = "装備";
97 if (entry.has(FLG_AVERAGE)) {
98 before_str[describer->before_n++] = "並の";
99 describer->body_str = "装備";
102 if (entry.has(FLG_RARE)) {
103 before_str[describer->before_n++] = "ドラゴン装備やカオス・ブレード等を含む珍しい";
104 describer->body_str = "装備";
107 if (entry.has(FLG_COMMON)) {
108 before_str[describer->before_n++] = "ありふれた(ドラゴン装備やカオス・ブレード等の珍しい物ではない)";
109 describer->body_str = "装備";
112 if (entry.has(FLG_WANTED)) {
113 before_str[describer->before_n++] = "ハンター事務所で賞金首とされている";
114 describer->body_str = "死体や骨";
117 if (entry.has(FLG_HUMAN)) {
118 before_str[describer->before_n++] = "悪魔魔法で使うための人間やヒューマノイドの";
119 describer->body_str = "死体や骨";
122 if (entry.has(FLG_UNIQUE)) {
123 before_str[describer->before_n++] = "ユニークモンスターの";
124 describer->body_str = "死体や骨";
127 if (entry.has(FLG_UNREADABLE)) {
128 before_str[describer->before_n++] = "あなたが読めない領域の";
129 describer->body_str = "魔法書";
132 if (entry.has(FLG_REALM1)) {
133 before_str[describer->before_n++] = "第一領域の";
134 describer->body_str = "魔法書";
137 if (entry.has(FLG_REALM2)) {
138 before_str[describer->before_n++] = "第二領域の";
139 describer->body_str = "魔法書";
142 if (entry.has(FLG_FIRST)) {
143 before_str[describer->before_n++] = "全4冊の内の1冊目の";
144 describer->body_str = "魔法書";
147 if (entry.has(FLG_SECOND)) {
148 before_str[describer->before_n++] = "全4冊の内の2冊目の";
149 describer->body_str = "魔法書";
152 if (entry.has(FLG_THIRD)) {
153 before_str[describer->before_n++] = "全4冊の内の3冊目の";
154 describer->body_str = "魔法書";
157 if (entry.has(FLG_FOURTH)) {
158 before_str[describer->before_n++] = "全4冊の内の4冊目の";
159 describer->body_str = "魔法書";
162 if (entry.has(FLG_ITEMS)) {
164 } /* Nothing to do */
165 else if (entry.has(FLG_WEAPONS)) {
166 describer->body_str = "武器";
167 } else if (entry.has(FLG_FAVORITE_WEAPONS)) {
168 describer->body_str = "得意武器";
169 } else if (entry.has(FLG_ARMORS)) {
170 describer->body_str = "防具";
171 } else if (entry.has(FLG_MISSILES)) {
172 describer->body_str = "弾や矢やクロスボウの矢";
173 } else if (entry.has(FLG_DEVICES)) {
174 describer->body_str = "巻物や魔法棒や杖やロッド";
175 } else if (entry.has(FLG_LIGHTS)) {
176 describer->body_str = "光源用のアイテム";
177 } else if (entry.has(FLG_JUNKS)) {
178 describer->body_str = "折れた棒等のガラクタ";
179 } else if (entry.has(FLG_CORPSES)) {
180 describer->body_str = "死体や骨";
181 } else if (entry.has(FLG_SPELLBOOKS)) {
182 describer->body_str = "魔法書";
183 } else if (entry.has(FLG_HAFTED)) {
184 describer->body_str = "鈍器";
185 } else if (entry.has(FLG_SHIELDS)) {
186 describer->body_str = "盾";
187 } else if (entry.has(FLG_BOWS)) {
188 describer->body_str = "スリングや弓やクロスボウ";
189 } else if (entry.has(FLG_RINGS)) {
190 describer->body_str = "指輪";
191 } else if (entry.has(FLG_AMULETS)) {
192 describer->body_str = "アミュレット";
193 } else if (entry.has(FLG_SUITS)) {
194 describer->body_str = "鎧";
195 } else if (entry.has(FLG_CLOAKS)) {
196 describer->body_str = "クローク";
197 } else if (entry.has(FLG_HELMS)) {
198 describer->body_str = "ヘルメットや冠";
199 } else if (entry.has(FLG_GLOVES)) {
200 describer->body_str = "籠手";
201 } else if (entry.has(FLG_BOOTS)) {
202 describer->body_str = "ブーツ";
206 if (!describer->before_n) {
209 for (int i = 0; i < describer->before_n && before_str[i]; i++) {
210 strcat(buff, before_str[i]);
214 strcat(buff, describer->body_str);
216 if (*describer->str) {
217 if (*describer->str == '^') {
219 describer->top = true;
222 strcat(buff, "で、名前が「");
223 angband_strcat(buff, describer->str, (MAX_NLEN - MAX_INSCRIPTION));
224 if (describer->top) {
225 strcat(buff, "」で始まるもの");
227 strcat(buff, "」を含むもの");
231 if (describer->insc) {
232 char tmp[MAX_INSCRIPTION + 1] = "";
233 angband_strcat(tmp, describer->insc, MAX_INSCRIPTION);
234 angband_strcat(buff, format("に「%s」", tmp), MAX_INSCRIPTION + 6);
236 if (str_find(describer->insc, "%%all")) {
237 strcat(buff, "(%%allは全能力を表す英字の記号で置換)");
238 } else if (str_find(describer->insc, "%all")) {
239 strcat(buff, "(%allは全能力を表す記号で置換)");
240 } else if (str_find(describer->insc, "%%")) {
241 strcat(buff, "(%%は追加能力を表す英字の記号で置換)");
242 } else if (str_find(describer->insc, "%")) {
243 strcat(buff, "(%は追加能力を表す記号で置換)");
246 strcat(buff, "と刻んで");
251 if (describer->act & DONT_AUTOPICK) {
252 strcat(buff, "放置する。");
253 } else if (describer->act & DO_AUTODESTROY) {
254 strcat(buff, "破壊する。");
255 } else if (describer->act & DO_QUERY_AUTOPICK) {
256 strcat(buff, "確認の後に拾う。");
261 if (describer->act & DO_DISPLAY) {
262 if (describer->act & DONT_AUTOPICK) {
263 strcat(buff, "全体マップ('M')で'N'を押したときに表示する。");
264 } else if (describer->act & DO_AUTODESTROY) {
265 strcat(buff, "全体マップ('M')で'K'を押したときに表示する。");
267 strcat(buff, "全体マップ('M')で'M'を押したときに表示する。");
270 strcat(buff, "全体マップには表示しない。");
275 void describe_autopick_en(char *buff, const autopick_type &entry, autopick_describer *describer)
277 concptr before_str[20]{};
278 concptr after_str[20]{};
279 concptr which_str[20]{};
280 concptr whose_str[20]{};
281 concptr whose_arg_str[20]{};
282 char arg_str[2][24]{};
283 int after_n = 0, which_n = 0, whose_n = 0, arg_n = 0;
284 if (entry.has(FLG_COLLECTING)) {
285 which_str[which_n++] = "can be absorbed into an existing inventory list slot";
288 if (entry.has(FLG_UNAWARE)) {
289 before_str[describer->before_n++] = "unidentified";
290 whose_str[whose_n] = "basic abilities are not known";
291 whose_arg_str[whose_n] = "";
295 if (entry.has(FLG_UNIDENTIFIED)) {
296 before_str[describer->before_n++] = "unidentified";
299 if (entry.has(FLG_IDENTIFIED)) {
300 before_str[describer->before_n++] = "identified";
303 if (entry.has(FLG_STAR_IDENTIFIED)) {
304 before_str[describer->before_n++] = "fully identified";
307 if (entry.has(FLG_RARE)) {
308 before_str[describer->before_n++] = "very rare";
309 after_str[after_n++] = "such as Dragon armor, Blades of Chaos, etc.";
312 if (entry.has(FLG_COMMON)) {
313 before_str[describer->before_n++] = "relatively common";
314 after_str[after_n++] = "compared to very rare Dragon armor, Blades of Chaos, etc.";
317 if (entry.has(FLG_WORTHLESS)) {
318 before_str[describer->before_n++] = "worthless";
319 which_str[which_n++] = "can not be sold at stores";
322 if (entry.has(FLG_ARTIFACT)) {
323 before_str[describer->before_n++] = "artifact";
326 if (entry.has(FLG_EGO)) {
327 before_str[describer->before_n++] = "ego";
330 if (entry.has(FLG_GOOD)) {
331 which_str[which_n++] = "are of good quality";
334 if (entry.has(FLG_NAMELESS)) {
335 which_str[which_n++] = "are neither ego items nor artifacts";
338 if (entry.has(FLG_AVERAGE)) {
339 which_str[which_n++] = "are of average quality";
342 if (entry.has(FLG_BOOSTED)) {
343 describer->body_str = "weapons";
344 whose_str[whose_n] = "damage dice is bigger than normal";
345 whose_arg_str[whose_n] = "";
349 if (entry.has(FLG_MORE_DICE)) {
350 describer->body_str = "weapons";
351 whose_str[whose_n] = "maximum damage from dice is bigger than ";
352 if (arg_n < (int)(sizeof(arg_str) / sizeof(arg_str[0]))) {
353 snprintf(arg_str[arg_n], sizeof(arg_str[arg_n]), "%d", entry.dice);
354 whose_arg_str[whose_n] = arg_str[arg_n];
357 whose_arg_str[whose_n] = "garbled";
362 if (entry.has(FLG_MORE_BONUS)) {
363 whose_str[whose_n] = "magical bonuses are bigger than (+";
364 if (arg_n < (int)(sizeof(arg_str) / sizeof(arg_str[0]))) {
365 snprintf(arg_str[arg_n], sizeof(arg_str[arg_n]), "%d)", entry.bonus);
366 whose_arg_str[whose_n] = arg_str[arg_n];
369 whose_arg_str[whose_n] = "garbled)";
374 if (entry.has(FLG_WANTED)) {
375 describer->body_str = "corpses or skeletons";
376 which_str[which_n++] = "are wanted at the Hunter's Office";
379 if (entry.has(FLG_HUMAN)) {
380 before_str[describer->before_n++] = "humanoid";
381 describer->body_str = "corpses or skeletons";
382 which_str[which_n++] = "can be used for Daemon magic";
385 if (entry.has(FLG_UNIQUE)) {
386 before_str[describer->before_n++] = "unique monsters'";
387 describer->body_str = "corpses or skeletons";
390 if (entry.has(FLG_UNREADABLE)) {
391 describer->body_str = "spellbooks";
392 after_str[after_n++] = "of different realms from yours";
395 if (entry.has(FLG_REALM1)) {
396 describer->body_str = "spellbooks";
397 after_str[after_n++] = "of your first realm";
400 if (entry.has(FLG_REALM2)) {
401 describer->body_str = "spellbooks";
402 after_str[after_n++] = "of your second realm";
405 if (entry.has(FLG_FIRST)) {
406 before_str[describer->before_n++] = "first one of four";
407 describer->body_str = "spellbooks";
410 if (entry.has(FLG_SECOND)) {
411 before_str[describer->before_n++] = "second one of four";
412 describer->body_str = "spellbooks";
415 if (entry.has(FLG_THIRD)) {
416 before_str[describer->before_n++] = "third one of four";
417 describer->body_str = "spellbooks";
420 if (entry.has(FLG_FOURTH)) {
421 before_str[describer->before_n++] = "fourth one of four";
422 describer->body_str = "spellbooks";
425 if (entry.has(FLG_ITEMS)) {
427 } /* Nothing to do */
428 else if (entry.has(FLG_WEAPONS)) {
429 describer->body_str = "weapons";
430 } else if (entry.has(FLG_FAVORITE_WEAPONS)) {
431 describer->body_str = "favorite weapons";
432 } else if (entry.has(FLG_ARMORS)) {
433 describer->body_str = "pieces of armor";
434 } else if (entry.has(FLG_MISSILES)) {
435 describer->body_str = "shots, arrows or crossbow bolts";
436 } else if (entry.has(FLG_DEVICES)) {
437 describer->body_str = "scrolls, wands, staffs or rods";
438 } else if (entry.has(FLG_LIGHTS)) {
439 describer->body_str = "light sources";
440 } else if (entry.has(FLG_JUNKS)) {
441 describer->body_str = "pieces of junk such as broken sticks";
442 } else if (entry.has(FLG_CORPSES)) {
443 describer->body_str = "corpses or skeletons";
444 } else if (entry.has(FLG_SPELLBOOKS)) {
445 describer->body_str = "spellbooks";
446 } else if (entry.has(FLG_HAFTED)) {
447 describer->body_str = "hafted weapons";
448 } else if (entry.has(FLG_SHIELDS)) {
449 describer->body_str = "shields";
450 } else if (entry.has(FLG_BOWS)) {
451 describer->body_str = "slings, bows or crossbows";
452 } else if (entry.has(FLG_RINGS)) {
453 describer->body_str = "rings";
454 } else if (entry.has(FLG_AMULETS)) {
455 describer->body_str = "amulets";
456 } else if (entry.has(FLG_SUITS)) {
457 describer->body_str = "pieces of body armor";
458 } else if (entry.has(FLG_CLOAKS)) {
459 describer->body_str = "cloaks";
460 } else if (entry.has(FLG_HELMS)) {
461 describer->body_str = "helms or crowns";
462 } else if (entry.has(FLG_GLOVES)) {
463 describer->body_str = "gloves";
464 } else if (entry.has(FLG_BOOTS)) {
465 describer->body_str = "boots";
468 if (*describer->str) {
469 if (*describer->str == '^') {
471 describer->top = true;
472 whose_str[whose_n] = "names begin with \"";
473 whose_arg_str[whose_n] = "";
476 which_str[which_n++] = "have \"";
480 if (describer->act & DONT_AUTOPICK) {
481 strcpy(buff, "Leave on floor ");
482 } else if (describer->act & DO_AUTODESTROY) {
483 strcpy(buff, "Destroy ");
484 } else if (describer->act & DO_QUERY_AUTOPICK) {
485 strcpy(buff, "Ask to pick up ");
487 strcpy(buff, "Pickup ");
490 if (describer->insc) {
491 strncat(buff, format("and inscribe \"%s\"", describer->insc).data(), 80);
493 if (angband_strstr(describer->insc, "%all")) {
494 strcat(buff, ", replacing %all with code string representing all abilities,");
495 } else if (angband_strstr(describer->insc, "%")) {
496 strcat(buff, ", replacing % with code string representing extra random abilities,");
499 strcat(buff, " on ");
502 if (!describer->before_n) {
503 strcat(buff, "all ");
505 for (int i = 0; i < describer->before_n && before_str[i]; i++) {
506 strcat(buff, before_str[i]);
511 strcat(buff, describer->body_str);
512 for (int i = 0; i < after_n && after_str[i]; i++) {
514 strcat(buff, after_str[i]);
517 for (int i = 0; i < whose_n && whose_str[i]; i++) {
519 strcat(buff, " whose ");
521 strcat(buff, ", and ");
524 strcat(buff, whose_str[i]);
525 strcat(buff, whose_arg_str[i]);
528 if (*describer->str && describer->top) {
529 strcat(buff, describer->str);
533 if (whose_n && which_n) {
534 strcat(buff, ", and ");
537 for (int i = 0; i < which_n && which_str[i]; i++) {
539 strcat(buff, " which ");
541 strcat(buff, ", and ");
544 strcat(buff, which_str[i]);
547 if (*describer->str && !describer->top) {
548 strncat(buff, describer->str, 80);
549 strcat(buff, "\" as part of their names");
554 if (describer->act & DO_DISPLAY) {
555 if (describer->act & DONT_AUTOPICK) {
556 strcat(buff, " Display these items when you press the N key in the full 'M'ap.");
557 } else if (describer->act & DO_AUTODESTROY) {
558 strcat(buff, " Display these items when you press the K key in the full 'M'ap.");
560 strcat(buff, " Display these items when you press the M key in the full 'M'ap.");
563 strcat(buff, " Not displayed in the full map.");
569 * @brief Describe which kind of object is Auto-picked/destroyed
571 void describe_autopick(char *buff, const autopick_type &entry)
573 //! @note autopick_describer::str は non-nullable、autopick_describer::insc は nullable という制約がある
574 autopick_describer describer;
575 describer.str = entry.name.data();
576 describer.act = entry.action;
577 describer.insc = entry.insc.empty() ? nullptr : entry.insc.data();
578 describer.top = false;
579 describer.before_n = 0;
580 describer.body_str = _("アイテム", "items");
582 describe_autpick_jp(buff, entry, &describer);
584 describe_autopick_en(buff, entry, &describer);