OSDN Git Service

[Refactor] #38997 get_realm_virtues() に player_type * 引数を追加.
[hengband/hengband.git] / src / avatar.c
1 /*!
2     @file avatar.c
3     @brief ウルティマ4を参考にした徳のシステムの実装 / Enable an Ultima IV style "avatar" game where you try to achieve perfection in various virtues.
4     @date 2013/12/23
5     @author
6     Topi Ylinen 1998\n
7     f1toyl@uta.fi\n
8     topi.ylinen@noodi.fi\n
9     \n
10     Copyright (c) 1989 James E. Wilson, Christopher J. Stuart
11     This software may be copied and distributed for educational, research, and
12     not for profit purposes provided that this copyright and statement are
13     included in all such copies.
14 */
15
16 #include "angband.h"
17 #include "avatar.h"
18 #include "realm.h"
19 #include "player-race.h"
20 #include "player-class.h"
21
22 /*!
23  * 徳の名称 / The names of the virtues
24  */
25 concptr virtue[MAX_VIRTUE] =
26 {
27         _("情", "Compassion"),
28         _("誉", "Honour"),
29         _("正", "Justice"),
30         _("犠", "Sacrifice"),
31         _("識", "Knowledge"),
32         _("誠", "Faith"),
33         _("啓", "Enlightenment"),
34         _("秘", "Mysticism"),
35         _("運", "Chance"),
36         _("然", "Nature"),
37         _("調", "Harmony"),
38         _("活", "Vitality"),
39         _("死", "Unlife"),
40         _("忍", "Patience"),
41         _("節", "Temperance"),
42         _("勤", "Diligence"),
43         _("勇", "Valour"),
44         _("個", "Individualism"),
45 };
46
47 /*!
48  * @brief 該当の徳がプレイヤーに指定されているか否かに応じつつ、大小を比較する。
49  * @details 徳がない場合は値0として比較する。
50  * @param type 比較したい徳のID
51  * @param num 比較基準値
52  * @param tekitou VIRTUE_LARGE = 基準値より大きいか / VIRTUE_SMALL = 基準値より小さいか
53  * @return 比較の真偽値を返す
54  * @todo 引数名を直しておく
55  */
56 bool compare_virtue(player_type *creature_ptr, int type, int num, int tekitou)
57 {
58         int vir;
59         if (virtue_number(creature_ptr, type))
60                 vir = creature_ptr->virtues[virtue_number(creature_ptr, type) - 1];
61         else
62                 vir = 0;
63
64         switch (tekitou)
65         {
66         case VIRTUE_LARGE:
67                 if (vir > num) return TRUE;
68                 else return FALSE;
69         case VIRTUE_SMALL:
70                 if (vir < num) return TRUE;
71                 else return FALSE;
72         }
73
74         return FALSE;
75 }
76
77 /*!
78  * @brief プレイヤーの指定の徳が何番目のスロットに登録されているかを返す。 / Aux function
79  * @param type 確認したい徳のID
80  * @return スロットがあるならばスロットのID(0~7)+1、ない場合は0を返す。
81  */
82 int virtue_number(player_type *creature_ptr, int type)
83 {
84         int i;
85
86         /* Search */
87         for (i = 0; i < 8; i++)
88         {
89                 if (creature_ptr->vir_types[i] == type) return i + 1;
90         }
91
92         /* No match */
93         return 0;
94 }
95
96 /*!
97  * @brief プレイヤーの職業や種族に依存しないランダムな徳を取得する / Aux function
98  * @param which 確認したい徳のID
99  * @return なし
100  */
101 static void get_random_virtue(int which)
102 {
103         int type = 0;
104
105         /* Randomly choose a type */
106         while (!(type) || virtue_number(p_ptr, type))
107         {
108                 switch (randint1(29))
109                 {
110                 case 1: case 2: case 3:
111                         type = V_SACRIFICE;
112                         break;
113                 case 4: case 5: case 6:
114                         type = V_COMPASSION;
115                         break;
116                 case 7: case 8: case 9: case 10: case 11: case 12:
117                         type = V_VALOUR;
118                         break;
119                 case 13: case 14: case 15: case 16: case 17:
120                         type = V_HONOUR;
121                         break;
122                 case 18: case 19: case 20: case 21:
123                         type = V_JUSTICE;
124                         break;
125                 case 22: case 23:
126                         type = V_TEMPERANCE;
127                         break;
128                 case 24: case 25:
129                         type = V_HARMONY;
130                         break;
131                 case 26: case 27: case 28:
132                         type = V_PATIENCE;
133                         break;
134                 default:
135                         type = V_DILIGENCE;
136                         break;
137                 }
138         }
139
140         /* Chosen */
141         p_ptr->vir_types[which] = (s16b)type;
142 }
143
144 /*!
145  * @brief プレイヤーの選んだ魔法領域に応じて対応する徳を返す。
146  * @param realm 魔法領域のID
147  * @return 対応する徳のID
148  */
149 static VIRTUES_IDX get_realm_virtues(player_type *creature_ptr, REALM_IDX realm)
150 {
151         switch (realm)
152         {
153         case REALM_LIFE:
154                 if (virtue_number(creature_ptr, V_VITALITY)) return V_TEMPERANCE;
155                 else return V_VITALITY;
156         case REALM_SORCERY:
157                 if (virtue_number(creature_ptr, V_KNOWLEDGE)) return V_ENCHANT;
158                 else return V_KNOWLEDGE;
159         case REALM_NATURE:
160                 if (virtue_number(creature_ptr, V_NATURE)) return V_HARMONY;
161                 else return V_NATURE;
162         case REALM_CHAOS:
163                 if (virtue_number(creature_ptr, V_CHANCE)) return V_INDIVIDUALISM;
164                 else return V_CHANCE;
165         case REALM_DEATH:
166                 return V_UNLIFE;
167         case REALM_TRUMP:
168                 return V_KNOWLEDGE;
169         case REALM_ARCANE:
170                 return 0;
171         case REALM_CRAFT:
172                 if (virtue_number(creature_ptr, V_ENCHANT)) return V_INDIVIDUALISM;
173                 else return V_ENCHANT;
174         case REALM_DAEMON:
175                 if (virtue_number(creature_ptr, V_JUSTICE)) return V_FAITH;
176                 else return V_JUSTICE;
177         case REALM_CRUSADE:
178                 if (virtue_number(creature_ptr, V_JUSTICE)) return V_HONOUR;
179                 else return V_JUSTICE;
180         case REALM_HEX:
181                 if (virtue_number(creature_ptr, V_COMPASSION)) return V_JUSTICE;
182                 else return V_COMPASSION;
183         };
184
185         return 0;
186 }
187
188
189 /*!
190  * @brief 作成中のプレイヤーキャラクターに徳8種類を与える。 / Select virtues & reset values for a new character
191  * @details 職業に応じて1~4種が固定、種族に応じて1種類が与えられ、後は重複なくランダムに選択される。
192  * @return なし
193  */
194 void get_virtues(player_type *creature_ptr)
195 {
196         int i = 0, j = 0;
197         s16b tmp_vir;
198
199         /* Reset */
200         for (i = 0; i < 8; i++)
201         {
202                 creature_ptr->virtues[i] = 0;
203                 creature_ptr->vir_types[i] = 0;
204         }
205
206         i = 0;
207
208         /* Get pre-defined types */
209         /* 1 or more virtues based on class */
210         switch (creature_ptr->pclass)
211         {
212         case CLASS_WARRIOR:
213         case CLASS_SAMURAI:
214                 creature_ptr->vir_types[i++] = V_VALOUR;
215                 creature_ptr->vir_types[i++] = V_HONOUR;
216                 break;
217         case CLASS_MAGE:
218                 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
219                 creature_ptr->vir_types[i++] = V_ENCHANT;
220                 break;
221         case CLASS_PRIEST:
222                 creature_ptr->vir_types[i++] = V_FAITH;
223                 creature_ptr->vir_types[i++] = V_TEMPERANCE;
224                 break;
225         case CLASS_ROGUE:
226         case CLASS_SNIPER:
227                 creature_ptr->vir_types[i++] = V_HONOUR;
228                 break;
229         case CLASS_RANGER:
230         case CLASS_ARCHER:
231                 creature_ptr->vir_types[i++] = V_NATURE;
232                 creature_ptr->vir_types[i++] = V_TEMPERANCE;
233                 break;
234         case CLASS_PALADIN:
235                 creature_ptr->vir_types[i++] = V_JUSTICE;
236                 creature_ptr->vir_types[i++] = V_VALOUR;
237                 creature_ptr->vir_types[i++] = V_HONOUR;
238                 creature_ptr->vir_types[i++] = V_FAITH;
239                 break;
240         case CLASS_WARRIOR_MAGE:
241         case CLASS_RED_MAGE:
242                 creature_ptr->vir_types[i++] = V_ENCHANT;
243                 creature_ptr->vir_types[i++] = V_VALOUR;
244                 break;
245         case CLASS_CHAOS_WARRIOR:
246                 creature_ptr->vir_types[i++] = V_CHANCE;
247                 creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
248                 break;
249         case CLASS_MONK:
250         case CLASS_FORCETRAINER:
251                 creature_ptr->vir_types[i++] = V_FAITH;
252                 creature_ptr->vir_types[i++] = V_HARMONY;
253                 creature_ptr->vir_types[i++] = V_TEMPERANCE;
254                 creature_ptr->vir_types[i++] = V_PATIENCE;
255                 break;
256         case CLASS_MINDCRAFTER:
257         case CLASS_MIRROR_MASTER:
258                 creature_ptr->vir_types[i++] = V_HARMONY;
259                 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
260                 creature_ptr->vir_types[i++] = V_PATIENCE;
261                 break;
262         case CLASS_HIGH_MAGE:
263         case CLASS_SORCERER:
264                 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
265                 creature_ptr->vir_types[i++] = V_ENCHANT;
266                 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
267                 break;
268         case CLASS_TOURIST:
269                 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
270                 creature_ptr->vir_types[i++] = V_CHANCE;
271                 break;
272         case CLASS_IMITATOR:
273                 creature_ptr->vir_types[i++] = V_CHANCE;
274                 break;
275         case CLASS_BLUE_MAGE:
276                 creature_ptr->vir_types[i++] = V_CHANCE;
277                 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
278                 break;
279         case CLASS_BEASTMASTER:
280                 creature_ptr->vir_types[i++] = V_NATURE;
281                 creature_ptr->vir_types[i++] = V_CHANCE;
282                 creature_ptr->vir_types[i++] = V_VITALITY;
283                 break;
284         case CLASS_MAGIC_EATER:
285                 creature_ptr->vir_types[i++] = V_ENCHANT;
286                 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
287                 break;
288         case CLASS_BARD:
289                 creature_ptr->vir_types[i++] = V_HARMONY;
290                 creature_ptr->vir_types[i++] = V_COMPASSION;
291                 break;
292         case CLASS_CAVALRY:
293                 creature_ptr->vir_types[i++] = V_VALOUR;
294                 creature_ptr->vir_types[i++] = V_HARMONY;
295                 break;
296         case CLASS_BERSERKER:
297                 creature_ptr->vir_types[i++] = V_VALOUR;
298                 creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
299                 break;
300         case CLASS_SMITH:
301                 creature_ptr->vir_types[i++] = V_HONOUR;
302                 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
303                 break;
304         case CLASS_NINJA:
305                 creature_ptr->vir_types[i++] = V_PATIENCE;
306                 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
307                 creature_ptr->vir_types[i++] = V_FAITH;
308                 creature_ptr->vir_types[i++] = V_UNLIFE;
309                 break;
310         };
311
312         /* Get one virtue based on race */
313         switch (creature_ptr->prace)
314         {
315         case RACE_HUMAN: case RACE_HALF_ELF: case RACE_DUNADAN:
316                 creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
317                 break;
318         case RACE_ELF: case RACE_SPRITE: case RACE_ENT:
319                 creature_ptr->vir_types[i++] = V_NATURE;
320                 break;
321         case RACE_HOBBIT: case RACE_HALF_OGRE:
322                 creature_ptr->vir_types[i++] = V_TEMPERANCE;
323                 break;
324         case RACE_DWARF: case RACE_KLACKON: case RACE_ANDROID:
325                 creature_ptr->vir_types[i++] = V_DILIGENCE;
326                 break;
327         case RACE_GNOME: case RACE_CYCLOPS:
328                 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
329                 break;
330         case RACE_HALF_ORC: case RACE_AMBERITE: case RACE_KOBOLD:
331                 creature_ptr->vir_types[i++] = V_HONOUR;
332                 break;
333         case RACE_HALF_TROLL: case RACE_BARBARIAN:
334                 creature_ptr->vir_types[i++] = V_VALOUR;
335                 break;
336         case RACE_HIGH_ELF: case RACE_KUTAR:
337                 creature_ptr->vir_types[i++] = V_VITALITY;
338                 break;
339         case RACE_HALF_GIANT: case RACE_GOLEM: case RACE_ANGEL: case RACE_DEMON:
340                 creature_ptr->vir_types[i++] = V_JUSTICE;
341                 break;
342         case RACE_HALF_TITAN:
343                 creature_ptr->vir_types[i++] = V_HARMONY;
344                 break;
345         case RACE_YEEK:
346                 creature_ptr->vir_types[i++] = V_SACRIFICE;
347                 break;
348         case RACE_MIND_FLAYER:
349                 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
350                 break;
351         case RACE_DARK_ELF: case RACE_DRACONIAN: case RACE_S_FAIRY:
352                 creature_ptr->vir_types[i++] = V_ENCHANT;
353                 break;
354         case RACE_NIBELUNG:
355                 creature_ptr->vir_types[i++] = V_PATIENCE;
356                 break;
357         case RACE_IMP:
358                 creature_ptr->vir_types[i++] = V_FAITH;
359                 break;
360         case RACE_ZOMBIE: case RACE_SKELETON:
361         case RACE_VAMPIRE: case RACE_SPECTRE:
362                 creature_ptr->vir_types[i++] = V_UNLIFE;
363                 break;
364         case RACE_BEASTMAN:
365                 creature_ptr->vir_types[i++] = V_CHANCE;
366                 break;
367         }
368
369         /* Get a virtue for realms */
370         if (creature_ptr->realm1)
371         {
372                 tmp_vir = get_realm_virtues(creature_ptr, creature_ptr->realm1);
373                 if (tmp_vir) creature_ptr->vir_types[i++] = tmp_vir;
374         }
375         if (creature_ptr->realm2)
376         {
377                 tmp_vir = get_realm_virtues(creature_ptr, creature_ptr->realm2);
378                 if (tmp_vir) creature_ptr->vir_types[i++] = tmp_vir;
379         }
380
381         /* Eliminate doubles */
382         for (i = 0; i < 8; i++)
383         {
384                 for (j = i + 1; j < 8; j++)
385                 {
386                         if ((creature_ptr->vir_types[j] != 0) && (creature_ptr->vir_types[j] == creature_ptr->vir_types[i]))
387                                 creature_ptr->vir_types[j] = 0;
388                 }
389         }
390
391         /* Fill in the blanks */
392         for (i = 0; i < 8; i++)
393         {
394                 if (creature_ptr->vir_types[i] == 0) get_random_virtue(i);
395         }
396 }
397
398 /*!
399  * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。
400  * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。
401  * @param virtue 徳のID
402  * @param amount 加減量
403  * @return なし
404  */
405 void chg_virtue(player_type *creature_ptr, int virtue_id, int amount)
406 {
407         int i = 0;
408
409         for (i = 0; i < 8; i++)
410         {
411                 if (creature_ptr->vir_types[i] == virtue_id)
412                 {
413                         if (amount > 0)
414                         {
415                                 if ((amount + creature_ptr->virtues[i] > 50) && one_in_(2))
416                                 {
417                                         creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 50);
418                                         return;
419                                 }
420                                 if ((amount + creature_ptr->virtues[i] > 80) && one_in_(2))
421                                 {
422                                         creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 80);
423                                         return;
424                                 }
425                                 if ((amount + creature_ptr->virtues[i] > 100) && one_in_(2))
426                                 {
427                                         creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 100);
428                                         return;
429                                 }
430                                 if (amount + creature_ptr->virtues[i] > 125)
431                                         creature_ptr->virtues[i] = 125;
432                                 else
433                                         creature_ptr->virtues[i] = creature_ptr->virtues[i] + amount;
434                         }
435                         else
436                         {
437                                 if ((amount + creature_ptr->virtues[i] < -50) && one_in_(2))
438                                 {
439                                         creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -50);
440                                         return;
441                                 }
442                                 if ((amount + creature_ptr->virtues[i] < -80) && one_in_(2))
443                                 {
444                                         creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -80);
445                                         return;
446                                 }
447                                 if ((amount + creature_ptr->virtues[i] < -100) && one_in_(2))
448                                 {
449                                         creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -100);
450                                         return;
451                                 }
452                                 if (amount + creature_ptr->virtues[i] < -125)
453                                         creature_ptr->virtues[i] = -125;
454                                 else
455                                         creature_ptr->virtues[i] = creature_ptr->virtues[i] + amount;
456                         }
457                         creature_ptr->update |= (PU_BONUS);
458                         return;
459                 }
460         }
461 }
462
463 /*!
464  * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする。
465  * @param virtue 徳のID
466  * @param amount セットしたい値。
467  * @return なし
468  */
469 void set_virtue(player_type *creature_ptr, int virtue_id, int amount)
470 {
471         int i = 0;
472
473         for (i = 0; i < 8; i++)
474         {
475                 if (creature_ptr->vir_types[i] == virtue_id)
476                 {
477                         creature_ptr->virtues[i] = (s16b)amount;
478                         return;
479                 }
480         }
481 }
482
483 /*!
484  * @brief 徳のダンプ表示を行う。
485  * @param OutFile ファイルポインタ。
486  * @return なし
487  */
488 void dump_virtues(player_type *creature_ptr, FILE *OutFile)
489 {
490         int v_nr = 0;
491
492         if (!OutFile) return;
493
494         for (v_nr = 0; v_nr < 8; v_nr++)
495         {
496                 GAME_TEXT vir_name [20];
497                 int tester = creature_ptr->virtues[v_nr];
498
499                 strcpy(vir_name, virtue[(creature_ptr->vir_types[v_nr])-1]);
500
501                 if (creature_ptr->vir_types[v_nr] == 0 || creature_ptr->vir_types[v_nr] > MAX_VIRTUE)
502                         fprintf(OutFile, _("おっと。%sの情報なし。", "Oops. No info about %s."), vir_name);
503
504                 else if (tester < -100)
505                         fprintf(OutFile, _("[%s]の対極", "You are the polar opposite of %s."), vir_name);
506                 else if (tester < -80)
507                         fprintf(OutFile, _("[%s]の大敵", "You are an arch-enemy of %s."), vir_name);
508                 else if (tester < -60)
509                         fprintf(OutFile, _("[%s]の強敵", "You are a bitter enemy of %s."), vir_name);
510                 else if (tester < -40)
511                         fprintf(OutFile, _("[%s]の敵", "You are an enemy of %s."), vir_name);
512                 else if (tester < -20)
513                         fprintf(OutFile, _("[%s]の罪者", "You have sinned against %s."), vir_name);
514                 else if (tester < 0)
515                         fprintf(OutFile, _("[%s]の迷道者", "You have strayed from the path of %s."), vir_name);
516                 else if (tester == 0)
517                         fprintf(OutFile,_("[%s]の中立者", "You are neutral to %s."), vir_name);
518                 else if (tester < 20)
519                         fprintf(OutFile,_("[%s]の小徳者", "You are somewhat virtuous in %s."), vir_name);
520                 else if (tester < 40)
521                         fprintf(OutFile,_("[%s]の中徳者", "You are virtuous in %s."), vir_name);
522                 else if (tester < 60)
523                         fprintf(OutFile,_("[%s]の高徳者", "You are very virtuous in %s."), vir_name);
524                 else if (tester < 80)
525                         fprintf(OutFile,_("[%s]の覇者", "You are a champion of %s."), vir_name);
526                 else if (tester < 100)
527                         fprintf(OutFile,_("[%s]の偉大な覇者", "You are a great champion of %s."), vir_name);
528                 else
529                         fprintf(OutFile,_("[%s]の具現者", "You are the living embodiment of %s."), vir_name);
530
531             fprintf(OutFile, "\n");
532         }
533 }