1 /**
2  * \file player.c
3  * \brief Player implementation
4  *
5  * Copyright (c) 2011 elly+angband@leptoquark.net. See COPYING.
6  *
7  * This work is free software; you can redistribute it and/or modify it
8  * under the terms of either:
9  *
10  * a) the GNU General Public License as published by the Free Software
11  *    Foundation, version 2, or
12  *
13  * b) the "Angband licence":
14  *    This software may be copied and distributed for educational, research,
15  *    and not for profit purposes provided that this copyright and statement
16  *    are included in all such copies.  Other copyrights may also apply.
17  */
18 
19 #include "effects.h"
20 #include "init.h"
21 #include "obj-pile.h"
22 #include "obj-util.h"
23 #include "player-birth.h"
24 #include "player-calcs.h"
25 #include "player-history.h"
26 #include "player-quest.h"
27 #include "player-spell.h"
28 #include "player-timed.h"
29 #include "z-color.h"
30 #include "z-util.h"
31 
32 /**
33  * Pointer to the player struct
34  */
35 struct player *player = NULL;
36 
37 struct player_body *bodies;
38 struct player_race *races;
39 struct player_shape *shapes;
40 struct player_class *classes;
41 struct player_ability *player_abilities;
42 struct magic_realm *realms;
43 
44 /**
45  * Base experience levels, may be adjusted up for race and/or class
46  */
47 const s32b player_exp[PY_MAX_LEVEL] =
48 {
49 	10,
50 	25,
51 	45,
52 	70,
53 	100,
54 	140,
55 	200,
56 	280,
57 	380,
58 	500,
59 	650,
60 	850,
61 	1100,
62 	1400,
63 	1800,
64 	2300,
65 	2900,
66 	3600,
67 	4400,
68 	5400,
69 	6800,
70 	8400,
71 	10200,
72 	12500,
73 	17500,
74 	25000,
75 	35000L,
76 	50000L,
77 	75000L,
78 	100000L,
79 	150000L,
80 	200000L,
81 	275000L,
82 	350000L,
83 	450000L,
84 	550000L,
85 	700000L,
86 	850000L,
87 	1000000L,
88 	1250000L,
89 	1500000L,
90 	1800000L,
91 	2100000L,
92 	2400000L,
93 	2700000L,
94 	3000000L,
95 	3500000L,
96 	4000000L,
97 	4500000L,
98 	5000000L
99 };
100 
101 
102 static const char *stat_name_list[] = {
103 	#define STAT(a) #a,
104 	#include "list-stats.h"
105 	#undef STAT
106 	"MAX",
107     NULL
108 };
109 
stat_name_to_idx(const char * name)110 int stat_name_to_idx(const char *name)
111 {
112     int i;
113     for (i = 0; stat_name_list[i]; i++) {
114         if (!my_stricmp(name, stat_name_list[i]))
115             return i;
116     }
117 
118     return -1;
119 }
120 
stat_idx_to_name(int type)121 const char *stat_idx_to_name(int type)
122 {
123     assert(type >= 0);
124     assert(type < STAT_MAX);
125 
126     return stat_name_list[type];
127 }
128 
lookup_realm(const char * name)129 const struct magic_realm *lookup_realm(const char *name)
130 {
131 	struct magic_realm *realm = realms;
132 	while (realm) {
133 		if (!my_stricmp(name, realm->name)) {
134 			return realm;
135 		}
136 		realm = realm->next;
137 	}
138 
139 	/* Fail horribly */
140 	quit_fmt("Failed to find %s magic realm", name);
141 	return realm;
142 }
143 
player_stat_inc(struct player * p,int stat)144 bool player_stat_inc(struct player *p, int stat)
145 {
146 	int v = p->stat_cur[stat];
147 
148 	if (v >= 18 + 100)
149 		return false;
150 	if (v < 18) {
151 		p->stat_cur[stat]++;
152 	} else if (v < 18 + 90) {
153 		int gain = (((18 + 100) - v) / 2 + 3) / 2;
154 		if (gain < 1)
155 			gain = 1;
156 		p->stat_cur[stat] += randint1(gain) + gain / 2;
157 		if (p->stat_cur[stat] > 18 + 99)
158 			p->stat_cur[stat] = 18 + 99;
159 	} else {
160 		p->stat_cur[stat] = 18 + 100;
161 	}
162 
163 	if (p->stat_cur[stat] > p->stat_max[stat])
164 		p->stat_max[stat] = p->stat_cur[stat];
165 
166 	p->upkeep->update |= PU_BONUS;
167 	return true;
168 }
169 
player_stat_dec(struct player * p,int stat,bool permanent)170 bool player_stat_dec(struct player *p, int stat, bool permanent)
171 {
172 	int cur, max, res = false;
173 
174 	cur = p->stat_cur[stat];
175 	max = p->stat_max[stat];
176 
177 	if (cur > 18+10)
178 		cur -= 10;
179 	else if (cur > 18)
180 		cur = 18;
181 	else if (cur > 3)
182 		cur -= 1;
183 
184 	res = (cur != p->stat_cur[stat]);
185 
186 	if (permanent) {
187 		if (max > 18+10)
188 			max -= 10;
189 		else if (max > 18)
190 			max = 18;
191 		else if (max > 3)
192 			max -= 1;
193 
194 		res = (max != p->stat_max[stat]);
195 	}
196 
197 	if (res) {
198 		p->stat_cur[stat] = cur;
199 		p->stat_max[stat] = max;
200 		p->upkeep->update |= (PU_BONUS);
201 		p->upkeep->redraw |= (PR_STATS);
202 	}
203 
204 	return res;
205 }
206 
adjust_level(struct player * p,bool verbose)207 static void adjust_level(struct player *p, bool verbose)
208 {
209 	if (p->exp < 0)
210 		p->exp = 0;
211 
212 	if (p->max_exp < 0)
213 		p->max_exp = 0;
214 
215 	if (p->exp > PY_MAX_EXP)
216 		p->exp = PY_MAX_EXP;
217 
218 	if (p->max_exp > PY_MAX_EXP)
219 		p->max_exp = PY_MAX_EXP;
220 
221 	if (p->exp > p->max_exp)
222 		p->max_exp = p->exp;
223 
224 	p->upkeep->redraw |= PR_EXP;
225 
226 	handle_stuff(p);
227 
228 	while ((p->lev > 1) &&
229 	       (p->exp < (player_exp[p->lev-2] * p->expfact / 100L)))
230 		p->lev--;
231 
232 
233 	while ((p->lev < PY_MAX_LEVEL) &&
234 	       (p->exp >= (player_exp[p->lev-1] * p->expfact / 100L))) {
235 		char buf[80];
236 
237 		p->lev++;
238 
239 		/* Save the highest level */
240 		if (p->lev > p->max_lev)
241 			p->max_lev = p->lev;
242 
243 		if (verbose) {
244 			/* Log level updates */
245 			strnfmt(buf, sizeof(buf), "Reached level %d", p->lev);
246 			history_add(p, buf, HIST_GAIN_LEVEL);
247 
248 			/* Message */
249 			msgt(MSG_LEVEL, "Welcome to level %d.",	p->lev);
250 		}
251 
252 		effect_simple(EF_RESTORE_STAT, source_none(), "0", STAT_STR, 0, 0, 0, 0, NULL);
253 		effect_simple(EF_RESTORE_STAT, source_none(), "0", STAT_INT, 0, 0, 0, 0, NULL);
254 		effect_simple(EF_RESTORE_STAT, source_none(), "0", STAT_WIS, 0, 0, 0, 0, NULL);
255 		effect_simple(EF_RESTORE_STAT, source_none(), "0", STAT_DEX, 0, 0, 0, 0, NULL);
256 		effect_simple(EF_RESTORE_STAT, source_none(), "0", STAT_CON, 0, 0, 0, 0, NULL);
257 	}
258 
259 	while ((p->max_lev < PY_MAX_LEVEL) &&
260 	       (p->max_exp >= (player_exp[p->max_lev-1] * p->expfact / 100L)))
261 		p->max_lev++;
262 
263 	p->upkeep->update |= (PU_BONUS | PU_HP | PU_SPELLS);
264 	p->upkeep->redraw |= (PR_LEV | PR_TITLE | PR_EXP | PR_STATS);
265 	handle_stuff(p);
266 }
267 
player_exp_gain(struct player * p,s32b amount)268 void player_exp_gain(struct player *p, s32b amount)
269 {
270 	p->exp += amount;
271 	if (p->exp < p->max_exp)
272 		p->max_exp += amount / 10;
273 	adjust_level(p, true);
274 }
275 
player_exp_lose(struct player * p,s32b amount,bool permanent)276 void player_exp_lose(struct player *p, s32b amount, bool permanent)
277 {
278 	if (p->exp < amount)
279 		amount = p->exp;
280 	p->exp -= amount;
281 	if (permanent)
282 		p->max_exp -= amount;
283 	adjust_level(p, true);
284 }
285 
286 /**
287  * Obtain object flags for the player
288  */
player_flags(struct player * p,bitflag f[OF_SIZE])289 void player_flags(struct player *p, bitflag f[OF_SIZE])
290 {
291 	/* Add racial flags */
292 	memcpy(f, p->race->flags, sizeof(p->race->flags));
293 	of_union(f, p->class->flags);
294 
295 	/* Some classes become immune to fear at a certain plevel */
296 	if (player_has(p, PF_BRAVERY_30) && p->lev >= 30) {
297 		of_on(f, OF_PROT_FEAR);
298 	}
299 }
300 
301 
302 /**
303  * Combine any flags due to timed effects on the player into those in f.
304  */
player_flags_timed(struct player * p,bitflag f[OF_SIZE])305 void player_flags_timed(struct player *p, bitflag f[OF_SIZE])
306 {
307 	if (p->timed[TMD_BOLD] || p->timed[TMD_HERO] || p->timed[TMD_SHERO]) {
308 		of_on(f, OF_PROT_FEAR);
309 	}
310 	if (p->timed[TMD_TELEPATHY]) {
311 		of_on(f, OF_TELEPATHY);
312 	}
313 	if (p->timed[TMD_SINVIS]) {
314 		of_on(f, OF_SEE_INVIS);
315 	}
316 	if (p->timed[TMD_FREE_ACT]) {
317 		of_on(f, OF_FREE_ACT);
318 	}
319 	if (p->timed[TMD_AFRAID] || p->timed[TMD_TERROR]) {
320 		of_on(f, OF_AFRAID);
321 	}
322 	if (p->timed[TMD_OPP_CONF]) {
323 		of_on(f, OF_PROT_CONF);
324 	}
325 }
326 
327 
player_hp_attr(struct player * p)328 byte player_hp_attr(struct player *p)
329 {
330 	byte attr;
331 
332 	if (p->chp >= p->mhp)
333 		attr = COLOUR_L_GREEN;
334 	else if (p->chp > (p->mhp * p->opts.hitpoint_warn) / 10)
335 		attr = COLOUR_YELLOW;
336 	else
337 		attr = COLOUR_RED;
338 
339 	return attr;
340 }
341 
player_sp_attr(struct player * p)342 byte player_sp_attr(struct player *p)
343 {
344 	byte attr;
345 
346 	if (p->csp >= p->msp)
347 		attr = COLOUR_L_GREEN;
348 	else if (p->csp > (p->msp * p->opts.hitpoint_warn) / 10)
349 		attr = COLOUR_YELLOW;
350 	else
351 		attr = COLOUR_RED;
352 
353 	return attr;
354 }
355 
player_restore_mana(struct player * p,int amt)356 bool player_restore_mana(struct player *p, int amt) {
357 	int old_csp = p->csp;
358 
359 	p->csp += amt;
360 	if (p->csp > p->msp) {
361 		p->csp = p->msp;
362 	}
363 	p->upkeep->redraw |= PR_MANA;
364 
365 	msg("You feel some of your energies returning.");
366 
367 	return p->csp != old_csp;
368 }
369 
370 /**
371  * Return a version of the player's name safe for use in filesystems.
372  *
373  * XXX This does not belong here.
374  */
player_safe_name(char * safe,size_t safelen,const char * name,bool strip_suffix)375 void player_safe_name(char *safe, size_t safelen, const char *name, bool strip_suffix)
376 {
377 	size_t i;
378 	size_t limit = 0;
379 
380 	if (name) {
381 		char *suffix = find_roman_suffix_start(name);
382 
383 		if (suffix) {
384 			limit = suffix - name - 1; /* -1 for preceding space */
385 		} else {
386 			limit = strlen(name);
387 		}
388 	}
389 
390 	/* Limit to maximum size of safename buffer */
391 	limit = MIN(limit, safelen);
392 
393 	for (i = 0; i < limit; i++) {
394 		char c = name[i];
395 
396 		/* Convert all non-alphanumeric symbols */
397 		if (!isalpha((unsigned char)c) && !isdigit((unsigned char)c))
398 			c = '_';
399 
400 		/* Build "base_name" */
401 		safe[i] = c;
402 	}
403 
404 	/* Terminate */
405 	safe[i] = '\0';
406 
407 	/* Require a "base" name */
408 	if (!safe[0])
409 		my_strcpy(safe, "PLAYER", safelen);
410 }
411 
412 
413 /**
414  * Release resources allocated for fields in the player structure.
415  */
player_cleanup_members(struct player * p)416 void player_cleanup_members(struct player *p)
417 {
418 	/* Free the history */
419 	history_clear(p);
420 
421 	/* Free the things that are always initialised */
422 	if (p->obj_k) {
423 		object_free(p->obj_k);
424 	}
425 	mem_free(p->timed);
426 	if (p->upkeep) {
427 		mem_free(p->upkeep->quiver);
428 		mem_free(p->upkeep->inven);
429 		mem_free(p->upkeep);
430 		p->upkeep = NULL;
431 	}
432 
433 	/* Free the things that are only sometimes initialised */
434 	if (p->quests) {
435 		player_quests_free(p);
436 	}
437 	if (p->spell_flags) {
438 		player_spells_free(p);
439 	}
440 	if (p->gear) {
441 		object_pile_free(p->gear);
442 		object_pile_free(p->gear_k);
443 	}
444 	if (p->body.slots) {
445 		for (int i = 0; i < p->body.count; i++)
446 			string_free(p->body.slots[i].name);
447 		mem_free(p->body.slots);
448 	}
449 	string_free(p->body.name);
450 	string_free(p->history);
451 	if (p->cave) {
452 		cave_free(p->cave);
453 		p->cave = NULL;
454 	}
455 }
456 
457 
458 /**
459  * Initialise player struct
460  */
init_player(void)461 static void init_player(void) {
462 	/* Create the player array, initialised with 0 */
463 	player = mem_zalloc(sizeof *player);
464 
465 	/* Allocate player sub-structs */
466 	player->upkeep = mem_zalloc(sizeof(struct player_upkeep));
467 	player->upkeep->inven = mem_zalloc((z_info->pack_size + 1) * sizeof(struct object *));
468 	player->upkeep->quiver = mem_zalloc(z_info->quiver_size * sizeof(struct object *));
469 	player->timed = mem_zalloc(TMD_MAX * sizeof(s16b));
470 	player->obj_k = object_new();
471 	player->obj_k->brands = mem_zalloc(z_info->brand_max * sizeof(bool));
472 	player->obj_k->slays = mem_zalloc(z_info->slay_max * sizeof(bool));
473 	player->obj_k->curses = mem_zalloc(z_info->curse_max *
474 									   sizeof(struct curse_data));
475 
476 	options_init_defaults(&player->opts);
477 }
478 
479 /**
480  * Free player struct
481  */
cleanup_player(void)482 static void cleanup_player(void) {
483 	if (!player) return;
484 
485 	player_cleanup_members(player);
486 
487 	/* Free the basic player struct */
488 	mem_free(player);
489 	player = NULL;
490 }
491 
492 struct init_module player_module = {
493 	.name = "player",
494 	.init = init_player,
495 	.cleanup = cleanup_player
496 };
497