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;
328 case CLASS_ELEMENTALIST:
329 creature_ptr->vir_types[i++] = V_NATURE;
335 /* Get one virtue based on race */
336 switch (creature_ptr->prace) {
340 creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
346 creature_ptr->vir_types[i++] = V_NATURE;
350 creature_ptr->vir_types[i++] = V_TEMPERANCE;
355 creature_ptr->vir_types[i++] = V_DILIGENCE;
359 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
364 creature_ptr->vir_types[i++] = V_HONOUR;
366 case RACE_HALF_TROLL:
368 creature_ptr->vir_types[i++] = V_VALOUR;
372 creature_ptr->vir_types[i++] = V_VITALITY;
374 case RACE_HALF_GIANT:
378 creature_ptr->vir_types[i++] = V_JUSTICE;
380 case RACE_HALF_TITAN:
381 creature_ptr->vir_types[i++] = V_HARMONY;
384 creature_ptr->vir_types[i++] = V_SACRIFICE;
386 case RACE_MIND_FLAYER:
387 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
392 creature_ptr->vir_types[i++] = V_ENCHANT;
395 creature_ptr->vir_types[i++] = V_PATIENCE;
398 creature_ptr->vir_types[i++] = V_FAITH;
404 creature_ptr->vir_types[i++] = V_UNLIFE;
407 creature_ptr->vir_types[i++] = V_CHANCE;
413 /* Get a virtue for realms */
414 if (creature_ptr->realm1) {
415 tmp_vir = get_realm_virtues(creature_ptr, creature_ptr->realm1);
417 creature_ptr->vir_types[i++] = tmp_vir;
420 if (creature_ptr->realm2) {
421 tmp_vir = get_realm_virtues(creature_ptr, creature_ptr->realm2);
423 creature_ptr->vir_types[i++] = tmp_vir;
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;
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);
439 * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。
440 * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。
445 void chg_virtue(player_type *creature_ptr, int virtue_id, int amount)
447 for (int i = 0; i < 8; i++) {
448 if (creature_ptr->vir_types[i] != virtue_id)
452 if ((amount + creature_ptr->virtues[i] > 50) && one_in_(2)) {
453 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 50);
457 if ((amount + creature_ptr->virtues[i] > 80) && one_in_(2)) {
458 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 80);
462 if ((amount + creature_ptr->virtues[i] > 100) && one_in_(2)) {
463 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 100);
467 if (amount + creature_ptr->virtues[i] > 125)
468 creature_ptr->virtues[i] = 125;
470 creature_ptr->virtues[i] = creature_ptr->virtues[i] + amount;
472 if ((amount + creature_ptr->virtues[i] < -50) && one_in_(2)) {
473 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -50);
477 if ((amount + creature_ptr->virtues[i] < -80) && one_in_(2)) {
478 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -80);
482 if ((amount + creature_ptr->virtues[i] < -100) && one_in_(2)) {
483 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -100);
487 if (amount + creature_ptr->virtues[i] < -125)
488 creature_ptr->virtues[i] = -125;
490 creature_ptr->virtues[i] = creature_ptr->virtues[i] + amount;
493 creature_ptr->update |= PU_BONUS;
499 * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする
501 * @param amount セットしたい値
504 void set_virtue(player_type *creature_ptr, int virtue_id, int amount)
506 for (int i = 0; i < 8; i++)
507 if (creature_ptr->vir_types[i] == virtue_id) {
508 creature_ptr->virtues[i] = (s16b)amount;
515 * @param out_file ファイルポインタ
518 void dump_virtues(player_type *creature_ptr, FILE *out_file)
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);
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);
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);
555 fprintf(out_file, _("[%s]の具現者", "You are the living embodiment of %s."), vir_name);
557 fprintf(out_file, "\n");