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"
20 #include "player-class.h"
23 * 徳の名称 / The names of the virtues
25 concptr virtue[MAX_VIRTUE] =
33 _("啓", "Enlightenment"),
44 _("個", "Individualism"),
48 * @brief 該当の徳がプレイヤーに指定されているか否かに応じつつ、大小を比較する。
49 * @details 徳がない場合は値0として比較する。
50 * @param type 比較したい徳のID
52 * @param tekitou VIRTUE_LARGE = 基準値より大きいか / VIRTUE_SMALL = 基準値より小さいか
56 bool compare_virtue(int type, int num, int tekitou)
59 if (virtue_number(type))
60 vir = p_ptr->virtues[virtue_number(type) - 1];
67 if (vir > num) return TRUE;
70 if (vir < num) return TRUE;
78 * @brief プレイヤーの指定の徳が何番目のスロットに登録されているかを返す。 / Aux function
79 * @param type 確認したい徳のID
80 * @return スロットがあるならばスロットのID(0~7)+1、ない場合は0を返す。
82 int virtue_number(int type)
87 for (i = 0; i < 8; i++)
89 if (p_ptr->vir_types[i] == type) return i + 1;
97 * @brief プレイヤーの職業や種族に依存しないランダムな徳を取得する / Aux function
98 * @param which 確認したい徳のID
101 static void get_random_virtue(int which)
105 /* Randomly choose a type */
106 while (!(type) || virtue_number(type))
108 switch (randint1(29))
110 case 1: case 2: case 3:
113 case 4: case 5: case 6:
116 case 7: case 8: case 9: case 10: case 11: case 12:
119 case 13: case 14: case 15: case 16: case 17:
122 case 18: case 19: case 20: case 21:
131 case 26: case 27: case 28:
141 p_ptr->vir_types[which] = (s16b)type;
145 * @brief プレイヤーの選んだ魔法領域に応じて対応する徳を返す。
146 * @param realm 魔法領域のID
149 static VIRTUES_IDX get_realm_virtues(REALM_IDX realm)
154 if (virtue_number(V_VITALITY)) return V_TEMPERANCE;
155 else return V_VITALITY;
157 if (virtue_number(V_KNOWLEDGE)) return V_ENCHANT;
158 else return V_KNOWLEDGE;
160 if (virtue_number(V_NATURE)) return V_HARMONY;
161 else return V_NATURE;
163 if (virtue_number(V_CHANCE)) return V_INDIVIDUALISM;
164 else return V_CHANCE;
172 if (virtue_number(V_ENCHANT)) return V_INDIVIDUALISM;
173 else return V_ENCHANT;
175 if (virtue_number(V_JUSTICE)) return V_FAITH;
176 else return V_JUSTICE;
178 if (virtue_number(V_JUSTICE)) return V_HONOUR;
179 else return V_JUSTICE;
181 if (virtue_number(V_COMPASSION)) return V_JUSTICE;
182 else return V_COMPASSION;
190 * @brief 作成中のプレイヤーキャラクターに徳8種類を与える。 / Select virtues & reset values for a new character
191 * @details 職業に応じて1~4種が固定、種族に応じて1種類が与えられ、後は重複なくランダムに選択される。
194 void get_virtues(void)
200 for (i = 0; i < 8; i++)
202 p_ptr->virtues[i] = 0;
203 p_ptr->vir_types[i] = 0;
208 /* Get pre-defined types */
209 /* 1 or more virtues based on class */
210 switch (p_ptr->pclass)
214 p_ptr->vir_types[i++] = V_VALOUR;
215 p_ptr->vir_types[i++] = V_HONOUR;
218 p_ptr->vir_types[i++] = V_KNOWLEDGE;
219 p_ptr->vir_types[i++] = V_ENCHANT;
222 p_ptr->vir_types[i++] = V_FAITH;
223 p_ptr->vir_types[i++] = V_TEMPERANCE;
227 p_ptr->vir_types[i++] = V_HONOUR;
231 p_ptr->vir_types[i++] = V_NATURE;
232 p_ptr->vir_types[i++] = V_TEMPERANCE;
235 p_ptr->vir_types[i++] = V_JUSTICE;
236 p_ptr->vir_types[i++] = V_VALOUR;
237 p_ptr->vir_types[i++] = V_HONOUR;
238 p_ptr->vir_types[i++] = V_FAITH;
240 case CLASS_WARRIOR_MAGE:
242 p_ptr->vir_types[i++] = V_ENCHANT;
243 p_ptr->vir_types[i++] = V_VALOUR;
245 case CLASS_CHAOS_WARRIOR:
246 p_ptr->vir_types[i++] = V_CHANCE;
247 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
250 case CLASS_FORCETRAINER:
251 p_ptr->vir_types[i++] = V_FAITH;
252 p_ptr->vir_types[i++] = V_HARMONY;
253 p_ptr->vir_types[i++] = V_TEMPERANCE;
254 p_ptr->vir_types[i++] = V_PATIENCE;
256 case CLASS_MINDCRAFTER:
257 case CLASS_MIRROR_MASTER:
258 p_ptr->vir_types[i++] = V_HARMONY;
259 p_ptr->vir_types[i++] = V_ENLIGHTEN;
260 p_ptr->vir_types[i++] = V_PATIENCE;
262 case CLASS_HIGH_MAGE:
264 p_ptr->vir_types[i++] = V_ENLIGHTEN;
265 p_ptr->vir_types[i++] = V_ENCHANT;
266 p_ptr->vir_types[i++] = V_KNOWLEDGE;
269 p_ptr->vir_types[i++] = V_ENLIGHTEN;
270 p_ptr->vir_types[i++] = V_CHANCE;
273 p_ptr->vir_types[i++] = V_CHANCE;
275 case CLASS_BLUE_MAGE:
276 p_ptr->vir_types[i++] = V_CHANCE;
277 p_ptr->vir_types[i++] = V_KNOWLEDGE;
279 case CLASS_BEASTMASTER:
280 p_ptr->vir_types[i++] = V_NATURE;
281 p_ptr->vir_types[i++] = V_CHANCE;
282 p_ptr->vir_types[i++] = V_VITALITY;
284 case CLASS_MAGIC_EATER:
285 p_ptr->vir_types[i++] = V_ENCHANT;
286 p_ptr->vir_types[i++] = V_KNOWLEDGE;
289 p_ptr->vir_types[i++] = V_HARMONY;
290 p_ptr->vir_types[i++] = V_COMPASSION;
293 p_ptr->vir_types[i++] = V_VALOUR;
294 p_ptr->vir_types[i++] = V_HARMONY;
296 case CLASS_BERSERKER:
297 p_ptr->vir_types[i++] = V_VALOUR;
298 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
301 p_ptr->vir_types[i++] = V_HONOUR;
302 p_ptr->vir_types[i++] = V_KNOWLEDGE;
305 p_ptr->vir_types[i++] = V_PATIENCE;
306 p_ptr->vir_types[i++] = V_KNOWLEDGE;
307 p_ptr->vir_types[i++] = V_FAITH;
308 p_ptr->vir_types[i++] = V_UNLIFE;
312 /* Get one virtue based on race */
313 switch (p_ptr->prace)
315 case RACE_HUMAN: case RACE_HALF_ELF: case RACE_DUNADAN:
316 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
318 case RACE_ELF: case RACE_SPRITE: case RACE_ENT:
319 p_ptr->vir_types[i++] = V_NATURE;
321 case RACE_HOBBIT: case RACE_HALF_OGRE:
322 p_ptr->vir_types[i++] = V_TEMPERANCE;
324 case RACE_DWARF: case RACE_KLACKON: case RACE_ANDROID:
325 p_ptr->vir_types[i++] = V_DILIGENCE;
327 case RACE_GNOME: case RACE_CYCLOPS:
328 p_ptr->vir_types[i++] = V_KNOWLEDGE;
330 case RACE_HALF_ORC: case RACE_AMBERITE: case RACE_KOBOLD:
331 p_ptr->vir_types[i++] = V_HONOUR;
333 case RACE_HALF_TROLL: case RACE_BARBARIAN:
334 p_ptr->vir_types[i++] = V_VALOUR;
336 case RACE_HIGH_ELF: case RACE_KUTAR:
337 p_ptr->vir_types[i++] = V_VITALITY;
339 case RACE_HALF_GIANT: case RACE_GOLEM: case RACE_ANGEL: case RACE_DEMON:
340 p_ptr->vir_types[i++] = V_JUSTICE;
342 case RACE_HALF_TITAN:
343 p_ptr->vir_types[i++] = V_HARMONY;
346 p_ptr->vir_types[i++] = V_SACRIFICE;
348 case RACE_MIND_FLAYER:
349 p_ptr->vir_types[i++] = V_ENLIGHTEN;
351 case RACE_DARK_ELF: case RACE_DRACONIAN: case RACE_S_FAIRY:
352 p_ptr->vir_types[i++] = V_ENCHANT;
355 p_ptr->vir_types[i++] = V_PATIENCE;
358 p_ptr->vir_types[i++] = V_FAITH;
360 case RACE_ZOMBIE: case RACE_SKELETON:
361 case RACE_VAMPIRE: case RACE_SPECTRE:
362 p_ptr->vir_types[i++] = V_UNLIFE;
365 p_ptr->vir_types[i++] = V_CHANCE;
369 /* Get a virtue for realms */
372 tmp_vir = get_realm_virtues(p_ptr->realm1);
373 if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir;
377 tmp_vir = get_realm_virtues(p_ptr->realm2);
378 if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir;
381 /* Eliminate doubles */
382 for (i = 0; i < 8; i++)
384 for (j = i + 1; j < 8; j++)
386 if ((p_ptr->vir_types[j] != 0) && (p_ptr->vir_types[j] == p_ptr->vir_types[i]))
387 p_ptr->vir_types[j] = 0;
391 /* Fill in the blanks */
392 for (i = 0; i < 8; i++)
394 if (p_ptr->vir_types[i] == 0) get_random_virtue(i);
399 * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。
400 * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。
405 void chg_virtue(int virtue_id, int amount)
409 for (i = 0; i < 8; i++)
411 if (p_ptr->vir_types[i] == virtue_id)
415 if ((amount + p_ptr->virtues[i] > 50) && one_in_(2))
417 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 50);
420 if ((amount + p_ptr->virtues[i] > 80) && one_in_(2))
422 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 80);
425 if ((amount + p_ptr->virtues[i] > 100) && one_in_(2))
427 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 100);
430 if (amount + p_ptr->virtues[i] > 125)
431 p_ptr->virtues[i] = 125;
433 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
437 if ((amount + p_ptr->virtues[i] < -50) && one_in_(2))
439 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -50);
442 if ((amount + p_ptr->virtues[i] < -80) && one_in_(2))
444 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -80);
447 if ((amount + p_ptr->virtues[i] < -100) && one_in_(2))
449 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -100);
452 if (amount + p_ptr->virtues[i] < -125)
453 p_ptr->virtues[i] = -125;
455 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
457 p_ptr->update |= (PU_BONUS);
464 * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする。
466 * @param amount セットしたい値。
469 void set_virtue(int virtue_id, int amount)
473 for (i = 0; i < 8; i++)
475 if (p_ptr->vir_types[i] == virtue_id)
477 p_ptr->virtues[i] = (s16b)amount;
485 * @param OutFile ファイルポインタ。
488 void dump_virtues(FILE *OutFile)
492 if (!OutFile) return;
494 for (v_nr = 0; v_nr < 8; v_nr++)
496 GAME_TEXT vir_name [20];
497 int tester = p_ptr->virtues[v_nr];
499 strcpy(vir_name, virtue[(p_ptr->vir_types[v_nr])-1]);
501 if (p_ptr->vir_types[v_nr] == 0 || p_ptr->vir_types[v_nr] > MAX_VIRTUE)
502 fprintf(OutFile, _("おっと。%sの情報なし。", "Oops. No info about %s."), vir_name);
504 else if (tester < -100)
505 fprintf(OutFile, _("[%s]の対極", "You are the polar opposite of %s."), vir_name);
506 else if (tester < -80)
507 fprintf(OutFile, _("[%s]の大敵", "You are an arch-enemy of %s."), vir_name);
508 else if (tester < -60)
509 fprintf(OutFile, _("[%s]の強敵", "You are a bitter enemy of %s."), vir_name);
510 else if (tester < -40)
511 fprintf(OutFile, _("[%s]の敵", "You are an enemy of %s."), vir_name);
512 else if (tester < -20)
513 fprintf(OutFile, _("[%s]の罪者", "You have sinned against %s."), vir_name);
515 fprintf(OutFile, _("[%s]の迷道者", "You have strayed from the path of %s."), vir_name);
516 else if (tester == 0)
517 fprintf(OutFile,_("[%s]の中立者", "You are neutral to %s."), vir_name);
518 else if (tester < 20)
519 fprintf(OutFile,_("[%s]の小徳者", "You are somewhat virtuous in %s."), vir_name);
520 else if (tester < 40)
521 fprintf(OutFile,_("[%s]の中徳者", "You are virtuous in %s."), vir_name);
522 else if (tester < 60)
523 fprintf(OutFile,_("[%s]の高徳者", "You are very virtuous in %s."), vir_name);
524 else if (tester < 80)
525 fprintf(OutFile,_("[%s]の覇者", "You are a champion of %s."), vir_name);
526 else if (tester < 100)
527 fprintf(OutFile,_("[%s]の偉大な覇者", "You are a great champion of %s."), vir_name);
529 fprintf(OutFile,_("[%s]の具現者", "You are the living embodiment of %s."), vir_name);
531 fprintf(OutFile, "\n");