OSDN Git Service

Merge pull request #765 from sikabane-works/release/3.0.0Alpha17
[hengbandforosx/hengbandosx.git] / src / birth / birth-select-realm.cpp
1 #include "birth/birth-select-realm.h"
2 #include "birth/birth-explanations-table.h"
3 #include "birth/birth-util.h"
4 #include "core/asking-player.h"
5 #include "io/input-key-acceptor.h"
6 #include "mind/mind-elementalist.h"
7 #include "player/player-realm.h"
8 #include "term/screen-processor.h"
9 #include "term/term-color-types.h"
10 #include "util/buffer-shaper.h"
11 #include "util/int-char-converter.h"
12
13 static const byte REALM_SELECT_CANCEL = 255;
14
15 typedef struct birth_realm_type {
16     int cs;
17     int n;
18     char p2;
19     char sym[VALID_REALM];
20     char buf[80];
21     int picks[VALID_REALM];
22     char cur[80];
23     int k;
24     int os;
25 } birth_realm_type;
26
27 static byte count_realm_selection(const u32b choices, int *count)
28 {
29     byte auto_select = REALM_NONE;
30     if (choices & CH_LIFE) {
31         (*count)++;
32         auto_select = REALM_LIFE;
33     }
34
35     if (choices & CH_SORCERY) {
36         (*count)++;
37         auto_select = REALM_SORCERY;
38     }
39
40     if (choices & CH_NATURE) {
41         (*count)++;
42         auto_select = REALM_NATURE;
43     }
44
45     if (choices & CH_CHAOS) {
46         (*count)++;
47         auto_select = REALM_CHAOS;
48     }
49
50     if (choices & CH_DEATH) {
51         (*count)++;
52         auto_select = REALM_DEATH;
53     }
54
55     if (choices & CH_TRUMP) {
56         (*count)++;
57         auto_select = REALM_TRUMP;
58     }
59
60     if (choices & CH_ARCANE) {
61         (*count)++;
62         auto_select = REALM_ARCANE;
63     }
64
65     if (choices & CH_ENCHANT) {
66         (*count)++;
67         auto_select = REALM_CRAFT;
68     }
69
70     if (choices & CH_DAEMON) {
71         (*count)++;
72         auto_select = REALM_DAEMON;
73     }
74
75     if (choices & CH_CRUSADE) {
76         (*count)++;
77         auto_select = REALM_CRUSADE;
78     }
79
80     if (choices & CH_MUSIC) {
81         (*count)++;
82         auto_select = REALM_MUSIC;
83     }
84
85     if (choices & CH_HISSATSU) {
86         (*count)++;
87         auto_select = REALM_HISSATSU;
88     }
89
90     if (choices & CH_HEX) {
91         (*count)++;
92         auto_select = REALM_HEX;
93     }
94
95     return auto_select;
96 }
97
98 static birth_realm_type *initialize_birth_realm_type(birth_realm_type *birth_realm_ptr)
99 {
100     birth_realm_ptr->cs = 0;
101     birth_realm_ptr->n = 0;
102     birth_realm_ptr->p2 = ')';
103     for (int i = 0; i < VALID_REALM; i++)
104         birth_realm_ptr->picks[i] = 0;
105
106     birth_realm_ptr->k = -1;
107     return birth_realm_ptr;
108 }
109
110 static void impose_first_realm(const player_type *creature_ptr, u32b *choices)
111 {
112     if (creature_ptr->realm2 == REALM_SELECT_CANCEL)
113         return;
114
115     if (creature_ptr->pclass != CLASS_PRIEST)
116         return;
117
118     if (is_good_realm(creature_ptr->realm1)) {
119         *choices &= ~(CH_DEATH | CH_DAEMON);
120     } else {
121         *choices &= ~(CH_LIFE | CH_CRUSADE);
122     }
123 }
124
125 static void analyze_realms(const player_type *creature_ptr, const u32b choices, birth_realm_type *birth_realm_ptr)
126 {
127     for (int i = 0; i < 32; i++) {
128         if ((choices & (1UL << i)) == 0)
129             continue;
130
131         if (creature_ptr->realm1 == i + 1) {
132             if (creature_ptr->realm2 == REALM_SELECT_CANCEL)
133                 birth_realm_ptr->cs = birth_realm_ptr->n;
134             else
135                 continue;
136         }
137
138         if (creature_ptr->realm2 == i + 1)
139             birth_realm_ptr->cs = birth_realm_ptr->n;
140
141         birth_realm_ptr->sym[birth_realm_ptr->n] = I2A(birth_realm_ptr->n);
142
143         sprintf(birth_realm_ptr->buf, "%c%c %s", birth_realm_ptr->sym[birth_realm_ptr->n], birth_realm_ptr->p2, realm_names[i + 1]);
144         put_str(birth_realm_ptr->buf, 12 + (birth_realm_ptr->n / 5), 2 + 15 * (birth_realm_ptr->n % 5));
145         birth_realm_ptr->picks[birth_realm_ptr->n++] = i + 1;
146     }
147 }
148
149 static void move_birth_realm_cursor(birth_realm_type *birth_realm_ptr)
150 {
151     if (birth_realm_ptr->cs == birth_realm_ptr->os)
152         return;
153
154     c_put_str(TERM_WHITE, birth_realm_ptr->cur, 12 + (birth_realm_ptr->os / 5), 2 + 15 * (birth_realm_ptr->os % 5));
155
156     if (birth_realm_ptr->cs == birth_realm_ptr->n) {
157         sprintf(birth_realm_ptr->cur, "%c%c %s", '*', birth_realm_ptr->p2, _("ランダム", "Random"));
158     } else {
159         sprintf(birth_realm_ptr->cur, "%c%c %s", birth_realm_ptr->sym[birth_realm_ptr->cs], birth_realm_ptr->p2,
160             realm_names[birth_realm_ptr->picks[birth_realm_ptr->cs]]);
161         sprintf(birth_realm_ptr->buf, "%s", realm_names[birth_realm_ptr->picks[birth_realm_ptr->cs]]);
162         c_put_str(TERM_L_BLUE, birth_realm_ptr->buf, 3, 40);
163         prt(_("の特徴", ": Characteristic"), 3, 40 + strlen(birth_realm_ptr->buf));
164         prt(realm_subinfo[technic2magic(birth_realm_ptr->picks[birth_realm_ptr->cs]) - 1], 4, 40);
165     }
166
167     c_put_str(TERM_YELLOW, birth_realm_ptr->cur, 12 + (birth_realm_ptr->cs / 5), 2 + 15 * (birth_realm_ptr->cs % 5));
168     birth_realm_ptr->os = birth_realm_ptr->cs;
169 }
170
171 static void interpret_realm_select_key(birth_realm_type *birth_realm_ptr, char c)
172 {
173     if (c == 'Q')
174         birth_quit();
175
176     if (c == '8') {
177         if (birth_realm_ptr->cs >= 5)
178             birth_realm_ptr->cs -= 5;
179     }
180
181     if (c == '4') {
182         if (birth_realm_ptr->cs > 0)
183             birth_realm_ptr->cs--;
184     }
185
186     if (c == '6') {
187         if (birth_realm_ptr->cs < birth_realm_ptr->n)
188             birth_realm_ptr->cs++;
189     }
190
191     if (c == '2') {
192         if ((birth_realm_ptr->cs + 5) <= birth_realm_ptr->n)
193             birth_realm_ptr->cs += 5;
194     }
195 }
196
197 static bool get_a_realm(player_type *creature_ptr, birth_realm_type *birth_realm_ptr)
198 {
199     birth_realm_ptr->os = birth_realm_ptr->n;
200     while (TRUE) {
201         move_birth_realm_cursor(birth_realm_ptr);
202         if (birth_realm_ptr->k >= 0)
203             break;
204
205         sprintf(birth_realm_ptr->buf, _("領域を選んで下さい(%c-%c) ('='初期オプション設定): ", "Choose a realm (%c-%c) ('=' for options): "),
206             birth_realm_ptr->sym[0], birth_realm_ptr->sym[birth_realm_ptr->n - 1]);
207
208         put_str(birth_realm_ptr->buf, 10, 10);
209         char c = inkey();
210         interpret_realm_select_key(birth_realm_ptr, c);
211         if (c == 'S')
212             return TRUE;
213
214         if (c == ' ' || c == '\r' || c == '\n') {
215             if (birth_realm_ptr->cs == birth_realm_ptr->n) {
216                 birth_realm_ptr->k = randint0(birth_realm_ptr->n);
217                 break;
218             } else {
219                 birth_realm_ptr->k = birth_realm_ptr->cs;
220                 break;
221             }
222         }
223
224         if (c == '*') {
225             birth_realm_ptr->k = randint0(birth_realm_ptr->n);
226             break;
227         }
228
229         birth_realm_ptr->k = (islower(c) ? A2I(c) : -1);
230         if ((birth_realm_ptr->k >= 0) && (birth_realm_ptr->k < birth_realm_ptr->n)) {
231             birth_realm_ptr->cs = birth_realm_ptr->k;
232             continue;
233         }
234
235         birth_realm_ptr->k = (isupper(c) ? (26 + c - 'A') : -1);
236         if ((birth_realm_ptr->k >= 26) && (birth_realm_ptr->k < birth_realm_ptr->n)) {
237             birth_realm_ptr->cs = birth_realm_ptr->k;
238             continue;
239         } else
240             birth_realm_ptr->k = -1;
241
242         birth_help_option(creature_ptr, c, BK_REALM);
243     }
244
245     return FALSE;
246 }
247
248 /*!
249  * @brief プレイヤーの魔法領域を選択する / Choose from one of the available magical realms
250  * @param choices 選択可能な魔法領域のビット配列
251  * @param count 選択可能な魔法領域を返すポインタ群。
252  * @return 選択した魔法領域のID
253  * @details 領域数が0 (戦士等)or 1 (観光客等)なら自動での値を返す
254  */
255 static byte select_realm(player_type *creature_ptr, u32b choices, int *count)
256 {
257     byte auto_select = count_realm_selection(choices, count);
258     clear_from(10);
259     if ((*count) < 2)
260         return auto_select;
261
262     impose_first_realm(creature_ptr, &choices);
263     put_str(_("注意:魔法の領域の選択によりあなたが習得する呪文のタイプが決まります。", "Note: The realm of magic will determine which spells you can learn."),
264         23, 5);
265
266     birth_realm_type tmp_birth_realm;
267     birth_realm_type *birth_realm_ptr = initialize_birth_realm_type(&tmp_birth_realm);
268     analyze_realms(creature_ptr, choices, birth_realm_ptr);
269     sprintf(birth_realm_ptr->cur, "%c%c %s", '*', birth_realm_ptr->p2, _("ランダム", "Random"));
270     if (get_a_realm(creature_ptr, birth_realm_ptr))
271         return REALM_SELECT_CANCEL;
272
273     clear_from(10);
274     return (byte)(birth_realm_ptr->picks[birth_realm_ptr->k]);
275 }
276
277 static void cleanup_realm_selection_window(void)
278 {
279     clear_from(10);
280     put_str("                                   ", 3, 40);
281     put_str("                                   ", 4, 40);
282     put_str("                                   ", 5, 40);
283 }
284
285 /*!
286  * @brief 選んだ魔法領域で本当に良いか問い合わせる
287  * @param count 魔法領域の数
288  * @return 選んだ魔法領域で良ければTRUE、再選択ならばFALSE
289  */
290 static bool check_realm_selection(player_type *creature_ptr, int count)
291 {
292     if (count < 2) {
293         prt(_("何かキーを押してください", "Hit any key."), 0, 0);
294         (void)inkey();
295         prt("", 0, 0);
296         return TRUE;
297     } else if (get_check_strict(creature_ptr, _("よろしいですか?", "Are you sure? "), CHECK_DEFAULT_Y))
298         return TRUE;
299
300     return FALSE;
301 }
302
303 /*!
304  * @brief 選択した魔法領域の解説を表示する / Choose the magical realms
305  * @return ユーザが魔法領域の確定を選んだらTRUEを返す。
306  */
307 bool get_player_realms(player_type *creature_ptr)
308 {
309     /* Clean up infomation of modifications */
310     put_str("                                   ", 3, 40);
311     put_str("                                   ", 4, 40);
312     put_str("                                   ", 5, 40);
313     put_str("                                   ", 6, 40);
314
315     /* Select the first realm */
316     creature_ptr->realm1 = REALM_NONE;
317     creature_ptr->realm2 = REALM_NONE;
318
319     if (creature_ptr->pclass == CLASS_ELEMENTALIST) {
320         creature_ptr->element = select_element_realm(creature_ptr);
321         if (creature_ptr->element == REALM_SELECT_CANCEL)
322             return FALSE;
323
324         put_str(_("魔法        :", "Magic       :"), 6, 1);
325         c_put_str(TERM_L_BLUE, get_element_title(creature_ptr->element), 6, 15);
326         return TRUE;
327     }
328
329     while (TRUE) {
330         char temp[80 * 10];
331         int count = 0;
332         creature_ptr->realm1 = select_realm(creature_ptr, realm_choices1[creature_ptr->pclass], &count);
333         if (creature_ptr->realm1 == REALM_SELECT_CANCEL)
334             return FALSE;
335         if (!creature_ptr->realm1)
336             break;
337
338         cleanup_realm_selection_window();
339         shape_buffer(realm_explanations[technic2magic(creature_ptr->realm1) - 1], 74, temp, sizeof(temp));
340         concptr t = temp;
341         for (int i = 0; i < 10; i++) {
342             if (t[0] == 0)
343                 break;
344             else {
345                 prt(t, 12 + i, 3);
346                 t += strlen(t) + 1;
347             }
348         }
349
350         if (check_realm_selection(creature_ptr, count))
351             break;
352     }
353
354     /* Select the second realm */
355     creature_ptr->realm2 = REALM_NONE;
356     if (creature_ptr->realm1 == REALM_NONE)
357         return TRUE;
358
359     /* Print the realm */
360     put_str(_("魔法        :", "Magic       :"), 6, 1);
361     c_put_str(TERM_L_BLUE, realm_names[creature_ptr->realm1], 6, 15);
362
363     /* Select the second realm */
364     while (TRUE) {
365         char temp[80 * 8];
366         int count = 0;
367         creature_ptr->realm2 = select_realm(creature_ptr, realm_choices2[creature_ptr->pclass], &count);
368
369         if (creature_ptr->realm2 == REALM_SELECT_CANCEL)
370             return FALSE;
371         if (!creature_ptr->realm2)
372             break;
373
374         cleanup_realm_selection_window();
375         shape_buffer(realm_explanations[technic2magic(creature_ptr->realm2) - 1], 74, temp, sizeof(temp));
376         concptr t = temp;
377         for (int i = 0; i < A_MAX; i++) {
378             if (t[0] == 0)
379                 break;
380             else {
381                 prt(t, 12 + i, 3);
382                 t += strlen(t) + 1;
383             }
384         }
385
386         if (check_realm_selection(creature_ptr, count))
387             break;
388     }
389
390     if (creature_ptr->realm2) {
391         /* Print the realm */
392         c_put_str(TERM_L_BLUE, format("%s, %s", realm_names[creature_ptr->realm1], realm_names[creature_ptr->realm2]), 6, 15);
393     }
394
395     return TRUE;
396 }