OSDN Git Service

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