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] =
66 * @brief 該当の徳がプレイヤーに指定されているか否かに応じつつ、大小を比較する。
67 * @details 徳がない場合は値0として比較する。
68 * @param type 比較したい徳のID
70 * @param tekitou VIRTUE_LARGE = 基準値より大きいか / VIRTUE_SMALL = 基準値より小さいか
74 bool compare_virtue(int type, int num, int tekitou)
77 if (virtue_number(type))
78 vir = p_ptr->virtues[virtue_number(type) - 1];
85 if (vir > num) return TRUE;
88 if (vir < num) return TRUE;
96 * @brief プレイヤーの指定の徳が何番目のスロットに登録されているかを返す。 / Aux function
97 * @param type 確認したい徳のID
98 * @return スロットがあるならばスロットのID(0~7)+1、ない場合は0を返す。
100 int virtue_number(int type)
105 for (i = 0; i < 8; i++)
107 if (p_ptr->vir_types[i] == type) return i + 1;
115 * @brief プレイヤーの職業や種族に依存しないランダムな徳を取得する / Aux function
116 * @param which 確認したい徳のID
119 static void get_random_virtue(int which)
123 /* Randomly choose a type */
124 while (!(type) || virtue_number(type))
126 switch (randint1(29))
128 case 1: case 2: case 3:
131 case 4: case 5: case 6:
134 case 7: case 8: case 9: case 10: case 11: case 12:
137 case 13: case 14: case 15: case 16: case 17:
140 case 18: case 19: case 20: case 21:
149 case 26: case 27: case 28:
159 p_ptr->vir_types[which] = type;
163 * @brief プレイヤーの選んだ魔法領域に応じて対応する徳を返す。
164 * @param realm 魔法領域のID
167 static s16b get_realm_virtues(byte realm)
172 if (virtue_number(V_VITALITY)) return V_TEMPERANCE;
173 else return V_VITALITY;
175 if (virtue_number(V_KNOWLEDGE)) return V_ENCHANT;
176 else return V_KNOWLEDGE;
178 if (virtue_number(V_NATURE)) return V_HARMONY;
179 else return V_NATURE;
181 if (virtue_number(V_CHANCE)) return V_INDIVIDUALISM;
182 else return V_CHANCE;
190 if (virtue_number(V_ENCHANT)) return V_INDIVIDUALISM;
191 else return V_ENCHANT;
193 if (virtue_number(V_JUSTICE)) return V_FAITH;
194 else return V_JUSTICE;
196 if (virtue_number(V_JUSTICE)) return V_HONOUR;
197 else return V_JUSTICE;
199 if (virtue_number(V_COMPASSION)) return V_JUSTICE;
200 else return V_COMPASSION;
208 * @brief 作成中のプレイヤーキャラクターに徳8種類を与える。 / Select virtues & reset values for a new character
209 * @details 職業に応じて1~4種が固定、種族に応じて1種類が与えられ、後は重複なくランダムに選択される。
212 void get_virtues(void)
218 for (i = 0; i < 8; i++)
220 p_ptr->virtues[i] = 0;
221 p_ptr->vir_types[i] = 0;
226 /* Get pre-defined types */
227 /* 1 or more virtues based on class */
228 switch (p_ptr->pclass)
232 p_ptr->vir_types[i++] = V_VALOUR;
233 p_ptr->vir_types[i++] = V_HONOUR;
236 p_ptr->vir_types[i++] = V_KNOWLEDGE;
237 p_ptr->vir_types[i++] = V_ENCHANT;
240 p_ptr->vir_types[i++] = V_FAITH;
241 p_ptr->vir_types[i++] = V_TEMPERANCE;
245 p_ptr->vir_types[i++] = V_HONOUR;
249 p_ptr->vir_types[i++] = V_NATURE;
250 p_ptr->vir_types[i++] = V_TEMPERANCE;
253 p_ptr->vir_types[i++] = V_JUSTICE;
254 p_ptr->vir_types[i++] = V_VALOUR;
255 p_ptr->vir_types[i++] = V_HONOUR;
256 p_ptr->vir_types[i++] = V_FAITH;
258 case CLASS_WARRIOR_MAGE:
260 p_ptr->vir_types[i++] = V_ENCHANT;
261 p_ptr->vir_types[i++] = V_VALOUR;
263 case CLASS_CHAOS_WARRIOR:
264 p_ptr->vir_types[i++] = V_CHANCE;
265 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
268 case CLASS_FORCETRAINER:
269 p_ptr->vir_types[i++] = V_FAITH;
270 p_ptr->vir_types[i++] = V_HARMONY;
271 p_ptr->vir_types[i++] = V_TEMPERANCE;
272 p_ptr->vir_types[i++] = V_PATIENCE;
274 case CLASS_MINDCRAFTER:
275 case CLASS_MIRROR_MASTER:
276 p_ptr->vir_types[i++] = V_HARMONY;
277 p_ptr->vir_types[i++] = V_ENLIGHTEN;
278 p_ptr->vir_types[i++] = V_PATIENCE;
280 case CLASS_HIGH_MAGE:
282 p_ptr->vir_types[i++] = V_ENLIGHTEN;
283 p_ptr->vir_types[i++] = V_ENCHANT;
284 p_ptr->vir_types[i++] = V_KNOWLEDGE;
287 p_ptr->vir_types[i++] = V_ENLIGHTEN;
288 p_ptr->vir_types[i++] = V_CHANCE;
291 p_ptr->vir_types[i++] = V_CHANCE;
293 case CLASS_BLUE_MAGE:
294 p_ptr->vir_types[i++] = V_CHANCE;
295 p_ptr->vir_types[i++] = V_KNOWLEDGE;
297 case CLASS_BEASTMASTER:
298 p_ptr->vir_types[i++] = V_NATURE;
299 p_ptr->vir_types[i++] = V_CHANCE;
300 p_ptr->vir_types[i++] = V_VITALITY;
302 case CLASS_MAGIC_EATER:
303 p_ptr->vir_types[i++] = V_ENCHANT;
304 p_ptr->vir_types[i++] = V_KNOWLEDGE;
307 p_ptr->vir_types[i++] = V_HARMONY;
308 p_ptr->vir_types[i++] = V_COMPASSION;
311 p_ptr->vir_types[i++] = V_VALOUR;
312 p_ptr->vir_types[i++] = V_HARMONY;
314 case CLASS_BERSERKER:
315 p_ptr->vir_types[i++] = V_VALOUR;
316 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
319 p_ptr->vir_types[i++] = V_HONOUR;
320 p_ptr->vir_types[i++] = V_KNOWLEDGE;
323 p_ptr->vir_types[i++] = V_PATIENCE;
324 p_ptr->vir_types[i++] = V_KNOWLEDGE;
325 p_ptr->vir_types[i++] = V_FAITH;
326 p_ptr->vir_types[i++] = V_UNLIFE;
330 /* Get one virtue based on race */
331 switch (p_ptr->prace)
333 case RACE_HUMAN: case RACE_HALF_ELF: case RACE_DUNADAN:
334 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
336 case RACE_ELF: case RACE_SPRITE: case RACE_ENT:
337 p_ptr->vir_types[i++] = V_NATURE;
339 case RACE_HOBBIT: case RACE_HALF_OGRE:
340 p_ptr->vir_types[i++] = V_TEMPERANCE;
342 case RACE_DWARF: case RACE_KLACKON: case RACE_ANDROID:
343 p_ptr->vir_types[i++] = V_DILIGENCE;
345 case RACE_GNOME: case RACE_CYCLOPS:
346 p_ptr->vir_types[i++] = V_KNOWLEDGE;
348 case RACE_HALF_ORC: case RACE_AMBERITE: case RACE_KOBOLD:
349 p_ptr->vir_types[i++] = V_HONOUR;
351 case RACE_HALF_TROLL: case RACE_BARBARIAN:
352 p_ptr->vir_types[i++] = V_VALOUR;
354 case RACE_HIGH_ELF: case RACE_KUTAR:
355 p_ptr->vir_types[i++] = V_VITALITY;
357 case RACE_HALF_GIANT: case RACE_GOLEM: case RACE_ANGEL: case RACE_DEMON:
358 p_ptr->vir_types[i++] = V_JUSTICE;
360 case RACE_HALF_TITAN:
361 p_ptr->vir_types[i++] = V_HARMONY;
364 p_ptr->vir_types[i++] = V_SACRIFICE;
366 case RACE_MIND_FLAYER:
367 p_ptr->vir_types[i++] = V_ENLIGHTEN;
369 case RACE_DARK_ELF: case RACE_DRACONIAN: case RACE_S_FAIRY:
370 p_ptr->vir_types[i++] = V_ENCHANT;
373 p_ptr->vir_types[i++] = V_PATIENCE;
376 p_ptr->vir_types[i++] = V_FAITH;
378 case RACE_ZOMBIE: case RACE_SKELETON:
379 case RACE_VAMPIRE: case RACE_SPECTRE:
380 p_ptr->vir_types[i++] = V_UNLIFE;
383 p_ptr->vir_types[i++] = V_CHANCE;
387 /* Get a virtue for realms */
390 tmp_vir = get_realm_virtues(p_ptr->realm1);
391 if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir;
395 tmp_vir = get_realm_virtues(p_ptr->realm2);
396 if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir;
399 /* Eliminate doubles */
400 for (i = 0; i < 8; i++)
402 for (j = i + 1; j < 8; j++)
404 if ((p_ptr->vir_types[j] != 0) && (p_ptr->vir_types[j] == p_ptr->vir_types[i]))
405 p_ptr->vir_types[j] = 0;
409 /* Fill in the blanks */
410 for (i = 0; i < 8; i++)
412 if (p_ptr->vir_types[i] == 0) get_random_virtue(i);
417 * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。
418 * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。
423 void chg_virtue(int virtue, int amount)
427 for (i = 0; i < 8; i++)
429 if (p_ptr->vir_types[i] == virtue)
433 if ((amount + p_ptr->virtues[i] > 50) && one_in_(2))
435 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 50);
438 if ((amount + p_ptr->virtues[i] > 80) && one_in_(2))
440 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 80);
443 if ((amount + p_ptr->virtues[i] > 100) && one_in_(2))
445 p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 100);
448 if (amount + p_ptr->virtues[i] > 125)
449 p_ptr->virtues[i] = 125;
451 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
455 if ((amount + p_ptr->virtues[i] < -50) && one_in_(2))
457 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -50);
460 if ((amount + p_ptr->virtues[i] < -80) && one_in_(2))
462 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -80);
465 if ((amount + p_ptr->virtues[i] < -100) && one_in_(2))
467 p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -100);
470 if (amount + p_ptr->virtues[i] < -125)
471 p_ptr->virtues[i] = -125;
473 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
475 p_ptr->update |= (PU_BONUS);
482 * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする。
484 * @param amount セットしたい値。
487 void set_virtue(int virtue, int amount)
491 for (i = 0; i < 8; i++)
493 if (p_ptr->vir_types[i] == virtue)
495 p_ptr->virtues[i] = amount;
503 * @param OutFile ファイルポインタ。
506 void dump_virtues(FILE *OutFile)
510 if (!OutFile) return;
512 for (v_nr = 0; v_nr < 8; v_nr++)
515 int tester = p_ptr->virtues[v_nr];
517 strcpy(v_name, virtue[(p_ptr->vir_types[v_nr])-1]);
519 if (p_ptr->vir_types[v_nr] == 0 || p_ptr->vir_types[v_nr] > MAX_VIRTUE)
521 fprintf(OutFile, "おっと。%sの情報なし。", v_name);
523 fprintf(OutFile, "Oops. No info about %s.", v_name);
526 else if (tester < -100)
528 fprintf(OutFile, "[%s]の対極",
530 fprintf(OutFile, "You are the polar opposite of %s.",
534 else if (tester < -80)
536 fprintf(OutFile, "[%s]の大敵",
538 fprintf(OutFile, "You are an arch-enemy of %s.",
542 else if (tester < -60)
544 fprintf(OutFile, "[%s]の強敵",
546 fprintf(OutFile, "You are a bitter enemy of %s.",
550 else if (tester < -40)
552 fprintf(OutFile, "[%s]の敵",
554 fprintf(OutFile, "You are an enemy of %s.",
558 else if (tester < -20)
560 fprintf(OutFile, "[%s]の罪者",
562 fprintf(OutFile, "You have sinned against %s.",
568 fprintf(OutFile, "[%s]の迷道者",
570 fprintf(OutFile, "You have strayed from the path of %s.",
574 else if (tester == 0)
576 fprintf(OutFile,"[%s]の中立者",
578 fprintf(OutFile,"You are neutral to %s.",
582 else if (tester < 20)
584 fprintf(OutFile,"[%s]の小徳者",
586 fprintf(OutFile,"You are somewhat virtuous in %s.",
590 else if (tester < 40)
592 fprintf(OutFile,"[%s]の中徳者",
594 fprintf(OutFile,"You are virtuous in %s.",
598 else if (tester < 60)
600 fprintf(OutFile,"[%s]の高徳者",
602 fprintf(OutFile,"You are very virtuous in %s.",
606 else if (tester < 80)
608 fprintf(OutFile,"[%s]の覇者",
610 fprintf(OutFile,"You are a champion of %s.",
614 else if (tester < 100)
616 fprintf(OutFile,"[%s]の偉大な覇者",
618 fprintf(OutFile,"You are a great champion of %s.",
624 fprintf(OutFile,"[%s]の具現者",
626 fprintf(OutFile,"You are the living embodiment of %s.",
631 fprintf(OutFile, "\n");