3 * @brief 自動拾い機能の実装 / Object Auto-picker/Destroyer
6 * Copyright (c) 2002 Mogami\n
8 * This software may be copied and distributed for educational, research, and\n
9 * not for profit purposes provided that this copyright and statement are\n
10 * included in all such copies.\n
11 * 2014 Deskull rearranged comment for Doxygen.\n
16 #include "autopick/autopick-key-table.h"
18 #include "autopick/autopick.h"
20 #include "core/show-file.h"
21 #include "cmd/cmd-save.h"
22 #include "io/read-pref-file.h"
26 #include "market/store.h"
27 #include "player-status.h"
28 #include "player-move.h"
29 #include "player-class.h"
30 #include "player-race.h"
31 #include "player-inventory.h"
32 #include "view/display-player.h"
33 #include "object/object-kind.h"
34 #include "object-ego.h"
35 #include "object-flavor.h"
36 #include "object-hook.h"
42 #include "monsterrace.h"
43 #include "view-mainwindow.h" // 暫定。後で消す
45 static GAME_TEXT KEY_ALL[] = _("すべての", "all");
46 static GAME_TEXT KEY_UNAWARE[] = _("未判明の", "unaware");
47 static GAME_TEXT KEY_UNIDENTIFIED[] = _("未鑑定の", "unidentified");
48 static GAME_TEXT KEY_IDENTIFIED[] = _("鑑定済みの", "identified");
49 static GAME_TEXT KEY_STAR_IDENTIFIED[] = _("*鑑定*済みの", "*identified*");
50 static GAME_TEXT KEY_COLLECTING[] = _("収集中の", "collecting");
51 static GAME_TEXT KEY_ARTIFACT[] = _("アーティファクト", "artifact");
52 static GAME_TEXT KEY_EGO[] = _("エゴ", "ego");
53 static GAME_TEXT KEY_GOOD[] = _("上質の", "good");
54 static GAME_TEXT KEY_NAMELESS[] = _("無銘の", "nameless");
55 static GAME_TEXT KEY_AVERAGE[] = _("並の", "average");
56 static GAME_TEXT KEY_WORTHLESS[] = _("無価値の", "worthless");
57 static GAME_TEXT KEY_RARE[] = _("レアな", "rare");
58 static GAME_TEXT KEY_COMMON[] = _("ありふれた", "common");
59 static GAME_TEXT KEY_BOOSTED[] = _("ダイス目の違う", "dice boosted");
60 static GAME_TEXT KEY_MORE_THAN[] = _("ダイス目", "more than");
61 static GAME_TEXT KEY_DICE[] = _("以上の", "dice");
62 static GAME_TEXT KEY_MORE_BONUS[] = _("修正値", "more bonus than");
63 static GAME_TEXT KEY_MORE_BONUS2[] = _("以上の", "");
64 static GAME_TEXT KEY_WANTED[] = _("賞金首の", "wanted");
65 static GAME_TEXT KEY_UNIQUE[] = _("ユニーク・モンスターの", "unique monster's");
66 static GAME_TEXT KEY_HUMAN[] = _("人間の", "human");
67 static GAME_TEXT KEY_UNREADABLE[] = _("読めない", "unreadable");
68 static GAME_TEXT KEY_REALM1[] = _("第一領域の", "first realm's");
69 static GAME_TEXT KEY_REALM2[] = _("第二領域の", "second realm's");
70 static GAME_TEXT KEY_FIRST[] = _("1冊目の", "first");
71 static GAME_TEXT KEY_SECOND[] = _("2冊目の", "second");
72 static GAME_TEXT KEY_THIRD[] = _("3冊目の", "third");
73 static GAME_TEXT KEY_FOURTH[] = _("4冊目の", "fourth");
74 static GAME_TEXT KEY_ITEMS[] = _("アイテム", "items");
75 static GAME_TEXT KEY_WEAPONS[] = _("武器", "weapons");
76 static GAME_TEXT KEY_FAVORITE_WEAPONS[] = _("得意武器", "favorite weapons");
77 static GAME_TEXT KEY_ARMORS[] = _("防具", "armors");
78 static GAME_TEXT KEY_MISSILES[] = _("矢", "missiles");
79 static GAME_TEXT KEY_DEVICES[] = _("魔法アイテム", "magical devices");
80 static GAME_TEXT KEY_LIGHTS[] = _("光源", "lights");
81 static GAME_TEXT KEY_JUNKS[] = _("がらくた", "junks");
82 static GAME_TEXT KEY_CORPSES[] = _("死体や骨", "corpses or skeletons");
83 static GAME_TEXT KEY_SPELLBOOKS[] = _("魔法書", "spellbooks");
84 static GAME_TEXT KEY_HAFTED[] = _("鈍器", "hafted weapons");
85 static GAME_TEXT KEY_SHIELDS[] = _("盾", "shields");
86 static GAME_TEXT KEY_BOWS[] = _("弓", "bows");
87 static GAME_TEXT KEY_RINGS[] = _("指輪", "rings");
88 static GAME_TEXT KEY_AMULETS[] = _("アミュレット", "amulets");
89 static GAME_TEXT KEY_SUITS[] = _("鎧", "suits");
90 static GAME_TEXT KEY_CLOAKS[] = _("クローク", "cloaks");
91 static GAME_TEXT KEY_HELMS[] = _("兜", "helms");
92 static GAME_TEXT KEY_GLOVES[] = _("籠手", "gloves");
93 static GAME_TEXT KEY_BOOTS[] = _("靴", "boots");
95 #define MAX_AUTOPICK_DEFAULT 200
98 #define PT_WITH_PNAME 1
100 #define MAX_YANK MAX_LINELEN
101 #define MAX_LINES 3000
103 #define MARK_MARK 0x01
104 #define MARK_BY_SHIFT 0x02
106 #define LSTAT_BYPASS 0x01
107 #define LSTAT_EXPRESSION 0x02
108 #define LSTAT_AUTOREGISTER 0x04
110 #define QUIT_WITHOUT_SAVE 1
111 #define QUIT_AND_SAVE 2
114 * Dirty flag for text editor
116 #define DIRTY_ALL 0x0001
117 #define DIRTY_MODE 0x0004
118 #define DIRTY_SCREEN 0x0008
119 #define DIRTY_NOT_FOUND 0x0010
120 #define DIRTY_NO_SEARCH 0x0020
121 #define DIRTY_EXPRESSION 0x0040
122 #define DIRTY_SKIP_INACTIVE 0x0080
123 #define DIRTY_INACTIVE 0x0100
125 #define DESCRIPT_HGT 3
127 #define MATCH_KEY(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
128 ? (ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
129 #define MATCH_KEY2(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
130 ? (prev_ptr = ptr, ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
133 #define ADD_KEY(KEY) strcat(ptr, KEY)
135 #define ADD_KEY(KEY) (strcat(ptr, KEY), strcat(ptr, " "))
137 #define ADD_KEY2(KEY) strcat(ptr, KEY)
139 #define ADD_FLG(FLG) (entry->flag[FLG / 32] |= (1L << (FLG % 32)))
140 #define REM_FLG(FLG) (entry->flag[FLG / 32] &= ~(1L << (FLG % 32)))
141 #define ADD_FLG_NOUN(FLG) (ADD_FLG(FLG), prev_flg = FLG)
142 #define IS_FLG(FLG) (entry->flag[FLG / 32] & (1L << (FLG % 32)))
145 static char kanji_colon[] = ":";
149 * 自動拾い/破壊設定のリストに関する変数 / List for auto-picker/destroyer entries
151 int max_autopick = 0; /*!< 現在登録している自動拾い/破壊設定の数 */
152 int max_max_autopick = 0; /*!< 自動拾い/破壊設定の限界数 */
153 autopick_type *autopick_list = NULL; /*!< 自動拾い/破壊設定構造体のポインタ配列 */
156 * Automatically destroy an item if it is to be destroyed
158 * When always_pickup is 'yes', we disable auto-destroyer function of
159 * auto-picker/destroyer, and do only easy-auto-destroyer.
161 static object_type autopick_last_destroyed_object;
164 * Struct for yank buffer
166 typedef struct chain_str {
167 struct chain_str *next;
172 * Data struct for text editor
178 int old_wid, old_hgt;
180 int old_upper, old_left;
184 object_type *search_o_ptr;
186 concptr last_destroyed;
188 chain_str_type *yank;
192 byte states[MAX_LINES];
203 * Editor command id's
206 #define EC_SAVEQUIT 2
224 #define EC_KILL_LINE 20
225 #define EC_DELETE_CHAR 21
226 #define EC_BACKSPACE 22
227 #define EC_SEARCH_STR 23
228 #define EC_SEARCH_FORW 24
229 #define EC_SEARCH_BACK 25
230 #define EC_SEARCH_OBJ 26
231 #define EC_SEARCH_DESTROYED 27
232 #define EC_INSERT_OBJECT 28
233 #define EC_INSERT_DESTROYED 29
234 #define EC_INSERT_BLOCK 30
235 #define EC_INSERT_MACRO 31
236 #define EC_INSERT_KEYMAP 32
237 #define EC_CL_AUTOPICK 33
238 #define EC_CL_DESTROY 34
239 #define EC_CL_LEAVE 35
240 #define EC_CL_QUERY 36
241 #define EC_CL_NO_DISP 37
242 #define EC_OK_COLLECTING 38
243 #define EC_IK_UNAWARE 39
244 #define EC_IK_UNIDENTIFIED 40
245 #define EC_IK_IDENTIFIED 41
246 #define EC_IK_STAR_IDENTIFIED 42
247 #define EC_OK_BOOSTED 43
248 #define EC_OK_MORE_DICE 44
249 #define EC_OK_MORE_BONUS 45
250 #define EC_OK_WORTHLESS 46
251 #define EC_OK_ARTIFACT 47
253 #define EC_OK_GOOD 49
254 #define EC_OK_NAMELESS 50
255 #define EC_OK_AVERAGE 51
256 #define EC_OK_RARE 52
257 #define EC_OK_COMMON 53
258 #define EC_OK_WANTED 54
259 #define EC_OK_UNIQUE 55
260 #define EC_OK_HUMAN 56
261 #define EC_OK_UNREADABLE 57
262 #define EC_OK_REALM1 58
263 #define EC_OK_REALM2 59
264 #define EC_OK_FIRST 60
265 #define EC_OK_SECOND 61
266 #define EC_OK_THIRD 62
267 #define EC_OK_FOURTH 63
268 #define EC_KK_WEAPONS 64
269 #define EC_KK_FAVORITE_WEAPONS 65
270 #define EC_KK_ARMORS 66
271 #define EC_KK_MISSILES 67
272 #define EC_KK_DEVICES 68
273 #define EC_KK_LIGHTS 69
274 #define EC_KK_JUNKS 70
275 #define EC_KK_CORPSES 71
276 #define EC_KK_SPELLBOOKS 72
277 #define EC_KK_SHIELDS 73
278 #define EC_KK_BOWS 74
279 #define EC_KK_RINGS 75
280 #define EC_KK_AMULETS 76
281 #define EC_KK_SUITS 77
282 #define EC_KK_CLOAKS 78
283 #define EC_KK_HELMS 79
284 #define EC_KK_GLOVES 80
285 #define EC_KK_BOOTS 81
287 static GAME_TEXT MN_QUIT[] = _("セーブ無しで終了", "Quit without save");
288 static GAME_TEXT MN_SAVEQUIT[] = _("セーブして終了", "Save & Quit");
289 static GAME_TEXT MN_REVERT[] = _("全ての変更を破棄", "Revert all changes");
290 static GAME_TEXT MN_HELP[] = _("ヘルプ", "Help");
292 static GAME_TEXT MN_MOVE[] = _("カーソル移動", "Move cursor");
293 static GAME_TEXT MN_LEFT[] = _("左 (←矢印キー)", "Left (Left Arrow key)");
294 static GAME_TEXT MN_DOWN[] = _("下 (↓矢印キー)", "Down (Down Arrow key)");
295 static GAME_TEXT MN_UP[] = _("上 (↑矢印キー)", "Up (Up Arrow key)");
296 static GAME_TEXT MN_RIGHT[] = _("右 (→矢印キー)", "Right (Right Arrow key)");
297 static GAME_TEXT MN_BOL[] = _("行の先頭", "Beggining of line");
298 static GAME_TEXT MN_EOL[] = _("行の終端", "End of line");
299 static GAME_TEXT MN_PGUP[] = _("上のページ (PageUpキー)", "Page up (PageUp key)");
300 static GAME_TEXT MN_PGDOWN[] = _("下のページ (PageDownキー)", "Page down(PageDown key)");
301 static GAME_TEXT MN_TOP[] = _("1行目へ移動 (Homeキー)", "Top (Home key)");
302 static GAME_TEXT MN_BOTTOM[] = _("最下行へ移動(Endキー)", "Bottom (End key)");
304 static GAME_TEXT MN_EDIT[] = _("編集", "Edit");
305 static GAME_TEXT MN_CUT[] = _("カット", "Cut");
306 static GAME_TEXT MN_COPY[] = _("コピー", "Copy");
307 static GAME_TEXT MN_PASTE[] = _("ペースト", "Paste");
308 static GAME_TEXT MN_BLOCK[] = _("選択範囲の指定", "Select block");
309 static GAME_TEXT MN_KILL_LINE[] = _("行の残りを削除", "Kill rest of line");
310 static GAME_TEXT MN_DELETE_CHAR[] = _("1文字削除", "Delete character");
311 static GAME_TEXT MN_BACKSPACE[] = _("バックスペース", "Backspace");
312 static GAME_TEXT MN_RETURN[] = _("改行", "Return");
314 static GAME_TEXT MN_SEARCH[] = _("検索", "Search");
315 static GAME_TEXT MN_SEARCH_STR[] = _("文字列で検索", "Search by string");
316 static GAME_TEXT MN_SEARCH_FORW[] = _("前方へ再検索", "Search foward");
317 static GAME_TEXT MN_SEARCH_BACK[] = _("後方へ再検索", "Search backward");
318 static GAME_TEXT MN_SEARCH_OBJ[] = _("アイテムを選択して検索", "Search by inventory object");
319 static GAME_TEXT MN_SEARCH_DESTROYED[] = _("自動破壊されたアイテムで検索", "Search by destroyed object");
321 static GAME_TEXT MN_INSERT[] = _("色々挿入", "Insert...");
322 static GAME_TEXT MN_INSERT_OBJECT[] = _("選択したアイテムの名前を挿入", "Insert name of choosen object");
323 static GAME_TEXT MN_INSERT_DESTROYED[] = _("自動破壊されたアイテムの名前を挿入", "Insert name of destroyed object");
324 static GAME_TEXT MN_INSERT_BLOCK[] = _("条件分岐ブロックの例を挿入", "Insert conditional block");
325 static GAME_TEXT MN_INSERT_MACRO[] = _("マクロ定義を挿入", "Insert a macro definition");
326 static GAME_TEXT MN_INSERT_KEYMAP[] = _("キーマップ定義を挿入", "Insert a keymap definition");
328 static GAME_TEXT MN_COMMAND_LETTER[] = _("拾い/破壊/放置の選択", "Command letter");
329 static GAME_TEXT MN_CL_AUTOPICK[] = _("「 」 (自動拾い)", "' ' (Auto pick)");
330 static GAME_TEXT MN_CL_DESTROY[] = _("「!」 (自動破壊)", "'!' (Auto destroy)");
331 static GAME_TEXT MN_CL_LEAVE[] = _("「~」 (放置)", "'~' (Leave it on the floor)");
332 static GAME_TEXT MN_CL_QUERY[] = _("「;」 (確認して拾う)", "';' (Query to pick up)");
333 static GAME_TEXT MN_CL_NO_DISP[] = _("「(」 (マップコマンドで表示しない)", "'(' (No display on the large map)");
335 static GAME_TEXT MN_ADJECTIVE_GEN[] = _("形容詞(一般)の選択", "Adjective (general)");
336 static GAME_TEXT MN_RARE[] = _("レアな (装備)", "rare (equipment)");
337 static GAME_TEXT MN_COMMON[] = _("ありふれた (装備)", "common (equipment)");
339 static GAME_TEXT MN_ADJECTIVE_SPECIAL[] = _("形容詞(特殊)の選択", "Adjective (special)");
340 static GAME_TEXT MN_BOOSTED[] = _("ダイス目の違う (武器)", "dice boosted (weapons)");
341 static GAME_TEXT MN_MORE_DICE[] = _("ダイス目 # 以上の (武器)", "more than # dice (weapons)");
342 static GAME_TEXT MN_MORE_BONUS[] = _("修正値 # 以上の (指輪等)", "more bonus than # (rings etc.)");
343 static GAME_TEXT MN_WANTED[] = _("賞金首の (死体)", "wanted (corpse)");
344 static GAME_TEXT MN_UNIQUE[] = _("ユニーク・モンスターの (死体)", "unique (corpse)");
345 static GAME_TEXT MN_HUMAN[] = _("人間の (死体)", "human (corpse)");
346 static GAME_TEXT MN_UNREADABLE[] = _("読めない (魔法書)", "unreadable (spellbooks)");
347 static GAME_TEXT MN_REALM1[] = _("第一領域の (魔法書)", "realm1 (spellbooks)");
348 static GAME_TEXT MN_REALM2[] = _("第二領域の (魔法書)", "realm2 (spellbooks)");
349 static GAME_TEXT MN_FIRST[] = _("1冊目の (魔法書)", "first (spellbooks)");
350 static GAME_TEXT MN_SECOND[] = _("2冊目の (魔法書)", "second (spellbooks)");
351 static GAME_TEXT MN_THIRD[] = _("3冊目の (魔法書)", "third (spellbooks)");
352 static GAME_TEXT MN_FOURTH[] = _("4冊目の (魔法書)", "fourth (spellbooks)");
354 static GAME_TEXT MN_NOUN[] = _("名詞の選択", "Keywords (noun)");
363 command_menu_type menu_data[] =
365 {MN_HELP, 0, -1, EC_HELP},
366 {MN_QUIT, 0, KTRL('q'), EC_QUIT},
367 {MN_SAVEQUIT, 0, KTRL('w'), EC_SAVEQUIT},
368 {MN_REVERT, 0, KTRL('z'), EC_REVERT},
370 {MN_EDIT, 0, -1, -1},
371 {MN_CUT, 1, KTRL('x'), EC_CUT},
372 {MN_COPY, 1, KTRL('c'), EC_COPY},
373 {MN_PASTE, 1, KTRL('v'), EC_PASTE},
374 {MN_BLOCK, 1, KTRL('g'), EC_BLOCK},
375 {MN_KILL_LINE, 1, KTRL('k'), EC_KILL_LINE},
376 {MN_DELETE_CHAR, 1, KTRL('d'), EC_DELETE_CHAR},
377 {MN_BACKSPACE, 1, KTRL('h'), EC_BACKSPACE},
378 {MN_RETURN, 1, KTRL('j'), EC_RETURN},
379 {MN_RETURN, 1, KTRL('m'), EC_RETURN},
381 {MN_SEARCH, 0, -1, -1},
382 {MN_SEARCH_STR, 1, KTRL('s'), EC_SEARCH_STR},
383 {MN_SEARCH_FORW, 1, -1, EC_SEARCH_FORW},
384 {MN_SEARCH_BACK, 1, KTRL('r'), EC_SEARCH_BACK},
385 {MN_SEARCH_OBJ, 1, KTRL('y'), EC_SEARCH_OBJ},
386 {MN_SEARCH_DESTROYED, 1, -1, EC_SEARCH_DESTROYED},
388 {MN_MOVE, 0, -1, -1},
389 {MN_LEFT, 1, KTRL('b'), EC_LEFT},
390 {MN_DOWN, 1, KTRL('n'), EC_DOWN},
391 {MN_UP, 1, KTRL('p'), EC_UP},
392 {MN_RIGHT, 1, KTRL('f'), EC_RIGHT},
393 {MN_BOL, 1, KTRL('a'), EC_BOL},
394 {MN_EOL, 1, KTRL('e'), EC_EOL},
395 {MN_PGUP, 1, KTRL('o'), EC_PGUP},
396 {MN_PGDOWN, 1, KTRL('l'), EC_PGDOWN},
397 {MN_TOP, 1, KTRL('t'), EC_TOP},
398 {MN_BOTTOM, 1, KTRL('u'), EC_BOTTOM},
400 {MN_INSERT, 0, -1, -1},
401 {MN_INSERT_OBJECT, 1, KTRL('i'), EC_INSERT_OBJECT},
402 {MN_INSERT_DESTROYED, 1, -1, EC_INSERT_DESTROYED},
403 {MN_INSERT_BLOCK, 1, -1, EC_INSERT_BLOCK},
404 {MN_INSERT_MACRO, 1, -1, EC_INSERT_MACRO},
405 {MN_INSERT_KEYMAP, 1, -1, EC_INSERT_KEYMAP},
407 {MN_ADJECTIVE_GEN, 0, -1, -1},
408 {KEY_UNAWARE, 1, -1, EC_IK_UNAWARE},
409 {KEY_UNIDENTIFIED, 1, -1, EC_IK_UNIDENTIFIED},
410 {KEY_IDENTIFIED, 1, -1, EC_IK_IDENTIFIED},
411 {KEY_STAR_IDENTIFIED, 1, -1, EC_IK_STAR_IDENTIFIED},
412 {KEY_COLLECTING, 1, -1, EC_OK_COLLECTING},
413 {KEY_ARTIFACT, 1, -1, EC_OK_ARTIFACT},
414 {KEY_EGO, 1, -1, EC_OK_EGO},
415 {KEY_GOOD, 1, -1, EC_OK_GOOD},
416 {KEY_NAMELESS, 1, -1, EC_OK_NAMELESS},
417 {KEY_AVERAGE, 1, -1, EC_OK_AVERAGE},
418 {KEY_WORTHLESS, 1, -1, EC_OK_WORTHLESS},
419 {MN_RARE, 1, -1, EC_OK_RARE},
420 {MN_COMMON, 1, -1, EC_OK_COMMON},
422 {MN_ADJECTIVE_SPECIAL, 0, -1, -1},
423 {MN_BOOSTED, 1, -1, EC_OK_BOOSTED},
424 {MN_MORE_DICE, 1, -1, EC_OK_MORE_DICE},
425 {MN_MORE_BONUS, 1, -1, EC_OK_MORE_BONUS},
426 {MN_WANTED, 1, -1, EC_OK_WANTED},
427 {MN_UNIQUE, 1, -1, EC_OK_UNIQUE},
428 {MN_HUMAN, 1, -1, EC_OK_HUMAN},
429 {MN_UNREADABLE, 1, -1, EC_OK_UNREADABLE},
430 {MN_REALM1, 1, -1, EC_OK_REALM1},
431 {MN_REALM2, 1, -1, EC_OK_REALM2},
432 {MN_FIRST, 1, -1, EC_OK_FIRST},
433 {MN_SECOND, 1, -1, EC_OK_SECOND},
434 {MN_THIRD, 1, -1, EC_OK_THIRD},
435 {MN_FOURTH, 1, -1, EC_OK_FOURTH},
437 {MN_NOUN, 0, -1, -1},
438 {KEY_WEAPONS, 1, -1, EC_KK_WEAPONS},
439 {KEY_FAVORITE_WEAPONS, 1, -1, EC_KK_FAVORITE_WEAPONS},
440 {KEY_ARMORS, 1, -1, EC_KK_ARMORS},
441 {KEY_MISSILES, 1, -1, EC_KK_MISSILES},
442 {KEY_DEVICES, 1, -1, EC_KK_DEVICES},
443 {KEY_LIGHTS, 1, -1, EC_KK_LIGHTS},
444 {KEY_JUNKS, 1, -1, EC_KK_JUNKS},
445 {KEY_CORPSES, 1, -1, EC_KK_CORPSES},
446 {KEY_SPELLBOOKS, 1, -1, EC_KK_SPELLBOOKS},
447 {KEY_SHIELDS, 1, -1, EC_KK_SHIELDS},
448 {KEY_BOWS, 1, -1, EC_KK_BOWS},
449 {KEY_RINGS, 1, -1, EC_KK_RINGS},
450 {KEY_AMULETS, 1, -1, EC_KK_AMULETS},
451 {KEY_SUITS, 1, -1, EC_KK_SUITS},
452 {KEY_CLOAKS, 1, -1, EC_KK_CLOAKS},
453 {KEY_HELMS, 1, -1, EC_KK_HELMS},
454 {KEY_GLOVES, 1, -1, EC_KK_GLOVES},
455 {KEY_BOOTS, 1, -1, EC_KK_BOOTS},
457 {MN_COMMAND_LETTER, 0, -1, -1},
458 {MN_CL_AUTOPICK, 1, -1, EC_CL_AUTOPICK},
459 {MN_CL_DESTROY, 1, -1, EC_CL_DESTROY},
460 {MN_CL_LEAVE, 1, -1, EC_CL_LEAVE},
461 {MN_CL_QUERY, 1, -1, EC_CL_QUERY},
462 {MN_CL_NO_DISP, 1, -1, EC_CL_NO_DISP},
464 {MN_DELETE_CHAR, -1, 0x7F, EC_DELETE_CHAR},
470 * A function to create new entry
472 static bool autopick_new_entry(autopick_type *entry, concptr str, bool allow_default)
474 if (str[0] && str[1] == ':') switch (str[0])
477 case 'A': case 'P': case 'C':
481 entry->flag[0] = entry->flag[1] = 0L;
485 byte act = DO_AUTOPICK | DO_DISPLAY;
488 if ((act & DO_AUTOPICK) && *str == '!')
491 act |= DO_AUTODESTROY;
496 if ((act & DO_AUTOPICK) && *str == '~')
499 act |= DONT_AUTOPICK;
504 if ((act & DO_AUTOPICK) && *str == ';')
507 act |= DO_QUERY_AUTOPICK;
512 if ((act & DO_DISPLAY) && *str == '(')
523 char buf[MAX_LINELEN];
525 for (i = 0; *str; i++)
543 if (isupper(c)) c = (char)tolower(c);
549 if (!allow_default && *buf == 0) return FALSE;
550 if (*buf == 0 && insc) return FALSE;
552 concptr prev_ptr, ptr;
553 ptr = prev_ptr = buf;
554 concptr old_ptr = NULL;
555 while (old_ptr != ptr)
558 if (MATCH_KEY(KEY_ALL)) ADD_FLG(FLG_ALL);
559 if (MATCH_KEY(KEY_COLLECTING)) ADD_FLG(FLG_COLLECTING);
560 if (MATCH_KEY(KEY_UNAWARE)) ADD_FLG(FLG_UNAWARE);
561 if (MATCH_KEY(KEY_UNIDENTIFIED)) ADD_FLG(FLG_UNIDENTIFIED);
562 if (MATCH_KEY(KEY_IDENTIFIED)) ADD_FLG(FLG_IDENTIFIED);
563 if (MATCH_KEY(KEY_STAR_IDENTIFIED)) ADD_FLG(FLG_STAR_IDENTIFIED);
564 if (MATCH_KEY(KEY_BOOSTED)) ADD_FLG(FLG_BOOSTED);
566 /*** Weapons whose dd*ds is more than nn ***/
567 if (MATCH_KEY2(KEY_MORE_THAN))
572 while (' ' == *ptr) ptr++;
574 while ('0' <= *ptr && *ptr <= '9')
576 entry->dice = 10 * entry->dice + (*ptr - '0');
583 (void)MATCH_KEY(KEY_DICE);
584 ADD_FLG(FLG_MORE_DICE);
590 /*** Items whose magical bonus is more than n ***/
591 if (MATCH_KEY2(KEY_MORE_BONUS))
596 while (' ' == *ptr) ptr++;
598 while ('0' <= *ptr && *ptr <= '9')
600 entry->bonus = 10 * entry->bonus + (*ptr - '0');
608 (void)MATCH_KEY(KEY_MORE_BONUS2);
610 if (' ' == *ptr) ptr++;
612 ADD_FLG(FLG_MORE_BONUS);
618 if (MATCH_KEY(KEY_WORTHLESS)) ADD_FLG(FLG_WORTHLESS);
619 if (MATCH_KEY(KEY_EGO)) ADD_FLG(FLG_EGO);
620 if (MATCH_KEY(KEY_GOOD)) ADD_FLG(FLG_GOOD);
621 if (MATCH_KEY(KEY_NAMELESS)) ADD_FLG(FLG_NAMELESS);
622 if (MATCH_KEY(KEY_AVERAGE)) ADD_FLG(FLG_AVERAGE);
623 if (MATCH_KEY(KEY_RARE)) ADD_FLG(FLG_RARE);
624 if (MATCH_KEY(KEY_COMMON)) ADD_FLG(FLG_COMMON);
625 if (MATCH_KEY(KEY_WANTED)) ADD_FLG(FLG_WANTED);
626 if (MATCH_KEY(KEY_UNIQUE)) ADD_FLG(FLG_UNIQUE);
627 if (MATCH_KEY(KEY_HUMAN)) ADD_FLG(FLG_HUMAN);
628 if (MATCH_KEY(KEY_UNREADABLE)) ADD_FLG(FLG_UNREADABLE);
629 if (MATCH_KEY(KEY_REALM1)) ADD_FLG(FLG_REALM1);
630 if (MATCH_KEY(KEY_REALM2)) ADD_FLG(FLG_REALM2);
631 if (MATCH_KEY(KEY_FIRST)) ADD_FLG(FLG_FIRST);
632 if (MATCH_KEY(KEY_SECOND)) ADD_FLG(FLG_SECOND);
633 if (MATCH_KEY(KEY_THIRD)) ADD_FLG(FLG_THIRD);
634 if (MATCH_KEY(KEY_FOURTH)) ADD_FLG(FLG_FOURTH);
638 if (MATCH_KEY2(KEY_ARTIFACT)) ADD_FLG_NOUN(FLG_ARTIFACT);
640 if (MATCH_KEY2(KEY_ITEMS)) ADD_FLG_NOUN(FLG_ITEMS);
641 else if (MATCH_KEY2(KEY_WEAPONS)) ADD_FLG_NOUN(FLG_WEAPONS);
642 else if (MATCH_KEY2(KEY_FAVORITE_WEAPONS)) ADD_FLG_NOUN(FLG_FAVORITE_WEAPONS);
643 else if (MATCH_KEY2(KEY_ARMORS)) ADD_FLG_NOUN(FLG_ARMORS);
644 else if (MATCH_KEY2(KEY_MISSILES)) ADD_FLG_NOUN(FLG_MISSILES);
645 else if (MATCH_KEY2(KEY_DEVICES)) ADD_FLG_NOUN(FLG_DEVICES);
646 else if (MATCH_KEY2(KEY_LIGHTS)) ADD_FLG_NOUN(FLG_LIGHTS);
647 else if (MATCH_KEY2(KEY_JUNKS)) ADD_FLG_NOUN(FLG_JUNKS);
648 else if (MATCH_KEY2(KEY_CORPSES)) ADD_FLG_NOUN(FLG_CORPSES);
649 else if (MATCH_KEY2(KEY_SPELLBOOKS)) ADD_FLG_NOUN(FLG_SPELLBOOKS);
650 else if (MATCH_KEY2(KEY_HAFTED)) ADD_FLG_NOUN(FLG_HAFTED);
651 else if (MATCH_KEY2(KEY_SHIELDS)) ADD_FLG_NOUN(FLG_SHIELDS);
652 else if (MATCH_KEY2(KEY_BOWS)) ADD_FLG_NOUN(FLG_BOWS);
653 else if (MATCH_KEY2(KEY_RINGS)) ADD_FLG_NOUN(FLG_RINGS);
654 else if (MATCH_KEY2(KEY_AMULETS)) ADD_FLG_NOUN(FLG_AMULETS);
655 else if (MATCH_KEY2(KEY_SUITS)) ADD_FLG_NOUN(FLG_SUITS);
656 else if (MATCH_KEY2(KEY_CLOAKS)) ADD_FLG_NOUN(FLG_CLOAKS);
657 else if (MATCH_KEY2(KEY_HELMS)) ADD_FLG_NOUN(FLG_HELMS);
658 else if (MATCH_KEY2(KEY_GLOVES)) ADD_FLG_NOUN(FLG_GLOVES);
659 else if (MATCH_KEY2(KEY_BOOTS)) ADD_FLG_NOUN(FLG_BOOTS);
664 else if (ptr[0] == kanji_colon[0] && ptr[1] == kanji_colon[1])
667 else if (*ptr == '\0')
670 ADD_FLG_NOUN(FLG_ITEMS);
676 entry->flag[prev_flg / 32] &= ~(1L << (prev_flg % 32));
681 entry->name = string_make(ptr);
683 entry->insc = string_make(insc);
690 * Get auto-picker entry from o_ptr.
692 static void autopick_entry_from_object(player_type *player_ptr, autopick_type *entry, object_type *o_ptr)
694 /* Assume that object name is to be added */
698 /* エゴ銘が邪魔かもしれないので、デフォルトで「^」は付けない */
699 bool bol_mark = FALSE;
701 /* We can always use the ^ mark in English */
702 bool bol_mark = TRUE;
705 GAME_TEXT name_str[MAX_NLEN];
708 entry->insc = string_make(quark_str(o_ptr->inscription));
709 entry->action = DO_AUTOPICK | DO_DISPLAY;
710 entry->flag[0] = entry->flag[1] = 0L;
713 if (!object_is_aware(o_ptr))
715 ADD_FLG(FLG_UNAWARE);
718 else if (!object_is_known(o_ptr))
720 if (!(o_ptr->ident & IDENT_SENSE))
722 ADD_FLG(FLG_UNIDENTIFIED);
727 switch (o_ptr->feeling)
731 ADD_FLG(FLG_NAMELESS);
737 ADD_FLG(FLG_NAMELESS);
738 ADD_FLG(FLG_WORTHLESS);
744 ADD_FLG(FLG_WORTHLESS);
761 if (object_is_ego(o_ptr))
763 if (object_is_weapon_armour_ammo(o_ptr))
766 * Base name of ego weapons and armors
767 * are almost meaningless.
768 * Register the ego type only.
770 ego_item_type *e_ptr = &e_info[o_ptr->name2];
772 /* エゴ銘には「^」マークが使える */
773 sprintf(name_str, "^%s", e_name + e_ptr->name);
775 /* We ommit the basename and cannot use the ^ mark */
776 strcpy(name_str, e_name + e_ptr->name);
779 if (!object_is_rare(o_ptr)) ADD_FLG(FLG_COMMON);
784 else if (object_is_artifact(o_ptr))
785 ADD_FLG(FLG_ARTIFACT);
788 if (object_is_equipment(o_ptr))
789 ADD_FLG(FLG_NAMELESS);
796 if (object_is_melee_weapon(o_ptr))
798 object_kind *k_ptr = &k_info[o_ptr->k_idx];
800 if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
801 ADD_FLG(FLG_BOOSTED);
804 if (object_is_bounty(o_ptr))
806 REM_FLG(FLG_WORTHLESS);
810 if ((o_ptr->tval == TV_CORPSE || o_ptr->tval == TV_STATUE)
811 && (r_info[o_ptr->pval].flags1 & RF1_UNIQUE))
816 if (o_ptr->tval == TV_CORPSE && my_strchr("pht", r_info[o_ptr->pval].d_char))
821 if (o_ptr->tval >= TV_LIFE_BOOK &&
822 !check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval))
824 ADD_FLG(FLG_UNREADABLE);
825 if (o_ptr->tval != TV_ARCANE_BOOK) name = FALSE;
828 if (REALM1_BOOK == o_ptr->tval &&
829 player_ptr->pclass != CLASS_SORCERER &&
830 player_ptr->pclass != CLASS_RED_MAGE)
836 if (REALM2_BOOK == o_ptr->tval &&
837 player_ptr->pclass != CLASS_SORCERER &&
838 player_ptr->pclass != CLASS_RED_MAGE)
844 if (o_ptr->tval >= TV_LIFE_BOOK && 0 == o_ptr->sval)
846 if (o_ptr->tval >= TV_LIFE_BOOK && 1 == o_ptr->sval)
848 if (o_ptr->tval >= TV_LIFE_BOOK && 2 == o_ptr->sval)
850 if (o_ptr->tval >= TV_LIFE_BOOK && 3 == o_ptr->sval)
853 if (object_is_ammo(o_ptr))
854 ADD_FLG(FLG_MISSILES);
855 else if (o_ptr->tval == TV_SCROLL || o_ptr->tval == TV_STAFF
856 || o_ptr->tval == TV_WAND || o_ptr->tval == TV_ROD)
857 ADD_FLG(FLG_DEVICES);
858 else if (o_ptr->tval == TV_LITE)
860 else if (o_ptr->tval == TV_SKELETON || o_ptr->tval == TV_BOTTLE
861 || o_ptr->tval == TV_JUNK || o_ptr->tval == TV_STATUE)
863 else if (o_ptr->tval == TV_CORPSE)
864 ADD_FLG(FLG_CORPSES);
865 else if (o_ptr->tval >= TV_LIFE_BOOK)
866 ADD_FLG(FLG_SPELLBOOKS);
867 else if (o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_SWORD
868 || o_ptr->tval == TV_DIGGING || o_ptr->tval == TV_HAFTED)
869 ADD_FLG(FLG_WEAPONS);
870 else if (o_ptr->tval == TV_SHIELD)
871 ADD_FLG(FLG_SHIELDS);
872 else if (o_ptr->tval == TV_BOW)
874 else if (o_ptr->tval == TV_RING)
876 else if (o_ptr->tval == TV_AMULET)
877 ADD_FLG(FLG_AMULETS);
878 else if (o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_HARD_ARMOR ||
879 o_ptr->tval == TV_SOFT_ARMOR)
881 else if (o_ptr->tval == TV_CLOAK)
883 else if (o_ptr->tval == TV_HELM)
885 else if (o_ptr->tval == TV_GLOVES)
887 else if (o_ptr->tval == TV_BOOTS)
892 str_tolower(name_str);
893 entry->name = string_make(name_str);
897 GAME_TEXT o_name[MAX_NLEN];
898 object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL | OD_NAME_ONLY));
901 * If necessary, add a '^' which indicates the
904 sprintf(name_str, "%s%s", bol_mark ? "^" : "", o_name);
905 str_tolower(name_str);
906 entry->name = string_make(name_str);
911 * A function to delete entry
913 static void autopick_free_entry(autopick_type *entry)
915 string_free(entry->name);
916 string_free(entry->insc);
923 * Initialize the autopick
925 static void init_autopick(void)
927 static const char easy_autopick_inscription[] = "(:=g";
933 max_max_autopick = MAX_AUTOPICK_DEFAULT;
934 C_MAKE(autopick_list, max_max_autopick, autopick_type);
938 for (i = 0; i < max_autopick; i++)
939 autopick_free_entry(&autopick_list[i]);
942 autopick_new_entry(&entry, easy_autopick_inscription, TRUE);
943 autopick_list[max_autopick++] = entry;
948 * Get file name for autopick preference
950 static concptr pickpref_filename(player_type *player_ptr, int filename_mode)
952 static const char namebase[] = _("picktype", "pickpref");
954 switch (filename_mode)
957 return format("%s.prf", namebase);
960 return format("%s-%s.prf", namebase, player_ptr->base_name);
969 * Load an autopick preference file
971 void autopick_load_pref(player_type *player_ptr, bool disp_mes)
975 my_strcpy(buf, pickpref_filename(player_ptr, PT_WITH_PNAME), sizeof(buf));
976 errr err = process_autopick_file(player_ptr, buf);
977 if (err == 0 && disp_mes)
979 msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf);
984 my_strcpy(buf, pickpref_filename(player_ptr, PT_DEFAULT), sizeof(buf));
985 err = process_autopick_file(player_ptr, buf);
986 if (err == 0 && disp_mes)
988 msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf);
994 msg_print(_("自動拾い設定ファイルの読み込みに失敗しました。", "Failed to reload autopick preference."));
1000 * Add one line to autopick_list[]
1002 static void add_autopick_list(autopick_type *entry)
1004 if (max_autopick >= max_max_autopick)
1006 int old_max_max_autopick = max_max_autopick;
1007 autopick_type *old_autopick_list = autopick_list;
1008 max_max_autopick += MAX_AUTOPICK_DEFAULT;
1009 C_MAKE(autopick_list, max_max_autopick, autopick_type);
1010 (void)C_COPY(autopick_list, old_autopick_list, old_max_max_autopick, autopick_type);
1011 C_KILL(old_autopick_list, old_max_max_autopick, autopick_type);
1014 autopick_list[max_autopick] = *entry;
1020 * Process line for auto picker/destroyer.
1022 void process_autopick_file_command(char *buf)
1024 autopick_type an_entry, *entry = &an_entry;
1026 for (i = 0; buf[i]; i++)
1029 if (iskanji(buf[i]))
1035 if (iswspace(buf[i]) && buf[i] != ' ')
1040 if (!autopick_new_entry(entry, buf, FALSE)) return;
1042 for (i = 0; i < max_autopick; i++)
1044 if (!strcmp(entry->name, autopick_list[i].name)
1045 && entry->flag[0] == autopick_list[i].flag[0]
1046 && entry->flag[1] == autopick_list[i].flag[1]
1047 && entry->dice == autopick_list[i].dice
1048 && entry->bonus == autopick_list[i].bonus)
1050 autopick_free_entry(entry);
1055 add_autopick_list(entry);
1061 * Reconstruct preference line from entry
1063 concptr autopick_line_from_entry(autopick_type *entry)
1065 char buf[MAX_LINELEN];
1067 if (!(entry->action & DO_DISPLAY)) strcat(buf, "(");
1068 if (entry->action & DO_QUERY_AUTOPICK) strcat(buf, ";");
1069 if (entry->action & DO_AUTODESTROY) strcat(buf, "!");
1070 if (entry->action & DONT_AUTOPICK) strcat(buf, "~");
1074 if (IS_FLG(FLG_ALL)) ADD_KEY(KEY_ALL);
1075 if (IS_FLG(FLG_COLLECTING)) ADD_KEY(KEY_COLLECTING);
1076 if (IS_FLG(FLG_UNAWARE)) ADD_KEY(KEY_UNAWARE);
1077 if (IS_FLG(FLG_UNIDENTIFIED)) ADD_KEY(KEY_UNIDENTIFIED);
1078 if (IS_FLG(FLG_IDENTIFIED)) ADD_KEY(KEY_IDENTIFIED);
1079 if (IS_FLG(FLG_STAR_IDENTIFIED)) ADD_KEY(KEY_STAR_IDENTIFIED);
1080 if (IS_FLG(FLG_BOOSTED)) ADD_KEY(KEY_BOOSTED);
1082 if (IS_FLG(FLG_MORE_DICE))
1084 ADD_KEY(KEY_MORE_THAN);
1085 strcat(ptr, format("%d", entry->dice));
1089 if (IS_FLG(FLG_MORE_BONUS))
1091 ADD_KEY(KEY_MORE_BONUS);
1092 strcat(ptr, format("%d", entry->bonus));
1093 ADD_KEY(KEY_MORE_BONUS2);
1096 if (IS_FLG(FLG_UNREADABLE)) ADD_KEY(KEY_UNREADABLE);
1097 if (IS_FLG(FLG_REALM1)) ADD_KEY(KEY_REALM1);
1098 if (IS_FLG(FLG_REALM2)) ADD_KEY(KEY_REALM2);
1099 if (IS_FLG(FLG_FIRST)) ADD_KEY(KEY_FIRST);
1100 if (IS_FLG(FLG_SECOND)) ADD_KEY(KEY_SECOND);
1101 if (IS_FLG(FLG_THIRD)) ADD_KEY(KEY_THIRD);
1102 if (IS_FLG(FLG_FOURTH)) ADD_KEY(KEY_FOURTH);
1103 if (IS_FLG(FLG_WANTED)) ADD_KEY(KEY_WANTED);
1104 if (IS_FLG(FLG_UNIQUE)) ADD_KEY(KEY_UNIQUE);
1105 if (IS_FLG(FLG_HUMAN)) ADD_KEY(KEY_HUMAN);
1106 if (IS_FLG(FLG_WORTHLESS)) ADD_KEY(KEY_WORTHLESS);
1107 if (IS_FLG(FLG_GOOD)) ADD_KEY(KEY_GOOD);
1108 if (IS_FLG(FLG_NAMELESS)) ADD_KEY(KEY_NAMELESS);
1109 if (IS_FLG(FLG_AVERAGE)) ADD_KEY(KEY_AVERAGE);
1110 if (IS_FLG(FLG_RARE)) ADD_KEY(KEY_RARE);
1111 if (IS_FLG(FLG_COMMON)) ADD_KEY(KEY_COMMON);
1112 if (IS_FLG(FLG_EGO)) ADD_KEY(KEY_EGO);
1114 if (IS_FLG(FLG_ARTIFACT)) ADD_KEY(KEY_ARTIFACT);
1116 bool sepa_flag = TRUE;
1117 if (IS_FLG(FLG_ITEMS)) ADD_KEY2(KEY_ITEMS);
1118 else if (IS_FLG(FLG_WEAPONS)) ADD_KEY2(KEY_WEAPONS);
1119 else if (IS_FLG(FLG_FAVORITE_WEAPONS)) ADD_KEY2(KEY_FAVORITE_WEAPONS);
1120 else if (IS_FLG(FLG_ARMORS)) ADD_KEY2(KEY_ARMORS);
1121 else if (IS_FLG(FLG_MISSILES)) ADD_KEY2(KEY_MISSILES);
1122 else if (IS_FLG(FLG_DEVICES)) ADD_KEY2(KEY_DEVICES);
1123 else if (IS_FLG(FLG_LIGHTS)) ADD_KEY2(KEY_LIGHTS);
1124 else if (IS_FLG(FLG_JUNKS)) ADD_KEY2(KEY_JUNKS);
1125 else if (IS_FLG(FLG_CORPSES)) ADD_KEY2(KEY_CORPSES);
1126 else if (IS_FLG(FLG_SPELLBOOKS)) ADD_KEY2(KEY_SPELLBOOKS);
1127 else if (IS_FLG(FLG_HAFTED)) ADD_KEY2(KEY_HAFTED);
1128 else if (IS_FLG(FLG_SHIELDS)) ADD_KEY2(KEY_SHIELDS);
1129 else if (IS_FLG(FLG_BOWS)) ADD_KEY2(KEY_BOWS);
1130 else if (IS_FLG(FLG_RINGS)) ADD_KEY2(KEY_RINGS);
1131 else if (IS_FLG(FLG_AMULETS)) ADD_KEY2(KEY_AMULETS);
1132 else if (IS_FLG(FLG_SUITS)) ADD_KEY2(KEY_SUITS);
1133 else if (IS_FLG(FLG_CLOAKS)) ADD_KEY2(KEY_CLOAKS);
1134 else if (IS_FLG(FLG_HELMS)) ADD_KEY2(KEY_HELMS);
1135 else if (IS_FLG(FLG_GLOVES)) ADD_KEY2(KEY_GLOVES);
1136 else if (IS_FLG(FLG_BOOTS)) ADD_KEY2(KEY_BOOTS);
1137 else if (!IS_FLG(FLG_ARTIFACT))
1140 if (entry->name && entry->name[0])
1142 if (sepa_flag) strcat(buf, ":");
1144 int i = strlen(buf);
1146 while (entry->name[j] && i < MAX_LINELEN - 2 - 1)
1149 if (iskanji(entry->name[j]))
1150 buf[i++] = entry->name[j++];
1152 buf[i++] = entry->name[j++];
1157 if (!entry->insc) return string_make(buf);
1163 while (entry->insc[j] && i < MAX_LINELEN - 2)
1166 if (iskanji(entry->insc[j]))
1167 buf[i++] = entry->insc[j++];
1169 buf[i++] = entry->insc[j++];
1173 return string_make(buf);
1178 * Reconstruct preference line from entry and kill entry
1180 static concptr autopick_line_from_entry_kill(autopick_type *entry)
1182 concptr ptr = autopick_line_from_entry(entry);
1183 autopick_free_entry(entry);
1189 * A function for Auto-picker/destroyer
1190 * Examine whether the object matches to the entry
1192 static bool is_autopick_aux(player_type *player_ptr, object_type *o_ptr, autopick_type *entry, concptr o_name)
1194 concptr ptr = entry->name;
1195 if (IS_FLG(FLG_UNAWARE) && object_is_aware(o_ptr))
1198 if (IS_FLG(FLG_UNIDENTIFIED)
1199 && (object_is_known(o_ptr) || (o_ptr->ident & IDENT_SENSE)))
1202 if (IS_FLG(FLG_IDENTIFIED) && !object_is_known(o_ptr))
1205 if (IS_FLG(FLG_STAR_IDENTIFIED) &&
1206 (!object_is_known(o_ptr) || !OBJECT_IS_FULL_KNOWN(o_ptr)))
1209 if (IS_FLG(FLG_BOOSTED))
1211 object_kind *k_ptr = &k_info[o_ptr->k_idx];
1212 if (!object_is_melee_weapon(o_ptr))
1215 if ((o_ptr->dd == k_ptr->dd) && (o_ptr->ds == k_ptr->ds))
1218 if (!object_is_known(o_ptr) && object_is_quest_target(o_ptr))
1224 if (IS_FLG(FLG_MORE_DICE))
1226 if (o_ptr->dd * o_ptr->ds < entry->dice)
1230 if (IS_FLG(FLG_MORE_BONUS))
1232 if (!object_is_known(o_ptr)) return FALSE;
1236 if (o_ptr->pval < entry->bonus) return FALSE;
1240 if (o_ptr->to_h < entry->bonus &&
1241 o_ptr->to_d < entry->bonus &&
1242 o_ptr->to_a < entry->bonus &&
1243 o_ptr->pval < entry->bonus)
1248 if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0)
1251 if (IS_FLG(FLG_ARTIFACT))
1253 if (!object_is_known(o_ptr) || !object_is_artifact(o_ptr))
1257 if (IS_FLG(FLG_EGO))
1259 if (!object_is_ego(o_ptr)) return FALSE;
1260 if (!object_is_known(o_ptr) &&
1261 !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT))
1265 if (IS_FLG(FLG_GOOD))
1267 if (!object_is_equipment(o_ptr)) return FALSE;
1268 if (object_is_known(o_ptr))
1270 if (!object_is_nameless(o_ptr))
1273 if (o_ptr->to_a <= 0 && (o_ptr->to_h + o_ptr->to_d) <= 0)
1276 else if (o_ptr->ident & IDENT_SENSE)
1278 switch (o_ptr->feeling)
1293 if (IS_FLG(FLG_NAMELESS))
1295 if (!object_is_equipment(o_ptr)) return FALSE;
1296 if (object_is_known(o_ptr))
1298 if (!object_is_nameless(o_ptr))
1301 else if (o_ptr->ident & IDENT_SENSE)
1303 switch (o_ptr->feeling)
1321 if (IS_FLG(FLG_AVERAGE))
1323 if (!object_is_equipment(o_ptr)) return FALSE;
1324 if (object_is_known(o_ptr))
1326 if (!object_is_nameless(o_ptr))
1329 if (object_is_cursed(o_ptr) || object_is_broken(o_ptr))
1332 if (o_ptr->to_a > 0 || (o_ptr->to_h + o_ptr->to_d) > 0)
1335 else if (o_ptr->ident & IDENT_SENSE)
1337 switch (o_ptr->feeling)
1352 if (IS_FLG(FLG_RARE) && !object_is_rare(o_ptr))
1355 if (IS_FLG(FLG_COMMON) && object_is_rare(o_ptr))
1358 if (IS_FLG(FLG_WANTED) && !object_is_bounty(o_ptr))
1361 if (IS_FLG(FLG_UNIQUE) &&
1362 ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) ||
1363 !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE)))
1366 if (IS_FLG(FLG_HUMAN) &&
1367 (o_ptr->tval != TV_CORPSE ||
1368 !my_strchr("pht", r_info[o_ptr->pval].d_char)))
1371 if (IS_FLG(FLG_UNREADABLE) &&
1372 (o_ptr->tval < TV_LIFE_BOOK ||
1373 check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval)))
1376 if (IS_FLG(FLG_REALM1) &&
1377 (REALM1_BOOK != o_ptr->tval ||
1378 player_ptr->pclass == CLASS_SORCERER ||
1379 player_ptr->pclass == CLASS_RED_MAGE))
1382 if (IS_FLG(FLG_REALM2) &&
1383 (REALM2_BOOK != o_ptr->tval ||
1384 player_ptr->pclass == CLASS_SORCERER ||
1385 player_ptr->pclass == CLASS_RED_MAGE))
1388 if (IS_FLG(FLG_FIRST) &&
1389 (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval))
1392 if (IS_FLG(FLG_SECOND) &&
1393 (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval))
1396 if (IS_FLG(FLG_THIRD) &&
1397 (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval))
1400 if (IS_FLG(FLG_FOURTH) &&
1401 (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval))
1404 if (IS_FLG(FLG_WEAPONS))
1406 if (!object_is_weapon(o_ptr))
1409 else if (IS_FLG(FLG_FAVORITE_WEAPONS))
1411 if (!object_is_favorite(o_ptr))
1414 else if (IS_FLG(FLG_ARMORS))
1416 if (!object_is_armour(o_ptr))
1419 else if (IS_FLG(FLG_MISSILES))
1421 if (!object_is_ammo(o_ptr)) return FALSE;
1423 else if (IS_FLG(FLG_DEVICES))
1425 switch (o_ptr->tval)
1427 case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD:
1429 default: return FALSE;
1432 else if (IS_FLG(FLG_LIGHTS))
1434 if (!(o_ptr->tval == TV_LITE))
1437 else if (IS_FLG(FLG_JUNKS))
1439 switch (o_ptr->tval)
1441 case TV_SKELETON: case TV_BOTTLE:
1442 case TV_JUNK: case TV_STATUE:
1444 default: return FALSE;
1447 else if (IS_FLG(FLG_CORPSES))
1449 if (o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_SKELETON)
1452 else if (IS_FLG(FLG_SPELLBOOKS))
1454 if (!(o_ptr->tval >= TV_LIFE_BOOK))
1457 else if (IS_FLG(FLG_HAFTED))
1459 if (!(o_ptr->tval == TV_HAFTED))
1462 else if (IS_FLG(FLG_SHIELDS))
1464 if (!(o_ptr->tval == TV_SHIELD))
1467 else if (IS_FLG(FLG_BOWS))
1469 if (!(o_ptr->tval == TV_BOW))
1472 else if (IS_FLG(FLG_RINGS))
1474 if (!(o_ptr->tval == TV_RING))
1477 else if (IS_FLG(FLG_AMULETS))
1479 if (!(o_ptr->tval == TV_AMULET))
1482 else if (IS_FLG(FLG_SUITS))
1484 if (!(o_ptr->tval == TV_DRAG_ARMOR ||
1485 o_ptr->tval == TV_HARD_ARMOR ||
1486 o_ptr->tval == TV_SOFT_ARMOR))
1489 else if (IS_FLG(FLG_CLOAKS))
1491 if (!(o_ptr->tval == TV_CLOAK))
1494 else if (IS_FLG(FLG_HELMS))
1496 if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM))
1499 else if (IS_FLG(FLG_GLOVES))
1501 if (!(o_ptr->tval == TV_GLOVES))
1504 else if (IS_FLG(FLG_BOOTS))
1506 if (!(o_ptr->tval == TV_BOOTS))
1513 if (strncmp(o_name, ptr, strlen(ptr))) return FALSE;
1517 if (!my_strstr(o_name, ptr)) return FALSE;
1520 if (!IS_FLG(FLG_COLLECTING)) return TRUE;
1522 for (int j = 0; j < INVEN_PACK; j++)
1525 * 'Collecting' means the item must be absorbed
1526 * into an inventory slot.
1527 * But an item can not be absorbed into itself!
1529 if ((&player_ptr->inventory_list[j] != o_ptr) &&
1530 object_similar(&player_ptr->inventory_list[j], o_ptr))
1539 * A function for Auto-picker/destroyer
1540 * Examine whether the object matches to the list of keywords or not.
1542 int is_autopick(player_type *player_ptr, object_type *o_ptr)
1544 GAME_TEXT o_name[MAX_NLEN];
1545 if (o_ptr->tval == TV_GOLD) return -1;
1547 object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
1548 str_tolower(o_name);
1549 for (int i = 0; i < max_autopick; i++)
1551 autopick_type *entry = &autopick_list[i];
1552 if (is_autopick_aux(player_ptr, o_ptr, entry, o_name))
1563 static void auto_inscribe_item(player_type *player_ptr, object_type *o_ptr, int idx)
1565 if (idx < 0 || !autopick_list[idx].insc) return;
1567 if (!o_ptr->inscription)
1568 o_ptr->inscription = quark_add(autopick_list[idx].insc);
1570 player_ptr->window |= (PW_EQUIP | PW_INVEN);
1571 player_ptr->update |= (PU_BONUS);
1576 * Automatically destroy items in this grid.
1578 static bool is_opt_confirm_destroy(player_type *player_ptr, object_type *o_ptr)
1580 if (!destroy_items) return FALSE;
1583 if (object_value(o_ptr) > 0) return FALSE;
1586 if (object_is_weapon_armour_ammo(o_ptr)) return FALSE;
1589 if ((o_ptr->tval == TV_CHEST) && o_ptr->pval) return FALSE;
1593 if (object_is_bounty(o_ptr)) return FALSE;
1597 if (o_ptr->tval == TV_CORPSE) return FALSE;
1600 if ((o_ptr->tval == TV_SKELETON) || (o_ptr->tval == TV_BOTTLE) || (o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_STATUE)) return FALSE;
1604 if (player_ptr->prace == RACE_DEMON)
1606 if (o_ptr->tval == TV_CORPSE &&
1607 o_ptr->sval == SV_CORPSE &&
1608 my_strchr("pht", r_info[o_ptr->pval].d_char))
1612 if (player_ptr->pclass == CLASS_ARCHER)
1614 if (o_ptr->tval == TV_SKELETON ||
1615 (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON))
1618 else if (player_ptr->pclass == CLASS_NINJA)
1620 if (o_ptr->tval == TV_LITE &&
1621 o_ptr->name2 == EGO_LITE_DARKNESS && object_is_known(o_ptr))
1624 else if (player_ptr->pclass == CLASS_BEASTMASTER ||
1625 player_ptr->pclass == CLASS_CAVALRY)
1627 if (o_ptr->tval == TV_WAND &&
1628 o_ptr->sval == SV_WAND_HEAL_MONSTER && object_is_aware(o_ptr))
1633 if (o_ptr->tval == TV_GOLD) return FALSE;
1639 static void auto_destroy_item(player_type *player_ptr, object_type *o_ptr, int autopick_idx)
1641 bool destroy = FALSE;
1642 if (is_opt_confirm_destroy(player_ptr, o_ptr)) destroy = TRUE;
1644 if (autopick_idx >= 0 &&
1645 !(autopick_list[autopick_idx].action & DO_AUTODESTROY))
1650 if (autopick_idx >= 0 &&
1651 (autopick_list[autopick_idx].action & DO_AUTODESTROY))
1655 if (!destroy) return;
1657 disturb(player_ptr, FALSE, FALSE);
1658 if (!can_player_destroy_object(o_ptr))
1660 GAME_TEXT o_name[MAX_NLEN];
1661 object_desc(player_ptr, o_name, o_ptr, 0);
1662 msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name);
1666 (void)COPY(&autopick_last_destroyed_object, o_ptr, object_type);
1667 o_ptr->marked |= OM_AUTODESTROY;
1668 player_ptr->update |= PU_AUTODESTROY;
1673 * Auto-destroy marked item
1675 static void autopick_delayed_alter_aux(player_type *player_ptr, INVENTORY_IDX item)
1678 o_ptr = REF_ITEM(player_ptr, player_ptr->current_floor_ptr, item);
1680 if (o_ptr->k_idx == 0 || !(o_ptr->marked & OM_AUTODESTROY)) return;
1682 GAME_TEXT o_name[MAX_NLEN];
1683 object_desc(player_ptr, o_name, o_ptr, 0);
1686 inven_item_increase(player_ptr, item, -(o_ptr->number));
1687 inven_item_optimize(player_ptr, item);
1691 delete_object_idx(player_ptr, 0 - item);
1694 msg_format(_("%sを自動破壊します。", "Auto-destroying %s."), o_name);
1699 * Auto-destroy marked items in inventry and on floor
1701 void autopick_delayed_alter(player_type *owner_ptr)
1706 * Scan inventry in reverse order to prevent
1707 * skipping after inven_item_optimize()
1709 for (item = INVEN_TOTAL - 1; item >= 0; item--)
1710 autopick_delayed_alter_aux(owner_ptr, item);
1712 floor_type *floor_ptr = owner_ptr->current_floor_ptr;
1713 item = floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx;
1716 OBJECT_IDX next = floor_ptr->o_list[item].next_o_idx;
1717 autopick_delayed_alter_aux(owner_ptr, -item);
1724 * Auto-inscription and/or destroy
1726 * Auto-destroyer works only on inventory or on floor stack only when
1729 void autopick_alter_item(player_type *player_ptr, INVENTORY_IDX item, bool destroy)
1732 o_ptr = REF_ITEM(player_ptr, player_ptr->current_floor_ptr, item);
1733 int idx = is_autopick(player_ptr, o_ptr);
1734 auto_inscribe_item(player_ptr, o_ptr, idx);
1735 if (destroy && item <= INVEN_PACK)
1736 auto_destroy_item(player_ptr, o_ptr, idx);
1741 * Automatically pickup/destroy items in this grid.
1743 void autopick_pickup_items(player_type* player_ptr, grid_type *g_ptr)
1745 OBJECT_IDX this_o_idx, next_o_idx = 0;
1746 for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1748 object_type *o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
1749 next_o_idx = o_ptr->next_o_idx;
1750 int idx = is_autopick(player_ptr, o_ptr);
1751 auto_inscribe_item(player_ptr, o_ptr, idx);
1752 bool is_auto_pickup = idx >= 0;
1753 is_auto_pickup &= (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK)) != 0;
1754 if (!is_auto_pickup)
1756 auto_destroy_item(player_ptr, o_ptr, idx);
1760 disturb(player_ptr, FALSE, FALSE);
1761 if (!inven_carry_okay(o_ptr))
1763 GAME_TEXT o_name[MAX_NLEN];
1764 object_desc(player_ptr, o_name, o_ptr, 0);
1765 msg_format(_("ザックには%sを入れる隙間がない。", "You have no room for %s."), o_name);
1766 o_ptr->marked |= OM_NOMSG;
1770 if (!(autopick_list[idx].action & DO_QUERY_AUTOPICK))
1772 py_pickup_aux(player_ptr, this_o_idx);
1776 char out_val[MAX_NLEN + 20];
1777 GAME_TEXT o_name[MAX_NLEN];
1778 if (o_ptr->marked & OM_NO_QUERY)
1783 object_desc(player_ptr, o_name, o_ptr, 0);
1784 sprintf(out_val, _("%sを拾いますか? ", "Pick up %s? "), o_name);
1785 if (!get_check(out_val))
1787 o_ptr->marked |= OM_NOMSG | OM_NO_QUERY;
1791 py_pickup_aux(player_ptr, this_o_idx);
1796 static const char autoregister_header[] = "?:$AUTOREGISTER";
1799 * Clear auto registered lines in the picktype.prf .
1801 static bool clear_auto_register(player_type *player_ptr)
1803 char tmp_file[1024];
1804 char pref_file[1024];
1809 bool autoregister = FALSE;
1812 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME));
1813 pref_fff = my_fopen(pref_file, "r");
1817 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT));
1818 pref_fff = my_fopen(pref_file, "r");
1826 tmp_fff = my_fopen_temp(tmp_file, sizeof(tmp_file));
1830 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
1837 if (my_fgets(pref_fff, buf, sizeof(buf))) break;
1841 if (buf[0] != '#' && buf[0] != '?') num++;
1845 if (streq(buf, autoregister_header))
1847 autoregister = TRUE;
1851 fprintf(tmp_fff, "%s\n", buf);
1855 my_fclose(pref_fff);
1860 msg_format(_("以前のキャラクター用の自動設定(%d行)が残っています。",
1861 "Auto registered lines (%d lines) for previous character are remaining."), num);
1862 strcpy(buf, _("古い設定行は削除します。よろしいですか?", "These lines will be deleted. Are you sure? "));
1864 if (!get_check(buf))
1867 autoregister = FALSE;
1869 msg_print(_("エディタのカット&ペースト等を使って必要な行を避難してください。",
1870 "Use cut & paste of auto picker editor (_) to keep old prefs."));
1876 tmp_fff = my_fopen(tmp_file, "r");
1877 pref_fff = my_fopen(pref_file, "w");
1879 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
1880 fprintf(pref_fff, "%s\n", buf);
1882 my_fclose(pref_fff);
1892 * Automatically register an auto-destroy preference line
1894 bool autopick_autoregister(player_type *player_ptr, object_type *o_ptr)
1897 char pref_file[1024];
1899 autopick_type an_entry, *entry = &an_entry;
1900 int match_autopick = is_autopick(player_ptr, o_ptr);
1901 if (match_autopick != -1)
1904 byte act = autopick_list[match_autopick].action;
1905 if (act & DO_AUTOPICK) what = _("自動で拾う", "auto-pickup");
1906 else if (act & DO_AUTODESTROY) what = _("自動破壊する", "auto-destroy");
1907 else if (act & DONT_AUTOPICK) what = _("放置する", "leave on floor");
1908 else what = _("確認して拾う", "query auto-pickup");
1910 msg_format(_("そのアイテムは既に%sように設定されています。", "The object is already registered to %s."), what);
1914 if ((object_is_known(o_ptr) && object_is_artifact(o_ptr)) ||
1915 ((o_ptr->ident & IDENT_SENSE) &&
1916 (o_ptr->feeling == FEEL_TERRIBLE || o_ptr->feeling == FEEL_SPECIAL)))
1918 GAME_TEXT o_name[MAX_NLEN];
1919 object_desc(player_ptr, o_name, o_ptr, 0);
1920 msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name);
1924 if (!player_ptr->autopick_autoregister)
1926 if (!clear_auto_register(player_ptr)) return FALSE;
1929 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME));
1930 pref_fff = my_fopen(pref_file, "r");
1934 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT));
1935 pref_fff = my_fopen(pref_file, "r");
1942 if (my_fgets(pref_fff, buf, sizeof(buf)))
1944 player_ptr->autopick_autoregister = FALSE;
1948 if (streq(buf, autoregister_header))
1950 player_ptr->autopick_autoregister = TRUE;
1960 * File could not be opened for reading. Assume header not
1963 player_ptr->autopick_autoregister = FALSE;
1966 pref_fff = my_fopen(pref_file, "a");
1969 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), pref_file);
1974 if (!player_ptr->autopick_autoregister)
1976 fprintf(pref_fff, "%s\n", autoregister_header);
1978 fprintf(pref_fff, "%s\n", _("# *警告!!* 以降の行は自動登録されたものです。",
1979 "# *Warning!* The lines below will be deleted later."));
1980 fprintf(pref_fff, "%s\n", _("# 後で自動的に削除されますので、必要な行は上の方へ移動しておいてください。",
1981 "# Keep it by cut & paste if you need these lines for future characters."));
1982 player_ptr->autopick_autoregister = TRUE;
1985 autopick_entry_from_object(player_ptr, entry, o_ptr);
1986 entry->action = DO_AUTODESTROY;
1987 add_autopick_list(entry);
1989 concptr tmp = autopick_line_from_entry(entry);
1990 fprintf(pref_fff, "%s\n", tmp);
1998 * Describe which kind of object is Auto-picked/destroyed
2000 static void describe_autopick(char *buff, autopick_type *entry)
2002 concptr str = entry->name;
2003 byte act = entry->action;
2004 concptr insc = entry->insc;
2010 concptr before_str[100], body_str;
2014 if (IS_FLG(FLG_COLLECTING))
2015 before_str[before_n++] = "収集中で既に持っているスロットにまとめられる";
2017 if (IS_FLG(FLG_UNAWARE))
2018 before_str[before_n++] = "未鑑定でその効果も判明していない";
2020 if (IS_FLG(FLG_UNIDENTIFIED))
2021 before_str[before_n++] = "未鑑定の";
2023 if (IS_FLG(FLG_IDENTIFIED))
2024 before_str[before_n++] = "鑑定済みの";
2026 if (IS_FLG(FLG_STAR_IDENTIFIED))
2027 before_str[before_n++] = "完全に鑑定済みの";
2029 if (IS_FLG(FLG_BOOSTED))
2031 before_str[before_n++] = "ダメージダイスが通常より大きい";
2035 if (IS_FLG(FLG_MORE_DICE))
2037 static char more_than_desc_str[] = "___";
2038 before_str[before_n++] = "ダメージダイスの最大値が";
2041 sprintf(more_than_desc_str, "%d", entry->dice);
2042 before_str[before_n++] = more_than_desc_str;
2043 before_str[before_n++] = "以上の";
2046 if (IS_FLG(FLG_MORE_BONUS))
2048 static char more_bonus_desc_str[] = "___";
2049 before_str[before_n++] = "修正値が(+";
2051 sprintf(more_bonus_desc_str, "%d", entry->bonus);
2052 before_str[before_n++] = more_bonus_desc_str;
2053 before_str[before_n++] = ")以上の";
2056 if (IS_FLG(FLG_WORTHLESS))
2057 before_str[before_n++] = "店で無価値と判定される";
2059 if (IS_FLG(FLG_ARTIFACT))
2061 before_str[before_n++] = "アーティファクトの";
2065 if (IS_FLG(FLG_EGO))
2067 before_str[before_n++] = "エゴアイテムの";
2071 if (IS_FLG(FLG_GOOD))
2073 before_str[before_n++] = "上質の";
2077 if (IS_FLG(FLG_NAMELESS))
2079 before_str[before_n++] = "エゴでもアーティファクトでもない";
2083 if (IS_FLG(FLG_AVERAGE))
2085 before_str[before_n++] = "並の";
2089 if (IS_FLG(FLG_RARE))
2091 before_str[before_n++] = "ドラゴン装備やカオス・ブレード等を含む珍しい";
2095 if (IS_FLG(FLG_COMMON))
2097 before_str[before_n++] = "ありふれた(ドラゴン装備やカオス・ブレード等の珍しい物ではない)";
2101 if (IS_FLG(FLG_WANTED))
2103 before_str[before_n++] = "ハンター事務所で賞金首とされている";
2107 if (IS_FLG(FLG_HUMAN))
2109 before_str[before_n++] = "悪魔魔法で使うための人間やヒューマノイドの";
2113 if (IS_FLG(FLG_UNIQUE))
2115 before_str[before_n++] = "ユニークモンスターの";
2119 if (IS_FLG(FLG_UNREADABLE))
2121 before_str[before_n++] = "あなたが読めない領域の";
2125 if (IS_FLG(FLG_REALM1))
2127 before_str[before_n++] = "第一領域の";
2131 if (IS_FLG(FLG_REALM2))
2133 before_str[before_n++] = "第二領域の";
2137 if (IS_FLG(FLG_FIRST))
2139 before_str[before_n++] = "全4冊の内の1冊目の";
2143 if (IS_FLG(FLG_SECOND))
2145 before_str[before_n++] = "全4冊の内の2冊目の";
2149 if (IS_FLG(FLG_THIRD))
2151 before_str[before_n++] = "全4冊の内の3冊目の";
2155 if (IS_FLG(FLG_FOURTH))
2157 before_str[before_n++] = "全4冊の内の4冊目の";
2161 if (IS_FLG(FLG_ITEMS))
2162 ; /* Nothing to do */
2163 else if (IS_FLG(FLG_WEAPONS))
2165 else if (IS_FLG(FLG_FAVORITE_WEAPONS))
2167 else if (IS_FLG(FLG_ARMORS))
2169 else if (IS_FLG(FLG_MISSILES))
2170 body_str = "弾や矢やクロスボウの矢";
2171 else if (IS_FLG(FLG_DEVICES))
2172 body_str = "巻物や魔法棒や杖やロッド";
2173 else if (IS_FLG(FLG_LIGHTS))
2174 body_str = "光源用のアイテム";
2175 else if (IS_FLG(FLG_JUNKS))
2176 body_str = "折れた棒等のガラクタ";
2177 else if (IS_FLG(FLG_CORPSES))
2179 else if (IS_FLG(FLG_SPELLBOOKS))
2181 else if (IS_FLG(FLG_HAFTED))
2183 else if (IS_FLG(FLG_SHIELDS))
2185 else if (IS_FLG(FLG_BOWS))
2186 body_str = "スリングや弓やクロスボウ";
2187 else if (IS_FLG(FLG_RINGS))
2189 else if (IS_FLG(FLG_AMULETS))
2190 body_str = "アミュレット";
2191 else if (IS_FLG(FLG_SUITS))
2193 else if (IS_FLG(FLG_CLOAKS))
2195 else if (IS_FLG(FLG_HELMS))
2196 body_str = "ヘルメットや冠";
2197 else if (IS_FLG(FLG_GLOVES))
2199 else if (IS_FLG(FLG_BOOTS))
2204 strcat(buff, "全ての");
2205 else for (i = 0; i < before_n && before_str[i]; i++)
2206 strcat(buff, before_str[i]);
2208 strcat(buff, body_str);
2218 strcat(buff, "で、名前が「");
2219 strncat(buff, str, 80);
2221 strcat(buff, "」で始まるもの");
2223 strcat(buff, "」を含むもの");
2228 strncat(buff, format("に「%s」", insc), 80);
2230 if (my_strstr(insc, "%%all"))
2231 strcat(buff, "(%%allは全能力を表す英字の記号で置換)");
2232 else if (my_strstr(insc, "%all"))
2233 strcat(buff, "(%allは全能力を表す記号で置換)");
2234 else if (my_strstr(insc, "%%"))
2235 strcat(buff, "(%%は追加能力を表す英字の記号で置換)");
2236 else if (my_strstr(insc, "%"))
2237 strcat(buff, "(%は追加能力を表す記号で置換)");
2239 strcat(buff, "と刻んで");
2244 if (act & DONT_AUTOPICK)
2245 strcat(buff, "放置する。");
2246 else if (act & DO_AUTODESTROY)
2247 strcat(buff, "破壊する。");
2248 else if (act & DO_QUERY_AUTOPICK)
2249 strcat(buff, "確認の後に拾う。");
2251 strcat(buff, "拾う。");
2253 if (act & DO_DISPLAY)
2255 if (act & DONT_AUTOPICK)
2256 strcat(buff, "全体マップ('M')で'N'を押したときに表示する。");
2257 else if (act & DO_AUTODESTROY)
2258 strcat(buff, "全体マップ('M')で'K'を押したときに表示する。");
2260 strcat(buff, "全体マップ('M')で'M'を押したときに表示する。");
2263 strcat(buff, "全体マップには表示しない。");
2267 concptr before_str[20], after_str[20], which_str[20], whose_str[20], body_str;
2268 int before_n = 0, after_n = 0, which_n = 0, whose_n = 0;
2270 if (IS_FLG(FLG_COLLECTING))
2271 which_str[which_n++] = "can be absorbed into an existing inventory list slot";
2273 if (IS_FLG(FLG_UNAWARE))
2275 before_str[before_n++] = "unidentified";
2276 whose_str[whose_n++] = "basic abilities are not known";
2279 if (IS_FLG(FLG_UNIDENTIFIED))
2280 before_str[before_n++] = "unidentified";
2282 if (IS_FLG(FLG_IDENTIFIED))
2283 before_str[before_n++] = "identified";
2285 if (IS_FLG(FLG_STAR_IDENTIFIED))
2286 before_str[before_n++] = "fully identified";
2288 if (IS_FLG(FLG_RARE))
2290 before_str[before_n++] = "very rare";
2291 body_str = "equipments";
2292 after_str[after_n++] = "such as Dragon armor, Blades of Chaos, etc.";
2295 if (IS_FLG(FLG_COMMON))
2297 before_str[before_n++] = "relatively common";
2298 body_str = "equipments";
2299 after_str[after_n++] = "compared to very rare Dragon armor, Blades of Chaos, etc.";
2302 if (IS_FLG(FLG_WORTHLESS))
2304 before_str[before_n++] = "worthless";
2305 which_str[which_n++] = "can not be sold at stores";
2308 if (IS_FLG(FLG_ARTIFACT))
2310 before_str[before_n++] = "artifact";
2313 if (IS_FLG(FLG_EGO))
2315 before_str[before_n++] = "ego";
2318 if (IS_FLG(FLG_GOOD))
2320 body_str = "equipment";
2321 which_str[which_n++] = "have good quality";
2324 if (IS_FLG(FLG_NAMELESS))
2326 body_str = "equipment";
2327 which_str[which_n++] = "is neither ego-item nor artifact";
2330 if (IS_FLG(FLG_AVERAGE))
2332 body_str = "equipment";
2333 which_str[which_n++] = "have average quality";
2336 if (IS_FLG(FLG_BOOSTED))
2338 body_str = "weapons";
2339 whose_str[whose_n++] = "damage dice is bigger than normal";
2342 if (IS_FLG(FLG_MORE_DICE))
2344 static char more_than_desc_str[] =
2345 "maximum damage from dice is bigger than __";
2346 body_str = "weapons";
2348 sprintf(more_than_desc_str + sizeof(more_than_desc_str) - 3,
2350 whose_str[whose_n++] = more_than_desc_str;
2353 if (IS_FLG(FLG_MORE_BONUS))
2355 static char more_bonus_desc_str[] =
2356 "magical bonus is bigger than (+__)";
2358 sprintf(more_bonus_desc_str + sizeof(more_bonus_desc_str) - 4,
2359 "%d)", entry->bonus);
2360 whose_str[whose_n++] = more_bonus_desc_str;
2363 if (IS_FLG(FLG_WANTED))
2365 body_str = "corpse or skeletons";
2366 which_str[which_n++] = "is wanted at the Hunter's Office";
2369 if (IS_FLG(FLG_HUMAN))
2371 before_str[before_n++] = "humanoid";
2372 body_str = "corpse or skeletons";
2373 which_str[which_n++] = "can be used for Daemon magic";
2376 if (IS_FLG(FLG_UNIQUE))
2378 before_str[before_n++] = "unique monster's";
2379 body_str = "corpse or skeletons";
2382 if (IS_FLG(FLG_UNREADABLE))
2384 body_str = "spellbooks";
2385 after_str[after_n++] = "of different realms from yours";
2388 if (IS_FLG(FLG_REALM1))
2390 body_str = "spellbooks";
2391 after_str[after_n++] = "of your first realm";
2394 if (IS_FLG(FLG_REALM2))
2396 body_str = "spellbooks";
2397 after_str[after_n++] = "of your second realm";
2400 if (IS_FLG(FLG_FIRST))
2402 before_str[before_n++] = "first one of four";
2403 body_str = "spellbooks";
2406 if (IS_FLG(FLG_SECOND))
2408 before_str[before_n++] = "second one of four";
2409 body_str = "spellbooks";
2412 if (IS_FLG(FLG_THIRD))
2414 before_str[before_n++] = "third one of four";
2415 body_str = "spellbooks";
2418 if (IS_FLG(FLG_FOURTH))
2420 before_str[before_n++] = "fourth one of four";
2421 body_str = "spellbooks";
2424 if (IS_FLG(FLG_ITEMS))
2425 ; /* Nothing to do */
2426 else if (IS_FLG(FLG_WEAPONS))
2427 body_str = "weapons";
2428 else if (IS_FLG(FLG_FAVORITE_WEAPONS))
2429 body_str = "favorite weapons";
2430 else if (IS_FLG(FLG_ARMORS))
2431 body_str = "armors";
2432 else if (IS_FLG(FLG_MISSILES))
2433 body_str = "shots, arrows or crossbow bolts";
2434 else if (IS_FLG(FLG_DEVICES))
2435 body_str = "scrolls, wands, staffs or rods";
2436 else if (IS_FLG(FLG_LIGHTS))
2437 body_str = "light sources";
2438 else if (IS_FLG(FLG_JUNKS))
2439 body_str = "junk such as broken sticks";
2440 else if (IS_FLG(FLG_CORPSES))
2441 body_str = "corpses or skeletons";
2442 else if (IS_FLG(FLG_SPELLBOOKS))
2443 body_str = "spellbooks";
2444 else if (IS_FLG(FLG_HAFTED))
2445 body_str = "hafted weapons";
2446 else if (IS_FLG(FLG_SHIELDS))
2447 body_str = "shields";
2448 else if (IS_FLG(FLG_BOWS))
2449 body_str = "slings, bows or crossbows";
2450 else if (IS_FLG(FLG_RINGS))
2452 else if (IS_FLG(FLG_AMULETS))
2453 body_str = "amulets";
2454 else if (IS_FLG(FLG_SUITS))
2455 body_str = "body armors";
2456 else if (IS_FLG(FLG_CLOAKS))
2457 body_str = "cloaks";
2458 else if (IS_FLG(FLG_HELMS))
2459 body_str = "helms or crowns";
2460 else if (IS_FLG(FLG_GLOVES))
2461 body_str = "gloves";
2462 else if (IS_FLG(FLG_BOOTS))
2471 whose_str[whose_n++] = "name begins with \"";
2474 which_str[which_n++] = "have \"";
2478 if (act & DONT_AUTOPICK)
2479 strcpy(buff, "Leave on floor ");
2480 else if (act & DO_AUTODESTROY)
2481 strcpy(buff, "Destroy ");
2482 else if (act & DO_QUERY_AUTOPICK)
2483 strcpy(buff, "Ask to pick up ");
2485 strcpy(buff, "Pickup ");
2489 strncat(buff, format("and inscribe \"%s\"", insc), 80);
2491 if (my_strstr(insc, "%all"))
2492 strcat(buff, ", replacing %all with code string representing all abilities,");
2493 else if (my_strstr(insc, "%"))
2494 strcat(buff, ", replacing % with code string representing extra random abilities,");
2496 strcat(buff, " on ");
2500 strcat(buff, "all ");
2501 else for (i = 0; i < before_n && before_str[i]; i++)
2503 strcat(buff, before_str[i]);
2507 strcat(buff, body_str);
2509 for (i = 0; i < after_n && after_str[i]; i++)
2512 strcat(buff, after_str[i]);
2515 for (i = 0; i < whose_n && whose_str[i]; i++)
2518 strcat(buff, " whose ");
2520 strcat(buff, ", and ");
2522 strcat(buff, whose_str[i]);
2531 if (whose_n && which_n)
2532 strcat(buff, ", and ");
2534 for (i = 0; i < which_n && which_str[i]; i++)
2537 strcat(buff, " which ");
2539 strcat(buff, ", and ");
2541 strcat(buff, which_str[i]);
2546 strncat(buff, str, 80);
2547 strcat(buff, "\" as part of its name");
2551 if (act & DO_DISPLAY)
2553 if (act & DONT_AUTOPICK)
2554 strcat(buff, " Display these items when you press the N key in the full 'M'ap.");
2555 else if (act & DO_AUTODESTROY)
2556 strcat(buff, " Display these items when you press the K key in the full 'M'ap.");
2558 strcat(buff, " Display these items when you press the M key in the full 'M'ap.");
2561 strcat(buff, " Not displayed in the full map.");
2567 * Read whole lines of a file to memory
2569 static concptr *read_text_lines(concptr filename)
2571 concptr *lines_list = NULL;
2577 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2578 fff = my_fopen(buf, "r");
2579 if (!fff) return NULL;
2581 C_MAKE(lines_list, MAX_LINES, concptr);
2582 while (my_fgets(fff, buf, sizeof(buf)) == 0)
2584 lines_list[lines++] = string_make(buf);
2585 if (lines >= MAX_LINES - 1) break;
2589 lines_list[0] = string_make("");
2597 * Copy the default autopick file to the user directory
2599 static void prepare_default_pickpref(player_type *player_ptr)
2601 const concptr messages[] = {
2602 _("あなたは「自動拾いエディタ」を初めて起動しました。", "You have activated the Auto-Picker Editor for the first time."),
2603 _("自動拾いのユーザー設定ファイルがまだ書かれていないので、", "Since user pref file for autopick is not yet created,"),
2604 _("基本的な自動拾い設定ファイルをlib/pref/picktype.prfからコピーします。", "the default setting is loaded from lib/pref/pickpref.prf ."),
2608 concptr filename = pickpref_filename(player_ptr, PT_DEFAULT);
2609 for (int i = 0; messages[i]; i++)
2611 msg_print(messages[i]);
2616 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2618 user_fp = my_fopen(buf, "w");
2619 if (!user_fp) return;
2621 fprintf(user_fp, "#***\n");
2622 for (int i = 0; messages[i]; i++)
2624 fprintf(user_fp, "#*** %s\n", messages[i]);
2627 fprintf(user_fp, "#***\n\n\n");
2628 path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, filename);
2630 pref_fp = my_fopen(buf, "r");
2638 while (!my_fgets(pref_fp, buf, sizeof(buf)))
2640 fprintf(user_fp, "%s\n", buf);
2648 * Read an autopick prefence file to memory
2649 * Prepare default if no user file is found
2651 static concptr *read_pickpref_text_lines(player_type *player_ptr, int *filename_mode_p)
2653 /* Try a filename with player name */
2654 *filename_mode_p = PT_WITH_PNAME;
2656 strcpy(buf, pickpref_filename(player_ptr, *filename_mode_p));
2657 concptr *lines_list;
2658 lines_list = read_text_lines(buf);
2662 *filename_mode_p = PT_DEFAULT;
2663 strcpy(buf, pickpref_filename(player_ptr, *filename_mode_p));
2664 lines_list = read_text_lines(buf);
2669 prepare_default_pickpref(player_ptr);
2670 lines_list = read_text_lines(buf);
2675 C_MAKE(lines_list, MAX_LINES, concptr);
2676 lines_list[0] = string_make("");
2684 * Write whole lines of memory to a file.
2686 static bool write_text_lines(concptr filename, concptr *lines_list)
2689 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2691 fff = my_fopen(buf, "w");
2692 if (!fff) return FALSE;
2694 for (int lines = 0; lines_list[lines]; lines++)
2696 my_fputs(fff, lines_list[lines], 1024);
2705 * Free memory of lines_list.
2707 static void free_text_lines(concptr *lines_list)
2709 for (int lines = 0; lines_list[lines]; lines++)
2711 string_free(lines_list[lines]);
2714 /* free list of pointers */
2715 C_KILL(lines_list, MAX_LINES, concptr);
2720 * Delete or insert string
2722 static void toggle_keyword(text_body_type *tb, BIT_FLAGS flg)
2729 by1 = MIN(tb->my, tb->cy);
2730 by2 = MAX(tb->my, tb->cy);
2732 else /* if (!tb->mark) */
2737 for (int y = by1; y <= by2; y++)
2739 autopick_type an_entry, *entry = &an_entry;
2740 if (!autopick_new_entry(entry, tb->lines_list[y], !fixed)) continue;
2742 string_free(tb->lines_list[y]);
2745 if (!IS_FLG(flg)) add = TRUE;
2751 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
2754 for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
2757 else if (FLG_UNAWARE <= flg && flg <= FLG_STAR_IDENTIFIED)
2760 for (i = FLG_UNAWARE; i <= FLG_STAR_IDENTIFIED; i++)
2763 else if (FLG_ARTIFACT <= flg && flg <= FLG_AVERAGE)
2766 for (i = FLG_ARTIFACT; i <= FLG_AVERAGE; i++)
2769 else if (FLG_RARE <= flg && flg <= FLG_COMMON)
2772 for (i = FLG_RARE; i <= FLG_COMMON; i++)
2776 if (add) ADD_FLG(flg);
2779 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2780 tb->dirty_flags |= DIRTY_ALL;
2787 * Change command letter
2789 static void toggle_command_letter(text_body_type *tb, byte flg)
2791 autopick_type an_entry, *entry = &an_entry;
2797 by1 = MIN(tb->my, tb->cy);
2798 by2 = MAX(tb->my, tb->cy);
2800 else /* if (!tb->mark) */
2805 for (y = by1; y <= by2; y++)
2809 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
2811 string_free(tb->lines_list[y]);
2815 if (!(entry->action & flg)) add = TRUE;
2821 if (entry->action & DONT_AUTOPICK) wid--;
2822 else if (entry->action & DO_AUTODESTROY) wid--;
2823 else if (entry->action & DO_QUERY_AUTOPICK) wid--;
2824 if (!(entry->action & DO_DISPLAY)) wid--;
2826 if (flg != DO_DISPLAY)
2828 entry->action &= ~(DO_AUTOPICK | DONT_AUTOPICK | DO_AUTODESTROY | DO_QUERY_AUTOPICK);
2829 if (add) entry->action |= flg;
2830 else entry->action |= DO_AUTOPICK;
2834 entry->action &= ~(DO_DISPLAY);
2835 if (add) entry->action |= flg;
2840 if (entry->action & DONT_AUTOPICK) wid++;
2841 else if (entry->action & DO_AUTODESTROY) wid++;
2842 else if (entry->action & DO_QUERY_AUTOPICK) wid++;
2843 if (!(entry->action & DO_DISPLAY)) wid++;
2845 if (wid > 0) tb->cx++;
2846 if (wid < 0 && tb->cx > 0) tb->cx--;
2849 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2850 tb->dirty_flags |= DIRTY_ALL;
2857 * Delete or insert string
2859 static void add_keyword(text_body_type *tb, BIT_FLAGS flg)
2864 by1 = MIN(tb->my, tb->cy);
2865 by2 = MAX(tb->my, tb->cy);
2872 for (int y = by1; y <= by2; y++)
2874 autopick_type an_entry, *entry = &an_entry;
2875 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
2879 autopick_free_entry(entry);
2883 string_free(tb->lines_list[y]);
2884 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
2887 for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
2892 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2893 tb->dirty_flags |= DIRTY_ALL;
2900 * Check if this line is expression or not.
2901 * And update it if it is.
2903 static void check_expression_line(text_body_type *tb, int y)
2905 concptr s = tb->lines_list[y];
2907 if ((s[0] == '?' && s[1] == ':') ||
2908 (tb->states[y] & LSTAT_BYPASS))
2910 tb->dirty_flags |= DIRTY_EXPRESSION;
2916 * Add an empty line at the last of the file
2918 static bool add_empty_line(text_body_type *tb)
2921 for (num_lines = 0; tb->lines_list[num_lines]; num_lines++);
2923 if (num_lines >= MAX_LINES - 2) return FALSE;
2924 if (!tb->lines_list[num_lines - 1][0]) return FALSE;
2926 tb->lines_list[num_lines] = string_make("");
2927 tb->dirty_flags |= DIRTY_EXPRESSION;
2934 * Insert return code and split the line
2936 static bool insert_return_code(text_body_type *tb)
2938 char buf[MAX_LINELEN];
2939 int i, j, num_lines;
2941 for (num_lines = 0; tb->lines_list[num_lines]; num_lines++);
2943 if (num_lines >= MAX_LINES - 2) return FALSE;
2946 for (; tb->cy < num_lines; num_lines--)
2948 tb->lines_list[num_lines + 1] = tb->lines_list[num_lines];
2949 tb->states[num_lines + 1] = tb->states[num_lines];
2952 for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
2955 if (iskanji(tb->lines_list[tb->cy][i]))
2956 buf[j++] = tb->lines_list[tb->cy][i++];
2958 buf[j++] = tb->lines_list[tb->cy][i];
2962 tb->lines_list[tb->cy + 1] = string_make(&tb->lines_list[tb->cy][i]);
2963 string_free(tb->lines_list[tb->cy]);
2964 tb->lines_list[tb->cy] = string_make(buf);
2965 tb->dirty_flags |= DIRTY_EXPRESSION;
2972 * Choose an item and get auto-picker entry from it.
2974 static bool entry_from_choosed_object(player_type *player_ptr, autopick_type *entry)
2976 concptr q = _("どのアイテムを登録しますか? ", "Enter which item? ");
2977 concptr s = _("アイテムを持っていない。", "You have nothing to enter.");
2979 o_ptr = choose_object(player_ptr, NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, 0);
2980 if (!o_ptr) return FALSE;
2982 autopick_entry_from_object(player_ptr, entry, o_ptr);
2988 * Choose an item for search
2990 static bool get_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
2992 concptr q = _("どのアイテムを検索しますか? ", "Enter which item? ");
2993 concptr s = _("アイテムを持っていない。", "You have nothing to enter.");
2995 o_ptr = choose_object(player_ptr, NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, 0);
2996 if (!o_ptr) return FALSE;
2999 string_free(*search_strp);
3000 char buf[MAX_NLEN + 20];
3001 object_desc(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
3002 *search_strp = string_make(format("<%s>", buf));
3008 * Prepare for search by destroyed object
3010 static bool get_destroyed_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
3012 if (!autopick_last_destroyed_object.k_idx) return FALSE;
3014 *o_handle = &autopick_last_destroyed_object;
3015 string_free(*search_strp);
3016 char buf[MAX_NLEN + 20];
3017 object_desc(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
3018 *search_strp = string_make(format("<%s>", buf));
3024 * Choose an item or string for search
3026 static byte get_string_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
3030 * TERM_YELLOW : Overwrite mode
3031 * TERM_WHITE : Insert mode
3033 byte color = TERM_YELLOW;
3034 char buf[MAX_NLEN + 20];
3036 char prompt[] = _("検索(^I:持ち物 ^L:破壊された物): ", "Search key(^I:inven ^L:destroyed): ");
3037 int col = sizeof(prompt) - 1;
3038 if (*search_strp) strcpy(buf, *search_strp);
3041 if (*o_handle) color = TERM_L_GREEN;
3050 Term_erase(col, 0, 255);
3051 Term_putstr(col, 0, -1, color, buf);
3052 Term_gotoxy(col + pos, 0);
3054 skey = inkey_special(TRUE);
3062 if (pos == 0) break;
3066 int next_pos = i + 1;
3069 if (iskanji(buf[i])) next_pos++;
3071 if (next_pos >= pos) break;
3083 if ('\0' == buf[pos]) break;
3086 if (iskanji(buf[pos])) pos += 2;
3103 if (*o_handle) return (back ? -1 : 1);
3104 string_free(*search_strp);
3105 *search_strp = string_make(buf);
3107 return (back ? -1 : 1);
3110 return get_object_for_search(player_ptr, o_handle, search_strp);
3113 if (get_destroyed_object_for_search(player_ptr, o_handle, search_strp))
3121 if (pos == 0) break;
3125 int next_pos = i + 1;
3127 if (iskanji(buf[i])) next_pos++;
3129 if (next_pos >= pos) break;
3143 if (buf[pos] == '\0') break;
3147 if (iskanji(buf[pos])) src++;
3150 while ('\0' != (buf[dst++] = buf[src++]));
3159 if (skey & SKEY_MASK) break;
3162 if (color != TERM_WHITE)
3164 if (color == TERM_L_GREEN)
3167 string_free(*search_strp);
3168 *search_strp = NULL;
3175 strcpy(tmp, buf + pos);
3197 if (pos < len && (isprint(c) || iskana(c)))
3199 if (pos < len && isprint(c))
3211 my_strcat(buf, tmp, len + 1);
3217 if (*o_handle == NULL || color == TERM_L_GREEN) continue;
3221 string_free(*search_strp);
3222 *search_strp = NULL;
3228 * Search next line matches for o_ptr
3230 static void search_for_object(player_type *player_ptr, text_body_type *tb, object_type *o_ptr, bool forward)
3232 autopick_type an_entry, *entry = &an_entry;
3233 GAME_TEXT o_name[MAX_NLEN];
3234 int bypassed_cy = -1;
3236 object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
3237 str_tolower(o_name);
3244 if (!tb->lines_list[++i]) break;
3251 if (!autopick_new_entry(entry, tb->lines_list[i], FALSE)) continue;
3253 match = is_autopick_aux(player_ptr, o_ptr, entry, o_name);
3254 autopick_free_entry(entry);
3255 if (!match) continue;
3257 if (tb->states[i] & LSTAT_BYPASS)
3259 if (bypassed_cy == -1) bypassed_cy = i;
3265 if (bypassed_cy != -1)
3267 tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
3273 if (bypassed_cy == -1)
3275 tb->dirty_flags |= DIRTY_NOT_FOUND;
3280 tb->cy = bypassed_cy;
3281 tb->dirty_flags |= DIRTY_INACTIVE;
3286 * Search next line matches to the string
3288 static void search_for_string(text_body_type *tb, concptr search_str, bool forward)
3290 int bypassed_cy = -1;
3291 int bypassed_cx = 0;
3299 if (!tb->lines_list[++i]) break;
3306 pos = my_strstr(tb->lines_list[i], search_str);
3309 if ((tb->states[i] & LSTAT_BYPASS) &&
3310 !(tb->states[i] & LSTAT_EXPRESSION))
3312 if (bypassed_cy == -1)
3315 bypassed_cx = (int)(pos - tb->lines_list[i]);
3321 tb->cx = (int)(pos - tb->lines_list[i]);
3324 if (bypassed_cy != -1)
3326 tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
3332 if (bypassed_cy == -1)
3334 tb->dirty_flags |= DIRTY_NOT_FOUND;
3338 tb->cx = bypassed_cx;
3339 tb->cy = bypassed_cy;
3340 tb->dirty_flags |= DIRTY_INACTIVE;
3345 * Find a command by 'key'.
3347 static int get_com_id(char key)
3349 for (int i = 0; menu_data[i].name; i++)
3351 if (menu_data[i].key == key)
3353 return menu_data[i].com_id;
3362 * Display the menu, and get a command
3364 static int do_command_menu(int level, int start)
3367 int col0 = 5 + level * 7;
3368 int row0 = 1 + level * 3;
3369 int menu_id_list[26];
3371 char linestr[MAX_LINELEN];
3374 for (int i = start; menu_data[i].level >= level; i++)
3378 /* Ignore lower level sub menus */
3379 if (menu_data[i].level > level) continue;
3381 len = strlen(menu_data[i].name);
3382 if (len > max_len) max_len = len;
3384 menu_id_list[menu_key] = i;
3388 while (menu_key < 26)
3390 menu_id_list[menu_key] = -1;
3394 int max_menu_wid = max_len + 3 + 3;
3396 /* Prepare box line */
3398 strcat(linestr, "+");
3399 for (int i = 0; i < max_menu_wid + 2; i++)
3401 strcat(linestr, "-");
3404 strcat(linestr, "+");
3414 int row1 = row0 + 1;
3415 Term_putstr(col0, row0, -1, TERM_WHITE, linestr);
3418 for (int i = start; menu_data[i].level >= level; i++)
3420 char com_key_str[3];
3422 if (menu_data[i].level > level) continue;
3424 if (menu_data[i].com_id == -1)
3426 strcpy(com_key_str, _("▼", ">"));
3428 else if (menu_data[i].key != -1)
3430 com_key_str[0] = '^';
3431 com_key_str[1] = menu_data[i].key + '@';
3432 com_key_str[2] = '\0';
3436 com_key_str[0] = '\0';
3439 str = format("| %c) %-*s %2s | ", menu_key + 'a', max_len, menu_data[i].name, com_key_str);
3441 Term_putstr(col0, row1++, -1, TERM_WHITE, str);
3446 Term_putstr(col0, row1, -1, TERM_WHITE, linestr);
3450 prt(format(_("(a-%c) コマンド:", "(a-%c) Command:"), menu_key + 'a' - 1), 0, 0);
3453 if (key == ESCAPE) return 0;
3455 bool is_alphabet = key >= 'a' && key <= 'z';
3458 com_id = get_com_id(key);
3467 menu_id = menu_id_list[key - 'a'];
3469 if (menu_id < 0) continue;
3471 com_id = menu_data[menu_id].com_id;
3475 com_id = do_command_menu(level + 1, menu_id + 1);
3477 if (com_id) return com_id;
3488 static chain_str_type *new_chain_str(concptr str)
3490 chain_str_type *chain;
3491 size_t len = strlen(str);
3492 chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char));
3493 strcpy(chain->s, str);
3499 static void kill_yank_chain(text_body_type *tb)
3501 chain_str_type *chain = tb->yank;
3503 tb->yank_eol = TRUE;
3507 chain_str_type *next = chain->next;
3508 size_t len = strlen(chain->s);
3510 rnfree(chain, sizeof(chain_str_type) + len * sizeof(char));
3517 static void add_str_to_yank(text_body_type *tb, concptr str)
3519 tb->yank_eol = FALSE;
3520 if (NULL == tb->yank)
3522 tb->yank = new_chain_str(str);
3526 chain_str_type *chain;
3533 chain->next = new_chain_str(str);
3538 chain = chain->next;
3544 * Do work for the copy editor-command
3546 static void copy_text_to_yank(text_body_type *tb)
3548 int len = strlen(tb->lines_list[tb->cy]);
3549 if (tb->cx > len) tb->cx = len;
3558 kill_yank_chain(tb);
3559 if (tb->my != tb->cy)
3561 int by1 = MIN(tb->my, tb->cy);
3562 int by2 = MAX(tb->my, tb->cy);
3564 for (int y = by1; y <= by2; y++)
3566 add_str_to_yank(tb, tb->lines_list[y]);
3569 add_str_to_yank(tb, "");
3571 tb->dirty_flags |= DIRTY_ALL;
3575 char buf[MAX_LINELEN];
3576 int bx1 = MIN(tb->mx, tb->cx);
3577 int bx2 = MAX(tb->mx, tb->cx);
3578 if (bx2 > len) bx2 = len;
3580 if (bx1 == 0 && bx2 == len)
3582 add_str_to_yank(tb, tb->lines_list[tb->cy]);
3583 add_str_to_yank(tb, "");
3587 int end = bx2 - bx1;
3588 for (int i = 0; i < bx2 - bx1; i++)
3590 buf[i] = tb->lines_list[tb->cy][bx1 + i];
3594 add_str_to_yank(tb, buf);
3598 tb->dirty_flags |= DIRTY_ALL;
3605 static void draw_text_editor(player_type *player_ptr, text_body_type *tb)
3608 int by1 = 0, by2 = 0;
3610 Term_get_size(&tb->wid, &tb->hgt);
3613 * Top line (-1), description line (-3), separator (-1)
3616 tb->hgt -= 2 + DESCRIPT_HGT;
3619 /* Don't let cursor at second byte of kanji */
3620 for (i = 0; tb->lines_list[tb->cy][i]; i++)
3621 if (iskanji(tb->lines_list[tb->cy][i]))
3627 * Move to a correct position in the
3630 if (i & 1) tb->cx--;
3636 if (tb->cy < tb->upper || tb->upper + tb->hgt <= tb->cy)
3637 tb->upper = tb->cy - (tb->hgt) / 2;
3640 if ((tb->cx < tb->left + 10 && tb->left > 0) || tb->left + tb->wid - 5 <= tb->cx)
3641 tb->left = tb->cx - (tb->wid) * 2 / 3;
3645 if (tb->old_wid != tb->wid || tb->old_hgt != tb->hgt)
3646 tb->dirty_flags |= DIRTY_SCREEN;
3647 else if (tb->old_upper != tb->upper || tb->old_left != tb->left)
3648 tb->dirty_flags |= DIRTY_ALL;
3650 if (tb->dirty_flags & DIRTY_SCREEN)
3652 tb->dirty_flags |= (DIRTY_ALL | DIRTY_MODE);
3656 if (tb->dirty_flags & DIRTY_MODE)
3658 char buf[MAX_LINELEN];
3659 int sepa_length = tb->wid;
3660 for (i = 0; i < sepa_length; i++)
3663 Term_putstr(0, tb->hgt + 1, sepa_length, TERM_WHITE, buf);
3666 if (tb->dirty_flags & DIRTY_EXPRESSION)
3669 for (int y = 0; tb->lines_list[y]; y++)
3673 concptr s = tb->lines_list[y];
3677 tb->states[y] = state;
3679 if (*s++ != '?') continue;
3680 if (*s++ != ':') continue;
3682 if (streq(s, "$AUTOREGISTER"))
3683 state |= LSTAT_AUTOREGISTER;
3686 ss = (char *)string_make(s);
3689 v = process_pref_file_expr(player_ptr, &ss, &f);
3691 if (streq(v, "0")) state |= LSTAT_BYPASS;
3692 else state &= ~LSTAT_BYPASS;
3694 C_KILL(s_keep, s_len + 1, char);
3696 tb->states[y] = state | LSTAT_EXPRESSION;
3699 tb->dirty_flags |= DIRTY_ALL;
3704 tb->dirty_flags |= DIRTY_ALL;
3706 by1 = MIN(tb->my, tb->cy);
3707 by2 = MAX(tb->my, tb->cy);
3710 for (i = 0; i < tb->hgt; i++)
3716 int y = tb->upper + i;
3718 if (!(tb->dirty_flags & DIRTY_ALL) && (tb->dirty_line != y))
3721 msg = tb->lines_list[y];
3724 for (j = 0; *msg; msg++, j++)
3726 if (j == tb->left) break;
3741 Term_erase(0, i + 1, tb->wid);
3742 if (tb->states[y] & LSTAT_AUTOREGISTER)
3748 if (tb->states[y] & LSTAT_BYPASS) color = TERM_SLATE;
3749 else color = TERM_WHITE;
3752 if (!tb->mark || (y < by1 || by2 < y))
3754 Term_putstr(leftcol, i + 1, tb->wid - 1, color, msg);
3756 else if (by1 != by2)
3758 Term_putstr(leftcol, i + 1, tb->wid - 1, TERM_YELLOW, msg);
3762 int x0 = leftcol + tb->left;
3763 int len = strlen(tb->lines_list[tb->cy]);
3764 int bx1 = MIN(tb->mx, tb->cx);
3765 int bx2 = MAX(tb->mx, tb->cx);
3767 if (bx2 > len) bx2 = len;
3769 Term_gotoxy(leftcol, i + 1);
3770 if (x0 < bx1) Term_addstr(bx1 - x0, color, msg);
3771 if (x0 < bx2) Term_addstr(bx2 - bx1, TERM_YELLOW, msg + (bx1 - x0));
3772 Term_addstr(-1, color, msg + (bx2 - x0));
3776 for (; i < tb->hgt; i++)
3778 Term_erase(0, i + 1, tb->wid);
3781 bool is_dirty_diary = (tb->dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND | DIRTY_NO_SEARCH)) != 0;
3782 bool is_updated = tb->old_cy != tb->cy || is_dirty_diary || tb->dirty_line == tb->cy;
3783 if (is_updated) return;
3785 autopick_type an_entry, *entry = &an_entry;
3786 concptr str1 = NULL, str2 = NULL;
3787 for (i = 0; i < DESCRIPT_HGT; i++)
3789 Term_erase(0, tb->hgt + 2 + i, tb->wid);
3792 if (tb->dirty_flags & DIRTY_NOT_FOUND)
3794 str1 = format(_("パターンが見つかりません: %s", "Pattern not found: %s"), tb->search_str);
3796 else if (tb->dirty_flags & DIRTY_SKIP_INACTIVE)
3798 str1 = format(_("無効状態の行をスキップしました。(%sを検索中)",
3799 "Some inactive lines are skipped. (Searching %s)"), tb->search_str);
3801 else if (tb->dirty_flags & DIRTY_INACTIVE)
3803 str1 = format(_("無効状態の行だけが見付かりました。(%sを検索中)",
3804 "Found only an inactive line. (Searching %s)"), tb->search_str);
3806 else if (tb->dirty_flags & DIRTY_NO_SEARCH)
3808 str1 = _("検索するパターンがありません(^S で検索)。", "No pattern to search. (Press ^S to search.)");
3810 else if (tb->lines_list[tb->cy][0] == '#')
3812 str1 = _("この行はコメントです。", "This line is a comment.");
3814 else if (tb->lines_list[tb->cy][0] && tb->lines_list[tb->cy][1] == ':')
3816 switch (tb->lines_list[tb->cy][0])
3819 str1 = _("この行は条件分岐式です。", "This line is a Conditional Expression.");
3822 str1 = _("この行はマクロの実行内容を定義します。", "This line defines a Macro action.");
3825 str1 = _("この行はマクロのトリガー・キーを定義します。", "This line defines a Macro trigger key.");
3828 str1 = _("この行はキー配置を定義します。", "This line defines a Keymap.");
3832 switch (tb->lines_list[tb->cy][0])
3835 if (tb->states[tb->cy] & LSTAT_BYPASS)
3837 str2 = _("現在の式の値は「偽(=0)」です。", "The expression is 'False'(=0) currently.");
3841 str2 = _("現在の式の値は「真(=1)」です。", "The expression is 'True'(=1) currently.");
3846 if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
3848 str2 = _("この行は後で削除されます。", "This line will be delete later.");
3851 else if (tb->states[tb->cy] & LSTAT_BYPASS)
3853 str2 = _("この行は現在は無効な状態です。", "This line is bypassed currently.");
3858 else if (autopick_new_entry(entry, tb->lines_list[tb->cy], FALSE))
3860 char buf[MAX_LINELEN];
3861 char temp[MAX_LINELEN];
3864 describe_autopick(buf, entry);
3866 if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
3868 strcat(buf, _("この行は後で削除されます。", " This line will be delete later."));
3871 if (tb->states[tb->cy] & LSTAT_BYPASS)
3873 strcat(buf, _("この行は現在は無効な状態です。", " This line is bypassed currently."));
3876 roff_to_buf(buf, 81, temp, sizeof(temp));
3878 for (i = 0; i < 3; i++)
3884 prt(t, tb->hgt + 1 + 1 + i, 0);
3888 autopick_free_entry(entry);
3891 if (str1) prt(str1, tb->hgt + 1 + 1, 0);
3892 if (str2) prt(str2, tb->hgt + 1 + 2, 0);
3897 * Kill segment of a line
3899 static void kill_line_segment(text_body_type *tb, int y, int x0, int x1, bool whole)
3901 concptr s = tb->lines_list[y];
3902 if (whole && x0 == 0 && s[x1] == '\0' && tb->lines_list[y + 1])
3904 string_free(tb->lines_list[y]);
3907 for (i = y; tb->lines_list[i + 1]; i++)
3908 tb->lines_list[i] = tb->lines_list[i + 1];
3909 tb->lines_list[i] = NULL;
3911 tb->dirty_flags |= DIRTY_EXPRESSION;
3916 if (x0 == x1) return;
3918 char buf[MAX_LINELEN];
3920 for (int x = 0; x < x0; x++)
3923 for (int x = x1; s[x]; x++)
3927 string_free(tb->lines_list[y]);
3928 tb->lines_list[y] = string_make(buf);
3929 check_expression_line(tb, y);
3935 * Get a trigger key and insert ASCII string for the trigger
3937 static bool insert_macro_line(text_body_type *tb)
3956 ascii_to_text(tmp, buf);
3957 if (!tmp[0]) return FALSE;
3960 insert_return_code(tb);
3961 string_free(tb->lines_list[tb->cy]);
3962 tb->lines_list[tb->cy] = string_make(format("P:%s", tmp));
3964 i = macro_find_exact(buf);
3971 ascii_to_text(tmp, macro__act[i]);
3974 insert_return_code(tb);
3975 string_free(tb->lines_list[tb->cy]);
3976 tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
3983 * Get a command key and insert ASCII string for the key
3985 static bool insert_keymap_line(text_body_type *tb)
3988 if (rogue_like_commands)
3990 mode = KEYMAP_MODE_ROGUE;
3994 mode = KEYMAP_MODE_ORIG;
4004 ascii_to_text(tmp, buf);
4005 if (!tmp[0]) return FALSE;
4008 insert_return_code(tb);
4009 string_free(tb->lines_list[tb->cy]);
4010 tb->lines_list[tb->cy] = string_make(format("C:%d:%s", mode, tmp));
4012 concptr act = keymap_act[mode][(byte)(buf[0])];
4015 ascii_to_text(tmp, act);
4018 insert_return_code(tb);
4019 string_free(tb->lines_list[tb->cy]);
4020 tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
4027 * Execute a single editor command
4029 static bool do_editor_command(player_type *player_ptr, text_body_type *tb, int com_id)
4036 if (!get_check(_("全ての変更を破棄してから終了します。よろしいですか? ",
4037 "Discard all changes and quit. Are you sure? "))) break;
4040 return QUIT_WITHOUT_SAVE;
4043 return QUIT_AND_SAVE;
4046 if (!get_check(_("全ての変更を破棄して元の状態に戻します。よろしいですか? ",
4047 "Discard all changes and revert to original file. Are you sure? "))) break;
4049 free_text_lines(tb->lines_list);
4050 tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
4051 tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
4052 tb->cx = tb->cy = 0;
4055 tb->changed = FALSE;
4059 (void)show_file(player_ptr, TRUE, _("jeditor.txt", "editor.txt"), NULL, 0, 0);
4060 tb->dirty_flags |= DIRTY_SCREEN;
4068 tb->dirty_flags |= DIRTY_ALL;
4071 insert_return_code(tb);
4075 tb->dirty_flags |= DIRTY_ALL;
4087 len = strlen(tb->lines_list[tb->cy]);
4088 if (len < tb->cx) tb->cx = len;
4090 for (i = 0; tb->lines_list[tb->cy][i]; i++)
4092 if (iskanji(tb->lines_list[tb->cy][i]))
4104 else if (tb->cy > 0)
4107 tb->cx = strlen(tb->lines_list[tb->cy]);
4113 if (!tb->lines_list[tb->cy + 1])
4115 if (!add_empty_line(tb)) break;
4122 if (tb->cy > 0) tb->cy--;
4128 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
4131 int len = strlen(tb->lines_list[tb->cy]);
4135 if (!tb->lines_list[tb->cy + 1])
4137 if (!add_empty_line(tb)) break;
4151 tb->cx = strlen(tb->lines_list[tb->cy]);
4155 while (0 < tb->cy && tb->upper <= tb->cy)
4157 while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt)
4162 while (tb->cy < tb->upper + tb->hgt)
4164 if (!tb->lines_list[tb->cy + 1])
4166 if (!add_empty_line(tb)) break;
4182 if (!tb->lines_list[tb->cy + 1])
4184 if (!add_empty_line(tb)) break;
4195 copy_text_to_yank(tb);
4196 if (tb->my == tb->cy)
4198 int bx1 = MIN(tb->mx, tb->cx);
4199 int bx2 = MAX(tb->mx, tb->cx);
4200 int len = strlen(tb->lines_list[tb->cy]);
4201 if (bx2 > len) bx2 = len;
4203 kill_line_segment(tb, tb->cy, bx1, bx2, TRUE);
4208 int by1 = MIN(tb->my, tb->cy);
4209 int by2 = MAX(tb->my, tb->cy);
4211 for (int y = by2; y >= by1; y--)
4213 int len = strlen(tb->lines_list[y]);
4215 kill_line_segment(tb, y, 0, len, TRUE);
4223 tb->dirty_flags |= DIRTY_ALL;
4228 copy_text_to_yank(tb);
4231 * Move cursor position to the end of the selection
4233 * Pressing ^C ^V correctly duplicates the selection.
4235 if (tb->my != tb->cy)
4237 tb->cy = MAX(tb->cy, tb->my);
4238 if (!tb->lines_list[tb->cy + 1])
4240 if (!add_empty_line(tb)) break;
4247 tb->cx = MAX(tb->cx, tb->mx);
4248 if (!tb->lines_list[tb->cy][tb->cx])
4250 if (!tb->lines_list[tb->cy + 1])
4252 if (!add_empty_line(tb)) break;
4263 chain_str_type *chain = tb->yank;
4264 int len = strlen(tb->lines_list[tb->cy]);
4266 if (tb->cx > len) tb->cx = len;
4271 tb->dirty_flags |= DIRTY_ALL;
4276 concptr yank_str = chain->s;
4277 char buf[MAX_LINELEN];
4279 char rest[MAX_LINELEN], *rest_ptr = rest;
4280 for (i = 0; i < tb->cx; i++)
4281 buf[i] = tb->lines_list[tb->cy][i];
4283 strcpy(rest, &(tb->lines_list[tb->cy][i]));
4284 while (*yank_str && i < MAX_LINELEN - 1)
4286 buf[i++] = *yank_str++;
4290 chain = chain->next;
4291 if (chain || tb->yank_eol)
4293 insert_return_code(tb);
4294 string_free(tb->lines_list[tb->cy]);
4295 tb->lines_list[tb->cy] = string_make(buf);
4302 tb->cx = strlen(buf);
4303 while (*rest_ptr && i < MAX_LINELEN - 1)
4305 buf[i++] = *rest_ptr++;
4309 string_free(tb->lines_list[tb->cy]);
4310 tb->lines_list[tb->cy] = string_make(buf);
4314 tb->dirty_flags |= DIRTY_ALL;
4315 tb->dirty_flags |= DIRTY_EXPRESSION;
4324 tb->dirty_flags |= DIRTY_ALL;
4328 tb->mark = MARK_MARK;
4329 if (com_id == tb->old_com_id)
4337 tb->dirty_flags |= DIRTY_ALL;
4341 int len = strlen(tb->lines_list[tb->cy]);
4345 if (tb->cx > len) tb->mx = len;
4350 int len = strlen(tb->lines_list[tb->cy]);
4351 if (tb->cx > len) tb->cx = len;
4356 tb->dirty_flags |= DIRTY_ALL;
4359 if (tb->old_com_id != com_id)
4361 kill_yank_chain(tb);
4367 add_str_to_yank(tb, &(tb->lines_list[tb->cy][tb->cx]));
4368 kill_line_segment(tb, tb->cy, tb->cx, len, FALSE);
4369 tb->dirty_line = tb->cy;
4373 if (tb->yank_eol) add_str_to_yank(tb, "");
4375 tb->yank_eol = TRUE;
4376 do_editor_command(player_ptr, tb, EC_DELETE_CHAR);
4379 case EC_DELETE_CHAR:
4384 tb->dirty_flags |= DIRTY_ALL;
4388 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
4391 int len = strlen(tb->lines_list[tb->cy]);
4394 do_editor_command(player_ptr, tb, EC_BACKSPACE);
4398 if (tb->lines_list[tb->cy + 1])
4409 do_editor_command(player_ptr, tb, EC_BACKSPACE);
4415 char buf[MAX_LINELEN];
4419 tb->dirty_flags |= DIRTY_ALL;
4422 len = strlen(tb->lines_list[tb->cy]);
4423 if (len < tb->cx) tb->cx = len;
4427 if (tb->cy == 0) break;
4428 tb->cx = strlen(tb->lines_list[tb->cy - 1]);
4429 strcpy(buf, tb->lines_list[tb->cy - 1]);
4430 strcat(buf, tb->lines_list[tb->cy]);
4431 string_free(tb->lines_list[tb->cy - 1]);
4432 string_free(tb->lines_list[tb->cy]);
4433 tb->lines_list[tb->cy - 1] = string_make(buf);
4435 for (i = tb->cy; tb->lines_list[i + 1]; i++)
4436 tb->lines_list[i] = tb->lines_list[i + 1];
4438 tb->lines_list[i] = NULL;
4440 tb->dirty_flags |= DIRTY_ALL;
4441 tb->dirty_flags |= DIRTY_EXPRESSION;
4446 for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4450 if (iskanji(tb->lines_list[tb->cy][i]))
4451 buf[j++] = tb->lines_list[tb->cy][i++];
4453 buf[j++] = tb->lines_list[tb->cy][i];
4462 for (; tb->lines_list[tb->cy][i]; i++)
4464 buf[j++] = tb->lines_list[tb->cy][i];
4468 string_free(tb->lines_list[tb->cy]);
4469 tb->lines_list[tb->cy] = string_make(buf);
4470 tb->dirty_line = tb->cy;
4471 check_expression_line(tb, tb->cy);
4478 tb->dirty_flags |= DIRTY_SCREEN;
4479 search_dir = get_string_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str);
4481 if (!search_dir) break;
4483 if (search_dir == 1) do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4484 else do_editor_command(player_ptr, tb, EC_SEARCH_BACK);
4487 case EC_SEARCH_FORW:
4488 if (tb->search_o_ptr)
4490 search_for_object(player_ptr, tb, tb->search_o_ptr, TRUE);
4494 if (tb->search_str && tb->search_str[0])
4496 search_for_string(tb, tb->search_str, TRUE);
4500 tb->dirty_flags |= DIRTY_NO_SEARCH;
4503 case EC_SEARCH_BACK:
4504 if (tb->search_o_ptr)
4506 search_for_object(player_ptr, tb, tb->search_o_ptr, FALSE);
4510 if (tb->search_str && tb->search_str[0])
4512 search_for_string(tb, tb->search_str, FALSE);
4516 tb->dirty_flags |= DIRTY_NO_SEARCH;
4520 tb->dirty_flags |= DIRTY_SCREEN;
4522 if (!get_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str)) break;
4524 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4527 case EC_SEARCH_DESTROYED:
4528 if (!get_destroyed_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str))
4530 tb->dirty_flags |= DIRTY_NO_SEARCH;
4534 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4537 case EC_INSERT_OBJECT:
4539 autopick_type an_entry, *entry = &an_entry;
4540 if (!entry_from_choosed_object(player_ptr, entry))
4542 tb->dirty_flags |= DIRTY_SCREEN;
4547 insert_return_code(tb);
4548 string_free(tb->lines_list[tb->cy]);
4549 tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry);
4550 tb->dirty_flags |= DIRTY_SCREEN;
4553 case EC_INSERT_DESTROYED:
4554 if (!tb->last_destroyed) break;
4557 insert_return_code(tb);
4558 string_free(tb->lines_list[tb->cy]);
4559 tb->lines_list[tb->cy] = string_make(tb->last_destroyed);
4560 tb->dirty_flags |= DIRTY_ALL;
4564 case EC_INSERT_BLOCK:
4566 char expression[80];
4567 sprintf(expression, "?:[AND [EQU $RACE %s] [EQU $CLASS %s] [GEQ $LEVEL %02d]]",
4569 rp_ptr->E_title, cp_ptr->E_title,
4571 rp_ptr->title, cp_ptr->title,
4575 insert_return_code(tb);
4576 string_free(tb->lines_list[tb->cy]);
4577 tb->lines_list[tb->cy] = string_make(expression);
4579 insert_return_code(tb);
4580 string_free(tb->lines_list[tb->cy]);
4581 tb->lines_list[tb->cy] = string_make("?:1");
4582 tb->dirty_flags |= DIRTY_ALL;
4587 case EC_INSERT_MACRO:
4588 draw_text_editor(player_ptr, tb);
4589 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
4590 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, _("P:<トリガーキー>: ", "P:<Trigger key>: "));
4591 if (!insert_macro_line(tb)) break;
4594 tb->dirty_flags |= DIRTY_ALL;
4598 case EC_INSERT_KEYMAP:
4599 draw_text_editor(player_ptr, tb);
4600 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
4601 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW,
4602 format(_("C:%d:<コマンドキー>: ", "C:%d:<Keypress>: "), (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
4604 if (!insert_keymap_line(tb)) break;
4607 tb->dirty_flags |= DIRTY_ALL;
4611 case EC_CL_AUTOPICK: toggle_command_letter(tb, DO_AUTOPICK); break;
4612 case EC_CL_DESTROY: toggle_command_letter(tb, DO_AUTODESTROY); break;
4613 case EC_CL_LEAVE: toggle_command_letter(tb, DONT_AUTOPICK); break;
4614 case EC_CL_QUERY: toggle_command_letter(tb, DO_QUERY_AUTOPICK); break;
4615 case EC_CL_NO_DISP: toggle_command_letter(tb, DO_DISPLAY); break;
4617 case EC_IK_UNAWARE: toggle_keyword(tb, FLG_UNAWARE); break;
4618 case EC_IK_UNIDENTIFIED: toggle_keyword(tb, FLG_UNIDENTIFIED); break;
4619 case EC_IK_IDENTIFIED: toggle_keyword(tb, FLG_IDENTIFIED); break;
4620 case EC_IK_STAR_IDENTIFIED: toggle_keyword(tb, FLG_STAR_IDENTIFIED); break;
4621 case EC_KK_WEAPONS: toggle_keyword(tb, FLG_WEAPONS); break;
4622 case EC_KK_FAVORITE_WEAPONS: toggle_keyword(tb, FLG_FAVORITE_WEAPONS); break;
4623 case EC_KK_ARMORS: toggle_keyword(tb, FLG_ARMORS); break;
4624 case EC_KK_MISSILES: toggle_keyword(tb, FLG_MISSILES); break;
4625 case EC_KK_DEVICES: toggle_keyword(tb, FLG_DEVICES); break;
4626 case EC_KK_LIGHTS: toggle_keyword(tb, FLG_LIGHTS); break;
4627 case EC_KK_JUNKS: toggle_keyword(tb, FLG_JUNKS); break;
4628 case EC_KK_CORPSES: toggle_keyword(tb, FLG_CORPSES); break;
4629 case EC_KK_SPELLBOOKS: toggle_keyword(tb, FLG_SPELLBOOKS); break;
4630 case EC_KK_SHIELDS: toggle_keyword(tb, FLG_SHIELDS); break;
4631 case EC_KK_BOWS: toggle_keyword(tb, FLG_BOWS); break;
4632 case EC_KK_RINGS: toggle_keyword(tb, FLG_RINGS); break;
4633 case EC_KK_AMULETS: toggle_keyword(tb, FLG_AMULETS); break;
4634 case EC_KK_SUITS: toggle_keyword(tb, FLG_SUITS); break;
4635 case EC_KK_CLOAKS: toggle_keyword(tb, FLG_CLOAKS); break;
4636 case EC_KK_HELMS: toggle_keyword(tb, FLG_HELMS); break;
4637 case EC_KK_GLOVES: toggle_keyword(tb, FLG_GLOVES); break;
4638 case EC_KK_BOOTS: toggle_keyword(tb, FLG_BOOTS); break;
4639 case EC_OK_COLLECTING: toggle_keyword(tb, FLG_COLLECTING); break;
4640 case EC_OK_BOOSTED: toggle_keyword(tb, FLG_BOOSTED); break;
4641 case EC_OK_MORE_DICE: toggle_keyword(tb, FLG_MORE_DICE); break;
4642 case EC_OK_MORE_BONUS: toggle_keyword(tb, FLG_MORE_BONUS); break;
4643 case EC_OK_WORTHLESS: toggle_keyword(tb, FLG_WORTHLESS); break;
4644 case EC_OK_ARTIFACT: toggle_keyword(tb, FLG_ARTIFACT); break;
4645 case EC_OK_EGO: toggle_keyword(tb, FLG_EGO); break;
4646 case EC_OK_GOOD: toggle_keyword(tb, FLG_GOOD); break;
4647 case EC_OK_NAMELESS: toggle_keyword(tb, FLG_NAMELESS); break;
4648 case EC_OK_AVERAGE: toggle_keyword(tb, FLG_AVERAGE); break;
4649 case EC_OK_RARE: toggle_keyword(tb, FLG_RARE); break;
4650 case EC_OK_COMMON: toggle_keyword(tb, FLG_COMMON); break;
4651 case EC_OK_WANTED: toggle_keyword(tb, FLG_WANTED); break;
4652 case EC_OK_UNIQUE: toggle_keyword(tb, FLG_UNIQUE); break;
4653 case EC_OK_HUMAN: toggle_keyword(tb, FLG_HUMAN); break;
4654 case EC_OK_UNREADABLE:
4655 toggle_keyword(tb, FLG_UNREADABLE);
4656 add_keyword(tb, FLG_SPELLBOOKS);
4659 toggle_keyword(tb, FLG_REALM1);
4660 add_keyword(tb, FLG_SPELLBOOKS);
4663 toggle_keyword(tb, FLG_REALM2);
4664 add_keyword(tb, FLG_SPELLBOOKS);
4667 toggle_keyword(tb, FLG_FIRST);
4668 add_keyword(tb, FLG_SPELLBOOKS);
4671 toggle_keyword(tb, FLG_SECOND);
4672 add_keyword(tb, FLG_SPELLBOOKS);
4675 toggle_keyword(tb, FLG_THIRD);
4676 add_keyword(tb, FLG_SPELLBOOKS);
4679 toggle_keyword(tb, FLG_FOURTH);
4680 add_keyword(tb, FLG_SPELLBOOKS);
4684 tb->old_com_id = com_id;
4690 * Insert single letter at cursor position.
4692 static void insert_single_letter(text_body_type *tb, int key)
4695 char buf[MAX_LINELEN];
4697 for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4699 buf[j++] = tb->lines_list[tb->cy][i];
4709 if (j + 2 < MAX_LINELEN)
4711 buf[j++] = (char)key;
4712 buf[j++] = (char)next;
4721 if (j + 1 < MAX_LINELEN)
4722 buf[j++] = (char)key;
4726 for (; tb->lines_list[tb->cy][i] && j + 1 < MAX_LINELEN; i++)
4727 buf[j++] = tb->lines_list[tb->cy][i];
4730 string_free(tb->lines_list[tb->cy]);
4731 tb->lines_list[tb->cy] = string_make(buf);
4732 len = strlen(tb->lines_list[tb->cy]);
4733 if (len < tb->cx) tb->cx = len;
4735 tb->dirty_line = tb->cy;
4736 check_expression_line(tb, tb->cy);
4742 * Check special key code and get a movement command id
4744 static int analyze_move_key(text_body_type *tb, int skey)
4747 if (!(skey & SKEY_MASK)) return 0;
4749 switch (skey & ~SKEY_MOD_MASK)
4751 case SKEY_DOWN: com_id = EC_DOWN; break;
4752 case SKEY_LEFT: com_id = EC_LEFT; break;
4753 case SKEY_RIGHT: com_id = EC_RIGHT; break;
4754 case SKEY_UP: com_id = EC_UP; break;
4755 case SKEY_PGUP: com_id = EC_PGUP; break;
4756 case SKEY_PGDOWN: com_id = EC_PGDOWN; break;
4757 case SKEY_TOP: com_id = EC_TOP; break;
4758 case SKEY_BOTTOM: com_id = EC_BOTTOM; break;
4763 if (!(skey & SKEY_MOD_SHIFT))
4766 * Un-shifted cursor keys cancells
4767 * selection created by shift+cursor.
4769 if (tb->mark & MARK_BY_SHIFT)
4772 tb->dirty_flags |= DIRTY_ALL;
4778 if (tb->mark) return com_id;
4780 int len = strlen(tb->lines_list[tb->cy]);
4781 tb->mark = MARK_MARK | MARK_BY_SHIFT;
4784 if (tb->cx > len) tb->mx = len;
4786 if (com_id == EC_UP || com_id == EC_DOWN)
4788 tb->dirty_flags |= DIRTY_ALL;
4792 tb->dirty_line = tb->cy;
4799 * In-game editor of Object Auto-picker/Destoryer
4800 * @param player_ptr プレーヤーへの参照ポインタ
4802 void do_cmd_edit_autopick(player_type *player_ptr)
4804 static int cx_save = 0;
4805 static int cy_save = 0;
4806 text_body_type text_body, *tb = &text_body;
4807 autopick_type an_entry, *entry = &an_entry;
4808 char buf[MAX_LINELEN];
4811 static s32b old_autosave_turn = 0L;
4814 tb->changed = FALSE;
4817 tb->upper = tb->left = 0;
4819 tb->mx = tb->my = 0;
4820 tb->old_cy = tb->old_upper = tb->old_left = -1;
4821 tb->old_wid = tb->old_hgt = -1;
4825 tb->search_o_ptr = NULL;
4826 tb->search_str = NULL;
4827 tb->last_destroyed = NULL;
4828 tb->dirty_flags = DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
4829 tb->dirty_line = -1;
4830 tb->filename_mode = PT_DEFAULT;
4832 if (current_world_ptr->game_turn < old_autosave_turn)
4834 while (old_autosave_turn > current_world_ptr->game_turn) old_autosave_turn -= TURNS_PER_TICK * TOWN_DAWN;
4837 if (current_world_ptr->game_turn > old_autosave_turn + 100L)
4839 do_cmd_save_game(player_ptr, TRUE);
4840 old_autosave_turn = current_world_ptr->game_turn;
4845 if (autopick_last_destroyed_object.k_idx)
4847 autopick_entry_from_object(player_ptr, entry, &autopick_last_destroyed_object);
4848 tb->last_destroyed = autopick_line_from_entry_kill(entry);
4851 tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
4852 for (i = 0; i < tb->cy; i++)
4854 if (!tb->lines_list[i])
4856 tb->cy = tb->cx = 0;
4865 draw_text_editor(player_ptr, tb);
4866 prt(_("(^Q:終了 ^W:セーブして終了, ESC:メニュー, その他:入力)",
4867 "(^Q:Quit, ^W:Save&Quit, ESC:Menu, Other:Input text)"), 0, 0);
4870 prt(format("(%d,%d)", tb->cx, tb->cy), 0, 60);
4874 prt(format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60);
4877 Term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1);
4878 tb->dirty_flags = 0;
4879 tb->dirty_line = -1;
4880 tb->old_cy = tb->cy;
4881 tb->old_upper = tb->upper;
4882 tb->old_left = tb->left;
4883 tb->old_wid = tb->wid;
4884 tb->old_hgt = tb->hgt;
4886 key = inkey_special(TRUE);
4888 if (key & SKEY_MASK)
4890 com_id = analyze_move_key(tb, key);
4892 else if (key == ESCAPE)
4894 com_id = do_command_menu(0, 0);
4895 tb->dirty_flags |= DIRTY_SCREEN;
4897 else if (!iscntrl((unsigned char)key))
4902 tb->dirty_flags |= DIRTY_ALL;
4905 insert_single_letter(tb, key);
4910 com_id = get_com_id((char)key);
4913 if (com_id) quit = do_editor_command(player_ptr, tb, com_id);
4917 strcpy(buf, pickpref_filename(player_ptr, tb->filename_mode));
4919 if (quit == QUIT_AND_SAVE)
4920 write_text_lines(buf, tb->lines_list);
4922 free_text_lines(tb->lines_list);
4923 string_free(tb->search_str);
4924 string_free(tb->last_destroyed);
4925 kill_yank_chain(tb);
4927 process_autopick_file(player_ptr, buf);
4928 current_world_ptr->start_time = (u32b)time(NULL);