OSDN Git Service

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