OSDN Git Service

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