Angband 3.0.9b.
[angband.git] / src / cmd6.c
blobceeb7df4c7e417fdaef79bd9aad69ee2834b3c13
1 /* File: cmd6.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"
13 #include "script.h"
17 * This file includes code for eating food, drinking potions,
18 * reading scrolls, aiming wands, using staffs, zapping rods,
19 * and activating artifacts.
21 * In all cases, if the player becomes "aware" of the item's use
22 * by testing it, mark it as "aware" and reward some experience
23 * based on the object's level, always rounding up. If the player
24 * remains "unaware", mark that object "kind" as "tried".
26 * This code now correctly handles the unstacking of wands, staffs,
27 * and rods. Note the overly paranoid warning about potential pack
28 * overflow, which allows the player to use and drop a stacked item.
30 * In all "unstacking" scenarios, the "used" object is "carried" as if
31 * the player had just picked it up. In particular, this means that if
32 * the use of an item induces pack overflow, that item will be dropped.
34 * For simplicity, these routines induce a full "pack reorganization"
35 * which not only combines similar items, but also reorganizes various
36 * items to obey the current "sorting" method. This may require about
37 * 400 item comparisons, but only occasionally.
39 * There may be a BIG problem with any "effect" that can cause "changes"
40 * to the inventory. For example, a "scroll of recharging" can cause
41 * a wand/staff to "disappear", moving the inventory up. Luckily, the
42 * scrolls all appear BEFORE the staffs/wands, so this is not a problem.
43 * But, for example, a "staff of recharging" could cause MAJOR problems.
44 * In such a case, it will be best to either (1) "postpone" the effect
45 * until the end of the function, or (2) "change" the effect, say, into
46 * giving a staff "negative" charges, or "turning a staff into a stick".
47 * It seems as though a "rod of recharging" might in fact cause problems.
48 * The basic problem is that the act of recharging (and destroying) an
49 * item causes the inducer of that action to "move", causing "o_ptr" to
50 * no longer point at the correct item, with horrifying results.
52 * Note that food/potions/scrolls no longer use bit-flags for effects,
53 * but instead use the "sval" (which is also used to sort the objects).
62 * Eat some food (from the pack or floor)
64 void do_cmd_eat_food(void)
66 int item, lev;
67 bool ident;
69 object_type *o_ptr;
71 cptr q, s;
74 /* Restrict choices to food */
75 item_tester_tval = TV_FOOD;
77 /* Get an item */
78 q = "Eat which item? ";
79 s = "You have nothing to eat.";
80 if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
82 /* Get the item (in the pack) */
83 if (item >= 0)
85 o_ptr = &inventory[item];
88 /* Get the item (on the floor) */
89 else
91 o_ptr = &o_list[0 - item];
95 /* Sound */
96 sound(MSG_EAT);
99 /* Take a turn */
100 p_ptr->energy_use = 100;
102 /* Identity not known yet */
103 ident = FALSE;
105 /* Object level */
106 lev = k_info[o_ptr->k_idx].level;
108 /* Eat the food */
109 use_object(o_ptr, &ident);
111 /* Combine / Reorder the pack (later) */
112 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
114 /* We have tried it */
115 object_tried(o_ptr);
117 /* The player is now aware of the object */
118 if (ident && !object_aware_p(o_ptr))
120 object_aware(o_ptr);
121 gain_exp((lev + (p_ptr->lev / 2)) / p_ptr->lev);
122 p_ptr->notice |= PN_SQUELCH;
125 /* Window stuff */
126 p_ptr->window |= (PW_INVEN | PW_EQUIP);
129 /* Destroy a food in the pack */
130 if (item >= 0)
132 inven_item_increase(item, -1);
133 inven_item_describe(item);
134 inven_item_optimize(item);
137 /* Destroy a food on the floor */
138 else
140 floor_item_increase(0 - item, -1);
141 floor_item_describe(0 - item);
142 floor_item_optimize(0 - item);
150 * Quaff a potion (from the pack or the floor)
152 void do_cmd_quaff_potion(void)
154 int item, lev;
155 bool ident;
156 object_type *o_ptr;
157 cptr q, s;
160 /* Restrict choices to potions */
161 item_tester_tval = TV_POTION;
163 /* Get an item */
164 q = "Quaff which potion? ";
165 s = "You have no potions to quaff.";
166 if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
168 /* Get the item (in the pack) */
169 if (item >= 0)
171 o_ptr = &inventory[item];
174 /* Get the item (on the floor) */
175 else
177 o_ptr = &o_list[0 - item];
181 /* Sound */
182 sound(MSG_QUAFF);
185 /* Take a turn */
186 p_ptr->energy_use = 100;
188 /* Not identified yet */
189 ident = FALSE;
191 /* Object level */
192 lev = k_info[o_ptr->k_idx].level;
194 /* Quaff the potion */
195 use_object(o_ptr, &ident);
197 /* Combine / Reorder the pack (later) */
198 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
200 /* The item has been tried */
201 object_tried(o_ptr);
203 /* An identification was made */
204 if (ident && !object_aware_p(o_ptr))
206 object_aware(o_ptr);
207 gain_exp((lev + (p_ptr->lev / 2)) / p_ptr->lev);
208 p_ptr->notice |= PN_SQUELCH;
211 /* Window stuff */
212 p_ptr->window |= (PW_INVEN | PW_EQUIP);
214 /* Destroy a potion in the pack */
215 if (item >= 0)
217 inven_item_increase(item, -1);
218 inven_item_describe(item);
219 inven_item_optimize(item);
222 /* Destroy a potion on the floor */
223 else
225 floor_item_increase(0 - item, -1);
226 floor_item_describe(0 - item);
227 floor_item_optimize(0 - item);
233 * Read a scroll (from the pack or floor).
235 * Certain scrolls can be "aborted" without losing the scroll. These
236 * include scrolls with no effects but recharge or identify, which are
237 * cancelled before use. XXX Reading them still takes a turn, though.
239 void do_cmd_read_scroll(void)
241 int item, used_up, lev;
242 bool ident;
244 object_type *o_ptr;
246 cptr q, s;
249 /* Check some conditions */
250 if (p_ptr->timed[TMD_BLIND])
252 msg_print("You can't see anything.");
253 return;
255 if (no_lite())
257 msg_print("You have no light to read by.");
258 return;
261 if (p_ptr->timed[TMD_CONFUSED])
263 msg_print("You are too confused!");
264 return;
267 /* Restrict choices to scrolls */
268 item_tester_tval = TV_SCROLL;
270 /* Get an item */
271 q = "Read which scroll? ";
272 s = "You have no scrolls to read.";
273 if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
275 /* Get the item (in the pack) */
276 if (item >= 0)
278 o_ptr = &inventory[item];
281 /* Get the item (on the floor) */
282 else
284 o_ptr = &o_list[0 - item];
288 /* Take a turn */
289 p_ptr->energy_use = 100;
291 /* Check for amnesia */
292 if (rand_int(2) != 0 && p_ptr->timed[TMD_AMNESIA])
294 /* Can't remember how */
295 msg_print("You can't remember how to read!");
296 return;
299 /* Not identified yet */
300 ident = FALSE;
302 /* Object level */
303 lev = k_info[o_ptr->k_idx].level;
305 /* Read the scroll */
306 used_up = use_object(o_ptr, &ident);
308 /* Combine / Reorder the pack (later) */
309 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
311 /* The item was tried */
312 object_tried(o_ptr);
314 /* An identification was made */
315 if (ident && !object_aware_p(o_ptr))
317 object_aware(o_ptr);
318 gain_exp((lev + (p_ptr->lev / 2)) / p_ptr->lev);
319 p_ptr->notice |= PN_SQUELCH;
322 /* Window stuff */
323 p_ptr->window |= (PW_INVEN | PW_EQUIP);
326 /* Hack -- allow certain scrolls to be "preserved" */
327 if (!used_up) return;
330 /* Destroy a scroll in the pack */
331 if (item >= 0)
333 inven_item_increase(item, -1);
334 inven_item_describe(item);
335 inven_item_optimize(item);
338 /* Destroy a scroll on the floor */
339 else
341 floor_item_increase(0 - item, -1);
342 floor_item_describe(0 - item);
343 floor_item_optimize(0 - item);
354 * Use a staff
356 * One charge of one staff disappears.
358 * Hack -- staffs of identify can be "cancelled".
360 void do_cmd_use_staff(void)
362 int item, chance, lev;
364 bool ident;
366 object_type *o_ptr;
368 bool use_charge;
370 cptr q, s;
373 /* Restrict choices to staves */
374 item_tester_tval = TV_STAFF;
376 /* Get an item */
377 q = "Use which staff? ";
378 s = "You have no staff to use.";
379 if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
381 /* Get the item (in the pack) */
382 if (item >= 0)
384 o_ptr = &inventory[item];
387 /* Get the item (on the floor) */
388 else
390 o_ptr = &o_list[0 - item];
393 /* Take a turn */
394 p_ptr->energy_use = 100;
397 /* Not identified yet */
398 ident = FALSE;
400 /* Extract the item level */
401 lev = k_info[o_ptr->k_idx].level;
403 /* Base chance of success */
404 chance = p_ptr->skills[SKILL_DEV];
406 /* Confusion hurts skill */
407 if (p_ptr->timed[TMD_CONFUSED]) chance = chance / 2;
409 /* High level objects are harder */
410 chance = chance - ((lev > 50) ? 50 : lev);
412 /* Give everyone a (slight) chance */
413 if ((chance < USE_DEVICE) && (rand_int(USE_DEVICE - chance + 1) == 0))
415 chance = USE_DEVICE;
418 /* Roll for usage */
419 if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE))
421 if (flush_failure) flush();
422 msg_print("You failed to use the staff properly.");
423 return;
426 /* Notice empty staffs */
427 if (o_ptr->pval <= 0)
429 if (flush_failure) flush();
430 msg_print("The staff has no charges left.");
431 o_ptr->ident |= (IDENT_EMPTY);
432 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
433 p_ptr->window |= (PW_INVEN);
434 return;
438 /* Sound */
439 sound(MSG_USE_STAFF);
442 /* Use the staff */
443 use_charge = use_object(o_ptr, &ident);
446 /* Combine / Reorder the pack (later) */
447 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
449 /* Tried the item */
450 object_tried(o_ptr);
452 /* An identification was made */
453 if (ident && !object_aware_p(o_ptr))
455 object_aware(o_ptr);
456 gain_exp((lev + (p_ptr->lev / 2)) / p_ptr->lev);
457 p_ptr->notice |= PN_SQUELCH;
460 /* Window stuff */
461 p_ptr->window |= (PW_INVEN | PW_EQUIP);
464 /* Hack -- some uses are "free" */
465 if (!use_charge) return;
468 /* Use a single charge */
469 o_ptr->pval--;
471 /* Describe charges in the pack */
472 if (item >= 0)
474 inven_item_charges(item);
477 /* Describe charges on the floor */
478 else
480 floor_item_charges(0 - item);
486 * Aim a wand (from the pack or floor).
488 * Use a single charge from a single item.
489 * Handle "unstacking" in a logical manner.
491 * For simplicity, you cannot use a stack of items from the
492 * ground. This would require too much nasty code.
494 * There are no wands which can "destroy" themselves, in the inventory
495 * or on the ground, so we can ignore this possibility. Note that this
496 * required giving "wand of wonder" the ability to ignore destruction
497 * by electric balls.
499 * All wands can be "cancelled" at the "Direction?" prompt for free.
501 * Note that the basic "bolt" wands do slightly less damage than the
502 * basic "bolt" rods, but the basic "ball" wands do the same damage
503 * as the basic "ball" rods.
505 void do_cmd_aim_wand(void)
507 int item, lev;
509 bool ident;
511 object_type *o_ptr;
513 cptr q, s;
516 /* Restrict choices to wands */
517 item_tester_tval = TV_WAND;
519 /* Get an item */
520 q = "Aim which wand? ";
521 s = "You have no wand to aim.";
522 if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
524 /* Get the item (in the pack) */
525 if (item >= 0)
527 o_ptr = &inventory[item];
530 /* Get the item (on the floor) */
531 else
533 o_ptr = &o_list[0 - item];
538 /* Aim the wand */
539 if (!use_object(o_ptr, &ident)) return;
542 /* Combine / Reorder the pack (later) */
543 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
545 /* Mark it as tried */
546 object_tried(o_ptr);
548 /* Object level */
549 lev = k_info[o_ptr->k_idx].level;
551 /* Apply identification */
552 if (ident && !object_aware_p(o_ptr))
554 object_aware(o_ptr);
555 gain_exp((lev + (p_ptr->lev / 2)) / p_ptr->lev);
556 p_ptr->notice |= PN_SQUELCH;
559 /* Window stuff */
560 p_ptr->window |= (PW_INVEN | PW_EQUIP);
563 /* Use a single charge */
564 o_ptr->pval--;
566 /* Describe the charges in the pack */
567 if (item >= 0)
569 inven_item_charges(item);
572 /* Describe the charges on the floor */
573 else
575 floor_item_charges(0 - item);
584 * Zap a Rod
586 * Unstack fully charged rods as needed.
588 * Hack -- rods of perception can be "cancelled"
589 * All rods can be cancelled at the "Direction?" prompt
591 void do_cmd_zap_rod(void)
593 int item;
594 bool ident;
595 object_type *o_ptr;
596 cptr q, s;
599 /* Restrict choices to rods */
600 item_tester_tval = TV_ROD;
602 /* Get an item */
603 q = "Zap which rod? ";
604 s = "You have no rod to zap.";
605 if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
607 /* Get the item (in the pack) */
608 if (item >= 0)
610 o_ptr = &inventory[item];
613 /* Get the item (on the floor) */
614 else
616 o_ptr = &o_list[0 - item];
619 /* Zap the rod */
620 if (!use_object(o_ptr, &ident)) return;
622 /* Combine / Reorder the pack (later) */
623 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
625 /* Tried the object */
626 object_tried(o_ptr);
628 /* Successfully determined the object function */
629 if (ident && !object_aware_p(o_ptr))
631 /* Object level */
632 int lev = k_info[o_ptr->k_idx].level;
634 object_aware(o_ptr);
635 gain_exp((lev + (p_ptr->lev / 2)) / p_ptr->lev);
636 p_ptr->notice |= PN_SQUELCH;
639 /* Window stuff */
640 p_ptr->window |= (PW_INVEN | PW_EQUIP);
647 * Hook to determine if an object is activatable
649 static bool item_tester_hook_activate(const object_type *o_ptr)
651 u32b f1, f2, f3;
653 /* Not known */
654 if (!object_known_p(o_ptr)) return (FALSE);
656 /* Extract the flags */
657 object_flags(o_ptr, &f1, &f2, &f3);
659 /* Check activation flag */
660 if (f3 & (TR3_ACTIVATE)) return (TRUE);
662 /* Assume not */
663 return (FALSE);
668 * Activate a wielded object. Wielded objects never stack.
669 * And even if they did, activatable objects never stack.
671 * Note that it always takes a turn to activate an artifact, even if
672 * the user hits "escape" at the "direction" prompt.
674 void do_cmd_activate(void)
676 int item, lev, chance;
677 bool ident;
678 object_type *o_ptr;
680 cptr q, s;
683 /* Prepare the hook */
684 item_tester_hook = item_tester_hook_activate;
686 /* Get an item */
687 q = "Activate which item? ";
688 s = "You have nothing to activate.";
689 if (!get_item(&item, q, s, (USE_EQUIP))) return;
691 /* Get the item (in the pack) */
692 if (item >= 0)
694 o_ptr = &inventory[item];
697 /* Get the item (on the floor) */
698 else
700 o_ptr = &o_list[0 - item];
704 /* Take a turn */
705 p_ptr->energy_use = 100;
708 /* Extract the item level */
709 lev = k_info[o_ptr->k_idx].level;
711 /* Hack -- use artifact level instead */
712 if (artifact_p(o_ptr)) lev = a_info[o_ptr->name1].level;
714 /* Base chance of success */
715 chance = p_ptr->skills[SKILL_DEV];
717 /* Confusion hurts skill */
718 if (p_ptr->timed[TMD_CONFUSED]) chance = chance / 2;
720 /* High level objects are harder */
721 chance = chance - ((lev > 50) ? 50 : lev);
724 /* Give everyone a (slight) chance */
725 if ((chance < USE_DEVICE) && (rand_int(USE_DEVICE - chance + 1) == 0))
727 chance = USE_DEVICE;
730 /* Check for amnesia */
731 if (rand_int(2) != 0 && p_ptr->timed[TMD_AMNESIA])
733 if (flush_failure) flush();
734 msg_print("You can't remember how to activate it.");
735 return;
738 /* Roll for usage */
739 if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE))
741 if (flush_failure) flush();
742 msg_print("You failed to activate it properly.");
743 return;
746 /* Activate the object */
747 (void)use_object(o_ptr, &ident);