OSDN Git Service

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