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.
20 * 徳の名称 / The names of the virtues
22 cptr virtue[MAX_VIRTUE] =
30 _("啓", "Enlightenment"),
41 _("個", "Individualism"),
45 * @brief 該当の徳がプレイヤーに指定されているか否かに応じつつ、大小を比較する。
46 * @details 徳がない場合は値0として比較する。
47 * @param type 比較したい徳のID
49 * @param tekitou VIRTUE_LARGE = 基準値より大きいか / VIRTUE_SMALL = 基準値より小さいか
53 bool compare_virtue(int type, int num, int tekitou)
56 if (virtue_number(type))
57 vir = p_ptr->virtues[virtue_number(type) - 1];
64 if (vir > num) return TRUE;
67 if (vir < num) return TRUE;
75 * @brief プレイヤーの指定の徳が何番目のスロットに登録されているかを返す。 / Aux function
76 * @param type 確認したい徳のID
77 * @return スロットがあるならばスロットのID(0~7)+1、ない場合は0を返す。
79 int virtue_number(int type)
84 for (i = 0; i < 8; i++)
86 if (p_ptr->vir_types[i] == type) return i + 1;
94 * @brief プレイヤーの職業や種族に依存しないランダムな徳を取得する / Aux function
95 * @param which 確認したい徳のID
98 static void get_random_virtue(int which)
102 /* Randomly choose a type */
103 while (!(type) || virtue_number(type))
105 switch (randint1(29))
107 case 1: case 2: case 3:
110 case 4: case 5: case 6:
113 case 7: case 8: case 9: case 10: case 11: case 12:
116 case 13: case 14: case 15: case 16: case 17:
119 case 18: case 19: case 20: case 21:
128 case 26: case 27: case 28:
138 p_ptr->vir_types[which] = type;
142 * @brief プレイヤーの選んだ魔法領域に応じて対応する徳を返す。
143 * @param realm 魔法領域のID
146 static s16b get_realm_virtues(byte realm)
151 if (virtue_number(V_VITALITY)) return V_TEMPERANCE;
152 else return V_VITALITY;
154 if (virtue_number(V_KNOWLEDGE)) return V_ENCHANT;
155 else return V_KNOWLEDGE;
157 if (virtue_number(V_NATURE)) return V_HARMONY;
158 else return V_NATURE;
160 if (virtue_number(V_CHANCE)) return V_INDIVIDUALISM;
161 else return V_CHANCE;
169 if (virtue_number(V_ENCHANT)) return V_INDIVIDUALISM;
170 else return V_ENCHANT;
172 if (virtue_number(V_JUSTICE)) return V_FAITH;
173 else return V_JUSTICE;
175 if (virtue_number(V_JUSTICE)) return V_HONOUR;
176 else return V_JUSTICE;
178 if (virtue_number(V_COMPASSION)) return V_JUSTICE;
179 else return V_COMPASSION;
187 * @brief 作成中のプレイヤーキャラクターに徳8種類を与える。 / Select virtues & reset values for a new character
188 * @details 職業に応じて1~4種が固定、種族に応じて1種類が与えられ、後は重複なくランダムに選択される。
191 void get_virtues(void)
197 for (i = 0; i < 8; i++)
199 p_ptr->virtues[i] = 0;
200 p_ptr->vir_types[i] = 0;
205 /* Get pre-defined types */
206 /* 1 or more virtues based on class */
207 switch (p_ptr->pclass)
211 p_ptr->vir_types[i++] = V_VALOUR;
212 p_ptr->vir_types[i++] = V_HONOUR;
215 p_ptr->vir_types[i++] = V_KNOWLEDGE;
216 p_ptr->vir_types[i++] = V_ENCHANT;
219 p_ptr->vir_types[i++] = V_FAITH;
220 p_ptr->vir_types[i++] = V_TEMPERANCE;
224 p_ptr->vir_types[i++] = V_HONOUR;
228 p_ptr->vir_types[i++] = V_NATURE;
229 p_ptr->vir_types[i++] = V_TEMPERANCE;
232 p_ptr->vir_types[i++] = V_JUSTICE;
233 p_ptr->vir_types[i++] = V_VALOUR;
234 p_ptr->vir_types[i++] = V_HONOUR;
235 p_ptr->vir_types[i++] = V_FAITH;
237 case CLASS_WARRIOR_MAGE:
239 p_ptr->vir_types[i++] = V_ENCHANT;
240 p_ptr->vir_types[i++] = V_VALOUR;
242 case CLASS_CHAOS_WARRIOR:
243 p_ptr->vir_types[i++] = V_CHANCE;
244 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
247 case CLASS_FORCETRAINER:
248 p_ptr->vir_types[i++] = V_FAITH;
249 p_ptr->vir_types[i++] = V_HARMONY;
250 p_ptr->vir_types[i++] = V_TEMPERANCE;
251 p_ptr->vir_types[i++] = V_PATIENCE;
253 case CLASS_MINDCRAFTER:
254 case CLASS_MIRROR_MASTER:
255 p_ptr->vir_types[i++] = V_HARMONY;
256 p_ptr->vir_types[i++] = V_ENLIGHTEN;
257 p_ptr->vir_types[i++] = V_PATIENCE;
259 case CLASS_HIGH_MAGE:
261 p_ptr->vir_types[i++] = V_ENLIGHTEN;
262 p_ptr->vir_types[i++] = V_ENCHANT;
263 p_ptr->vir_types[i++] = V_KNOWLEDGE;
266 p_ptr->vir_types[i++] = V_ENLIGHTEN;
267 p_ptr->vir_types[i++] = V_CHANCE;
270 p_ptr->vir_types[i++] = V_CHANCE;
272 case CLASS_BLUE_MAGE:
273 p_ptr->vir_types[i++] = V_CHANCE;
274 p_ptr->vir_types[i++] = V_KNOWLEDGE;
276 case CLASS_BEASTMASTER:
277 p_ptr->vir_types[i++] = V_NATURE;
278 p_ptr->vir_types[i++] = V_CHANCE;
279 p_ptr->vir_types[i++] = V_VITALITY;
281 case CLASS_MAGIC_EATER:
282 p_ptr->vir_types[i++] = V_ENCHANT;
283 p_ptr->vir_types[i++] = V_KNOWLEDGE;
286 p_ptr->vir_types[i++] = V_HARMONY;
287 p_ptr->vir_types[i++] = V_COMPASSION;
290 p_ptr->vir_types[i++] = V_VALOUR;
291 p_ptr->vir_types[i++] = V_HARMONY;
293 case CLASS_BERSERKER:
294 p_ptr->vir_types[i++] = V_VALOUR;
295 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
298 p_ptr->vir_types[i++] = V_HONOUR;
299 p_ptr->vir_types[i++] = V_KNOWLEDGE;
302 p_ptr->vir_types[i++] = V_PATIENCE;
303 p_ptr->vir_types[i++] = V_KNOWLEDGE;
304 p_ptr->vir_types[i++] = V_FAITH;
305 p_ptr->vir_types[i++] = V_UNLIFE;
309 /* Get one virtue based on race */
310 switch (p_ptr->prace)
312 case RACE_HUMAN: case RACE_HALF_ELF: case RACE_DUNADAN:
313 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
315 case RACE_ELF: case RACE_SPRITE: case RACE_ENT:
316 p_ptr->vir_types[i++] = V_NATURE;
318 case RACE_HOBBIT: case RACE_HALF_OGRE:
319 p_ptr->vir_types[i++] = V_TEMPERANCE;
321 case RACE_DWARF: case RACE_KLACKON: case RACE_ANDROID:
322 p_ptr->vir_types[i++] = V_DILIGENCE;
324 case RACE_GNOME: case RACE_CYCLOPS:
325 p_ptr->vir_types[i++] = V_KNOWLEDGE;
327 case RACE_HALF_ORC: case RACE_AMBERITE: case RACE_KOBOLD:
328 p_ptr->vir_types[i++] = V_HONOUR;
330 case RACE_HALF_TROLL: case RACE_BARBARIAN:
331 p_ptr->vir_types[i++] = V_VALOUR;
333 case RACE_HIGH_ELF: case RACE_KUTAR:
334 p_ptr->vir_types[i++] = V_VITALITY;
336 case RACE_HALF_GIANT: case RACE_GOLEM: case RACE_ANGEL: case RACE_DEMON:
337 p_ptr->vir_types[i++] = V_JUSTICE;
339 case RACE_HALF_TITAN:
340 p_ptr->vir_types[i++] = V_HARMONY;
343 p_ptr->vir_types[i++] = V_SACRIFICE;
345 case RACE_MIND_FLAYER:
346 p_ptr->vir_types[i++] = V_ENLIGHTEN;
348 case RACE_DARK_ELF: case RACE_DRACONIAN: case RACE_S_FAIRY:
349 p_ptr->vir_types[i++] = V_ENCHANT;
352 p_ptr->vir_types[i++] = V_PATIENCE;
355 p_ptr->vir_types[i++] = V_FAITH;
357 case RACE_ZOMBIE: case RACE_SKELETON:
358 case RACE_VAMPIRE: case RACE_SPECTRE:
359 p_ptr->vir_types[i++] = V_UNLIFE;
362 p_ptr->vir_types[i++] = V_CHANCE;
366 /* Get a virtue for realms */
369 tmp_vir = get_realm_virtues(p_ptr->realm1);
370 if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir;
374 tmp_vir = get_realm_virtues(p_ptr->realm2);
375 if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir;
378 /* Eliminate doubles */
379 for (i = 0; i < 8; i++)
381 for (j = i + 1; j < 8; j++)
383 if ((p_ptr->vir_types[j] != 0) && (p_ptr->vir_types[j] == p_ptr->vir_types[i]))
384 p_ptr->vir_types[j] = 0;
388 /* Fill in the blanks */
389 for (i = 0; i < 8; i++)
391 if (p_ptr->vir_types[i] == 0) get_random_virtue(i);
396 * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。
397 * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。
402 void chg_virtue(int virtue_id, int amount)
406 for (i = 0; i < 8; i++)
408 if (p_ptr->vir_types[i] == virtue_id)
412 if ((amount + p_ptr->virtues[i] > 50) && one_in_(2))
414 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 50);
417 if ((amount + p_ptr->virtues[i] > 80) && one_in_(2))
419 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 80);
422 if ((amount + p_ptr->virtues[i] > 100) && one_in_(2))
424 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 100);
427 if (amount + p_ptr->virtues[i] > 125)
428 p_ptr->virtues[i] = 125;
430 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
434 if ((amount + p_ptr->virtues[i] < -50) && one_in_(2))
436 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -50);
439 if ((amount + p_ptr->virtues[i] < -80) && one_in_(2))
441 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -80);
444 if ((amount + p_ptr->virtues[i] < -100) && one_in_(2))
446 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -100);
449 if (amount + p_ptr->virtues[i] < -125)
450 p_ptr->virtues[i] = -125;
452 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
454 p_ptr->update |= (PU_BONUS);
461 * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする。
463 * @param amount セットしたい値。
466 void set_virtue(int virtue_id, int amount)
470 for (i = 0; i < 8; i++)
472 if (p_ptr->vir_types[i] == virtue_id)
474 p_ptr->virtues[i] = amount;
482 * @param OutFile ファイルポインタ。
485 void dump_virtues(FILE *OutFile)
489 if (!OutFile) return;
491 for (v_nr = 0; v_nr < 8; v_nr++)
494 int tester = p_ptr->virtues[v_nr];
496 strcpy(vir_name, virtue[(p_ptr->vir_types[v_nr])-1]);
498 if (p_ptr->vir_types[v_nr] == 0 || p_ptr->vir_types[v_nr] > MAX_VIRTUE)
499 fprintf(OutFile, _("おっと。%sの情報なし。", "Oops. No info about %s."), vir_name);
501 else if (tester < -100)
502 fprintf(OutFile, _("[%s]の対極", "You are the polar opposite of %s."), vir_name);
503 else if (tester < -80)
504 fprintf(OutFile, _("[%s]の大敵", "You are an arch-enemy of %s."), vir_name);
505 else if (tester < -60)
506 fprintf(OutFile, _("[%s]の強敵", "You are a bitter enemy of %s."), vir_name);
507 else if (tester < -40)
508 fprintf(OutFile, _("[%s]の敵", "You are an enemy of %s."), vir_name);
509 else if (tester < -20)
510 fprintf(OutFile, _("[%s]の罪者", "You have sinned against %s."), vir_name);
512 fprintf(OutFile, _("[%s]の迷道者", "You have strayed from the path of %s."), vir_name);
513 else if (tester == 0)
514 fprintf(OutFile,_("[%s]の中立者", "You are neutral to %s."), vir_name);
515 else if (tester < 20)
516 fprintf(OutFile,_("[%s]の小徳者", "You are somewhat virtuous in %s."), vir_name);
517 else if (tester < 40)
518 fprintf(OutFile,_("[%s]の中徳者", "You are virtuous in %s."), vir_name);
519 else if (tester < 60)
520 fprintf(OutFile,_("[%s]の高徳者", "You are very virtuous in %s."), vir_name);
521 else if (tester < 80)
522 fprintf(OutFile,_("[%s]の覇者", "You are a champion of %s."), vir_name);
523 else if (tester < 100)
524 fprintf(OutFile,_("[%s]の偉大な覇者", "You are a great champion of %s."), vir_name);
526 fprintf(OutFile,_("[%s]の具現者", "You are the living embodiment of %s."), vir_name);
528 fprintf(OutFile, "\n");