3 @brief ウルティマ4を参考にした徳のシステムの実装 / Enable an Ultima IV style "avatar" game where you try to achieve perfection in various virtues.
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.
19 #include "player-race.h"
22 * 徳の名称 / The names of the virtues
24 concptr virtue[MAX_VIRTUE] =
32 _("啓", "Enlightenment"),
43 _("個", "Individualism"),
47 * @brief 該当の徳がプレイヤーに指定されているか否かに応じつつ、大小を比較する。
48 * @details 徳がない場合は値0として比較する。
49 * @param type 比較したい徳のID
51 * @param tekitou VIRTUE_LARGE = 基準値より大きいか / VIRTUE_SMALL = 基準値より小さいか
55 bool compare_virtue(int type, int num, int tekitou)
58 if (virtue_number(type))
59 vir = p_ptr->virtues[virtue_number(type) - 1];
66 if (vir > num) return TRUE;
69 if (vir < num) return TRUE;
77 * @brief プレイヤーの指定の徳が何番目のスロットに登録されているかを返す。 / Aux function
78 * @param type 確認したい徳のID
79 * @return スロットがあるならばスロットのID(0~7)+1、ない場合は0を返す。
81 int virtue_number(int type)
86 for (i = 0; i < 8; i++)
88 if (p_ptr->vir_types[i] == type) return i + 1;
96 * @brief プレイヤーの職業や種族に依存しないランダムな徳を取得する / Aux function
97 * @param which 確認したい徳のID
100 static void get_random_virtue(int which)
104 /* Randomly choose a type */
105 while (!(type) || virtue_number(type))
107 switch (randint1(29))
109 case 1: case 2: case 3:
112 case 4: case 5: case 6:
115 case 7: case 8: case 9: case 10: case 11: case 12:
118 case 13: case 14: case 15: case 16: case 17:
121 case 18: case 19: case 20: case 21:
130 case 26: case 27: case 28:
140 p_ptr->vir_types[which] = (s16b)type;
144 * @brief プレイヤーの選んだ魔法領域に応じて対応する徳を返す。
145 * @param realm 魔法領域のID
148 static VIRTUES_IDX get_realm_virtues(REALM_IDX realm)
153 if (virtue_number(V_VITALITY)) return V_TEMPERANCE;
154 else return V_VITALITY;
156 if (virtue_number(V_KNOWLEDGE)) return V_ENCHANT;
157 else return V_KNOWLEDGE;
159 if (virtue_number(V_NATURE)) return V_HARMONY;
160 else return V_NATURE;
162 if (virtue_number(V_CHANCE)) return V_INDIVIDUALISM;
163 else return V_CHANCE;
171 if (virtue_number(V_ENCHANT)) return V_INDIVIDUALISM;
172 else return V_ENCHANT;
174 if (virtue_number(V_JUSTICE)) return V_FAITH;
175 else return V_JUSTICE;
177 if (virtue_number(V_JUSTICE)) return V_HONOUR;
178 else return V_JUSTICE;
180 if (virtue_number(V_COMPASSION)) return V_JUSTICE;
181 else return V_COMPASSION;
189 * @brief 作成中のプレイヤーキャラクターに徳8種類を与える。 / Select virtues & reset values for a new character
190 * @details 職業に応じて1~4種が固定、種族に応じて1種類が与えられ、後は重複なくランダムに選択される。
193 void get_virtues(void)
199 for (i = 0; i < 8; i++)
201 p_ptr->virtues[i] = 0;
202 p_ptr->vir_types[i] = 0;
207 /* Get pre-defined types */
208 /* 1 or more virtues based on class */
209 switch (p_ptr->pclass)
213 p_ptr->vir_types[i++] = V_VALOUR;
214 p_ptr->vir_types[i++] = V_HONOUR;
217 p_ptr->vir_types[i++] = V_KNOWLEDGE;
218 p_ptr->vir_types[i++] = V_ENCHANT;
221 p_ptr->vir_types[i++] = V_FAITH;
222 p_ptr->vir_types[i++] = V_TEMPERANCE;
226 p_ptr->vir_types[i++] = V_HONOUR;
230 p_ptr->vir_types[i++] = V_NATURE;
231 p_ptr->vir_types[i++] = V_TEMPERANCE;
234 p_ptr->vir_types[i++] = V_JUSTICE;
235 p_ptr->vir_types[i++] = V_VALOUR;
236 p_ptr->vir_types[i++] = V_HONOUR;
237 p_ptr->vir_types[i++] = V_FAITH;
239 case CLASS_WARRIOR_MAGE:
241 p_ptr->vir_types[i++] = V_ENCHANT;
242 p_ptr->vir_types[i++] = V_VALOUR;
244 case CLASS_CHAOS_WARRIOR:
245 p_ptr->vir_types[i++] = V_CHANCE;
246 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
249 case CLASS_FORCETRAINER:
250 p_ptr->vir_types[i++] = V_FAITH;
251 p_ptr->vir_types[i++] = V_HARMONY;
252 p_ptr->vir_types[i++] = V_TEMPERANCE;
253 p_ptr->vir_types[i++] = V_PATIENCE;
255 case CLASS_MINDCRAFTER:
256 case CLASS_MIRROR_MASTER:
257 p_ptr->vir_types[i++] = V_HARMONY;
258 p_ptr->vir_types[i++] = V_ENLIGHTEN;
259 p_ptr->vir_types[i++] = V_PATIENCE;
261 case CLASS_HIGH_MAGE:
263 p_ptr->vir_types[i++] = V_ENLIGHTEN;
264 p_ptr->vir_types[i++] = V_ENCHANT;
265 p_ptr->vir_types[i++] = V_KNOWLEDGE;
268 p_ptr->vir_types[i++] = V_ENLIGHTEN;
269 p_ptr->vir_types[i++] = V_CHANCE;
272 p_ptr->vir_types[i++] = V_CHANCE;
274 case CLASS_BLUE_MAGE:
275 p_ptr->vir_types[i++] = V_CHANCE;
276 p_ptr->vir_types[i++] = V_KNOWLEDGE;
278 case CLASS_BEASTMASTER:
279 p_ptr->vir_types[i++] = V_NATURE;
280 p_ptr->vir_types[i++] = V_CHANCE;
281 p_ptr->vir_types[i++] = V_VITALITY;
283 case CLASS_MAGIC_EATER:
284 p_ptr->vir_types[i++] = V_ENCHANT;
285 p_ptr->vir_types[i++] = V_KNOWLEDGE;
288 p_ptr->vir_types[i++] = V_HARMONY;
289 p_ptr->vir_types[i++] = V_COMPASSION;
292 p_ptr->vir_types[i++] = V_VALOUR;
293 p_ptr->vir_types[i++] = V_HARMONY;
295 case CLASS_BERSERKER:
296 p_ptr->vir_types[i++] = V_VALOUR;
297 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
300 p_ptr->vir_types[i++] = V_HONOUR;
301 p_ptr->vir_types[i++] = V_KNOWLEDGE;
304 p_ptr->vir_types[i++] = V_PATIENCE;
305 p_ptr->vir_types[i++] = V_KNOWLEDGE;
306 p_ptr->vir_types[i++] = V_FAITH;
307 p_ptr->vir_types[i++] = V_UNLIFE;
311 /* Get one virtue based on race */
312 switch (p_ptr->prace)
314 case RACE_HUMAN: case RACE_HALF_ELF: case RACE_DUNADAN:
315 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
317 case RACE_ELF: case RACE_SPRITE: case RACE_ENT:
318 p_ptr->vir_types[i++] = V_NATURE;
320 case RACE_HOBBIT: case RACE_HALF_OGRE:
321 p_ptr->vir_types[i++] = V_TEMPERANCE;
323 case RACE_DWARF: case RACE_KLACKON: case RACE_ANDROID:
324 p_ptr->vir_types[i++] = V_DILIGENCE;
326 case RACE_GNOME: case RACE_CYCLOPS:
327 p_ptr->vir_types[i++] = V_KNOWLEDGE;
329 case RACE_HALF_ORC: case RACE_AMBERITE: case RACE_KOBOLD:
330 p_ptr->vir_types[i++] = V_HONOUR;
332 case RACE_HALF_TROLL: case RACE_BARBARIAN:
333 p_ptr->vir_types[i++] = V_VALOUR;
335 case RACE_HIGH_ELF: case RACE_KUTAR:
336 p_ptr->vir_types[i++] = V_VITALITY;
338 case RACE_HALF_GIANT: case RACE_GOLEM: case RACE_ANGEL: case RACE_DEMON:
339 p_ptr->vir_types[i++] = V_JUSTICE;
341 case RACE_HALF_TITAN:
342 p_ptr->vir_types[i++] = V_HARMONY;
345 p_ptr->vir_types[i++] = V_SACRIFICE;
347 case RACE_MIND_FLAYER:
348 p_ptr->vir_types[i++] = V_ENLIGHTEN;
350 case RACE_DARK_ELF: case RACE_DRACONIAN: case RACE_S_FAIRY:
351 p_ptr->vir_types[i++] = V_ENCHANT;
354 p_ptr->vir_types[i++] = V_PATIENCE;
357 p_ptr->vir_types[i++] = V_FAITH;
359 case RACE_ZOMBIE: case RACE_SKELETON:
360 case RACE_VAMPIRE: case RACE_SPECTRE:
361 p_ptr->vir_types[i++] = V_UNLIFE;
364 p_ptr->vir_types[i++] = V_CHANCE;
368 /* Get a virtue for realms */
371 tmp_vir = get_realm_virtues(p_ptr->realm1);
372 if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir;
376 tmp_vir = get_realm_virtues(p_ptr->realm2);
377 if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir;
380 /* Eliminate doubles */
381 for (i = 0; i < 8; i++)
383 for (j = i + 1; j < 8; j++)
385 if ((p_ptr->vir_types[j] != 0) && (p_ptr->vir_types[j] == p_ptr->vir_types[i]))
386 p_ptr->vir_types[j] = 0;
390 /* Fill in the blanks */
391 for (i = 0; i < 8; i++)
393 if (p_ptr->vir_types[i] == 0) get_random_virtue(i);
398 * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。
399 * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。
404 void chg_virtue(int virtue_id, int amount)
408 for (i = 0; i < 8; i++)
410 if (p_ptr->vir_types[i] == virtue_id)
414 if ((amount + p_ptr->virtues[i] > 50) && one_in_(2))
416 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 50);
419 if ((amount + p_ptr->virtues[i] > 80) && one_in_(2))
421 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 80);
424 if ((amount + p_ptr->virtues[i] > 100) && one_in_(2))
426 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 100);
429 if (amount + p_ptr->virtues[i] > 125)
430 p_ptr->virtues[i] = 125;
432 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
436 if ((amount + p_ptr->virtues[i] < -50) && one_in_(2))
438 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -50);
441 if ((amount + p_ptr->virtues[i] < -80) && one_in_(2))
443 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -80);
446 if ((amount + p_ptr->virtues[i] < -100) && one_in_(2))
448 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -100);
451 if (amount + p_ptr->virtues[i] < -125)
452 p_ptr->virtues[i] = -125;
454 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
456 p_ptr->update |= (PU_BONUS);
463 * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする。
465 * @param amount セットしたい値。
468 void set_virtue(int virtue_id, int amount)
472 for (i = 0; i < 8; i++)
474 if (p_ptr->vir_types[i] == virtue_id)
476 p_ptr->virtues[i] = (s16b)amount;
484 * @param OutFile ファイルポインタ。
487 void dump_virtues(FILE *OutFile)
491 if (!OutFile) return;
493 for (v_nr = 0; v_nr < 8; v_nr++)
495 GAME_TEXT vir_name [20];
496 int tester = p_ptr->virtues[v_nr];
498 strcpy(vir_name, virtue[(p_ptr->vir_types[v_nr])-1]);
500 if (p_ptr->vir_types[v_nr] == 0 || p_ptr->vir_types[v_nr] > MAX_VIRTUE)
501 fprintf(OutFile, _("おっと。%sの情報なし。", "Oops. No info about %s."), vir_name);
503 else if (tester < -100)
504 fprintf(OutFile, _("[%s]の対極", "You are the polar opposite of %s."), vir_name);
505 else if (tester < -80)
506 fprintf(OutFile, _("[%s]の大敵", "You are an arch-enemy of %s."), vir_name);
507 else if (tester < -60)
508 fprintf(OutFile, _("[%s]の強敵", "You are a bitter enemy of %s."), vir_name);
509 else if (tester < -40)
510 fprintf(OutFile, _("[%s]の敵", "You are an enemy of %s."), vir_name);
511 else if (tester < -20)
512 fprintf(OutFile, _("[%s]の罪者", "You have sinned against %s."), vir_name);
514 fprintf(OutFile, _("[%s]の迷道者", "You have strayed from the path of %s."), vir_name);
515 else if (tester == 0)
516 fprintf(OutFile,_("[%s]の中立者", "You are neutral to %s."), vir_name);
517 else if (tester < 20)
518 fprintf(OutFile,_("[%s]の小徳者", "You are somewhat virtuous in %s."), vir_name);
519 else if (tester < 40)
520 fprintf(OutFile,_("[%s]の中徳者", "You are virtuous in %s."), vir_name);
521 else if (tester < 60)
522 fprintf(OutFile,_("[%s]の高徳者", "You are very virtuous in %s."), vir_name);
523 else if (tester < 80)
524 fprintf(OutFile,_("[%s]の覇者", "You are a champion of %s."), vir_name);
525 else if (tester < 100)
526 fprintf(OutFile,_("[%s]の偉大な覇者", "You are a great champion of %s."), vir_name);
528 fprintf(OutFile,_("[%s]の具現者", "You are the living embodiment of %s."), vir_name);
530 fprintf(OutFile, "\n");