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