1 /* File: avatar.c */
2
3 /*
4 * Purpose: Enable an Ultima IV style "avatar" game where you try to
5 * achieve perfection in various virtues.
6 *
7 * Topi Ylinen 1998
8 *
9 */
10
11 /*
12 * Copyright (c) 1989 James E. Wilson, Christopher J. Stuart
13 *
14 * This software may be copied and distributed for educational, research, and
15 * not for profit purposes provided that this copyright and statement are
16 * included in all such copies.
17 */
18
19 #include "angband.h"
20
21
22 /* The names of the virtues */
23 cptr virtue[MAX_VIRTUE] =
24 {
25 "Compassion",
26 "Honour",
27 "Justice",
28 "Sacrifice",
29 "Knowledge",
30 "Faith",
31 "Enlightenment",
32 "Mysticism",
33 "Chance",
34 "Nature",
35 "Harmony",
36 "Vitality",
37 "Unlife",
38 "Patience",
39 "Temperance",
40 "Diligence",
41 "Valour",
42 "Individualism",
43 };
44
45
46 /* Aux function */
exist_virtue(int type)47 static bool exist_virtue(int type)
48 {
49 int i;
50
51 /* Search */
52 for (i = 0; i < MAX_PLAYER_VIRTUES; i++)
53 {
54 if (p_ptr->vir_types[i] == type) return TRUE;
55 }
56
57 /* No match */
58 return FALSE;
59 }
60
61
62 /* Aux function */
get_random_virtue(int which)63 static void get_random_virtue(int which)
64 {
65 int type = 0;
66
67 /* Randomly choose a type */
68 while (!type || exist_virtue(type))
69 {
70 switch (randint1(29))
71 {
72 case 1: case 2: case 3:
73 type = V_SACRIFICE;
74 break;
75 case 4: case 5: case 6:
76 type = V_COMPASSION;
77 break;
78 case 7: case 8: case 9: case 10: case 11: case 12:
79 type = V_VALOUR;
80 break;
81 case 13: case 14: case 15: case 16: case 17:
82 type = V_HONOUR;
83 break;
84 case 18: case 19: case 20: case 21:
85 type = V_JUSTICE;
86 break;
87 case 22: case 23:
88 type = V_TEMPERANCE;
89 break;
90 case 24: case 25:
91 type = V_HARMONY;
92 break;
93 case 26: case 27: case 28:
94 type = V_PATIENCE;
95 break;
96 default:
97 type = V_DILIGENCE;
98 }
99 }
100
101 /* Chosen */
102 p_ptr->vir_types[which] = type;
103 }
104
105
106 /*
107 * Select virtues & reset values for a new character
108 */
get_virtues(void)109 void get_virtues(void)
110 {
111 int i, j;
112
113 /* Reset */
114 for (i = 0; i < MAX_PLAYER_VIRTUES; i++)
115 {
116 p_ptr->virtues[i] = 0;
117 p_ptr->vir_types[i] = 0;
118 }
119
120 i = 0;
121
122 /* Get pre-defined types */
123 /* One or more virtues based on class */
124 switch (p_ptr->rp.pclass)
125 {
126 case CLASS_WARRIOR:
127 p_ptr->vir_types[i++] = V_VALOUR;
128 p_ptr->vir_types[i++] = V_HONOUR;
129 break;
130 case CLASS_MAGE:
131 p_ptr->vir_types[i++] = V_KNOWLEDGE;
132 p_ptr->vir_types[i++] = V_ENCHANT;
133 break;
134 case CLASS_PRIEST:
135 p_ptr->vir_types[i++] = V_FAITH;
136 p_ptr->vir_types[i++] = V_TEMPERANCE;
137 break;
138 case CLASS_ROGUE:
139 p_ptr->vir_types[i++] = V_HONOUR;
140 break;
141 case CLASS_RANGER:
142 p_ptr->vir_types[i++] = V_NATURE;
143 p_ptr->vir_types[i++] = V_TEMPERANCE;
144 break;
145 case CLASS_PALADIN:
146 p_ptr->vir_types[i++] = V_JUSTICE;
147 p_ptr->vir_types[i++] = V_VALOUR;
148 p_ptr->vir_types[i++] = V_HONOUR;
149 p_ptr->vir_types[i++] = V_FAITH;
150 break;
151 case CLASS_WARRIOR_MAGE:
152 p_ptr->vir_types[i++] = V_ENCHANT;
153 p_ptr->vir_types[i++] = V_VALOUR;
154 break;
155 case CLASS_CHAOS_WARRIOR:
156 p_ptr->vir_types[i++] = V_CHANCE;
157 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
158 break;
159 case CLASS_MONK:
160 p_ptr->vir_types[i++] = V_FAITH;
161 p_ptr->vir_types[i++] = V_HARMONY;
162 p_ptr->vir_types[i++] = V_TEMPERANCE;
163 p_ptr->vir_types[i++] = V_PATIENCE;
164 break;
165 case CLASS_MINDCRAFTER:
166 p_ptr->vir_types[i++] = V_HARMONY;
167 p_ptr->vir_types[i++] = V_ENLIGHTEN;
168 p_ptr->vir_types[i++] = V_PATIENCE;
169 break;
170 case CLASS_HIGH_MAGE:
171 p_ptr->vir_types[i++] = V_ENLIGHTEN;
172 p_ptr->vir_types[i++] = V_ENCHANT;
173 p_ptr->vir_types[i++] = V_KNOWLEDGE;
174 break;
175 };
176
177
178 /* Get one virtue based on race */
179 switch (p_ptr->rp.prace)
180 {
181 case RACE_HUMAN: case RACE_HALF_ELF:
182 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
183 break;
184 case RACE_ELF: case RACE_SPRITE:
185 p_ptr->vir_types[i++] = V_NATURE;
186 break;
187 case RACE_HOBBIT: case RACE_HALF_OGRE:
188 p_ptr->vir_types[i++] = V_TEMPERANCE;
189 break;
190 case RACE_DWARF: case RACE_KLACKON:
191 p_ptr->vir_types[i++] = V_DILIGENCE;
192 break;
193 case RACE_GNOME: case RACE_CYCLOPS:
194 p_ptr->vir_types[i++] = V_KNOWLEDGE;
195 break;
196 case RACE_HALF_ORC: case RACE_AMBERITE: case RACE_KOBOLD:
197 p_ptr->vir_types[i++] = V_HONOUR;
198 break;
199 case RACE_HALF_TROLL: case RACE_BARBARIAN:
200 p_ptr->vir_types[i++] = V_VALOUR;
201 break;
202 case RACE_HIGH_ELF:
203 p_ptr->vir_types[i++] = V_VITALITY;
204 break;
205 case RACE_HALF_GIANT: case RACE_GOLEM:
206 p_ptr->vir_types[i++] = V_JUSTICE;
207 break;
208 case RACE_HALF_TITAN:
209 p_ptr->vir_types[i++] = V_HARMONY;
210 break;
211 case RACE_YEEK:
212 p_ptr->vir_types[i++] = V_SACRIFICE;
213 break;
214 case RACE_MIND_FLAYER:
215 p_ptr->vir_types[i++] = V_ENLIGHTEN;
216 break;
217 case RACE_DARK_ELF: case RACE_DRACONIAN:
218 p_ptr->vir_types[i++] = V_ENCHANT;
219 break;
220 case RACE_NIBELUNG:
221 p_ptr->vir_types[i++] = V_PATIENCE;
222 break;
223 case RACE_IMP:
224 p_ptr->vir_types[i++] = V_FAITH;
225 break;
226 case RACE_ZOMBIE: case RACE_SKELETON: case RACE_VAMPIRE:
227 case RACE_SPECTRE: case RACE_GHOUL:
228 p_ptr->vir_types[i++] = V_UNLIFE;
229 break;
230 case RACE_BEASTMAN:
231 p_ptr->vir_types[i++] = V_CHANCE;
232 break;
233 }
234
235 /* Get a virtue for r[0].realm */
236 if (p_ptr->spell.r[0].realm)
237 {
238 switch (p_ptr->spell.r[0].realm)
239 {
240 case 1:
241 if (exist_virtue(V_VITALITY))
242 p_ptr->vir_types[i++] = V_COMPASSION;
243 else
244 p_ptr->vir_types[i++] = V_VITALITY;
245 break;
246 case 2:
247 if (exist_virtue(V_ENCHANT))
248 p_ptr->vir_types[i++] = V_KNOWLEDGE;
249 else
250 p_ptr->vir_types[i++] = V_ENCHANT;
251 break;
252 case 3:
253 if (exist_virtue(V_NATURE))
254 p_ptr->vir_types[i++] = V_HARMONY;
255 else
256 p_ptr->vir_types[i++] = V_NATURE;
257 break;
258 case 4:
259 if (exist_virtue(V_CHANCE))
260 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
261 else
262 p_ptr->vir_types[i++] = V_CHANCE;
263 break;
264 case 5:
265 p_ptr->vir_types[i++] = V_UNLIFE;
266 break;
267 case 6:
268 p_ptr->vir_types[i++] = V_KNOWLEDGE;
269 break;
270 case 7:
271 break;
272 };
273 }
274
275 /* Get a virtue for r[1].realm */
276 if (p_ptr->spell.r[1].realm)
277 {
278 switch (p_ptr->spell.r[1].realm)
279 {
280 case 1:
281 if (exist_virtue(V_VITALITY))
282 p_ptr->vir_types[i++] = V_COMPASSION;
283 else
284 p_ptr->vir_types[i++] = V_VITALITY;
285 break;
286 case 2:
287 if (exist_virtue(V_ENCHANT))
288 p_ptr->vir_types[i++] = V_KNOWLEDGE;
289 else
290 p_ptr->vir_types[i++] = V_ENCHANT;
291 break;
292 case 3:
293 if (exist_virtue(V_NATURE))
294 p_ptr->vir_types[i++] = V_HARMONY;
295 else
296 p_ptr->vir_types[i++] = V_NATURE;
297 break;
298 case 4:
299 if (exist_virtue(V_CHANCE))
300 p_ptr->vir_types[i++] = V_INDIVIDUALISM;
301 else
302 p_ptr->vir_types[i++] = V_CHANCE;
303 break;
304 case 5:
305 p_ptr->vir_types[i++] = V_UNLIFE;
306 break;
307 case 6:
308 p_ptr->vir_types[i++] = V_KNOWLEDGE;
309 break;
310 case 7:
311 break;
312 };
313 }
314
315 /* Eliminate doubles */
316 for (i = 0; i < MAX_PLAYER_VIRTUES; i++)
317 {
318 for (j = i + 1; j < MAX_PLAYER_VIRTUES; j++)
319 {
320 if ((p_ptr->vir_types[j] != 0) &&
321 (p_ptr->vir_types[j] == p_ptr->vir_types[i]))
322 p_ptr->vir_types[j] = 0;
323 }
324 }
325
326 /* Fill in the blanks */
327 for (i = 0; i < MAX_PLAYER_VIRTUES; i++)
328 {
329 if (p_ptr->vir_types[i] == 0) get_random_virtue(i);
330 }
331 }
332
333
chg_virtue(int virtue,int amount)334 void chg_virtue(int virtue, int amount)
335 {
336 int i;
337
338 for (i = 0; i < MAX_PLAYER_VIRTUES; i++)
339 {
340 if (p_ptr->vir_types[i] == virtue)
341 {
342 if (amount > 0)
343 {
344 if (amount + p_ptr->virtues[i] > 125)
345 p_ptr->virtues[i] = 125;
346 else
347 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
348 }
349 else
350 {
351 if (amount + p_ptr->virtues[i] < -125)
352 p_ptr->virtues[i] = -125;
353 else
354 p_ptr->virtues[i] = p_ptr->virtues[i] + amount;
355 }
356 return;
357 }
358 }
359 }
360
361
dump_virtues(FILE * OutFile)362 void dump_virtues(FILE *OutFile)
363 {
364 int v_nr;
365
366 if (!OutFile) return;
367
368 for (v_nr = 0; v_nr < MAX_PLAYER_VIRTUES; v_nr++)
369 {
370 char virt_name[20];
371
372 int tester = p_ptr->virtues[v_nr];
373
374 strcpy(virt_name, virtue[(p_ptr->vir_types[v_nr]) - 1]);
375
376 if ((p_ptr->vir_types[v_nr] == 0) ||
377 (p_ptr->vir_types[v_nr] > MAX_VIRTUE))
378 froff(OutFile, "Oops. No info about %s.", virt_name);
379 else if (tester < -100)
380 froff(OutFile, "You are the polar opposite of %s.", virt_name);
381 else if (tester < -80)
382 froff(OutFile, "You are an arch-enemy of %s.", virt_name);
383 else if (tester < -60)
384 froff(OutFile, "You are a bitter enemy of %s.", virt_name);
385 else if (tester < -40)
386 froff(OutFile, "You are an enemy of %s.", virt_name);
387 else if (tester < -20)
388 froff(OutFile, "You have sinned against %s.", virt_name);
389 else if (tester < 0)
390 froff(OutFile, "You have strayed from the path of %s.",
391 virt_name);
392 else if (tester == 0)
393 froff(OutFile, "You are neutral to %s.", virt_name);
394 else if (tester < 20)
395 froff(OutFile, "You are somewhat virtuous in %s.", virt_name);
396 else if (tester < 40)
397 froff(OutFile, "You are virtuous in %s.", virt_name);
398 else if (tester < 60)
399 froff(OutFile, "You are very virtuous in %s.", virt_name);
400 else if (tester < 80)
401 froff(OutFile, "You are a champion of %s.", virt_name);
402 else if (tester < 100)
403 froff(OutFile, "You are a great champion of %s.", virt_name);
404 else
405 froff(OutFile, "You are the living embodiment of %s.", virt_name);
406
407 froff(OutFile, "\n");
408 }
409
410 if (p_ptr->state.wizard)
411 froff(OutFile, "Your overall alignment is %ld.\n", p_ptr->align);
412 }
413