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(player_type *creature_ptr, int type, int num, int tekitou)
59 if (virtue_number(creature_ptr, type))
60 vir = creature_ptr->virtues[virtue_number(creature_ptr, 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(player_type *creature_ptr, int type)
87 for (i = 0; i < 8; i++)
89 if (creature_ptr->vir_types[i] == type) return i + 1;
97 * @brief プレイヤーの職業や種族に依存しないランダムな徳を取得する / Aux function
98 * @param which 確認したい徳のID
101 static void get_random_virtue(player_type *creature_ptr, int which)
105 /* Randomly choose a type */
106 while (!(type) || virtue_number(creature_ptr, 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 creature_ptr->vir_types[which] = (s16b)type;
145 * @brief プレイヤーの選んだ魔法領域に応じて対応する徳を返す。
146 * @param realm 魔法領域のID
149 static VIRTUES_IDX get_realm_virtues(player_type *creature_ptr, REALM_IDX realm)
154 if (virtue_number(creature_ptr, V_VITALITY)) return V_TEMPERANCE;
155 else return V_VITALITY;
157 if (virtue_number(creature_ptr, V_KNOWLEDGE)) return V_ENCHANT;
158 else return V_KNOWLEDGE;
160 if (virtue_number(creature_ptr, V_NATURE)) return V_HARMONY;
161 else return V_NATURE;
163 if (virtue_number(creature_ptr, V_CHANCE)) return V_INDIVIDUALISM;
164 else return V_CHANCE;
172 if (virtue_number(creature_ptr, V_ENCHANT)) return V_INDIVIDUALISM;
173 else return V_ENCHANT;
175 if (virtue_number(creature_ptr, V_JUSTICE)) return V_FAITH;
176 else return V_JUSTICE;
178 if (virtue_number(creature_ptr, V_JUSTICE)) return V_HONOUR;
179 else return V_JUSTICE;
181 if (virtue_number(creature_ptr, 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(player_type *creature_ptr)
200 for (i = 0; i < 8; i++)
202 creature_ptr->virtues[i] = 0;
203 creature_ptr->vir_types[i] = 0;
208 /* Get pre-defined types */
209 /* 1 or more virtues based on class */
210 switch (creature_ptr->pclass)
214 creature_ptr->vir_types[i++] = V_VALOUR;
215 creature_ptr->vir_types[i++] = V_HONOUR;
218 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
219 creature_ptr->vir_types[i++] = V_ENCHANT;
222 creature_ptr->vir_types[i++] = V_FAITH;
223 creature_ptr->vir_types[i++] = V_TEMPERANCE;
227 creature_ptr->vir_types[i++] = V_HONOUR;
231 creature_ptr->vir_types[i++] = V_NATURE;
232 creature_ptr->vir_types[i++] = V_TEMPERANCE;
235 creature_ptr->vir_types[i++] = V_JUSTICE;
236 creature_ptr->vir_types[i++] = V_VALOUR;
237 creature_ptr->vir_types[i++] = V_HONOUR;
238 creature_ptr->vir_types[i++] = V_FAITH;
240 case CLASS_WARRIOR_MAGE:
242 creature_ptr->vir_types[i++] = V_ENCHANT;
243 creature_ptr->vir_types[i++] = V_VALOUR;
245 case CLASS_CHAOS_WARRIOR:
246 creature_ptr->vir_types[i++] = V_CHANCE;
247 creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
250 case CLASS_FORCETRAINER:
251 creature_ptr->vir_types[i++] = V_FAITH;
252 creature_ptr->vir_types[i++] = V_HARMONY;
253 creature_ptr->vir_types[i++] = V_TEMPERANCE;
254 creature_ptr->vir_types[i++] = V_PATIENCE;
256 case CLASS_MINDCRAFTER:
257 case CLASS_MIRROR_MASTER:
258 creature_ptr->vir_types[i++] = V_HARMONY;
259 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
260 creature_ptr->vir_types[i++] = V_PATIENCE;
262 case CLASS_HIGH_MAGE:
264 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
265 creature_ptr->vir_types[i++] = V_ENCHANT;
266 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
269 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
270 creature_ptr->vir_types[i++] = V_CHANCE;
273 creature_ptr->vir_types[i++] = V_CHANCE;
275 case CLASS_BLUE_MAGE:
276 creature_ptr->vir_types[i++] = V_CHANCE;
277 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
279 case CLASS_BEASTMASTER:
280 creature_ptr->vir_types[i++] = V_NATURE;
281 creature_ptr->vir_types[i++] = V_CHANCE;
282 creature_ptr->vir_types[i++] = V_VITALITY;
284 case CLASS_MAGIC_EATER:
285 creature_ptr->vir_types[i++] = V_ENCHANT;
286 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
289 creature_ptr->vir_types[i++] = V_HARMONY;
290 creature_ptr->vir_types[i++] = V_COMPASSION;
293 creature_ptr->vir_types[i++] = V_VALOUR;
294 creature_ptr->vir_types[i++] = V_HARMONY;
296 case CLASS_BERSERKER:
297 creature_ptr->vir_types[i++] = V_VALOUR;
298 creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
301 creature_ptr->vir_types[i++] = V_HONOUR;
302 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
305 creature_ptr->vir_types[i++] = V_PATIENCE;
306 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
307 creature_ptr->vir_types[i++] = V_FAITH;
308 creature_ptr->vir_types[i++] = V_UNLIFE;
312 /* Get one virtue based on race */
313 switch (creature_ptr->prace)
315 case RACE_HUMAN: case RACE_HALF_ELF: case RACE_DUNADAN:
316 creature_ptr->vir_types[i++] = V_INDIVIDUALISM;
318 case RACE_ELF: case RACE_SPRITE: case RACE_ENT:
319 creature_ptr->vir_types[i++] = V_NATURE;
321 case RACE_HOBBIT: case RACE_HALF_OGRE:
322 creature_ptr->vir_types[i++] = V_TEMPERANCE;
324 case RACE_DWARF: case RACE_KLACKON: case RACE_ANDROID:
325 creature_ptr->vir_types[i++] = V_DILIGENCE;
327 case RACE_GNOME: case RACE_CYCLOPS:
328 creature_ptr->vir_types[i++] = V_KNOWLEDGE;
330 case RACE_HALF_ORC: case RACE_AMBERITE: case RACE_KOBOLD:
331 creature_ptr->vir_types[i++] = V_HONOUR;
333 case RACE_HALF_TROLL: case RACE_BARBARIAN:
334 creature_ptr->vir_types[i++] = V_VALOUR;
336 case RACE_HIGH_ELF: case RACE_KUTAR:
337 creature_ptr->vir_types[i++] = V_VITALITY;
339 case RACE_HALF_GIANT: case RACE_GOLEM: case RACE_ANGEL: case RACE_DEMON:
340 creature_ptr->vir_types[i++] = V_JUSTICE;
342 case RACE_HALF_TITAN:
343 creature_ptr->vir_types[i++] = V_HARMONY;
346 creature_ptr->vir_types[i++] = V_SACRIFICE;
348 case RACE_MIND_FLAYER:
349 creature_ptr->vir_types[i++] = V_ENLIGHTEN;
351 case RACE_DARK_ELF: case RACE_DRACONIAN: case RACE_S_FAIRY:
352 creature_ptr->vir_types[i++] = V_ENCHANT;
355 creature_ptr->vir_types[i++] = V_PATIENCE;
358 creature_ptr->vir_types[i++] = V_FAITH;
360 case RACE_ZOMBIE: case RACE_SKELETON:
361 case RACE_VAMPIRE: case RACE_SPECTRE:
362 creature_ptr->vir_types[i++] = V_UNLIFE;
365 creature_ptr->vir_types[i++] = V_CHANCE;
369 /* Get a virtue for realms */
370 if (creature_ptr->realm1)
372 tmp_vir = get_realm_virtues(creature_ptr, creature_ptr->realm1);
373 if (tmp_vir) creature_ptr->vir_types[i++] = tmp_vir;
375 if (creature_ptr->realm2)
377 tmp_vir = get_realm_virtues(creature_ptr, creature_ptr->realm2);
378 if (tmp_vir) creature_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 ((creature_ptr->vir_types[j] != 0) && (creature_ptr->vir_types[j] == creature_ptr->vir_types[i]))
387 creature_ptr->vir_types[j] = 0;
391 /* Fill in the blanks */
392 for (i = 0; i < 8; i++)
394 if (creature_ptr->vir_types[i] == 0) get_random_virtue(creature_ptr, i);
399 * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。
400 * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。
405 void chg_virtue(player_type *creature_ptr, int virtue_id, int amount)
409 for (i = 0; i < 8; i++)
411 if (creature_ptr->vir_types[i] == virtue_id)
415 if ((amount + creature_ptr->virtues[i] > 50) && one_in_(2))
417 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 50);
420 if ((amount + creature_ptr->virtues[i] > 80) && one_in_(2))
422 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 80);
425 if ((amount + creature_ptr->virtues[i] > 100) && one_in_(2))
427 creature_ptr->virtues[i] = MAX(creature_ptr->virtues[i], 100);
430 if (amount + creature_ptr->virtues[i] > 125)
431 creature_ptr->virtues[i] = 125;
433 creature_ptr->virtues[i] = creature_ptr->virtues[i] + amount;
437 if ((amount + creature_ptr->virtues[i] < -50) && one_in_(2))
439 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -50);
442 if ((amount + creature_ptr->virtues[i] < -80) && one_in_(2))
444 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -80);
447 if ((amount + creature_ptr->virtues[i] < -100) && one_in_(2))
449 creature_ptr->virtues[i] = MIN(creature_ptr->virtues[i], -100);
452 if (amount + creature_ptr->virtues[i] < -125)
453 creature_ptr->virtues[i] = -125;
455 creature_ptr->virtues[i] = creature_ptr->virtues[i] + amount;
457 creature_ptr->update |= (PU_BONUS);
464 * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする。
466 * @param amount セットしたい値。
469 void set_virtue(player_type *creature_ptr, int virtue_id, int amount)
473 for (i = 0; i < 8; i++)
475 if (creature_ptr->vir_types[i] == virtue_id)
477 creature_ptr->virtues[i] = (s16b)amount;
485 * @param OutFile ファイルポインタ。
488 void dump_virtues(player_type *creature_ptr, 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 = creature_ptr->virtues[v_nr];
499 strcpy(vir_name, virtue[(creature_ptr->vir_types[v_nr])-1]);
501 if (creature_ptr->vir_types[v_nr] == 0 || creature_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");