2 * @brief ウルティマ4を参考にした徳のシステムの実装 / Enable an Ultima IV style "avatar" game where you try to achieve perfection in various virtues.
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.
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"
22 * 徳の名称 / The names of the virtues
24 concptr virtue[MAX_VIRTUE] = {
31 _("啓", "Enlightenment"),
42 _("個", "Individualism"),
46 * @brief 該当の徳がプレイヤーに指定されているか否かに応じつつ、大小を比較する。
47 * @details 徳がない場合は値0として比較する。
48 * @param type 比較したい徳のID
50 * @param tekitou VIRTUE_LARGE = 基準値より大きいか / VIRTUE_SMALL = 基準値より小さいか
54 bool compare_virtue(player_type *creature_ptr, int type, int num, int tekitou)
56 int vir = virtue_number(creature_ptr, type) ? creature_ptr->virtues[virtue_number(creature_ptr, type) - 1] : 0;
74 * @brief プレイヤーの指定の徳が何番目のスロットに登録されているかを返す。 / Aux function
75 * @param type 確認したい徳のID
76 * @return スロットがあるならばスロットのID(0~7)+1、ない場合は0を返す。
78 int virtue_number(player_type *creature_ptr, int type)
80 for (int i = 0; i < 8; i++)
81 if (creature_ptr->vir_types[i] == type)
88 * @brief プレイヤーの職業や種族に依存しないランダムな徳を取得する / Aux function
89 * @param which 確認したい徳のID
92 static void get_random_virtue(player_type *creature_ptr, int which)
95 while (!(type) || virtue_number(creature_ptr, type)) {
96 switch (randint1(29)) {
147 creature_ptr->vir_types[which] = (s16b)type;
151 * @brief プレイヤーの選んだ魔法領域に応じて対応する徳を返す。
152 * @param realm 魔法領域のID
155 static VIRTUES_IDX get_realm_virtues(player_type *creature_ptr, REALM_IDX realm)
159 if (virtue_number(creature_ptr, V_VITALITY))
164 if (virtue_number(creature_ptr, V_KNOWLEDGE))
169 if (virtue_number(creature_ptr, V_NATURE))
174 if (virtue_number(creature_ptr, V_CHANCE))
175 return V_INDIVIDUALISM;
185 if (virtue_number(creature_ptr, V_ENCHANT))
186 return V_INDIVIDUALISM;
190 if (virtue_number(creature_ptr, V_JUSTICE))
195 if (virtue_number(creature_ptr, V_JUSTICE))
200 if (virtue_number(creature_ptr, V_COMPASSION))
210 * @brief 作成中のプレイヤーキャラクターに徳8種類を与える。 / Select virtues & reset values for a new character
211 * @details 職業に応じて1~4種が固定、種族に応じて1種類が与えられ、後は重複なくランダムに選択される。
214 void get_virtues(player_type *creature_ptr)
220 for (i = 0; i < 8; i++) {
221 creature_ptr->virtues[i] = 0;
222 creature_ptr->vir_types[i] = 0;
227 /* Get pre-defined types */
228 /* 1 or more virtues based on class */
229 switch (creature_ptr->pclass) {
232 creature_ptr->vir_types[i++] = V_VALOUR;
233 creature_ptr->vir_types[i++] = V_HONOUR;
236 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
237 creature_ptr->vir_types[i++] = V_ENCHANT;
240 creature_ptr->vir_types[i++] = V_FAITH;
241 creature_ptr->vir_types[i++] = V_TEMPERANCE;
245 creature_ptr->vir_types[i++] = V_HONOUR;
249 creature_ptr->vir_types[i++] = V_NATURE;
250 creature_ptr->vir_types[i++] = V_TEMPERANCE;
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;
258 case CLASS_WARRIOR_MAGE:
260 creature_ptr->vir_types[i++] = V_ENCHANT;
261 creature_ptr->vir_types[i++] = V_VALOUR;
263 case CLASS_CHAOS_WARRIOR:
264 creature_ptr->vir_types[i++] = V_CHANCE;
265 creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
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;
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;
280 case CLASS_HIGH_MAGE:
282 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
283 creature_ptr->vir_types[i++] = V_ENCHANT;
284 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
287 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
288 creature_ptr->vir_types[i++] = V_CHANCE;
291 creature_ptr->vir_types[i++] = V_CHANCE;
293 case CLASS_BLUE_MAGE:
294 creature_ptr->vir_types[i++] = V_CHANCE;
295 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
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;
302 case CLASS_MAGIC_EATER:
303 creature_ptr->vir_types[i++] = V_ENCHANT;
304 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
307 creature_ptr->vir_types[i++] = V_HARMONY;
308 creature_ptr->vir_types[i++] = V_COMPASSION;
311 creature_ptr->vir_types[i++] = V_VALOUR;
312 creature_ptr->vir_types[i++] = V_HARMONY;
314 case CLASS_BERSERKER:
315 creature_ptr->vir_types[i++] = V_VALOUR;
316 creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
319 creature_ptr->vir_types[i++] = V_HONOUR;
320 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
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;
330 /* Get one virtue based on race */
331 switch (creature_ptr->prace) {
335 creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
340 creature_ptr->vir_types[i++] = V_NATURE;
344 creature_ptr->vir_types[i++] = V_TEMPERANCE;
349 creature_ptr->vir_types[i++] = V_DILIGENCE;
353 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
358 creature_ptr->vir_types[i++] = V_HONOUR;
360 case RACE_HALF_TROLL:
362 creature_ptr->vir_types[i++] = V_VALOUR;
366 creature_ptr->vir_types[i++] = V_VITALITY;
368 case RACE_HALF_GIANT:
372 creature_ptr->vir_types[i++] = V_JUSTICE;
374 case RACE_HALF_TITAN:
375 creature_ptr->vir_types[i++] = V_HARMONY;
378 creature_ptr->vir_types[i++] = V_SACRIFICE;
380 case RACE_MIND_FLAYER:
381 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
386 creature_ptr->vir_types[i++] = V_ENCHANT;
389 creature_ptr->vir_types[i++] = V_PATIENCE;
392 creature_ptr->vir_types[i++] = V_FAITH;
398 creature_ptr->vir_types[i++] = V_UNLIFE;
401 creature_ptr->vir_types[i++] = V_CHANCE;
405 /* Get a virtue for realms */
406 if (creature_ptr->realm1) {
407 tmp_vir = get_realm_virtues(creature_ptr, creature_ptr->realm1);
409 creature_ptr->vir_types[i++] = tmp_vir;
412 if (creature_ptr->realm2) {
413 tmp_vir = get_realm_virtues(creature_ptr, creature_ptr->realm2);
415 creature_ptr->vir_types[i++] = tmp_vir;
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;
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);
431 * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。
432 * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。
437 void chg_virtue(player_type *creature_ptr, int virtue_id, int amount)
439 for (int i = 0; i < 8; i++) {
440 if (creature_ptr->vir_types[i] != virtue_id)
444 if ((amount + creature_ptr->virtues[i] > 50) && one_in_(2)) {
445 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 50);
449 if ((amount + creature_ptr->virtues[i] > 80) && one_in_(2)) {
450 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 80);
454 if ((amount + creature_ptr->virtues[i] > 100) && one_in_(2)) {
455 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 100);
459 if (amount + creature_ptr->virtues[i] > 125)
460 creature_ptr->virtues[i] = 125;
462 creature_ptr->virtues[i] = creature_ptr->virtues[i] + amount;
464 if ((amount + creature_ptr->virtues[i] < -50) && one_in_(2)) {
465 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -50);
469 if ((amount + creature_ptr->virtues[i] < -80) && one_in_(2)) {
470 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -80);
474 if ((amount + creature_ptr->virtues[i] < -100) && one_in_(2)) {
475 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -100);
479 if (amount + creature_ptr->virtues[i] < -125)
480 creature_ptr->virtues[i] = -125;
482 creature_ptr->virtues[i] = creature_ptr->virtues[i] + amount;
485 creature_ptr->update |= PU_BONUS;
491 * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする
493 * @param amount セットしたい値
496 void set_virtue(player_type *creature_ptr, int virtue_id, int amount)
498 for (int i = 0; i < 8; i++)
499 if (creature_ptr->vir_types[i] == virtue_id) {
500 creature_ptr->virtues[i] = (s16b)amount;
507 * @param out_file ファイルポインタ
510 void dump_virtues(player_type *creature_ptr, FILE *out_file)
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);
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);
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);
547 fprintf(out_file, _("[%s]の具現者", "You are the living embodiment of %s."), vir_name);
549 fprintf(out_file, "\n");