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.
21 * 徳の名称 / The names of the virtues
23 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(int type, int num, int tekitou)
57 if (virtue_number(type))
58 vir = p_ptr->virtues[virtue_number(type) - 1];
65 if (vir > num) return TRUE;
68 if (vir < num) return TRUE;
76 * @brief プレイヤーの指定の徳が何番目のスロットに登録されているかを返す。 / Aux function
77 * @param type 確認したい徳のID
78 * @return スロットがあるならばスロットのID(0~7)+1、ない場合は0を返す。
80 int virtue_number(int type)
85 for (i = 0; i < 8; i++)
87 if (p_ptr->vir_types[i] == type) return i + 1;
95 * @brief プレイヤーの職業や種族に依存しないランダムな徳を取得する / Aux function
96 * @param which 確認したい徳のID
99 static void get_random_virtue(int which)
103 /* Randomly choose a type */
104 while (!(type) || virtue_number(type))
106 switch (randint1(29))
108 case 1: case 2: case 3:
111 case 4: case 5: case 6:
114 case 7: case 8: case 9: case 10: case 11: case 12:
117 case 13: case 14: case 15: case 16: case 17:
120 case 18: case 19: case 20: case 21:
129 case 26: case 27: case 28:
139 p_ptr->vir_types[which] = (s16b)type;
143 * @brief プレイヤーの選んだ魔法領域に応じて対応する徳を返す。
144 * @param realm 魔法領域のID
147 static VIRTUES_IDX get_realm_virtues(REALM_IDX realm)
152 if (virtue_number(V_VITALITY)) return V_TEMPERANCE;
153 else return V_VITALITY;
155 if (virtue_number(V_KNOWLEDGE)) return V_ENCHANT;
156 else return V_KNOWLEDGE;
158 if (virtue_number(V_NATURE)) return V_HARMONY;
159 else return V_NATURE;
161 if (virtue_number(V_CHANCE)) return V_INDIVIDUALISM;
162 else return V_CHANCE;
170 if (virtue_number(V_ENCHANT)) return V_INDIVIDUALISM;
171 else return V_ENCHANT;
173 if (virtue_number(V_JUSTICE)) return V_FAITH;
174 else return V_JUSTICE;
176 if (virtue_number(V_JUSTICE)) return V_HONOUR;
177 else return V_JUSTICE;
179 if (virtue_number(V_COMPASSION)) return V_JUSTICE;
180 else return V_COMPASSION;
188 * @brief 作成中のプレイヤーキャラクターに徳8種類を与える。 / Select virtues & reset values for a new character
189 * @details 職業に応じて1~4種が固定、種族に応じて1種類が与えられ、後は重複なくランダムに選択される。
192 void get_virtues(void)
198 for (i = 0; i < 8; i++)
200 p_ptr->virtues[i] = 0;
201 p_ptr->vir_types[i] = 0;
206 /* Get pre-defined types */
207 /* 1 or more virtues based on class */
208 switch (p_ptr->pclass)
212 p_ptr->vir_types[i++] = V_VALOUR;
213 p_ptr->vir_types[i++] = V_HONOUR;
216 p_ptr->vir_types[i++] = V_KNOWLEDGE;
217 p_ptr->vir_types[i++] = V_ENCHANT;
220 p_ptr->vir_types[i++] = V_FAITH;
221 p_ptr->vir_types[i++] = V_TEMPERANCE;
225 p_ptr->vir_types[i++] = V_HONOUR;
229 p_ptr->vir_types[i++] = V_NATURE;
230 p_ptr->vir_types[i++] = V_TEMPERANCE;
233 p_ptr->vir_types[i++] = V_JUSTICE;
234 p_ptr->vir_types[i++] = V_VALOUR;
235 p_ptr->vir_types[i++] = V_HONOUR;
236 p_ptr->vir_types[i++] = V_FAITH;
238 case CLASS_WARRIOR_MAGE:
240 p_ptr->vir_types[i++] = V_ENCHANT;
241 p_ptr->vir_types[i++] = V_VALOUR;
243 case CLASS_CHAOS_WARRIOR:
244 p_ptr->vir_types[i++] = V_CHANCE;
245 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
248 case CLASS_FORCETRAINER:
249 p_ptr->vir_types[i++] = V_FAITH;
250 p_ptr->vir_types[i++] = V_HARMONY;
251 p_ptr->vir_types[i++] = V_TEMPERANCE;
252 p_ptr->vir_types[i++] = V_PATIENCE;
254 case CLASS_MINDCRAFTER:
255 case CLASS_MIRROR_MASTER:
256 p_ptr->vir_types[i++] = V_HARMONY;
257 p_ptr->vir_types[i++] = V_ENLIGHTEN;
258 p_ptr->vir_types[i++] = V_PATIENCE;
260 case CLASS_HIGH_MAGE:
262 p_ptr->vir_types[i++] = V_ENLIGHTEN;
263 p_ptr->vir_types[i++] = V_ENCHANT;
264 p_ptr->vir_types[i++] = V_KNOWLEDGE;
267 p_ptr->vir_types[i++] = V_ENLIGHTEN;
268 p_ptr->vir_types[i++] = V_CHANCE;
271 p_ptr->vir_types[i++] = V_CHANCE;
273 case CLASS_BLUE_MAGE:
274 p_ptr->vir_types[i++] = V_CHANCE;
275 p_ptr->vir_types[i++] = V_KNOWLEDGE;
277 case CLASS_BEASTMASTER:
278 p_ptr->vir_types[i++] = V_NATURE;
279 p_ptr->vir_types[i++] = V_CHANCE;
280 p_ptr->vir_types[i++] = V_VITALITY;
282 case CLASS_MAGIC_EATER:
283 p_ptr->vir_types[i++] = V_ENCHANT;
284 p_ptr->vir_types[i++] = V_KNOWLEDGE;
287 p_ptr->vir_types[i++] = V_HARMONY;
288 p_ptr->vir_types[i++] = V_COMPASSION;
291 p_ptr->vir_types[i++] = V_VALOUR;
292 p_ptr->vir_types[i++] = V_HARMONY;
294 case CLASS_BERSERKER:
295 p_ptr->vir_types[i++] = V_VALOUR;
296 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
299 p_ptr->vir_types[i++] = V_HONOUR;
300 p_ptr->vir_types[i++] = V_KNOWLEDGE;
303 p_ptr->vir_types[i++] = V_PATIENCE;
304 p_ptr->vir_types[i++] = V_KNOWLEDGE;
305 p_ptr->vir_types[i++] = V_FAITH;
306 p_ptr->vir_types[i++] = V_UNLIFE;
310 /* Get one virtue based on race */
311 switch (p_ptr->prace)
313 case RACE_HUMAN: case RACE_HALF_ELF: case RACE_DUNADAN:
314 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
316 case RACE_ELF: case RACE_SPRITE: case RACE_ENT:
317 p_ptr->vir_types[i++] = V_NATURE;
319 case RACE_HOBBIT: case RACE_HALF_OGRE:
320 p_ptr->vir_types[i++] = V_TEMPERANCE;
322 case RACE_DWARF: case RACE_KLACKON: case RACE_ANDROID:
323 p_ptr->vir_types[i++] = V_DILIGENCE;
325 case RACE_GNOME: case RACE_CYCLOPS:
326 p_ptr->vir_types[i++] = V_KNOWLEDGE;
328 case RACE_HALF_ORC: case RACE_AMBERITE: case RACE_KOBOLD:
329 p_ptr->vir_types[i++] = V_HONOUR;
331 case RACE_HALF_TROLL: case RACE_BARBARIAN:
332 p_ptr->vir_types[i++] = V_VALOUR;
334 case RACE_HIGH_ELF: case RACE_KUTAR:
335 p_ptr->vir_types[i++] = V_VITALITY;
337 case RACE_HALF_GIANT: case RACE_GOLEM: case RACE_ANGEL: case RACE_DEMON:
338 p_ptr->vir_types[i++] = V_JUSTICE;
340 case RACE_HALF_TITAN:
341 p_ptr->vir_types[i++] = V_HARMONY;
344 p_ptr->vir_types[i++] = V_SACRIFICE;
346 case RACE_MIND_FLAYER:
347 p_ptr->vir_types[i++] = V_ENLIGHTEN;
349 case RACE_DARK_ELF: case RACE_DRACONIAN: case RACE_S_FAIRY:
350 p_ptr->vir_types[i++] = V_ENCHANT;
353 p_ptr->vir_types[i++] = V_PATIENCE;
356 p_ptr->vir_types[i++] = V_FAITH;
358 case RACE_ZOMBIE: case RACE_SKELETON:
359 case RACE_VAMPIRE: case RACE_SPECTRE:
360 p_ptr->vir_types[i++] = V_UNLIFE;
363 p_ptr->vir_types[i++] = V_CHANCE;
367 /* Get a virtue for realms */
370 tmp_vir = get_realm_virtues(p_ptr->realm1);
371 if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir;
375 tmp_vir = get_realm_virtues(p_ptr->realm2);
376 if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir;
379 /* Eliminate doubles */
380 for (i = 0; i < 8; i++)
382 for (j = i + 1; j < 8; j++)
384 if ((p_ptr->vir_types[j] != 0) && (p_ptr->vir_types[j] == p_ptr->vir_types[i]))
385 p_ptr->vir_types[j] = 0;
389 /* Fill in the blanks */
390 for (i = 0; i < 8; i++)
392 if (p_ptr->vir_types[i] == 0) get_random_virtue(i);
397 * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。
398 * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。
403 void chg_virtue(int virtue_id, int amount)
407 for (i = 0; i < 8; i++)
409 if (p_ptr->vir_types[i] == virtue_id)
413 if ((amount + p_ptr->virtues[i] > 50) && one_in_(2))
415 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 50);
418 if ((amount + p_ptr->virtues[i] > 80) && one_in_(2))
420 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 80);
423 if ((amount + p_ptr->virtues[i] > 100) && one_in_(2))
425 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 100);
428 if (amount + p_ptr->virtues[i] > 125)
429 p_ptr->virtues[i] = 125;
431 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
435 if ((amount + p_ptr->virtues[i] < -50) && one_in_(2))
437 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -50);
440 if ((amount + p_ptr->virtues[i] < -80) && one_in_(2))
442 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -80);
445 if ((amount + p_ptr->virtues[i] < -100) && one_in_(2))
447 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -100);
450 if (amount + p_ptr->virtues[i] < -125)
451 p_ptr->virtues[i] = -125;
453 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
455 p_ptr->update |= (PU_BONUS);
462 * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする。
464 * @param amount セットしたい値。
467 void set_virtue(int virtue_id, int amount)
471 for (i = 0; i < 8; i++)
473 if (p_ptr->vir_types[i] == virtue_id)
475 p_ptr->virtues[i] = (s16b)amount;
483 * @param OutFile ファイルポインタ。
486 void dump_virtues(FILE *OutFile)
490 if (!OutFile) return;
492 for (v_nr = 0; v_nr < 8; v_nr++)
494 GAME_TEXT vir_name [20];
495 int tester = p_ptr->virtues[v_nr];
497 strcpy(vir_name, virtue[(p_ptr->vir_types[v_nr])-1]);
499 if (p_ptr->vir_types[v_nr] == 0 || p_ptr->vir_types[v_nr] > MAX_VIRTUE)
500 fprintf(OutFile, _("おっと。%sの情報なし。", "Oops. No info about %s."), vir_name);
502 else if (tester < -100)
503 fprintf(OutFile, _("[%s]の対極", "You are the polar opposite of %s."), vir_name);
504 else if (tester < -80)
505 fprintf(OutFile, _("[%s]の大敵", "You are an arch-enemy of %s."), vir_name);
506 else if (tester < -60)
507 fprintf(OutFile, _("[%s]の強敵", "You are a bitter enemy of %s."), vir_name);
508 else if (tester < -40)
509 fprintf(OutFile, _("[%s]の敵", "You are an enemy of %s."), vir_name);
510 else if (tester < -20)
511 fprintf(OutFile, _("[%s]の罪者", "You have sinned against %s."), vir_name);
513 fprintf(OutFile, _("[%s]の迷道者", "You have strayed from the path of %s."), vir_name);
514 else if (tester == 0)
515 fprintf(OutFile,_("[%s]の中立者", "You are neutral to %s."), vir_name);
516 else if (tester < 20)
517 fprintf(OutFile,_("[%s]の小徳者", "You are somewhat virtuous in %s."), vir_name);
518 else if (tester < 40)
519 fprintf(OutFile,_("[%s]の中徳者", "You are virtuous in %s."), vir_name);
520 else if (tester < 60)
521 fprintf(OutFile,_("[%s]の高徳者", "You are very virtuous in %s."), vir_name);
522 else if (tester < 80)
523 fprintf(OutFile,_("[%s]の覇者", "You are a champion of %s."), vir_name);
524 else if (tester < 100)
525 fprintf(OutFile,_("[%s]の偉大な覇者", "You are a great champion of %s."), vir_name);
527 fprintf(OutFile,_("[%s]の具現者", "You are the living embodiment of %s."), vir_name);
529 fprintf(OutFile, "\n");