OSDN Git Service

[Refactor] #39962 display_player_various() からstrengthen_basedam() を分離 / Separated...
[hengband/hengband.git] / src / view / status-first-page.c
1 /*!
2  * @file status-first-page.c
3  * @brief \83L\83\83\83\89\8aî\96{\8fî\95ñ\8by\82Ñ\8bZ\94\\92l\82Ì\95\\8e¦
4  * @date 2020/02/23
5  * @author Hourier
6  */
7
8 #include "angband.h"
9 #include "status-first-page.h"
10 #include "artifact.h"
11 #include "combat/melee.h"
12 #include "combat/shoot.h"
13 #include "object-hook.h"
14 #include "objectkind.h"
15
16 static TERM_COLOR likert_color = TERM_WHITE;
17
18 /*!
19  * @brief 
20  * @param creature_ptr \83v\83\8c\81[\83\84\81[\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
21  * @param o_ptr \91\95\94õ\92\86\82Ì\8b|\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
22  * @param shots \8eË\8c\82\89ñ\90\94
23  * @param shot_frac \8eË\8c\82\91¬\93x
24  * @return \82È\82µ
25  */
26 static void calc_shot_params(player_type *creature_ptr, object_type *o_ptr, int *shots, int *shot_frac)
27 {
28         if (o_ptr->k_idx == 0) return;
29
30         ENERGY energy_fire = bow_energy(o_ptr->sval);
31         *shots = creature_ptr->num_fire * 100;
32         *shot_frac = ((*shots) * 100 / energy_fire) % 100;
33         *shots = (*shots) / energy_fire;
34         if (o_ptr->name1 != ART_CRIMSON) return;
35
36         *shots = 1;
37         *shot_frac = 0;
38         if (creature_ptr->pclass != CLASS_ARCHER) return;
39
40         if (creature_ptr->lev >= 10) (*shots)++;
41         if (creature_ptr->lev >= 30) (*shots)++;
42         if (creature_ptr->lev >= 45) (*shots)++;
43 }
44
45
46 /*!
47  * @brief \95\90\8aí\91\95\94õ\82É\90§\8cÀ\82Ì\82 \82é\83N\83\89\83X\82Å\81A\92¼\90Ú\8dU\8c\82\82Ì\83_\83\81\81[\83W\82ð\8cv\8eZ\82·\82é
48  * @param creature_ptr \83v\83\8c\81[\83\84\81[\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
49  * @param hand \8eè (\97\98\82«\8eè\82ª0\81A\94½\91Î\82Ì\8eè\82ª1\81c\82Ì\82Í\82¸)
50  * @param damage \92¼\90Ú\8dU\8c\82\82Ì\83_\83\81\81[\83W
51  * @param basedam \91f\8eè\82É\82¨\82¯\82é\92¼\90Ú\8dU\8c\82\82Ì\83_\83\81\81[\83W
52  * @param o_ptr \91\95\94õ\92\86\82Ì\95\90\8aí\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
53  * @return \97\98\82«\8eè\82È\82çTRUE\81A\94½\91Î\82Ì\8eè\82È\82çFALSE
54  */
55 static bool calc_weapon_damage_limit(player_type *creature_ptr, int hand, int *damage, int *basedam, object_type *o_ptr)
56 {
57         PLAYER_LEVEL level = creature_ptr->lev;
58         if (hand > 0)
59         {
60                 damage[hand] = 0;
61                 return FALSE;
62         }
63
64         if (creature_ptr->pclass == CLASS_FORCETRAINER) level = MAX(1, level - 3);
65         if (creature_ptr->special_defense & KAMAE_BYAKKO)
66                 *basedam = monk_ave_damage[level][1];
67         else if (creature_ptr->special_defense & (KAMAE_GENBU | KAMAE_SUZAKU))
68                 *basedam = monk_ave_damage[level][2];
69         else
70                 *basedam = monk_ave_damage[level][0];
71
72         damage[hand] += *basedam;
73         if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_POISON_NEEDLE)) damage[hand] = 1;
74         if (damage[hand] < 0) damage[hand] = 0;
75
76         return TRUE;
77 }
78
79
80 /*!
81  * @brief \95Ð\8eè\82 \82½\82è\82Ì\83_\83\81\81[\83W\97Ê\82ð\8cv\8eZ\82·\82é
82  * @param o_ptr \91\95\94õ\92\86\82Ì\95\90\8aí\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
83  * @param hand \8eè
84  * @param damage \92¼\90Ú\8dU\8c\82\82Ì\83_\83\81\81[\83W
85  * @param basedam \91f\8eè\82É\82¨\82¯\82é\92¼\90Ú\8dU\8c\82\82Ì\83_\83\81\81[\83W
86  * @return \91f\8eè\82È\82çFALSE\81A\95\90\8aí\82ð\8e\9d\82Á\82Ä\82¢\82ê\82ÎTRUE
87  */
88 static bool calc_weapon_one_hand(object_type *o_ptr, int hand, int *damage, int *basedam)
89 {
90         if (o_ptr->k_idx == 0) return FALSE;
91
92         *basedam = 0;
93         damage[hand] += *basedam;
94         if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_POISON_NEEDLE))
95                 damage[hand] = 1;
96
97         if (damage[hand] < 0)
98                 damage[hand] = 0;
99
100         return TRUE;
101 }
102
103
104 /*!
105  * @brief \83\94\83H\81[\83p\83\8b\95\90\8aí\93\99\82É\82æ\82é\83_\83\81\81[\83W\8b­\89»
106  * @param creature_ptr \83v\83\8c\81[\83\84\81[\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
107  * @param o_ptr \91\95\94õ\92\86\82Ì\95\90\8aí\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
108  * @param basedam \91f\8eè\82É\82¨\82¯\82é\92¼\90Ú\8dU\8c\82\82Ì\83_\83\81\81[\83W
109  * @param flgs \83I\83u\83W\83F\83N\83g\83t\83\89\83O\8cQ
110  * @return \8b­\89»\8cã\82Ì\91f\8eè\83_\83\81\81[\83W
111  */
112 static int strengthen_basedam(player_type *creature_ptr, object_type *o_ptr, int basedam, BIT_FLAGS *flgs)
113 {
114         if (OBJECT_IS_FULL_KNOWN(o_ptr) && ((o_ptr->name1 == ART_VORPAL_BLADE) || (o_ptr->name1 == ART_CHAINSWORD)))
115         {
116                 /* vorpal blade */
117                 basedam *= 5;
118                 basedam /= 3;
119         }
120         else if (have_flag(flgs, TR_VORPAL))
121         {
122                 /* vorpal flag only */
123                 basedam *= 11;
124                 basedam /= 9;
125         }
126
127         // \97\9d\97Í
128         bool is_force = creature_ptr->pclass != CLASS_SAMURAI;
129         is_force &= have_flag(flgs, TR_FORCE_WEAPON);
130         is_force &= creature_ptr->csp > (o_ptr->dd * o_ptr->ds / 5);
131         if (is_force) basedam = basedam * 7 / 2;
132
133         return basedam;
134 }
135
136
137 /*!
138  * @brief \8bZ\94\\83\89\83\93\83N\82Ì\95\\8e¦\8aî\8f\80\82ð\92è\82ß\82é
139  * Returns a "rating" of x depending on y
140  * @param x \8bZ\94\\92l
141  * @param y \8bZ\94\\92l\82É\91Î\82·\82é\83\89\83\93\83N\8aî\8f\80\94ä
142  * @return \82È\82µ
143  */
144 static concptr likert(int x, int y)
145 {
146         static char dummy[20] = "", dummy2[20] = "";
147         memset(dummy, 0, strlen(dummy));
148         memset(dummy2, 0, strlen(dummy2));
149         if (y <= 0) y = 1;
150
151         if (show_actual_value)
152                 sprintf(dummy, "%3d-", x);
153
154         if (x < 0)
155         {
156                 likert_color = TERM_L_DARK;
157                 strcat(dummy, _("\8dÅ\92á", "Very Bad"));
158                 return dummy;
159         }
160
161         switch ((x / y))
162         {
163         case 0:
164         case 1:
165         {
166                 likert_color = TERM_RED;
167                 strcat(dummy, _("\88«\82¢", "Bad"));
168                 break;
169
170         }
171         case 2:
172         {
173                 likert_color = TERM_L_RED;
174                 strcat(dummy, _("\97ò\82é", "Poor"));
175                 break;
176         }
177         case 3:
178         case 4:
179         {
180                 likert_color = TERM_ORANGE;
181                 strcat(dummy, _("\95\81\92Ê", "Fair"));
182                 break;
183         }
184         case 5:
185         {
186                 likert_color = TERM_YELLOW;
187                 strcat(dummy, _("\97Ç\82¢", "Good"));
188                 break;
189         }
190         case 6:
191         {
192                 likert_color = TERM_YELLOW;
193                 strcat(dummy, _("\91å\95Ï\97Ç\82¢", "Very Good"));
194                 break;
195         }
196         case 7:
197         case 8:
198         {
199                 likert_color = TERM_L_GREEN;
200                 strcat(dummy, _("\91ì\89z", "Excellent"));
201                 break;
202         }
203         case 9:
204         case 10:
205         case 11:
206         case 12:
207         case 13:
208         {
209                 likert_color = TERM_GREEN;
210                 strcat(dummy, _("\92´\89z", "Superb"));
211                 break;
212         }
213         case 14:
214         case 15:
215         case 16:
216         case 17:
217         {
218                 likert_color = TERM_BLUE;
219                 strcat(dummy, _("\89p\97Y\93I", "Heroic"));
220                 break;
221         }
222         default:
223         {
224                 likert_color = TERM_VIOLET;
225                 sprintf(dummy2, _("\93`\90à\93I[%d]", "Legendary[%d]"), (int)((((x / y) - 17) * 5) / 2));
226                 strcat(dummy, dummy2);
227                 break;
228         }
229         }
230
231         return dummy;
232 }
233
234
235 /*!
236  * @brief \83L\83\83\83\89\8aî\96{\8fî\95ñ\8by\82Ñ\8bZ\94\\92l\82ð\83\81\83C\83\93\83E\83B\83\93\83h\83E\82É\95\\8e¦\82·\82é
237  * @param creature_ptr \83v\83\8c\81[\83\84\81[\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
238  * @param xthb \95\90\8aí\93\99\82ð\8aÜ\82ß\82½\8dÅ\8fI\96½\92\86\97¦
239  * @param damage \91Å\8c\82\8fC\90³
240  * @param shots \8eË\8c\82\89ñ\90\94
241  * @param shot_frac \8eË\8c\82\91¬\93x
242  * @param display_player_one_line 1\8ds\95\\8e¦\97p\82Ì\83R\81[\83\8b\83o\83b\83N\8aÖ\90\94
243  * @return \82È\82µ
244  */
245 static void display_first_page(player_type *creature_ptr, int xthb, int *damage, int shots, int shot_frac, void(*display_player_one_line)(int, concptr, TERM_COLOR))
246 {
247         int xthn = creature_ptr->skill_thn + (creature_ptr->to_h_m * BTH_PLUS_ADJ);
248
249         int muta_att = 0;
250         if (creature_ptr->muta2 & MUT2_HORNS) muta_att++;
251         if (creature_ptr->muta2 & MUT2_SCOR_TAIL) muta_att++;
252         if (creature_ptr->muta2 & MUT2_BEAK) muta_att++;
253         if (creature_ptr->muta2 & MUT2_TRUNK) muta_att++;
254         if (creature_ptr->muta2 & MUT2_TENTACLES) muta_att++;
255
256         int blows1 = creature_ptr->migite ? creature_ptr->num_blow[0] : 0;
257         int blows2 = creature_ptr->hidarite ? creature_ptr->num_blow[1] : 0;
258         int xdis = creature_ptr->skill_dis;
259         int xdev = creature_ptr->skill_dev;
260         int xsav = creature_ptr->skill_sav;
261         int xstl = creature_ptr->skill_stl;
262         int     xsrh = creature_ptr->skill_srh;
263         int     xfos = creature_ptr->skill_fos;
264         int xdig = creature_ptr->skill_dig;
265
266         concptr desc = likert(xthn, 12);
267         (*display_player_one_line)(ENTRY_SKILL_FIGHT, desc, likert_color);
268
269         desc = likert(xthb, 12);
270         (*display_player_one_line)(ENTRY_SKILL_SHOOT, desc, likert_color);
271
272         desc = likert(xsav, 7);
273         (*display_player_one_line)(ENTRY_SKILL_SAVING, desc, likert_color);
274
275         desc = likert((xstl > 0) ? xstl : -1, 1);
276         (*display_player_one_line)(ENTRY_SKILL_STEALTH, desc, likert_color);
277
278         desc = likert(xfos, 6);
279         (*display_player_one_line)(ENTRY_SKILL_PERCEP, desc, likert_color);
280
281         desc = likert(xsrh, 6);
282         (*display_player_one_line)(ENTRY_SKILL_SEARCH, desc, likert_color);
283
284         desc = likert(xdis, 8);
285         (*display_player_one_line)(ENTRY_SKILL_DISARM, desc, likert_color);
286
287         desc = likert(xdev, 6);
288         (*display_player_one_line)(ENTRY_SKILL_DEVICE, desc, likert_color);
289
290         desc = likert(xdev, 6);
291         (*display_player_one_line)(ENTRY_SKILL_DEVICE, desc, likert_color);
292
293         desc = likert(xdig, 4);
294         (*display_player_one_line)(ENTRY_SKILL_DIG, desc, likert_color);
295
296         if (!muta_att)
297                 (*display_player_one_line)(ENTRY_BLOWS, format("%d+%d", blows1, blows2), TERM_L_BLUE);
298         else
299                 (*display_player_one_line)(ENTRY_BLOWS, format("%d+%d+%d", blows1, blows2, muta_att), TERM_L_BLUE);
300
301         (*display_player_one_line)(ENTRY_SHOTS, format("%d.%02d", shots, shot_frac), TERM_L_BLUE);
302
303         if ((damage[0] + damage[1]) == 0)
304                 desc = "nil!";
305         else
306                 desc = format("%d+%d", blows1 * damage[0] / 100, blows2 * damage[1] / 100);
307
308         (*display_player_one_line)(ENTRY_AVG_DMG, desc, TERM_L_BLUE);
309         (*display_player_one_line)(ENTRY_INFRA, format("%d feet", creature_ptr->see_infra * 10), TERM_WHITE);
310 }
311
312
313 /*!
314  * @brief \83v\83\8c\83C\83\84\81[\83X\83e\81[\83^\83X\82Ì1\83y\81[\83W\96Ú\8ae\8eí\8fÚ\8d×\82ð\82Ü\82Æ\82ß\82Ä\95\\8e¦\82·\82é
315  * Prints ratings on certain abilities
316  * @param creature_ptr \83v\83\8c\81[\83\84\81[\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
317  * @param display_player_one_line 1\8ds\95\\8e¦\97p\82Ì\83R\81[\83\8b\83o\83b\83N\8aÖ\90\94
318  * @return \82È\82µ
319  * @details
320  * This code is "imitated" elsewhere to "dump" a character sheet.
321  */
322 void display_player_various(player_type *creature_ptr, void(*display_player_one_line)(int, concptr, TERM_COLOR))
323 {
324         object_type *o_ptr;
325         o_ptr = &creature_ptr->inventory_list[INVEN_BOW];
326         int tmp = creature_ptr->to_h_b + o_ptr->to_h;
327         int     xthb = creature_ptr->skill_thb + (tmp * BTH_PLUS_ADJ);
328         int     shots = 0;
329         int shot_frac = 0;
330         calc_shot_params(creature_ptr, o_ptr, &shots, &shot_frac);
331
332         int damage[2];
333         int to_h[2];
334         BIT_FLAGS flgs[TR_FLAG_SIZE];
335         for (int i = 0; i < 2; i++)
336         {
337                 int basedam;
338                 damage[i] = creature_ptr->dis_to_d[i] * 100;
339                 if (((creature_ptr->pclass == CLASS_MONK) || (creature_ptr->pclass == CLASS_FORCETRAINER)) && (empty_hands(creature_ptr, TRUE) & EMPTY_HAND_RARM))
340                 {
341                         if (!calc_weapon_damage_limit(creature_ptr, i, damage, &basedam, o_ptr))
342                                 break;
343
344                         continue;
345                 }
346
347                 o_ptr = &creature_ptr->inventory_list[INVEN_RARM + i];
348                 if (calc_weapon_one_hand(o_ptr, i, damage, &basedam)) continue;
349
350                 to_h[i] = 0;
351                 bool poison_needle = FALSE;
352                 if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_POISON_NEEDLE)) poison_needle = TRUE;
353                 if (object_is_known(o_ptr))
354                 {
355                         damage[i] += o_ptr->to_d * 100;
356                         to_h[i] += o_ptr->to_h;
357                 }
358
359                 basedam = ((o_ptr->dd + creature_ptr->to_dd[i]) * (o_ptr->ds + creature_ptr->to_ds[i] + 1)) * 50;
360                 object_flags_known(o_ptr, flgs);
361
362                 basedam = calc_expect_crit(creature_ptr, o_ptr->weight, to_h[i], basedam, creature_ptr->dis_to_h[i], poison_needle);
363                 basedam = strengthen_basedam(creature_ptr, o_ptr, basedam, flgs);
364                 damage[i] += basedam;
365                 if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_POISON_NEEDLE)) damage[i] = 1;
366                 if (damage[i] < 0) damage[i] = 0;
367         }
368
369         display_first_page(creature_ptr, xthb, damage, shots, shot_frac, display_player_one_line);
370 }