Angband 3.0.9b.
[angband.git] / src / xtra1.c
blob0ea40a0f97047abb47a52dd48cc2824572cacc93
1 /* File: xtra1.c */
3 /*
4 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies. Other copyrights may also apply.
9 */
11 #include "angband.h"
12 #include "script.h"
17 * Converts stat num into a six-char (right justified) string
19 void cnv_stat(int val, char *out_val, size_t out_len)
21 /* Above 18 */
22 if (val > 18)
24 int bonus = (val - 18);
26 if (bonus >= 100)
27 strnfmt(out_val, out_len, "18/%03d", bonus);
28 else
29 strnfmt(out_val, out_len, " 18/%02d", bonus);
32 /* From 3 to 18 */
33 else
35 strnfmt(out_val, out_len, " %2d", val);
42 * Modify a stat value by a "modifier", return new value
44 * Stats go up: 3,4,...,17,18,18/10,18/20,...,18/220
45 * Or even: 18/13, 18/23, 18/33, ..., 18/220
47 * Stats go down: 18/220, 18/210,..., 18/10, 18, 17, ..., 3
48 * Or even: 18/13, 18/03, 18, 17, ..., 3
50 s16b modify_stat_value(int value, int amount)
52 int i;
54 /* Reward */
55 if (amount > 0)
57 /* Apply each point */
58 for (i = 0; i < amount; i++)
60 /* One point at a time */
61 if (value < 18) value++;
63 /* Ten "points" at a time */
64 else value += 10;
68 /* Penalty */
69 else if (amount < 0)
71 /* Apply each point */
72 for (i = 0; i < (0 - amount); i++)
74 /* Ten points at a time */
75 if (value >= 18+10) value -= 10;
77 /* Hack -- prevent weirdness */
78 else if (value > 18) value = 18;
80 /* One point at a time */
81 else if (value > 3) value--;
85 /* Return new value */
86 return (value);
92 /*** Sidebar display functions ***/
95 * Print character info at given row, column in a 13 char field
97 static void prt_field(cptr info, int row, int col)
99 /* Dump 13 spaces to clear */
100 c_put_str(TERM_WHITE, " ", row, col);
102 /* Dump the info itself */
103 c_put_str(TERM_L_BLUE, info, row, col);
108 * Print character stat in given row, column
110 static void prt_stat(int stat, int row, int col)
112 char tmp[32];
114 /* Display "injured" stat */
115 if (p_ptr->stat_cur[stat] < p_ptr->stat_max[stat])
117 put_str(stat_names_reduced[stat], row, col);
118 cnv_stat(p_ptr->stat_use[stat], tmp, sizeof(tmp));
119 c_put_str(TERM_YELLOW, tmp, row, col + 6);
122 /* Display "healthy" stat */
123 else
125 put_str(stat_names[stat], row, col);
126 cnv_stat(p_ptr->stat_use[stat], tmp, sizeof(tmp));
127 c_put_str(TERM_L_GREEN, tmp, row, col + 6);
130 /* Indicate natural maximum */
131 if (p_ptr->stat_max[stat] == 18+100)
133 put_str("!", row, col + 3);
139 * Prints "title", including "wizard" or "winner" as needed.
141 static void prt_title(int row, int col)
143 cptr p;
145 /* Wizard */
146 if (p_ptr->wizard)
148 p = "[=-WIZARD-=]";
151 /* Winner */
152 else if (p_ptr->total_winner || (p_ptr->lev > PY_MAX_LEVEL))
154 p = "***WINNER***";
157 /* Normal */
158 else
160 p = c_text + cp_ptr->title[(p_ptr->lev - 1) / 5];
163 prt_field(p, row, col);
168 * Prints level
170 static void prt_level(int row, int col)
172 char tmp[32];
174 strnfmt(tmp, sizeof(tmp), "%6d", p_ptr->lev);
176 if (p_ptr->lev >= p_ptr->max_lev)
178 put_str("LEVEL ", row, col);
179 c_put_str(TERM_L_GREEN, tmp, row, col + 6);
181 else
183 put_str("Level ", row, col);
184 c_put_str(TERM_YELLOW, tmp, row, col + 6);
190 * Display the experience
192 static void prt_exp(int row, int col)
194 char out_val[32];
195 bool lev50 = (p_ptr->lev == 50);
197 long xp = (long)p_ptr->exp;
200 /* Calculate XP for next level */
201 if (!lev50)
202 xp = (long)(player_exp[p_ptr->lev - 1] * p_ptr->expfact / 100L) - p_ptr->exp;
204 /* Format XP */
205 strnfmt(out_val, sizeof(out_val), "%8ld", (long)xp);
208 if (p_ptr->exp >= p_ptr->max_exp)
210 put_str((lev50 ? "EXP" : "NXT"), row, col);
211 c_put_str(TERM_L_GREEN, out_val, row, col + 4);
213 else
215 put_str((lev50 ? "Exp" : "Nxt"), row, col);
216 c_put_str(TERM_YELLOW, out_val, row, col + 4);
222 * Prints current gold
224 static void prt_gold(int row, int col)
226 char tmp[32];
228 put_str("AU ", row, col);
229 strnfmt(tmp, sizeof(tmp), "%9ld", (long)p_ptr->au);
230 c_put_str(TERM_L_GREEN, tmp, row, col + 3);
235 * Equippy chars
237 static void prt_equippy(int row, int col)
239 int i;
241 byte a;
242 char c;
244 object_type *o_ptr;
246 /* No equippy chars in bigtile mode */
247 if (use_bigtile) return;
249 /* Dump equippy chars */
250 for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
252 /* Object */
253 o_ptr = &inventory[i];
255 a = object_attr(o_ptr);
256 c = object_char(o_ptr);
258 /* Clear the part of the screen */
259 if (!o_ptr->k_idx)
261 c = ' ';
262 a = TERM_WHITE;
265 /* Dump */
266 Term_putch(col + i - INVEN_WIELD, row, a, c);
272 * Prints current AC
274 static void prt_ac(int row, int col)
276 char tmp[32];
278 put_str("Cur AC ", row, col);
279 strnfmt(tmp, sizeof(tmp), "%5d", p_ptr->dis_ac + p_ptr->dis_to_a);
280 c_put_str(TERM_L_GREEN, tmp, row, col + 7);
285 * Prints Cur hit points
287 static void prt_hp(int row, int col)
289 char cur_hp[32], max_hp[32];
290 byte color;
292 put_str("HP ", row, col);
294 strnfmt(max_hp, sizeof(max_hp), "%4d", p_ptr->mhp);
295 strnfmt(cur_hp, sizeof(cur_hp), "%4d", p_ptr->chp);
297 if (p_ptr->chp >= p_ptr->mhp)
298 color = TERM_L_GREEN;
299 else if (p_ptr->chp > (p_ptr->mhp * op_ptr->hitpoint_warn) / 10)
300 color = TERM_YELLOW;
301 else
302 color = TERM_RED;
304 c_put_str(color, cur_hp, row, col + 3);
305 c_put_str(TERM_WHITE, "/", row, col + 7);
306 c_put_str(TERM_L_GREEN, max_hp, row, col + 8);
311 * Prints players max/cur spell points
313 static void prt_sp(int row, int col)
315 char cur_sp[32], max_sp[32];
316 byte color;
318 /* Do not show mana unless it matters */
319 if (!cp_ptr->spell_book) return;
321 put_str("SP ", row, col);
323 strnfmt(max_sp, sizeof(max_sp), "%4d", p_ptr->msp);
324 strnfmt(cur_sp, sizeof(cur_sp), "%4d", p_ptr->csp);
326 if (p_ptr->csp >= p_ptr->msp)
327 color = TERM_L_GREEN;
328 else if (p_ptr->csp > (p_ptr->msp * op_ptr->hitpoint_warn) / 10)
329 color = TERM_YELLOW;
330 else
331 color = TERM_RED;
333 /* Show mana */
334 c_put_str(color, cur_sp, row, col + 3);
335 c_put_str(TERM_WHITE, "/", row, col + 7);
336 c_put_str(TERM_L_GREEN, max_sp, row, col + 8);
341 * Redraw the "monster health bar"
343 * The "monster health bar" provides visual feedback on the "health"
344 * of the monster currently being "tracked". There are several ways
345 * to "track" a monster, including targetting it, attacking it, and
346 * affecting it (and nobody else) with a ranged attack. When nothing
347 * is being tracked, we clear the health bar. If the monster being
348 * tracked is not currently visible, a special health bar is shown.
350 static void prt_health(int row, int col)
352 /* Not tracking */
353 if (!p_ptr->health_who)
355 /* Erase the health bar */
356 Term_erase(col, row, 12);
359 /* Tracking an unseen monster */
360 else if (!mon_list[p_ptr->health_who].ml)
362 /* Indicate that the monster health is "unknown" */
363 Term_putstr(col, row, 12, TERM_WHITE, "[----------]");
366 /* Tracking a hallucinatory monster */
367 else if (p_ptr->timed[TMD_IMAGE])
369 /* Indicate that the monster health is "unknown" */
370 Term_putstr(col, row, 12, TERM_WHITE, "[----------]");
373 /* Tracking a dead monster (?) */
374 else if (!mon_list[p_ptr->health_who].hp < 0)
376 /* Indicate that the monster health is "unknown" */
377 Term_putstr(col, row, 12, TERM_WHITE, "[----------]");
380 /* Tracking a visible monster */
381 else
383 int pct, len;
385 monster_type *m_ptr = &mon_list[p_ptr->health_who];
387 /* Default to almost dead */
388 byte attr = TERM_RED;
390 /* Extract the "percent" of health */
391 pct = 100L * m_ptr->hp / m_ptr->maxhp;
393 /* Badly wounded */
394 if (pct >= 10) attr = TERM_L_RED;
396 /* Wounded */
397 if (pct >= 25) attr = TERM_ORANGE;
399 /* Somewhat Wounded */
400 if (pct >= 60) attr = TERM_YELLOW;
402 /* Healthy */
403 if (pct >= 100) attr = TERM_L_GREEN;
405 /* Afraid */
406 if (m_ptr->monfear) attr = TERM_VIOLET;
408 /* Confused */
409 if (m_ptr->confused) attr = TERM_UMBER;
411 /* Stunned */
412 if (m_ptr->stunned) attr = TERM_L_BLUE;
414 /* Asleep */
415 if (m_ptr->csleep) attr = TERM_BLUE;
417 /* Convert percent into "health" */
418 len = (pct < 10) ? 1 : (pct < 90) ? (pct / 10 + 1) : 10;
420 /* Default to "unknown" */
421 Term_putstr(col, row, 12, TERM_WHITE, "[----------]");
423 /* Dump the current "health" (use '*' symbols) */
424 Term_putstr(col + 1, row, len, attr, "**********");
430 * Print cut indicator.
432 static void prt_cut(int row, int col)
434 int c = p_ptr->timed[TMD_CUT];
436 if (c > 1000)
438 c_put_str(TERM_L_RED, "Mortal wound", row, col);
440 else if (c > 200)
442 c_put_str(TERM_RED, "Deep gash ", row, col);
444 else if (c > 100)
446 c_put_str(TERM_RED, "Severe cut ", row, col);
448 else if (c > 50)
450 c_put_str(TERM_ORANGE, "Nasty cut ", row, col);
452 else if (c > 25)
454 c_put_str(TERM_ORANGE, "Bad cut ", row, col);
456 else if (c > 10)
458 c_put_str(TERM_YELLOW, "Light cut ", row, col);
460 else if (c)
462 c_put_str(TERM_YELLOW, "Graze ", row, col);
464 else
466 put_str(" ", row, col);
472 * Print stun indicator.
474 static void prt_stun(int row, int col)
476 int s = p_ptr->timed[TMD_STUN];
478 if (s > 100)
480 c_put_str(TERM_RED, "Knocked out ", row, col);
482 else if (s > 50)
484 c_put_str(TERM_ORANGE, "Heavy stun ", row, col);
486 else if (s)
488 c_put_str(TERM_ORANGE, "Stun ", row, col);
490 else
492 put_str(" ", row, col);
499 /* Some simple wrapper functions */
500 static void prt_str(int row, int col) { prt_stat(A_STR, row, col); }
501 static void prt_dex(int row, int col) { prt_stat(A_DEX, row, col); }
502 static void prt_wis(int row, int col) { prt_stat(A_WIS, row, col); }
503 static void prt_int(int row, int col) { prt_stat(A_INT, row, col); }
504 static void prt_con(int row, int col) { prt_stat(A_CON, row, col); }
505 static void prt_chr(int row, int col) { prt_stat(A_CHR, row, col); }
506 static void prt_race(int row, int col) { prt_field(p_name + rp_ptr->name, row, col); }
507 static void prt_class(int row, int col) { prt_field(c_name + cp_ptr->name, row, col); }
511 * Struct of sidebar handlers.
513 static const struct side_handler_t
515 void (*hook)(int, int); /* int row, int col */
516 int priority; /* 1 is most important (always displayed) */
517 u32b flag; /* PR_* flag this corresponds to */
518 } side_handlers[] =
520 { prt_race, 20, PR_MISC },
521 { prt_class, 19, PR_MISC },
522 { prt_title, 18, PR_TITLE },
523 { prt_level, 10, PR_LEV },
524 { prt_exp, 15, PR_EXP },
525 { prt_gold, 11, PR_GOLD },
526 { prt_equippy, 17, PR_EQUIPPY },
527 { prt_str, 6, PR_STATS },
528 { prt_int, 5, PR_STATS },
529 { prt_wis, 4, PR_STATS },
530 { prt_dex, 3, PR_STATS },
531 { prt_con, 2, PR_STATS },
532 { prt_chr, 1, PR_STATS },
533 { NULL, 14, 0 },
534 { prt_ac, 7, PR_ARMOR },
535 { prt_hp, 8, PR_HP },
536 { prt_sp, 9, PR_MANA },
537 { NULL, 22, 0 },
538 { prt_health, 12, PR_HEALTH },
539 { NULL, 21, 0 },
540 { prt_cut, 13, PR_CUT },
541 { prt_stun, 16, PR_STUN }
546 * This prints the sidebar, using a clever method which means that it will only
547 * print as much as can be displayed on <24-line screens.
549 * Each row is given a priority; the least important higher numbers and the most
550 * important lower numbers. As the screen gets smaller, the rows start to
551 * disappear in the order of lowest to highest importance.
553 static void display_sidebar(void)
555 int x, y, row;
556 int max_priority;
557 size_t i;
558 u32b to_clear = 0;
561 Term_get_size(&x, &y);
563 /* Keep the top and bottom lines clear. */
564 max_priority = y - 2;
566 /* Display list entries */
567 for (i = 0, row = 1; i < N_ELEMENTS(side_handlers); i++)
569 const struct side_handler_t *hnd = &side_handlers[i];
571 /* If this is high enough priority, display it */
572 if (hnd->priority <= max_priority)
574 /* If the redraw flag it set, and there is a hook */
575 if ((p_ptr->redraw & hnd->flag) && hnd->hook)
577 /* Mark flag for removal */
578 to_clear |= hnd->flag;
580 /* Display at the current row */
581 hnd->hook(row, 0);
584 /* Increment for next time */
585 row++;
589 /* Clear flags */
590 p_ptr->redraw &= ~(to_clear);
596 /*** Status line display functions ***/
599 * Prints depth in stat area
601 static void prt_depth(int row, int col)
603 char depths[32];
605 if (!p_ptr->depth)
607 my_strcpy(depths, "Town", sizeof(depths));
609 else if (depth_in_feet)
611 strnfmt(depths, sizeof(depths), "%d ft", p_ptr->depth * 50);
613 else
615 strnfmt(depths, sizeof(depths), "Lev %d", p_ptr->depth);
618 /* Right-Adjust the "depth", and clear old values */
619 prt(format("%7s", depths), row, col);
624 * Prints status of hunger
626 static void prt_hunger(int row, int col)
628 /* Fainting / Starving */
629 if (p_ptr->food < PY_FOOD_FAINT)
631 c_put_str(TERM_RED, "Weak ", row, col);
634 /* Weak */
635 else if (p_ptr->food < PY_FOOD_WEAK)
637 c_put_str(TERM_ORANGE, "Weak ", row, col);
640 /* Hungry */
641 else if (p_ptr->food < PY_FOOD_ALERT)
643 c_put_str(TERM_YELLOW, "Hungry", row, col);
646 /* Normal */
647 else if (p_ptr->food < PY_FOOD_FULL)
649 c_put_str(TERM_L_GREEN, " ", row, col);
652 /* Full */
653 else if (p_ptr->food < PY_FOOD_MAX)
655 c_put_str(TERM_L_GREEN, "Full ", row, col);
658 /* Gorged */
659 else
661 c_put_str(TERM_GREEN, "Gorged", row, col);
667 * Prints Blind status
669 static void prt_blind(int row, int col)
671 if (p_ptr->timed[TMD_BLIND])
673 c_put_str(TERM_ORANGE, "Blind", row, col);
675 else
677 put_str(" ", row, col);
683 * Prints Confusion status
685 static void prt_confused(int row, int col)
687 bool confused = p_ptr->timed[TMD_CONFUSED] ? TRUE : FALSE;
688 bool forget = p_ptr->timed[TMD_AMNESIA] ? TRUE : FALSE;
690 const char *text = " ";
692 if (confused && !forget)
693 text = "Confused";
694 else if (confused && forget)
695 text = "Conf Amn";
696 else if (!confused && forget)
697 text = "Amnesiac";
699 c_put_str(TERM_ORANGE, text, row, col);
704 * Prints Fear status
706 static void prt_afraid(int row, int col)
708 if (p_ptr->timed[TMD_AFRAID])
710 c_put_str(TERM_ORANGE, "Afraid", row, col);
712 else
714 put_str(" ", row, col);
720 * Prints Poisoned status
722 static void prt_poisoned(int row, int col)
724 if (p_ptr->timed[TMD_POISONED])
726 c_put_str(TERM_ORANGE, "Poisoned", row, col);
728 else
730 put_str(" ", row, col);
736 * Prints Searching, Resting, Paralysis, or 'count' status
737 * Display is always exactly 10 characters wide (see below)
739 * This function was a major bottleneck when resting, so a lot of
740 * the text formatting code was optimized in place below.
742 static void prt_state(int row, int col)
744 byte attr = TERM_WHITE;
746 char text[16];
749 /* Paralysis */
750 if (p_ptr->timed[TMD_PARALYZED])
752 attr = TERM_RED;
754 my_strcpy(text, "Paralyzed!", sizeof(text));
757 /* Resting */
758 else if (p_ptr->resting)
760 int i;
761 int n = p_ptr->resting;
763 /* Start with "Rest" */
764 my_strcpy(text, "Rest ", sizeof(text));
766 /* Extensive (timed) rest */
767 if (n >= 1000)
769 i = n / 100;
770 text[9] = '0';
771 text[8] = '0';
772 text[7] = I2D(i % 10);
773 if (i >= 10)
775 i = i / 10;
776 text[6] = I2D(i % 10);
777 if (i >= 10)
779 text[5] = I2D(i / 10);
784 /* Long (timed) rest */
785 else if (n >= 100)
787 i = n;
788 text[9] = I2D(i % 10);
789 i = i / 10;
790 text[8] = I2D(i % 10);
791 text[7] = I2D(i / 10);
794 /* Medium (timed) rest */
795 else if (n >= 10)
797 i = n;
798 text[9] = I2D(i % 10);
799 text[8] = I2D(i / 10);
802 /* Short (timed) rest */
803 else if (n > 0)
805 i = n;
806 text[9] = I2D(i);
809 /* Rest until healed */
810 else if (n == -1)
812 text[5] = text[6] = text[7] = text[8] = text[9] = '*';
815 /* Rest until done */
816 else if (n == -2)
818 text[5] = text[6] = text[7] = text[8] = text[9] = '&';
822 /* Repeating */
823 else if (p_ptr->command_rep)
825 if (p_ptr->command_rep > 999)
826 strnfmt(text, sizeof(text), "Rep. %3d00", p_ptr->command_rep / 100);
827 else
828 strnfmt(text, sizeof(text), "Repeat %3d", p_ptr->command_rep);
831 /* Searching */
832 else if (p_ptr->searching)
834 my_strcpy(text, "Searching ", sizeof(text));
837 /* Nothing interesting */
838 else
840 my_strcpy(text, " ", sizeof(text));
843 /* Display the info (or blanks) */
844 c_put_str(attr, text, row, col);
849 * Prints the speed of a character.
851 static void prt_speed(int row, int col)
853 int i = p_ptr->pspeed;
855 byte attr = TERM_WHITE;
856 const char *type = NULL;
857 char buf[32] = "";
859 /* Hack -- Visually "undo" the Search Mode Slowdown */
860 if (p_ptr->searching) i += 10;
862 /* Fast */
863 if (i > 110)
865 attr = TERM_L_GREEN;
866 type = "Fast";
869 /* Slow */
870 else if (i < 110)
872 attr = TERM_L_UMBER;
873 type = "Slow";
876 if (type)
877 strnfmt(buf, sizeof(buf), "%s (%+d)", type, (i - 110));
879 /* Display the speed */
880 c_put_str(attr, format("%-14s", buf), row, col);
885 * Print whether a character is studying or not.
887 static void prt_study(int row, int col)
889 if (p_ptr->new_spells)
891 put_str("Study", row, col);
893 else
895 put_str(" ", row, col);
900 static void prt_elements(int row, int col)
902 int wid, n;
904 /* Number of resists to display */
905 int count = 5;
907 /* XXX Ignore column setting */
908 col = 80;
909 wid = Term->wid - col;
911 /* Print up to 5 letters of the resist */
912 n = MIN(wid / count, 5);
915 /* Check space */
916 if (n <= 0) return;
919 if (p_ptr->timed[TMD_OPP_ACID])
920 Term_putstr(col, row, n, TERM_SLATE, "Acid ");
921 else
922 Term_putstr(col, row, n, TERM_SLATE, " ");
924 col += n;
926 if (p_ptr->timed[TMD_OPP_ELEC])
927 Term_putstr(col, row, n, TERM_BLUE, "Elec ");
928 else
929 Term_putstr(col, row, n, TERM_BLUE, " ");
931 col += n;
933 if (p_ptr->timed[TMD_OPP_FIRE])
934 Term_putstr(col, row, n, TERM_RED, "Fire ");
935 else
936 Term_putstr(col, row, n, TERM_RED, " ");
938 col += n;
940 if (p_ptr->timed[TMD_OPP_COLD])
941 Term_putstr(col, row, n, TERM_WHITE, "Cold ");
942 else
943 Term_putstr(col, row, n, TERM_WHITE, " ");
945 col += n;
947 if (p_ptr->timed[TMD_OPP_POIS])
948 Term_putstr(col, row, n, TERM_GREEN, "Pois ");
949 else
950 Term_putstr(col, row, n, TERM_GREEN, " ");
957 * Struct of status line indicators.
959 static const struct status_handler_t
961 u32b flag; /* p_ptr->redraw flag this entry is for */
962 int column; /* Column to display at */
963 void (*hook)(int row, int col); /* Display function */
964 } status_handlers[] =
966 { PR_HUNGER, 0, prt_hunger }, /* "Weak" / "Hungry" / "Full" / "Gorged" */
967 { PR_BLIND, 7, prt_blind }, /* "Blind" */
968 { PR_CONFUSED, 13, prt_confused }, /* "Confused" */
969 { PR_AFRAID, 22, prt_afraid }, /* "Afraid" */
970 { PR_POISONED, 29, prt_poisoned }, /* "Poisoned" */
971 { PR_STATE, 38, prt_state }, /* <state> */
972 { PR_SPEED, 49, prt_speed }, /* "Slow (-NN)" or "Fast (+NN)" */
973 { PR_STUDY, 64, prt_study }, /* "Study" */
974 { PR_DEPTH, 70, prt_depth }, /* "Lev NNN" / "NNNN ft" */
975 { PR_OPPOSE_ELEMENTS, 80, prt_elements }, /* Acid Elec Fire Cold Pois */
980 * Print the status line.
982 static void display_statusline(void)
984 int row = Term->hgt - 1;
985 size_t i;
987 /* Display those which need redrawing */
988 for (i = 0; i < N_ELEMENTS(status_handlers); i++)
990 const struct status_handler_t *hnd = &status_handlers[i];
992 if (p_ptr->redraw & hnd->flag)
994 p_ptr->redraw &= ~(hnd->flag);
995 hnd->hook(row, hnd->column);
999 return;
1005 /*** Subwindow display functions ***/
1008 * Hack -- display player in sub-windows (mode 0)
1010 static void fix_player_0(void)
1012 /* Display player */
1013 display_player(0);
1018 * Hack -- display player in sub-windows (mode 1)
1020 static void fix_player_1(void)
1022 /* Display flags */
1023 display_player(1);
1028 * Hack - Display the left-hand-side of the main term in a separate window
1030 static void fix_frame_compact(void)
1032 int row = 0;
1033 int col = 0;
1034 int i;
1036 /* Race and Class */
1037 prt_field(p_name + rp_ptr->name, row++, col);
1038 prt_field(c_name + cp_ptr->name, row++, col);
1040 /* Title */
1041 prt_title(row++, col);
1043 /* Level/Experience */
1044 prt_level(row++, col);
1045 prt_exp(row++, col);
1047 /* Gold */
1048 prt_gold(row++, col);
1050 /* Equippy chars */
1051 prt_equippy(row++, col);
1053 /* All Stats */
1054 for (i = 0; i < A_MAX; i++) prt_stat(i, row++, col);
1056 /* Empty row */
1057 row++;
1059 /* Armor */
1060 prt_ac(row++, col);
1062 /* Hitpoints */
1063 prt_hp(row++, col);
1065 /* Spellpoints */
1066 prt_sp(row++, col);
1068 /* Monster health */
1069 prt_health(row++, col);
1071 /* Cut */
1072 prt_cut(row++, col);
1074 /* Stun */
1075 prt_stun(row++, col);
1080 * Hack -- display recent messages in sub-windows
1082 * Adjust for width and split messages. XXX XXX XXX
1084 static void fix_message(void)
1086 int i;
1087 int w, h;
1088 int x, y;
1090 /* Get size */
1091 Term_get_size(&w, &h);
1093 /* Dump messages */
1094 for (i = 0; i < h; i++)
1096 byte color = message_color((s16b)i);
1098 /* Dump the message on the appropriate line */
1099 Term_putstr(0, (h - 1) - i, -1, color, message_str((s16b)i));
1101 /* Cursor */
1102 Term_locate(&x, &y);
1104 /* Clear to end of line */
1105 Term_erase(x, y, 255);
1111 * Hack -- display overhead view in sub-windows.
1113 * This is most useful on a fast machine with the "center_player" option set,
1114 * which induces a call to this function every time the player moves. With
1115 * the "center_player" option not set, this function is only called when the
1116 * panel changes.
1118 * The "display_map()" function handles NULL arguments in a special manner.
1120 static void fix_overhead(void)
1122 /* Redraw map */
1123 display_map(NULL, NULL);
1128 * Hack -- display monster recall in sub-windows
1130 static void fix_monster(void)
1132 /* Display monster race info */
1133 if (p_ptr->monster_race_idx)
1134 display_roff(p_ptr->monster_race_idx);
1139 * Hack -- display object recall in sub-windows
1141 static void fix_object(void)
1143 /* Display object type info */
1144 if (p_ptr->object_kind_idx)
1145 display_koff(p_ptr->object_kind_idx);
1150 * Print the status display subwindow
1152 static void fix_status(void)
1154 int row = 0;
1155 size_t i;
1157 for (i = 0; i < N_ELEMENTS(status_handlers) - 1; i++)
1159 status_handlers[i].hook(row, 0);
1160 row++;
1168 * Struct of subwindow display handlers.
1170 static const struct win_handler_t
1172 u32b flag;
1173 void (*hook)(void);
1174 } win_handlers[] =
1176 { PW_INVEN, display_inven }, /* Display inventory */
1177 { PW_EQUIP, display_equip }, /* Display equipment */
1178 { PW_PLAYER_0, fix_player_0 },
1179 { PW_PLAYER_1, fix_player_1 },
1180 { PW_PLAYER_2, fix_frame_compact },
1181 #if 0
1182 { PW_MAP, fix_map }, /* The maps are always up-to-date */
1183 #endif
1184 { PW_MESSAGE, fix_message },
1185 { PW_OVERHEAD, fix_overhead },
1186 { PW_MONSTER, fix_monster },
1187 { PW_OBJECT, fix_object },
1188 { PW_MONLIST, display_monlist }, /* Display visible monsters */
1189 { PW_STATUS, fix_status } /* Display status lines */
1194 * Handle "p_ptr->window"
1196 void window_stuff(void)
1198 size_t i, j;
1199 u32b mask = 0L;
1200 term *old = Term;
1202 /* Nothing to do */
1203 if (!p_ptr->window) return;
1205 /* Scan windows */
1206 for (i = 0; i < ANGBAND_TERM_MAX; i++)
1208 /* Ignore non-windows */
1209 if (!angband_term[i]) break;
1211 /* Save usable flags */
1212 mask |= op_ptr->window_flag[i];
1215 /* Apply usable flags */
1216 p_ptr->window &= (mask);
1218 /* Nothing to do */
1219 if (!p_ptr->window) return;
1222 /* Walk through all the handlers */
1223 for (i = 0; i < N_ELEMENTS(win_handlers); i++)
1225 const struct win_handler_t *hnd = &win_handlers[i];
1227 /* Don't bother if it has no flags set */
1228 if (!(p_ptr->window & hnd->flag)) continue;
1230 /* Iterate over all the terms */
1231 for (j = 0; j < ANGBAND_TERM_MAX; j++)
1233 /* No window */
1234 if (!angband_term[j]) continue;
1236 /* No relevant flags */
1237 if (!(op_ptr->window_flag[j] & hnd->flag)) continue;
1239 /* Call the hook */
1240 Term_activate(angband_term[j]);
1241 hnd->hook();
1242 Term_fresh();
1245 /* Forget the flag */
1246 p_ptr->window &= ~(hnd->flag);
1249 /* Restore old terminal */
1250 Term_activate(old);
1256 /*** Update flag handler functions ***/
1259 * Calculate number of spells player should have, and forget,
1260 * or remember, spells until that number is properly reflected.
1262 * Note that this function induces various "status" messages,
1263 * which must be bypasses until the character is created.
1265 static void calc_spells(void)
1267 int i, j, k, levels;
1268 int num_allowed, num_known;
1269 int percent_spells;
1271 const magic_type *s_ptr;
1273 s16b old_spells;
1275 cptr p = ((cp_ptr->spell_book == TV_MAGIC_BOOK) ? "spell" : "prayer");
1278 /* Hack -- must be literate */
1279 if (!cp_ptr->spell_book) return;
1281 /* Hack -- wait for creation */
1282 if (!character_generated) return;
1284 /* Hack -- handle "xtra" mode */
1285 if (character_xtra) return;
1287 /* Save the new_spells value */
1288 old_spells = p_ptr->new_spells;
1291 /* Determine the number of spells allowed */
1292 levels = p_ptr->lev - cp_ptr->spell_first + 1;
1294 /* Hack -- no negative spells */
1295 if (levels < 0) levels = 0;
1297 /* Number of 1/100 spells per level */
1298 percent_spells = adj_mag_study[p_ptr->stat_ind[cp_ptr->spell_stat]];
1300 /* Extract total allowed spells (rounded up) */
1301 num_allowed = (((percent_spells * levels) + 50) / 100);
1303 /* Assume none known */
1304 num_known = 0;
1306 /* Count the number of spells we know */
1307 for (j = 0; j < PY_MAX_SPELLS; j++)
1309 /* Count known spells */
1310 if (p_ptr->spell_flags[j] & PY_SPELL_LEARNED)
1312 num_known++;
1316 /* See how many spells we must forget or may learn */
1317 p_ptr->new_spells = num_allowed - num_known;
1321 /* Forget spells which are too hard */
1322 for (i = PY_MAX_SPELLS - 1; i >= 0; i--)
1324 /* Get the spell */
1325 j = p_ptr->spell_order[i];
1327 /* Skip non-spells */
1328 if (j >= 99) continue;
1330 /* Get the spell */
1331 s_ptr = &mp_ptr->info[j];
1333 /* Skip spells we are allowed to know */
1334 if (s_ptr->slevel <= p_ptr->lev) continue;
1336 /* Is it known? */
1337 if (p_ptr->spell_flags[j] & PY_SPELL_LEARNED)
1339 /* Mark as forgotten */
1340 p_ptr->spell_flags[j] |= PY_SPELL_FORGOTTEN;
1342 /* No longer known */
1343 p_ptr->spell_flags[j] &= ~PY_SPELL_LEARNED;
1345 /* Message */
1346 msg_format("You have forgotten the %s of %s.", p,
1347 get_spell_name(cp_ptr->spell_book, j));
1349 /* One more can be learned */
1350 p_ptr->new_spells++;
1355 /* Forget spells if we know too many spells */
1356 for (i = PY_MAX_SPELLS - 1; i >= 0; i--)
1358 /* Stop when possible */
1359 if (p_ptr->new_spells >= 0) break;
1361 /* Get the (i+1)th spell learned */
1362 j = p_ptr->spell_order[i];
1364 /* Skip unknown spells */
1365 if (j >= 99) continue;
1367 /* Forget it (if learned) */
1368 if (p_ptr->spell_flags[j] & PY_SPELL_LEARNED)
1370 /* Mark as forgotten */
1371 p_ptr->spell_flags[j] |= PY_SPELL_FORGOTTEN;
1373 /* No longer known */
1374 p_ptr->spell_flags[j] &= ~PY_SPELL_LEARNED;
1376 /* Message */
1377 msg_format("You have forgotten the %s of %s.", p,
1378 get_spell_name(cp_ptr->spell_book, j));
1380 /* One more can be learned */
1381 p_ptr->new_spells++;
1386 /* Check for spells to remember */
1387 for (i = 0; i < PY_MAX_SPELLS; i++)
1389 /* None left to remember */
1390 if (p_ptr->new_spells <= 0) break;
1392 /* Get the next spell we learned */
1393 j = p_ptr->spell_order[i];
1395 /* Skip unknown spells */
1396 if (j >= 99) break;
1398 /* Get the spell */
1399 s_ptr = &mp_ptr->info[j];
1401 /* Skip spells we cannot remember */
1402 if (s_ptr->slevel > p_ptr->lev) continue;
1404 /* First set of spells */
1405 if (p_ptr->spell_flags[j] & PY_SPELL_FORGOTTEN)
1407 /* No longer forgotten */
1408 p_ptr->spell_flags[j] &= ~PY_SPELL_FORGOTTEN;
1410 /* Known once more */
1411 p_ptr->spell_flags[j] |= PY_SPELL_LEARNED;
1413 /* Message */
1414 msg_format("You have remembered the %s of %s.",
1415 p, get_spell_name(cp_ptr->spell_book, j));
1417 /* One less can be learned */
1418 p_ptr->new_spells--;
1423 /* Assume no spells available */
1424 k = 0;
1426 /* Count spells that can be learned */
1427 for (j = 0; j < PY_MAX_SPELLS; j++)
1429 /* Get the spell */
1430 s_ptr = &mp_ptr->info[j];
1432 /* Skip spells we cannot remember */
1433 if (s_ptr->slevel > p_ptr->lev) continue;
1435 /* Skip spells we already know */
1436 if (p_ptr->spell_flags[j] & PY_SPELL_LEARNED)
1438 continue;
1441 /* Count it */
1442 k++;
1445 /* Cannot learn more spells than exist */
1446 if (p_ptr->new_spells > k) p_ptr->new_spells = k;
1448 /* Spell count changed */
1449 if (old_spells != p_ptr->new_spells)
1451 /* Message if needed */
1452 if (p_ptr->new_spells)
1454 /* Message */
1455 msg_format("You can learn %d more %s%s.",
1456 p_ptr->new_spells, p,
1457 (p_ptr->new_spells != 1) ? "s" : "");
1460 /* Redraw Study Status */
1461 p_ptr->redraw |= (PR_STUDY);
1463 /* Redraw object recall */
1464 p_ptr->window |= (PW_OBJECT);
1470 * Calculate maximum mana. You do not need to know any spells.
1471 * Note that mana is lowered by heavy (or inappropriate) armor.
1473 * This function induces status messages.
1475 static void calc_mana(void)
1477 int msp, levels, cur_wgt, max_wgt;
1479 object_type *o_ptr;
1481 bool old_cumber_glove = p_ptr->cumber_glove;
1482 bool old_cumber_armor = p_ptr->cumber_armor;
1484 /* Hack -- Must be literate */
1485 if (!cp_ptr->spell_book) return;
1488 /* Extract "effective" player level */
1489 levels = (p_ptr->lev - cp_ptr->spell_first) + 1;
1491 /* Hack -- no negative mana */
1492 if (levels < 0) levels = 0;
1494 /* Extract total mana */
1495 msp = (long)adj_mag_mana[p_ptr->stat_ind[cp_ptr->spell_stat]] * levels / 100;
1497 /* Hack -- usually add one mana */
1498 if (msp) msp++;
1500 /* Process gloves for those disturbed by them */
1501 if (cp_ptr->flags & CF_CUMBER_GLOVE)
1503 u32b f1, f2, f3;
1505 /* Assume player is not encumbered by gloves */
1506 p_ptr->cumber_glove = FALSE;
1508 /* Get the gloves */
1509 o_ptr = &inventory[INVEN_HANDS];
1511 /* Examine the gloves */
1512 object_flags(o_ptr, &f1, &f2, &f3);
1514 /* Normal gloves hurt mage-type spells */
1515 if (o_ptr->k_idx &&
1516 !(f3 & (TR3_FREE_ACT)) &&
1517 !((f1 & (TR1_DEX)) && (o_ptr->pval > 0)))
1519 /* Encumbered */
1520 p_ptr->cumber_glove = TRUE;
1522 /* Reduce mana */
1523 msp = (3 * msp) / 4;
1528 /* Assume player not encumbered by armor */
1529 p_ptr->cumber_armor = FALSE;
1531 /* Weigh the armor */
1532 cur_wgt = 0;
1533 cur_wgt += inventory[INVEN_BODY].weight;
1534 cur_wgt += inventory[INVEN_HEAD].weight;
1535 cur_wgt += inventory[INVEN_ARM].weight;
1536 cur_wgt += inventory[INVEN_OUTER].weight;
1537 cur_wgt += inventory[INVEN_HANDS].weight;
1538 cur_wgt += inventory[INVEN_FEET].weight;
1540 /* Determine the weight allowance */
1541 max_wgt = cp_ptr->spell_weight;
1543 /* Heavy armor penalizes mana */
1544 if (((cur_wgt - max_wgt) / 10) > 0)
1546 /* Encumbered */
1547 p_ptr->cumber_armor = TRUE;
1549 /* Reduce mana */
1550 msp -= ((cur_wgt - max_wgt) / 10);
1554 /* Mana can never be negative */
1555 if (msp < 0) msp = 0;
1558 /* Maximum mana has changed */
1559 if (p_ptr->msp != msp)
1561 /* Save new limit */
1562 p_ptr->msp = msp;
1564 /* Enforce new limit */
1565 if (p_ptr->csp >= msp)
1567 p_ptr->csp = msp;
1568 p_ptr->csp_frac = 0;
1571 /* Display mana later */
1572 p_ptr->redraw |= (PR_MANA);
1574 /* Window stuff */
1575 p_ptr->window |= (PW_PLAYER_0 | PW_PLAYER_1);
1579 /* Hack -- handle "xtra" mode */
1580 if (character_xtra) return;
1582 /* Take note when "glove state" changes */
1583 if (old_cumber_glove != p_ptr->cumber_glove)
1585 /* Message */
1586 if (p_ptr->cumber_glove)
1588 msg_print("Your covered hands feel unsuitable for spellcasting.");
1590 else
1592 msg_print("Your hands feel more suitable for spellcasting.");
1597 /* Take note when "armor state" changes */
1598 if (old_cumber_armor != p_ptr->cumber_armor)
1600 /* Message */
1601 if (p_ptr->cumber_armor)
1603 msg_print("The weight of your armor encumbers your movement.");
1605 else
1607 msg_print("You feel able to move more freely.");
1614 * Calculate the players (maximal) hit points
1616 * Adjust current hitpoints if necessary
1618 static void calc_hitpoints(void)
1620 long bonus;
1621 int mhp;
1623 /* Get "1/100th hitpoint bonus per level" value */
1624 bonus = adj_con_mhp[p_ptr->stat_ind[A_CON]];
1626 /* Calculate hitpoints */
1627 mhp = p_ptr->player_hp[p_ptr->lev-1] + (bonus * p_ptr->lev / 100);
1629 /* Always have at least one hitpoint per level */
1630 if (mhp < p_ptr->lev + 1) mhp = p_ptr->lev + 1;
1632 /* New maximum hitpoints */
1633 if (p_ptr->mhp != mhp)
1635 /* Save new limit */
1636 p_ptr->mhp = mhp;
1638 /* Enforce new limit */
1639 if (p_ptr->chp >= mhp)
1641 p_ptr->chp = mhp;
1642 p_ptr->chp_frac = 0;
1645 /* Display hitpoints (later) */
1646 p_ptr->redraw |= (PR_HP);
1648 /* Window stuff */
1649 p_ptr->window |= (PW_PLAYER_0 | PW_PLAYER_1);
1655 * Calculate and set the current light radius.
1657 * The brightest wielded object counts as the light source; radii do not add
1658 * up anymore.
1660 * Note that a cursed light source no longer emits light.
1662 static void calc_torch(void)
1664 int i;
1666 s16b old_lite = p_ptr->cur_lite;
1667 bool burn_light = TRUE;
1669 s16b new_lite = 0;
1670 int extra_lite = 0;
1674 /* Ascertain lightness if in the town */
1675 if (!p_ptr->depth && ((turn % (10L * TOWN_DAWN)) < ((10L * TOWN_DAWN) / 2)))
1676 burn_light = FALSE;
1679 /* Examine all wielded objects, use the brightest */
1680 for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
1682 u32b f1, f2, f3;
1684 int amt = 0;
1685 object_type *o_ptr = &inventory[i];
1687 /* Skip empty slots */
1688 if (!o_ptr->k_idx) continue;
1690 /* Extract the flags */
1691 object_flags(o_ptr, &f1, &f2, &f3);
1693 /* Cursed objects emit no light */
1694 if (o_ptr->ident & IDENT_CURSED)
1696 amt = 0;
1699 /* Examine actual lites */
1700 else if (o_ptr->tval == TV_LITE)
1702 int flag_inc = (f3 & TR3_LITE) ? 1 : 0;
1704 /* Artifact Lites provide permanent bright light */
1705 if (artifact_p(o_ptr))
1706 amt = 3 + flag_inc;
1708 /* Non-artifact lights and those without fuel provide no light */
1709 else if (!burn_light || o_ptr->timeout == 0)
1710 amt = 0;
1712 /* All lit lights provide at least radius 2 light */
1713 else
1715 amt = 2 + flag_inc;
1717 /* Torches below half fuel provide less light */
1718 if (o_ptr->sval == SV_LITE_TORCH && o_ptr->timeout < (FUEL_TORCH / 4))
1719 amt--;
1723 else
1725 /* LITE flag on an non-cursed non-lights always increases radius */
1726 if (f3 & TR3_LITE) extra_lite++;
1729 /* Alter p_ptr->cur_lite if reasonable */
1730 if (new_lite < amt)
1731 new_lite = amt;
1734 /* Add bonus from LITE flags */
1735 new_lite += extra_lite;
1737 /* Limit light */
1738 new_lite = MIN(new_lite, 5);
1739 new_lite = MAX(new_lite, 0);
1741 /* Notice changes in the "lite radius" */
1742 if (old_lite != new_lite)
1744 /* Update the visuals */
1745 p_ptr->cur_lite = new_lite;
1746 p_ptr->update |= (PU_UPDATE_VIEW | PU_MONSTERS);
1752 * Computes current weight limit.
1754 static int weight_limit(void)
1756 int i;
1758 /* Weight limit based only on strength */
1759 i = adj_str_wgt[p_ptr->stat_ind[A_STR]] * 100;
1761 /* Return the result */
1762 return (i);
1767 * Calculate the players current "state", taking into account
1768 * not only race/class intrinsics, but also objects being worn
1769 * and temporary spell effects.
1771 * See also calc_mana() and calc_hitpoints().
1773 * Take note of the new "speed code", in particular, a very strong
1774 * player will start slowing down as soon as he reaches 150 pounds,
1775 * but not until he reaches 450 pounds will he be half as fast as
1776 * a normal kobold. This both hurts and helps the player, hurts
1777 * because in the old days a player could just avoid 300 pounds,
1778 * and helps because now carrying 300 pounds is not very painful.
1780 * The "weapon" and "bow" do *not* add to the bonuses to hit or to
1781 * damage, since that would affect non-combat things. These values
1782 * are actually added in later, at the appropriate place.
1784 * This function induces various "status" messages.
1786 static void calc_bonuses(void)
1788 int i, j, hold;
1790 int old_speed;
1792 int old_telepathy;
1793 int old_see_inv;
1795 int old_dis_ac;
1796 int old_dis_to_a;
1798 int extra_blows;
1799 int extra_shots;
1800 int extra_might;
1802 int old_stat_top[A_MAX];
1803 int old_stat_use[A_MAX];
1804 int old_stat_ind[A_MAX];
1806 bool old_heavy_shoot;
1807 bool old_heavy_wield;
1808 bool old_icky_wield;
1810 object_type *o_ptr;
1812 u32b f1, f2, f3;
1815 /*** Memorize ***/
1817 /* Save the old speed */
1818 old_speed = p_ptr->pspeed;
1820 /* Save the old vision stuff */
1821 old_telepathy = p_ptr->telepathy;
1822 old_see_inv = p_ptr->see_inv;
1824 /* Save the old armor class */
1825 old_dis_ac = p_ptr->dis_ac;
1826 old_dis_to_a = p_ptr->dis_to_a;
1828 /* Save the old stats */
1829 for (i = 0; i < A_MAX; i++)
1831 old_stat_top[i] = p_ptr->stat_top[i];
1832 old_stat_use[i] = p_ptr->stat_use[i];
1833 old_stat_ind[i] = p_ptr->stat_ind[i];
1836 old_heavy_shoot = p_ptr->heavy_shoot;
1837 old_heavy_wield = p_ptr->heavy_wield;
1838 old_icky_wield = p_ptr->icky_wield;
1841 /*** Reset ***/
1843 /* Reset player speed */
1844 p_ptr->pspeed = 110;
1846 /* Reset "blow" info */
1847 p_ptr->num_blow = 1;
1848 extra_blows = 0;
1850 /* Reset "fire" info */
1851 p_ptr->num_fire = 0;
1852 p_ptr->ammo_mult = 0;
1853 p_ptr->ammo_tval = 0;
1854 extra_shots = 0;
1855 extra_might = 0;
1857 /* Clear the stat modifiers */
1858 for (i = 0; i < A_MAX; i++) p_ptr->stat_add[i] = 0;
1860 /* Clear the Displayed/Real armor class */
1861 p_ptr->dis_ac = p_ptr->ac = 0;
1863 /* Clear the Displayed/Real Bonuses */
1864 p_ptr->dis_to_h = p_ptr->to_h = 0;
1865 p_ptr->dis_to_d = p_ptr->to_d = 0;
1866 p_ptr->dis_to_a = p_ptr->to_a = 0;
1868 /* Clear all the flags */
1869 p_ptr->aggravate = FALSE;
1870 p_ptr->teleport = FALSE;
1871 p_ptr->exp_drain = FALSE;
1872 p_ptr->bless_blade = FALSE;
1873 p_ptr->impact = FALSE;
1874 p_ptr->see_inv = FALSE;
1875 p_ptr->free_act = FALSE;
1876 p_ptr->slow_digest = FALSE;
1877 p_ptr->regenerate = FALSE;
1878 p_ptr->ffall = FALSE;
1879 p_ptr->hold_life = FALSE;
1880 p_ptr->telepathy = FALSE;
1881 p_ptr->sustain_str = FALSE;
1882 p_ptr->sustain_int = FALSE;
1883 p_ptr->sustain_wis = FALSE;
1884 p_ptr->sustain_con = FALSE;
1885 p_ptr->sustain_dex = FALSE;
1886 p_ptr->sustain_chr = FALSE;
1887 p_ptr->resist_acid = FALSE;
1888 p_ptr->resist_elec = FALSE;
1889 p_ptr->resist_fire = FALSE;
1890 p_ptr->resist_cold = FALSE;
1891 p_ptr->resist_pois = FALSE;
1892 p_ptr->resist_fear = FALSE;
1893 p_ptr->resist_lite = FALSE;
1894 p_ptr->resist_dark = FALSE;
1895 p_ptr->resist_blind = FALSE;
1896 p_ptr->resist_confu = FALSE;
1897 p_ptr->resist_sound = FALSE;
1898 p_ptr->resist_chaos = FALSE;
1899 p_ptr->resist_disen = FALSE;
1900 p_ptr->resist_shard = FALSE;
1901 p_ptr->resist_nexus = FALSE;
1902 p_ptr->resist_nethr = FALSE;
1903 p_ptr->immune_acid = FALSE;
1904 p_ptr->immune_elec = FALSE;
1905 p_ptr->immune_fire = FALSE;
1906 p_ptr->immune_cold = FALSE;
1909 /*** Extract race/class info ***/
1911 /* Base infravision (purely racial) */
1912 p_ptr->see_infra = rp_ptr->infra;
1914 /* Base skill -- disarming */
1915 p_ptr->skills[SKILL_DIS] = rp_ptr->r_dis + cp_ptr->c_dis;
1917 /* Base skill -- magic devices */
1918 p_ptr->skills[SKILL_DEV] = rp_ptr->r_dev + cp_ptr->c_dev;
1920 /* Base skill -- saving throw */
1921 p_ptr->skills[SKILL_SAV] = rp_ptr->r_sav + cp_ptr->c_sav;
1923 /* Base skill -- stealth */
1924 p_ptr->skills[SKILL_STL] = rp_ptr->r_stl + cp_ptr->c_stl;
1926 /* Base skill -- searching ability */
1927 p_ptr->skills[SKILL_SRH] = rp_ptr->r_srh + cp_ptr->c_srh;
1929 /* Base skill -- searching frequency */
1930 p_ptr->skills[SKILL_FOS] = rp_ptr->r_fos + cp_ptr->c_fos;
1932 /* Base skill -- combat (normal) */
1933 p_ptr->skills[SKILL_THN] = rp_ptr->r_thn + cp_ptr->c_thn;
1935 /* Base skill -- combat (shooting) */
1936 p_ptr->skills[SKILL_THB] = rp_ptr->r_thb + cp_ptr->c_thb;
1938 /* Base skill -- combat (throwing) */
1939 p_ptr->skills[SKILL_THT] = rp_ptr->r_thb + cp_ptr->c_thb;
1941 /* Base skill -- digging */
1942 p_ptr->skills[SKILL_DIG] = 0;
1944 /*** Analyze player ***/
1946 /* Extract the player flags */
1947 player_flags(&f1, &f2, &f3);
1949 /* Good flags */
1950 if (f3 & (TR3_SLOW_DIGEST)) p_ptr->slow_digest = TRUE;
1951 if (f3 & (TR3_FEATHER)) p_ptr->ffall = TRUE;
1952 if (f3 & (TR3_REGEN)) p_ptr->regenerate = TRUE;
1953 if (f3 & (TR3_TELEPATHY)) p_ptr->telepathy = TRUE;
1954 if (f3 & (TR3_SEE_INVIS)) p_ptr->see_inv = TRUE;
1955 if (f3 & (TR3_FREE_ACT)) p_ptr->free_act = TRUE;
1956 if (f3 & (TR3_HOLD_LIFE)) p_ptr->hold_life = TRUE;
1958 /* Weird flags */
1959 if (f3 & (TR3_BLESSED)) p_ptr->bless_blade = TRUE;
1961 /* Bad flags */
1962 if (f3 & (TR3_IMPACT)) p_ptr->impact = TRUE;
1963 if (f3 & (TR3_AGGRAVATE)) p_ptr->aggravate = TRUE;
1964 if (f3 & (TR3_TELEPORT)) p_ptr->teleport = TRUE;
1965 if (f3 & (TR3_DRAIN_EXP)) p_ptr->exp_drain = TRUE;
1967 /* Immunity flags */
1968 if (f2 & (TR2_IM_FIRE)) p_ptr->immune_fire = TRUE;
1969 if (f2 & (TR2_IM_ACID)) p_ptr->immune_acid = TRUE;
1970 if (f2 & (TR2_IM_COLD)) p_ptr->immune_cold = TRUE;
1971 if (f2 & (TR2_IM_ELEC)) p_ptr->immune_elec = TRUE;
1973 /* Resistance flags */
1974 if (f2 & (TR2_RES_ACID)) p_ptr->resist_acid = TRUE;
1975 if (f2 & (TR2_RES_ELEC)) p_ptr->resist_elec = TRUE;
1976 if (f2 & (TR2_RES_FIRE)) p_ptr->resist_fire = TRUE;
1977 if (f2 & (TR2_RES_COLD)) p_ptr->resist_cold = TRUE;
1978 if (f2 & (TR2_RES_POIS)) p_ptr->resist_pois = TRUE;
1979 if (f2 & (TR2_RES_FEAR)) p_ptr->resist_fear = TRUE;
1980 if (f2 & (TR2_RES_LITE)) p_ptr->resist_lite = TRUE;
1981 if (f2 & (TR2_RES_DARK)) p_ptr->resist_dark = TRUE;
1982 if (f2 & (TR2_RES_BLIND)) p_ptr->resist_blind = TRUE;
1983 if (f2 & (TR2_RES_CONFU)) p_ptr->resist_confu = TRUE;
1984 if (f2 & (TR2_RES_SOUND)) p_ptr->resist_sound = TRUE;
1985 if (f2 & (TR2_RES_SHARD)) p_ptr->resist_shard = TRUE;
1986 if (f2 & (TR2_RES_NEXUS)) p_ptr->resist_nexus = TRUE;
1987 if (f2 & (TR2_RES_NETHR)) p_ptr->resist_nethr = TRUE;
1988 if (f2 & (TR2_RES_CHAOS)) p_ptr->resist_chaos = TRUE;
1989 if (f2 & (TR2_RES_DISEN)) p_ptr->resist_disen = TRUE;
1991 /* Sustain flags */
1992 if (f2 & (TR2_SUST_STR)) p_ptr->sustain_str = TRUE;
1993 if (f2 & (TR2_SUST_INT)) p_ptr->sustain_int = TRUE;
1994 if (f2 & (TR2_SUST_WIS)) p_ptr->sustain_wis = TRUE;
1995 if (f2 & (TR2_SUST_DEX)) p_ptr->sustain_dex = TRUE;
1996 if (f2 & (TR2_SUST_CON)) p_ptr->sustain_con = TRUE;
1997 if (f2 & (TR2_SUST_CHR)) p_ptr->sustain_chr = TRUE;
2000 /*** Analyze equipment ***/
2002 /* Scan the equipment */
2003 for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
2005 o_ptr = &inventory[i];
2007 /* Skip non-objects */
2008 if (!o_ptr->k_idx) continue;
2010 /* Extract the item flags */
2011 object_flags(o_ptr, &f1, &f2, &f3);
2013 /* Affect stats */
2014 if (f1 & (TR1_STR)) p_ptr->stat_add[A_STR] += o_ptr->pval;
2015 if (f1 & (TR1_INT)) p_ptr->stat_add[A_INT] += o_ptr->pval;
2016 if (f1 & (TR1_WIS)) p_ptr->stat_add[A_WIS] += o_ptr->pval;
2017 if (f1 & (TR1_DEX)) p_ptr->stat_add[A_DEX] += o_ptr->pval;
2018 if (f1 & (TR1_CON)) p_ptr->stat_add[A_CON] += o_ptr->pval;
2019 if (f1 & (TR1_CHR)) p_ptr->stat_add[A_CHR] += o_ptr->pval;
2021 /* Affect stealth */
2022 if (f1 & (TR1_STEALTH)) p_ptr->skills[SKILL_STL] += o_ptr->pval;
2024 /* Affect searching ability (factor of five) */
2025 if (f1 & (TR1_SEARCH)) p_ptr->skills[SKILL_SRH] += (o_ptr->pval * 5);
2027 /* Affect searching frequency (factor of five) */
2028 if (f1 & (TR1_SEARCH)) p_ptr->skills[SKILL_FOS] += (o_ptr->pval * 5);
2030 /* Affect infravision */
2031 if (f1 & (TR1_INFRA)) p_ptr->see_infra += o_ptr->pval;
2033 /* Affect digging (factor of 20) */
2034 if (f1 & (TR1_TUNNEL)) p_ptr->skills[SKILL_DIG] += (o_ptr->pval * 20);
2036 /* Affect speed */
2037 if (f1 & (TR1_SPEED)) p_ptr->pspeed += o_ptr->pval;
2039 /* Affect blows */
2040 if (f1 & (TR1_BLOWS)) extra_blows += o_ptr->pval;
2042 /* Affect shots */
2043 if (f1 & (TR1_SHOTS)) extra_shots += o_ptr->pval;
2045 /* Affect Might */
2046 if (f1 & (TR1_MIGHT)) extra_might += o_ptr->pval;
2048 /* Good flags */
2049 if (f3 & (TR3_SLOW_DIGEST)) p_ptr->slow_digest = TRUE;
2050 if (f3 & (TR3_FEATHER)) p_ptr->ffall = TRUE;
2051 if (f3 & (TR3_REGEN)) p_ptr->regenerate = TRUE;
2052 if (f3 & (TR3_TELEPATHY)) p_ptr->telepathy = TRUE;
2053 if (f3 & (TR3_SEE_INVIS)) p_ptr->see_inv = TRUE;
2054 if (f3 & (TR3_FREE_ACT)) p_ptr->free_act = TRUE;
2055 if (f3 & (TR3_HOLD_LIFE)) p_ptr->hold_life = TRUE;
2057 /* Weird flags */
2058 if (f3 & (TR3_BLESSED)) p_ptr->bless_blade = TRUE;
2060 /* Bad flags */
2061 if (f3 & (TR3_IMPACT)) p_ptr->impact = TRUE;
2062 if (f3 & (TR3_AGGRAVATE)) p_ptr->aggravate = TRUE;
2063 if (f3 & (TR3_TELEPORT)) p_ptr->teleport = TRUE;
2064 if (f3 & (TR3_DRAIN_EXP)) p_ptr->exp_drain = TRUE;
2066 /* Immunity flags */
2067 if (f2 & (TR2_IM_FIRE)) p_ptr->immune_fire = TRUE;
2068 if (f2 & (TR2_IM_ACID)) p_ptr->immune_acid = TRUE;
2069 if (f2 & (TR2_IM_COLD)) p_ptr->immune_cold = TRUE;
2070 if (f2 & (TR2_IM_ELEC)) p_ptr->immune_elec = TRUE;
2072 /* Resistance flags */
2073 if (f2 & (TR2_RES_ACID)) p_ptr->resist_acid = TRUE;
2074 if (f2 & (TR2_RES_ELEC)) p_ptr->resist_elec = TRUE;
2075 if (f2 & (TR2_RES_FIRE)) p_ptr->resist_fire = TRUE;
2076 if (f2 & (TR2_RES_COLD)) p_ptr->resist_cold = TRUE;
2077 if (f2 & (TR2_RES_POIS)) p_ptr->resist_pois = TRUE;
2078 if (f2 & (TR2_RES_FEAR)) p_ptr->resist_fear = TRUE;
2079 if (f2 & (TR2_RES_LITE)) p_ptr->resist_lite = TRUE;
2080 if (f2 & (TR2_RES_DARK)) p_ptr->resist_dark = TRUE;
2081 if (f2 & (TR2_RES_BLIND)) p_ptr->resist_blind = TRUE;
2082 if (f2 & (TR2_RES_CONFU)) p_ptr->resist_confu = TRUE;
2083 if (f2 & (TR2_RES_SOUND)) p_ptr->resist_sound = TRUE;
2084 if (f2 & (TR2_RES_SHARD)) p_ptr->resist_shard = TRUE;
2085 if (f2 & (TR2_RES_NEXUS)) p_ptr->resist_nexus = TRUE;
2086 if (f2 & (TR2_RES_NETHR)) p_ptr->resist_nethr = TRUE;
2087 if (f2 & (TR2_RES_CHAOS)) p_ptr->resist_chaos = TRUE;
2088 if (f2 & (TR2_RES_DISEN)) p_ptr->resist_disen = TRUE;
2090 /* Sustain flags */
2091 if (f2 & (TR2_SUST_STR)) p_ptr->sustain_str = TRUE;
2092 if (f2 & (TR2_SUST_INT)) p_ptr->sustain_int = TRUE;
2093 if (f2 & (TR2_SUST_WIS)) p_ptr->sustain_wis = TRUE;
2094 if (f2 & (TR2_SUST_DEX)) p_ptr->sustain_dex = TRUE;
2095 if (f2 & (TR2_SUST_CON)) p_ptr->sustain_con = TRUE;
2096 if (f2 & (TR2_SUST_CHR)) p_ptr->sustain_chr = TRUE;
2098 /* Modify the base armor class */
2099 p_ptr->ac += o_ptr->ac;
2101 /* The base armor class is always known */
2102 p_ptr->dis_ac += o_ptr->ac;
2104 /* Apply the bonuses to armor class */
2105 p_ptr->to_a += o_ptr->to_a;
2107 /* Apply the mental bonuses to armor class, if known */
2108 if (object_known_p(o_ptr)) p_ptr->dis_to_a += o_ptr->to_a;
2110 /* Hack -- do not apply "weapon" bonuses */
2111 if (i == INVEN_WIELD) continue;
2113 /* Hack -- do not apply "bow" bonuses */
2114 if (i == INVEN_BOW) continue;
2116 /* Apply the bonuses to hit/damage */
2117 p_ptr->to_h += o_ptr->to_h;
2118 p_ptr->to_d += o_ptr->to_d;
2120 /* Apply the mental bonuses tp hit/damage, if known */
2121 if (object_known_p(o_ptr)) p_ptr->dis_to_h += o_ptr->to_h;
2122 if (object_known_p(o_ptr)) p_ptr->dis_to_d += o_ptr->to_d;
2126 /*** Handle stats ***/
2128 /* Calculate stats */
2129 for (i = 0; i < A_MAX; i++)
2131 int add, top, use, ind;
2133 /* Extract modifier */
2134 add = p_ptr->stat_add[i];
2136 /* Maximize mode */
2137 if (adult_maximize)
2139 /* Modify the stats for race/class */
2140 add += (rp_ptr->r_adj[i] + cp_ptr->c_adj[i]);
2143 /* Extract the new "stat_top" value for the stat */
2144 top = modify_stat_value(p_ptr->stat_max[i], add);
2146 /* Save the new value */
2147 p_ptr->stat_top[i] = top;
2149 /* Extract the new "stat_use" value for the stat */
2150 use = modify_stat_value(p_ptr->stat_cur[i], add);
2152 /* Save the new value */
2153 p_ptr->stat_use[i] = use;
2155 /* Values: 3, 4, ..., 17 */
2156 if (use <= 18) ind = (use - 3);
2158 /* Ranges: 18/00-18/09, ..., 18/210-18/219 */
2159 else if (use <= 18+219) ind = (15 + (use - 18) / 10);
2161 /* Range: 18/220+ */
2162 else ind = (37);
2164 /* Save the new index */
2165 p_ptr->stat_ind[i] = ind;
2169 /*** Temporary flags ***/
2171 /* Apply temporary "stun" */
2172 if (p_ptr->timed[TMD_STUN] > 50)
2174 p_ptr->to_h -= 20;
2175 p_ptr->dis_to_h -= 20;
2176 p_ptr->to_d -= 20;
2177 p_ptr->dis_to_d -= 20;
2179 else if (p_ptr->timed[TMD_STUN])
2181 p_ptr->to_h -= 5;
2182 p_ptr->dis_to_h -= 5;
2183 p_ptr->to_d -= 5;
2184 p_ptr->dis_to_d -= 5;
2187 /* Invulnerability */
2188 if (p_ptr->timed[TMD_INVULN])
2190 p_ptr->to_a += 100;
2191 p_ptr->dis_to_a += 100;
2194 /* Temporary blessing */
2195 if (p_ptr->timed[TMD_BLESSED])
2197 p_ptr->to_a += 5;
2198 p_ptr->dis_to_a += 5;
2199 p_ptr->to_h += 10;
2200 p_ptr->dis_to_h += 10;
2203 /* Temporary shield */
2204 if (p_ptr->timed[TMD_SHIELD])
2206 p_ptr->to_a += 50;
2207 p_ptr->dis_to_a += 50;
2210 /* Temporary "Hero" */
2211 if (p_ptr->timed[TMD_HERO])
2213 p_ptr->to_h += 12;
2214 p_ptr->dis_to_h += 12;
2217 /* Temporary "Berserk" */
2218 if (p_ptr->timed[TMD_SHERO])
2220 p_ptr->to_h += 24;
2221 p_ptr->dis_to_h += 24;
2222 p_ptr->to_a -= 10;
2223 p_ptr->dis_to_a -= 10;
2226 /* Temporary "fast" */
2227 if (p_ptr->timed[TMD_FAST])
2229 p_ptr->pspeed += 10;
2232 /* Temporary "slow" */
2233 if (p_ptr->timed[TMD_SLOW])
2235 p_ptr->pspeed -= 10;
2238 /* Temporary see invisible */
2239 if (p_ptr->timed[TMD_SINVIS])
2241 p_ptr->see_inv = TRUE;
2244 /* Temporary infravision boost */
2245 if (p_ptr->timed[TMD_SINFRA])
2247 p_ptr->see_infra += 5;
2251 /*** Special flags ***/
2253 /* Hack -- Hero/Shero -> Res fear */
2254 if (p_ptr->timed[TMD_HERO] || p_ptr->timed[TMD_SHERO])
2256 p_ptr->resist_fear = TRUE;
2260 /*** Analyze weight ***/
2262 /* Extract the current weight (in tenth pounds) */
2263 j = p_ptr->total_weight;
2265 /* Extract the "weight limit" (in tenth pounds) */
2266 i = weight_limit();
2268 /* Apply "encumbrance" from weight */
2269 if (j > i / 2) p_ptr->pspeed -= ((j - (i / 2)) / (i / 10));
2271 /* Bloating slows the player down (a little) */
2272 if (p_ptr->food >= PY_FOOD_MAX) p_ptr->pspeed -= 10;
2274 /* Searching slows the player down */
2275 if (p_ptr->searching) p_ptr->pspeed -= 10;
2277 /* Sanity check on extreme speeds */
2278 if (p_ptr->pspeed < 0) p_ptr->pspeed = 0;
2279 if (p_ptr->pspeed > 199) p_ptr->pspeed = 199;
2281 /*** Apply modifier bonuses ***/
2283 /* Actual Modifier Bonuses (Un-inflate stat bonuses) */
2284 p_ptr->to_a += ((int)(adj_dex_ta[p_ptr->stat_ind[A_DEX]]) - 128);
2285 p_ptr->to_d += ((int)(adj_str_td[p_ptr->stat_ind[A_STR]]) - 128);
2286 p_ptr->to_h += ((int)(adj_dex_th[p_ptr->stat_ind[A_DEX]]) - 128);
2287 p_ptr->to_h += ((int)(adj_str_th[p_ptr->stat_ind[A_STR]]) - 128);
2289 /* Displayed Modifier Bonuses (Un-inflate stat bonuses) */
2290 p_ptr->dis_to_a += ((int)(adj_dex_ta[p_ptr->stat_ind[A_DEX]]) - 128);
2291 p_ptr->dis_to_d += ((int)(adj_str_td[p_ptr->stat_ind[A_STR]]) - 128);
2292 p_ptr->dis_to_h += ((int)(adj_dex_th[p_ptr->stat_ind[A_DEX]]) - 128);
2293 p_ptr->dis_to_h += ((int)(adj_str_th[p_ptr->stat_ind[A_STR]]) - 128);
2296 /*** Modify skills ***/
2298 /* Affect Skill -- stealth (bonus one) */
2299 p_ptr->skills[SKILL_STL] += 1;
2301 /* Affect Skill -- disarming (DEX and INT) */
2302 p_ptr->skills[SKILL_DIS] += adj_dex_dis[p_ptr->stat_ind[A_DEX]];
2303 p_ptr->skills[SKILL_DIS] += adj_int_dis[p_ptr->stat_ind[A_INT]];
2305 /* Affect Skill -- magic devices (INT) */
2306 p_ptr->skills[SKILL_DEV] += adj_int_dev[p_ptr->stat_ind[A_INT]];
2308 /* Affect Skill -- saving throw (WIS) */
2309 p_ptr->skills[SKILL_SAV] += adj_wis_sav[p_ptr->stat_ind[A_WIS]];
2311 /* Affect Skill -- digging (STR) */
2312 p_ptr->skills[SKILL_DIG] += adj_str_dig[p_ptr->stat_ind[A_STR]];
2314 /* Affect Skill -- disarming (Level, by Class) */
2315 p_ptr->skills[SKILL_DIS] += (cp_ptr->x_dis * p_ptr->lev / 10);
2317 /* Affect Skill -- magic devices (Level, by Class) */
2318 p_ptr->skills[SKILL_DEV] += (cp_ptr->x_dev * p_ptr->lev / 10);
2320 /* Affect Skill -- saving throw (Level, by Class) */
2321 p_ptr->skills[SKILL_SAV] += (cp_ptr->x_sav * p_ptr->lev / 10);
2323 /* Affect Skill -- stealth (Level, by Class) */
2324 p_ptr->skills[SKILL_STL] += (cp_ptr->x_stl * p_ptr->lev / 10);
2326 /* Affect Skill -- search ability (Level, by Class) */
2327 p_ptr->skills[SKILL_SRH] += (cp_ptr->x_srh * p_ptr->lev / 10);
2329 /* Affect Skill -- search frequency (Level, by Class) */
2330 p_ptr->skills[SKILL_FOS] += (cp_ptr->x_fos * p_ptr->lev / 10);
2332 /* Affect Skill -- combat (normal) (Level, by Class) */
2333 p_ptr->skills[SKILL_THN] += (cp_ptr->x_thn * p_ptr->lev / 10);
2335 /* Affect Skill -- combat (shooting) (Level, by Class) */
2336 p_ptr->skills[SKILL_THB] += (cp_ptr->x_thb * p_ptr->lev / 10);
2338 /* Affect Skill -- combat (throwing) (Level, by Class) */
2339 p_ptr->skills[SKILL_THT] += (cp_ptr->x_thb * p_ptr->lev / 10);
2341 /* Limit Skill -- digging from 1 up */
2342 if (p_ptr->skills[SKILL_DIG] < 1) p_ptr->skills[SKILL_DIG] = 1;
2344 /* Limit Skill -- stealth from 0 to 30 */
2345 if (p_ptr->skills[SKILL_STL] > 30) p_ptr->skills[SKILL_STL] = 30;
2346 if (p_ptr->skills[SKILL_STL] < 0) p_ptr->skills[SKILL_STL] = 0;
2348 /* Apply Skill -- Extract noise from stealth */
2349 p_ptr->noise = (1L << (30 - p_ptr->skills[SKILL_STL]));
2351 /* Obtain the "hold" value */
2352 hold = adj_str_hold[p_ptr->stat_ind[A_STR]];
2355 /*** Analyze current bow ***/
2357 /* Examine the "current bow" */
2358 o_ptr = &inventory[INVEN_BOW];
2360 /* Assume not heavy */
2361 p_ptr->heavy_shoot = FALSE;
2363 /* It is hard to carholdry a heavy bow */
2364 if (hold < o_ptr->weight / 10)
2366 /* Hard to wield a heavy bow */
2367 p_ptr->to_h += 2 * (hold - o_ptr->weight / 10);
2368 p_ptr->dis_to_h += 2 * (hold - o_ptr->weight / 10);
2370 /* Heavy Bow */
2371 p_ptr->heavy_shoot = TRUE;
2374 /* Analyze launcher */
2375 if (o_ptr->k_idx)
2377 /* Get to shoot */
2378 p_ptr->num_fire = 1;
2380 /* Analyze the launcher */
2381 switch (o_ptr->sval)
2383 /* Sling and ammo */
2384 case SV_SLING:
2386 p_ptr->ammo_tval = TV_SHOT;
2387 p_ptr->ammo_mult = 2;
2388 break;
2391 /* Short Bow and Arrow */
2392 case SV_SHORT_BOW:
2394 p_ptr->ammo_tval = TV_ARROW;
2395 p_ptr->ammo_mult = 2;
2396 break;
2399 /* Long Bow and Arrow */
2400 case SV_LONG_BOW:
2402 p_ptr->ammo_tval = TV_ARROW;
2403 p_ptr->ammo_mult = 3;
2404 break;
2407 /* Light Crossbow and Bolt */
2408 case SV_LIGHT_XBOW:
2410 p_ptr->ammo_tval = TV_BOLT;
2411 p_ptr->ammo_mult = 3;
2412 break;
2415 /* Heavy Crossbow and Bolt */
2416 case SV_HEAVY_XBOW:
2418 p_ptr->ammo_tval = TV_BOLT;
2419 p_ptr->ammo_mult = 4;
2420 break;
2424 /* Apply special flags */
2425 if (o_ptr->k_idx && !p_ptr->heavy_shoot)
2427 /* Extra shots */
2428 p_ptr->num_fire += extra_shots;
2430 /* Extra might */
2431 p_ptr->ammo_mult += extra_might;
2433 /* Hack -- Rangers love Bows */
2434 if ((cp_ptr->flags & CF_EXTRA_SHOT) &&
2435 (p_ptr->ammo_tval == TV_ARROW))
2437 /* Extra shot at level 20 */
2438 if (p_ptr->lev >= 20) p_ptr->num_fire++;
2440 /* Extra shot at level 40 */
2441 if (p_ptr->lev >= 40) p_ptr->num_fire++;
2445 /* Require at least one shot */
2446 if (p_ptr->num_fire < 1) p_ptr->num_fire = 1;
2450 /*** Analyze weapon ***/
2452 /* Examine the "current weapon" */
2453 o_ptr = &inventory[INVEN_WIELD];
2455 /* Assume not heavy */
2456 p_ptr->heavy_wield = FALSE;
2458 /* It is hard to hold a heavy weapon */
2459 if (hold < o_ptr->weight / 10)
2461 /* Hard to wield a heavy weapon */
2462 p_ptr->to_h += 2 * (hold - o_ptr->weight / 10);
2463 p_ptr->dis_to_h += 2 * (hold - o_ptr->weight / 10);
2465 /* Heavy weapon */
2466 p_ptr->heavy_wield = TRUE;
2469 /* Normal weapons */
2470 if (o_ptr->k_idx && !p_ptr->heavy_wield)
2472 int str_index, dex_index;
2474 int div;
2476 /* Enforce a minimum "weight" (tenth pounds) */
2477 div = ((o_ptr->weight < cp_ptr->min_weight) ? cp_ptr->min_weight : o_ptr->weight);
2479 /* Get the strength vs weight */
2480 str_index = (adj_str_blow[p_ptr->stat_ind[A_STR]] * cp_ptr->att_multiply / div);
2482 /* Maximal value */
2483 if (str_index > 11) str_index = 11;
2485 /* Index by dexterity */
2486 dex_index = (adj_dex_blow[p_ptr->stat_ind[A_DEX]]);
2488 /* Maximal value */
2489 if (dex_index > 11) dex_index = 11;
2491 /* Use the blows table */
2492 p_ptr->num_blow = blows_table[str_index][dex_index];
2494 /* Maximal value */
2495 if (p_ptr->num_blow > cp_ptr->max_attacks) p_ptr->num_blow = cp_ptr->max_attacks;
2497 /* Add in the "bonus blows" */
2498 p_ptr->num_blow += extra_blows;
2500 /* Require at least one blow */
2501 if (p_ptr->num_blow < 1) p_ptr->num_blow = 1;
2503 /* Boost digging skill by weapon weight */
2504 p_ptr->skills[SKILL_DIG] += (o_ptr->weight / 10);
2507 /* Assume okay */
2508 p_ptr->icky_wield = FALSE;
2510 /* Priest weapon penalty for non-blessed edged weapons */
2511 if ((cp_ptr->flags & CF_BLESS_WEAPON) && (!p_ptr->bless_blade) &&
2512 ((o_ptr->tval == TV_SWORD) || (o_ptr->tval == TV_POLEARM)))
2514 /* Reduce the real bonuses */
2515 p_ptr->to_h -= 2;
2516 p_ptr->to_d -= 2;
2518 /* Reduce the mental bonuses */
2519 p_ptr->dis_to_h -= 2;
2520 p_ptr->dis_to_d -= 2;
2522 /* Icky weapon */
2523 p_ptr->icky_wield = TRUE;
2527 /*** Notice changes ***/
2529 /* Analyze stats */
2530 for (i = 0; i < A_MAX; i++)
2532 /* Notice changes */
2533 if (p_ptr->stat_top[i] != old_stat_top[i])
2535 /* Redisplay the stats later */
2536 p_ptr->redraw |= (PR_STATS);
2538 /* Window stuff */
2539 p_ptr->window |= (PW_PLAYER_0 | PW_PLAYER_1);
2542 /* Notice changes */
2543 if (p_ptr->stat_use[i] != old_stat_use[i])
2545 /* Redisplay the stats later */
2546 p_ptr->redraw |= (PR_STATS);
2548 /* Window stuff */
2549 p_ptr->window |= (PW_PLAYER_0 | PW_PLAYER_1);
2552 /* Notice changes */
2553 if (p_ptr->stat_ind[i] != old_stat_ind[i])
2555 /* Change in CON affects Hitpoints */
2556 if (i == A_CON)
2558 p_ptr->update |= (PU_HP);
2561 /* Change in INT may affect Mana/Spells */
2562 else if (i == A_INT)
2564 if (cp_ptr->spell_stat == A_INT)
2566 p_ptr->update |= (PU_MANA | PU_SPELLS);
2570 /* Change in WIS may affect Mana/Spells */
2571 else if (i == A_WIS)
2573 if (cp_ptr->spell_stat == A_WIS)
2575 p_ptr->update |= (PU_MANA | PU_SPELLS);
2581 /* Hack -- Telepathy Change */
2582 if (p_ptr->telepathy != old_telepathy)
2584 /* Update monster visibility */
2585 p_ptr->update |= (PU_MONSTERS);
2588 /* Hack -- See Invis Change */
2589 if (p_ptr->see_inv != old_see_inv)
2591 /* Update monster visibility */
2592 p_ptr->update |= (PU_MONSTERS);
2595 /* Redraw speed (if needed) */
2596 if (p_ptr->pspeed != old_speed)
2598 /* Redraw speed */
2599 p_ptr->redraw |= (PR_SPEED);
2602 /* Redraw armor (if needed) */
2603 if ((p_ptr->dis_ac != old_dis_ac) || (p_ptr->dis_to_a != old_dis_to_a))
2605 /* Redraw */
2606 p_ptr->redraw |= (PR_ARMOR);
2608 /* Window stuff */
2609 p_ptr->window |= (PW_PLAYER_0 | PW_PLAYER_1);
2612 /* Hack -- handle "xtra" mode */
2613 if (character_xtra) return;
2615 /* Take note when "heavy bow" changes */
2616 if (old_heavy_shoot != p_ptr->heavy_shoot)
2618 /* Message */
2619 if (p_ptr->heavy_shoot)
2621 msg_print("You have trouble wielding such a heavy bow.");
2623 else if (inventory[INVEN_BOW].k_idx)
2625 msg_print("You have no trouble wielding your bow.");
2627 else
2629 msg_print("You feel relieved to put down your heavy bow.");
2633 /* Take note when "heavy weapon" changes */
2634 if (old_heavy_wield != p_ptr->heavy_wield)
2636 /* Message */
2637 if (p_ptr->heavy_wield)
2639 msg_print("You have trouble wielding such a heavy weapon.");
2641 else if (inventory[INVEN_WIELD].k_idx)
2643 msg_print("You have no trouble wielding your weapon.");
2645 else
2647 msg_print("You feel relieved to put down your heavy weapon.");
2651 /* Take note when "illegal weapon" changes */
2652 if (old_icky_wield != p_ptr->icky_wield)
2654 /* Message */
2655 if (p_ptr->icky_wield)
2657 msg_print("You do not feel comfortable with your weapon.");
2659 else if (inventory[INVEN_WIELD].k_idx)
2661 msg_print("You feel comfortable with your weapon.");
2663 else
2665 msg_print("You feel more comfortable after removing your weapon.");
2673 /*** Generic "deal with" functions ***/
2676 * Handle "p_ptr->notice"
2678 void notice_stuff(void)
2680 /* Notice stuff */
2681 if (!p_ptr->notice) return;
2684 /* Deal with autoinscribe stuff */
2685 if (p_ptr->notice & PN_AUTOINSCRIBE)
2687 p_ptr->notice &= ~(PN_AUTOINSCRIBE);
2688 autoinscribe_pack();
2689 autoinscribe_ground();
2692 /* Deal with squelch stuff */
2693 if (p_ptr->notice & PN_SQUELCH)
2695 p_ptr->notice &= ~(PN_SQUELCH);
2696 if (hide_squelchable) squelch_drop();
2699 /* Combine the pack */
2700 if (p_ptr->notice & PN_COMBINE)
2702 p_ptr->notice &= ~(PN_COMBINE);
2703 combine_pack();
2706 /* Reorder the pack */
2707 if (p_ptr->notice & PN_REORDER)
2709 p_ptr->notice &= ~(PN_REORDER);
2710 reorder_pack();
2715 * Handle "p_ptr->update"
2717 void update_stuff(void)
2719 /* Update stuff */
2720 if (!p_ptr->update) return;
2723 if (p_ptr->update & (PU_BONUS))
2725 p_ptr->update &= ~(PU_BONUS);
2726 calc_bonuses();
2729 if (p_ptr->update & (PU_TORCH))
2731 p_ptr->update &= ~(PU_TORCH);
2732 calc_torch();
2735 if (p_ptr->update & (PU_HP))
2737 p_ptr->update &= ~(PU_HP);
2738 calc_hitpoints();
2741 if (p_ptr->update & (PU_MANA))
2743 p_ptr->update &= ~(PU_MANA);
2744 calc_mana();
2747 if (p_ptr->update & (PU_SPELLS))
2749 p_ptr->update &= ~(PU_SPELLS);
2750 calc_spells();
2754 /* Character is not ready yet, no screen updates */
2755 if (!character_generated) return;
2758 /* Character is in "icky" mode, no screen updates */
2759 if (character_icky) return;
2762 if (p_ptr->update & (PU_FORGET_VIEW))
2764 p_ptr->update &= ~(PU_FORGET_VIEW);
2765 forget_view();
2768 if (p_ptr->update & (PU_UPDATE_VIEW))
2770 p_ptr->update &= ~(PU_UPDATE_VIEW);
2771 update_view();
2775 if (p_ptr->update & (PU_FORGET_FLOW))
2777 p_ptr->update &= ~(PU_FORGET_FLOW);
2778 forget_flow();
2781 if (p_ptr->update & (PU_UPDATE_FLOW))
2783 p_ptr->update &= ~(PU_UPDATE_FLOW);
2784 update_flow();
2788 if (p_ptr->update & (PU_DISTANCE))
2790 p_ptr->update &= ~(PU_DISTANCE);
2791 p_ptr->update &= ~(PU_MONSTERS);
2792 update_monsters(TRUE);
2795 if (p_ptr->update & (PU_MONSTERS))
2797 p_ptr->update &= ~(PU_MONSTERS);
2798 update_monsters(FALSE);
2802 if (p_ptr->update & (PU_PANEL))
2804 p_ptr->update &= ~(PU_PANEL);
2805 verify_panel();
2811 * Handle "p_ptr->redraw"
2813 void redraw_stuff(void)
2815 /* Redraw stuff */
2816 if (!p_ptr->redraw) return;
2819 /* Character is not ready yet, no screen updates */
2820 if (!character_generated) return;
2823 /* Character is in "icky" mode, no screen updates */
2824 if (character_icky) return;
2827 /* HACK - Redraw window "Display player (compact)" if necessary */
2828 if (p_ptr->redraw & (PR_MISC | PR_TITLE | PR_LEV | PR_EXP |
2829 PR_STATS | PR_ARMOR | PR_HP | PR_MANA |
2830 PR_GOLD | PR_HEALTH | PR_EQUIPPY | PR_CUT |
2831 PR_STUN))
2833 p_ptr->window |= PW_PLAYER_2;
2836 /* HACK - Redraw window "Display status" if necessary */
2837 if (p_ptr->redraw & (PR_HUNGER | PR_BLIND | PR_CONFUSED | PR_AFRAID |
2838 PR_POISONED | PR_STATE | PR_SPEED | PR_STUDY |
2839 PR_DEPTH))
2841 p_ptr->window |= PW_STATUS;
2844 if (p_ptr->redraw & (PR_MAP))
2846 p_ptr->redraw &= ~(PR_MAP);
2847 prt_map();
2850 if (p_ptr->redraw & (PR_HP))
2853 * hack: redraw player, since the player's color
2854 * now indicates approximate health. Note that
2855 * using this command when graphics mode is on
2856 * causes the character to be a black square.
2858 if ((hp_changes_color) && (arg_graphics == GRAPHICS_NONE))
2860 lite_spot(p_ptr->py, p_ptr->px);
2864 /* Redraw the sidebar */
2865 display_sidebar();
2867 /* Redraw the status line */
2868 display_statusline();
2870 return;
2875 * Handle "p_ptr->update" and "p_ptr->redraw" and "p_ptr->window"
2877 void handle_stuff(void)
2879 /* Update stuff */
2880 if (p_ptr->update) update_stuff();
2882 /* Redraw stuff */
2883 if (p_ptr->redraw) redraw_stuff();
2885 /* Window stuff */
2886 if (p_ptr->window) window_stuff();