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.
17 * Converts stat num into a six-char (right justified) string
19 void cnv_stat(int val
, char *out_val
, size_t out_len
)
24 int bonus
= (val
- 18);
27 strnfmt(out_val
, out_len
, "18/%03d", bonus
);
29 strnfmt(out_val
, out_len
, " 18/%02d", bonus
);
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
)
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 */
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 */
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
)
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 */
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
)
152 else if (p_ptr
->total_winner
|| (p_ptr
->lev
> PY_MAX_LEVEL
))
160 p
= c_text
+ cp_ptr
->title
[(p_ptr
->lev
- 1) / 5];
163 prt_field(p
, row
, col
);
170 static void prt_level(int row
, int col
)
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);
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
)
195 bool lev50
= (p_ptr
->lev
== 50);
197 long xp
= (long)p_ptr
->exp
;
200 /* Calculate XP for next level */
202 xp
= (long)(player_exp
[p_ptr
->lev
- 1] * p_ptr
->expfact
/ 100L) - p_ptr
->exp
;
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);
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
)
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);
237 static void prt_equippy(int row
, int col
)
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
++)
253 o_ptr
= &inventory
[i
];
255 a
= object_attr(o_ptr
);
256 c
= object_char(o_ptr
);
258 /* Clear the part of the screen */
266 Term_putch(col
+ i
- INVEN_WIELD
, row
, a
, c
);
274 static void prt_ac(int row
, int col
)
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];
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)
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];
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)
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
)
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 */
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
;
394 if (pct
>= 10) attr
= TERM_L_RED
;
397 if (pct
>= 25) attr
= TERM_ORANGE
;
399 /* Somewhat Wounded */
400 if (pct
>= 60) attr
= TERM_YELLOW
;
403 if (pct
>= 100) attr
= TERM_L_GREEN
;
406 if (m_ptr
->monfear
) attr
= TERM_VIOLET
;
409 if (m_ptr
->confused
) attr
= TERM_UMBER
;
412 if (m_ptr
->stunned
) attr
= TERM_L_BLUE
;
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
];
438 c_put_str(TERM_L_RED
, "Mortal wound", row
, col
);
442 c_put_str(TERM_RED
, "Deep gash ", row
, col
);
446 c_put_str(TERM_RED
, "Severe cut ", row
, col
);
450 c_put_str(TERM_ORANGE
, "Nasty cut ", row
, col
);
454 c_put_str(TERM_ORANGE
, "Bad cut ", row
, col
);
458 c_put_str(TERM_YELLOW
, "Light cut ", row
, col
);
462 c_put_str(TERM_YELLOW
, "Graze ", row
, col
);
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
];
480 c_put_str(TERM_RED
, "Knocked out ", row
, col
);
484 c_put_str(TERM_ORANGE
, "Heavy stun ", row
, col
);
488 c_put_str(TERM_ORANGE
, "Stun ", row
, col
);
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 */
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
},
534 { prt_ac
, 7, PR_ARMOR
},
535 { prt_hp
, 8, PR_HP
},
536 { prt_sp
, 9, PR_MANA
},
538 { prt_health
, 12, PR_HEALTH
},
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)
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 */
584 /* Increment for next time */
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
)
607 my_strcpy(depths
, "Town", sizeof(depths
));
609 else if (depth_in_feet
)
611 strnfmt(depths
, sizeof(depths
), "%d ft", p_ptr
->depth
* 50);
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
);
635 else if (p_ptr
->food
< PY_FOOD_WEAK
)
637 c_put_str(TERM_ORANGE
, "Weak ", row
, col
);
641 else if (p_ptr
->food
< PY_FOOD_ALERT
)
643 c_put_str(TERM_YELLOW
, "Hungry", row
, col
);
647 else if (p_ptr
->food
< PY_FOOD_FULL
)
649 c_put_str(TERM_L_GREEN
, " ", row
, col
);
653 else if (p_ptr
->food
< PY_FOOD_MAX
)
655 c_put_str(TERM_L_GREEN
, "Full ", row
, col
);
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
);
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
)
694 else if (confused
&& forget
)
696 else if (!confused
&& forget
)
699 c_put_str(TERM_ORANGE
, text
, row
, col
);
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
);
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
);
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
;
750 if (p_ptr
->timed
[TMD_PARALYZED
])
754 my_strcpy(text
, "Paralyzed!", sizeof(text
));
758 else if (p_ptr
->resting
)
761 int n
= p_ptr
->resting
;
763 /* Start with "Rest" */
764 my_strcpy(text
, "Rest ", sizeof(text
));
766 /* Extensive (timed) rest */
772 text
[7] = I2D(i
% 10);
776 text
[6] = I2D(i
% 10);
779 text
[5] = I2D(i
/ 10);
784 /* Long (timed) rest */
788 text
[9] = I2D(i
% 10);
790 text
[8] = I2D(i
% 10);
791 text
[7] = I2D(i
/ 10);
794 /* Medium (timed) rest */
798 text
[9] = I2D(i
% 10);
799 text
[8] = I2D(i
/ 10);
802 /* Short (timed) rest */
809 /* Rest until healed */
812 text
[5] = text
[6] = text
[7] = text
[8] = text
[9] = '*';
815 /* Rest until done */
818 text
[5] = text
[6] = text
[7] = text
[8] = text
[9] = '&';
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);
828 strnfmt(text
, sizeof(text
), "Repeat %3d", p_ptr
->command_rep
);
832 else if (p_ptr
->searching
)
834 my_strcpy(text
, "Searching ", sizeof(text
));
837 /* Nothing interesting */
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
;
859 /* Hack -- Visually "undo" the Search Mode Slowdown */
860 if (p_ptr
->searching
) i
+= 10;
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
);
895 put_str(" ", row
, col
);
900 static void prt_elements(int row
, int col
)
904 /* Number of resists to display */
907 /* XXX Ignore column setting */
909 wid
= Term
->wid
- col
;
911 /* Print up to 5 letters of the resist */
912 n
= MIN(wid
/ count
, 5);
919 if (p_ptr
->timed
[TMD_OPP_ACID
])
920 Term_putstr(col
, row
, n
, TERM_SLATE
, "Acid ");
922 Term_putstr(col
, row
, n
, TERM_SLATE
, " ");
926 if (p_ptr
->timed
[TMD_OPP_ELEC
])
927 Term_putstr(col
, row
, n
, TERM_BLUE
, "Elec ");
929 Term_putstr(col
, row
, n
, TERM_BLUE
, " ");
933 if (p_ptr
->timed
[TMD_OPP_FIRE
])
934 Term_putstr(col
, row
, n
, TERM_RED
, "Fire ");
936 Term_putstr(col
, row
, n
, TERM_RED
, " ");
940 if (p_ptr
->timed
[TMD_OPP_COLD
])
941 Term_putstr(col
, row
, n
, TERM_WHITE
, "Cold ");
943 Term_putstr(col
, row
, n
, TERM_WHITE
, " ");
947 if (p_ptr
->timed
[TMD_OPP_POIS
])
948 Term_putstr(col
, row
, n
, TERM_GREEN
, "Pois ");
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;
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
);
1005 /*** Subwindow display functions ***/
1008 * Hack -- display player in sub-windows (mode 0)
1010 static void fix_player_0(void)
1012 /* Display player */
1018 * Hack -- display player in sub-windows (mode 1)
1020 static void fix_player_1(void)
1028 * Hack - Display the left-hand-side of the main term in a separate window
1030 static void fix_frame_compact(void)
1036 /* Race and Class */
1037 prt_field(p_name
+ rp_ptr
->name
, row
++, col
);
1038 prt_field(c_name
+ cp_ptr
->name
, row
++, col
);
1041 prt_title(row
++, col
);
1043 /* Level/Experience */
1044 prt_level(row
++, col
);
1045 prt_exp(row
++, col
);
1048 prt_gold(row
++, col
);
1051 prt_equippy(row
++, col
);
1054 for (i
= 0; i
< A_MAX
; i
++) prt_stat(i
, row
++, col
);
1068 /* Monster health */
1069 prt_health(row
++, col
);
1072 prt_cut(row
++, col
);
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)
1091 Term_get_size(&w
, &h
);
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
));
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
1118 * The "display_map()" function handles NULL arguments in a special manner.
1120 static void fix_overhead(void)
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)
1157 for (i
= 0; i
< N_ELEMENTS(status_handlers
) - 1; i
++)
1159 status_handlers
[i
].hook(row
, 0);
1168 * Struct of subwindow display handlers.
1170 static const struct win_handler_t
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
},
1182 { PW_MAP
, fix_map
}, /* The maps are always up-to-date */
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)
1203 if (!p_ptr
->window
) return;
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
);
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
++)
1234 if (!angband_term
[j
]) continue;
1236 /* No relevant flags */
1237 if (!(op_ptr
->window_flag
[j
] & hnd
->flag
)) continue;
1240 Term_activate(angband_term
[j
]);
1245 /* Forget the flag */
1246 p_ptr
->window
&= ~(hnd
->flag
);
1249 /* Restore old terminal */
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
;
1271 const magic_type
*s_ptr
;
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 */
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
)
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
--)
1325 j
= p_ptr
->spell_order
[i
];
1327 /* Skip non-spells */
1328 if (j
>= 99) continue;
1331 s_ptr
= &mp_ptr
->info
[j
];
1333 /* Skip spells we are allowed to know */
1334 if (s_ptr
->slevel
<= p_ptr
->lev
) continue;
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
;
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
;
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 */
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
;
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 */
1426 /* Count spells that can be learned */
1427 for (j
= 0; j
< PY_MAX_SPELLS
; j
++)
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
)
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
)
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
;
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 */
1500 /* Process gloves for those disturbed by them */
1501 if (cp_ptr
->flags
& CF_CUMBER_GLOVE
)
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 */
1516 !(f3
& (TR3_FREE_ACT
)) &&
1517 !((f1
& (TR1_DEX
)) && (o_ptr
->pval
> 0)))
1520 p_ptr
->cumber_glove
= TRUE
;
1523 msp
= (3 * msp
) / 4;
1528 /* Assume player not encumbered by armor */
1529 p_ptr
->cumber_armor
= FALSE
;
1531 /* Weigh the armor */
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)
1547 p_ptr
->cumber_armor
= TRUE
;
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 */
1564 /* Enforce new limit */
1565 if (p_ptr
->csp
>= msp
)
1568 p_ptr
->csp_frac
= 0;
1571 /* Display mana later */
1572 p_ptr
->redraw
|= (PR_MANA
);
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
)
1586 if (p_ptr
->cumber_glove
)
1588 msg_print("Your covered hands feel unsuitable for spellcasting.");
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
)
1601 if (p_ptr
->cumber_armor
)
1603 msg_print("The weight of your armor encumbers your movement.");
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)
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 */
1638 /* Enforce new limit */
1639 if (p_ptr
->chp
>= mhp
)
1642 p_ptr
->chp_frac
= 0;
1645 /* Display hitpoints (later) */
1646 p_ptr
->redraw
|= (PR_HP
);
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
1660 * Note that a cursed light source no longer emits light.
1662 static void calc_torch(void)
1666 s16b old_lite
= p_ptr
->cur_lite
;
1667 bool burn_light
= TRUE
;
1674 /* Ascertain lightness if in the town */
1675 if (!p_ptr
->depth
&& ((turn
% (10L * TOWN_DAWN
)) < ((10L * TOWN_DAWN
) / 2)))
1679 /* Examine all wielded objects, use the brightest */
1680 for (i
= INVEN_WIELD
; i
< INVEN_TOTAL
; i
++)
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
)
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
))
1708 /* Non-artifact lights and those without fuel provide no light */
1709 else if (!burn_light
|| o_ptr
->timeout
== 0)
1712 /* All lit lights provide at least radius 2 light */
1717 /* Torches below half fuel provide less light */
1718 if (o_ptr
->sval
== SV_LITE_TORCH
&& o_ptr
->timeout
< (FUEL_TORCH
/ 4))
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 */
1734 /* Add bonus from LITE flags */
1735 new_lite
+= extra_lite
;
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)
1758 /* Weight limit based only on strength */
1759 i
= adj_str_wgt
[p_ptr
->stat_ind
[A_STR
]] * 100;
1761 /* Return the result */
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)
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
;
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
;
1843 /* Reset player speed */
1844 p_ptr
->pspeed
= 110;
1846 /* Reset "blow" info */
1847 p_ptr
->num_blow
= 1;
1850 /* Reset "fire" info */
1851 p_ptr
->num_fire
= 0;
1852 p_ptr
->ammo_mult
= 0;
1853 p_ptr
->ammo_tval
= 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
);
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
;
1959 if (f3
& (TR3_BLESSED
)) p_ptr
->bless_blade
= TRUE
;
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
;
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
);
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);
2037 if (f1
& (TR1_SPEED
)) p_ptr
->pspeed
+= o_ptr
->pval
;
2040 if (f1
& (TR1_BLOWS
)) extra_blows
+= o_ptr
->pval
;
2043 if (f1
& (TR1_SHOTS
)) extra_shots
+= o_ptr
->pval
;
2046 if (f1
& (TR1_MIGHT
)) extra_might
+= o_ptr
->pval
;
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
;
2058 if (f3
& (TR3_BLESSED
)) p_ptr
->bless_blade
= TRUE
;
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
;
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
];
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+ */
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)
2175 p_ptr
->dis_to_h
-= 20;
2177 p_ptr
->dis_to_d
-= 20;
2179 else if (p_ptr
->timed
[TMD_STUN
])
2182 p_ptr
->dis_to_h
-= 5;
2184 p_ptr
->dis_to_d
-= 5;
2187 /* Invulnerability */
2188 if (p_ptr
->timed
[TMD_INVULN
])
2191 p_ptr
->dis_to_a
+= 100;
2194 /* Temporary blessing */
2195 if (p_ptr
->timed
[TMD_BLESSED
])
2198 p_ptr
->dis_to_a
+= 5;
2200 p_ptr
->dis_to_h
+= 10;
2203 /* Temporary shield */
2204 if (p_ptr
->timed
[TMD_SHIELD
])
2207 p_ptr
->dis_to_a
+= 50;
2210 /* Temporary "Hero" */
2211 if (p_ptr
->timed
[TMD_HERO
])
2214 p_ptr
->dis_to_h
+= 12;
2217 /* Temporary "Berserk" */
2218 if (p_ptr
->timed
[TMD_SHERO
])
2221 p_ptr
->dis_to_h
+= 24;
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) */
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);
2371 p_ptr
->heavy_shoot
= TRUE
;
2374 /* Analyze launcher */
2378 p_ptr
->num_fire
= 1;
2380 /* Analyze the launcher */
2381 switch (o_ptr
->sval
)
2383 /* Sling and ammo */
2386 p_ptr
->ammo_tval
= TV_SHOT
;
2387 p_ptr
->ammo_mult
= 2;
2391 /* Short Bow and Arrow */
2394 p_ptr
->ammo_tval
= TV_ARROW
;
2395 p_ptr
->ammo_mult
= 2;
2399 /* Long Bow and Arrow */
2402 p_ptr
->ammo_tval
= TV_ARROW
;
2403 p_ptr
->ammo_mult
= 3;
2407 /* Light Crossbow and Bolt */
2410 p_ptr
->ammo_tval
= TV_BOLT
;
2411 p_ptr
->ammo_mult
= 3;
2415 /* Heavy Crossbow and Bolt */
2418 p_ptr
->ammo_tval
= TV_BOLT
;
2419 p_ptr
->ammo_mult
= 4;
2424 /* Apply special flags */
2425 if (o_ptr
->k_idx
&& !p_ptr
->heavy_shoot
)
2428 p_ptr
->num_fire
+= extra_shots
;
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);
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
;
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
);
2483 if (str_index
> 11) str_index
= 11;
2485 /* Index by dexterity */
2486 dex_index
= (adj_dex_blow
[p_ptr
->stat_ind
[A_DEX
]]);
2489 if (dex_index
> 11) dex_index
= 11;
2491 /* Use the blows table */
2492 p_ptr
->num_blow
= blows_table
[str_index
][dex_index
];
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);
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 */
2518 /* Reduce the mental bonuses */
2519 p_ptr
->dis_to_h
-= 2;
2520 p_ptr
->dis_to_d
-= 2;
2523 p_ptr
->icky_wield
= TRUE
;
2527 /*** Notice changes ***/
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
);
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
);
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 */
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
)
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
))
2606 p_ptr
->redraw
|= (PR_ARMOR
);
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
)
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.");
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
)
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.");
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
)
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.");
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)
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
);
2706 /* Reorder the pack */
2707 if (p_ptr
->notice
& PN_REORDER
)
2709 p_ptr
->notice
&= ~(PN_REORDER
);
2715 * Handle "p_ptr->update"
2717 void update_stuff(void)
2720 if (!p_ptr
->update
) return;
2723 if (p_ptr
->update
& (PU_BONUS
))
2725 p_ptr
->update
&= ~(PU_BONUS
);
2729 if (p_ptr
->update
& (PU_TORCH
))
2731 p_ptr
->update
&= ~(PU_TORCH
);
2735 if (p_ptr
->update
& (PU_HP
))
2737 p_ptr
->update
&= ~(PU_HP
);
2741 if (p_ptr
->update
& (PU_MANA
))
2743 p_ptr
->update
&= ~(PU_MANA
);
2747 if (p_ptr
->update
& (PU_SPELLS
))
2749 p_ptr
->update
&= ~(PU_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
);
2768 if (p_ptr
->update
& (PU_UPDATE_VIEW
))
2770 p_ptr
->update
&= ~(PU_UPDATE_VIEW
);
2775 if (p_ptr
->update
& (PU_FORGET_FLOW
))
2777 p_ptr
->update
&= ~(PU_FORGET_FLOW
);
2781 if (p_ptr
->update
& (PU_UPDATE_FLOW
))
2783 p_ptr
->update
&= ~(PU_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
);
2811 * Handle "p_ptr->redraw"
2813 void redraw_stuff(void)
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
|
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
|
2841 p_ptr
->window
|= PW_STATUS
;
2844 if (p_ptr
->redraw
& (PR_MAP
))
2846 p_ptr
->redraw
&= ~(PR_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 */
2867 /* Redraw the status line */
2868 display_statusline();
2875 * Handle "p_ptr->update" and "p_ptr->redraw" and "p_ptr->window"
2877 void handle_stuff(void)
2880 if (p_ptr
->update
) update_stuff();
2883 if (p_ptr
->redraw
) redraw_stuff();
2886 if (p_ptr
->window
) window_stuff();