OSDN Git Service

2df26fe86fc06851e18a8a2ab38ed20ed4e0bef6
[hengband/hengband.git] / src / autopick / autopick.c
1 /*!
2  * @file autopick.c
3  * @brief 自動拾い機能の実装 / Object Auto-picker/Destroyer
4  * @date 2014/01/02
5  * @author
6  * Copyright (c) 2002  Mogami\n
7  *\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
12  */
13
14 #include "angband.h"
15 #include "util.h"
16 #include "autopick/autopick-commands-table.h"
17 #include "autopick/autopick-dirty-flags.h"
18 #include "autopick/autopick-flags-table.h"
19 #include "autopick/autopick-initializer.h"
20 #include "autopick/autopick-key-flag-process.h"
21 #include "autopick/autopick-menu-data-table.h"
22 #include "autopick/autopick-methods-table.h"
23 #include "autopick/autopick-destroyer.h"
24 #include "autopick/autopick-entry.h"
25 #include "autopick/autopick-reader-writer.h"
26 #include "autopick/autopick-finder.h"
27 #include "autopick/autopick-drawer.h"
28 #include "autopick/autopick-searcher.h"
29 #include "autopick/autopick-inserter-killer.h"
30 #include "autopick/autopick-registry.h"
31 #include "autopick/autopick-command-menu.h"
32 #include "autopick/autopick-editor-util.h"
33 #include "autopick/autopick-editor-command.h"
34 #include "gameterm.h"
35 #include "autopick/autopick.h"
36 #include "core/show-file.h"
37 #include "cmd/cmd-save.h"
38 #include "io/read-pref-file.h"
39
40 #include "mind.h"
41
42 #include "market/store.h"
43 #include "player-move.h"
44 #include "player-class.h"
45 #include "view/display-player.h" // 暫定。後で消す.
46 #include "object-flavor.h"
47
48 #include "world.h"
49 #include "view/display-main-window.h" // 暫定。後で消す.
50
51 /*
52  *  Auto-destroy marked item
53  */
54 static void autopick_delayed_alter_aux(player_type *player_ptr, INVENTORY_IDX item)
55 {
56         object_type *o_ptr;
57         o_ptr = REF_ITEM(player_ptr, player_ptr->current_floor_ptr, item);
58
59         if (o_ptr->k_idx == 0 || !(o_ptr->marked & OM_AUTODESTROY)) return;
60
61         GAME_TEXT o_name[MAX_NLEN];
62         object_desc(player_ptr, o_name, o_ptr, 0);
63         if (item >= 0)
64         {
65                 inven_item_increase(player_ptr, item, -(o_ptr->number));
66                 inven_item_optimize(player_ptr, item);
67         }
68         else
69         {
70                 delete_object_idx(player_ptr, 0 - item);
71         }
72
73         msg_format(_("%sを自動破壊します。", "Auto-destroying %s."), o_name);
74 }
75
76
77 /*
78  *  Auto-destroy marked items in inventry and on floor
79  */
80 void autopick_delayed_alter(player_type *owner_ptr)
81 {
82         INVENTORY_IDX item;
83
84         /*
85          * Scan inventry in reverse order to prevent
86          * skipping after inven_item_optimize()
87          */
88         for (item = INVEN_TOTAL - 1; item >= 0; item--)
89                 autopick_delayed_alter_aux(owner_ptr, item);
90
91         floor_type *floor_ptr = owner_ptr->current_floor_ptr;
92         item = floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx;
93         while (item)
94         {
95                 OBJECT_IDX next = floor_ptr->o_list[item].next_o_idx;
96                 autopick_delayed_alter_aux(owner_ptr, -item);
97                 item = next;
98         }
99 }
100
101
102 /*
103  * Auto-inscription and/or destroy
104  *
105  * Auto-destroyer works only on inventory or on floor stack only when
106  * requested.
107  */
108 void autopick_alter_item(player_type *player_ptr, INVENTORY_IDX item, bool destroy)
109 {
110         object_type *o_ptr;
111         o_ptr = REF_ITEM(player_ptr, player_ptr->current_floor_ptr, item);
112         int idx = find_autopick_list(player_ptr, o_ptr);
113         auto_inscribe_item(player_ptr, o_ptr, idx);
114         if (destroy && item <= INVEN_PACK)
115                 auto_destroy_item(player_ptr, o_ptr, idx);
116 }
117
118
119 /*
120  * Automatically pickup/destroy items in this grid.
121  */
122 void autopick_pickup_items(player_type* player_ptr, grid_type *g_ptr)
123 {
124         OBJECT_IDX this_o_idx, next_o_idx = 0;
125         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
126         {
127                 object_type *o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
128                 next_o_idx = o_ptr->next_o_idx;
129                 int idx = find_autopick_list(player_ptr, o_ptr);
130                 auto_inscribe_item(player_ptr, o_ptr, idx);
131                 bool is_auto_pickup = idx >= 0;
132                 is_auto_pickup &= (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK)) != 0;
133                 if (!is_auto_pickup)
134                 {
135                         auto_destroy_item(player_ptr, o_ptr, idx);
136                         continue;
137                 }
138
139                 disturb(player_ptr, FALSE, FALSE);
140                 if (!inven_carry_okay(o_ptr))
141                 {
142                         GAME_TEXT o_name[MAX_NLEN];
143                         object_desc(player_ptr, o_name, o_ptr, 0);
144                         msg_format(_("ザックには%sを入れる隙間がない。", "You have no room for %s."), o_name);
145                         o_ptr->marked |= OM_NOMSG;
146                         continue;
147                 }
148
149                 if (!(autopick_list[idx].action & DO_QUERY_AUTOPICK))
150                 {
151                         py_pickup_aux(player_ptr, this_o_idx);
152                         continue;
153                 }
154
155                 char out_val[MAX_NLEN + 20];
156                 GAME_TEXT o_name[MAX_NLEN];
157                 if (o_ptr->marked & OM_NO_QUERY)
158                 {
159                         continue;
160                 }
161
162                 object_desc(player_ptr, o_name, o_ptr, 0);
163                 sprintf(out_val, _("%sを拾いますか? ", "Pick up %s? "), o_name);
164                 if (!get_check(out_val))
165                 {
166                         o_ptr->marked |= OM_NOMSG | OM_NO_QUERY;
167                         continue;
168                 }
169
170                 py_pickup_aux(player_ptr, this_o_idx);
171         }
172 }
173
174
175 /*
176  * Check special key code and get a movement command id
177  */
178 static int analyze_move_key(text_body_type *tb, int skey)
179 {
180         int com_id;
181         if (!(skey & SKEY_MASK)) return 0;
182
183         switch (skey & ~SKEY_MOD_MASK)
184         {
185         case SKEY_DOWN:   com_id = EC_DOWN;   break;
186         case SKEY_LEFT:   com_id = EC_LEFT;   break;
187         case SKEY_RIGHT:  com_id = EC_RIGHT;  break;
188         case SKEY_UP:     com_id = EC_UP;     break;
189         case SKEY_PGUP:   com_id = EC_PGUP;   break;
190         case SKEY_PGDOWN: com_id = EC_PGDOWN; break;
191         case SKEY_TOP:    com_id = EC_TOP;    break;
192         case SKEY_BOTTOM: com_id = EC_BOTTOM; break;
193         default:
194                 return 0;
195         }
196
197         if (!(skey & SKEY_MOD_SHIFT))
198         {
199                 /*
200                  * Un-shifted cursor keys cancells
201                  * selection created by shift+cursor.
202                  */
203                 if (tb->mark & MARK_BY_SHIFT)
204                 {
205                         tb->mark = 0;
206                         tb->dirty_flags |= DIRTY_ALL;
207                 }
208
209                 return com_id;
210         }
211
212         if (tb->mark) return com_id;
213
214         int len = strlen(tb->lines_list[tb->cy]);
215         tb->mark = MARK_MARK | MARK_BY_SHIFT;
216         tb->my = tb->cy;
217         tb->mx = tb->cx;
218         if (tb->cx > len) tb->mx = len;
219
220         if (com_id == EC_UP || com_id == EC_DOWN)
221         {
222                 tb->dirty_flags |= DIRTY_ALL;
223         }
224         else
225         {
226                 tb->dirty_line = tb->cy;
227         }
228
229         return com_id;
230 }
231
232 /*
233  * In-game editor of Object Auto-picker/Destoryer
234  * @param player_ptr プレーヤーへの参照ポインタ
235  */
236 void do_cmd_edit_autopick(player_type *player_ptr)
237 {
238         static int cx_save = 0;
239         static int cy_save = 0;
240         autopick_type an_entry, *entry = &an_entry;
241         char buf[MAX_LINELEN];
242         int i;
243         int key = -1;
244         static s32b old_autosave_turn = 0L;
245         byte quit = 0;
246
247         text_body_type text_body;
248         text_body_type *tb = &text_body;
249         tb->changed = FALSE;
250         tb->cx = cx_save;
251         tb->cy = cy_save;
252         tb->upper = tb->left = 0;
253         tb->mark = 0;
254         tb->mx = tb->my = 0;
255         tb->old_cy = tb->old_upper = tb->old_left = -1;
256         tb->old_wid = tb->old_hgt = -1;
257         tb->old_com_id = 0;
258
259         tb->yank = NULL;
260         tb->search_o_ptr = NULL;
261         tb->search_str = NULL;
262         tb->last_destroyed = NULL;
263         tb->dirty_flags = DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
264         tb->dirty_line = -1;
265         tb->filename_mode = PT_DEFAULT;
266
267         if (current_world_ptr->game_turn < old_autosave_turn)
268         {
269                 while (old_autosave_turn > current_world_ptr->game_turn) old_autosave_turn -= TURNS_PER_TICK * TOWN_DAWN;
270         }
271
272         if (current_world_ptr->game_turn > old_autosave_turn + 100L)
273         {
274                 do_cmd_save_game(player_ptr, TRUE);
275                 old_autosave_turn = current_world_ptr->game_turn;
276         }
277
278         update_playtime();
279         init_autopick();
280         if (autopick_last_destroyed_object.k_idx)
281         {
282                 autopick_entry_from_object(player_ptr, entry, &autopick_last_destroyed_object);
283                 tb->last_destroyed = autopick_line_from_entry_kill(entry);
284         }
285
286         tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
287         for (i = 0; i < tb->cy; i++)
288         {
289                 if (!tb->lines_list[i])
290                 {
291                         tb->cy = tb->cx = 0;
292                         break;
293                 }
294         }
295
296         screen_save();
297         while (!quit)
298         {
299                 int com_id = 0;
300                 draw_text_editor(player_ptr, tb);
301                 prt(_("(^Q:終了 ^W:セーブして終了, ESC:メニュー, その他:入力)",
302                         "(^Q:Quit, ^W:Save&Quit, ESC:Menu, Other:Input text)"), 0, 0);
303                 if (!tb->mark)
304                 {
305                         prt(format("(%d,%d)", tb->cx, tb->cy), 0, 60);
306                 }
307                 else
308                 {
309                         prt(format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60);
310                 }
311
312                 Term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1);
313                 tb->dirty_flags = 0;
314                 tb->dirty_line = -1;
315                 tb->old_cy = tb->cy;
316                 tb->old_upper = tb->upper;
317                 tb->old_left = tb->left;
318                 tb->old_wid = tb->wid;
319                 tb->old_hgt = tb->hgt;
320
321                 key = inkey_special(TRUE);
322
323                 if (key & SKEY_MASK)
324                 {
325                         com_id = analyze_move_key(tb, key);
326                 }
327                 else if (key == ESCAPE)
328                 {
329                         com_id = do_command_menu(0, 0);
330                         tb->dirty_flags |= DIRTY_SCREEN;
331                 }
332                 else if (!iscntrl((unsigned char)key))
333                 {
334                         if (tb->mark)
335                         {
336                                 tb->mark = 0;
337                                 tb->dirty_flags |= DIRTY_ALL;
338                         }
339
340                         insert_single_letter(tb, key);
341                         continue;
342                 }
343                 else
344                 {
345                         com_id = get_com_id((char)key);
346                 }
347
348                 if (com_id) quit = do_editor_command(player_ptr, tb, com_id);
349         }
350
351         screen_load();
352         strcpy(buf, pickpref_filename(player_ptr, tb->filename_mode));
353
354         if (quit == QUIT_AND_SAVE)
355                 write_text_lines(buf, tb->lines_list);
356
357         free_text_lines(tb->lines_list);
358         string_free(tb->search_str);
359         string_free(tb->last_destroyed);
360         kill_yank_chain(tb);
361
362         process_autopick_file(player_ptr, buf);
363         current_world_ptr->start_time = (u32b)time(NULL);
364         cx_save = tb->cx;
365         cy_save = tb->cy;
366 }