1 /**
2 * \file player-util.c
3 * \brief Player utility functions
4 *
5 * Copyright (c) 2011 The Angband Developers. 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 "angband.h"
20 #include "cave.h"
21 #include "cmd-core.h"
22 #include "cmds.h"
23 #include "game-input.h"
24 #include "game-world.h"
25 #include "generate.h"
26 #include "init.h"
27 #include "obj-chest.h"
28 #include "obj-gear.h"
29 #include "obj-knowledge.h"
30 #include "obj-pile.h"
31 #include "obj-tval.h"
32 #include "obj-util.h"
33 #include "player-calcs.h"
34 #include "player-history.h"
35 #include "player-spell.h"
36 #include "player-timed.h"
37 #include "player-util.h"
38 #include "project.h"
39 #include "score.h"
40 #include "store.h"
41 #include "target.h"
42 #include "trap.h"
43
44 /**
45 * Increment to the next or decrement to the preceeding level
46 accounting for the stair skip value in constants
47 Keep in mind to check all intermediate level for unskippable
48 quests
49 */
dungeon_get_next_level(int dlev,int added)50 int dungeon_get_next_level(int dlev, int added)
51 {
52 int target_level, i;
53
54 /* Get target level */
55 target_level = dlev + added * z_info->stair_skip;
56
57 /* Don't allow levels below max */
58 if (target_level > z_info->max_depth - 1)
59 target_level = z_info->max_depth - 1;
60
61 /* Don't allow levels above the town */
62 if (target_level < 0) target_level = 0;
63
64 /* Check intermediate levels for quests */
65 for (i = dlev; i <= target_level; i++) {
66 if (is_quest(i)) return i;
67 }
68
69 return target_level;
70 }
71
72 /**
73 * Set recall depth for a player recalling from town
74 */
player_set_recall_depth(struct player * p)75 void player_set_recall_depth(struct player *p)
76 {
77 /* Account for forced descent */
78 if (OPT(p, birth_force_descend)) {
79 /* Force descent to a lower level if allowed */
80 if ((p->max_depth < z_info->max_depth - 1) && !is_quest(p->max_depth)) {
81 p->recall_depth = dungeon_get_next_level(p->max_depth, 1);
82 }
83 }
84
85 /* Players who haven't left town before go to level 1 */
86 p->recall_depth = MAX(p->recall_depth, 1);
87 }
88
89 /**
90 * Give the player the choice of persistent level to recall to. Note that if
91 * a level greater than the player's maximum depth is chosen, we silently go
92 * to the maximum depth.
93 */
player_get_recall_depth(struct player * p)94 bool player_get_recall_depth(struct player *p)
95 {
96 bool level_ok = false;
97 int new = 0;
98
99 while (!level_ok) {
100 char *prompt = "Which level do you wish to return to (0 to cancel)? ";
101 int i;
102
103 /* Choose the level */
104 new = get_quantity(prompt, p->max_depth);
105 if (new == 0) {
106 return false;
107 }
108
109 /* Is that level valid? */
110 for (i = 0; i < chunk_list_max; i++) {
111 if (chunk_list[i]->depth == new) {
112 level_ok = true;
113 break;
114 }
115 }
116 if (!level_ok) {
117 msg("You must choose a level you have previously visited.");
118 }
119 }
120 p->recall_depth = new;
121 return true;
122 }
123
124 /**
125 * Change dungeon level - e.g. by going up stairs or with WoR.
126 */
dungeon_change_level(struct player * p,int dlev)127 void dungeon_change_level(struct player *p, int dlev)
128 {
129 /* New depth */
130 p->depth = dlev;
131
132 /* If we're returning to town, update the store contents
133 according to how long we've been away */
134 if (!dlev && daycount)
135 store_update();
136
137 /* Leaving, make new level */
138 p->upkeep->generate_level = true;
139
140 /* Save the game when we arrive on the new level. */
141 p->upkeep->autosave = true;
142 }
143
144
145 /**
146 * Decreases players hit points and sets death flag if necessary
147 *
148 * Hack -- this function allows the user to save (or quit) the game
149 * when he dies, since the "You die." message is shown before setting
150 * the player to "dead".
151 */
take_hit(struct player * p,int dam,const char * kb_str)152 void take_hit(struct player *p, int dam, const char *kb_str)
153 {
154 int old_chp = p->chp;
155
156 int warning = (p->mhp * p->opts.hitpoint_warn / 10);
157
158 /* Paranoia */
159 if (p->is_dead) return;
160
161 /* Mega-Hack -- Apply "invulnerability" */
162 if (p->timed[TMD_INVULN] && (dam < 9000)) return;
163
164 /* Apply damage reduction */
165 dam -= p->state.dam_red;
166 if (p->state.perc_dam_red) {
167 dam -= (dam * p->state.perc_dam_red) / 100 ;
168 }
169 if (dam <= 0) return;
170
171 /* Disturb */
172 disturb(p);
173
174 /* Hurt the player */
175 p->chp -= dam;
176
177 /* Reward COMBAT_REGEN characters with mana for their lost hitpoints
178 * Unenviable task of separating what should and should not cause rage
179 * If we eliminate the most exploitable cases it should be fine.
180 * All traps and lava currently give mana, which could be exploited */
181 if (player_has(p, PF_COMBAT_REGEN) && strcmp(kb_str, "poison")
182 && strcmp(kb_str, "a fatal wound") && strcmp(kb_str, "starvation")) {
183 /* lose X% of hitpoints get X% of spell points */
184 s32b sp_gain = (MAX((s32b)p->msp, 10) << 16) / (s32b)p->mhp * dam;
185 player_adjust_mana_precise(p, sp_gain);
186 }
187
188 /* Display the hitpoints */
189 p->upkeep->redraw |= (PR_HP);
190
191 /* Dead player */
192 if (p->chp < 0) {
193 /* From hell's heart I stab at thee */
194 if (p->timed[TMD_BLOODLUST]
195 && (p->chp + p->timed[TMD_BLOODLUST] + p->lev >= 0)) {
196 if (randint0(10)) {
197 msg("Your lust for blood keeps you alive!");
198 } else {
199 msg("So great was his prowess and skill in warfare, the Elves said: ");
200 msg("'The Mormegil cannot be slain, save by mischance.'");
201 }
202 } else if ((p->wizard || OPT(p, cheat_live)) && !get_check("Die? ")) {
203 event_signal(EVENT_CHEAT_DEATH);
204 } else {
205 /* Hack -- Note death */
206 msgt(MSG_DEATH, "You die.");
207 event_signal(EVENT_MESSAGE_FLUSH);
208
209 /* Note cause of death */
210 my_strcpy(p->died_from, kb_str, sizeof(p->died_from));
211
212 /* No longer a winner */
213 p->total_winner = false;
214
215 /* Note death */
216 p->is_dead = true;
217
218 /* Dead */
219 return;
220 }
221 }
222
223 /* Hitpoint warning */
224 if (p->chp < warning) {
225 /* Hack -- bell on first notice */
226 if (old_chp > warning)
227 bell("Low hitpoint warning!");
228
229 /* Message */
230 msgt(MSG_HITPOINT_WARN, "*** LOW HITPOINT WARNING! ***");
231 event_signal(EVENT_MESSAGE_FLUSH);
232 }
233 }
234
235 /**
236 * Win or not, know inventory, home items and history upon death, enter score
237 */
death_knowledge(struct player * p)238 void death_knowledge(struct player *p)
239 {
240 struct store *home = &stores[STORE_HOME];
241 struct object *obj;
242 time_t death_time = (time_t)0;
243
244 /* Retire in the town in a good state */
245 if (p->total_winner) {
246 p->depth = 0;
247 my_strcpy(p->died_from, "Ripe Old Age", sizeof(p->died_from));
248 p->exp = p->max_exp;
249 p->lev = p->max_lev;
250 p->au += 10000000L;
251 }
252
253 player_learn_all_runes(p);
254 for (obj = p->gear; obj; obj = obj->next) {
255 object_flavor_aware(obj);
256 obj->known->effect = obj->effect;
257 obj->known->activation = obj->activation;
258 }
259
260 for (obj = home->stock; obj; obj = obj->next) {
261 object_flavor_aware(obj);
262 obj->known->effect = obj->effect;
263 obj->known->activation = obj->activation;
264 }
265
266 history_unmask_unknown(p);
267
268 /* Get time of death */
269 (void)time(&death_time);
270 enter_score(&death_time);
271
272 /* Hack -- Recalculate bonuses */
273 p->upkeep->update |= (PU_BONUS);
274 handle_stuff(p);
275 }
276
277 /**
278 * Energy per move, taking extra moves into account
279 */
energy_per_move(struct player * p)280 int energy_per_move(struct player *p)
281 {
282 int num = p->state.num_moves;
283 int energy = z_info->move_energy;
284 return (energy * (1 + ABS(num) - num)) / (1 + ABS(num));
285 }
286
287 /**
288 * Modify a stat value by a "modifier", return new value
289 *
290 * Stats go up: 3,4,...,17,18,18/10,18/20,...,18/220
291 * Or even: 18/13, 18/23, 18/33, ..., 18/220
292 *
293 * Stats go down: 18/220, 18/210,..., 18/10, 18, 17, ..., 3
294 * Or even: 18/13, 18/03, 18, 17, ..., 3
295 */
modify_stat_value(int value,int amount)296 s16b modify_stat_value(int value, int amount)
297 {
298 int i;
299
300 /* Reward or penalty */
301 if (amount > 0) {
302 /* Apply each point */
303 for (i = 0; i < amount; i++) {
304 /* One point at a time */
305 if (value < 18) value++;
306
307 /* Ten "points" at a time */
308 else value += 10;
309 }
310 } else if (amount < 0) {
311 /* Apply each point */
312 for (i = 0; i < (0 - amount); i++) {
313 /* Ten points at a time */
314 if (value >= 18+10) value -= 10;
315
316 /* Hack -- prevent weirdness */
317 else if (value > 18) value = 18;
318
319 /* One point at a time */
320 else if (value > 3) value--;
321 }
322 }
323
324 /* Return new value */
325 return (value);
326 }
327
328 /**
329 * Regenerate one turn's worth of hit points
330 */
player_regen_hp(struct player * p)331 void player_regen_hp(struct player *p)
332 {
333 s32b hp_gain;
334 int percent = 0;/* max 32k -> 50% of mhp; more accurately "pertwobytes" */
335 int fed_pct, old_chp = p->chp;
336
337 /* Default regeneration */
338 if (p->timed[TMD_FOOD] >= PY_FOOD_WEAK) {
339 percent = PY_REGEN_NORMAL;
340 } else if (p->timed[TMD_FOOD] >= PY_FOOD_FAINT) {
341 percent = PY_REGEN_WEAK;
342 } else if (p->timed[TMD_FOOD] >= PY_FOOD_STARVE) {
343 percent = PY_REGEN_FAINT;
344 }
345
346 /* Food bonus - better fed players regenerate up to 1/3 faster */
347 fed_pct = p->timed[TMD_FOOD] / z_info->food_value;
348 percent *= 100 + fed_pct / 3;
349 percent /= 100;
350
351 /* Various things speed up regeneration */
352 if (player_of_has(p, OF_REGEN))
353 percent *= 2;
354 if (player_resting_can_regenerate(p))
355 percent *= 2;
356
357 /* Some things slow it down */
358 if (player_of_has(p, OF_IMPAIR_HP) || player_has(p, PF_COMBAT_REGEN))
359 percent /= 2;
360
361 /* Various things interfere with physical healing */
362 if (p->timed[TMD_PARALYZED]) percent = 0;
363 if (p->timed[TMD_POISONED]) percent = 0;
364 if (p->timed[TMD_STUN]) percent = 0;
365 if (p->timed[TMD_CUT]) percent = 0;
366
367 /* Extract the new hitpoints */
368 hp_gain = (s32b)(p->mhp * percent) + PY_REGEN_HPBASE;
369 player_adjust_hp_precise(p, hp_gain);
370
371 /* Notice changes */
372 if (old_chp != p->chp) {
373 equip_learn_flag(p, OF_REGEN);
374 equip_learn_flag(p, OF_IMPAIR_HP);
375 }
376 }
377
378
379 /**
380 * Regenerate one turn's worth of mana
381 */
player_regen_mana(struct player * p)382 void player_regen_mana(struct player *p)
383 {
384 s32b sp_gain;
385 int percent, old_csp = p->csp;
386
387 /* Save the old spell points */
388 old_csp = p->csp;
389
390 /* Default regeneration */
391 percent = PY_REGEN_NORMAL;
392
393 /* Various things speed up regeneration, but shouldn't punish healthy BGs */
394 if (!(player_has(p, PF_COMBAT_REGEN) && p->chp > p->mhp / 2)) {
395 if (player_of_has(p, OF_REGEN))
396 percent *= 2;
397 if (player_resting_can_regenerate(p))
398 percent *= 2;
399 }
400
401 /* Some things slow it down */
402 if (player_has(p, PF_COMBAT_REGEN)) {
403 percent /= -2;
404 } else if (player_of_has(p, OF_IMPAIR_MANA)) {
405 percent /= 2;
406 }
407
408 /* Regenerate mana */
409 sp_gain = (s32b)(p->msp * percent);
410 if (percent >= 0)
411 sp_gain += PY_REGEN_MNBASE;
412 sp_gain = player_adjust_mana_precise(p, sp_gain);
413
414 /* SP degen heals BGs at double efficiency vs casting */
415 if (sp_gain < 0 && player_has(p, PF_COMBAT_REGEN)) {
416 convert_mana_to_hp(p, -sp_gain << 2);
417 }
418
419 /* Notice changes */
420 if (old_csp != p->csp) {
421 p->upkeep->redraw |= (PR_MANA);
422 equip_learn_flag(p, OF_REGEN);
423 equip_learn_flag(p, OF_IMPAIR_MANA);
424 }
425 }
426
player_adjust_hp_precise(struct player * p,s32b hp_gain)427 void player_adjust_hp_precise(struct player *p, s32b hp_gain)
428 {
429 s32b new_chp;
430 int num, old_chp = p->chp;
431
432 /* Load it all into 4 byte format*/
433 new_chp = (s32b)((p->chp << 16) + p->chp_frac) + hp_gain;
434
435 /* Check for overflow */
436 /* {new_chp = LONG_MIN;} DAVIDTODO*/
437 if ((new_chp < 0) && (old_chp > 0) && (hp_gain > 0)) {
438 new_chp = INT32_MAX;
439 } else if ((new_chp > 0) && (old_chp < 0) && (hp_gain < 0)) {
440 new_chp = INT32_MIN;
441 }
442
443 /* Break it back down*/
444 p->chp = (s16b)(new_chp >> 16); /* div 65536 */
445 p->chp_frac = (u16b)(new_chp & 0xFFFF); /* mod 65536 */
446 /*DAVIDTODO neg new_chp ok? I think so because eg a slightly negative
447 * new_chp will give -1 for chp and very high chp_frac.*/
448
449 /* Fully healed */
450 if (p->chp >= p->mhp) {
451 p->chp = p->mhp;
452 p->chp_frac = 0;
453 }
454
455 num = p->chp - old_chp;
456 if (num == 0)
457 return;
458
459 p->upkeep->redraw |= (PR_HP);
460 }
461
462
463 /**
464 * Accept a 4 byte signed int, divide it by 65k, and add
465 * to current spell points. p->csp and csp_frac are 2 bytes each.
466 */
player_adjust_mana_precise(struct player * p,s32b sp_gain)467 s32b player_adjust_mana_precise(struct player *p, s32b sp_gain)
468 {
469 s32b old_csp_long, new_csp_long;
470 int old_csp_short = p->csp;
471
472 if (sp_gain == 0) return 0;
473
474 /* Load it all into 4 byte format*/
475 old_csp_long = (s32b)((p->csp << 16) + p->csp_frac);
476 new_csp_long = old_csp_long + sp_gain;
477
478 /* Check for overflow */
479
480 /* new_csp = LONG_MAX LONG_MIN;} DAVIDTODO produces warning*/
481 if ((new_csp_long < 0) && (old_csp_long > 0) && (sp_gain > 0)) {
482 new_csp_long = INT32_MAX;
483 sp_gain = 0;
484 } else if ((new_csp_long > 0) && (old_csp_long < 0) && (sp_gain < 0)) {
485 new_csp_long = INT32_MIN;
486 sp_gain = 0;
487 }
488
489 /* Break it back down*/
490 p->csp = (s16b)(new_csp_long >> 16); /* div 65536 */
491 p->csp_frac = (u16b)(new_csp_long & 0xFFFF); /* mod 65536 */
492
493 /* Max/min SP */
494 if (p->csp >= p->msp) {
495 p->csp = p->msp;
496 p->csp_frac = 0;
497 sp_gain = 0;
498 } else if (p->csp < 0) {
499 p->csp = 0;
500 p->csp_frac = 0;
501 sp_gain = 0;
502 }
503
504 /* Notice changes */
505 if (old_csp_short != p->csp) {
506 p->upkeep->redraw |= (PR_MANA);
507 }
508
509 if (sp_gain == 0) {
510 /* Recalculate */
511 new_csp_long = (s32b)((p->csp << 16) + p->csp_frac);
512 sp_gain = new_csp_long - old_csp_long;
513 }
514
515 return sp_gain;
516 }
517
convert_mana_to_hp(struct player * p,s32b sp_long)518 void convert_mana_to_hp(struct player *p, s32b sp_long) {
519 s32b hp_gain, sp_ratio;
520
521 if (sp_long <= 0 || p->msp == 0 || p->mhp == p->chp) return;
522
523 /* Total HP from max */
524 hp_gain = (s32b)((p->mhp - p->chp) << 16);
525 hp_gain -= (s32b)p->chp_frac;
526
527 /* Spend X% of SP get X/2% of lost HP. E.g., at 50% HP get X/4% */
528 /* Gain stays low at msp<10 because MP gains are generous at msp<10 */
529 /* sp_ratio is max sp to spent sp, doubled to suit target rate. */
530 sp_ratio = (MAX(10, (s32b)p->msp) << 16) * 2 / sp_long;
531
532 /* Limit max healing to 25% of damage; ergo spending > 50% msp
533 * is inefficient */
534 if (sp_ratio < 4) {sp_ratio = 4;}
535 hp_gain /= sp_ratio;
536
537 /* DAVIDTODO Flavorful comments on large gains would be fun and informative */
538
539 player_adjust_hp_precise(p, hp_gain);
540 }
541
542 /**
543 * Update the player's light fuel
544 */
player_update_light(struct player * p)545 void player_update_light(struct player *p)
546 {
547 /* Check for light being wielded */
548 struct object *obj = equipped_item_by_slot_name(p, "light");
549
550 /* Burn some fuel in the current light */
551 if (obj && tval_is_light(obj)) {
552 bool burn_fuel = true;
553
554 /* Turn off the wanton burning of light during the day in the town */
555 if (!p->depth && is_daytime())
556 burn_fuel = false;
557
558 /* If the light has the NO_FUEL flag, well... */
559 if (of_has(obj->flags, OF_NO_FUEL))
560 burn_fuel = false;
561
562 /* Use some fuel (except on artifacts, or during the day) */
563 if (burn_fuel && obj->timeout > 0) {
564 /* Decrease life-span */
565 obj->timeout--;
566
567 /* Hack -- notice interesting fuel steps */
568 if ((obj->timeout < 100) || (!(obj->timeout % 100)))
569 /* Redraw stuff */
570 p->upkeep->redraw |= (PR_EQUIP);
571
572 /* Hack -- Special treatment when blind */
573 if (p->timed[TMD_BLIND]) {
574 /* Hack -- save some light for later */
575 if (obj->timeout == 0) obj->timeout++;
576 } else if (obj->timeout == 0) {
577 /* The light is now out */
578 disturb(p);
579 msg("Your light has gone out!");
580
581 /* If it's a torch, now is the time to delete it */
582 if (of_has(obj->flags, OF_BURNS_OUT)) {
583 bool dummy;
584 struct object *burnt = gear_object_for_use(obj, 1, false,
585 &dummy);
586 if (burnt->known)
587 object_delete(&burnt->known);
588 object_delete(&burnt);
589 }
590 } else if ((obj->timeout < 50) && (!(obj->timeout % 20))) {
591 /* The light is getting dim */
592 disturb(p);
593 msg("Your light is growing faint.");
594 }
595 }
596 }
597
598 /* Calculate torch radius */
599 p->upkeep->update |= (PU_TORCH);
600 }
601
602 /**
603 * Find the player's best digging tool. If forbid_stack is true, ignores
604 * stacks of more than one item.
605 */
player_best_digger(struct player * p,bool forbid_stack)606 struct object *player_best_digger(struct player *p, bool forbid_stack)
607 {
608 int weapon_slot = slot_by_name(player, "weapon");
609 struct object *current_weapon = slot_object(player, weapon_slot);
610 struct object *obj, *best = NULL;
611 /* Prefer any melee weapon over unarmed digging, i.e. best == NULL. */
612 int best_score = -1;
613 struct player_state local_state;
614
615 for (obj = p->gear; obj; obj = obj->next) {
616 int score, old_number;
617 if (!tval_is_melee_weapon(obj)) continue;
618 if (obj->number < 1 || (forbid_stack && obj->number > 1)) continue;
619
620 /* Swap temporarily for the calc_bonuses() computation. */
621 old_number = obj->number;
622 if (obj != current_weapon) {
623 obj->number = 1;
624 p->body.slots[weapon_slot].obj = obj;
625 }
626
627 /*
628 * Avoid side effects from using update set to false
629 * with calc_bonuses().
630 */
631 local_state.stat_ind[STAT_STR] = 0;
632 local_state.stat_ind[STAT_DEX] = 0;
633 calc_bonuses(p, &local_state, true, false);
634 score = local_state.skills[SKILL_DIGGING];
635
636 /* Swap back. */
637 if (obj != current_weapon) {
638 obj->number = old_number;
639 player->body.slots[weapon_slot].obj = current_weapon;
640 }
641
642 if (score > best_score) {
643 best = obj;
644 best_score = score;
645 }
646 }
647
648 return best;
649 }
650
651 /**
652 * Melee a random adjacent monster
653 */
player_attack_random_monster(struct player * p)654 bool player_attack_random_monster(struct player *p)
655 {
656 int i, dir = randint0(8);
657
658 /* Confused players get a free pass */
659 if (p->timed[TMD_CONFUSED]) return false;
660
661 /* Look for a monster, attack */
662 for (i = 0; i < 8; i++, dir++) {
663 struct loc grid = loc_sum(player->grid, ddgrid_ddd[dir % 8]);
664 if (square_monster(cave, grid)) {
665 p->upkeep->energy_use = z_info->move_energy;
666 msg("You angrily lash out at a nearby foe!");
667 move_player(ddd[dir % 8], false);
668 return true;
669 }
670 }
671 return false;
672 }
673
674 /**
675 * Have random bad stuff happen to the player from over-exertion
676 *
677 * This function uses the PY_EXERT_* flags
678 */
player_over_exert(struct player * p,int flag,int chance,int amount)679 void player_over_exert(struct player *p, int flag, int chance, int amount)
680 {
681 if (chance <= 0) return;
682
683 /* CON damage */
684 if (flag & PY_EXERT_CON) {
685 if (randint0(100) < chance) {
686 /* Hack - only permanent with high chance (no-mana casting) */
687 bool perm = (randint0(100) < chance / 2) && (chance >= 50);
688 msg("You have damaged your health!");
689 player_stat_dec(p, STAT_CON, perm);
690 }
691 }
692
693 /* Fainting */
694 if (flag & PY_EXERT_FAINT) {
695 if (randint0(100) < chance) {
696 msg("You faint from the effort!");
697
698 /* Bypass free action */
699 (void)player_inc_timed(p, TMD_PARALYZED, randint1(amount),
700 true, false);
701 }
702 }
703
704 /* Scrambled stats */
705 if (flag & PY_EXERT_SCRAMBLE) {
706 if (randint0(100) < chance) {
707 (void)player_inc_timed(p, TMD_SCRAMBLE, randint1(amount),
708 true, true);
709 }
710 }
711
712 /* Cut damage */
713 if (flag & PY_EXERT_CUT) {
714 if (randint0(100) < chance) {
715 msg("Wounds appear on your body!");
716 (void)player_inc_timed(p, TMD_CUT, randint1(amount),
717 true, false);
718 }
719 }
720
721 /* Confusion */
722 if (flag & PY_EXERT_CONF) {
723 if (randint0(100) < chance) {
724 (void)player_inc_timed(p, TMD_CONFUSED, randint1(amount),
725 true, true);
726 }
727 }
728
729 /* Hallucination */
730 if (flag & PY_EXERT_HALLU) {
731 if (randint0(100) < chance) {
732 (void)player_inc_timed(p, TMD_IMAGE, randint1(amount),
733 true, true);
734 }
735 }
736
737 /* Slowing */
738 if (flag & PY_EXERT_SLOW) {
739 if (randint0(100) < chance) {
740 msg("You feel suddenly lethargic.");
741 (void)player_inc_timed(p, TMD_SLOW, randint1(amount),
742 true, false);
743 }
744 }
745
746 /* HP */
747 if (flag & PY_EXERT_HP) {
748 if (randint0(100) < chance) {
749 msg("You cry out in sudden pain!");
750 take_hit(p, randint1(amount), "over-exertion");
751 }
752 }
753 }
754
755
756 /**
757 * See how much damage the player will take from damaging terrain
758 */
player_check_terrain_damage(struct player * p,struct loc grid)759 int player_check_terrain_damage(struct player *p, struct loc grid)
760 {
761 int dam_taken = 0;
762
763 if (square_isfiery(cave, grid)) {
764 int base_dam = 100 + randint1(100);
765 int res = p->state.el_info[ELEM_FIRE].res_level;
766
767 /* Fire damage */
768 dam_taken = adjust_dam(p, ELEM_FIRE, base_dam, RANDOMISE, res, false);
769
770 /* Feather fall makes one lightfooted. */
771 if (player_of_has(p, OF_FEATHER)) {
772 dam_taken /= 2;
773 }
774 }
775
776 return dam_taken;
777 }
778
779 /**
780 * Terrain damages the player
781 */
player_take_terrain_damage(struct player * p,struct loc grid)782 void player_take_terrain_damage(struct player *p, struct loc grid)
783 {
784 int dam_taken = player_check_terrain_damage(p, grid);
785
786 if (!dam_taken) {
787 return;
788 }
789
790 /* Damage the player and inventory */
791 take_hit(player, dam_taken, square_feat(cave, grid)->die_msg);
792 if (square_isfiery(cave, grid)) {
793 msg(square_feat(cave, grid)->hurt_msg);
794 inven_damage(player, PROJ_FIRE, dam_taken);
795 }
796 }
797
798 /**
799 * Find a player shape from the name
800 */
lookup_player_shape(const char * name)801 struct player_shape *lookup_player_shape(const char *name)
802 {
803 struct player_shape *shape = shapes;
804 while (shape) {
805 if (streq(shape->name, name)) {
806 return shape;
807 }
808 shape = shape->next;
809 }
810 msg("Could not find %s shape!", name);
811 return NULL;
812 }
813
814 /**
815 * Find a player shape index from the shape name
816 */
shape_name_to_idx(const char * name)817 int shape_name_to_idx(const char *name)
818 {
819 struct player_shape *shape = lookup_player_shape(name);
820 if (shape) {
821 return shape->sidx;
822 } else {
823 return -1;
824 }
825 }
826
827 /**
828 * Find a player shape from the index
829 */
player_shape_by_idx(int index)830 struct player_shape *player_shape_by_idx(int index)
831 {
832 struct player_shape *shape = shapes;
833 while (shape) {
834 if (shape->sidx == index) {
835 return shape;
836 }
837 shape = shape->next;
838 }
839 msg("Could not find shape %d!", index);
840 return NULL;
841 }
842
843 /**
844 * Revert to normal shape
845 */
player_resume_normal_shape(struct player * p)846 void player_resume_normal_shape(struct player *p)
847 {
848 p->shape = lookup_player_shape("normal");
849 msg("You resume your usual shape.");
850
851 /* Kill vampire attack */
852 (void) player_clear_timed(p, TMD_ATT_VAMP, true);
853
854 /* Update */
855 player->upkeep->update |= (PU_BONUS);
856 player->upkeep->redraw |= (PR_TITLE | PR_MISC);
857 handle_stuff(player);
858 }
859
860 /**
861 * Check if the player is shapechanged
862 */
player_is_shapechanged(struct player * p)863 bool player_is_shapechanged(struct player *p)
864 {
865 return streq(p->shape->name, "normal") ? false : true;
866 }
867
868 /**
869 * Check if the player is immune from traps
870 */
player_is_trapsafe(struct player * p)871 bool player_is_trapsafe(struct player *p)
872 {
873 if (p->timed[TMD_TRAPSAFE]) return true;
874 if (player_of_has(p, OF_TRAP_IMMUNE)) return true;
875 return false;
876 }
877
878 /**
879 * Return true if the player can cast a spell.
880 *
881 * \param p is the player
882 * \param show_msg should be set to true if a failure message should be
883 * displayed.
884 */
player_can_cast(struct player * p,bool show_msg)885 bool player_can_cast(struct player *p, bool show_msg)
886 {
887 if (!p->class->magic.total_spells) {
888 if (show_msg) {
889 msg("You cannot pray or produce magics.");
890 }
891 return false;
892 }
893
894 if (p->timed[TMD_BLIND] || no_light()) {
895 if (show_msg) {
896 msg("You cannot see!");
897 }
898 return false;
899 }
900
901 if (p->timed[TMD_CONFUSED]) {
902 if (show_msg) {
903 msg("You are too confused!");
904 }
905 return false;
906 }
907
908 return true;
909 }
910
911 /**
912 * Return true if the player can study a spell.
913 *
914 * \param p is the player
915 * \param show_msg should be set to true if a failure message should be
916 * displayed.
917 */
player_can_study(struct player * p,bool show_msg)918 bool player_can_study(struct player *p, bool show_msg)
919 {
920 if (!player_can_cast(p, show_msg))
921 return false;
922
923 if (!p->upkeep->new_spells) {
924 if (show_msg) {
925 int count;
926 struct magic_realm *r = class_magic_realms(p->class, &count), *r1;
927 char buf[120];
928
929 my_strcpy(buf, r->spell_noun, sizeof(buf));
930 my_strcat(buf, "s", sizeof(buf));
931 r1 = r->next;
932 mem_free(r);
933 r = r1;
934 if (count > 1) {
935 while (r) {
936 count--;
937 if (count) {
938 my_strcat(buf, ", ", sizeof(buf));
939 } else {
940 my_strcat(buf, " or ", sizeof(buf));
941 }
942 my_strcat(buf, r->spell_noun, sizeof(buf));
943 my_strcat(buf, "s", sizeof(buf));
944 r1 = r->next;
945 mem_free(r);
946 r = r1;
947 }
948 }
949 msg("You cannot learn any new %s!", buf);
950 }
951 return false;
952 }
953
954 return true;
955 }
956
957 /**
958 * Return true if the player can read scrolls or books.
959 *
960 * \param p is the player
961 * \param show_msg should be set to true if a failure message should be
962 * displayed.
963 */
player_can_read(struct player * p,bool show_msg)964 bool player_can_read(struct player *p, bool show_msg)
965 {
966 if (p->timed[TMD_BLIND]) {
967 if (show_msg)
968 msg("You can't see anything.");
969
970 return false;
971 }
972
973 if (no_light()) {
974 if (show_msg)
975 msg("You have no light to read by.");
976
977 return false;
978 }
979
980 if (p->timed[TMD_CONFUSED]) {
981 if (show_msg)
982 msg("You are too confused to read!");
983
984 return false;
985 }
986
987 if (p->timed[TMD_AMNESIA]) {
988 if (show_msg)
989 msg("You can't remember how to read!");
990
991 return false;
992 }
993
994 return true;
995 }
996
997 /**
998 * Return true if the player can fire something with a launcher.
999 *
1000 * \param p is the player
1001 * \param show_msg should be set to true if a failure message should be
1002 * displayed.
1003 */
player_can_fire(struct player * p,bool show_msg)1004 bool player_can_fire(struct player *p, bool show_msg)
1005 {
1006 struct object *obj = equipped_item_by_slot_name(p, "shooting");
1007
1008 /* Require a usable launcher */
1009 if (!obj || !p->state.ammo_tval) {
1010 if (show_msg)
1011 msg("You have nothing to fire with.");
1012 return false;
1013 }
1014
1015 return true;
1016 }
1017
1018 /**
1019 * Return true if the player can refuel their light source.
1020 *
1021 * \param p is the player
1022 * \param show_msg should be set to true if a failure message should be
1023 * displayed.
1024 */
player_can_refuel(struct player * p,bool show_msg)1025 bool player_can_refuel(struct player *p, bool show_msg)
1026 {
1027 struct object *obj = equipped_item_by_slot_name(p, "light");
1028
1029 if (obj && of_has(obj->flags, OF_TAKES_FUEL)) {
1030 return true;
1031 }
1032
1033 if (show_msg) {
1034 msg("Your light cannot be refuelled.");
1035 }
1036
1037 return false;
1038 }
1039
1040 /**
1041 * Prerequiste function for command. See struct cmd_info in cmd-process.c.
1042 */
player_can_cast_prereq(void)1043 bool player_can_cast_prereq(void)
1044 {
1045 return player_can_cast(player, true);
1046 }
1047
1048 /**
1049 * Prerequiste function for command. See struct cmd_info in cmd-process.c.
1050 */
player_can_study_prereq(void)1051 bool player_can_study_prereq(void)
1052 {
1053 return player_can_study(player, true);
1054 }
1055
1056 /**
1057 * Prerequiste function for command. See struct cmd_info in cmd-process.c.
1058 */
player_can_read_prereq(void)1059 bool player_can_read_prereq(void)
1060 {
1061 return player_can_read(player, true);
1062 }
1063
1064 /**
1065 * Prerequiste function for command. See struct cmd_info in cmd-process.c.
1066 */
player_can_fire_prereq(void)1067 bool player_can_fire_prereq(void)
1068 {
1069 return player_can_fire(player, true);
1070 }
1071
1072 /**
1073 * Prerequiste function for command. See struct cmd_info in cmd-process.c.
1074 */
player_can_refuel_prereq(void)1075 bool player_can_refuel_prereq(void)
1076 {
1077 return player_can_refuel(player, true);
1078 }
1079
1080 /**
1081 * Return true if the player has access to a book that has unlearned spells.
1082 *
1083 * \param p is the player
1084 */
player_book_has_unlearned_spells(struct player * p)1085 bool player_book_has_unlearned_spells(struct player *p)
1086 {
1087 int i, j;
1088 int item_max = z_info->pack_size + z_info->floor_size;
1089 struct object **item_list = mem_zalloc(item_max * sizeof(struct object *));
1090 int item_num;
1091
1092 /* Check if the player can learn new spells */
1093 if (!p->upkeep->new_spells) {
1094 mem_free(item_list);
1095 return false;
1096 }
1097
1098 /* Check through all available books */
1099 item_num = scan_items(item_list, item_max, USE_INVEN | USE_FLOOR,
1100 obj_can_study);
1101 for (i = 0; i < item_num; i++) {
1102 const struct class_book *book = player_object_to_book(p, item_list[i]);
1103 if (!book) continue;
1104
1105 /* Extract spells */
1106 for (j = 0; j < book->num_spells; j++)
1107 if (spell_okay_to_study(book->spells[j].sidx)) {
1108 /* There is a spell the player can study */
1109 mem_free(item_list);
1110 return true;
1111 }
1112 }
1113
1114 mem_free(item_list);
1115 return false;
1116 }
1117
1118 /**
1119 * Apply confusion, if needed, to a direction
1120 *
1121 * Display a message and return true if direction changes.
1122 */
player_confuse_dir(struct player * p,int * dp,bool too)1123 bool player_confuse_dir(struct player *p, int *dp, bool too)
1124 {
1125 int dir = *dp;
1126
1127 if (p->timed[TMD_CONFUSED]) {
1128 if ((dir == 5) || (randint0(100) < 75)) {
1129 /* Random direction */
1130 dir = ddd[randint0(8)];
1131 }
1132
1133 /* Running attempts always fail */
1134 if (too) {
1135 msg("You are too confused.");
1136 return true;
1137 }
1138
1139 if (*dp != dir) {
1140 msg("You are confused.");
1141 *dp = dir;
1142 return true;
1143 }
1144 }
1145
1146 return false;
1147 }
1148
1149 /**
1150 * Return true if the provided count is one of the conditional REST_ flags.
1151 */
player_resting_is_special(s16b count)1152 bool player_resting_is_special(s16b count)
1153 {
1154 switch (count) {
1155 case REST_COMPLETE:
1156 case REST_ALL_POINTS:
1157 case REST_SOME_POINTS:
1158 return true;
1159 }
1160
1161 return false;
1162 }
1163
1164 /**
1165 * Return true if the player is resting.
1166 */
player_is_resting(struct player * p)1167 bool player_is_resting(struct player *p)
1168 {
1169 return (p->upkeep->resting > 0 ||
1170 player_resting_is_special(p->upkeep->resting));
1171 }
1172
1173 /**
1174 * Return the remaining number of resting turns.
1175 */
player_resting_count(struct player * p)1176 s16b player_resting_count(struct player *p)
1177 {
1178 return p->upkeep->resting;
1179 }
1180
1181 /**
1182 * In order to prevent the regeneration bonus from the first few turns, we have
1183 * to store the number of turns the player has rested. Otherwise, the first
1184 * few turns will have the bonus and the last few will not.
1185 */
1186 static int player_turns_rested = 0;
1187 static bool player_rest_disturb = false;
1188
1189 /**
1190 * Set the number of resting turns.
1191 *
1192 * \param count is the number of turns to rest or one of the REST_ constants.
1193 */
player_resting_set_count(struct player * p,s16b count)1194 void player_resting_set_count(struct player *p, s16b count)
1195 {
1196 /* Cancel if player is disturbed */
1197 if (player_rest_disturb) {
1198 p->upkeep->resting = 0;
1199 player_rest_disturb = false;
1200 return;
1201 }
1202
1203 /* Ignore if the rest count is negative. */
1204 if ((count < 0) && !player_resting_is_special(count)) {
1205 p->upkeep->resting = 0;
1206 return;
1207 }
1208
1209 /* Save the rest code */
1210 p->upkeep->resting = count;
1211
1212 /* Truncate overlarge values */
1213 if (p->upkeep->resting > 9999) p->upkeep->resting = 9999;
1214 }
1215
1216 /**
1217 * Cancel current rest.
1218 */
player_resting_cancel(struct player * p,bool disturb)1219 void player_resting_cancel(struct player *p, bool disturb)
1220 {
1221 player_resting_set_count(p, 0);
1222 player_turns_rested = 0;
1223 player_rest_disturb = disturb;
1224 }
1225
1226 /**
1227 * Return true if the player should get a regeneration bonus for the current
1228 * rest.
1229 */
player_resting_can_regenerate(struct player * p)1230 bool player_resting_can_regenerate(struct player *p)
1231 {
1232 return player_turns_rested >= REST_REQUIRED_FOR_REGEN ||
1233 player_resting_is_special(p->upkeep->resting);
1234 }
1235
1236 /**
1237 * Perform one turn of resting. This only handles the bookkeeping of resting
1238 * itself, and does not calculate any possible other effects of resting (see
1239 * process_world() for regeneration).
1240 */
player_resting_step_turn(struct player * p)1241 void player_resting_step_turn(struct player *p)
1242 {
1243 /* Timed rest */
1244 if (p->upkeep->resting > 0) {
1245 /* Reduce rest count */
1246 p->upkeep->resting--;
1247
1248 /* Redraw the state */
1249 p->upkeep->redraw |= (PR_STATE);
1250 }
1251
1252 /* Take a turn */
1253 p->upkeep->energy_use = z_info->move_energy;
1254
1255 /* Increment the resting counters */
1256 p->resting_turn++;
1257 player_turns_rested++;
1258 }
1259
1260 /**
1261 * Handle the conditions for conditional resting (resting with the REST_
1262 * constants).
1263 */
player_resting_complete_special(struct player * p)1264 void player_resting_complete_special(struct player *p)
1265 {
1266 /* Complete resting */
1267 if (!player_resting_is_special(p->upkeep->resting)) return;
1268
1269 if (p->upkeep->resting == REST_ALL_POINTS) {
1270 if ((p->chp == p->mhp) && (p->csp == p->msp))
1271 /* Stop resting */
1272 disturb(p);
1273 } else if (p->upkeep->resting == REST_COMPLETE) {
1274 if ((p->chp == p->mhp) &&
1275 (p->csp == p->msp || player_has(p, PF_COMBAT_REGEN)) &&
1276 !p->timed[TMD_BLIND] && !p->timed[TMD_CONFUSED] &&
1277 !p->timed[TMD_POISONED] && !p->timed[TMD_AFRAID] &&
1278 !p->timed[TMD_TERROR] && !p->timed[TMD_STUN] &&
1279 !p->timed[TMD_CUT] && !p->timed[TMD_SLOW] &&
1280 !p->timed[TMD_PARALYZED] && !p->timed[TMD_IMAGE] &&
1281 !p->word_recall && !p->deep_descent)
1282 /* Stop resting */
1283 disturb(p);
1284 } else if (p->upkeep->resting == REST_SOME_POINTS) {
1285 if ((p->chp == p->mhp) || (p->csp == p->msp))
1286 /* Stop resting */
1287 disturb(p);
1288 }
1289 }
1290
1291 /* Record the player's last rest count for repeating */
1292 static int player_resting_repeat_count = 0;
1293
1294 /**
1295 * Get the number of resting turns to repeat.
1296 *
1297 * \param p The current player.
1298 */
player_get_resting_repeat_count(struct player * p)1299 int player_get_resting_repeat_count(struct player *p)
1300 {
1301 return player_resting_repeat_count;
1302 }
1303
1304 /**
1305 * Set the number of resting turns to repeat.
1306 *
1307 * \param count is the number of turns requested for rest most recently.
1308 */
player_set_resting_repeat_count(struct player * p,s16b count)1309 void player_set_resting_repeat_count(struct player *p, s16b count)
1310 {
1311 player_resting_repeat_count = count;
1312 }
1313
1314 /**
1315 * Check if the player state has the given OF_ flag.
1316 */
player_of_has(struct player * p,int flag)1317 bool player_of_has(struct player *p, int flag)
1318 {
1319 assert(p);
1320 return of_has(p->state.flags, flag);
1321 }
1322
1323 /**
1324 * Check if the player resists (or better) an element
1325 */
player_resists(struct player * p,int element)1326 bool player_resists(struct player *p, int element)
1327 {
1328 return (p->state.el_info[element].res_level > 0);
1329 }
1330
1331 /**
1332 * Check if the player resists (or better) an element
1333 */
player_is_immune(struct player * p,int element)1334 bool player_is_immune(struct player *p, int element)
1335 {
1336 return (p->state.el_info[element].res_level == 3);
1337 }
1338
1339 /**
1340 * Places the player at the given coordinates in the cave.
1341 */
player_place(struct chunk * c,struct player * p,struct loc grid)1342 void player_place(struct chunk *c, struct player *p, struct loc grid)
1343 {
1344 assert(!square_monster(c, grid));
1345
1346 /* Save player location */
1347 p->grid = grid;
1348
1349 /* Mark cave grid */
1350 square_set_mon(c, grid, -1);
1351
1352 /* Clear stair creation */
1353 p->upkeep->create_down_stair = false;
1354 p->upkeep->create_up_stair = false;
1355 }
1356
1357 /*
1358 * Something has happened to disturb the player.
1359 *
1360 * The first arg indicates a major disturbance, which affects search.
1361 *
1362 * The second arg is currently unused, but could induce output flush.
1363 *
1364 * All disturbance cancels repeated commands, resting, and running.
1365 *
1366 * XXX-AS: Make callers either pass in a command
1367 * or call cmd_cancel_repeat inside the function calling this
1368 */
disturb(struct player * p)1369 void disturb(struct player *p)
1370 {
1371 /* Cancel repeated commands */
1372 cmd_cancel_repeat();
1373
1374 /* Cancel Resting */
1375 if (player_is_resting(p)) {
1376 player_resting_cancel(p, true);
1377 p->upkeep->redraw |= PR_STATE;
1378 }
1379
1380 /* Cancel running */
1381 if (p->upkeep->running) {
1382 p->upkeep->running = 0;
1383
1384 /* Cancel queued commands */
1385 cmdq_flush();
1386
1387 /* Check for new panel if appropriate */
1388 event_signal(EVENT_PLAYERMOVED);
1389 p->upkeep->update |= PU_TORCH;
1390
1391 /* Mark the whole map to be redrawn */
1392 event_signal_point(EVENT_MAP, -1, -1);
1393 }
1394
1395 /* Flush input */
1396 event_signal(EVENT_INPUT_FLUSH);
1397 }
1398
1399 /**
1400 * Search for traps or secret doors
1401 */
search(struct player * p)1402 void search(struct player *p)
1403 {
1404 struct loc grid;
1405
1406 /* Various conditions mean no searching */
1407 if (p->timed[TMD_BLIND] || no_light() ||
1408 p->timed[TMD_CONFUSED] || p->timed[TMD_IMAGE])
1409 return;
1410
1411 /* Search the nearby grids, which are always in bounds */
1412 for (grid.y = (p->grid.y - 1); grid.y <= (p->grid.y + 1); grid.y++) {
1413 for (grid.x = (p->grid.x - 1); grid.x <= (p->grid.x + 1); grid.x++) {
1414 struct object *obj;
1415
1416 /* Secret doors */
1417 if (square_issecretdoor(cave, grid)) {
1418 msg("You have found a secret door.");
1419 place_closed_door(cave, grid);
1420 disturb(p);
1421 }
1422
1423 /* Traps on chests */
1424 for (obj = square_object(cave, grid); obj; obj = obj->next) {
1425 if (!obj->known || !is_trapped_chest(obj))
1426 continue;
1427
1428 if (obj->known->pval != obj->pval) {
1429 msg("You have discovered a trap on the chest!");
1430 obj->known->pval = obj->pval;
1431 disturb(p);
1432 }
1433 }
1434 }
1435 }
1436 }
1437