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-keys-table.h"
17 #include "autopick/autopick-editor-table.h"
19 #include "autopick/autopick.h"
21 #include "core/show-file.h"
22 #include "cmd/cmd-save.h"
23 #include "io/read-pref-file.h"
27 #include "market/store.h"
28 #include "player-status.h"
29 #include "player-move.h"
30 #include "player-class.h"
31 #include "player-race.h"
32 #include "player-inventory.h"
33 #include "view/display-player.h"
34 #include "object/object-kind.h"
35 #include "object-ego.h"
36 #include "object-flavor.h"
37 #include "object-hook.h"
43 #include "monsterrace.h"
44 #include "view-mainwindow.h" // 暫定。後で消す
46 #define MAX_LINELEN 1024
53 #define FLG_UNIDENTIFIED 2
54 #define FLG_IDENTIFIED 3
55 #define FLG_STAR_IDENTIFIED 4
56 #define FLG_COLLECTING 5
57 #define FLG_ARTIFACT 6
60 #define FLG_NAMELESS 11
61 #define FLG_AVERAGE 12
62 #define FLG_WORTHLESS 13
65 #define FLG_BOOSTED 16
66 #define FLG_MORE_DICE 17
67 #define FLG_MORE_BONUS 18
71 #define FLG_UNREADABLE 22
80 #define FLG_WEAPONS 31
81 #define FLG_FAVORITE_WEAPONS 32
83 #define FLG_MISSILES 34
84 #define FLG_DEVICES 35
87 #define FLG_CORPSES 38
88 #define FLG_SPELLBOOKS 39
90 #define FLG_SHIELDS 41
93 #define FLG_AMULETS 44
100 #define FLG_NOUN_BEGIN FLG_ITEMS
101 #define FLG_NOUN_END FLG_BOOTS
103 #define MAX_AUTOPICK_DEFAULT 200
106 #define PT_WITH_PNAME 1
108 #define MAX_YANK MAX_LINELEN
109 #define MAX_LINES 3000
111 #define MARK_MARK 0x01
112 #define MARK_BY_SHIFT 0x02
114 #define LSTAT_BYPASS 0x01
115 #define LSTAT_EXPRESSION 0x02
116 #define LSTAT_AUTOREGISTER 0x04
118 #define QUIT_WITHOUT_SAVE 1
119 #define QUIT_AND_SAVE 2
122 * Dirty flag for text editor
124 #define DIRTY_ALL 0x0001
125 #define DIRTY_MODE 0x0004
126 #define DIRTY_SCREEN 0x0008
127 #define DIRTY_NOT_FOUND 0x0010
128 #define DIRTY_NO_SEARCH 0x0020
129 #define DIRTY_EXPRESSION 0x0040
130 #define DIRTY_SKIP_INACTIVE 0x0080
131 #define DIRTY_INACTIVE 0x0100
133 #define DESCRIPT_HGT 3
135 #define MATCH_KEY(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
136 ? (ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
137 #define MATCH_KEY2(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
138 ? (prev_ptr = ptr, ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
141 #define ADD_KEY(KEY) strcat(ptr, KEY)
143 #define ADD_KEY(KEY) (strcat(ptr, KEY), strcat(ptr, " "))
145 #define ADD_KEY2(KEY) strcat(ptr, KEY)
147 #define ADD_FLG(FLG) (entry->flag[FLG / 32] |= (1L << (FLG % 32)))
148 #define REM_FLG(FLG) (entry->flag[FLG / 32] &= ~(1L << (FLG % 32)))
149 #define ADD_FLG_NOUN(FLG) (ADD_FLG(FLG), prev_flg = FLG)
150 #define IS_FLG(FLG) (entry->flag[FLG / 32] & (1L << (FLG % 32)))
153 static char kanji_colon[] = ":";
157 * 自動拾い/破壊設定のリストに関する変数 / List for auto-picker/destroyer entries
159 int max_autopick = 0; /*!< 現在登録している自動拾い/破壊設定の数 */
160 int max_max_autopick = 0; /*!< 自動拾い/破壊設定の限界数 */
161 autopick_type *autopick_list = NULL; /*!< 自動拾い/破壊設定構造体のポインタ配列 */
164 * Automatically destroy an item if it is to be destroyed
166 * When always_pickup is 'yes', we disable auto-destroyer function of
167 * auto-picker/destroyer, and do only easy-auto-destroyer.
169 static object_type autopick_last_destroyed_object;
172 * Struct for yank buffer
174 typedef struct chain_str {
175 struct chain_str *next;
180 * Data struct for text editor
186 int old_wid, old_hgt;
188 int old_upper, old_left;
192 object_type *search_o_ptr;
194 concptr last_destroyed;
196 chain_str_type *yank;
200 byte states[MAX_LINES];
211 * Editor command id's
214 #define EC_SAVEQUIT 2
232 #define EC_KILL_LINE 20
233 #define EC_DELETE_CHAR 21
234 #define EC_BACKSPACE 22
235 #define EC_SEARCH_STR 23
236 #define EC_SEARCH_FORW 24
237 #define EC_SEARCH_BACK 25
238 #define EC_SEARCH_OBJ 26
239 #define EC_SEARCH_DESTROYED 27
240 #define EC_INSERT_OBJECT 28
241 #define EC_INSERT_DESTROYED 29
242 #define EC_INSERT_BLOCK 30
243 #define EC_INSERT_MACRO 31
244 #define EC_INSERT_KEYMAP 32
245 #define EC_CL_AUTOPICK 33
246 #define EC_CL_DESTROY 34
247 #define EC_CL_LEAVE 35
248 #define EC_CL_QUERY 36
249 #define EC_CL_NO_DISP 37
250 #define EC_OK_COLLECTING 38
251 #define EC_IK_UNAWARE 39
252 #define EC_IK_UNIDENTIFIED 40
253 #define EC_IK_IDENTIFIED 41
254 #define EC_IK_STAR_IDENTIFIED 42
255 #define EC_OK_BOOSTED 43
256 #define EC_OK_MORE_DICE 44
257 #define EC_OK_MORE_BONUS 45
258 #define EC_OK_WORTHLESS 46
259 #define EC_OK_ARTIFACT 47
261 #define EC_OK_GOOD 49
262 #define EC_OK_NAMELESS 50
263 #define EC_OK_AVERAGE 51
264 #define EC_OK_RARE 52
265 #define EC_OK_COMMON 53
266 #define EC_OK_WANTED 54
267 #define EC_OK_UNIQUE 55
268 #define EC_OK_HUMAN 56
269 #define EC_OK_UNREADABLE 57
270 #define EC_OK_REALM1 58
271 #define EC_OK_REALM2 59
272 #define EC_OK_FIRST 60
273 #define EC_OK_SECOND 61
274 #define EC_OK_THIRD 62
275 #define EC_OK_FOURTH 63
276 #define EC_KK_WEAPONS 64
277 #define EC_KK_FAVORITE_WEAPONS 65
278 #define EC_KK_ARMORS 66
279 #define EC_KK_MISSILES 67
280 #define EC_KK_DEVICES 68
281 #define EC_KK_LIGHTS 69
282 #define EC_KK_JUNKS 70
283 #define EC_KK_CORPSES 71
284 #define EC_KK_SPELLBOOKS 72
285 #define EC_KK_SHIELDS 73
286 #define EC_KK_BOWS 74
287 #define EC_KK_RINGS 75
288 #define EC_KK_AMULETS 76
289 #define EC_KK_SUITS 77
290 #define EC_KK_CLOAKS 78
291 #define EC_KK_HELMS 79
292 #define EC_KK_GLOVES 80
293 #define EC_KK_BOOTS 81
302 command_menu_type menu_data[] =
304 {MN_HELP, 0, -1, EC_HELP},
305 {MN_QUIT, 0, KTRL('q'), EC_QUIT},
306 {MN_SAVEQUIT, 0, KTRL('w'), EC_SAVEQUIT},
307 {MN_REVERT, 0, KTRL('z'), EC_REVERT},
309 {MN_EDIT, 0, -1, -1},
310 {MN_CUT, 1, KTRL('x'), EC_CUT},
311 {MN_COPY, 1, KTRL('c'), EC_COPY},
312 {MN_PASTE, 1, KTRL('v'), EC_PASTE},
313 {MN_BLOCK, 1, KTRL('g'), EC_BLOCK},
314 {MN_KILL_LINE, 1, KTRL('k'), EC_KILL_LINE},
315 {MN_DELETE_CHAR, 1, KTRL('d'), EC_DELETE_CHAR},
316 {MN_BACKSPACE, 1, KTRL('h'), EC_BACKSPACE},
317 {MN_RETURN, 1, KTRL('j'), EC_RETURN},
318 {MN_RETURN, 1, KTRL('m'), EC_RETURN},
320 {MN_SEARCH, 0, -1, -1},
321 {MN_SEARCH_STR, 1, KTRL('s'), EC_SEARCH_STR},
322 {MN_SEARCH_FORW, 1, -1, EC_SEARCH_FORW},
323 {MN_SEARCH_BACK, 1, KTRL('r'), EC_SEARCH_BACK},
324 {MN_SEARCH_OBJ, 1, KTRL('y'), EC_SEARCH_OBJ},
325 {MN_SEARCH_DESTROYED, 1, -1, EC_SEARCH_DESTROYED},
327 {MN_MOVE, 0, -1, -1},
328 {MN_LEFT, 1, KTRL('b'), EC_LEFT},
329 {MN_DOWN, 1, KTRL('n'), EC_DOWN},
330 {MN_UP, 1, KTRL('p'), EC_UP},
331 {MN_RIGHT, 1, KTRL('f'), EC_RIGHT},
332 {MN_BOL, 1, KTRL('a'), EC_BOL},
333 {MN_EOL, 1, KTRL('e'), EC_EOL},
334 {MN_PGUP, 1, KTRL('o'), EC_PGUP},
335 {MN_PGDOWN, 1, KTRL('l'), EC_PGDOWN},
336 {MN_TOP, 1, KTRL('t'), EC_TOP},
337 {MN_BOTTOM, 1, KTRL('u'), EC_BOTTOM},
339 {MN_INSERT, 0, -1, -1},
340 {MN_INSERT_OBJECT, 1, KTRL('i'), EC_INSERT_OBJECT},
341 {MN_INSERT_DESTROYED, 1, -1, EC_INSERT_DESTROYED},
342 {MN_INSERT_BLOCK, 1, -1, EC_INSERT_BLOCK},
343 {MN_INSERT_MACRO, 1, -1, EC_INSERT_MACRO},
344 {MN_INSERT_KEYMAP, 1, -1, EC_INSERT_KEYMAP},
346 {MN_ADJECTIVE_GEN, 0, -1, -1},
347 {KEY_UNAWARE, 1, -1, EC_IK_UNAWARE},
348 {KEY_UNIDENTIFIED, 1, -1, EC_IK_UNIDENTIFIED},
349 {KEY_IDENTIFIED, 1, -1, EC_IK_IDENTIFIED},
350 {KEY_STAR_IDENTIFIED, 1, -1, EC_IK_STAR_IDENTIFIED},
351 {KEY_COLLECTING, 1, -1, EC_OK_COLLECTING},
352 {KEY_ARTIFACT, 1, -1, EC_OK_ARTIFACT},
353 {KEY_EGO, 1, -1, EC_OK_EGO},
354 {KEY_GOOD, 1, -1, EC_OK_GOOD},
355 {KEY_NAMELESS, 1, -1, EC_OK_NAMELESS},
356 {KEY_AVERAGE, 1, -1, EC_OK_AVERAGE},
357 {KEY_WORTHLESS, 1, -1, EC_OK_WORTHLESS},
358 {MN_RARE, 1, -1, EC_OK_RARE},
359 {MN_COMMON, 1, -1, EC_OK_COMMON},
361 {MN_ADJECTIVE_SPECIAL, 0, -1, -1},
362 {MN_BOOSTED, 1, -1, EC_OK_BOOSTED},
363 {MN_MORE_DICE, 1, -1, EC_OK_MORE_DICE},
364 {MN_MORE_BONUS, 1, -1, EC_OK_MORE_BONUS},
365 {MN_WANTED, 1, -1, EC_OK_WANTED},
366 {MN_UNIQUE, 1, -1, EC_OK_UNIQUE},
367 {MN_HUMAN, 1, -1, EC_OK_HUMAN},
368 {MN_UNREADABLE, 1, -1, EC_OK_UNREADABLE},
369 {MN_REALM1, 1, -1, EC_OK_REALM1},
370 {MN_REALM2, 1, -1, EC_OK_REALM2},
371 {MN_FIRST, 1, -1, EC_OK_FIRST},
372 {MN_SECOND, 1, -1, EC_OK_SECOND},
373 {MN_THIRD, 1, -1, EC_OK_THIRD},
374 {MN_FOURTH, 1, -1, EC_OK_FOURTH},
376 {MN_NOUN, 0, -1, -1},
377 {KEY_WEAPONS, 1, -1, EC_KK_WEAPONS},
378 {KEY_FAVORITE_WEAPONS, 1, -1, EC_KK_FAVORITE_WEAPONS},
379 {KEY_ARMORS, 1, -1, EC_KK_ARMORS},
380 {KEY_MISSILES, 1, -1, EC_KK_MISSILES},
381 {KEY_DEVICES, 1, -1, EC_KK_DEVICES},
382 {KEY_LIGHTS, 1, -1, EC_KK_LIGHTS},
383 {KEY_JUNKS, 1, -1, EC_KK_JUNKS},
384 {KEY_CORPSES, 1, -1, EC_KK_CORPSES},
385 {KEY_SPELLBOOKS, 1, -1, EC_KK_SPELLBOOKS},
386 {KEY_SHIELDS, 1, -1, EC_KK_SHIELDS},
387 {KEY_BOWS, 1, -1, EC_KK_BOWS},
388 {KEY_RINGS, 1, -1, EC_KK_RINGS},
389 {KEY_AMULETS, 1, -1, EC_KK_AMULETS},
390 {KEY_SUITS, 1, -1, EC_KK_SUITS},
391 {KEY_CLOAKS, 1, -1, EC_KK_CLOAKS},
392 {KEY_HELMS, 1, -1, EC_KK_HELMS},
393 {KEY_GLOVES, 1, -1, EC_KK_GLOVES},
394 {KEY_BOOTS, 1, -1, EC_KK_BOOTS},
396 {MN_COMMAND_LETTER, 0, -1, -1},
397 {MN_CL_AUTOPICK, 1, -1, EC_CL_AUTOPICK},
398 {MN_CL_DESTROY, 1, -1, EC_CL_DESTROY},
399 {MN_CL_LEAVE, 1, -1, EC_CL_LEAVE},
400 {MN_CL_QUERY, 1, -1, EC_CL_QUERY},
401 {MN_CL_NO_DISP, 1, -1, EC_CL_NO_DISP},
403 {MN_DELETE_CHAR, -1, 0x7F, EC_DELETE_CHAR},
409 * A function to create new entry
411 static bool autopick_new_entry(autopick_type *entry, concptr str, bool allow_default)
413 if (str[0] && str[1] == ':') switch (str[0])
416 case 'A': case 'P': case 'C':
420 entry->flag[0] = entry->flag[1] = 0L;
424 byte act = DO_AUTOPICK | DO_DISPLAY;
427 if ((act & DO_AUTOPICK) && *str == '!')
430 act |= DO_AUTODESTROY;
435 if ((act & DO_AUTOPICK) && *str == '~')
438 act |= DONT_AUTOPICK;
443 if ((act & DO_AUTOPICK) && *str == ';')
446 act |= DO_QUERY_AUTOPICK;
451 if ((act & DO_DISPLAY) && *str == '(')
462 char buf[MAX_LINELEN];
464 for (i = 0; *str; i++)
482 if (isupper(c)) c = (char)tolower(c);
488 if (!allow_default && *buf == 0) return FALSE;
489 if (*buf == 0 && insc) return FALSE;
491 concptr prev_ptr, ptr;
492 ptr = prev_ptr = buf;
493 concptr old_ptr = NULL;
494 while (old_ptr != ptr)
497 if (MATCH_KEY(KEY_ALL)) ADD_FLG(FLG_ALL);
498 if (MATCH_KEY(KEY_COLLECTING)) ADD_FLG(FLG_COLLECTING);
499 if (MATCH_KEY(KEY_UNAWARE)) ADD_FLG(FLG_UNAWARE);
500 if (MATCH_KEY(KEY_UNIDENTIFIED)) ADD_FLG(FLG_UNIDENTIFIED);
501 if (MATCH_KEY(KEY_IDENTIFIED)) ADD_FLG(FLG_IDENTIFIED);
502 if (MATCH_KEY(KEY_STAR_IDENTIFIED)) ADD_FLG(FLG_STAR_IDENTIFIED);
503 if (MATCH_KEY(KEY_BOOSTED)) ADD_FLG(FLG_BOOSTED);
505 /*** Weapons whose dd*ds is more than nn ***/
506 if (MATCH_KEY2(KEY_MORE_THAN))
511 while (' ' == *ptr) ptr++;
513 while ('0' <= *ptr && *ptr <= '9')
515 entry->dice = 10 * entry->dice + (*ptr - '0');
522 (void)MATCH_KEY(KEY_DICE);
523 ADD_FLG(FLG_MORE_DICE);
529 /*** Items whose magical bonus is more than n ***/
530 if (MATCH_KEY2(KEY_MORE_BONUS))
535 while (' ' == *ptr) ptr++;
537 while ('0' <= *ptr && *ptr <= '9')
539 entry->bonus = 10 * entry->bonus + (*ptr - '0');
547 (void)MATCH_KEY(KEY_MORE_BONUS2);
549 if (' ' == *ptr) ptr++;
551 ADD_FLG(FLG_MORE_BONUS);
557 if (MATCH_KEY(KEY_WORTHLESS)) ADD_FLG(FLG_WORTHLESS);
558 if (MATCH_KEY(KEY_EGO)) ADD_FLG(FLG_EGO);
559 if (MATCH_KEY(KEY_GOOD)) ADD_FLG(FLG_GOOD);
560 if (MATCH_KEY(KEY_NAMELESS)) ADD_FLG(FLG_NAMELESS);
561 if (MATCH_KEY(KEY_AVERAGE)) ADD_FLG(FLG_AVERAGE);
562 if (MATCH_KEY(KEY_RARE)) ADD_FLG(FLG_RARE);
563 if (MATCH_KEY(KEY_COMMON)) ADD_FLG(FLG_COMMON);
564 if (MATCH_KEY(KEY_WANTED)) ADD_FLG(FLG_WANTED);
565 if (MATCH_KEY(KEY_UNIQUE)) ADD_FLG(FLG_UNIQUE);
566 if (MATCH_KEY(KEY_HUMAN)) ADD_FLG(FLG_HUMAN);
567 if (MATCH_KEY(KEY_UNREADABLE)) ADD_FLG(FLG_UNREADABLE);
568 if (MATCH_KEY(KEY_REALM1)) ADD_FLG(FLG_REALM1);
569 if (MATCH_KEY(KEY_REALM2)) ADD_FLG(FLG_REALM2);
570 if (MATCH_KEY(KEY_FIRST)) ADD_FLG(FLG_FIRST);
571 if (MATCH_KEY(KEY_SECOND)) ADD_FLG(FLG_SECOND);
572 if (MATCH_KEY(KEY_THIRD)) ADD_FLG(FLG_THIRD);
573 if (MATCH_KEY(KEY_FOURTH)) ADD_FLG(FLG_FOURTH);
577 if (MATCH_KEY2(KEY_ARTIFACT)) ADD_FLG_NOUN(FLG_ARTIFACT);
579 if (MATCH_KEY2(KEY_ITEMS)) ADD_FLG_NOUN(FLG_ITEMS);
580 else if (MATCH_KEY2(KEY_WEAPONS)) ADD_FLG_NOUN(FLG_WEAPONS);
581 else if (MATCH_KEY2(KEY_FAVORITE_WEAPONS)) ADD_FLG_NOUN(FLG_FAVORITE_WEAPONS);
582 else if (MATCH_KEY2(KEY_ARMORS)) ADD_FLG_NOUN(FLG_ARMORS);
583 else if (MATCH_KEY2(KEY_MISSILES)) ADD_FLG_NOUN(FLG_MISSILES);
584 else if (MATCH_KEY2(KEY_DEVICES)) ADD_FLG_NOUN(FLG_DEVICES);
585 else if (MATCH_KEY2(KEY_LIGHTS)) ADD_FLG_NOUN(FLG_LIGHTS);
586 else if (MATCH_KEY2(KEY_JUNKS)) ADD_FLG_NOUN(FLG_JUNKS);
587 else if (MATCH_KEY2(KEY_CORPSES)) ADD_FLG_NOUN(FLG_CORPSES);
588 else if (MATCH_KEY2(KEY_SPELLBOOKS)) ADD_FLG_NOUN(FLG_SPELLBOOKS);
589 else if (MATCH_KEY2(KEY_HAFTED)) ADD_FLG_NOUN(FLG_HAFTED);
590 else if (MATCH_KEY2(KEY_SHIELDS)) ADD_FLG_NOUN(FLG_SHIELDS);
591 else if (MATCH_KEY2(KEY_BOWS)) ADD_FLG_NOUN(FLG_BOWS);
592 else if (MATCH_KEY2(KEY_RINGS)) ADD_FLG_NOUN(FLG_RINGS);
593 else if (MATCH_KEY2(KEY_AMULETS)) ADD_FLG_NOUN(FLG_AMULETS);
594 else if (MATCH_KEY2(KEY_SUITS)) ADD_FLG_NOUN(FLG_SUITS);
595 else if (MATCH_KEY2(KEY_CLOAKS)) ADD_FLG_NOUN(FLG_CLOAKS);
596 else if (MATCH_KEY2(KEY_HELMS)) ADD_FLG_NOUN(FLG_HELMS);
597 else if (MATCH_KEY2(KEY_GLOVES)) ADD_FLG_NOUN(FLG_GLOVES);
598 else if (MATCH_KEY2(KEY_BOOTS)) ADD_FLG_NOUN(FLG_BOOTS);
603 else if (ptr[0] == kanji_colon[0] && ptr[1] == kanji_colon[1])
606 else if (*ptr == '\0')
609 ADD_FLG_NOUN(FLG_ITEMS);
615 entry->flag[prev_flg / 32] &= ~(1L << (prev_flg % 32));
620 entry->name = string_make(ptr);
622 entry->insc = string_make(insc);
629 * Get auto-picker entry from o_ptr.
631 static void autopick_entry_from_object(player_type *player_ptr, autopick_type *entry, object_type *o_ptr)
633 /* Assume that object name is to be added */
637 /* エゴ銘が邪魔かもしれないので、デフォルトで「^」は付けない */
638 bool bol_mark = FALSE;
640 /* We can always use the ^ mark in English */
641 bool bol_mark = TRUE;
644 GAME_TEXT name_str[MAX_NLEN];
647 entry->insc = string_make(quark_str(o_ptr->inscription));
648 entry->action = DO_AUTOPICK | DO_DISPLAY;
649 entry->flag[0] = entry->flag[1] = 0L;
652 if (!object_is_aware(o_ptr))
654 ADD_FLG(FLG_UNAWARE);
657 else if (!object_is_known(o_ptr))
659 if (!(o_ptr->ident & IDENT_SENSE))
661 ADD_FLG(FLG_UNIDENTIFIED);
666 switch (o_ptr->feeling)
670 ADD_FLG(FLG_NAMELESS);
676 ADD_FLG(FLG_NAMELESS);
677 ADD_FLG(FLG_WORTHLESS);
683 ADD_FLG(FLG_WORTHLESS);
700 if (object_is_ego(o_ptr))
702 if (object_is_weapon_armour_ammo(o_ptr))
705 * Base name of ego weapons and armors
706 * are almost meaningless.
707 * Register the ego type only.
709 ego_item_type *e_ptr = &e_info[o_ptr->name2];
711 /* エゴ銘には「^」マークが使える */
712 sprintf(name_str, "^%s", e_name + e_ptr->name);
714 /* We ommit the basename and cannot use the ^ mark */
715 strcpy(name_str, e_name + e_ptr->name);
718 if (!object_is_rare(o_ptr)) ADD_FLG(FLG_COMMON);
723 else if (object_is_artifact(o_ptr))
724 ADD_FLG(FLG_ARTIFACT);
727 if (object_is_equipment(o_ptr))
728 ADD_FLG(FLG_NAMELESS);
735 if (object_is_melee_weapon(o_ptr))
737 object_kind *k_ptr = &k_info[o_ptr->k_idx];
739 if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
740 ADD_FLG(FLG_BOOSTED);
743 if (object_is_bounty(o_ptr))
745 REM_FLG(FLG_WORTHLESS);
749 if ((o_ptr->tval == TV_CORPSE || o_ptr->tval == TV_STATUE)
750 && (r_info[o_ptr->pval].flags1 & RF1_UNIQUE))
755 if (o_ptr->tval == TV_CORPSE && my_strchr("pht", r_info[o_ptr->pval].d_char))
760 if (o_ptr->tval >= TV_LIFE_BOOK &&
761 !check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval))
763 ADD_FLG(FLG_UNREADABLE);
764 if (o_ptr->tval != TV_ARCANE_BOOK) name = FALSE;
767 if (REALM1_BOOK == o_ptr->tval &&
768 player_ptr->pclass != CLASS_SORCERER &&
769 player_ptr->pclass != CLASS_RED_MAGE)
775 if (REALM2_BOOK == o_ptr->tval &&
776 player_ptr->pclass != CLASS_SORCERER &&
777 player_ptr->pclass != CLASS_RED_MAGE)
783 if (o_ptr->tval >= TV_LIFE_BOOK && 0 == o_ptr->sval)
785 if (o_ptr->tval >= TV_LIFE_BOOK && 1 == o_ptr->sval)
787 if (o_ptr->tval >= TV_LIFE_BOOK && 2 == o_ptr->sval)
789 if (o_ptr->tval >= TV_LIFE_BOOK && 3 == o_ptr->sval)
792 if (object_is_ammo(o_ptr))
793 ADD_FLG(FLG_MISSILES);
794 else if (o_ptr->tval == TV_SCROLL || o_ptr->tval == TV_STAFF
795 || o_ptr->tval == TV_WAND || o_ptr->tval == TV_ROD)
796 ADD_FLG(FLG_DEVICES);
797 else if (o_ptr->tval == TV_LITE)
799 else if (o_ptr->tval == TV_SKELETON || o_ptr->tval == TV_BOTTLE
800 || o_ptr->tval == TV_JUNK || o_ptr->tval == TV_STATUE)
802 else if (o_ptr->tval == TV_CORPSE)
803 ADD_FLG(FLG_CORPSES);
804 else if (o_ptr->tval >= TV_LIFE_BOOK)
805 ADD_FLG(FLG_SPELLBOOKS);
806 else if (o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_SWORD
807 || o_ptr->tval == TV_DIGGING || o_ptr->tval == TV_HAFTED)
808 ADD_FLG(FLG_WEAPONS);
809 else if (o_ptr->tval == TV_SHIELD)
810 ADD_FLG(FLG_SHIELDS);
811 else if (o_ptr->tval == TV_BOW)
813 else if (o_ptr->tval == TV_RING)
815 else if (o_ptr->tval == TV_AMULET)
816 ADD_FLG(FLG_AMULETS);
817 else if (o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_HARD_ARMOR ||
818 o_ptr->tval == TV_SOFT_ARMOR)
820 else if (o_ptr->tval == TV_CLOAK)
822 else if (o_ptr->tval == TV_HELM)
824 else if (o_ptr->tval == TV_GLOVES)
826 else if (o_ptr->tval == TV_BOOTS)
831 str_tolower(name_str);
832 entry->name = string_make(name_str);
836 GAME_TEXT o_name[MAX_NLEN];
837 object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL | OD_NAME_ONLY));
840 * If necessary, add a '^' which indicates the
843 sprintf(name_str, "%s%s", bol_mark ? "^" : "", o_name);
844 str_tolower(name_str);
845 entry->name = string_make(name_str);
850 * A function to delete entry
852 static void autopick_free_entry(autopick_type *entry)
854 string_free(entry->name);
855 string_free(entry->insc);
862 * Initialize the autopick
864 static void init_autopick(void)
866 static const char easy_autopick_inscription[] = "(:=g";
872 max_max_autopick = MAX_AUTOPICK_DEFAULT;
873 C_MAKE(autopick_list, max_max_autopick, autopick_type);
877 for (i = 0; i < max_autopick; i++)
878 autopick_free_entry(&autopick_list[i]);
881 autopick_new_entry(&entry, easy_autopick_inscription, TRUE);
882 autopick_list[max_autopick++] = entry;
887 * Get file name for autopick preference
889 static concptr pickpref_filename(player_type *player_ptr, int filename_mode)
891 static const char namebase[] = _("picktype", "pickpref");
893 switch (filename_mode)
896 return format("%s.prf", namebase);
899 return format("%s-%s.prf", namebase, player_ptr->base_name);
908 * Load an autopick preference file
910 void autopick_load_pref(player_type *player_ptr, bool disp_mes)
914 my_strcpy(buf, pickpref_filename(player_ptr, PT_WITH_PNAME), sizeof(buf));
915 errr err = process_autopick_file(player_ptr, buf);
916 if (err == 0 && disp_mes)
918 msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf);
923 my_strcpy(buf, pickpref_filename(player_ptr, PT_DEFAULT), sizeof(buf));
924 err = process_autopick_file(player_ptr, buf);
925 if (err == 0 && disp_mes)
927 msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf);
933 msg_print(_("自動拾い設定ファイルの読み込みに失敗しました。", "Failed to reload autopick preference."));
939 * Add one line to autopick_list[]
941 static void add_autopick_list(autopick_type *entry)
943 if (max_autopick >= max_max_autopick)
945 int old_max_max_autopick = max_max_autopick;
946 autopick_type *old_autopick_list = autopick_list;
947 max_max_autopick += MAX_AUTOPICK_DEFAULT;
948 C_MAKE(autopick_list, max_max_autopick, autopick_type);
949 (void)C_COPY(autopick_list, old_autopick_list, old_max_max_autopick, autopick_type);
950 C_KILL(old_autopick_list, old_max_max_autopick, autopick_type);
953 autopick_list[max_autopick] = *entry;
959 * Process line for auto picker/destroyer.
961 void process_autopick_file_command(char *buf)
963 autopick_type an_entry, *entry = &an_entry;
965 for (i = 0; buf[i]; i++)
974 if (iswspace(buf[i]) && buf[i] != ' ')
979 if (!autopick_new_entry(entry, buf, FALSE)) return;
981 for (i = 0; i < max_autopick; i++)
983 if (!strcmp(entry->name, autopick_list[i].name)
984 && entry->flag[0] == autopick_list[i].flag[0]
985 && entry->flag[1] == autopick_list[i].flag[1]
986 && entry->dice == autopick_list[i].dice
987 && entry->bonus == autopick_list[i].bonus)
989 autopick_free_entry(entry);
994 add_autopick_list(entry);
1000 * Reconstruct preference line from entry
1002 concptr autopick_line_from_entry(autopick_type *entry)
1004 char buf[MAX_LINELEN];
1006 if (!(entry->action & DO_DISPLAY)) strcat(buf, "(");
1007 if (entry->action & DO_QUERY_AUTOPICK) strcat(buf, ";");
1008 if (entry->action & DO_AUTODESTROY) strcat(buf, "!");
1009 if (entry->action & DONT_AUTOPICK) strcat(buf, "~");
1013 if (IS_FLG(FLG_ALL)) ADD_KEY(KEY_ALL);
1014 if (IS_FLG(FLG_COLLECTING)) ADD_KEY(KEY_COLLECTING);
1015 if (IS_FLG(FLG_UNAWARE)) ADD_KEY(KEY_UNAWARE);
1016 if (IS_FLG(FLG_UNIDENTIFIED)) ADD_KEY(KEY_UNIDENTIFIED);
1017 if (IS_FLG(FLG_IDENTIFIED)) ADD_KEY(KEY_IDENTIFIED);
1018 if (IS_FLG(FLG_STAR_IDENTIFIED)) ADD_KEY(KEY_STAR_IDENTIFIED);
1019 if (IS_FLG(FLG_BOOSTED)) ADD_KEY(KEY_BOOSTED);
1021 if (IS_FLG(FLG_MORE_DICE))
1023 ADD_KEY(KEY_MORE_THAN);
1024 strcat(ptr, format("%d", entry->dice));
1028 if (IS_FLG(FLG_MORE_BONUS))
1030 ADD_KEY(KEY_MORE_BONUS);
1031 strcat(ptr, format("%d", entry->bonus));
1032 ADD_KEY(KEY_MORE_BONUS2);
1035 if (IS_FLG(FLG_UNREADABLE)) ADD_KEY(KEY_UNREADABLE);
1036 if (IS_FLG(FLG_REALM1)) ADD_KEY(KEY_REALM1);
1037 if (IS_FLG(FLG_REALM2)) ADD_KEY(KEY_REALM2);
1038 if (IS_FLG(FLG_FIRST)) ADD_KEY(KEY_FIRST);
1039 if (IS_FLG(FLG_SECOND)) ADD_KEY(KEY_SECOND);
1040 if (IS_FLG(FLG_THIRD)) ADD_KEY(KEY_THIRD);
1041 if (IS_FLG(FLG_FOURTH)) ADD_KEY(KEY_FOURTH);
1042 if (IS_FLG(FLG_WANTED)) ADD_KEY(KEY_WANTED);
1043 if (IS_FLG(FLG_UNIQUE)) ADD_KEY(KEY_UNIQUE);
1044 if (IS_FLG(FLG_HUMAN)) ADD_KEY(KEY_HUMAN);
1045 if (IS_FLG(FLG_WORTHLESS)) ADD_KEY(KEY_WORTHLESS);
1046 if (IS_FLG(FLG_GOOD)) ADD_KEY(KEY_GOOD);
1047 if (IS_FLG(FLG_NAMELESS)) ADD_KEY(KEY_NAMELESS);
1048 if (IS_FLG(FLG_AVERAGE)) ADD_KEY(KEY_AVERAGE);
1049 if (IS_FLG(FLG_RARE)) ADD_KEY(KEY_RARE);
1050 if (IS_FLG(FLG_COMMON)) ADD_KEY(KEY_COMMON);
1051 if (IS_FLG(FLG_EGO)) ADD_KEY(KEY_EGO);
1053 if (IS_FLG(FLG_ARTIFACT)) ADD_KEY(KEY_ARTIFACT);
1055 bool sepa_flag = TRUE;
1056 if (IS_FLG(FLG_ITEMS)) ADD_KEY2(KEY_ITEMS);
1057 else if (IS_FLG(FLG_WEAPONS)) ADD_KEY2(KEY_WEAPONS);
1058 else if (IS_FLG(FLG_FAVORITE_WEAPONS)) ADD_KEY2(KEY_FAVORITE_WEAPONS);
1059 else if (IS_FLG(FLG_ARMORS)) ADD_KEY2(KEY_ARMORS);
1060 else if (IS_FLG(FLG_MISSILES)) ADD_KEY2(KEY_MISSILES);
1061 else if (IS_FLG(FLG_DEVICES)) ADD_KEY2(KEY_DEVICES);
1062 else if (IS_FLG(FLG_LIGHTS)) ADD_KEY2(KEY_LIGHTS);
1063 else if (IS_FLG(FLG_JUNKS)) ADD_KEY2(KEY_JUNKS);
1064 else if (IS_FLG(FLG_CORPSES)) ADD_KEY2(KEY_CORPSES);
1065 else if (IS_FLG(FLG_SPELLBOOKS)) ADD_KEY2(KEY_SPELLBOOKS);
1066 else if (IS_FLG(FLG_HAFTED)) ADD_KEY2(KEY_HAFTED);
1067 else if (IS_FLG(FLG_SHIELDS)) ADD_KEY2(KEY_SHIELDS);
1068 else if (IS_FLG(FLG_BOWS)) ADD_KEY2(KEY_BOWS);
1069 else if (IS_FLG(FLG_RINGS)) ADD_KEY2(KEY_RINGS);
1070 else if (IS_FLG(FLG_AMULETS)) ADD_KEY2(KEY_AMULETS);
1071 else if (IS_FLG(FLG_SUITS)) ADD_KEY2(KEY_SUITS);
1072 else if (IS_FLG(FLG_CLOAKS)) ADD_KEY2(KEY_CLOAKS);
1073 else if (IS_FLG(FLG_HELMS)) ADD_KEY2(KEY_HELMS);
1074 else if (IS_FLG(FLG_GLOVES)) ADD_KEY2(KEY_GLOVES);
1075 else if (IS_FLG(FLG_BOOTS)) ADD_KEY2(KEY_BOOTS);
1076 else if (!IS_FLG(FLG_ARTIFACT))
1079 if (entry->name && entry->name[0])
1081 if (sepa_flag) strcat(buf, ":");
1083 int i = strlen(buf);
1085 while (entry->name[j] && i < MAX_LINELEN - 2 - 1)
1088 if (iskanji(entry->name[j]))
1089 buf[i++] = entry->name[j++];
1091 buf[i++] = entry->name[j++];
1096 if (!entry->insc) return string_make(buf);
1102 while (entry->insc[j] && i < MAX_LINELEN - 2)
1105 if (iskanji(entry->insc[j]))
1106 buf[i++] = entry->insc[j++];
1108 buf[i++] = entry->insc[j++];
1112 return string_make(buf);
1117 * Reconstruct preference line from entry and kill entry
1119 static concptr autopick_line_from_entry_kill(autopick_type *entry)
1121 concptr ptr = autopick_line_from_entry(entry);
1122 autopick_free_entry(entry);
1128 * A function for Auto-picker/destroyer
1129 * Examine whether the object matches to the entry
1131 static bool is_autopick_aux(player_type *player_ptr, object_type *o_ptr, autopick_type *entry, concptr o_name)
1133 concptr ptr = entry->name;
1134 if (IS_FLG(FLG_UNAWARE) && object_is_aware(o_ptr))
1137 if (IS_FLG(FLG_UNIDENTIFIED)
1138 && (object_is_known(o_ptr) || (o_ptr->ident & IDENT_SENSE)))
1141 if (IS_FLG(FLG_IDENTIFIED) && !object_is_known(o_ptr))
1144 if (IS_FLG(FLG_STAR_IDENTIFIED) &&
1145 (!object_is_known(o_ptr) || !OBJECT_IS_FULL_KNOWN(o_ptr)))
1148 if (IS_FLG(FLG_BOOSTED))
1150 object_kind *k_ptr = &k_info[o_ptr->k_idx];
1151 if (!object_is_melee_weapon(o_ptr))
1154 if ((o_ptr->dd == k_ptr->dd) && (o_ptr->ds == k_ptr->ds))
1157 if (!object_is_known(o_ptr) && object_is_quest_target(o_ptr))
1163 if (IS_FLG(FLG_MORE_DICE))
1165 if (o_ptr->dd * o_ptr->ds < entry->dice)
1169 if (IS_FLG(FLG_MORE_BONUS))
1171 if (!object_is_known(o_ptr)) return FALSE;
1175 if (o_ptr->pval < entry->bonus) return FALSE;
1179 if (o_ptr->to_h < entry->bonus &&
1180 o_ptr->to_d < entry->bonus &&
1181 o_ptr->to_a < entry->bonus &&
1182 o_ptr->pval < entry->bonus)
1187 if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0)
1190 if (IS_FLG(FLG_ARTIFACT))
1192 if (!object_is_known(o_ptr) || !object_is_artifact(o_ptr))
1196 if (IS_FLG(FLG_EGO))
1198 if (!object_is_ego(o_ptr)) return FALSE;
1199 if (!object_is_known(o_ptr) &&
1200 !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT))
1204 if (IS_FLG(FLG_GOOD))
1206 if (!object_is_equipment(o_ptr)) return FALSE;
1207 if (object_is_known(o_ptr))
1209 if (!object_is_nameless(o_ptr))
1212 if (o_ptr->to_a <= 0 && (o_ptr->to_h + o_ptr->to_d) <= 0)
1215 else if (o_ptr->ident & IDENT_SENSE)
1217 switch (o_ptr->feeling)
1232 if (IS_FLG(FLG_NAMELESS))
1234 if (!object_is_equipment(o_ptr)) return FALSE;
1235 if (object_is_known(o_ptr))
1237 if (!object_is_nameless(o_ptr))
1240 else if (o_ptr->ident & IDENT_SENSE)
1242 switch (o_ptr->feeling)
1260 if (IS_FLG(FLG_AVERAGE))
1262 if (!object_is_equipment(o_ptr)) return FALSE;
1263 if (object_is_known(o_ptr))
1265 if (!object_is_nameless(o_ptr))
1268 if (object_is_cursed(o_ptr) || object_is_broken(o_ptr))
1271 if (o_ptr->to_a > 0 || (o_ptr->to_h + o_ptr->to_d) > 0)
1274 else if (o_ptr->ident & IDENT_SENSE)
1276 switch (o_ptr->feeling)
1291 if (IS_FLG(FLG_RARE) && !object_is_rare(o_ptr))
1294 if (IS_FLG(FLG_COMMON) && object_is_rare(o_ptr))
1297 if (IS_FLG(FLG_WANTED) && !object_is_bounty(o_ptr))
1300 if (IS_FLG(FLG_UNIQUE) &&
1301 ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) ||
1302 !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE)))
1305 if (IS_FLG(FLG_HUMAN) &&
1306 (o_ptr->tval != TV_CORPSE ||
1307 !my_strchr("pht", r_info[o_ptr->pval].d_char)))
1310 if (IS_FLG(FLG_UNREADABLE) &&
1311 (o_ptr->tval < TV_LIFE_BOOK ||
1312 check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval)))
1315 if (IS_FLG(FLG_REALM1) &&
1316 (REALM1_BOOK != o_ptr->tval ||
1317 player_ptr->pclass == CLASS_SORCERER ||
1318 player_ptr->pclass == CLASS_RED_MAGE))
1321 if (IS_FLG(FLG_REALM2) &&
1322 (REALM2_BOOK != o_ptr->tval ||
1323 player_ptr->pclass == CLASS_SORCERER ||
1324 player_ptr->pclass == CLASS_RED_MAGE))
1327 if (IS_FLG(FLG_FIRST) &&
1328 (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval))
1331 if (IS_FLG(FLG_SECOND) &&
1332 (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval))
1335 if (IS_FLG(FLG_THIRD) &&
1336 (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval))
1339 if (IS_FLG(FLG_FOURTH) &&
1340 (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval))
1343 if (IS_FLG(FLG_WEAPONS))
1345 if (!object_is_weapon(o_ptr))
1348 else if (IS_FLG(FLG_FAVORITE_WEAPONS))
1350 if (!object_is_favorite(o_ptr))
1353 else if (IS_FLG(FLG_ARMORS))
1355 if (!object_is_armour(o_ptr))
1358 else if (IS_FLG(FLG_MISSILES))
1360 if (!object_is_ammo(o_ptr)) return FALSE;
1362 else if (IS_FLG(FLG_DEVICES))
1364 switch (o_ptr->tval)
1366 case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD:
1368 default: return FALSE;
1371 else if (IS_FLG(FLG_LIGHTS))
1373 if (!(o_ptr->tval == TV_LITE))
1376 else if (IS_FLG(FLG_JUNKS))
1378 switch (o_ptr->tval)
1380 case TV_SKELETON: case TV_BOTTLE:
1381 case TV_JUNK: case TV_STATUE:
1383 default: return FALSE;
1386 else if (IS_FLG(FLG_CORPSES))
1388 if (o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_SKELETON)
1391 else if (IS_FLG(FLG_SPELLBOOKS))
1393 if (!(o_ptr->tval >= TV_LIFE_BOOK))
1396 else if (IS_FLG(FLG_HAFTED))
1398 if (!(o_ptr->tval == TV_HAFTED))
1401 else if (IS_FLG(FLG_SHIELDS))
1403 if (!(o_ptr->tval == TV_SHIELD))
1406 else if (IS_FLG(FLG_BOWS))
1408 if (!(o_ptr->tval == TV_BOW))
1411 else if (IS_FLG(FLG_RINGS))
1413 if (!(o_ptr->tval == TV_RING))
1416 else if (IS_FLG(FLG_AMULETS))
1418 if (!(o_ptr->tval == TV_AMULET))
1421 else if (IS_FLG(FLG_SUITS))
1423 if (!(o_ptr->tval == TV_DRAG_ARMOR ||
1424 o_ptr->tval == TV_HARD_ARMOR ||
1425 o_ptr->tval == TV_SOFT_ARMOR))
1428 else if (IS_FLG(FLG_CLOAKS))
1430 if (!(o_ptr->tval == TV_CLOAK))
1433 else if (IS_FLG(FLG_HELMS))
1435 if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM))
1438 else if (IS_FLG(FLG_GLOVES))
1440 if (!(o_ptr->tval == TV_GLOVES))
1443 else if (IS_FLG(FLG_BOOTS))
1445 if (!(o_ptr->tval == TV_BOOTS))
1452 if (strncmp(o_name, ptr, strlen(ptr))) return FALSE;
1456 if (!my_strstr(o_name, ptr)) return FALSE;
1459 if (!IS_FLG(FLG_COLLECTING)) return TRUE;
1461 for (int j = 0; j < INVEN_PACK; j++)
1464 * 'Collecting' means the item must be absorbed
1465 * into an inventory slot.
1466 * But an item can not be absorbed into itself!
1468 if ((&player_ptr->inventory_list[j] != o_ptr) &&
1469 object_similar(&player_ptr->inventory_list[j], o_ptr))
1478 * A function for Auto-picker/destroyer
1479 * Examine whether the object matches to the list of keywords or not.
1481 int is_autopick(player_type *player_ptr, object_type *o_ptr)
1483 GAME_TEXT o_name[MAX_NLEN];
1484 if (o_ptr->tval == TV_GOLD) return -1;
1486 object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
1487 str_tolower(o_name);
1488 for (int i = 0; i < max_autopick; i++)
1490 autopick_type *entry = &autopick_list[i];
1491 if (is_autopick_aux(player_ptr, o_ptr, entry, o_name))
1502 static void auto_inscribe_item(player_type *player_ptr, object_type *o_ptr, int idx)
1504 if (idx < 0 || !autopick_list[idx].insc) return;
1506 if (!o_ptr->inscription)
1507 o_ptr->inscription = quark_add(autopick_list[idx].insc);
1509 player_ptr->window |= (PW_EQUIP | PW_INVEN);
1510 player_ptr->update |= (PU_BONUS);
1515 * Automatically destroy items in this grid.
1517 static bool is_opt_confirm_destroy(player_type *player_ptr, object_type *o_ptr)
1519 if (!destroy_items) return FALSE;
1522 if (object_value(o_ptr) > 0) return FALSE;
1525 if (object_is_weapon_armour_ammo(o_ptr)) return FALSE;
1528 if ((o_ptr->tval == TV_CHEST) && o_ptr->pval) return FALSE;
1532 if (object_is_bounty(o_ptr)) return FALSE;
1536 if (o_ptr->tval == TV_CORPSE) return FALSE;
1539 if ((o_ptr->tval == TV_SKELETON) || (o_ptr->tval == TV_BOTTLE) || (o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_STATUE)) return FALSE;
1543 if (player_ptr->prace == RACE_DEMON)
1545 if (o_ptr->tval == TV_CORPSE &&
1546 o_ptr->sval == SV_CORPSE &&
1547 my_strchr("pht", r_info[o_ptr->pval].d_char))
1551 if (player_ptr->pclass == CLASS_ARCHER)
1553 if (o_ptr->tval == TV_SKELETON ||
1554 (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON))
1557 else if (player_ptr->pclass == CLASS_NINJA)
1559 if (o_ptr->tval == TV_LITE &&
1560 o_ptr->name2 == EGO_LITE_DARKNESS && object_is_known(o_ptr))
1563 else if (player_ptr->pclass == CLASS_BEASTMASTER ||
1564 player_ptr->pclass == CLASS_CAVALRY)
1566 if (o_ptr->tval == TV_WAND &&
1567 o_ptr->sval == SV_WAND_HEAL_MONSTER && object_is_aware(o_ptr))
1572 if (o_ptr->tval == TV_GOLD) return FALSE;
1578 static void auto_destroy_item(player_type *player_ptr, object_type *o_ptr, int autopick_idx)
1580 bool destroy = FALSE;
1581 if (is_opt_confirm_destroy(player_ptr, o_ptr)) destroy = TRUE;
1583 if (autopick_idx >= 0 &&
1584 !(autopick_list[autopick_idx].action & DO_AUTODESTROY))
1589 if (autopick_idx >= 0 &&
1590 (autopick_list[autopick_idx].action & DO_AUTODESTROY))
1594 if (!destroy) return;
1596 disturb(player_ptr, FALSE, FALSE);
1597 if (!can_player_destroy_object(o_ptr))
1599 GAME_TEXT o_name[MAX_NLEN];
1600 object_desc(player_ptr, o_name, o_ptr, 0);
1601 msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name);
1605 (void)COPY(&autopick_last_destroyed_object, o_ptr, object_type);
1606 o_ptr->marked |= OM_AUTODESTROY;
1607 player_ptr->update |= PU_AUTODESTROY;
1612 * Auto-destroy marked item
1614 static void autopick_delayed_alter_aux(player_type *player_ptr, INVENTORY_IDX item)
1617 o_ptr = REF_ITEM(player_ptr, player_ptr->current_floor_ptr, item);
1619 if (o_ptr->k_idx == 0 || !(o_ptr->marked & OM_AUTODESTROY)) return;
1621 GAME_TEXT o_name[MAX_NLEN];
1622 object_desc(player_ptr, o_name, o_ptr, 0);
1625 inven_item_increase(player_ptr, item, -(o_ptr->number));
1626 inven_item_optimize(player_ptr, item);
1630 delete_object_idx(player_ptr, 0 - item);
1633 msg_format(_("%sを自動破壊します。", "Auto-destroying %s."), o_name);
1638 * Auto-destroy marked items in inventry and on floor
1640 void autopick_delayed_alter(player_type *owner_ptr)
1645 * Scan inventry in reverse order to prevent
1646 * skipping after inven_item_optimize()
1648 for (item = INVEN_TOTAL - 1; item >= 0; item--)
1649 autopick_delayed_alter_aux(owner_ptr, item);
1651 floor_type *floor_ptr = owner_ptr->current_floor_ptr;
1652 item = floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx;
1655 OBJECT_IDX next = floor_ptr->o_list[item].next_o_idx;
1656 autopick_delayed_alter_aux(owner_ptr, -item);
1663 * Auto-inscription and/or destroy
1665 * Auto-destroyer works only on inventory or on floor stack only when
1668 void autopick_alter_item(player_type *player_ptr, INVENTORY_IDX item, bool destroy)
1671 o_ptr = REF_ITEM(player_ptr, player_ptr->current_floor_ptr, item);
1672 int idx = is_autopick(player_ptr, o_ptr);
1673 auto_inscribe_item(player_ptr, o_ptr, idx);
1674 if (destroy && item <= INVEN_PACK)
1675 auto_destroy_item(player_ptr, o_ptr, idx);
1680 * Automatically pickup/destroy items in this grid.
1682 void autopick_pickup_items(player_type* player_ptr, grid_type *g_ptr)
1684 OBJECT_IDX this_o_idx, next_o_idx = 0;
1685 for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1687 object_type *o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
1688 next_o_idx = o_ptr->next_o_idx;
1689 int idx = is_autopick(player_ptr, o_ptr);
1690 auto_inscribe_item(player_ptr, o_ptr, idx);
1691 bool is_auto_pickup = idx >= 0;
1692 is_auto_pickup &= (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK)) != 0;
1693 if (!is_auto_pickup)
1695 auto_destroy_item(player_ptr, o_ptr, idx);
1699 disturb(player_ptr, FALSE, FALSE);
1700 if (!inven_carry_okay(o_ptr))
1702 GAME_TEXT o_name[MAX_NLEN];
1703 object_desc(player_ptr, o_name, o_ptr, 0);
1704 msg_format(_("ザックには%sを入れる隙間がない。", "You have no room for %s."), o_name);
1705 o_ptr->marked |= OM_NOMSG;
1709 if (!(autopick_list[idx].action & DO_QUERY_AUTOPICK))
1711 py_pickup_aux(player_ptr, this_o_idx);
1715 char out_val[MAX_NLEN + 20];
1716 GAME_TEXT o_name[MAX_NLEN];
1717 if (o_ptr->marked & OM_NO_QUERY)
1722 object_desc(player_ptr, o_name, o_ptr, 0);
1723 sprintf(out_val, _("%sを拾いますか? ", "Pick up %s? "), o_name);
1724 if (!get_check(out_val))
1726 o_ptr->marked |= OM_NOMSG | OM_NO_QUERY;
1730 py_pickup_aux(player_ptr, this_o_idx);
1735 static const char autoregister_header[] = "?:$AUTOREGISTER";
1738 * Clear auto registered lines in the picktype.prf .
1740 static bool clear_auto_register(player_type *player_ptr)
1742 char tmp_file[1024];
1743 char pref_file[1024];
1748 bool autoregister = FALSE;
1751 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME));
1752 pref_fff = my_fopen(pref_file, "r");
1756 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT));
1757 pref_fff = my_fopen(pref_file, "r");
1765 tmp_fff = my_fopen_temp(tmp_file, sizeof(tmp_file));
1769 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
1776 if (my_fgets(pref_fff, buf, sizeof(buf))) break;
1780 if (buf[0] != '#' && buf[0] != '?') num++;
1784 if (streq(buf, autoregister_header))
1786 autoregister = TRUE;
1790 fprintf(tmp_fff, "%s\n", buf);
1794 my_fclose(pref_fff);
1799 msg_format(_("以前のキャラクター用の自動設定(%d行)が残っています。",
1800 "Auto registered lines (%d lines) for previous character are remaining."), num);
1801 strcpy(buf, _("古い設定行は削除します。よろしいですか?", "These lines will be deleted. Are you sure? "));
1803 if (!get_check(buf))
1806 autoregister = FALSE;
1808 msg_print(_("エディタのカット&ペースト等を使って必要な行を避難してください。",
1809 "Use cut & paste of auto picker editor (_) to keep old prefs."));
1815 tmp_fff = my_fopen(tmp_file, "r");
1816 pref_fff = my_fopen(pref_file, "w");
1818 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
1819 fprintf(pref_fff, "%s\n", buf);
1821 my_fclose(pref_fff);
1831 * Automatically register an auto-destroy preference line
1833 bool autopick_autoregister(player_type *player_ptr, object_type *o_ptr)
1836 char pref_file[1024];
1838 autopick_type an_entry, *entry = &an_entry;
1839 int match_autopick = is_autopick(player_ptr, o_ptr);
1840 if (match_autopick != -1)
1843 byte act = autopick_list[match_autopick].action;
1844 if (act & DO_AUTOPICK) what = _("自動で拾う", "auto-pickup");
1845 else if (act & DO_AUTODESTROY) what = _("自動破壊する", "auto-destroy");
1846 else if (act & DONT_AUTOPICK) what = _("放置する", "leave on floor");
1847 else what = _("確認して拾う", "query auto-pickup");
1849 msg_format(_("そのアイテムは既に%sように設定されています。", "The object is already registered to %s."), what);
1853 if ((object_is_known(o_ptr) && object_is_artifact(o_ptr)) ||
1854 ((o_ptr->ident & IDENT_SENSE) &&
1855 (o_ptr->feeling == FEEL_TERRIBLE || o_ptr->feeling == FEEL_SPECIAL)))
1857 GAME_TEXT o_name[MAX_NLEN];
1858 object_desc(player_ptr, o_name, o_ptr, 0);
1859 msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name);
1863 if (!player_ptr->autopick_autoregister)
1865 if (!clear_auto_register(player_ptr)) return FALSE;
1868 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME));
1869 pref_fff = my_fopen(pref_file, "r");
1873 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT));
1874 pref_fff = my_fopen(pref_file, "r");
1881 if (my_fgets(pref_fff, buf, sizeof(buf)))
1883 player_ptr->autopick_autoregister = FALSE;
1887 if (streq(buf, autoregister_header))
1889 player_ptr->autopick_autoregister = TRUE;
1899 * File could not be opened for reading. Assume header not
1902 player_ptr->autopick_autoregister = FALSE;
1905 pref_fff = my_fopen(pref_file, "a");
1908 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), pref_file);
1913 if (!player_ptr->autopick_autoregister)
1915 fprintf(pref_fff, "%s\n", autoregister_header);
1917 fprintf(pref_fff, "%s\n", _("# *警告!!* 以降の行は自動登録されたものです。",
1918 "# *Warning!* The lines below will be deleted later."));
1919 fprintf(pref_fff, "%s\n", _("# 後で自動的に削除されますので、必要な行は上の方へ移動しておいてください。",
1920 "# Keep it by cut & paste if you need these lines for future characters."));
1921 player_ptr->autopick_autoregister = TRUE;
1924 autopick_entry_from_object(player_ptr, entry, o_ptr);
1925 entry->action = DO_AUTODESTROY;
1926 add_autopick_list(entry);
1928 concptr tmp = autopick_line_from_entry(entry);
1929 fprintf(pref_fff, "%s\n", tmp);
1937 * Describe which kind of object is Auto-picked/destroyed
1939 static void describe_autopick(char *buff, autopick_type *entry)
1941 concptr str = entry->name;
1942 byte act = entry->action;
1943 concptr insc = entry->insc;
1949 concptr before_str[100], body_str;
1953 if (IS_FLG(FLG_COLLECTING))
1954 before_str[before_n++] = "収集中で既に持っているスロットにまとめられる";
1956 if (IS_FLG(FLG_UNAWARE))
1957 before_str[before_n++] = "未鑑定でその効果も判明していない";
1959 if (IS_FLG(FLG_UNIDENTIFIED))
1960 before_str[before_n++] = "未鑑定の";
1962 if (IS_FLG(FLG_IDENTIFIED))
1963 before_str[before_n++] = "鑑定済みの";
1965 if (IS_FLG(FLG_STAR_IDENTIFIED))
1966 before_str[before_n++] = "完全に鑑定済みの";
1968 if (IS_FLG(FLG_BOOSTED))
1970 before_str[before_n++] = "ダメージダイスが通常より大きい";
1974 if (IS_FLG(FLG_MORE_DICE))
1976 static char more_than_desc_str[] = "___";
1977 before_str[before_n++] = "ダメージダイスの最大値が";
1980 sprintf(more_than_desc_str, "%d", entry->dice);
1981 before_str[before_n++] = more_than_desc_str;
1982 before_str[before_n++] = "以上の";
1985 if (IS_FLG(FLG_MORE_BONUS))
1987 static char more_bonus_desc_str[] = "___";
1988 before_str[before_n++] = "修正値が(+";
1990 sprintf(more_bonus_desc_str, "%d", entry->bonus);
1991 before_str[before_n++] = more_bonus_desc_str;
1992 before_str[before_n++] = ")以上の";
1995 if (IS_FLG(FLG_WORTHLESS))
1996 before_str[before_n++] = "店で無価値と判定される";
1998 if (IS_FLG(FLG_ARTIFACT))
2000 before_str[before_n++] = "アーティファクトの";
2004 if (IS_FLG(FLG_EGO))
2006 before_str[before_n++] = "エゴアイテムの";
2010 if (IS_FLG(FLG_GOOD))
2012 before_str[before_n++] = "上質の";
2016 if (IS_FLG(FLG_NAMELESS))
2018 before_str[before_n++] = "エゴでもアーティファクトでもない";
2022 if (IS_FLG(FLG_AVERAGE))
2024 before_str[before_n++] = "並の";
2028 if (IS_FLG(FLG_RARE))
2030 before_str[before_n++] = "ドラゴン装備やカオス・ブレード等を含む珍しい";
2034 if (IS_FLG(FLG_COMMON))
2036 before_str[before_n++] = "ありふれた(ドラゴン装備やカオス・ブレード等の珍しい物ではない)";
2040 if (IS_FLG(FLG_WANTED))
2042 before_str[before_n++] = "ハンター事務所で賞金首とされている";
2046 if (IS_FLG(FLG_HUMAN))
2048 before_str[before_n++] = "悪魔魔法で使うための人間やヒューマノイドの";
2052 if (IS_FLG(FLG_UNIQUE))
2054 before_str[before_n++] = "ユニークモンスターの";
2058 if (IS_FLG(FLG_UNREADABLE))
2060 before_str[before_n++] = "あなたが読めない領域の";
2064 if (IS_FLG(FLG_REALM1))
2066 before_str[before_n++] = "第一領域の";
2070 if (IS_FLG(FLG_REALM2))
2072 before_str[before_n++] = "第二領域の";
2076 if (IS_FLG(FLG_FIRST))
2078 before_str[before_n++] = "全4冊の内の1冊目の";
2082 if (IS_FLG(FLG_SECOND))
2084 before_str[before_n++] = "全4冊の内の2冊目の";
2088 if (IS_FLG(FLG_THIRD))
2090 before_str[before_n++] = "全4冊の内の3冊目の";
2094 if (IS_FLG(FLG_FOURTH))
2096 before_str[before_n++] = "全4冊の内の4冊目の";
2100 if (IS_FLG(FLG_ITEMS))
2101 ; /* Nothing to do */
2102 else if (IS_FLG(FLG_WEAPONS))
2104 else if (IS_FLG(FLG_FAVORITE_WEAPONS))
2106 else if (IS_FLG(FLG_ARMORS))
2108 else if (IS_FLG(FLG_MISSILES))
2109 body_str = "弾や矢やクロスボウの矢";
2110 else if (IS_FLG(FLG_DEVICES))
2111 body_str = "巻物や魔法棒や杖やロッド";
2112 else if (IS_FLG(FLG_LIGHTS))
2113 body_str = "光源用のアイテム";
2114 else if (IS_FLG(FLG_JUNKS))
2115 body_str = "折れた棒等のガラクタ";
2116 else if (IS_FLG(FLG_CORPSES))
2118 else if (IS_FLG(FLG_SPELLBOOKS))
2120 else if (IS_FLG(FLG_HAFTED))
2122 else if (IS_FLG(FLG_SHIELDS))
2124 else if (IS_FLG(FLG_BOWS))
2125 body_str = "スリングや弓やクロスボウ";
2126 else if (IS_FLG(FLG_RINGS))
2128 else if (IS_FLG(FLG_AMULETS))
2129 body_str = "アミュレット";
2130 else if (IS_FLG(FLG_SUITS))
2132 else if (IS_FLG(FLG_CLOAKS))
2134 else if (IS_FLG(FLG_HELMS))
2135 body_str = "ヘルメットや冠";
2136 else if (IS_FLG(FLG_GLOVES))
2138 else if (IS_FLG(FLG_BOOTS))
2143 strcat(buff, "全ての");
2144 else for (i = 0; i < before_n && before_str[i]; i++)
2145 strcat(buff, before_str[i]);
2147 strcat(buff, body_str);
2157 strcat(buff, "で、名前が「");
2158 strncat(buff, str, 80);
2160 strcat(buff, "」で始まるもの");
2162 strcat(buff, "」を含むもの");
2167 strncat(buff, format("に「%s」", insc), 80);
2169 if (my_strstr(insc, "%%all"))
2170 strcat(buff, "(%%allは全能力を表す英字の記号で置換)");
2171 else if (my_strstr(insc, "%all"))
2172 strcat(buff, "(%allは全能力を表す記号で置換)");
2173 else if (my_strstr(insc, "%%"))
2174 strcat(buff, "(%%は追加能力を表す英字の記号で置換)");
2175 else if (my_strstr(insc, "%"))
2176 strcat(buff, "(%は追加能力を表す記号で置換)");
2178 strcat(buff, "と刻んで");
2183 if (act & DONT_AUTOPICK)
2184 strcat(buff, "放置する。");
2185 else if (act & DO_AUTODESTROY)
2186 strcat(buff, "破壊する。");
2187 else if (act & DO_QUERY_AUTOPICK)
2188 strcat(buff, "確認の後に拾う。");
2190 strcat(buff, "拾う。");
2192 if (act & DO_DISPLAY)
2194 if (act & DONT_AUTOPICK)
2195 strcat(buff, "全体マップ('M')で'N'を押したときに表示する。");
2196 else if (act & DO_AUTODESTROY)
2197 strcat(buff, "全体マップ('M')で'K'を押したときに表示する。");
2199 strcat(buff, "全体マップ('M')で'M'を押したときに表示する。");
2202 strcat(buff, "全体マップには表示しない。");
2206 concptr before_str[20], after_str[20], which_str[20], whose_str[20], body_str;
2207 int before_n = 0, after_n = 0, which_n = 0, whose_n = 0;
2209 if (IS_FLG(FLG_COLLECTING))
2210 which_str[which_n++] = "can be absorbed into an existing inventory list slot";
2212 if (IS_FLG(FLG_UNAWARE))
2214 before_str[before_n++] = "unidentified";
2215 whose_str[whose_n++] = "basic abilities are not known";
2218 if (IS_FLG(FLG_UNIDENTIFIED))
2219 before_str[before_n++] = "unidentified";
2221 if (IS_FLG(FLG_IDENTIFIED))
2222 before_str[before_n++] = "identified";
2224 if (IS_FLG(FLG_STAR_IDENTIFIED))
2225 before_str[before_n++] = "fully identified";
2227 if (IS_FLG(FLG_RARE))
2229 before_str[before_n++] = "very rare";
2230 body_str = "equipments";
2231 after_str[after_n++] = "such as Dragon armor, Blades of Chaos, etc.";
2234 if (IS_FLG(FLG_COMMON))
2236 before_str[before_n++] = "relatively common";
2237 body_str = "equipments";
2238 after_str[after_n++] = "compared to very rare Dragon armor, Blades of Chaos, etc.";
2241 if (IS_FLG(FLG_WORTHLESS))
2243 before_str[before_n++] = "worthless";
2244 which_str[which_n++] = "can not be sold at stores";
2247 if (IS_FLG(FLG_ARTIFACT))
2249 before_str[before_n++] = "artifact";
2252 if (IS_FLG(FLG_EGO))
2254 before_str[before_n++] = "ego";
2257 if (IS_FLG(FLG_GOOD))
2259 body_str = "equipment";
2260 which_str[which_n++] = "have good quality";
2263 if (IS_FLG(FLG_NAMELESS))
2265 body_str = "equipment";
2266 which_str[which_n++] = "is neither ego-item nor artifact";
2269 if (IS_FLG(FLG_AVERAGE))
2271 body_str = "equipment";
2272 which_str[which_n++] = "have average quality";
2275 if (IS_FLG(FLG_BOOSTED))
2277 body_str = "weapons";
2278 whose_str[whose_n++] = "damage dice is bigger than normal";
2281 if (IS_FLG(FLG_MORE_DICE))
2283 static char more_than_desc_str[] =
2284 "maximum damage from dice is bigger than __";
2285 body_str = "weapons";
2287 sprintf(more_than_desc_str + sizeof(more_than_desc_str) - 3,
2289 whose_str[whose_n++] = more_than_desc_str;
2292 if (IS_FLG(FLG_MORE_BONUS))
2294 static char more_bonus_desc_str[] =
2295 "magical bonus is bigger than (+__)";
2297 sprintf(more_bonus_desc_str + sizeof(more_bonus_desc_str) - 4,
2298 "%d)", entry->bonus);
2299 whose_str[whose_n++] = more_bonus_desc_str;
2302 if (IS_FLG(FLG_WANTED))
2304 body_str = "corpse or skeletons";
2305 which_str[which_n++] = "is wanted at the Hunter's Office";
2308 if (IS_FLG(FLG_HUMAN))
2310 before_str[before_n++] = "humanoid";
2311 body_str = "corpse or skeletons";
2312 which_str[which_n++] = "can be used for Daemon magic";
2315 if (IS_FLG(FLG_UNIQUE))
2317 before_str[before_n++] = "unique monster's";
2318 body_str = "corpse or skeletons";
2321 if (IS_FLG(FLG_UNREADABLE))
2323 body_str = "spellbooks";
2324 after_str[after_n++] = "of different realms from yours";
2327 if (IS_FLG(FLG_REALM1))
2329 body_str = "spellbooks";
2330 after_str[after_n++] = "of your first realm";
2333 if (IS_FLG(FLG_REALM2))
2335 body_str = "spellbooks";
2336 after_str[after_n++] = "of your second realm";
2339 if (IS_FLG(FLG_FIRST))
2341 before_str[before_n++] = "first one of four";
2342 body_str = "spellbooks";
2345 if (IS_FLG(FLG_SECOND))
2347 before_str[before_n++] = "second one of four";
2348 body_str = "spellbooks";
2351 if (IS_FLG(FLG_THIRD))
2353 before_str[before_n++] = "third one of four";
2354 body_str = "spellbooks";
2357 if (IS_FLG(FLG_FOURTH))
2359 before_str[before_n++] = "fourth one of four";
2360 body_str = "spellbooks";
2363 if (IS_FLG(FLG_ITEMS))
2364 ; /* Nothing to do */
2365 else if (IS_FLG(FLG_WEAPONS))
2366 body_str = "weapons";
2367 else if (IS_FLG(FLG_FAVORITE_WEAPONS))
2368 body_str = "favorite weapons";
2369 else if (IS_FLG(FLG_ARMORS))
2370 body_str = "armors";
2371 else if (IS_FLG(FLG_MISSILES))
2372 body_str = "shots, arrows or crossbow bolts";
2373 else if (IS_FLG(FLG_DEVICES))
2374 body_str = "scrolls, wands, staffs or rods";
2375 else if (IS_FLG(FLG_LIGHTS))
2376 body_str = "light sources";
2377 else if (IS_FLG(FLG_JUNKS))
2378 body_str = "junk such as broken sticks";
2379 else if (IS_FLG(FLG_CORPSES))
2380 body_str = "corpses or skeletons";
2381 else if (IS_FLG(FLG_SPELLBOOKS))
2382 body_str = "spellbooks";
2383 else if (IS_FLG(FLG_HAFTED))
2384 body_str = "hafted weapons";
2385 else if (IS_FLG(FLG_SHIELDS))
2386 body_str = "shields";
2387 else if (IS_FLG(FLG_BOWS))
2388 body_str = "slings, bows or crossbows";
2389 else if (IS_FLG(FLG_RINGS))
2391 else if (IS_FLG(FLG_AMULETS))
2392 body_str = "amulets";
2393 else if (IS_FLG(FLG_SUITS))
2394 body_str = "body armors";
2395 else if (IS_FLG(FLG_CLOAKS))
2396 body_str = "cloaks";
2397 else if (IS_FLG(FLG_HELMS))
2398 body_str = "helms or crowns";
2399 else if (IS_FLG(FLG_GLOVES))
2400 body_str = "gloves";
2401 else if (IS_FLG(FLG_BOOTS))
2410 whose_str[whose_n++] = "name begins with \"";
2413 which_str[which_n++] = "have \"";
2417 if (act & DONT_AUTOPICK)
2418 strcpy(buff, "Leave on floor ");
2419 else if (act & DO_AUTODESTROY)
2420 strcpy(buff, "Destroy ");
2421 else if (act & DO_QUERY_AUTOPICK)
2422 strcpy(buff, "Ask to pick up ");
2424 strcpy(buff, "Pickup ");
2428 strncat(buff, format("and inscribe \"%s\"", insc), 80);
2430 if (my_strstr(insc, "%all"))
2431 strcat(buff, ", replacing %all with code string representing all abilities,");
2432 else if (my_strstr(insc, "%"))
2433 strcat(buff, ", replacing % with code string representing extra random abilities,");
2435 strcat(buff, " on ");
2439 strcat(buff, "all ");
2440 else for (i = 0; i < before_n && before_str[i]; i++)
2442 strcat(buff, before_str[i]);
2446 strcat(buff, body_str);
2448 for (i = 0; i < after_n && after_str[i]; i++)
2451 strcat(buff, after_str[i]);
2454 for (i = 0; i < whose_n && whose_str[i]; i++)
2457 strcat(buff, " whose ");
2459 strcat(buff, ", and ");
2461 strcat(buff, whose_str[i]);
2470 if (whose_n && which_n)
2471 strcat(buff, ", and ");
2473 for (i = 0; i < which_n && which_str[i]; i++)
2476 strcat(buff, " which ");
2478 strcat(buff, ", and ");
2480 strcat(buff, which_str[i]);
2485 strncat(buff, str, 80);
2486 strcat(buff, "\" as part of its name");
2490 if (act & DO_DISPLAY)
2492 if (act & DONT_AUTOPICK)
2493 strcat(buff, " Display these items when you press the N key in the full 'M'ap.");
2494 else if (act & DO_AUTODESTROY)
2495 strcat(buff, " Display these items when you press the K key in the full 'M'ap.");
2497 strcat(buff, " Display these items when you press the M key in the full 'M'ap.");
2500 strcat(buff, " Not displayed in the full map.");
2506 * Read whole lines of a file to memory
2508 static concptr *read_text_lines(concptr filename)
2510 concptr *lines_list = NULL;
2516 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2517 fff = my_fopen(buf, "r");
2518 if (!fff) return NULL;
2520 C_MAKE(lines_list, MAX_LINES, concptr);
2521 while (my_fgets(fff, buf, sizeof(buf)) == 0)
2523 lines_list[lines++] = string_make(buf);
2524 if (lines >= MAX_LINES - 1) break;
2528 lines_list[0] = string_make("");
2536 * Copy the default autopick file to the user directory
2538 static void prepare_default_pickpref(player_type *player_ptr)
2540 const concptr messages[] = {
2541 _("あなたは「自動拾いエディタ」を初めて起動しました。", "You have activated the Auto-Picker Editor for the first time."),
2542 _("自動拾いのユーザー設定ファイルがまだ書かれていないので、", "Since user pref file for autopick is not yet created,"),
2543 _("基本的な自動拾い設定ファイルをlib/pref/picktype.prfからコピーします。", "the default setting is loaded from lib/pref/pickpref.prf ."),
2547 concptr filename = pickpref_filename(player_ptr, PT_DEFAULT);
2548 for (int i = 0; messages[i]; i++)
2550 msg_print(messages[i]);
2555 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2557 user_fp = my_fopen(buf, "w");
2558 if (!user_fp) return;
2560 fprintf(user_fp, "#***\n");
2561 for (int i = 0; messages[i]; i++)
2563 fprintf(user_fp, "#*** %s\n", messages[i]);
2566 fprintf(user_fp, "#***\n\n\n");
2567 path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, filename);
2569 pref_fp = my_fopen(buf, "r");
2577 while (!my_fgets(pref_fp, buf, sizeof(buf)))
2579 fprintf(user_fp, "%s\n", buf);
2587 * Read an autopick prefence file to memory
2588 * Prepare default if no user file is found
2590 static concptr *read_pickpref_text_lines(player_type *player_ptr, int *filename_mode_p)
2592 /* Try a filename with player name */
2593 *filename_mode_p = PT_WITH_PNAME;
2595 strcpy(buf, pickpref_filename(player_ptr, *filename_mode_p));
2596 concptr *lines_list;
2597 lines_list = read_text_lines(buf);
2601 *filename_mode_p = PT_DEFAULT;
2602 strcpy(buf, pickpref_filename(player_ptr, *filename_mode_p));
2603 lines_list = read_text_lines(buf);
2608 prepare_default_pickpref(player_ptr);
2609 lines_list = read_text_lines(buf);
2614 C_MAKE(lines_list, MAX_LINES, concptr);
2615 lines_list[0] = string_make("");
2623 * Write whole lines of memory to a file.
2625 static bool write_text_lines(concptr filename, concptr *lines_list)
2628 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2630 fff = my_fopen(buf, "w");
2631 if (!fff) return FALSE;
2633 for (int lines = 0; lines_list[lines]; lines++)
2635 my_fputs(fff, lines_list[lines], 1024);
2644 * Free memory of lines_list.
2646 static void free_text_lines(concptr *lines_list)
2648 for (int lines = 0; lines_list[lines]; lines++)
2650 string_free(lines_list[lines]);
2653 /* free list of pointers */
2654 C_KILL(lines_list, MAX_LINES, concptr);
2659 * Delete or insert string
2661 static void toggle_keyword(text_body_type *tb, BIT_FLAGS flg)
2668 by1 = MIN(tb->my, tb->cy);
2669 by2 = MAX(tb->my, tb->cy);
2671 else /* if (!tb->mark) */
2676 for (int y = by1; y <= by2; y++)
2678 autopick_type an_entry, *entry = &an_entry;
2679 if (!autopick_new_entry(entry, tb->lines_list[y], !fixed)) continue;
2681 string_free(tb->lines_list[y]);
2684 if (!IS_FLG(flg)) add = TRUE;
2690 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
2693 for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
2696 else if (FLG_UNAWARE <= flg && flg <= FLG_STAR_IDENTIFIED)
2699 for (i = FLG_UNAWARE; i <= FLG_STAR_IDENTIFIED; i++)
2702 else if (FLG_ARTIFACT <= flg && flg <= FLG_AVERAGE)
2705 for (i = FLG_ARTIFACT; i <= FLG_AVERAGE; i++)
2708 else if (FLG_RARE <= flg && flg <= FLG_COMMON)
2711 for (i = FLG_RARE; i <= FLG_COMMON; i++)
2715 if (add) ADD_FLG(flg);
2718 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2719 tb->dirty_flags |= DIRTY_ALL;
2726 * Change command letter
2728 static void toggle_command_letter(text_body_type *tb, byte flg)
2730 autopick_type an_entry, *entry = &an_entry;
2736 by1 = MIN(tb->my, tb->cy);
2737 by2 = MAX(tb->my, tb->cy);
2739 else /* if (!tb->mark) */
2744 for (y = by1; y <= by2; y++)
2748 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
2750 string_free(tb->lines_list[y]);
2754 if (!(entry->action & flg)) add = TRUE;
2760 if (entry->action & DONT_AUTOPICK) wid--;
2761 else if (entry->action & DO_AUTODESTROY) wid--;
2762 else if (entry->action & DO_QUERY_AUTOPICK) wid--;
2763 if (!(entry->action & DO_DISPLAY)) wid--;
2765 if (flg != DO_DISPLAY)
2767 entry->action &= ~(DO_AUTOPICK | DONT_AUTOPICK | DO_AUTODESTROY | DO_QUERY_AUTOPICK);
2768 if (add) entry->action |= flg;
2769 else entry->action |= DO_AUTOPICK;
2773 entry->action &= ~(DO_DISPLAY);
2774 if (add) entry->action |= flg;
2779 if (entry->action & DONT_AUTOPICK) wid++;
2780 else if (entry->action & DO_AUTODESTROY) wid++;
2781 else if (entry->action & DO_QUERY_AUTOPICK) wid++;
2782 if (!(entry->action & DO_DISPLAY)) wid++;
2784 if (wid > 0) tb->cx++;
2785 if (wid < 0 && tb->cx > 0) tb->cx--;
2788 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2789 tb->dirty_flags |= DIRTY_ALL;
2796 * Delete or insert string
2798 static void add_keyword(text_body_type *tb, BIT_FLAGS flg)
2803 by1 = MIN(tb->my, tb->cy);
2804 by2 = MAX(tb->my, tb->cy);
2811 for (int y = by1; y <= by2; y++)
2813 autopick_type an_entry, *entry = &an_entry;
2814 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
2818 autopick_free_entry(entry);
2822 string_free(tb->lines_list[y]);
2823 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
2826 for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
2831 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2832 tb->dirty_flags |= DIRTY_ALL;
2839 * Check if this line is expression or not.
2840 * And update it if it is.
2842 static void check_expression_line(text_body_type *tb, int y)
2844 concptr s = tb->lines_list[y];
2846 if ((s[0] == '?' && s[1] == ':') ||
2847 (tb->states[y] & LSTAT_BYPASS))
2849 tb->dirty_flags |= DIRTY_EXPRESSION;
2855 * Add an empty line at the last of the file
2857 static bool add_empty_line(text_body_type *tb)
2860 for (num_lines = 0; tb->lines_list[num_lines]; num_lines++);
2862 if (num_lines >= MAX_LINES - 2) return FALSE;
2863 if (!tb->lines_list[num_lines - 1][0]) return FALSE;
2865 tb->lines_list[num_lines] = string_make("");
2866 tb->dirty_flags |= DIRTY_EXPRESSION;
2873 * Insert return code and split the line
2875 static bool insert_return_code(text_body_type *tb)
2877 char buf[MAX_LINELEN];
2878 int i, j, num_lines;
2880 for (num_lines = 0; tb->lines_list[num_lines]; num_lines++);
2882 if (num_lines >= MAX_LINES - 2) return FALSE;
2885 for (; tb->cy < num_lines; num_lines--)
2887 tb->lines_list[num_lines + 1] = tb->lines_list[num_lines];
2888 tb->states[num_lines + 1] = tb->states[num_lines];
2891 for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
2894 if (iskanji(tb->lines_list[tb->cy][i]))
2895 buf[j++] = tb->lines_list[tb->cy][i++];
2897 buf[j++] = tb->lines_list[tb->cy][i];
2901 tb->lines_list[tb->cy + 1] = string_make(&tb->lines_list[tb->cy][i]);
2902 string_free(tb->lines_list[tb->cy]);
2903 tb->lines_list[tb->cy] = string_make(buf);
2904 tb->dirty_flags |= DIRTY_EXPRESSION;
2911 * Choose an item and get auto-picker entry from it.
2913 static bool entry_from_choosed_object(player_type *player_ptr, autopick_type *entry)
2915 concptr q = _("どのアイテムを登録しますか? ", "Enter which item? ");
2916 concptr s = _("アイテムを持っていない。", "You have nothing to enter.");
2918 o_ptr = choose_object(player_ptr, NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, 0);
2919 if (!o_ptr) return FALSE;
2921 autopick_entry_from_object(player_ptr, entry, o_ptr);
2927 * Choose an item for search
2929 static bool get_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
2931 concptr q = _("どのアイテムを検索しますか? ", "Enter which item? ");
2932 concptr s = _("アイテムを持っていない。", "You have nothing to enter.");
2934 o_ptr = choose_object(player_ptr, NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, 0);
2935 if (!o_ptr) return FALSE;
2938 string_free(*search_strp);
2939 char buf[MAX_NLEN + 20];
2940 object_desc(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
2941 *search_strp = string_make(format("<%s>", buf));
2947 * Prepare for search by destroyed object
2949 static bool get_destroyed_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
2951 if (!autopick_last_destroyed_object.k_idx) return FALSE;
2953 *o_handle = &autopick_last_destroyed_object;
2954 string_free(*search_strp);
2955 char buf[MAX_NLEN + 20];
2956 object_desc(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
2957 *search_strp = string_make(format("<%s>", buf));
2963 * Choose an item or string for search
2965 static byte get_string_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
2969 * TERM_YELLOW : Overwrite mode
2970 * TERM_WHITE : Insert mode
2972 byte color = TERM_YELLOW;
2973 char buf[MAX_NLEN + 20];
2975 char prompt[] = _("検索(^I:持ち物 ^L:破壊された物): ", "Search key(^I:inven ^L:destroyed): ");
2976 int col = sizeof(prompt) - 1;
2977 if (*search_strp) strcpy(buf, *search_strp);
2980 if (*o_handle) color = TERM_L_GREEN;
2989 Term_erase(col, 0, 255);
2990 Term_putstr(col, 0, -1, color, buf);
2991 Term_gotoxy(col + pos, 0);
2993 skey = inkey_special(TRUE);
3001 if (pos == 0) break;
3005 int next_pos = i + 1;
3008 if (iskanji(buf[i])) next_pos++;
3010 if (next_pos >= pos) break;
3022 if ('\0' == buf[pos]) break;
3025 if (iskanji(buf[pos])) pos += 2;
3042 if (*o_handle) return (back ? -1 : 1);
3043 string_free(*search_strp);
3044 *search_strp = string_make(buf);
3046 return (back ? -1 : 1);
3049 return get_object_for_search(player_ptr, o_handle, search_strp);
3052 if (get_destroyed_object_for_search(player_ptr, o_handle, search_strp))
3060 if (pos == 0) break;
3064 int next_pos = i + 1;
3066 if (iskanji(buf[i])) next_pos++;
3068 if (next_pos >= pos) break;
3082 if (buf[pos] == '\0') break;
3086 if (iskanji(buf[pos])) src++;
3089 while ('\0' != (buf[dst++] = buf[src++]));
3098 if (skey & SKEY_MASK) break;
3101 if (color != TERM_WHITE)
3103 if (color == TERM_L_GREEN)
3106 string_free(*search_strp);
3107 *search_strp = NULL;
3114 strcpy(tmp, buf + pos);
3136 if (pos < len && (isprint(c) || iskana(c)))
3138 if (pos < len && isprint(c))
3150 my_strcat(buf, tmp, len + 1);
3156 if (*o_handle == NULL || color == TERM_L_GREEN) continue;
3160 string_free(*search_strp);
3161 *search_strp = NULL;
3167 * Search next line matches for o_ptr
3169 static void search_for_object(player_type *player_ptr, text_body_type *tb, object_type *o_ptr, bool forward)
3171 autopick_type an_entry, *entry = &an_entry;
3172 GAME_TEXT o_name[MAX_NLEN];
3173 int bypassed_cy = -1;
3175 object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
3176 str_tolower(o_name);
3183 if (!tb->lines_list[++i]) break;
3190 if (!autopick_new_entry(entry, tb->lines_list[i], FALSE)) continue;
3192 match = is_autopick_aux(player_ptr, o_ptr, entry, o_name);
3193 autopick_free_entry(entry);
3194 if (!match) continue;
3196 if (tb->states[i] & LSTAT_BYPASS)
3198 if (bypassed_cy == -1) bypassed_cy = i;
3204 if (bypassed_cy != -1)
3206 tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
3212 if (bypassed_cy == -1)
3214 tb->dirty_flags |= DIRTY_NOT_FOUND;
3219 tb->cy = bypassed_cy;
3220 tb->dirty_flags |= DIRTY_INACTIVE;
3225 * Search next line matches to the string
3227 static void search_for_string(text_body_type *tb, concptr search_str, bool forward)
3229 int bypassed_cy = -1;
3230 int bypassed_cx = 0;
3238 if (!tb->lines_list[++i]) break;
3245 pos = my_strstr(tb->lines_list[i], search_str);
3248 if ((tb->states[i] & LSTAT_BYPASS) &&
3249 !(tb->states[i] & LSTAT_EXPRESSION))
3251 if (bypassed_cy == -1)
3254 bypassed_cx = (int)(pos - tb->lines_list[i]);
3260 tb->cx = (int)(pos - tb->lines_list[i]);
3263 if (bypassed_cy != -1)
3265 tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
3271 if (bypassed_cy == -1)
3273 tb->dirty_flags |= DIRTY_NOT_FOUND;
3277 tb->cx = bypassed_cx;
3278 tb->cy = bypassed_cy;
3279 tb->dirty_flags |= DIRTY_INACTIVE;
3284 * Find a command by 'key'.
3286 static int get_com_id(char key)
3288 for (int i = 0; menu_data[i].name; i++)
3290 if (menu_data[i].key == key)
3292 return menu_data[i].com_id;
3301 * Display the menu, and get a command
3303 static int do_command_menu(int level, int start)
3306 int col0 = 5 + level * 7;
3307 int row0 = 1 + level * 3;
3308 int menu_id_list[26];
3310 char linestr[MAX_LINELEN];
3313 for (int i = start; menu_data[i].level >= level; i++)
3317 /* Ignore lower level sub menus */
3318 if (menu_data[i].level > level) continue;
3320 len = strlen(menu_data[i].name);
3321 if (len > max_len) max_len = len;
3323 menu_id_list[menu_key] = i;
3327 while (menu_key < 26)
3329 menu_id_list[menu_key] = -1;
3333 int max_menu_wid = max_len + 3 + 3;
3335 /* Prepare box line */
3337 strcat(linestr, "+");
3338 for (int i = 0; i < max_menu_wid + 2; i++)
3340 strcat(linestr, "-");
3343 strcat(linestr, "+");
3353 int row1 = row0 + 1;
3354 Term_putstr(col0, row0, -1, TERM_WHITE, linestr);
3357 for (int i = start; menu_data[i].level >= level; i++)
3359 char com_key_str[3];
3361 if (menu_data[i].level > level) continue;
3363 if (menu_data[i].com_id == -1)
3365 strcpy(com_key_str, _("▼", ">"));
3367 else if (menu_data[i].key != -1)
3369 com_key_str[0] = '^';
3370 com_key_str[1] = menu_data[i].key + '@';
3371 com_key_str[2] = '\0';
3375 com_key_str[0] = '\0';
3378 str = format("| %c) %-*s %2s | ", menu_key + 'a', max_len, menu_data[i].name, com_key_str);
3380 Term_putstr(col0, row1++, -1, TERM_WHITE, str);
3385 Term_putstr(col0, row1, -1, TERM_WHITE, linestr);
3389 prt(format(_("(a-%c) コマンド:", "(a-%c) Command:"), menu_key + 'a' - 1), 0, 0);
3392 if (key == ESCAPE) return 0;
3394 bool is_alphabet = key >= 'a' && key <= 'z';
3397 com_id = get_com_id(key);
3406 menu_id = menu_id_list[key - 'a'];
3408 if (menu_id < 0) continue;
3410 com_id = menu_data[menu_id].com_id;
3414 com_id = do_command_menu(level + 1, menu_id + 1);
3416 if (com_id) return com_id;
3427 static chain_str_type *new_chain_str(concptr str)
3429 chain_str_type *chain;
3430 size_t len = strlen(str);
3431 chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char));
3432 strcpy(chain->s, str);
3438 static void kill_yank_chain(text_body_type *tb)
3440 chain_str_type *chain = tb->yank;
3442 tb->yank_eol = TRUE;
3446 chain_str_type *next = chain->next;
3447 size_t len = strlen(chain->s);
3449 rnfree(chain, sizeof(chain_str_type) + len * sizeof(char));
3456 static void add_str_to_yank(text_body_type *tb, concptr str)
3458 tb->yank_eol = FALSE;
3459 if (NULL == tb->yank)
3461 tb->yank = new_chain_str(str);
3465 chain_str_type *chain;
3472 chain->next = new_chain_str(str);
3477 chain = chain->next;
3483 * Do work for the copy editor-command
3485 static void copy_text_to_yank(text_body_type *tb)
3487 int len = strlen(tb->lines_list[tb->cy]);
3488 if (tb->cx > len) tb->cx = len;
3497 kill_yank_chain(tb);
3498 if (tb->my != tb->cy)
3500 int by1 = MIN(tb->my, tb->cy);
3501 int by2 = MAX(tb->my, tb->cy);
3503 for (int y = by1; y <= by2; y++)
3505 add_str_to_yank(tb, tb->lines_list[y]);
3508 add_str_to_yank(tb, "");
3510 tb->dirty_flags |= DIRTY_ALL;
3514 char buf[MAX_LINELEN];
3515 int bx1 = MIN(tb->mx, tb->cx);
3516 int bx2 = MAX(tb->mx, tb->cx);
3517 if (bx2 > len) bx2 = len;
3519 if (bx1 == 0 && bx2 == len)
3521 add_str_to_yank(tb, tb->lines_list[tb->cy]);
3522 add_str_to_yank(tb, "");
3526 int end = bx2 - bx1;
3527 for (int i = 0; i < bx2 - bx1; i++)
3529 buf[i] = tb->lines_list[tb->cy][bx1 + i];
3533 add_str_to_yank(tb, buf);
3537 tb->dirty_flags |= DIRTY_ALL;
3544 static void draw_text_editor(player_type *player_ptr, text_body_type *tb)
3547 int by1 = 0, by2 = 0;
3549 Term_get_size(&tb->wid, &tb->hgt);
3552 * Top line (-1), description line (-3), separator (-1)
3555 tb->hgt -= 2 + DESCRIPT_HGT;
3558 /* Don't let cursor at second byte of kanji */
3559 for (i = 0; tb->lines_list[tb->cy][i]; i++)
3560 if (iskanji(tb->lines_list[tb->cy][i]))
3566 * Move to a correct position in the
3569 if (i & 1) tb->cx--;
3575 if (tb->cy < tb->upper || tb->upper + tb->hgt <= tb->cy)
3576 tb->upper = tb->cy - (tb->hgt) / 2;
3579 if ((tb->cx < tb->left + 10 && tb->left > 0) || tb->left + tb->wid - 5 <= tb->cx)
3580 tb->left = tb->cx - (tb->wid) * 2 / 3;
3584 if (tb->old_wid != tb->wid || tb->old_hgt != tb->hgt)
3585 tb->dirty_flags |= DIRTY_SCREEN;
3586 else if (tb->old_upper != tb->upper || tb->old_left != tb->left)
3587 tb->dirty_flags |= DIRTY_ALL;
3589 if (tb->dirty_flags & DIRTY_SCREEN)
3591 tb->dirty_flags |= (DIRTY_ALL | DIRTY_MODE);
3595 if (tb->dirty_flags & DIRTY_MODE)
3597 char buf[MAX_LINELEN];
3598 int sepa_length = tb->wid;
3599 for (i = 0; i < sepa_length; i++)
3602 Term_putstr(0, tb->hgt + 1, sepa_length, TERM_WHITE, buf);
3605 if (tb->dirty_flags & DIRTY_EXPRESSION)
3608 for (int y = 0; tb->lines_list[y]; y++)
3612 concptr s = tb->lines_list[y];
3616 tb->states[y] = state;
3618 if (*s++ != '?') continue;
3619 if (*s++ != ':') continue;
3621 if (streq(s, "$AUTOREGISTER"))
3622 state |= LSTAT_AUTOREGISTER;
3625 ss = (char *)string_make(s);
3628 v = process_pref_file_expr(player_ptr, &ss, &f);
3630 if (streq(v, "0")) state |= LSTAT_BYPASS;
3631 else state &= ~LSTAT_BYPASS;
3633 C_KILL(s_keep, s_len + 1, char);
3635 tb->states[y] = state | LSTAT_EXPRESSION;
3638 tb->dirty_flags |= DIRTY_ALL;
3643 tb->dirty_flags |= DIRTY_ALL;
3645 by1 = MIN(tb->my, tb->cy);
3646 by2 = MAX(tb->my, tb->cy);
3649 for (i = 0; i < tb->hgt; i++)
3655 int y = tb->upper + i;
3657 if (!(tb->dirty_flags & DIRTY_ALL) && (tb->dirty_line != y))
3660 msg = tb->lines_list[y];
3663 for (j = 0; *msg; msg++, j++)
3665 if (j == tb->left) break;
3680 Term_erase(0, i + 1, tb->wid);
3681 if (tb->states[y] & LSTAT_AUTOREGISTER)
3687 if (tb->states[y] & LSTAT_BYPASS) color = TERM_SLATE;
3688 else color = TERM_WHITE;
3691 if (!tb->mark || (y < by1 || by2 < y))
3693 Term_putstr(leftcol, i + 1, tb->wid - 1, color, msg);
3695 else if (by1 != by2)
3697 Term_putstr(leftcol, i + 1, tb->wid - 1, TERM_YELLOW, msg);
3701 int x0 = leftcol + tb->left;
3702 int len = strlen(tb->lines_list[tb->cy]);
3703 int bx1 = MIN(tb->mx, tb->cx);
3704 int bx2 = MAX(tb->mx, tb->cx);
3706 if (bx2 > len) bx2 = len;
3708 Term_gotoxy(leftcol, i + 1);
3709 if (x0 < bx1) Term_addstr(bx1 - x0, color, msg);
3710 if (x0 < bx2) Term_addstr(bx2 - bx1, TERM_YELLOW, msg + (bx1 - x0));
3711 Term_addstr(-1, color, msg + (bx2 - x0));
3715 for (; i < tb->hgt; i++)
3717 Term_erase(0, i + 1, tb->wid);
3720 bool is_dirty_diary = (tb->dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND | DIRTY_NO_SEARCH)) != 0;
3721 bool is_updated = tb->old_cy != tb->cy || is_dirty_diary || tb->dirty_line == tb->cy;
3722 if (is_updated) return;
3724 autopick_type an_entry, *entry = &an_entry;
3725 concptr str1 = NULL, str2 = NULL;
3726 for (i = 0; i < DESCRIPT_HGT; i++)
3728 Term_erase(0, tb->hgt + 2 + i, tb->wid);
3731 if (tb->dirty_flags & DIRTY_NOT_FOUND)
3733 str1 = format(_("パターンが見つかりません: %s", "Pattern not found: %s"), tb->search_str);
3735 else if (tb->dirty_flags & DIRTY_SKIP_INACTIVE)
3737 str1 = format(_("無効状態の行をスキップしました。(%sを検索中)",
3738 "Some inactive lines are skipped. (Searching %s)"), tb->search_str);
3740 else if (tb->dirty_flags & DIRTY_INACTIVE)
3742 str1 = format(_("無効状態の行だけが見付かりました。(%sを検索中)",
3743 "Found only an inactive line. (Searching %s)"), tb->search_str);
3745 else if (tb->dirty_flags & DIRTY_NO_SEARCH)
3747 str1 = _("検索するパターンがありません(^S で検索)。", "No pattern to search. (Press ^S to search.)");
3749 else if (tb->lines_list[tb->cy][0] == '#')
3751 str1 = _("この行はコメントです。", "This line is a comment.");
3753 else if (tb->lines_list[tb->cy][0] && tb->lines_list[tb->cy][1] == ':')
3755 switch (tb->lines_list[tb->cy][0])
3758 str1 = _("この行は条件分岐式です。", "This line is a Conditional Expression.");
3761 str1 = _("この行はマクロの実行内容を定義します。", "This line defines a Macro action.");
3764 str1 = _("この行はマクロのトリガー・キーを定義します。", "This line defines a Macro trigger key.");
3767 str1 = _("この行はキー配置を定義します。", "This line defines a Keymap.");
3771 switch (tb->lines_list[tb->cy][0])
3774 if (tb->states[tb->cy] & LSTAT_BYPASS)
3776 str2 = _("現在の式の値は「偽(=0)」です。", "The expression is 'False'(=0) currently.");
3780 str2 = _("現在の式の値は「真(=1)」です。", "The expression is 'True'(=1) currently.");
3785 if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
3787 str2 = _("この行は後で削除されます。", "This line will be delete later.");
3790 else if (tb->states[tb->cy] & LSTAT_BYPASS)
3792 str2 = _("この行は現在は無効な状態です。", "This line is bypassed currently.");
3797 else if (autopick_new_entry(entry, tb->lines_list[tb->cy], FALSE))
3799 char buf[MAX_LINELEN];
3800 char temp[MAX_LINELEN];
3803 describe_autopick(buf, entry);
3805 if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
3807 strcat(buf, _("この行は後で削除されます。", " This line will be delete later."));
3810 if (tb->states[tb->cy] & LSTAT_BYPASS)
3812 strcat(buf, _("この行は現在は無効な状態です。", " This line is bypassed currently."));
3815 roff_to_buf(buf, 81, temp, sizeof(temp));
3817 for (i = 0; i < 3; i++)
3823 prt(t, tb->hgt + 1 + 1 + i, 0);
3827 autopick_free_entry(entry);
3830 if (str1) prt(str1, tb->hgt + 1 + 1, 0);
3831 if (str2) prt(str2, tb->hgt + 1 + 2, 0);
3836 * Kill segment of a line
3838 static void kill_line_segment(text_body_type *tb, int y, int x0, int x1, bool whole)
3840 concptr s = tb->lines_list[y];
3841 if (whole && x0 == 0 && s[x1] == '\0' && tb->lines_list[y + 1])
3843 string_free(tb->lines_list[y]);
3846 for (i = y; tb->lines_list[i + 1]; i++)
3847 tb->lines_list[i] = tb->lines_list[i + 1];
3848 tb->lines_list[i] = NULL;
3850 tb->dirty_flags |= DIRTY_EXPRESSION;
3855 if (x0 == x1) return;
3857 char buf[MAX_LINELEN];
3859 for (int x = 0; x < x0; x++)
3862 for (int x = x1; s[x]; x++)
3866 string_free(tb->lines_list[y]);
3867 tb->lines_list[y] = string_make(buf);
3868 check_expression_line(tb, y);
3874 * Get a trigger key and insert ASCII string for the trigger
3876 static bool insert_macro_line(text_body_type *tb)
3895 ascii_to_text(tmp, buf);
3896 if (!tmp[0]) return FALSE;
3899 insert_return_code(tb);
3900 string_free(tb->lines_list[tb->cy]);
3901 tb->lines_list[tb->cy] = string_make(format("P:%s", tmp));
3903 i = macro_find_exact(buf);
3910 ascii_to_text(tmp, macro__act[i]);
3913 insert_return_code(tb);
3914 string_free(tb->lines_list[tb->cy]);
3915 tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
3922 * Get a command key and insert ASCII string for the key
3924 static bool insert_keymap_line(text_body_type *tb)
3927 if (rogue_like_commands)
3929 mode = KEYMAP_MODE_ROGUE;
3933 mode = KEYMAP_MODE_ORIG;
3943 ascii_to_text(tmp, buf);
3944 if (!tmp[0]) return FALSE;
3947 insert_return_code(tb);
3948 string_free(tb->lines_list[tb->cy]);
3949 tb->lines_list[tb->cy] = string_make(format("C:%d:%s", mode, tmp));
3951 concptr act = keymap_act[mode][(byte)(buf[0])];
3954 ascii_to_text(tmp, act);
3957 insert_return_code(tb);
3958 string_free(tb->lines_list[tb->cy]);
3959 tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
3966 * Execute a single editor command
3968 static bool do_editor_command(player_type *player_ptr, text_body_type *tb, int com_id)
3975 if (!get_check(_("全ての変更を破棄してから終了します。よろしいですか? ",
3976 "Discard all changes and quit. Are you sure? "))) break;
3979 return QUIT_WITHOUT_SAVE;
3982 return QUIT_AND_SAVE;
3985 if (!get_check(_("全ての変更を破棄して元の状態に戻します。よろしいですか? ",
3986 "Discard all changes and revert to original file. Are you sure? "))) break;
3988 free_text_lines(tb->lines_list);
3989 tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
3990 tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
3991 tb->cx = tb->cy = 0;
3994 tb->changed = FALSE;
3998 (void)show_file(player_ptr, TRUE, _("jeditor.txt", "editor.txt"), NULL, 0, 0);
3999 tb->dirty_flags |= DIRTY_SCREEN;
4007 tb->dirty_flags |= DIRTY_ALL;
4010 insert_return_code(tb);
4014 tb->dirty_flags |= DIRTY_ALL;
4026 len = strlen(tb->lines_list[tb->cy]);
4027 if (len < tb->cx) tb->cx = len;
4029 for (i = 0; tb->lines_list[tb->cy][i]; i++)
4031 if (iskanji(tb->lines_list[tb->cy][i]))
4043 else if (tb->cy > 0)
4046 tb->cx = strlen(tb->lines_list[tb->cy]);
4052 if (!tb->lines_list[tb->cy + 1])
4054 if (!add_empty_line(tb)) break;
4061 if (tb->cy > 0) tb->cy--;
4067 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
4070 int len = strlen(tb->lines_list[tb->cy]);
4074 if (!tb->lines_list[tb->cy + 1])
4076 if (!add_empty_line(tb)) break;
4090 tb->cx = strlen(tb->lines_list[tb->cy]);
4094 while (0 < tb->cy && tb->upper <= tb->cy)
4096 while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt)
4101 while (tb->cy < tb->upper + tb->hgt)
4103 if (!tb->lines_list[tb->cy + 1])
4105 if (!add_empty_line(tb)) break;
4121 if (!tb->lines_list[tb->cy + 1])
4123 if (!add_empty_line(tb)) break;
4134 copy_text_to_yank(tb);
4135 if (tb->my == tb->cy)
4137 int bx1 = MIN(tb->mx, tb->cx);
4138 int bx2 = MAX(tb->mx, tb->cx);
4139 int len = strlen(tb->lines_list[tb->cy]);
4140 if (bx2 > len) bx2 = len;
4142 kill_line_segment(tb, tb->cy, bx1, bx2, TRUE);
4147 int by1 = MIN(tb->my, tb->cy);
4148 int by2 = MAX(tb->my, tb->cy);
4150 for (int y = by2; y >= by1; y--)
4152 int len = strlen(tb->lines_list[y]);
4154 kill_line_segment(tb, y, 0, len, TRUE);
4162 tb->dirty_flags |= DIRTY_ALL;
4167 copy_text_to_yank(tb);
4170 * Move cursor position to the end of the selection
4172 * Pressing ^C ^V correctly duplicates the selection.
4174 if (tb->my != tb->cy)
4176 tb->cy = MAX(tb->cy, tb->my);
4177 if (!tb->lines_list[tb->cy + 1])
4179 if (!add_empty_line(tb)) break;
4186 tb->cx = MAX(tb->cx, tb->mx);
4187 if (!tb->lines_list[tb->cy][tb->cx])
4189 if (!tb->lines_list[tb->cy + 1])
4191 if (!add_empty_line(tb)) break;
4202 chain_str_type *chain = tb->yank;
4203 int len = strlen(tb->lines_list[tb->cy]);
4205 if (tb->cx > len) tb->cx = len;
4210 tb->dirty_flags |= DIRTY_ALL;
4215 concptr yank_str = chain->s;
4216 char buf[MAX_LINELEN];
4218 char rest[MAX_LINELEN], *rest_ptr = rest;
4219 for (i = 0; i < tb->cx; i++)
4220 buf[i] = tb->lines_list[tb->cy][i];
4222 strcpy(rest, &(tb->lines_list[tb->cy][i]));
4223 while (*yank_str && i < MAX_LINELEN - 1)
4225 buf[i++] = *yank_str++;
4229 chain = chain->next;
4230 if (chain || tb->yank_eol)
4232 insert_return_code(tb);
4233 string_free(tb->lines_list[tb->cy]);
4234 tb->lines_list[tb->cy] = string_make(buf);
4241 tb->cx = strlen(buf);
4242 while (*rest_ptr && i < MAX_LINELEN - 1)
4244 buf[i++] = *rest_ptr++;
4248 string_free(tb->lines_list[tb->cy]);
4249 tb->lines_list[tb->cy] = string_make(buf);
4253 tb->dirty_flags |= DIRTY_ALL;
4254 tb->dirty_flags |= DIRTY_EXPRESSION;
4263 tb->dirty_flags |= DIRTY_ALL;
4267 tb->mark = MARK_MARK;
4268 if (com_id == tb->old_com_id)
4276 tb->dirty_flags |= DIRTY_ALL;
4280 int len = strlen(tb->lines_list[tb->cy]);
4284 if (tb->cx > len) tb->mx = len;
4289 int len = strlen(tb->lines_list[tb->cy]);
4290 if (tb->cx > len) tb->cx = len;
4295 tb->dirty_flags |= DIRTY_ALL;
4298 if (tb->old_com_id != com_id)
4300 kill_yank_chain(tb);
4306 add_str_to_yank(tb, &(tb->lines_list[tb->cy][tb->cx]));
4307 kill_line_segment(tb, tb->cy, tb->cx, len, FALSE);
4308 tb->dirty_line = tb->cy;
4312 if (tb->yank_eol) add_str_to_yank(tb, "");
4314 tb->yank_eol = TRUE;
4315 do_editor_command(player_ptr, tb, EC_DELETE_CHAR);
4318 case EC_DELETE_CHAR:
4323 tb->dirty_flags |= DIRTY_ALL;
4327 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
4330 int len = strlen(tb->lines_list[tb->cy]);
4333 do_editor_command(player_ptr, tb, EC_BACKSPACE);
4337 if (tb->lines_list[tb->cy + 1])
4348 do_editor_command(player_ptr, tb, EC_BACKSPACE);
4354 char buf[MAX_LINELEN];
4358 tb->dirty_flags |= DIRTY_ALL;
4361 len = strlen(tb->lines_list[tb->cy]);
4362 if (len < tb->cx) tb->cx = len;
4366 if (tb->cy == 0) break;
4367 tb->cx = strlen(tb->lines_list[tb->cy - 1]);
4368 strcpy(buf, tb->lines_list[tb->cy - 1]);
4369 strcat(buf, tb->lines_list[tb->cy]);
4370 string_free(tb->lines_list[tb->cy - 1]);
4371 string_free(tb->lines_list[tb->cy]);
4372 tb->lines_list[tb->cy - 1] = string_make(buf);
4374 for (i = tb->cy; tb->lines_list[i + 1]; i++)
4375 tb->lines_list[i] = tb->lines_list[i + 1];
4377 tb->lines_list[i] = NULL;
4379 tb->dirty_flags |= DIRTY_ALL;
4380 tb->dirty_flags |= DIRTY_EXPRESSION;
4385 for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4389 if (iskanji(tb->lines_list[tb->cy][i]))
4390 buf[j++] = tb->lines_list[tb->cy][i++];
4392 buf[j++] = tb->lines_list[tb->cy][i];
4401 for (; tb->lines_list[tb->cy][i]; i++)
4403 buf[j++] = tb->lines_list[tb->cy][i];
4407 string_free(tb->lines_list[tb->cy]);
4408 tb->lines_list[tb->cy] = string_make(buf);
4409 tb->dirty_line = tb->cy;
4410 check_expression_line(tb, tb->cy);
4417 tb->dirty_flags |= DIRTY_SCREEN;
4418 search_dir = get_string_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str);
4420 if (!search_dir) break;
4422 if (search_dir == 1) do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4423 else do_editor_command(player_ptr, tb, EC_SEARCH_BACK);
4426 case EC_SEARCH_FORW:
4427 if (tb->search_o_ptr)
4429 search_for_object(player_ptr, tb, tb->search_o_ptr, TRUE);
4433 if (tb->search_str && tb->search_str[0])
4435 search_for_string(tb, tb->search_str, TRUE);
4439 tb->dirty_flags |= DIRTY_NO_SEARCH;
4442 case EC_SEARCH_BACK:
4443 if (tb->search_o_ptr)
4445 search_for_object(player_ptr, tb, tb->search_o_ptr, FALSE);
4449 if (tb->search_str && tb->search_str[0])
4451 search_for_string(tb, tb->search_str, FALSE);
4455 tb->dirty_flags |= DIRTY_NO_SEARCH;
4459 tb->dirty_flags |= DIRTY_SCREEN;
4461 if (!get_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str)) break;
4463 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4466 case EC_SEARCH_DESTROYED:
4467 if (!get_destroyed_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str))
4469 tb->dirty_flags |= DIRTY_NO_SEARCH;
4473 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4476 case EC_INSERT_OBJECT:
4478 autopick_type an_entry, *entry = &an_entry;
4479 if (!entry_from_choosed_object(player_ptr, entry))
4481 tb->dirty_flags |= DIRTY_SCREEN;
4486 insert_return_code(tb);
4487 string_free(tb->lines_list[tb->cy]);
4488 tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry);
4489 tb->dirty_flags |= DIRTY_SCREEN;
4492 case EC_INSERT_DESTROYED:
4493 if (!tb->last_destroyed) break;
4496 insert_return_code(tb);
4497 string_free(tb->lines_list[tb->cy]);
4498 tb->lines_list[tb->cy] = string_make(tb->last_destroyed);
4499 tb->dirty_flags |= DIRTY_ALL;
4503 case EC_INSERT_BLOCK:
4505 char expression[80];
4506 sprintf(expression, "?:[AND [EQU $RACE %s] [EQU $CLASS %s] [GEQ $LEVEL %02d]]",
4508 rp_ptr->E_title, cp_ptr->E_title,
4510 rp_ptr->title, cp_ptr->title,
4514 insert_return_code(tb);
4515 string_free(tb->lines_list[tb->cy]);
4516 tb->lines_list[tb->cy] = string_make(expression);
4518 insert_return_code(tb);
4519 string_free(tb->lines_list[tb->cy]);
4520 tb->lines_list[tb->cy] = string_make("?:1");
4521 tb->dirty_flags |= DIRTY_ALL;
4526 case EC_INSERT_MACRO:
4527 draw_text_editor(player_ptr, tb);
4528 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
4529 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, _("P:<トリガーキー>: ", "P:<Trigger key>: "));
4530 if (!insert_macro_line(tb)) break;
4533 tb->dirty_flags |= DIRTY_ALL;
4537 case EC_INSERT_KEYMAP:
4538 draw_text_editor(player_ptr, tb);
4539 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
4540 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW,
4541 format(_("C:%d:<コマンドキー>: ", "C:%d:<Keypress>: "), (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
4543 if (!insert_keymap_line(tb)) break;
4546 tb->dirty_flags |= DIRTY_ALL;
4550 case EC_CL_AUTOPICK: toggle_command_letter(tb, DO_AUTOPICK); break;
4551 case EC_CL_DESTROY: toggle_command_letter(tb, DO_AUTODESTROY); break;
4552 case EC_CL_LEAVE: toggle_command_letter(tb, DONT_AUTOPICK); break;
4553 case EC_CL_QUERY: toggle_command_letter(tb, DO_QUERY_AUTOPICK); break;
4554 case EC_CL_NO_DISP: toggle_command_letter(tb, DO_DISPLAY); break;
4556 case EC_IK_UNAWARE: toggle_keyword(tb, FLG_UNAWARE); break;
4557 case EC_IK_UNIDENTIFIED: toggle_keyword(tb, FLG_UNIDENTIFIED); break;
4558 case EC_IK_IDENTIFIED: toggle_keyword(tb, FLG_IDENTIFIED); break;
4559 case EC_IK_STAR_IDENTIFIED: toggle_keyword(tb, FLG_STAR_IDENTIFIED); break;
4560 case EC_KK_WEAPONS: toggle_keyword(tb, FLG_WEAPONS); break;
4561 case EC_KK_FAVORITE_WEAPONS: toggle_keyword(tb, FLG_FAVORITE_WEAPONS); break;
4562 case EC_KK_ARMORS: toggle_keyword(tb, FLG_ARMORS); break;
4563 case EC_KK_MISSILES: toggle_keyword(tb, FLG_MISSILES); break;
4564 case EC_KK_DEVICES: toggle_keyword(tb, FLG_DEVICES); break;
4565 case EC_KK_LIGHTS: toggle_keyword(tb, FLG_LIGHTS); break;
4566 case EC_KK_JUNKS: toggle_keyword(tb, FLG_JUNKS); break;
4567 case EC_KK_CORPSES: toggle_keyword(tb, FLG_CORPSES); break;
4568 case EC_KK_SPELLBOOKS: toggle_keyword(tb, FLG_SPELLBOOKS); break;
4569 case EC_KK_SHIELDS: toggle_keyword(tb, FLG_SHIELDS); break;
4570 case EC_KK_BOWS: toggle_keyword(tb, FLG_BOWS); break;
4571 case EC_KK_RINGS: toggle_keyword(tb, FLG_RINGS); break;
4572 case EC_KK_AMULETS: toggle_keyword(tb, FLG_AMULETS); break;
4573 case EC_KK_SUITS: toggle_keyword(tb, FLG_SUITS); break;
4574 case EC_KK_CLOAKS: toggle_keyword(tb, FLG_CLOAKS); break;
4575 case EC_KK_HELMS: toggle_keyword(tb, FLG_HELMS); break;
4576 case EC_KK_GLOVES: toggle_keyword(tb, FLG_GLOVES); break;
4577 case EC_KK_BOOTS: toggle_keyword(tb, FLG_BOOTS); break;
4578 case EC_OK_COLLECTING: toggle_keyword(tb, FLG_COLLECTING); break;
4579 case EC_OK_BOOSTED: toggle_keyword(tb, FLG_BOOSTED); break;
4580 case EC_OK_MORE_DICE: toggle_keyword(tb, FLG_MORE_DICE); break;
4581 case EC_OK_MORE_BONUS: toggle_keyword(tb, FLG_MORE_BONUS); break;
4582 case EC_OK_WORTHLESS: toggle_keyword(tb, FLG_WORTHLESS); break;
4583 case EC_OK_ARTIFACT: toggle_keyword(tb, FLG_ARTIFACT); break;
4584 case EC_OK_EGO: toggle_keyword(tb, FLG_EGO); break;
4585 case EC_OK_GOOD: toggle_keyword(tb, FLG_GOOD); break;
4586 case EC_OK_NAMELESS: toggle_keyword(tb, FLG_NAMELESS); break;
4587 case EC_OK_AVERAGE: toggle_keyword(tb, FLG_AVERAGE); break;
4588 case EC_OK_RARE: toggle_keyword(tb, FLG_RARE); break;
4589 case EC_OK_COMMON: toggle_keyword(tb, FLG_COMMON); break;
4590 case EC_OK_WANTED: toggle_keyword(tb, FLG_WANTED); break;
4591 case EC_OK_UNIQUE: toggle_keyword(tb, FLG_UNIQUE); break;
4592 case EC_OK_HUMAN: toggle_keyword(tb, FLG_HUMAN); break;
4593 case EC_OK_UNREADABLE:
4594 toggle_keyword(tb, FLG_UNREADABLE);
4595 add_keyword(tb, FLG_SPELLBOOKS);
4598 toggle_keyword(tb, FLG_REALM1);
4599 add_keyword(tb, FLG_SPELLBOOKS);
4602 toggle_keyword(tb, FLG_REALM2);
4603 add_keyword(tb, FLG_SPELLBOOKS);
4606 toggle_keyword(tb, FLG_FIRST);
4607 add_keyword(tb, FLG_SPELLBOOKS);
4610 toggle_keyword(tb, FLG_SECOND);
4611 add_keyword(tb, FLG_SPELLBOOKS);
4614 toggle_keyword(tb, FLG_THIRD);
4615 add_keyword(tb, FLG_SPELLBOOKS);
4618 toggle_keyword(tb, FLG_FOURTH);
4619 add_keyword(tb, FLG_SPELLBOOKS);
4623 tb->old_com_id = com_id;
4629 * Insert single letter at cursor position.
4631 static void insert_single_letter(text_body_type *tb, int key)
4634 char buf[MAX_LINELEN];
4636 for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4638 buf[j++] = tb->lines_list[tb->cy][i];
4648 if (j + 2 < MAX_LINELEN)
4650 buf[j++] = (char)key;
4651 buf[j++] = (char)next;
4660 if (j + 1 < MAX_LINELEN)
4661 buf[j++] = (char)key;
4665 for (; tb->lines_list[tb->cy][i] && j + 1 < MAX_LINELEN; i++)
4666 buf[j++] = tb->lines_list[tb->cy][i];
4669 string_free(tb->lines_list[tb->cy]);
4670 tb->lines_list[tb->cy] = string_make(buf);
4671 len = strlen(tb->lines_list[tb->cy]);
4672 if (len < tb->cx) tb->cx = len;
4674 tb->dirty_line = tb->cy;
4675 check_expression_line(tb, tb->cy);
4681 * Check special key code and get a movement command id
4683 static int analyze_move_key(text_body_type *tb, int skey)
4686 if (!(skey & SKEY_MASK)) return 0;
4688 switch (skey & ~SKEY_MOD_MASK)
4690 case SKEY_DOWN: com_id = EC_DOWN; break;
4691 case SKEY_LEFT: com_id = EC_LEFT; break;
4692 case SKEY_RIGHT: com_id = EC_RIGHT; break;
4693 case SKEY_UP: com_id = EC_UP; break;
4694 case SKEY_PGUP: com_id = EC_PGUP; break;
4695 case SKEY_PGDOWN: com_id = EC_PGDOWN; break;
4696 case SKEY_TOP: com_id = EC_TOP; break;
4697 case SKEY_BOTTOM: com_id = EC_BOTTOM; break;
4702 if (!(skey & SKEY_MOD_SHIFT))
4705 * Un-shifted cursor keys cancells
4706 * selection created by shift+cursor.
4708 if (tb->mark & MARK_BY_SHIFT)
4711 tb->dirty_flags |= DIRTY_ALL;
4717 if (tb->mark) return com_id;
4719 int len = strlen(tb->lines_list[tb->cy]);
4720 tb->mark = MARK_MARK | MARK_BY_SHIFT;
4723 if (tb->cx > len) tb->mx = len;
4725 if (com_id == EC_UP || com_id == EC_DOWN)
4727 tb->dirty_flags |= DIRTY_ALL;
4731 tb->dirty_line = tb->cy;
4738 * In-game editor of Object Auto-picker/Destoryer
4739 * @param player_ptr プレーヤーへの参照ポインタ
4741 void do_cmd_edit_autopick(player_type *player_ptr)
4743 static int cx_save = 0;
4744 static int cy_save = 0;
4745 text_body_type text_body, *tb = &text_body;
4746 autopick_type an_entry, *entry = &an_entry;
4747 char buf[MAX_LINELEN];
4750 static s32b old_autosave_turn = 0L;
4753 tb->changed = FALSE;
4756 tb->upper = tb->left = 0;
4758 tb->mx = tb->my = 0;
4759 tb->old_cy = tb->old_upper = tb->old_left = -1;
4760 tb->old_wid = tb->old_hgt = -1;
4764 tb->search_o_ptr = NULL;
4765 tb->search_str = NULL;
4766 tb->last_destroyed = NULL;
4767 tb->dirty_flags = DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
4768 tb->dirty_line = -1;
4769 tb->filename_mode = PT_DEFAULT;
4771 if (current_world_ptr->game_turn < old_autosave_turn)
4773 while (old_autosave_turn > current_world_ptr->game_turn) old_autosave_turn -= TURNS_PER_TICK * TOWN_DAWN;
4776 if (current_world_ptr->game_turn > old_autosave_turn + 100L)
4778 do_cmd_save_game(player_ptr, TRUE);
4779 old_autosave_turn = current_world_ptr->game_turn;
4784 if (autopick_last_destroyed_object.k_idx)
4786 autopick_entry_from_object(player_ptr, entry, &autopick_last_destroyed_object);
4787 tb->last_destroyed = autopick_line_from_entry_kill(entry);
4790 tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
4791 for (i = 0; i < tb->cy; i++)
4793 if (!tb->lines_list[i])
4795 tb->cy = tb->cx = 0;
4804 draw_text_editor(player_ptr, tb);
4805 prt(_("(^Q:終了 ^W:セーブして終了, ESC:メニュー, その他:入力)",
4806 "(^Q:Quit, ^W:Save&Quit, ESC:Menu, Other:Input text)"), 0, 0);
4809 prt(format("(%d,%d)", tb->cx, tb->cy), 0, 60);
4813 prt(format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60);
4816 Term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1);
4817 tb->dirty_flags = 0;
4818 tb->dirty_line = -1;
4819 tb->old_cy = tb->cy;
4820 tb->old_upper = tb->upper;
4821 tb->old_left = tb->left;
4822 tb->old_wid = tb->wid;
4823 tb->old_hgt = tb->hgt;
4825 key = inkey_special(TRUE);
4827 if (key & SKEY_MASK)
4829 com_id = analyze_move_key(tb, key);
4831 else if (key == ESCAPE)
4833 com_id = do_command_menu(0, 0);
4834 tb->dirty_flags |= DIRTY_SCREEN;
4836 else if (!iscntrl((unsigned char)key))
4841 tb->dirty_flags |= DIRTY_ALL;
4844 insert_single_letter(tb, key);
4849 com_id = get_com_id((char)key);
4852 if (com_id) quit = do_editor_command(player_ptr, tb, com_id);
4856 strcpy(buf, pickpref_filename(player_ptr, tb->filename_mode));
4858 if (quit == QUIT_AND_SAVE)
4859 write_text_lines(buf, tb->lines_list);
4861 free_text_lines(tb->lines_list);
4862 string_free(tb->search_str);
4863 string_free(tb->last_destroyed);
4864 kill_yank_chain(tb);
4866 process_autopick_file(player_ptr, buf);
4867 current_world_ptr->start_time = (u32b)time(NULL);