OSDN Git Service

Merge pull request #716 from sikabane-works/release/3.0.0Alpha16
[hengbandforosx/hengbandosx.git] / src / player-info / avatar.cpp
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     case CLASS_ELEMENTALIST:
329         creature_ptr->vir_types[i++] = V_NATURE;
330         break;
331     case MAX_CLASS:
332         break;
333     };
334
335     /* Get one virtue based on race */
336     switch (creature_ptr->prace) {
337     case RACE_HUMAN:
338     case RACE_HALF_ELF:
339     case RACE_DUNADAN:
340         creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
341         break;
342     case RACE_ELF:
343     case RACE_SPRITE:
344     case RACE_ENT:
345     case RACE_MERFOLK:
346         creature_ptr->vir_types[i++] = V_NATURE;
347         break;
348     case RACE_HOBBIT:
349     case RACE_HALF_OGRE:
350         creature_ptr->vir_types[i++] = V_TEMPERANCE;
351         break;
352     case RACE_DWARF:
353     case RACE_KLACKON:
354     case RACE_ANDROID:
355         creature_ptr->vir_types[i++] = V_DILIGENCE;
356         break;
357     case RACE_GNOME:
358     case RACE_CYCLOPS:
359         creature_ptr->vir_types[i++] = V_KNOWLEDGE;
360         break;
361     case RACE_HALF_ORC:
362     case RACE_AMBERITE:
363     case RACE_KOBOLD:
364         creature_ptr->vir_types[i++] = V_HONOUR;
365         break;
366     case RACE_HALF_TROLL:
367     case RACE_BARBARIAN:
368         creature_ptr->vir_types[i++] = V_VALOUR;
369         break;
370     case RACE_HIGH_ELF:
371     case RACE_KUTAR:
372         creature_ptr->vir_types[i++] = V_VITALITY;
373         break;
374     case RACE_HALF_GIANT:
375     case RACE_GOLEM:
376     case RACE_ARCHON:
377     case RACE_BALROG:
378         creature_ptr->vir_types[i++] = V_JUSTICE;
379         break;
380     case RACE_HALF_TITAN:
381         creature_ptr->vir_types[i++] = V_HARMONY;
382         break;
383     case RACE_YEEK:
384         creature_ptr->vir_types[i++] = V_SACRIFICE;
385         break;
386     case RACE_MIND_FLAYER:
387         creature_ptr->vir_types[i++] = V_ENLIGHTEN;
388         break;
389     case RACE_DARK_ELF:
390     case RACE_DRACONIAN:
391     case RACE_S_FAIRY:
392         creature_ptr->vir_types[i++] = V_ENCHANT;
393         break;
394     case RACE_NIBELUNG:
395         creature_ptr->vir_types[i++] = V_PATIENCE;
396         break;
397     case RACE_IMP:
398         creature_ptr->vir_types[i++] = V_FAITH;
399         break;
400     case RACE_ZOMBIE:
401     case RACE_SKELETON:
402     case RACE_VAMPIRE:
403     case RACE_SPECTRE:
404         creature_ptr->vir_types[i++] = V_UNLIFE;
405         break;
406     case RACE_BEASTMAN:
407         creature_ptr->vir_types[i++] = V_CHANCE;
408         break;
409     case MAX_RACES:
410         break;
411     }
412
413     /* Get a virtue for realms */
414     if (creature_ptr->realm1) {
415         tmp_vir = get_realm_virtues(creature_ptr, creature_ptr->realm1);
416         if (tmp_vir)
417             creature_ptr->vir_types[i++] = tmp_vir;
418     }
419
420     if (creature_ptr->realm2) {
421         tmp_vir = get_realm_virtues(creature_ptr, creature_ptr->realm2);
422         if (tmp_vir)
423             creature_ptr->vir_types[i++] = tmp_vir;
424     }
425
426     /* Eliminate doubles */
427     for (i = 0; i < 8; i++)
428         for (j = i + 1; j < 8; j++)
429             if ((creature_ptr->vir_types[j] != 0) && (creature_ptr->vir_types[j] == creature_ptr->vir_types[i]))
430                 creature_ptr->vir_types[j] = 0;
431
432     /* Fill in the blanks */
433     for (i = 0; i < 8; i++)
434         if (creature_ptr->vir_types[i] == 0)
435             get_random_virtue(creature_ptr, i);
436 }
437
438 /*!
439  * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。
440  * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。
441  * @param virtue 徳のID
442  * @param amount 加減量
443  * @return なし
444  */
445 void chg_virtue(player_type *creature_ptr, int virtue_id, int amount)
446 {
447     for (int i = 0; i < 8; i++) {
448         if (creature_ptr->vir_types[i] != virtue_id)
449             continue;
450
451         if (amount > 0) {
452             if ((amount + creature_ptr->virtues[i] > 50) && one_in_(2)) {
453                 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 50);
454                 return;
455             }
456
457             if ((amount + creature_ptr->virtues[i] > 80) && one_in_(2)) {
458                 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 80);
459                 return;
460             }
461
462             if ((amount + creature_ptr->virtues[i] > 100) && one_in_(2)) {
463                 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 100);
464                 return;
465             }
466
467             if (amount + creature_ptr->virtues[i] > 125)
468                 creature_ptr->virtues[i] = 125;
469             else
470                 creature_ptr->virtues[i] = creature_ptr->virtues[i] + amount;
471         } else {
472             if ((amount + creature_ptr->virtues[i] < -50) && one_in_(2)) {
473                 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -50);
474                 return;
475             }
476
477             if ((amount + creature_ptr->virtues[i] < -80) && one_in_(2)) {
478                 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -80);
479                 return;
480             }
481
482             if ((amount + creature_ptr->virtues[i] < -100) && one_in_(2)) {
483                 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -100);
484                 return;
485             }
486
487             if (amount + creature_ptr->virtues[i] < -125)
488                 creature_ptr->virtues[i] = -125;
489             else
490                 creature_ptr->virtues[i] = creature_ptr->virtues[i] + amount;
491         }
492
493         creature_ptr->update |= PU_BONUS;
494         return;
495     }
496 }
497
498 /*!
499  * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする
500  * @param virtue 徳のID
501  * @param amount セットしたい値
502  * @return なし
503  */
504 void set_virtue(player_type *creature_ptr, int virtue_id, int amount)
505 {
506     for (int i = 0; i < 8; i++)
507         if (creature_ptr->vir_types[i] == virtue_id) {
508             creature_ptr->virtues[i] = (s16b)amount;
509             return;
510         }
511 }
512
513 /*!
514  * @brief 徳のダンプ表示を行う
515  * @param out_file ファイルポインタ
516  * @return なし
517  */
518 void dump_virtues(player_type *creature_ptr, FILE *out_file)
519 {
520     if (!out_file)
521         return;
522
523     for (int v_nr = 0; v_nr < 8; v_nr++) {
524         GAME_TEXT vir_name[20];
525         int tester = creature_ptr->virtues[v_nr];
526         strcpy(vir_name, virtue[(creature_ptr->vir_types[v_nr]) - 1]);
527         if (creature_ptr->vir_types[v_nr] == 0 || creature_ptr->vir_types[v_nr] > MAX_VIRTUE)
528             fprintf(out_file, _("おっと。%sの情報なし。", "Oops. No info about %s."), vir_name);
529
530         else if (tester < -100)
531             fprintf(out_file, _("[%s]の対極", "You are the polar opposite of %s."), vir_name);
532         else if (tester < -80)
533             fprintf(out_file, _("[%s]の大敵", "You are an arch-enemy of %s."), vir_name);
534         else if (tester < -60)
535             fprintf(out_file, _("[%s]の強敵", "You are a bitter enemy of %s."), vir_name);
536         else if (tester < -40)
537             fprintf(out_file, _("[%s]の敵", "You are an enemy of %s."), vir_name);
538         else if (tester < -20)
539             fprintf(out_file, _("[%s]の罪者", "You have sinned against %s."), vir_name);
540         else if (tester < 0)
541             fprintf(out_file, _("[%s]の迷道者", "You have strayed from the path of %s."), vir_name);
542         else if (tester == 0)
543             fprintf(out_file, _("[%s]の中立者", "You are neutral to %s."), vir_name);
544         else if (tester < 20)
545             fprintf(out_file, _("[%s]の小徳者", "You are somewhat virtuous in %s."), vir_name);
546         else if (tester < 40)
547             fprintf(out_file, _("[%s]の中徳者", "You are virtuous in %s."), vir_name);
548         else if (tester < 60)
549             fprintf(out_file, _("[%s]の高徳者", "You are very virtuous in %s."), vir_name);
550         else if (tester < 80)
551             fprintf(out_file, _("[%s]の覇者", "You are a champion of %s."), vir_name);
552         else if (tester < 100)
553             fprintf(out_file, _("[%s]の偉大な覇者", "You are a great champion of %s."), vir_name);
554         else
555             fprintf(out_file, _("[%s]の具現者", "You are the living embodiment of %s."), vir_name);
556
557         fprintf(out_file, "\n");
558     }
559 }