1 /**
2  * \file player-calcs.c
3  * \brief Player status calculation, signalling ui events based on
4  *	status changes.
5  *
6  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
7  * Copyright (c) 2014 Nick McConnell
8  *
9  * This work is free software; you can redistribute it and/or modify it
10  * under the terms of either:
11  *
12  * a) the GNU General Public License as published by the Free Software
13  *    Foundation, version 2, or
14  *
15  * b) the "Angband licence":
16  *    This software may be copied and distributed for educational, research,
17  *    and not for profit purposes provided that this copyright and statement
18  *    are included in all such copies.  Other copyrights may also apply.
19  */
20 
21 #include "angband.h"
22 #include "cave.h"
23 #include "game-event.h"
24 #include "game-input.h"
25 #include "game-world.h"
26 #include "init.h"
27 #include "mon-msg.h"
28 #include "mon-util.h"
29 #include "obj-curse.h"
30 #include "obj-gear.h"
31 #include "obj-ignore.h"
32 #include "obj-knowledge.h"
33 #include "obj-power.h"
34 #include "obj-tval.h"
35 #include "obj-util.h"
36 #include "player-calcs.h"
37 #include "player-spell.h"
38 #include "player-timed.h"
39 #include "player-util.h"
40 
41 /**
42  * Stat Table (INT) -- Magic devices
43  */
44 static const int adj_int_dev[STAT_RANGE] =
45 {
46 	0	/* 3 */,
47 	0	/* 4 */,
48 	0	/* 5 */,
49 	0	/* 6 */,
50 	0	/* 7 */,
51 	1	/* 8 */,
52 	1	/* 9 */,
53 	1	/* 10 */,
54 	1	/* 11 */,
55 	1	/* 12 */,
56 	1	/* 13 */,
57 	1	/* 14 */,
58 	2	/* 15 */,
59 	2	/* 16 */,
60 	2	/* 17 */,
61 	3	/* 18/00-18/09 */,
62 	3	/* 18/10-18/19 */,
63 	3	/* 18/20-18/29 */,
64 	3	/* 18/30-18/39 */,
65 	3	/* 18/40-18/49 */,
66 	4	/* 18/50-18/59 */,
67 	4	/* 18/60-18/69 */,
68 	5	/* 18/70-18/79 */,
69 	5	/* 18/80-18/89 */,
70 	6	/* 18/90-18/99 */,
71 	6	/* 18/100-18/109 */,
72 	7	/* 18/110-18/119 */,
73 	7	/* 18/120-18/129 */,
74 	8	/* 18/130-18/139 */,
75 	8	/* 18/140-18/149 */,
76 	9	/* 18/150-18/159 */,
77 	9	/* 18/160-18/169 */,
78 	10	/* 18/170-18/179 */,
79 	10	/* 18/180-18/189 */,
80 	11	/* 18/190-18/199 */,
81 	11	/* 18/200-18/209 */,
82 	12	/* 18/210-18/219 */,
83 	13	/* 18/220+ */
84 };
85 
86 /**
87  * Stat Table (WIS) -- Saving throw
88  */
89 static const int adj_wis_sav[STAT_RANGE] =
90 {
91 	0	/* 3 */,
92 	0	/* 4 */,
93 	0	/* 5 */,
94 	0	/* 6 */,
95 	0	/* 7 */,
96 	1	/* 8 */,
97 	1	/* 9 */,
98 	1	/* 10 */,
99 	1	/* 11 */,
100 	1	/* 12 */,
101 	1	/* 13 */,
102 	1	/* 14 */,
103 	2	/* 15 */,
104 	2	/* 16 */,
105 	2	/* 17 */,
106 	3	/* 18/00-18/09 */,
107 	3	/* 18/10-18/19 */,
108 	3	/* 18/20-18/29 */,
109 	3	/* 18/30-18/39 */,
110 	3	/* 18/40-18/49 */,
111 	4	/* 18/50-18/59 */,
112 	4	/* 18/60-18/69 */,
113 	5	/* 18/70-18/79 */,
114 	5	/* 18/80-18/89 */,
115 	6	/* 18/90-18/99 */,
116 	7	/* 18/100-18/109 */,
117 	8	/* 18/110-18/119 */,
118 	9	/* 18/120-18/129 */,
119 	10	/* 18/130-18/139 */,
120 	11	/* 18/140-18/149 */,
121 	12	/* 18/150-18/159 */,
122 	13	/* 18/160-18/169 */,
123 	14	/* 18/170-18/179 */,
124 	15	/* 18/180-18/189 */,
125 	16	/* 18/190-18/199 */,
126 	17	/* 18/200-18/209 */,
127 	18	/* 18/210-18/219 */,
128 	19	/* 18/220+ */
129 };
130 
131 
132 /**
133  * Stat Table (DEX) -- disarming
134  */
135 static const int adj_dex_dis[STAT_RANGE] =
136 {
137 	0	/* 3 */,
138 	0	/* 4 */,
139 	0	/* 5 */,
140 	0	/* 6 */,
141 	0	/* 7 */,
142 	1	/* 8 */,
143 	1	/* 9 */,
144 	1	/* 10 */,
145 	1	/* 11 */,
146 	1	/* 12 */,
147 	1	/* 13 */,
148 	1	/* 14 */,
149 	2	/* 15 */,
150 	2	/* 16 */,
151 	2	/* 17 */,
152 	3	/* 18/00-18/09 */,
153 	3	/* 18/10-18/19 */,
154 	3	/* 18/20-18/29 */,
155 	4	/* 18/30-18/39 */,
156 	4	/* 18/40-18/49 */,
157 	5	/* 18/50-18/59 */,
158 	6	/* 18/60-18/69 */,
159 	7	/* 18/70-18/79 */,
160 	8	/* 18/80-18/89 */,
161 	9	/* 18/90-18/99 */,
162 	10	/* 18/100-18/109 */,
163 	10	/* 18/110-18/119 */,
164 	11	/* 18/120-18/129 */,
165 	12	/* 18/130-18/139 */,
166 	13	/* 18/140-18/149 */,
167 	14	/* 18/150-18/159 */,
168 	15	/* 18/160-18/169 */,
169 	16	/* 18/170-18/179 */,
170 	17	/* 18/180-18/189 */,
171 	18	/* 18/190-18/199 */,
172 	19	/* 18/200-18/209 */,
173 	19	/* 18/210-18/219 */,
174 	19	/* 18/220+ */
175 };
176 
177 
178 /**
179  * Stat Table (INT) -- disarming
180  */
181 static const int adj_int_dis[STAT_RANGE] =
182 {
183 	0	/* 3 */,
184 	0	/* 4 */,
185 	0	/* 5 */,
186 	0	/* 6 */,
187 	0	/* 7 */,
188 	1	/* 8 */,
189 	1	/* 9 */,
190 	1	/* 10 */,
191 	1	/* 11 */,
192 	1	/* 12 */,
193 	1	/* 13 */,
194 	1	/* 14 */,
195 	2	/* 15 */,
196 	2	/* 16 */,
197 	2	/* 17 */,
198 	3	/* 18/00-18/09 */,
199 	3	/* 18/10-18/19 */,
200 	3	/* 18/20-18/29 */,
201 	4	/* 18/30-18/39 */,
202 	4	/* 18/40-18/49 */,
203 	5	/* 18/50-18/59 */,
204 	6	/* 18/60-18/69 */,
205 	7	/* 18/70-18/79 */,
206 	8	/* 18/80-18/89 */,
207 	9	/* 18/90-18/99 */,
208 	10	/* 18/100-18/109 */,
209 	10	/* 18/110-18/119 */,
210 	11	/* 18/120-18/129 */,
211 	12	/* 18/130-18/139 */,
212 	13	/* 18/140-18/149 */,
213 	14	/* 18/150-18/159 */,
214 	15	/* 18/160-18/169 */,
215 	16	/* 18/170-18/179 */,
216 	17	/* 18/180-18/189 */,
217 	18	/* 18/190-18/199 */,
218 	19	/* 18/200-18/209 */,
219 	19	/* 18/210-18/219 */,
220 	19	/* 18/220+ */
221 };
222 
223 /**
224  * Stat Table (DEX) -- bonus to ac
225  */
226 static const int adj_dex_ta[STAT_RANGE] =
227 {
228 	-4	/* 3 */,
229 	-3	/* 4 */,
230 	-2	/* 5 */,
231 	-1	/* 6 */,
232 	0	/* 7 */,
233 	0	/* 8 */,
234 	0	/* 9 */,
235 	0	/* 10 */,
236 	0	/* 11 */,
237 	0	/* 12 */,
238 	0	/* 13 */,
239 	0	/* 14 */,
240 	1	/* 15 */,
241 	1	/* 16 */,
242 	1	/* 17 */,
243 	2	/* 18/00-18/09 */,
244 	2	/* 18/10-18/19 */,
245 	2	/* 18/20-18/29 */,
246 	2	/* 18/30-18/39 */,
247 	2	/* 18/40-18/49 */,
248 	3	/* 18/50-18/59 */,
249 	3	/* 18/60-18/69 */,
250 	3	/* 18/70-18/79 */,
251 	4	/* 18/80-18/89 */,
252 	5	/* 18/90-18/99 */,
253 	6	/* 18/100-18/109 */,
254 	7	/* 18/110-18/119 */,
255 	8	/* 18/120-18/129 */,
256 	9	/* 18/130-18/139 */,
257 	9	/* 18/140-18/149 */,
258 	10	/* 18/150-18/159 */,
259 	11	/* 18/160-18/169 */,
260 	12	/* 18/170-18/179 */,
261 	13	/* 18/180-18/189 */,
262 	14	/* 18/190-18/199 */,
263 	15	/* 18/200-18/209 */,
264 	15	/* 18/210-18/219 */,
265 	15	/* 18/220+ */
266 };
267 
268 /**
269  * Stat Table (STR) -- bonus to dam
270  */
271 const int adj_str_td[STAT_RANGE] =
272 {
273 	-2	/* 3 */,
274 	-2	/* 4 */,
275 	-1	/* 5 */,
276 	-1	/* 6 */,
277 	0	/* 7 */,
278 	0	/* 8 */,
279 	0	/* 9 */,
280 	0	/* 10 */,
281 	0	/* 11 */,
282 	0	/* 12 */,
283 	0	/* 13 */,
284 	0	/* 14 */,
285 	0	/* 15 */,
286 	1	/* 16 */,
287 	2	/* 17 */,
288 	2	/* 18/00-18/09 */,
289 	2	/* 18/10-18/19 */,
290 	3	/* 18/20-18/29 */,
291 	3	/* 18/30-18/39 */,
292 	3	/* 18/40-18/49 */,
293 	3	/* 18/50-18/59 */,
294 	3	/* 18/60-18/69 */,
295 	4	/* 18/70-18/79 */,
296 	5	/* 18/80-18/89 */,
297 	5	/* 18/90-18/99 */,
298 	6	/* 18/100-18/109 */,
299 	7	/* 18/110-18/119 */,
300 	8	/* 18/120-18/129 */,
301 	9	/* 18/130-18/139 */,
302 	10	/* 18/140-18/149 */,
303 	11	/* 18/150-18/159 */,
304 	12	/* 18/160-18/169 */,
305 	13	/* 18/170-18/179 */,
306 	14	/* 18/180-18/189 */,
307 	15	/* 18/190-18/199 */,
308 	16	/* 18/200-18/209 */,
309 	18	/* 18/210-18/219 */,
310 	20	/* 18/220+ */
311 };
312 
313 
314 /**
315  * Stat Table (DEX) -- bonus to hit
316  */
317 const int adj_dex_th[STAT_RANGE] =
318 {
319 	-3	/* 3 */,
320 	-2	/* 4 */,
321 	-2	/* 5 */,
322 	-1	/* 6 */,
323 	-1	/* 7 */,
324 	0	/* 8 */,
325 	0	/* 9 */,
326 	0	/* 10 */,
327 	0	/* 11 */,
328 	0	/* 12 */,
329 	0	/* 13 */,
330 	0	/* 14 */,
331 	0	/* 15 */,
332 	1	/* 16 */,
333 	2	/* 17 */,
334 	3	/* 18/00-18/09 */,
335 	3	/* 18/10-18/19 */,
336 	3	/* 18/20-18/29 */,
337 	3	/* 18/30-18/39 */,
338 	3	/* 18/40-18/49 */,
339 	4	/* 18/50-18/59 */,
340 	4	/* 18/60-18/69 */,
341 	4	/* 18/70-18/79 */,
342 	4	/* 18/80-18/89 */,
343 	5	/* 18/90-18/99 */,
344 	6	/* 18/100-18/109 */,
345 	7	/* 18/110-18/119 */,
346 	8	/* 18/120-18/129 */,
347 	9	/* 18/130-18/139 */,
348 	9	/* 18/140-18/149 */,
349 	10	/* 18/150-18/159 */,
350 	11	/* 18/160-18/169 */,
351 	12	/* 18/170-18/179 */,
352 	13	/* 18/180-18/189 */,
353 	14	/* 18/190-18/199 */,
354 	15	/* 18/200-18/209 */,
355 	15	/* 18/210-18/219 */,
356 	15	/* 18/220+ */
357 };
358 
359 
360 /**
361  * Stat Table (STR) -- bonus to hit
362  */
363 static const int adj_str_th[STAT_RANGE] =
364 {
365 	-3	/* 3 */,
366 	-2	/* 4 */,
367 	-1	/* 5 */,
368 	-1	/* 6 */,
369 	0	/* 7 */,
370 	0	/* 8 */,
371 	0	/* 9 */,
372 	0	/* 10 */,
373 	0	/* 11 */,
374 	0	/* 12 */,
375 	0	/* 13 */,
376 	0	/* 14 */,
377 	0	/* 15 */,
378 	0	/* 16 */,
379 	0	/* 17 */,
380 	1	/* 18/00-18/09 */,
381 	1	/* 18/10-18/19 */,
382 	1	/* 18/20-18/29 */,
383 	1	/* 18/30-18/39 */,
384 	1	/* 18/40-18/49 */,
385 	1	/* 18/50-18/59 */,
386 	1	/* 18/60-18/69 */,
387 	2	/* 18/70-18/79 */,
388 	3	/* 18/80-18/89 */,
389 	4	/* 18/90-18/99 */,
390 	5	/* 18/100-18/109 */,
391 	6	/* 18/110-18/119 */,
392 	7	/* 18/120-18/129 */,
393 	8	/* 18/130-18/139 */,
394 	9	/* 18/140-18/149 */,
395 	10	/* 18/150-18/159 */,
396 	11	/* 18/160-18/169 */,
397 	12	/* 18/170-18/179 */,
398 	13	/* 18/180-18/189 */,
399 	14	/* 18/190-18/199 */,
400 	15	/* 18/200-18/209 */,
401 	15	/* 18/210-18/219 */,
402 	15	/* 18/220+ */
403 };
404 
405 
406 /**
407  * Stat Table (STR) -- weight limit in deca-pounds
408  */
409 static const int adj_str_wgt[STAT_RANGE] =
410 {
411 	5	/* 3 */,
412 	6	/* 4 */,
413 	7	/* 5 */,
414 	8	/* 6 */,
415 	9	/* 7 */,
416 	10	/* 8 */,
417 	11	/* 9 */,
418 	12	/* 10 */,
419 	13	/* 11 */,
420 	14	/* 12 */,
421 	15	/* 13 */,
422 	16	/* 14 */,
423 	17	/* 15 */,
424 	18	/* 16 */,
425 	19	/* 17 */,
426 	20	/* 18/00-18/09 */,
427 	22	/* 18/10-18/19 */,
428 	24	/* 18/20-18/29 */,
429 	26	/* 18/30-18/39 */,
430 	28	/* 18/40-18/49 */,
431 	30	/* 18/50-18/59 */,
432 	30	/* 18/60-18/69 */,
433 	30	/* 18/70-18/79 */,
434 	30	/* 18/80-18/89 */,
435 	30	/* 18/90-18/99 */,
436 	30	/* 18/100-18/109 */,
437 	30	/* 18/110-18/119 */,
438 	30	/* 18/120-18/129 */,
439 	30	/* 18/130-18/139 */,
440 	30	/* 18/140-18/149 */,
441 	30	/* 18/150-18/159 */,
442 	30	/* 18/160-18/169 */,
443 	30	/* 18/170-18/179 */,
444 	30	/* 18/180-18/189 */,
445 	30	/* 18/190-18/199 */,
446 	30	/* 18/200-18/209 */,
447 	30	/* 18/210-18/219 */,
448 	30	/* 18/220+ */
449 };
450 
451 
452 /**
453  * Stat Table (STR) -- weapon weight limit in pounds
454  */
455 const int adj_str_hold[STAT_RANGE] =
456 {
457 	4	/* 3 */,
458 	5	/* 4 */,
459 	6	/* 5 */,
460 	7	/* 6 */,
461 	8	/* 7 */,
462 	10	/* 8 */,
463 	12	/* 9 */,
464 	14	/* 10 */,
465 	16	/* 11 */,
466 	18	/* 12 */,
467 	20	/* 13 */,
468 	22	/* 14 */,
469 	24	/* 15 */,
470 	26	/* 16 */,
471 	28	/* 17 */,
472 	30	/* 18/00-18/09 */,
473 	30	/* 18/10-18/19 */,
474 	35	/* 18/20-18/29 */,
475 	40	/* 18/30-18/39 */,
476 	45	/* 18/40-18/49 */,
477 	50	/* 18/50-18/59 */,
478 	55	/* 18/60-18/69 */,
479 	60	/* 18/70-18/79 */,
480 	65	/* 18/80-18/89 */,
481 	70	/* 18/90-18/99 */,
482 	80	/* 18/100-18/109 */,
483 	80	/* 18/110-18/119 */,
484 	80	/* 18/120-18/129 */,
485 	80	/* 18/130-18/139 */,
486 	80	/* 18/140-18/149 */,
487 	90	/* 18/150-18/159 */,
488 	90	/* 18/160-18/169 */,
489 	90	/* 18/170-18/179 */,
490 	90	/* 18/180-18/189 */,
491 	90	/* 18/190-18/199 */,
492 	100	/* 18/200-18/209 */,
493 	100	/* 18/210-18/219 */,
494 	100	/* 18/220+ */
495 };
496 
497 
498 /**
499  * Stat Table (STR) -- digging value
500  */
501 static const int adj_str_dig[STAT_RANGE] =
502 {
503 	0	/* 3 */,
504 	0	/* 4 */,
505 	1	/* 5 */,
506 	2	/* 6 */,
507 	3	/* 7 */,
508 	4	/* 8 */,
509 	4	/* 9 */,
510 	5	/* 10 */,
511 	5	/* 11 */,
512 	6	/* 12 */,
513 	6	/* 13 */,
514 	7	/* 14 */,
515 	7	/* 15 */,
516 	8	/* 16 */,
517 	8	/* 17 */,
518 	9	/* 18/00-18/09 */,
519 	10	/* 18/10-18/19 */,
520 	12	/* 18/20-18/29 */,
521 	15	/* 18/30-18/39 */,
522 	20	/* 18/40-18/49 */,
523 	25	/* 18/50-18/59 */,
524 	30	/* 18/60-18/69 */,
525 	35	/* 18/70-18/79 */,
526 	40	/* 18/80-18/89 */,
527 	45	/* 18/90-18/99 */,
528 	50	/* 18/100-18/109 */,
529 	55	/* 18/110-18/119 */,
530 	60	/* 18/120-18/129 */,
531 	65	/* 18/130-18/139 */,
532 	70	/* 18/140-18/149 */,
533 	75	/* 18/150-18/159 */,
534 	80	/* 18/160-18/169 */,
535 	85	/* 18/170-18/179 */,
536 	90	/* 18/180-18/189 */,
537 	95	/* 18/190-18/199 */,
538 	100	/* 18/200-18/209 */,
539 	100	/* 18/210-18/219 */,
540 	100	/* 18/220+ */
541 };
542 
543 
544 /**
545  * Stat Table (STR) -- help index into the "blow" table
546  */
547 const int adj_str_blow[STAT_RANGE] =
548 {
549 	3	/* 3 */,
550 	4	/* 4 */,
551 	5	/* 5 */,
552 	6	/* 6 */,
553 	7	/* 7 */,
554 	8	/* 8 */,
555 	9	/* 9 */,
556 	10	/* 10 */,
557 	11	/* 11 */,
558 	12	/* 12 */,
559 	13	/* 13 */,
560 	14	/* 14 */,
561 	15	/* 15 */,
562 	16	/* 16 */,
563 	17	/* 17 */,
564 	20 /* 18/00-18/09 */,
565 	30 /* 18/10-18/19 */,
566 	40 /* 18/20-18/29 */,
567 	50 /* 18/30-18/39 */,
568 	60 /* 18/40-18/49 */,
569 	70 /* 18/50-18/59 */,
570 	80 /* 18/60-18/69 */,
571 	90 /* 18/70-18/79 */,
572 	100 /* 18/80-18/89 */,
573 	110 /* 18/90-18/99 */,
574 	120 /* 18/100-18/109 */,
575 	130 /* 18/110-18/119 */,
576 	140 /* 18/120-18/129 */,
577 	150 /* 18/130-18/139 */,
578 	160 /* 18/140-18/149 */,
579 	170 /* 18/150-18/159 */,
580 	180 /* 18/160-18/169 */,
581 	190 /* 18/170-18/179 */,
582 	200 /* 18/180-18/189 */,
583 	210 /* 18/190-18/199 */,
584 	220 /* 18/200-18/209 */,
585 	230 /* 18/210-18/219 */,
586 	240 /* 18/220+ */
587 };
588 
589 
590 /**
591  * Stat Table (DEX) -- index into the "blow" table
592  */
593 static const int adj_dex_blow[STAT_RANGE] =
594 {
595 	0	/* 3 */,
596 	0	/* 4 */,
597 	0	/* 5 */,
598 	0	/* 6 */,
599 	0	/* 7 */,
600 	0	/* 8 */,
601 	0	/* 9 */,
602 	1	/* 10 */,
603 	1	/* 11 */,
604 	1	/* 12 */,
605 	1	/* 13 */,
606 	1	/* 14 */,
607 	1	/* 15 */,
608 	1	/* 16 */,
609 	2	/* 17 */,
610 	2	/* 18/00-18/09 */,
611 	2	/* 18/10-18/19 */,
612 	3	/* 18/20-18/29 */,
613 	3	/* 18/30-18/39 */,
614 	4	/* 18/40-18/49 */,
615 	4	/* 18/50-18/59 */,
616 	5	/* 18/60-18/69 */,
617 	5	/* 18/70-18/79 */,
618 	6	/* 18/80-18/89 */,
619 	6	/* 18/90-18/99 */,
620 	7	/* 18/100-18/109 */,
621 	7	/* 18/110-18/119 */,
622 	8	/* 18/120-18/129 */,
623 	8	/* 18/130-18/139 */,
624 	8	/* 18/140-18/149 */,
625 	9	/* 18/150-18/159 */,
626 	9	/* 18/160-18/169 */,
627 	9	/* 18/170-18/179 */,
628 	10	/* 18/180-18/189 */,
629 	10	/* 18/190-18/199 */,
630 	11	/* 18/200-18/209 */,
631 	11	/* 18/210-18/219 */,
632 	11	/* 18/220+ */
633 };
634 
635 
636 /**
637  * Stat Table (DEX) -- chance of avoiding "theft" and "falling"
638  */
639 const int adj_dex_safe[STAT_RANGE] =
640 {
641 	0	/* 3 */,
642 	1	/* 4 */,
643 	2	/* 5 */,
644 	3	/* 6 */,
645 	4	/* 7 */,
646 	5	/* 8 */,
647 	5	/* 9 */,
648 	6	/* 10 */,
649 	6	/* 11 */,
650 	7	/* 12 */,
651 	7	/* 13 */,
652 	8	/* 14 */,
653 	8	/* 15 */,
654 	9	/* 16 */,
655 	9	/* 17 */,
656 	10	/* 18/00-18/09 */,
657 	10	/* 18/10-18/19 */,
658 	15	/* 18/20-18/29 */,
659 	15	/* 18/30-18/39 */,
660 	20	/* 18/40-18/49 */,
661 	25	/* 18/50-18/59 */,
662 	30	/* 18/60-18/69 */,
663 	35	/* 18/70-18/79 */,
664 	40	/* 18/80-18/89 */,
665 	45	/* 18/90-18/99 */,
666 	50	/* 18/100-18/109 */,
667 	60	/* 18/110-18/119 */,
668 	70	/* 18/120-18/129 */,
669 	80	/* 18/130-18/139 */,
670 	90	/* 18/140-18/149 */,
671 	100	/* 18/150-18/159 */,
672 	100	/* 18/160-18/169 */,
673 	100	/* 18/170-18/179 */,
674 	100	/* 18/180-18/189 */,
675 	100	/* 18/190-18/199 */,
676 	100	/* 18/200-18/209 */,
677 	100	/* 18/210-18/219 */,
678 	100	/* 18/220+ */
679 };
680 
681 
682 /**
683  * Stat Table (CON) -- base regeneration rate
684  */
685 const int adj_con_fix[STAT_RANGE] =
686 {
687 	0	/* 3 */,
688 	0	/* 4 */,
689 	0	/* 5 */,
690 	0	/* 6 */,
691 	0	/* 7 */,
692 	0	/* 8 */,
693 	0	/* 9 */,
694 	0	/* 10 */,
695 	0	/* 11 */,
696 	0	/* 12 */,
697 	0	/* 13 */,
698 	1	/* 14 */,
699 	1	/* 15 */,
700 	1	/* 16 */,
701 	1	/* 17 */,
702 	2	/* 18/00-18/09 */,
703 	2	/* 18/10-18/19 */,
704 	2	/* 18/20-18/29 */,
705 	2	/* 18/30-18/39 */,
706 	2	/* 18/40-18/49 */,
707 	3	/* 18/50-18/59 */,
708 	3	/* 18/60-18/69 */,
709 	3	/* 18/70-18/79 */,
710 	3	/* 18/80-18/89 */,
711 	3	/* 18/90-18/99 */,
712 	4	/* 18/100-18/109 */,
713 	4	/* 18/110-18/119 */,
714 	5	/* 18/120-18/129 */,
715 	6	/* 18/130-18/139 */,
716 	6	/* 18/140-18/149 */,
717 	7	/* 18/150-18/159 */,
718 	7	/* 18/160-18/169 */,
719 	8	/* 18/170-18/179 */,
720 	8	/* 18/180-18/189 */,
721 	8	/* 18/190-18/199 */,
722 	9	/* 18/200-18/209 */,
723 	9	/* 18/210-18/219 */,
724 	9	/* 18/220+ */
725 };
726 
727 
728 /**
729  * Stat Table (CON) -- extra 1/100th hitpoints per level
730  */
731 static const int adj_con_mhp[STAT_RANGE] =
732 {
733 	-250	/* 3 */,
734 	-150	/* 4 */,
735 	-100	/* 5 */,
736 	 -75	/* 6 */,
737 	 -50	/* 7 */,
738 	 -25	/* 8 */,
739 	 -10	/* 9 */,
740 	  -5	/* 10 */,
741 	   0	/* 11 */,
742 	   5	/* 12 */,
743 	  10	/* 13 */,
744 	  25	/* 14 */,
745 	  50	/* 15 */,
746 	  75	/* 16 */,
747 	 100	/* 17 */,
748 	 150	/* 18/00-18/09 */,
749 	 175	/* 18/10-18/19 */,
750 	 200	/* 18/20-18/29 */,
751 	 225	/* 18/30-18/39 */,
752 	 250	/* 18/40-18/49 */,
753 	 275	/* 18/50-18/59 */,
754 	 300	/* 18/60-18/69 */,
755 	 350	/* 18/70-18/79 */,
756 	 400	/* 18/80-18/89 */,
757 	 450	/* 18/90-18/99 */,
758 	 500	/* 18/100-18/109 */,
759 	 550	/* 18/110-18/119 */,
760 	 600	/* 18/120-18/129 */,
761 	 650	/* 18/130-18/139 */,
762 	 700	/* 18/140-18/149 */,
763 	 750	/* 18/150-18/159 */,
764 	 800	/* 18/160-18/169 */,
765 	 900	/* 18/170-18/179 */,
766 	1000	/* 18/180-18/189 */,
767 	1100	/* 18/190-18/199 */,
768 	1250	/* 18/200-18/209 */,
769 	1250	/* 18/210-18/219 */,
770 	1250	/* 18/220+ */
771 };
772 
773 static const int adj_mag_study[STAT_RANGE] =
774 {
775 	  0	/* 3 */,
776 	  0	/* 4 */,
777 	 10	/* 5 */,
778 	 20	/* 6 */,
779 	 30	/* 7 */,
780 	 40	/* 8 */,
781 	 50	/* 9 */,
782 	 60	/* 10 */,
783 	 70	/* 11 */,
784 	 80	/* 12 */,
785 	 85	/* 13 */,
786 	 90	/* 14 */,
787 	 95	/* 15 */,
788 	100	/* 16 */,
789 	105	/* 17 */,
790 	110	/* 18/00-18/09 */,
791 	115	/* 18/10-18/19 */,
792 	120	/* 18/20-18/29 */,
793 	130	/* 18/30-18/39 */,
794 	140	/* 18/40-18/49 */,
795 	150	/* 18/50-18/59 */,
796 	160	/* 18/60-18/69 */,
797 	170	/* 18/70-18/79 */,
798 	180	/* 18/80-18/89 */,
799 	190	/* 18/90-18/99 */,
800 	200	/* 18/100-18/109 */,
801 	210	/* 18/110-18/119 */,
802 	220	/* 18/120-18/129 */,
803 	230	/* 18/130-18/139 */,
804 	240	/* 18/140-18/149 */,
805 	250	/* 18/150-18/159 */,
806 	250	/* 18/160-18/169 */,
807 	250	/* 18/170-18/179 */,
808 	250	/* 18/180-18/189 */,
809 	250	/* 18/190-18/199 */,
810 	250	/* 18/200-18/209 */,
811 	250	/* 18/210-18/219 */,
812 	250	/* 18/220+ */
813 };
814 
815 /**
816  * Stat Table (INT/WIS) -- extra 1/100 mana-points per level
817  */
818 static const int adj_mag_mana[STAT_RANGE] =
819 {
820 	  0	/* 3 */,
821 	 10	/* 4 */,
822 	 20	/* 5 */,
823 	 30	/* 6 */,
824 	 40	/* 7 */,
825 	 50	/* 8 */,
826 	 60	/* 9 */,
827 	 70	/* 10 */,
828 	 80	/* 11 */,
829 	 90	/* 12 */,
830 	100	/* 13 */,
831 	110	/* 14 */,
832 	120	/* 15 */,
833 	130	/* 16 */,
834 	140	/* 17 */,
835 	150	/* 18/00-18/09 */,
836 	160	/* 18/10-18/19 */,
837 	170	/* 18/20-18/29 */,
838 	180	/* 18/30-18/39 */,
839 	190	/* 18/40-18/49 */,
840 	200	/* 18/50-18/59 */,
841 	225	/* 18/60-18/69 */,
842 	250	/* 18/70-18/79 */,
843 	300	/* 18/80-18/89 */,
844 	350	/* 18/90-18/99 */,
845 	400	/* 18/100-18/109 */,
846 	450	/* 18/110-18/119 */,
847 	500	/* 18/120-18/129 */,
848 	550	/* 18/130-18/139 */,
849 	600	/* 18/140-18/149 */,
850 	650	/* 18/150-18/159 */,
851 	700	/* 18/160-18/169 */,
852 	750	/* 18/170-18/179 */,
853 	800	/* 18/180-18/189 */,
854 	800	/* 18/190-18/199 */,
855 	800	/* 18/200-18/209 */,
856 	800	/* 18/210-18/219 */,
857 	800	/* 18/220+ */
858 };
859 
860 /**
861  * This table is used to help calculate the number of blows the player can
862  * make in a single round of attacks (one player turn) with a normal weapon.
863  *
864  * This number ranges from a single blow/round for weak players to up to six
865  * blows/round for powerful warriors.
866  *
867  * Note that certain artifacts and ego-items give "bonus" blows/round.
868  *
869  * First, from the player class, we extract some values:
870  *
871  *    Warrior --> num = 6; mul = 5; div = MAX(30, weapon_weight);
872  *    Mage    --> num = 4; mul = 2; div = MAX(40, weapon_weight);
873  *    Priest  --> num = 4; mul = 3; div = MAX(35, weapon_weight);
874  *    Rogue   --> num = 5; mul = 4; div = MAX(30, weapon_weight);
875  *    Ranger  --> num = 5; mul = 4; div = MAX(35, weapon_weight);
876  *    Paladin --> num = 5; mul = 5; div = MAX(30, weapon_weight);
877  * (all specified in class.txt now)
878  *
879  * To get "P", we look up the relevant "adj_str_blow[]" (see above),
880  * multiply it by "mul", and then divide it by "div", rounding down.
881  *
882  * To get "D", we look up the relevant "adj_dex_blow[]" (see above).
883  *
884  * Then we look up the energy cost of each blow using "blows_table[P][D]".
885  * The player gets blows/round equal to 100/this number, up to a maximum of
886  * "num" blows/round, plus any "bonus" blows/round.
887  */
888 static const int blows_table[12][12] =
889 {
890 	/* P */
891    /* D:   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11+ */
892    /* DEX: 3,   10,  17,  /20, /40, /60, /80, /100,/120,/150,/180,/200 */
893 
894 	/* 0  */
895 	{  100, 100, 95,  85,  75,  60,  50,  42,  35,  30,  25,  23 },
896 
897 	/* 1  */
898 	{  100, 95,  85,  75,  60,  50,  42,  35,  30,  25,  23,  21 },
899 
900 	/* 2  */
901 	{  95,  85,  75,  60,  50,  42,  35,  30,  26,  23,  21,  20 },
902 
903 	/* 3  */
904 	{  85,  75,  60,  50,  42,  36,  32,  28,  25,  22,  20,  19 },
905 
906 	/* 4  */
907 	{  75,  60,  50,  42,  36,  33,  28,  25,  23,  21,  19,  18 },
908 
909 	/* 5  */
910 	{  60,  50,  42,  36,  33,  30,  27,  24,  22,  21,  19,  17 },
911 
912 	/* 6  */
913 	{  50,  42,  36,  33,  30,  27,  25,  23,  21,  20,  18,  17 },
914 
915 	/* 7  */
916 	{  42,  36,  33,  30,  28,  26,  24,  22,  20,  19,  18,  17 },
917 
918 	/* 8  */
919 	{  36,  33,  30,  28,  26,  24,  22,  21,  20,  19,  17,  16 },
920 
921 	/* 9  */
922 	{  35,  32,  29,  26,  24,  22,  21,  20,  19,  18,  17,  16 },
923 
924 	/* 10 */
925 	{  34,  30,  27,  25,  23,  22,  21,  20,  19,  18,  17,  16 },
926 
927 	/* 11+ */
928 	{  33,  29,  26,  24,  22,  21,  20,  19,  18,  17,  16,  15 },
929    /* DEX: 3,   10,  17,  /20, /40, /60, /80, /100,/120,/150,/180,/200 */
930 };
931 
932 /**
933  * Decide which object comes earlier in the standard inventory listing,
934  * defaulting to the first if nothing separates them.
935  *
936  * \return whether to replace the original object with the new one
937  */
earlier_object(struct object * orig,struct object * new,bool store)938 bool earlier_object(struct object *orig, struct object *new, bool store)
939 {
940 	/* Check we have actual objects */
941 	if (!new) return false;
942 	if (!orig) return true;
943 
944 	if (!store) {
945 		/* Readable books always come first */
946 		if (obj_can_browse(orig) && !obj_can_browse(new)) return false;
947 		if (!obj_can_browse(orig) && obj_can_browse(new)) return true;
948 	}
949 
950 	/* Usable ammo is before other ammo */
951 	if (tval_is_ammo(orig) && tval_is_ammo(new)) {
952 		/* First favour usable ammo */
953 		if ((player->state.ammo_tval == orig->tval) &&
954 			(player->state.ammo_tval != new->tval))
955 			return false;
956 		if ((player->state.ammo_tval != orig->tval) &&
957 			(player->state.ammo_tval == new->tval))
958 			return true;
959 	}
960 
961 	/* Objects sort by decreasing type */
962 	if (orig->tval > new->tval) return false;
963 	if (orig->tval < new->tval) return true;
964 
965 	if (!store) {
966 		/* Non-aware (flavored) items always come last (default to orig) */
967 		if (!object_flavor_is_aware(new)) return false;
968 		if (!object_flavor_is_aware(orig)) return true;
969 	}
970 
971 	/* Objects sort by increasing sval */
972 	if (orig->sval < new->sval) return false;
973 	if (orig->sval > new->sval) return true;
974 
975 	if (!store) {
976 		/* Unaware objects always come last (default to orig) */
977 		if (new->kind->flavor && !object_flavor_is_aware(new)) return false;
978 		if (orig->kind->flavor && !object_flavor_is_aware(orig)) return true;
979 
980 		/* Lights sort by decreasing fuel */
981 		if (tval_is_light(orig)) {
982 			if (orig->pval > new->pval) return false;
983 			if (orig->pval < new->pval) return true;
984 		}
985 	}
986 
987 	/* Objects sort by decreasing value, except ammo */
988 	if (tval_is_ammo(orig)) {
989 		if (object_value(orig, 1) < object_value(new, 1))
990 			return false;
991 		if (object_value(orig, 1) >	object_value(new, 1))
992 			return true;
993 	} else {
994 		if (object_value(orig, 1) >	object_value(new, 1))
995 			return false;
996 		if (object_value(orig, 1) <	object_value(new, 1))
997 			return true;
998 	}
999 
1000 	/* No preference */
1001 	return false;
1002 }
1003 
equipped_item_slot(struct player_body body,struct object * item)1004 int equipped_item_slot(struct player_body body, struct object *item)
1005 {
1006 	int i;
1007 
1008 	if (item == NULL) return body.count;
1009 
1010 	/* Look for an equipment slot with this item */
1011 	for (i = 0; i < body.count; i++)
1012 		if (item == body.slots[i].obj) break;
1013 
1014 	/* Correct slot, or body.count if not equipped */
1015 	return i;
1016 }
1017 
1018 /**
1019  * Put the player's inventory and quiver into easily accessible arrays.  The
1020  * pack may be overfull by one item
1021  */
calc_inventory(struct player_upkeep * upkeep,struct object * gear,struct player_body body)1022 void calc_inventory(struct player_upkeep *upkeep, struct object *gear,
1023 					struct player_body body)
1024 {
1025 	int i;
1026 	int old_inven_cnt = upkeep->inven_cnt;
1027 	struct object **old_quiver = mem_zalloc(z_info->quiver_size *
1028 												sizeof(struct object *));
1029 	struct object **old_pack = mem_zalloc(z_info->pack_size *
1030 											  sizeof(struct object *));
1031 
1032 	/* Prepare to fill the quiver */
1033 	upkeep->quiver_cnt = 0;
1034 
1035 	/* Copy the current quiver */
1036 	for (i = 0; i < z_info->quiver_size; i++)
1037 		if (upkeep->quiver[i])
1038 			old_quiver[i] = upkeep->quiver[i];
1039 		else
1040 			old_quiver[i] = NULL;
1041 
1042 	/* First, allocate inscribed items */
1043 	for (i = 0; i < z_info->quiver_size; i++) {
1044 		struct object *current;
1045 
1046 		/* Start with an empty slot */
1047 		upkeep->quiver[i] = NULL;
1048 
1049 		/* Find the first quiver object with the correct label */
1050 		for (current = gear; current; current = current->next) {
1051 			bool throwing = of_has(current->flags, OF_THROWING);
1052 
1053 			/* Only allow ammo and throwing weapons */
1054 			if (!(tval_is_ammo(current) || throwing)) continue;
1055 
1056 			/* Allocate inscribed objects if it's the right slot */
1057 			if (current->note) {
1058 				const char *s = strchr(quark_str(current->note), '@');
1059 				if (s && (s[1] == 'f' || s[1] == 'v')) {
1060 					int choice = s[2] - '0';
1061 
1062 					/* Correct slot, fill it straight away */
1063 					if (choice == i) {
1064 						int mult = tval_is_ammo(current) ? 1 : 5;
1065 						upkeep->quiver[i] = current;
1066 						upkeep->quiver_cnt += current->number * mult;
1067 
1068 						/* In the quiver counts as worn */
1069 						object_learn_on_wield(player, current);
1070 
1071 						/* Done with this slot */
1072 						break;
1073 					}
1074 				}
1075 			}
1076 		}
1077 	}
1078 
1079 	/* Now fill the rest of the slots in order */
1080 	for (i = 0; i < z_info->quiver_size; i++) {
1081 		struct object *current, *first = NULL;
1082 		int j;
1083 
1084 		/* If the slot is full, move on */
1085 		if (upkeep->quiver[i]) continue;
1086 
1087 		/* Find the first quiver object not yet allocated */
1088 		for (current = gear; current; current = current->next) {
1089 			bool already = false;
1090 
1091 			/* Ignore non-ammo */
1092 			if (!tval_is_ammo(current)) continue;
1093 
1094 			/* Ignore stuff already quivered */
1095 			for (j = 0; j < z_info->quiver_size; j++)
1096 				if (upkeep->quiver[j] == current)
1097 					already = true;
1098 			if (already) continue;
1099 
1100 			/* Choose the first in order */
1101 			if (earlier_object(first, current, false)) {
1102 				first = current;
1103 			}
1104 		}
1105 
1106 		/* Stop looking if there's nothing left */
1107 		if (!first) break;
1108 
1109 		/* If we have an item, slot it */
1110 		upkeep->quiver[i] = first;
1111 		upkeep->quiver_cnt += first->number;
1112 
1113 		/* In the quiver counts as worn */
1114 		object_learn_on_wield(player, first);
1115 	}
1116 
1117 	/* Note reordering */
1118 	if (character_dungeon)
1119 		for (i = 0; i < z_info->quiver_size; i++)
1120 			if (old_quiver[i] && (upkeep->quiver[i] != old_quiver[i])) {
1121 				msg("You re-arrange your quiver.");
1122 				break;
1123 			}
1124 
1125 	/* Copy the current pack */
1126 	for (i = 0; i < z_info->pack_size; i++)
1127 		old_pack[i] = upkeep->inven[i];
1128 
1129 	/* Prepare to fill the inventory */
1130 	upkeep->inven_cnt = 0;
1131 
1132 	for (i = 0; i <= z_info->pack_size; i++) {
1133 		struct object *current, *first = NULL;
1134 		for (current = gear; current; current = current->next) {
1135 			bool possible = true;
1136 			int j;
1137 
1138 			/* Skip equipment */
1139 			if (object_is_equipped(body, current))
1140 				possible = false;
1141 
1142 			/* Skip quivered objects */
1143 			for (j = 0; j < z_info->quiver_size; j++)
1144 				if (upkeep->quiver[j] == current)
1145 					possible = false;
1146 
1147 			/* Skip objects already allocated to the inventory */
1148 			for (j = 0; j < upkeep->inven_cnt; j++)
1149 				if (upkeep->inven[j] == current)
1150 					possible = false;
1151 
1152 			/* If still possible, choose the first in order */
1153 			if (!possible)
1154 				continue;
1155 			else if (earlier_object(first, current, false)) {
1156 				first = current;
1157 			}
1158 		}
1159 
1160 		/* Allocate */
1161 		upkeep->inven[i] = first;
1162 		if (first)
1163 			upkeep->inven_cnt++;
1164 	}
1165 
1166 	/* Note reordering */
1167 	if (character_dungeon && (upkeep->inven_cnt == old_inven_cnt))
1168 		for (i = 0; i < z_info->pack_size; i++)
1169 			if (old_pack[i] && (upkeep->inven[i] != old_pack[i]) &&
1170 				!object_is_equipped(body, old_pack[i])) {
1171 				msg("You re-arrange your pack.");
1172 				break;
1173 			}
1174 
1175 	mem_free(old_quiver);
1176 	mem_free(old_pack);
1177 }
1178 
update_inventory(struct player * p)1179 static void update_inventory(struct player *p)
1180 {
1181 	calc_inventory(p->upkeep, p->gear, p->body);
1182 }
1183 
1184 /**
1185  * Average of the player's spell stats across all the realms they can cast
1186  * from, rounded up
1187  *
1188  * If the player can only cast from a single realm, this is simple the stat
1189  * for that realm
1190  */
average_spell_stat(struct player * p,struct player_state * state)1191 static int average_spell_stat(struct player *p, struct player_state *state)
1192 {
1193 	int i, count, sum = 0;
1194 	struct magic_realm *realm = class_magic_realms(p->class, &count), *r_next;
1195 
1196 	for (i = count; i > 0; i--) {
1197 		sum += state->stat_ind[realm->stat];
1198 		r_next = realm->next;
1199 		mem_free(realm);
1200 		realm = r_next;
1201 	}
1202 	return (sum + count - 1) / count;
1203 }
1204 
1205 /**
1206  * Calculate number of spells player should have, and forget,
1207  * or remember, spells until that number is properly reflected.
1208  *
1209  * Note that this function induces various "status" messages,
1210  * which must be bypasses until the character is created.
1211  */
calc_spells(struct player * p)1212 static void calc_spells(struct player *p)
1213 {
1214 	int i, j, k, levels;
1215 	int num_allowed, num_known, num_total = p->class->magic.total_spells;
1216 	int percent_spells;
1217 
1218 	const struct class_spell *spell;
1219 
1220 	s16b old_spells;
1221 
1222 	/* Hack -- must be literate */
1223 	if (!p->class->magic.total_spells) return;
1224 
1225 	/* Hack -- wait for creation */
1226 	if (!character_generated) return;
1227 
1228 	/* Hack -- handle partial mode */
1229 	if (p->upkeep->only_partial) return;
1230 
1231 	/* Save the new_spells value */
1232 	old_spells = p->upkeep->new_spells;
1233 
1234 	/* Determine the number of spells allowed */
1235 	levels = p->lev - p->class->magic.spell_first + 1;
1236 
1237 	/* Hack -- no negative spells */
1238 	if (levels < 0) levels = 0;
1239 
1240 	/* Number of 1/100 spells per level (or something - needs clarifying) */
1241 	percent_spells = adj_mag_study[average_spell_stat(p, &p->state)];
1242 
1243 	/* Extract total allowed spells (rounded up) */
1244 	num_allowed = (((percent_spells * levels) + 50) / 100);
1245 
1246 	/* Assume none known */
1247 	num_known = 0;
1248 
1249 	/* Count the number of spells we know */
1250 	for (j = 0; j < num_total; j++)
1251 		if (p->spell_flags[j] & PY_SPELL_LEARNED)
1252 			num_known++;
1253 
1254 	/* See how many spells we must forget or may learn */
1255 	p->upkeep->new_spells = num_allowed - num_known;
1256 
1257 	/* Forget spells which are too hard */
1258 	for (i = num_total - 1; i >= 0; i--) {
1259 		/* Get the spell */
1260 		j = p->spell_order[i];
1261 
1262 		/* Skip non-spells */
1263 		if (j >= 99) continue;
1264 
1265 		/* Get the spell */
1266 		spell = spell_by_index(j);
1267 
1268 		/* Skip spells we are allowed to know */
1269 		if (spell->slevel <= p->lev) continue;
1270 
1271 		/* Is it known? */
1272 		if (p->spell_flags[j] & PY_SPELL_LEARNED) {
1273 			/* Mark as forgotten */
1274 			p->spell_flags[j] |= PY_SPELL_FORGOTTEN;
1275 
1276 			/* No longer known */
1277 			p->spell_flags[j] &= ~PY_SPELL_LEARNED;
1278 
1279 			/* Message */
1280 			msg("You have forgotten the %s of %s.", spell->realm->spell_noun,
1281 				spell->name);
1282 
1283 			/* One more can be learned */
1284 			p->upkeep->new_spells++;
1285 		}
1286 	}
1287 
1288 	/* Forget spells if we know too many spells */
1289 	for (i = num_total - 1; i >= 0; i--) {
1290 		/* Stop when possible */
1291 		if (p->upkeep->new_spells >= 0) break;
1292 
1293 		/* Get the (i+1)th spell learned */
1294 		j = p->spell_order[i];
1295 
1296 		/* Skip unknown spells */
1297 		if (j >= 99) continue;
1298 
1299 		/* Get the spell */
1300 		spell = spell_by_index(j);
1301 
1302 		/* Forget it (if learned) */
1303 		if (p->spell_flags[j] & PY_SPELL_LEARNED) {
1304 			/* Mark as forgotten */
1305 			p->spell_flags[j] |= PY_SPELL_FORGOTTEN;
1306 
1307 			/* No longer known */
1308 			p->spell_flags[j] &= ~PY_SPELL_LEARNED;
1309 
1310 			/* Message */
1311 			msg("You have forgotten the %s of %s.", spell->realm->spell_noun,
1312 				spell->name);
1313 
1314 			/* One more can be learned */
1315 			p->upkeep->new_spells++;
1316 		}
1317 	}
1318 
1319 	/* Check for spells to remember */
1320 	for (i = 0; i < num_total; i++) {
1321 		/* None left to remember */
1322 		if (p->upkeep->new_spells <= 0) break;
1323 
1324 		/* Get the next spell we learned */
1325 		j = p->spell_order[i];
1326 
1327 		/* Skip unknown spells */
1328 		if (j >= 99) break;
1329 
1330 		/* Get the spell */
1331 		spell = spell_by_index(j);
1332 
1333 		/* Skip spells we cannot remember */
1334 		if (spell->slevel > p->lev) continue;
1335 
1336 		/* First set of spells */
1337 		if (p->spell_flags[j] & PY_SPELL_FORGOTTEN) {
1338 			/* No longer forgotten */
1339 			p->spell_flags[j] &= ~PY_SPELL_FORGOTTEN;
1340 
1341 			/* Known once more */
1342 			p->spell_flags[j] |= PY_SPELL_LEARNED;
1343 
1344 			/* Message */
1345 			msg("You have remembered the %s of %s.", spell->realm->spell_noun,
1346 				spell->name);
1347 
1348 			/* One less can be learned */
1349 			p->upkeep->new_spells--;
1350 		}
1351 	}
1352 
1353 	/* Assume no spells available */
1354 	k = 0;
1355 
1356 	/* Count spells that can be learned */
1357 	for (j = 0; j < num_total; j++) {
1358 		/* Get the spell */
1359 		spell = spell_by_index(j);
1360 
1361 		/* Skip spells we cannot remember or don't exist */
1362 		if (!spell) continue;
1363 		if (spell->slevel > p->lev || spell->slevel == 0) continue;
1364 
1365 		/* Skip spells we already know */
1366 		if (p->spell_flags[j] & PY_SPELL_LEARNED)
1367 			continue;
1368 
1369 		/* Count it */
1370 		k++;
1371 	}
1372 
1373 	/* Cannot learn more spells than exist */
1374 	if (p->upkeep->new_spells > k) p->upkeep->new_spells = k;
1375 
1376 	/* Spell count changed */
1377 	if (old_spells != p->upkeep->new_spells) {
1378 		/* Message if needed */
1379 		if (p->upkeep->new_spells) {
1380 			int count;
1381 			struct magic_realm *r = class_magic_realms(p->class, &count), *r1;
1382 			char buf[120];
1383 
1384 			my_strcpy(buf, r->spell_noun, sizeof(buf));
1385 			if (p->upkeep->new_spells > 1) {
1386 				my_strcat(buf, "s", sizeof(buf));
1387 			}
1388 			r1 = r->next;
1389 			mem_free(r);
1390 			r = r1;
1391 			if (count > 1) {
1392 				while (r) {
1393 					count--;
1394 					if (count) {
1395 						my_strcat(buf, ", ", sizeof(buf));
1396 					} else {
1397 						my_strcat(buf, " or ", sizeof(buf));
1398 					}
1399 					my_strcat(buf, r->spell_noun, sizeof(buf));
1400 					if (p->upkeep->new_spells > 1) {
1401 						my_strcat(buf, "s", sizeof(buf));
1402 					}
1403 					r1 = r->next;
1404 					mem_free(r);
1405 					r = r1;
1406 				}
1407 			}
1408 			/* Message */
1409 			msg("You can learn %d more %s.", p->upkeep->new_spells, buf);
1410 		}
1411 
1412 		/* Redraw Study Status */
1413 		p->upkeep->redraw |= (PR_STUDY | PR_OBJECT);
1414 	}
1415 }
1416 
1417 
1418 /**
1419  * Calculate maximum mana.  You do not need to know any spells.
1420  * Note that mana is lowered by heavy (or inappropriate) armor.
1421  *
1422  * This function induces status messages.
1423  */
calc_mana(struct player * p,struct player_state * state,bool update)1424 static void calc_mana(struct player *p, struct player_state *state, bool update)
1425 {
1426 	int i, msp, levels, cur_wgt, max_wgt;
1427 
1428 	/* Must be literate */
1429 	if (!p->class->magic.total_spells) {
1430 		p->msp = 0;
1431 		p->csp = 0;
1432 		p->csp_frac = 0;
1433 		return;
1434 	}
1435 
1436 	/* Extract "effective" player level */
1437 	levels = (p->lev - p->class->magic.spell_first) + 1;
1438 	if (levels > 0) {
1439 		msp = 1;
1440 		msp += adj_mag_mana[average_spell_stat(p, state)] * levels / 100;
1441 	} else {
1442 		levels = 0;
1443 		msp = 0;
1444 	}
1445 
1446 	/* Assume player not encumbered by armor */
1447 	state->cumber_armor = false;
1448 
1449 	/* Weigh the armor */
1450 	cur_wgt = 0;
1451 	for (i = 0; i < p->body.count; i++) {
1452 		struct object *obj_local = slot_object(p, i);
1453 
1454 		/* Ignore non-armor */
1455 		if (slot_type_is(i, EQUIP_WEAPON)) continue;
1456 		if (slot_type_is(i, EQUIP_BOW)) continue;
1457 		if (slot_type_is(i, EQUIP_RING)) continue;
1458 		if (slot_type_is(i, EQUIP_AMULET)) continue;
1459 		if (slot_type_is(i, EQUIP_LIGHT)) continue;
1460 
1461 		/* Add weight */
1462 		if (obj_local)
1463 			cur_wgt += obj_local->weight;
1464 	}
1465 
1466 	/* Determine the weight allowance */
1467 	max_wgt = p->class->magic.spell_weight;
1468 
1469 	/* Heavy armor penalizes mana */
1470 	if (((cur_wgt - max_wgt) / 10) > 0) {
1471 		/* Encumbered */
1472 		state->cumber_armor = true;
1473 
1474 		/* Reduce mana */
1475 		msp -= ((cur_wgt - max_wgt) / 10);
1476 	}
1477 
1478 	/* Mana can never be negative */
1479 	if (msp < 0) msp = 0;
1480 
1481 	/* Return if no updates */
1482 	if (!update) return;
1483 
1484 	/* Maximum mana has changed */
1485 	if (p->msp != msp) {
1486 		/* Save new limit */
1487 		p->msp = msp;
1488 
1489 		/* Enforce new limit */
1490 		if (p->csp >= msp) {
1491 			p->csp = msp;
1492 			p->csp_frac = 0;
1493 		}
1494 
1495 		/* Display mana later */
1496 		p->upkeep->redraw |= (PR_MANA);
1497 	}
1498 }
1499 
1500 
1501 /**
1502  * Calculate the players (maximal) hit points
1503  *
1504  * Adjust current hitpoints if necessary
1505  */
calc_hitpoints(struct player * p)1506 static void calc_hitpoints(struct player *p)
1507 {
1508 	long bonus;
1509 	int mhp;
1510 
1511 	/* Get "1/100th hitpoint bonus per level" value */
1512 	bonus = adj_con_mhp[p->state.stat_ind[STAT_CON]];
1513 
1514 	/* Calculate hitpoints */
1515 	mhp = p->player_hp[p->lev-1] + (bonus * p->lev / 100);
1516 
1517 	/* Always have at least one hitpoint per level */
1518 	if (mhp < p->lev + 1) mhp = p->lev + 1;
1519 
1520 	/* New maximum hitpoints */
1521 	if (p->mhp != mhp) {
1522 		/* Save new limit */
1523 		p->mhp = mhp;
1524 
1525 		/* Enforce new limit */
1526 		if (p->chp >= mhp) {
1527 			p->chp = mhp;
1528 			p->chp_frac = 0;
1529 		}
1530 
1531 		/* Display hitpoints (later) */
1532 		p->upkeep->redraw |= (PR_HP);
1533 	}
1534 }
1535 
1536 
1537 /**
1538  * Calculate and set the current light radius.
1539  *
1540  * The light radius will be the total of all lights carried.
1541  */
calc_light(struct player * p,struct player_state * state,bool update)1542 static void calc_light(struct player *p, struct player_state *state,
1543 					   bool update)
1544 {
1545 	int i;
1546 
1547 	/* Assume no light */
1548 	state->cur_light = 0;
1549 
1550 	/* Ascertain lightness if in the town */
1551 	if (!p->depth && is_daytime() && update) {
1552 		/* Update the visuals if necessary*/
1553 		if (p->state.cur_light != state->cur_light)
1554 			p->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);
1555 
1556 		return;
1557 	}
1558 
1559 	/* Examine all wielded objects, use the brightest */
1560 	for (i = 0; i < p->body.count; i++) {
1561 		int amt = 0;
1562 		struct object *obj = slot_object(p, i);
1563 
1564 		/* Skip empty slots */
1565 		if (!obj) continue;
1566 
1567 		/* Light radius - innate plus modifier */
1568 		if (of_has(obj->flags, OF_LIGHT_2)) {
1569 			amt = 2;
1570 		} else if (of_has(obj->flags, OF_LIGHT_3)) {
1571 			amt = 3;
1572 		}
1573 		amt += obj->modifiers[OBJ_MOD_LIGHT];
1574 
1575 		/* Adjustment to allow UNLIGHT players to use +1 LIGHT gear */
1576 		if ((obj->modifiers[OBJ_MOD_LIGHT] > 0) && player_has(p, PF_UNLIGHT)) {
1577 			amt--;
1578 		}
1579 
1580 		/* Examine actual lights */
1581 		if (tval_is_light(obj) && !of_has(obj->flags, OF_NO_FUEL) &&
1582 				obj->timeout == 0)
1583 			/* Lights without fuel provide no light */
1584 			amt = 0;
1585 
1586 		/* Alter p->state.cur_light if reasonable */
1587 	    state->cur_light += amt;
1588 	}
1589 }
1590 
1591 /**
1592  * Populates `chances` with the player's chance of digging through
1593  * the diggable terrain types in one turn out of 1600.
1594  */
calc_digging_chances(struct player_state * state,int chances[DIGGING_MAX])1595 void calc_digging_chances(struct player_state *state, int chances[DIGGING_MAX])
1596 {
1597 	int i;
1598 
1599 	chances[DIGGING_RUBBLE] = state->skills[SKILL_DIGGING] * 8;
1600 	chances[DIGGING_MAGMA] = (state->skills[SKILL_DIGGING] - 10) * 4;
1601 	chances[DIGGING_QUARTZ] = (state->skills[SKILL_DIGGING] - 20) * 2;
1602 	chances[DIGGING_GRANITE] = (state->skills[SKILL_DIGGING] - 40) * 1;
1603 	/* Approximate a 1/1200 chance per skill point over 30 */
1604 	chances[DIGGING_DOORS] = (state->skills[SKILL_DIGGING] * 4 - 119) / 3;
1605 
1606 	/* Don't let any negative chances through */
1607 	for (i = 0; i < DIGGING_MAX; i++)
1608 		chances[i] = MAX(0, chances[i]);
1609 }
1610 
1611 /**
1612  * Calculate the blows a player would get.
1613  *
1614  * \param obj is the object for which we are calculating blows
1615  * \param state is the player state for which we are calculating blows
1616  * \param extra_blows is the number of +blows available from this object and
1617  * this state
1618  *
1619  * N.B. state->num_blows is now 100x the number of blows.
1620  */
calc_blows(struct player * p,const struct object * obj,struct player_state * state,int extra_blows)1621 int calc_blows(struct player *p, const struct object *obj,
1622 			   struct player_state *state, int extra_blows)
1623 {
1624 	int blows;
1625 	int str_index, dex_index;
1626 	int div;
1627 	int blow_energy;
1628 
1629 	int weight = (obj == NULL) ? 0 : obj->weight;
1630 	int min_weight = p->class->min_weight;
1631 
1632 	/* Enforce a minimum "weight" (tenth pounds) */
1633 	div = (weight < min_weight) ? min_weight : weight;
1634 
1635 	/* Get the strength vs weight */
1636 	str_index = adj_str_blow[state->stat_ind[STAT_STR]] *
1637 			p->class->att_multiply / div;
1638 
1639 	/* Maximal value */
1640 	if (str_index > 11) str_index = 11;
1641 
1642 	/* Index by dexterity */
1643 	dex_index = MIN(adj_dex_blow[state->stat_ind[STAT_DEX]], 11);
1644 
1645 	/* Use the blows table to get energy per blow */
1646 	blow_energy = blows_table[str_index][dex_index];
1647 
1648 	blows = MIN((10000 / blow_energy), (100 * p->class->max_attacks));
1649 
1650 	/* Require at least one blow, two for O-combat */
1651 	return MAX(blows + (100 * extra_blows),
1652 			   OPT(p, birth_percent_damage) ? 200 : 100);
1653 }
1654 
1655 
1656 /**
1657  * Computes current weight limit.
1658  */
weight_limit(struct player_state * state)1659 static int weight_limit(struct player_state *state)
1660 {
1661 	int i;
1662 
1663 	/* Weight limit based only on strength */
1664 	i = adj_str_wgt[state->stat_ind[STAT_STR]] * 100;
1665 
1666 	/* Return the result */
1667 	return (i);
1668 }
1669 
1670 
1671 /**
1672  * Computes weight remaining before burdened.
1673  */
weight_remaining(struct player * p)1674 int weight_remaining(struct player *p)
1675 {
1676 	int i;
1677 
1678 	/* Weight limit based only on strength */
1679 	i = 60 * adj_str_wgt[p->state.stat_ind[STAT_STR]]
1680 		- p->upkeep->total_weight - 1;
1681 
1682 	/* Return the result */
1683 	return (i);
1684 }
1685 
1686 
1687 /**
1688  * Calculate the effect of a shapechange on player state
1689  */
calc_shapechange(struct player_state * state,struct player_shape * shape,int * blows,int * shots,int * might,int * moves)1690 static void calc_shapechange(struct player_state *state,
1691 							 struct player_shape *shape,
1692 							 int *blows, int *shots, int *might, int *moves)
1693 {
1694 	int i;
1695 
1696 	/* Combat stats */
1697 	state->to_a += shape->to_a;
1698 	state->to_h += shape->to_h;
1699 	state->to_d += shape->to_d;
1700 
1701 	/* Skills */
1702 	for (i = 0; i < SKILL_MAX; i++) {
1703 		state->skills[i] += shape->skills[i];
1704 	}
1705 
1706 	/* Object flags */
1707 	of_union(state->flags, shape->flags);
1708 
1709 	/* Player flags */
1710 	pf_union(state->pflags, shape->pflags);
1711 
1712 	/* Stats */
1713 	for (i = 0; i < STAT_MAX; i++) {
1714 		state->stat_add[i] += shape->modifiers[i];
1715 	}
1716 
1717 	/* Other modifiers */
1718 	state->skills[SKILL_STEALTH] += shape->modifiers[OBJ_MOD_STEALTH];
1719 	state->skills[SKILL_SEARCH] += (shape->modifiers[OBJ_MOD_SEARCH] * 5);
1720 	state->see_infra += shape->modifiers[OBJ_MOD_INFRA];
1721 	state->skills[SKILL_DIGGING] += (shape->modifiers[OBJ_MOD_TUNNEL] * 20);
1722 	state->speed += shape->modifiers[OBJ_MOD_SPEED];
1723 	state->dam_red += shape->modifiers[OBJ_MOD_DAM_RED];
1724 	*blows += shape->modifiers[OBJ_MOD_BLOWS];
1725 	*shots += shape->modifiers[OBJ_MOD_SHOTS];
1726 	*might += shape->modifiers[OBJ_MOD_MIGHT];
1727 	*moves += shape->modifiers[OBJ_MOD_MOVES];
1728 
1729 	/* Resists and vulnerabilities */
1730 	for (i = 0; i < ELEM_MAX; i++) {
1731 		if (state->el_info[i].res_level == 0) {
1732 			/* Simple, just apply shape res/vuln */
1733 			state->el_info[i].res_level = shape->el_info[i].res_level;
1734 		} else if (state->el_info[i].res_level == -1) {
1735 			/* Shape resists cancel, immunities trump, vulnerabilities */
1736 			if (shape->el_info[i].res_level == 1) {
1737 				state->el_info[i].res_level = 0;
1738 			} else if (shape->el_info[i].res_level == 3) {
1739 				state->el_info[i].res_level = 3;
1740 			}
1741 		} else if (state->el_info[i].res_level == 1) {
1742 			/* Shape vulnerabilities cancel, immunities enhance, resists */
1743 			if (shape->el_info[i].res_level == -1) {
1744 				state->el_info[i].res_level = 0;
1745 			} else if (shape->el_info[i].res_level == 3) {
1746 				state->el_info[i].res_level = 3;
1747 			}
1748 		} else if (state->el_info[i].res_level == 3) {
1749 			/* Immmunity, shape has no effect */
1750 		}
1751 	}
1752 
1753 }
1754 
1755 /**
1756  * Calculate the players current "state", taking into account
1757  * not only race/class intrinsics, but also objects being worn
1758  * and temporary spell effects.
1759  *
1760  * See also calc_mana() and calc_hitpoints().
1761  *
1762  * Take note of the new "speed code", in particular, a very strong
1763  * player will start slowing down as soon as he reaches 150 pounds,
1764  * but not until he reaches 450 pounds will he be half as fast as
1765  * a normal kobold.  This both hurts and helps the player, hurts
1766  * because in the old days a player could just avoid 300 pounds,
1767  * and helps because now carrying 300 pounds is not very painful.
1768  *
1769  * The "weapon" and "bow" do *not* add to the bonuses to hit or to
1770  * damage, since that would affect non-combat things.  These values
1771  * are actually added in later, at the appropriate place.
1772  *
1773  * If known_only is true, calc_bonuses() will only use the known
1774  * information of objects; thus it returns what the player _knows_
1775  * the character state to be.
1776  */
calc_bonuses(struct player * p,struct player_state * state,bool known_only,bool update)1777 void calc_bonuses(struct player *p, struct player_state *state, bool known_only,
1778 				  bool update)
1779 {
1780 	int i, j, hold;
1781 	int extra_blows = 0;
1782 	int extra_shots = 0;
1783 	int extra_might = 0;
1784 	int extra_moves = 0;
1785 	struct object *launcher = equipped_item_by_slot_name(p, "shooting");
1786 	struct object *weapon = equipped_item_by_slot_name(p, "weapon");
1787 	bitflag f[OF_SIZE];
1788 	bitflag collect_f[OF_SIZE];
1789 	bool vuln[ELEM_MAX];
1790 
1791 	/* Hack to allow calculating hypothetical blows for extra STR, DEX - NRM */
1792 	int str_ind = state->stat_ind[STAT_STR];
1793 	int dex_ind = state->stat_ind[STAT_DEX];
1794 
1795 	/* Reset */
1796 	memset(state, 0, sizeof *state);
1797 
1798 	/* Set various defaults */
1799 	state->speed = 110;
1800 	state->num_blows = 100;
1801 
1802 	/* Extract race/class info */
1803 	state->see_infra = p->race->infra;
1804 	for (i = 0; i < SKILL_MAX; i++) {
1805 		state->skills[i] = p->race->r_skills[i]	+ p->class->c_skills[i];
1806 	}
1807 	for (i = 0; i < ELEM_MAX; i++) {
1808 		vuln[i] = false;
1809 		if (p->race->el_info[i].res_level == -1) {
1810 			vuln[i] = true;
1811 		} else {
1812 			state->el_info[i].res_level = p->race->el_info[i].res_level;
1813 		}
1814 	}
1815 
1816 	/* Base pflags */
1817 	pf_wipe(state->pflags);
1818 	pf_copy(state->pflags, p->race->pflags);
1819 	pf_union(state->pflags, p->class->pflags);
1820 
1821 	/* Extract the player flags */
1822 	player_flags(p, collect_f);
1823 
1824 	/* Analyze equipment */
1825 	for (i = 0; i < p->body.count; i++) {
1826 		int index = 0;
1827 		struct object *obj = slot_object(p, i);
1828 		struct curse_data *curse = obj ? obj->curses : NULL;
1829 
1830 		while (obj) {
1831 			int dig = 0;
1832 
1833 			/* Extract the item flags */
1834 			if (known_only) {
1835 				object_flags_known(obj, f);
1836 			} else {
1837 				object_flags(obj, f);
1838 			}
1839 			of_union(collect_f, f);
1840 
1841 			/* Apply modifiers */
1842 			state->stat_add[STAT_STR] += obj->modifiers[OBJ_MOD_STR]
1843 				* p->obj_k->modifiers[OBJ_MOD_STR];
1844 			state->stat_add[STAT_INT] += obj->modifiers[OBJ_MOD_INT]
1845 				* p->obj_k->modifiers[OBJ_MOD_INT];
1846 			state->stat_add[STAT_WIS] += obj->modifiers[OBJ_MOD_WIS]
1847 				* p->obj_k->modifiers[OBJ_MOD_WIS];
1848 			state->stat_add[STAT_DEX] += obj->modifiers[OBJ_MOD_DEX]
1849 				* p->obj_k->modifiers[OBJ_MOD_DEX];
1850 			state->stat_add[STAT_CON] += obj->modifiers[OBJ_MOD_CON]
1851 				* p->obj_k->modifiers[OBJ_MOD_CON];
1852 			state->skills[SKILL_STEALTH] += obj->modifiers[OBJ_MOD_STEALTH]
1853 				* p->obj_k->modifiers[OBJ_MOD_STEALTH];
1854 			state->skills[SKILL_SEARCH] += (obj->modifiers[OBJ_MOD_SEARCH] * 5)
1855 				* p->obj_k->modifiers[OBJ_MOD_SEARCH];
1856 
1857 			state->see_infra += obj->modifiers[OBJ_MOD_INFRA]
1858 				* p->obj_k->modifiers[OBJ_MOD_INFRA];
1859 			if (tval_is_digger(obj)) {
1860 				if (of_has(obj->flags, OF_DIG_1))
1861 					dig = 1;
1862 				else if (of_has(obj->flags, OF_DIG_2))
1863 					dig = 2;
1864 				else if (of_has(obj->flags, OF_DIG_3))
1865 					dig = 3;
1866 			}
1867 			dig += obj->modifiers[OBJ_MOD_TUNNEL]
1868 				* p->obj_k->modifiers[OBJ_MOD_TUNNEL];
1869 			state->skills[SKILL_DIGGING] += (dig * 20);
1870 			state->speed += obj->modifiers[OBJ_MOD_SPEED]
1871 				* p->obj_k->modifiers[OBJ_MOD_SPEED];
1872 			state->dam_red += obj->modifiers[OBJ_MOD_DAM_RED]
1873 				* p->obj_k->modifiers[OBJ_MOD_DAM_RED];
1874 			extra_blows += obj->modifiers[OBJ_MOD_BLOWS]
1875 				* p->obj_k->modifiers[OBJ_MOD_BLOWS];
1876 			extra_shots += obj->modifiers[OBJ_MOD_SHOTS]
1877 				* p->obj_k->modifiers[OBJ_MOD_SHOTS];
1878 			extra_might += obj->modifiers[OBJ_MOD_MIGHT]
1879 				* p->obj_k->modifiers[OBJ_MOD_MIGHT];
1880 			extra_moves += obj->modifiers[OBJ_MOD_MOVES]
1881 				* p->obj_k->modifiers[OBJ_MOD_MOVES];
1882 
1883 			/* Apply element info, noting vulnerabilites for later processing */
1884 			for (j = 0; j < ELEM_MAX; j++) {
1885 				if (!known_only || obj->known->el_info[j].res_level) {
1886 					if (obj->el_info[j].res_level == -1)
1887 						vuln[j] = true;
1888 
1889 					/* OK because res_level hasn't included vulnerability yet */
1890 					if (obj->el_info[j].res_level > state->el_info[j].res_level)
1891 						state->el_info[j].res_level = obj->el_info[j].res_level;
1892 				}
1893 			}
1894 
1895 			/* Apply combat bonuses */
1896 			state->ac += obj->ac;
1897 			if (!known_only || obj->known->to_a)
1898 				state->to_a += obj->to_a;
1899 			if (!slot_type_is(i, EQUIP_WEAPON) && !slot_type_is(i, EQUIP_BOW)) {
1900 				if (!known_only || obj->known->to_h) {
1901 					state->to_h += obj->to_h;
1902 				}
1903 				if (!known_only || obj->known->to_d) {
1904 					state->to_d += obj->to_d;
1905 				}
1906 			}
1907 
1908 			/* Move to any unprocessed curse object */
1909 			if (curse) {
1910 				index++;
1911 				obj = NULL;
1912 				while (index < z_info->curse_max) {
1913 					if (curse[index].power) {
1914 						obj = curses[index].obj;
1915 						break;
1916 					} else {
1917 						index++;
1918 					}
1919 				}
1920 			} else {
1921 				obj = NULL;
1922 			}
1923 		}
1924 	}
1925 
1926 	/* Apply the collected flags */
1927 	of_union(state->flags, collect_f);
1928 
1929 	/* Now deal with vulnerabilities */
1930 	for (i = 0; i < ELEM_MAX; i++) {
1931 		if (vuln[i] && (state->el_info[i].res_level < 3))
1932 			state->el_info[i].res_level--;
1933 	}
1934 
1935 	/* Add shapechange info */
1936 	calc_shapechange(state, p->shape, &extra_blows, &extra_shots, &extra_might,
1937 		&extra_moves);
1938 
1939 	/* Calculate light */
1940 	calc_light(p, state, update);
1941 
1942 	/* Unlight - needs change if anything but resist is introduced for dark */
1943 	if (player_has(p, PF_UNLIGHT) && character_dungeon) {
1944 		state->el_info[ELEM_DARK].res_level = 1;
1945 	}
1946 
1947 	/* Evil */
1948 	if (player_has(p, PF_EVIL) && character_dungeon) {
1949 		state->el_info[ELEM_NETHER].res_level = 1;
1950 		state->el_info[ELEM_HOLY_ORB].res_level = -1;
1951 	}
1952 
1953 	/* Combat Regeneration */
1954 	if (player_has(p, PF_COMBAT_REGEN) && character_dungeon) {
1955 		of_on(state->flags, OF_IMPAIR_HP);
1956 	}
1957 
1958 	/* Calculate the various stat values */
1959 	for (i = 0; i < STAT_MAX; i++) {
1960 		int add, use, ind;
1961 
1962 		add = state->stat_add[i];
1963 		add += (p->race->r_adj[i] + p->class->c_adj[i]);
1964 		state->stat_top[i] =  modify_stat_value(p->stat_max[i], add);
1965 		use = modify_stat_value(p->stat_cur[i], add);
1966 
1967 		state->stat_use[i] = use;
1968 
1969 		if (use <= 3) {/* Values: n/a */
1970 			ind = 0;
1971 		} else if (use <= 18) {/* Values: 3, 4, ..., 18 */
1972 			ind = (use - 3);
1973 		} else if (use <= 18+219) {/* Ranges: 18/00-18/09, ..., 18/210-18/219 */
1974 			ind = (15 + (use - 18) / 10);
1975 		} else {/* Range: 18/220+ */
1976 			ind = (37);
1977 		}
1978 
1979 		assert((0 <= ind) && (ind < STAT_RANGE));
1980 
1981 		/* Hack for hypothetical blows - NRM */
1982 		if (!update) {
1983 			if (i == STAT_STR) {
1984 				ind += str_ind;
1985 				ind = MIN(ind, 37);
1986 				ind = MAX(ind, 3);
1987 			} else if (i == STAT_DEX) {
1988 				ind += dex_ind;
1989 				ind = MIN(ind, 37);
1990 				ind = MAX(ind, 3);
1991 			}
1992 		}
1993 
1994 		/* Save the new index */
1995 		state->stat_ind[i] = ind;
1996 	}
1997 
1998 	/* Effects of food outside the "Fed" range */
1999 	if (!player_timed_grade_eq(p, TMD_FOOD, "Fed")) {
2000 		int excess = p->timed[TMD_FOOD] - PY_FOOD_FULL;
2001 		int lack = PY_FOOD_HUNGRY - p->timed[TMD_FOOD];
2002 		if ((excess > 0) && !p->timed[TMD_ATT_VAMP]) {
2003 			/* Scale to units 1/10 of the range and subtract from speed */
2004 			excess = (excess * 10) / (PY_FOOD_MAX - PY_FOOD_FULL);
2005 			state->speed -= excess;
2006 		} else if (lack > 0) {
2007 			/* Scale to units 1/20 of the range */
2008 			lack = (lack * 20) / PY_FOOD_HUNGRY;
2009 
2010 			/* Apply effects progressively */
2011 			state->to_h -= lack;
2012 			state->to_d -= lack;
2013 			if ((lack > 10) && (lack <= 15)) {
2014 				state->skills[SKILL_DEVICE] *= 9;
2015 				state->skills[SKILL_DEVICE] /= 10;
2016 			} else if ((lack > 15) && (lack <= 18)) {
2017 				state->skills[SKILL_DEVICE] *= 8;
2018 				state->skills[SKILL_DEVICE] /= 10;
2019 				state->skills[SKILL_DISARM_PHYS] *= 9;
2020 				state->skills[SKILL_DISARM_PHYS] /= 10;
2021 				state->skills[SKILL_DISARM_MAGIC] *= 9;
2022 				state->skills[SKILL_DISARM_MAGIC] /= 10;
2023 			} else if (lack > 18) {
2024 				state->skills[SKILL_DEVICE] *= 7;
2025 				state->skills[SKILL_DEVICE] /= 10;
2026 				state->skills[SKILL_DISARM_PHYS] *= 8;
2027 				state->skills[SKILL_DISARM_PHYS] /= 10;
2028 				state->skills[SKILL_DISARM_MAGIC] *= 8;
2029 				state->skills[SKILL_DISARM_MAGIC] /= 10;
2030 				state->skills[SKILL_SAVE] *= 9;
2031 				state->skills[SKILL_SAVE] /= 10;
2032 				state->skills[SKILL_SEARCH] *=9;
2033 				state->skills[SKILL_SEARCH] /= 10;
2034 			}
2035 		}
2036 	}
2037 
2038 	/* Other timed effects */
2039 	player_flags_timed(p, state->flags);
2040 
2041 	if (player_timed_grade_eq(p, TMD_STUN, "Heavy Stun")) {
2042 		state->to_h -= 20;
2043 		state->to_d -= 20;
2044 		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE] * 8 / 10;
2045 		if (update) {
2046 			p->timed[TMD_FASTCAST] = 0;
2047 		}
2048 	} else if (player_timed_grade_eq(p, TMD_STUN, "Stun")) {
2049 		state->to_h -= 5;
2050 		state->to_d -= 5;
2051 		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE] * 9 / 10;
2052 		if (update) {
2053 			p->timed[TMD_FASTCAST] = 0;
2054 		}
2055 	}
2056 	if (p->timed[TMD_INVULN]) {
2057 		state->to_a += 100;
2058 	}
2059 	if (p->timed[TMD_BLESSED]) {
2060 		state->to_a += 5;
2061 		state->to_h += 10;
2062 		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE] * 105 / 100;
2063 	}
2064 	if (p->timed[TMD_SHIELD]) {
2065 		state->to_a += 50;
2066 	}
2067 	if (p->timed[TMD_STONESKIN]) {
2068 		state->to_a += 40;
2069 		state->speed -= 5;
2070 	}
2071 	if (p->timed[TMD_HERO]) {
2072 		state->to_h += 12;
2073 		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE] * 105 / 100;
2074 	}
2075 	if (p->timed[TMD_SHERO]) {
2076 		state->skills[SKILL_TO_HIT_MELEE] += 75;
2077 		state->to_a -= 10;
2078 		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE] * 9 / 10;
2079 	}
2080 	if (p->timed[TMD_FAST] || p->timed[TMD_SPRINT]) {
2081 		state->speed += 10;
2082 	}
2083 	if (p->timed[TMD_SLOW]) {
2084 		state->speed -= 10;
2085 	}
2086 	if (p->timed[TMD_SINFRA]) {
2087 		state->see_infra += 5;
2088 	}
2089 	if (p->timed[TMD_TERROR]) {
2090 		state->speed += 10;
2091 	}
2092 	if (p->timed[TMD_OPP_ACID] && (state->el_info[ELEM_ACID].res_level < 2)) {
2093 			state->el_info[ELEM_ACID].res_level++;
2094 	}
2095 	if (p->timed[TMD_OPP_ELEC] && (state->el_info[ELEM_ELEC].res_level < 2)) {
2096 			state->el_info[ELEM_ELEC].res_level++;
2097 	}
2098 	if (p->timed[TMD_OPP_FIRE] && (state->el_info[ELEM_FIRE].res_level < 2)) {
2099 			state->el_info[ELEM_FIRE].res_level++;
2100 	}
2101 	if (p->timed[TMD_OPP_COLD] && (state->el_info[ELEM_COLD].res_level < 2)) {
2102 			state->el_info[ELEM_COLD].res_level++;
2103 	}
2104 	if (p->timed[TMD_OPP_POIS] && (state->el_info[ELEM_POIS].res_level < 2)) {
2105 			state->el_info[ELEM_POIS].res_level++;
2106 	}
2107 	if (p->timed[TMD_CONFUSED]) {
2108 		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE] * 75 / 100;
2109 	}
2110 	if (p->timed[TMD_AMNESIA]) {
2111 		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE] * 8 / 10;
2112 	}
2113 	if (p->timed[TMD_POISONED]) {
2114 		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE] * 95 / 100;
2115 	}
2116 	if (p->timed[TMD_IMAGE]) {
2117 		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE] * 8 / 10;
2118 	}
2119 	if (p->timed[TMD_BLOODLUST]) {
2120 		state->to_d += p->timed[TMD_BLOODLUST] / 2;
2121 		extra_blows += p->timed[TMD_BLOODLUST] / 20;
2122 	}
2123 	if (p->timed[TMD_STEALTH]) {
2124 		state->skills[SKILL_STEALTH] += 10;
2125 	}
2126 
2127 	/* Analyze flags - check for fear */
2128 	if (of_has(state->flags, OF_AFRAID)) {
2129 		state->to_h -= 20;
2130 		state->to_a += 8;
2131 		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE] * 95 / 100;
2132 	}
2133 
2134 	/* Analyze weight */
2135 	j = p->upkeep->total_weight;
2136 	i = weight_limit(state);
2137 	if (j > i / 2)
2138 		state->speed -= ((j - (i / 2)) / (i / 10));
2139 	if (state->speed < 0)
2140 		state->speed = 0;
2141 	if (state->speed > 199)
2142 		state->speed = 199;
2143 
2144 	/* Apply modifier bonuses (Un-inflate stat bonuses) */
2145 	state->to_a += adj_dex_ta[state->stat_ind[STAT_DEX]];
2146 	state->to_d += adj_str_td[state->stat_ind[STAT_STR]];
2147 	state->to_h += adj_dex_th[state->stat_ind[STAT_DEX]];
2148 	state->to_h += adj_str_th[state->stat_ind[STAT_STR]];
2149 
2150 
2151 	/* Modify skills */
2152 	state->skills[SKILL_DISARM_PHYS] += adj_dex_dis[state->stat_ind[STAT_DEX]];
2153 	state->skills[SKILL_DISARM_MAGIC] += adj_int_dis[state->stat_ind[STAT_INT]];
2154 	state->skills[SKILL_DEVICE] += adj_int_dev[state->stat_ind[STAT_INT]];
2155 	state->skills[SKILL_SAVE] += adj_wis_sav[state->stat_ind[STAT_WIS]];
2156 	state->skills[SKILL_DIGGING] += adj_str_dig[state->stat_ind[STAT_STR]];
2157 	for (i = 0; i < SKILL_MAX; i++)
2158 		state->skills[i] += (p->class->x_skills[i] * p->lev / 10);
2159 
2160 	if (state->skills[SKILL_DIGGING] < 1) state->skills[SKILL_DIGGING] = 1;
2161 	if (state->skills[SKILL_STEALTH] > 30) state->skills[SKILL_STEALTH] = 30;
2162 	if (state->skills[SKILL_STEALTH] < 0) state->skills[SKILL_STEALTH] = 0;
2163 	hold = adj_str_hold[state->stat_ind[STAT_STR]];
2164 
2165 
2166 	/* Analyze launcher */
2167 	state->heavy_shoot = false;
2168 	if (launcher) {
2169 		if (hold < launcher->weight / 10) {
2170 			state->to_h += 2 * (hold - launcher->weight / 10);
2171 			state->heavy_shoot = true;
2172 		}
2173 
2174 		state->num_shots = 10;
2175 
2176 		/* Type of ammo */
2177 		if (kf_has(launcher->kind->kind_flags, KF_SHOOTS_SHOTS))
2178 			state->ammo_tval = TV_SHOT;
2179 		else if (kf_has(launcher->kind->kind_flags, KF_SHOOTS_ARROWS))
2180 			state->ammo_tval = TV_ARROW;
2181 		else if (kf_has(launcher->kind->kind_flags, KF_SHOOTS_BOLTS))
2182 			state->ammo_tval = TV_BOLT;
2183 
2184 		/* Multiplier */
2185 		state->ammo_mult = launcher->pval;
2186 
2187 		/* Apply special flags */
2188 		if (!state->heavy_shoot) {
2189 			state->num_shots += extra_shots;
2190 			state->ammo_mult += extra_might;
2191 			if (player_has(p, PF_FAST_SHOT) && (state->ammo_tval == TV_ARROW)) {
2192 				state->num_shots += p->lev / 3;
2193 			}
2194 		}
2195 
2196 		/* Require at least one shot */
2197 		if (state->num_shots < 10) state->num_shots = 10;
2198 	}
2199 
2200 
2201 	/* Analyze weapon */
2202 	state->heavy_wield = false;
2203 	state->bless_wield = false;
2204 	if (weapon) {
2205 		/* It is hard to hold a heavy weapon */
2206 		if (hold < weapon->weight / 10) {
2207 			state->to_h += 2 * (hold - weapon->weight / 10);
2208 			state->heavy_wield = true;
2209 		}
2210 
2211 		/* Normal weapons */
2212 		if (!state->heavy_wield) {
2213 			state->num_blows = calc_blows(p, weapon, state, extra_blows);
2214 			state->skills[SKILL_DIGGING] += (weapon->weight / 10);
2215 		}
2216 
2217 		/* Divine weapon bonus for blessed weapons */
2218 		if (player_has(p, PF_BLESS_WEAPON) && of_has(state->flags, OF_BLESSED)){
2219 			state->to_h += 2;
2220 			state->to_d += 2;
2221 			state->bless_wield = true;
2222 		}
2223 	} else {
2224 		/* Unarmed */
2225 		state->num_blows = calc_blows(p, NULL, state, extra_blows);
2226 	}
2227 
2228 	/* Mana */
2229 	calc_mana(p, state, update);
2230 	if (!p->msp) {
2231 		pf_on(state->pflags, PF_NO_MANA);
2232 	}
2233 
2234 	/* Movement speed */
2235 	state->num_moves = extra_moves;
2236 
2237 	return;
2238 }
2239 
2240 /**
2241  * Calculate bonuses, and print various things on changes.
2242  */
update_bonuses(struct player * p)2243 static void update_bonuses(struct player *p)
2244 {
2245 	int i;
2246 
2247 	struct player_state state = p->state;
2248 	struct player_state known_state = p->known_state;
2249 
2250 
2251 	/* ------------------------------------
2252 	 * Calculate bonuses
2253 	 * ------------------------------------ */
2254 
2255 	calc_bonuses(p, &state, false, true);
2256 	calc_bonuses(p, &known_state, true, true);
2257 
2258 
2259 	/* ------------------------------------
2260 	 * Notice changes
2261 	 * ------------------------------------ */
2262 
2263 	/* Analyze stats */
2264 	for (i = 0; i < STAT_MAX; i++) {
2265 		/* Notice changes */
2266 		if (state.stat_top[i] != p->state.stat_top[i])
2267 			/* Redisplay the stats later */
2268 			p->upkeep->redraw |= (PR_STATS);
2269 
2270 		/* Notice changes */
2271 		if (state.stat_use[i] != p->state.stat_use[i])
2272 			/* Redisplay the stats later */
2273 			p->upkeep->redraw |= (PR_STATS);
2274 
2275 		/* Notice changes */
2276 		if (state.stat_ind[i] != p->state.stat_ind[i]) {
2277 			/* Change in CON affects Hitpoints */
2278 			if (i == STAT_CON)
2279 				p->upkeep->update |= (PU_HP);
2280 
2281 			/* Change in stats may affect Mana/Spells */
2282 			p->upkeep->update |= (PU_MANA | PU_SPELLS);
2283 		}
2284 	}
2285 
2286 
2287 	/* Hack -- Telepathy Change */
2288 	if (of_has(state.flags, OF_TELEPATHY) !=
2289 		of_has(p->state.flags, OF_TELEPATHY))
2290 		/* Update monster visibility */
2291 		p->upkeep->update |= (PU_MONSTERS);
2292 	/* Hack -- See Invis Change */
2293 	if (of_has(state.flags, OF_SEE_INVIS) !=
2294 		of_has(p->state.flags, OF_SEE_INVIS))
2295 		/* Update monster visibility */
2296 		p->upkeep->update |= (PU_MONSTERS);
2297 
2298 	/* Redraw speed (if needed) */
2299 	if (state.speed != p->state.speed)
2300 		p->upkeep->redraw |= (PR_SPEED);
2301 
2302 	/* Redraw armor (if needed) */
2303 	if ((known_state.ac != p->known_state.ac) ||
2304 		(known_state.to_a != p->known_state.to_a))
2305 		p->upkeep->redraw |= (PR_ARMOR);
2306 
2307 	/* Notice changes in the "light radius" */
2308 	if (p->state.cur_light != state.cur_light) {
2309 		/* Update the visuals */
2310 		p->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);
2311 	}
2312 
2313 	/* Hack -- handle partial mode */
2314 	if (!p->upkeep->only_partial) {
2315 		/* Take note when "heavy bow" changes */
2316 		if (p->state.heavy_shoot != state.heavy_shoot) {
2317 			/* Message */
2318 			if (state.heavy_shoot)
2319 				msg("You have trouble wielding such a heavy bow.");
2320 			else if (equipped_item_by_slot_name(p, "shooting"))
2321 				msg("You have no trouble wielding your bow.");
2322 			else
2323 				msg("You feel relieved to put down your heavy bow.");
2324 		}
2325 
2326 		/* Take note when "heavy weapon" changes */
2327 		if (p->state.heavy_wield != state.heavy_wield) {
2328 			/* Message */
2329 			if (state.heavy_wield)
2330 				msg("You have trouble wielding such a heavy weapon.");
2331 			else if (equipped_item_by_slot_name(p, "weapon"))
2332 				msg("You have no trouble wielding your weapon.");
2333 			else
2334 				msg("You feel relieved to put down your heavy weapon.");
2335 		}
2336 
2337 		/* Take note when "illegal weapon" changes */
2338 		if (p->state.bless_wield != state.bless_wield) {
2339 			/* Message */
2340 			if (state.bless_wield) {
2341 				msg("You feel attuned to your weapon.");
2342 			} else if (equipped_item_by_slot_name(p, "weapon")) {
2343 				msg("You feel less attuned to your weapon.");
2344 			}
2345 		}
2346 
2347 		/* Take note when "armor state" changes */
2348 		if (p->state.cumber_armor != state.cumber_armor) {
2349 			/* Message */
2350 			if (state.cumber_armor)
2351 				msg("The weight of your armor encumbers your movement.");
2352 			else
2353 				msg("You feel able to move more freely.");
2354 		}
2355 	}
2356 
2357 	memcpy(&p->state, &state, sizeof(state));
2358 	memcpy(&p->known_state, &known_state, sizeof(known_state));
2359 }
2360 
2361 
2362 
2363 
2364 /**
2365  * ------------------------------------------------------------------------
2366  * Monster and object tracking functions
2367  * ------------------------------------------------------------------------ */
2368 
2369 /**
2370  * Track the given monster
2371  */
health_track(struct player_upkeep * upkeep,struct monster * mon)2372 void health_track(struct player_upkeep *upkeep, struct monster *mon)
2373 {
2374 	upkeep->health_who = mon;
2375 	upkeep->redraw |= PR_HEALTH;
2376 }
2377 
2378 /**
2379  * Track the given monster race
2380  */
monster_race_track(struct player_upkeep * upkeep,struct monster_race * race)2381 void monster_race_track(struct player_upkeep *upkeep, struct monster_race *race)
2382 {
2383 	/* Save this monster ID */
2384 	upkeep->monster_race = race;
2385 
2386 	/* Window stuff */
2387 	upkeep->redraw |= (PR_MONSTER);
2388 }
2389 
2390 /**
2391  * Track the given object
2392  */
track_object(struct player_upkeep * upkeep,struct object * obj)2393 void track_object(struct player_upkeep *upkeep, struct object *obj)
2394 {
2395 	upkeep->object = obj;
2396 	upkeep->object_kind = NULL;
2397 	upkeep->redraw |= (PR_OBJECT);
2398 }
2399 
2400 /**
2401  * Track the given object kind
2402  */
track_object_kind(struct player_upkeep * upkeep,struct object_kind * kind)2403 void track_object_kind(struct player_upkeep *upkeep, struct object_kind *kind)
2404 {
2405 	upkeep->object = NULL;
2406 	upkeep->object_kind = kind;
2407 	upkeep->redraw |= (PR_OBJECT);
2408 }
2409 
2410 /**
2411  * Cancel all object tracking
2412  */
track_object_cancel(struct player_upkeep * upkeep)2413 void track_object_cancel(struct player_upkeep *upkeep)
2414 {
2415 	upkeep->object = NULL;
2416 	upkeep->object_kind = NULL;
2417 	upkeep->redraw |= (PR_OBJECT);
2418 }
2419 
2420 /**
2421  * Is the given item tracked?
2422  */
tracked_object_is(struct player_upkeep * upkeep,struct object * obj)2423 bool tracked_object_is(struct player_upkeep *upkeep, struct object *obj)
2424 {
2425 	return (upkeep->object == obj);
2426 }
2427 
2428 
2429 
2430 /**
2431  * ------------------------------------------------------------------------
2432  * Generic "deal with" functions
2433  * ------------------------------------------------------------------------ */
2434 
2435 /**
2436  * Handle "player->upkeep->notice"
2437  */
notice_stuff(struct player * p)2438 void notice_stuff(struct player *p)
2439 {
2440 	/* Notice stuff */
2441 	if (!p->upkeep->notice) return;
2442 
2443 	/* Deal with ignore stuff */
2444 	if (p->upkeep->notice & PN_IGNORE) {
2445 		p->upkeep->notice &= ~(PN_IGNORE);
2446 		ignore_drop();
2447 	}
2448 
2449 	/* Combine the pack */
2450 	if (p->upkeep->notice & PN_COMBINE) {
2451 		p->upkeep->notice &= ~(PN_COMBINE);
2452 		combine_pack();
2453 	}
2454 
2455 	/* Dump the monster messages */
2456 	if (p->upkeep->notice & PN_MON_MESSAGE) {
2457 		p->upkeep->notice &= ~(PN_MON_MESSAGE);
2458 
2459 		/* Make sure this comes after all of the monster messages */
2460 		show_monster_messages();
2461 	}
2462 }
2463 
2464 /**
2465  * Handle "player->upkeep->update"
2466  */
update_stuff(struct player * p)2467 void update_stuff(struct player *p)
2468 {
2469 	/* Update stuff */
2470 	if (!p->upkeep->update) return;
2471 
2472 
2473 	if (p->upkeep->update & (PU_INVEN)) {
2474 		p->upkeep->update &= ~(PU_INVEN);
2475 		update_inventory(p);
2476 	}
2477 
2478 	if (p->upkeep->update & (PU_BONUS)) {
2479 		p->upkeep->update &= ~(PU_BONUS);
2480 		update_bonuses(p);
2481 	}
2482 
2483 	if (p->upkeep->update & (PU_TORCH)) {
2484 		p->upkeep->update &= ~(PU_TORCH);
2485 		calc_light(p, &p->state, true);
2486 	}
2487 
2488 	if (p->upkeep->update & (PU_HP)) {
2489 		p->upkeep->update &= ~(PU_HP);
2490 		calc_hitpoints(p);
2491 	}
2492 
2493 	if (p->upkeep->update & (PU_MANA)) {
2494 		p->upkeep->update &= ~(PU_MANA);
2495 		calc_mana(p, &p->state, true);
2496 	}
2497 
2498 	if (p->upkeep->update & (PU_SPELLS)) {
2499 		p->upkeep->update &= ~(PU_SPELLS);
2500 		if (p->class->magic.total_spells > 0) {
2501 			calc_spells(p);
2502 		}
2503 	}
2504 
2505 	/* Character is not ready yet, no map updates */
2506 	if (!character_generated) return;
2507 
2508 	/* Map is not shown, no map updates */
2509 	if (!map_is_visible()) return;
2510 
2511 	if (p->upkeep->update & (PU_UPDATE_VIEW)) {
2512 		p->upkeep->update &= ~(PU_UPDATE_VIEW);
2513 		update_view(cave, p);
2514 	}
2515 
2516 	if (p->upkeep->update & (PU_DISTANCE)) {
2517 		p->upkeep->update &= ~(PU_DISTANCE);
2518 		p->upkeep->update &= ~(PU_MONSTERS);
2519 		update_monsters(true);
2520 	}
2521 
2522 	if (p->upkeep->update & (PU_MONSTERS)) {
2523 		p->upkeep->update &= ~(PU_MONSTERS);
2524 		update_monsters(false);
2525 	}
2526 
2527 
2528 	if (p->upkeep->update & (PU_PANEL)) {
2529 		p->upkeep->update &= ~(PU_PANEL);
2530 		event_signal(EVENT_PLAYERMOVED);
2531 	}
2532 }
2533 
2534 
2535 
2536 struct flag_event_trigger
2537 {
2538 	u32b flag;
2539 	game_event_type event;
2540 };
2541 
2542 
2543 
2544 /**
2545  * Events triggered by the various flags.
2546  */
2547 static const struct flag_event_trigger redraw_events[] =
2548 {
2549 	{ PR_MISC,    EVENT_RACE_CLASS },
2550 	{ PR_TITLE,   EVENT_PLAYERTITLE },
2551 	{ PR_LEV,     EVENT_PLAYERLEVEL },
2552 	{ PR_EXP,     EVENT_EXPERIENCE },
2553 	{ PR_STATS,   EVENT_STATS },
2554 	{ PR_ARMOR,   EVENT_AC },
2555 	{ PR_HP,      EVENT_HP },
2556 	{ PR_MANA,    EVENT_MANA },
2557 	{ PR_GOLD,    EVENT_GOLD },
2558 	{ PR_HEALTH,  EVENT_MONSTERHEALTH },
2559 	{ PR_DEPTH,   EVENT_DUNGEONLEVEL },
2560 	{ PR_SPEED,   EVENT_PLAYERSPEED },
2561 	{ PR_STATE,   EVENT_STATE },
2562 	{ PR_STATUS,  EVENT_STATUS },
2563 	{ PR_STUDY,   EVENT_STUDYSTATUS },
2564 	{ PR_DTRAP,   EVENT_DETECTIONSTATUS },
2565 	{ PR_FEELING, EVENT_FEELING },
2566 	{ PR_LIGHT,   EVENT_LIGHT },
2567 
2568 	{ PR_INVEN,   EVENT_INVENTORY },
2569 	{ PR_EQUIP,   EVENT_EQUIPMENT },
2570 	{ PR_MONLIST, EVENT_MONSTERLIST },
2571 	{ PR_ITEMLIST, EVENT_ITEMLIST },
2572 	{ PR_MONSTER, EVENT_MONSTERTARGET },
2573 	{ PR_OBJECT, EVENT_OBJECTTARGET },
2574 	{ PR_MESSAGE, EVENT_MESSAGE },
2575 };
2576 
2577 /**
2578  * Handle "player->upkeep->redraw"
2579  */
redraw_stuff(struct player * p)2580 void redraw_stuff(struct player *p)
2581 {
2582 	size_t i;
2583 	u32b redraw = p->upkeep->redraw;
2584 
2585 	/* Redraw stuff */
2586 	if (!redraw) return;
2587 
2588 	/* Character is not ready yet, no screen updates */
2589 	if (!character_generated) return;
2590 
2591 	/* Map is not shown, subwindow updates only */
2592 	if (!map_is_visible())
2593 		redraw &= PR_SUBWINDOW;
2594 
2595 	/* Hack - rarely update while resting or running, makes it over quicker */
2596 	if (((player_resting_count(p) % 100) || (p->upkeep->running % 100))
2597 		&& !(redraw & (PR_MESSAGE | PR_MAP)))
2598 		return;
2599 
2600 	/* For each listed flag, send the appropriate signal to the UI */
2601 	for (i = 0; i < N_ELEMENTS(redraw_events); i++) {
2602 		const struct flag_event_trigger *hnd = &redraw_events[i];
2603 
2604 		if (redraw & hnd->flag)
2605 			event_signal(hnd->event);
2606 	}
2607 
2608 	/* Then the ones that require parameters to be supplied. */
2609 	if (redraw & PR_MAP) {
2610 		/* Mark the whole map to be redrawn */
2611 		event_signal_point(EVENT_MAP, -1, -1);
2612 	}
2613 
2614 	p->upkeep->redraw &= ~redraw;
2615 
2616 	/* Map is not shown, subwindow updates only */
2617 	if (!map_is_visible()) return;
2618 
2619 	/*
2620 	 * Do any plotting, etc. delayed from earlier - this set of updates
2621 	 * is over.
2622 	 */
2623 	event_signal(EVENT_END);
2624 }
2625 
2626 
2627 /**
2628  * Handle "player->upkeep->update" and "player->upkeep->redraw"
2629  */
handle_stuff(struct player * p)2630 void handle_stuff(struct player *p)
2631 {
2632 	if (p->upkeep->update) update_stuff(p);
2633 	if (p->upkeep->redraw) redraw_stuff(p);
2634 }
2635 
2636