1 /**
2 * @file
3 * @brief Misc (mostly) inventory related functions.
4 **/
5
6 #include "AppHdr.h"
7
8 #include "items.h"
9
10 #include <algorithm>
11 #include <cctype>
12 #include <cstdio>
13 #include <cstdlib>
14 #include <cstring>
15 #include <functional> // mem_fn
16 #include <limits>
17
18 #include "adjust.h"
19 #include "areas.h"
20 #include "arena.h"
21 #include "artefact.h"
22 #include "art-enum.h"
23 #include "beam.h"
24 #include "bitary.h"
25 #include "cio.h"
26 #include "clua.h"
27 #include "colour.h"
28 #include "coord.h"
29 #include "coordit.h"
30 #include "corpse.h"
31 #include "dbg-util.h"
32 #include "defines.h"
33 #include "delay.h"
34 #include "describe.h"
35 #include "dgn-event.h"
36 #include "directn.h"
37 #include "dungeon.h"
38 #include "english.h"
39 #include "env.h"
40 #include "god-passive.h"
41 #include "god-prayer.h"
42 #include "hints.h"
43 #include "hints.h"
44 #include "hiscores.h"
45 #include "invent.h"
46 #include "item-name.h"
47 #include "item-prop.h"
48 #include "item-status-flag-type.h"
49 #include "item-use.h"
50 #include "libutil.h"
51 #include "macro.h"
52 #include "makeitem.h"
53 #include "message.h"
54 #include "nearby-danger.h"
55 #include "notes.h"
56 #include "options.h"
57 #include "orb.h"
58 #include "output.h"
59 #include "place.h"
60 #include "player-equip.h"
61 #include "player.h"
62 #include "prompt.h"
63 #include "quiver.h"
64 #include "randbook.h"
65 #include "religion.h"
66 #include "shopping.h"
67 #include "showsymb.h"
68 #include "skills.h"
69 #include "slot-select-mode.h"
70 #include "sound.h"
71 #include "spl-book.h"
72 #include "spl-util.h"
73 #include "stash.h"
74 #include "state.h"
75 #include "state.h"
76 #include "stringutil.h"
77 #include "tag-version.h"
78 #include "terrain.h"
79 #include "throw.h"
80 #include "tilepick.h"
81 #include "timed-effects.h" // bezotted
82 #include "travel.h"
83 #include "viewchar.h"
84 #include "view.h"
85 #include "xom.h"
86
87 /**
88 * Return an item's location (floor or inventory) and the corresponding env.item
89 * int or inv slot referring to it.
90 *
91 * @param item_def An item in either env.item (the floor or monster inventory)
92 * or you.inv.
93 *
94 * @return A pair containing bool and int. The bool is true for items in
95 * inventory, false for others. The int is the item's index in either
96 * you.inv or env.item.
97 */
98
item_int(item_def & item)99 pair<bool, int> item_int(item_def &item)
100 {
101 if (in_inventory(item))
102 return make_pair(true, item.link);
103 return make_pair(false, item.index());
104 }
105
106
107 /**
108 * Return an item_def& requested by an item's inv slot or env.item index.
109 *
110 * @param inv Is the item in inventory?
111 * @param number The index of the item, either in you.inv (if inv == true)
112 * or in env.item (if inv == false).
113 *
114 * @return The item.
115 */
116
item_from_int(bool inv,int number)117 item_def& item_from_int(bool inv, int number)
118 {
119 return inv ? you.inv[number] : env.item[number];
120 }
121
122 static int _autopickup_subtype(const item_def &item);
123 static void _autoinscribe_item(item_def& item);
124 static void _autoinscribe_floor_items();
125 static void _autoinscribe_inventory();
126 static void _multidrop(vector<SelItem> tmp_items);
127 static bool _merge_items_into_inv(item_def &it, int quant_got,
128 int &inv_slot, bool quiet);
129
130 static bool will_autopickup = false;
131 static bool will_autoinscribe = false;
132
_autopickup_item_name(const item_def & item)133 static inline string _autopickup_item_name(const item_def &item)
134 {
135 return userdef_annotate_item(STASH_LUA_SEARCH_ANNOTATE, &item)
136 + item_prefix(item, false) + " " + item.name(DESC_PLAIN);
137 }
138
139 // Used to be called "unlink_items", but all it really does is make
140 // sure item coordinates are correct to the stack they're in. -- bwr
fix_item_coordinates()141 void fix_item_coordinates()
142 {
143 // Nails all items to the ground (i.e. sets x,y).
144 for (int x = 0; x < GXM; x++)
145 for (int y = 0; y < GYM; y++)
146 {
147 int i = env.igrid[x][y];
148
149 while (i != NON_ITEM)
150 {
151 env.item[i].pos.x = x;
152 env.item[i].pos.y = y;
153 i = env.item[i].link;
154 }
155 }
156 }
157
158 // This function uses the items coordinates to relink all the env.igrid lists.
link_items()159 void link_items()
160 {
161 // First, initialise env.igrid array.
162 env.igrid.init(NON_ITEM);
163
164 // Link all items on the grid, plus shop inventory,
165 // but DON'T link the huge pile of monster items at (-2,-2).
166
167 for (int i = 0; i < MAX_ITEMS; i++)
168 {
169 // Don't mess with monster held items, since the index of the holding
170 // monster is stored in the link field.
171 if (env.item[i].held_by_monster())
172 continue;
173
174 if (!env.item[i].defined())
175 {
176 // Item is not assigned. Ignore.
177 env.item[i].link = NON_ITEM;
178 continue;
179 }
180
181 bool move_below = item_is_stationary(env.item[i])
182 && !item_is_stationary_net(env.item[i]);
183 int movable_ind = -1;
184 // Stationary item, find index at location
185 if (move_below)
186 {
187
188 for (stack_iterator si(env.item[i].pos); si; ++si)
189 {
190 if (!item_is_stationary(*si) || item_is_stationary_net(*si))
191 movable_ind = si->index();
192 }
193 }
194 // Link to top
195 if (!move_below || movable_ind == -1)
196 {
197 env.item[i].link = env.igrid(env.item[i].pos);
198 env.igrid(env.item[i].pos) = i;
199 }
200 // Link below movable items.
201 else
202 {
203 env.item[i].link = env.item[movable_ind].link;
204 env.item[movable_ind].link = i;
205 }
206 }
207 }
208
_item_ok_to_clean(int item)209 static bool _item_ok_to_clean(int item)
210 {
211 // Never clean zigfigs, Orbs, or runes.
212 if (env.item[item].base_type == OBJ_MISCELLANY
213 && env.item[item].sub_type == MISC_ZIGGURAT
214 || item_is_orb(env.item[item])
215 || env.item[item].base_type == OBJ_RUNES)
216 {
217 return false;
218 }
219
220 return true;
221 }
222
_item_preferred_to_clean(int item)223 static bool _item_preferred_to_clean(int item)
224 {
225 // Preferably clean "normal" weapons and ammo
226 if (env.item[item].base_type == OBJ_WEAPONS
227 && env.item[item].plus <= 0
228 && !is_artefact(env.item[item]))
229 {
230 return true;
231 }
232
233 if (env.item[item].base_type == OBJ_MISSILES
234 && env.item[item].plus <= 0 && !env.item[item].net_placed // XXX: plus...?
235 && !is_artefact(env.item[item]))
236 {
237 return true;
238 }
239
240 return false;
241 }
242
243 // Returns index number of first available space, or NON_ITEM for
244 // unsuccessful cleanup (should be exceedingly rare!)
_cull_items()245 static int _cull_items()
246 {
247 crawl_state.cancel_cmd_repeat();
248
249 // XXX: Not the prettiest of messages, but the player
250 // deserves to know whenever this kicks in. -- bwr
251 mprf(MSGCH_WARN, "Too many items on level, removing some.");
252
253 // Rules:
254 // 1. Don't cleanup anything nearby the player
255 // 2. Don't cleanup shops
256 // 3. Don't cleanup monster inventory
257 // 4. Clean 15% of items
258 // 5. never remove orbs or runes
259 // 7. uniques weapons are moved to the abyss
260 // 8. randarts are simply lost
261 // 9. unrandarts are 'destroyed', but may be generated again
262 // 10. Remove +0 weapons and ammo first, only removing others if this fails.
263
264 int first_cleaned = NON_ITEM;
265
266 // 2. Avoid shops by avoiding (0,5..9).
267 // 3. Avoid monster inventory by iterating over the dungeon grid.
268
269 // 10. Remove +0 weapons and ammo first, only removing others if this fails.
270 // Loop twice. First iteration, get rid of uninteresting stuff. Second
271 // iteration, get rid of anything non-essential
272 for (int remove_all=0; remove_all<2 && first_cleaned==NON_ITEM; remove_all++)
273 {
274 for (rectangle_iterator ri(1); ri; ++ri)
275 {
276 if (grid_distance(you.pos(), *ri) <= 8)
277 continue;
278
279 for (stack_iterator si(*ri); si; ++si)
280 {
281 if (_item_ok_to_clean(si->index())
282 && (remove_all || _item_preferred_to_clean(si->index()))
283 && x_chance_in_y(15, 100))
284 {
285 if (is_unrandom_artefact(*si))
286 {
287 // 7. Move uniques to abyss.
288 set_unique_item_status(*si, UNIQ_LOST_IN_ABYSS);
289 }
290
291 if (first_cleaned == NON_ITEM)
292 first_cleaned = si->index();
293
294 // POOF!
295 destroy_item(si->index());
296 }
297 }
298 }
299 }
300
301 return first_cleaned;
302 }
303
304 /*---------------------------------------------------------------------*/
stack_iterator(const coord_def & pos,bool accessible)305 stack_iterator::stack_iterator(const coord_def& pos, bool accessible)
306 {
307 cur_link = accessible ? you.visible_igrd(pos) : env.igrid(pos);
308 if (cur_link != NON_ITEM)
309 next_link = env.item[cur_link].link;
310 else
311 next_link = NON_ITEM;
312 }
313
stack_iterator(int start_link)314 stack_iterator::stack_iterator(int start_link)
315 {
316 cur_link = start_link;
317 if (cur_link != NON_ITEM)
318 next_link = env.item[cur_link].link;
319 else
320 next_link = NON_ITEM;
321 }
322
operator bool() const323 stack_iterator::operator bool() const
324 {
325 return cur_link != NON_ITEM;
326 }
327
operator *() const328 item_def& stack_iterator::operator*() const
329 {
330 ASSERT(cur_link != NON_ITEM);
331 return env.item[cur_link];
332 }
333
operator ->() const334 item_def* stack_iterator::operator->() const
335 {
336 ASSERT(cur_link != NON_ITEM);
337 return &env.item[cur_link];
338 }
339
index() const340 int stack_iterator::index() const
341 {
342 return cur_link;
343 }
344
operator ++()345 const stack_iterator& stack_iterator::operator ++ ()
346 {
347 cur_link = next_link;
348 if (cur_link != NON_ITEM)
349 next_link = env.item[cur_link].link;
350 return *this;
351 }
352
operator ++(int)353 stack_iterator stack_iterator::operator++(int)
354 {
355 const stack_iterator copy = *this;
356 ++(*this);
357 return copy;
358 }
359
mon_inv_iterator(monster & _mon)360 mon_inv_iterator::mon_inv_iterator(monster& _mon)
361 : mon(_mon)
362 {
363 type = static_cast<mon_inv_type>(0);
364 if (mon.inv[type] == NON_ITEM)
365 ++*this;
366 }
367
operator bool() const368 mon_inv_iterator::operator bool() const
369 {
370 return type < NUM_MONSTER_SLOTS;
371 }
372
operator *() const373 item_def& mon_inv_iterator::operator*() const
374 {
375 ASSERT(mon.inv[type] != NON_ITEM);
376 return env.item[mon.inv[type]];
377 }
378
operator ->() const379 item_def* mon_inv_iterator::operator->() const
380 {
381 ASSERT(mon.inv[type] != NON_ITEM);
382 return &env.item[mon.inv[type]];
383 }
384
operator ++()385 mon_inv_iterator& mon_inv_iterator::operator ++ ()
386 {
387 do
388 {
389 type = static_cast<mon_inv_type>(type + 1);
390 }
391 while (*this && mon.inv[type] == NON_ITEM);
392
393 return *this;
394 }
395
operator ++(int)396 mon_inv_iterator mon_inv_iterator::operator++(int)
397 {
398 const mon_inv_iterator copy = *this;
399 ++(*this);
400 return copy;
401 }
402
403 /**
404 * Reduce quantity of an inventory item, do cleanup if item goes away.
405 * @return True if stack of items no longer exists, false otherwise.
406 */
dec_inv_item_quantity(int obj,int amount)407 bool dec_inv_item_quantity(int obj, int amount)
408 {
409 bool ret = false;
410
411 if (you.equip[EQ_WEAPON] == obj)
412 you.wield_change = true;
413
414 if (you.inv[obj].quantity <= amount)
415 {
416 for (int i = EQ_FIRST_EQUIP; i < NUM_EQUIP; i++)
417 {
418 if (you.equip[i] == obj)
419 {
420 if (i == EQ_WEAPON)
421 {
422 unwield_item();
423 canned_msg(MSG_EMPTY_HANDED_NOW);
424 }
425 you.equip[i] = -1;
426 }
427 }
428
429 item_skills(you.inv[obj], you.skills_to_hide);
430
431 you.inv[obj].base_type = OBJ_UNASSIGNED;
432 you.inv[obj].quantity = 0;
433 you.inv[obj].props.clear();
434
435 ret = true;
436
437 // If we're repeating a command, the repetitions used up the
438 // item stack being repeated on, so stop rather than move onto
439 // the next stack.
440 crawl_state.cancel_cmd_repeat();
441 crawl_state.cancel_cmd_again();
442 quiver::on_actions_changed();
443 }
444 else
445 you.inv[obj].quantity -= amount;
446
447 return ret;
448 }
449
450 // Reduce quantity of a monster/grid item, do cleanup if item goes away.
451 //
452 // Returns true if stack of items no longer exists.
dec_mitm_item_quantity(int obj,int amount)453 bool dec_mitm_item_quantity(int obj, int amount)
454 {
455 item_def &item = env.item[obj];
456 if (amount > item.quantity)
457 amount = item.quantity; // can't use min due to type mismatch
458
459 if (item.quantity == amount)
460 {
461 destroy_item(obj);
462 // If we're repeating a command, the repetitions used up the
463 // item stack being repeated on, so stop rather than move onto
464 // the next stack.
465 crawl_state.cancel_cmd_repeat();
466 crawl_state.cancel_cmd_again();
467 return true;
468 }
469
470 item.quantity -= amount;
471 return false;
472 }
473
inc_inv_item_quantity(int obj,int amount)474 void inc_inv_item_quantity(int obj, int amount)
475 {
476 if (you.equip[EQ_WEAPON] == obj)
477 you.wield_change = true;
478
479 you.inv[obj].quantity += amount;
480 if (you.inv[obj].quantity == amount) // not currently possible?
481 quiver::on_actions_changed(true);
482 }
483
inc_mitm_item_quantity(int obj,int amount)484 void inc_mitm_item_quantity(int obj, int amount)
485 {
486 env.item[obj].quantity += amount;
487 }
488
init_item(int item)489 void init_item(int item)
490 {
491 if (item == NON_ITEM)
492 return;
493
494 env.item[item].clear();
495 }
496
497 // Returns an unused env.item slot, or NON_ITEM if none available.
498 // The reserve is the number of item slots to not check.
499 // Items may be culled if a reserve <= 10 is specified.
get_mitm_slot(int reserve)500 int get_mitm_slot(int reserve)
501 {
502 ASSERT(reserve >= 0);
503
504 if (crawl_state.game_is_arena())
505 reserve = 0;
506
507 int item = NON_ITEM;
508
509 for (item = 0; item < (MAX_ITEMS - reserve); item++)
510 if (!env.item[item].defined())
511 break;
512
513 if (item >= MAX_ITEMS - reserve)
514 {
515 if (crawl_state.game_is_arena())
516 {
517 item = arena_cull_items();
518 // If arena_cull_items() can't free up any space then
519 // _cull_items() won't be able to either, so give up.
520 if (item == NON_ITEM)
521 return NON_ITEM;
522 }
523 else
524 item = (reserve <= 10) ? _cull_items() : NON_ITEM;
525
526 if (item == NON_ITEM)
527 return NON_ITEM;
528 }
529
530 ASSERT(item != NON_ITEM);
531
532 init_item(item);
533
534 return item;
535 }
536
unlink_item(int dest)537 void unlink_item(int dest)
538 {
539 // Don't destroy non-items, may be called after an item has been
540 // reduced to zero quantity however.
541 if (dest == NON_ITEM || !env.item[dest].defined())
542 return;
543
544 monster* mons = env.item[dest].holding_monster();
545
546 if (mons != nullptr)
547 {
548 for (mon_inv_iterator ii(*mons); ii; ++ii)
549 {
550 if (ii->index() == dest)
551 {
552 item_def& item = *ii;
553 mons->inv[ii.slot()] = NON_ITEM;
554
555 item.pos.reset();
556 item.link = NON_ITEM;
557 return;
558 }
559 }
560 mprf(MSGCH_ERROR, "Item %s claims to be held by monster %s, but "
561 "it isn't in the monster's inventory.",
562 env.item[dest].name(DESC_PLAIN, false, true).c_str(),
563 mons->name(DESC_PLAIN, true).c_str());
564 // Don't return so the debugging code can take a look at it.
565 }
566 // Unlinking a newly created item, or a a temporary one, or an item in
567 // the player's inventory.
568 else if (env.item[dest].pos.origin() || env.item[dest].pos == ITEM_IN_INVENTORY)
569 {
570 env.item[dest].pos.reset();
571 env.item[dest].link = NON_ITEM;
572 return;
573 }
574 else
575 {
576 // Linked item on map:
577 //
578 // Use the items (x,y) to access the list (env.igrid[x][y]) where
579 // the item should be linked.
580
581 #if TAG_MAJOR_VERSION == 34
582 if (env.item[dest].pos.x != 0 || env.item[dest].pos.y < 5)
583 #endif
584 ASSERT_IN_BOUNDS(env.item[dest].pos);
585
586 // First check the top:
587 if (env.igrid(env.item[dest].pos) == dest)
588 {
589 // link env.igrid to the second item
590 env.igrid(env.item[dest].pos) = env.item[dest].link;
591
592 env.item[dest].pos.reset();
593 env.item[dest].link = NON_ITEM;
594 return;
595 }
596
597 // Okay, item is buried, find item that's on top of it.
598 for (stack_iterator si(env.item[dest].pos); si; ++si)
599 {
600 // Find item linking to dest item.
601 if (si->defined() && si->link == dest)
602 {
603 // unlink dest
604 si->link = env.item[dest].link;
605 env.item[dest].pos.reset();
606 env.item[dest].link = NON_ITEM;
607 return;
608 }
609 }
610 }
611
612 #ifdef DEBUG
613 // Okay, the sane ways are gone... let's warn the player:
614 mprf(MSGCH_ERROR, "BUG WARNING: Problems unlinking item '%s', (%d, %d)!!!",
615 env.item[dest].name(DESC_PLAIN).c_str(),
616 env.item[dest].pos.x, env.item[dest].pos.y);
617
618 // Okay, first we scan all items to see if we have something
619 // linked to this item. We're not going to return if we find
620 // such a case... instead, since things are already out of
621 // alignment, let's assume there might be multiple links as well.
622 bool linked = false;
623 int old_link = env.item[dest].link; // used to try linking the first
624
625 // Clean the relevant parts of the object.
626 env.item[dest].base_type = OBJ_UNASSIGNED;
627 env.item[dest].quantity = 0;
628 env.item[dest].link = NON_ITEM;
629 env.item[dest].pos.reset();
630 env.item[dest].props.clear();
631
632 // Look through all items for links to this item.
633 for (auto &item : env.item)
634 {
635 if (item.defined() && item.link == dest)
636 {
637 // unlink item
638 item.link = old_link;
639
640 if (!linked)
641 {
642 old_link = NON_ITEM;
643 linked = true;
644 }
645 }
646 }
647
648 // Now check the grids to see if it's linked as a list top.
649 for (int c = 2; c < (GXM - 1); c++)
650 for (int cy = 2; cy < (GYM - 1); cy++)
651 {
652 if (env.igrid[c][cy] == dest)
653 {
654 env.igrid[c][cy] = old_link;
655
656 if (!linked)
657 {
658 old_link = NON_ITEM; // cleaned after the first
659 linked = true;
660 }
661 }
662 }
663
664 // Okay, finally warn player if we didn't do anything.
665 if (!linked)
666 mprf(MSGCH_ERROR, "BUG WARNING: Item didn't seem to be linked at all.");
667 #endif
668 }
669
destroy_item(item_def & item,bool never_created)670 void destroy_item(item_def &item, bool never_created)
671 {
672 if (!item.defined())
673 return;
674
675 if (never_created)
676 {
677 if (is_unrandom_artefact(item))
678 set_unique_item_status(item, UNIQ_NOT_EXISTS);
679 }
680
681 item.clear();
682 }
683
destroy_item(int dest,bool never_created)684 void destroy_item(int dest, bool never_created)
685 {
686 // Don't destroy non-items, but this function may be called upon
687 // to remove items reduced to zero quantity, so we allow "invalid"
688 // objects in.
689 if (dest == NON_ITEM || !env.item[dest].defined())
690 return;
691
692 unlink_item(dest);
693 destroy_item(env.item[dest], never_created);
694 }
695
_handle_gone_item(const item_def & item)696 static void _handle_gone_item(const item_def &item)
697 {
698 if (player_in_branch(BRANCH_ABYSS)
699 && item.orig_place.branch == BRANCH_ABYSS)
700 {
701 if (is_unrandom_artefact(item))
702 set_unique_item_status(item, UNIQ_LOST_IN_ABYSS);
703 }
704 }
705
item_was_lost(const item_def & item)706 void item_was_lost(const item_def &item)
707 {
708 _handle_gone_item(item);
709 xom_check_lost_item(item);
710 }
711
item_was_destroyed(const item_def & item)712 void item_was_destroyed(const item_def &item)
713 {
714 _handle_gone_item(item);
715 xom_check_destroyed_item(item);
716 }
717
lose_item_stack(const coord_def & where)718 void lose_item_stack(const coord_def& where)
719 {
720 for (stack_iterator si(where); si; ++si)
721 {
722 if (si ->defined()) // FIXME is this check necessary?
723 {
724 item_was_lost(*si);
725 si->clear();
726 }
727 }
728 env.igrid(where) = NON_ITEM;
729 }
730
731 /**
732 * How many movable items are there at a location?
733 *
734 * @param obj The item link for the location.
735 * @return The number of movable items at the location.
736 */
count_movable_items(int obj)737 int count_movable_items(int obj)
738 {
739 int result = 0;
740
741 for (stack_iterator si(obj); si; ++si)
742 {
743 if (!item_is_stationary(*si))
744 ++result;
745 }
746 return result;
747 }
748
749 /**
750 * Fill the given vector with the items on the given location link.
751 *
752 * @param[out] items A vector to hold the item_defs of the item.
753 * @param[in] obj The location link; an index in env.item.
754 * @param exclude_stationary If true, don't include stationary items.
755 */
item_list_on_square(int obj)756 vector<const item_def*> item_list_on_square(int obj)
757 {
758 vector<const item_def*> items;
759 for (stack_iterator si(obj); si; ++si)
760 items.push_back(& (*si));
761 return items;
762 }
763
need_to_autopickup()764 bool need_to_autopickup()
765 {
766 return will_autopickup;
767 }
768
request_autopickup(bool do_pickup)769 void request_autopickup(bool do_pickup)
770 {
771 will_autopickup = do_pickup;
772 }
773
item_is_branded(const item_def & item)774 bool item_is_branded(const item_def& item)
775 {
776 switch (item.base_type)
777 {
778 case OBJ_WEAPONS:
779 return get_weapon_brand(item) != SPWPN_NORMAL;
780 case OBJ_ARMOUR:
781 return get_armour_ego_type(item) != SPARM_NORMAL;
782 case OBJ_MISSILES:
783 return get_ammo_brand(item) != SPMSL_NORMAL;
784 default:
785 return false;
786 }
787 }
788
789 // 2 - artefact, 1 - glowing/runed, 0 - mundane
_item_name_specialness(const item_def & item)790 static int _item_name_specialness(const item_def& item)
791 {
792 if (item.base_type != OBJ_WEAPONS && item.base_type != OBJ_ARMOUR
793 && item.base_type != OBJ_MISSILES && item.base_type != OBJ_JEWELLERY)
794 {
795 return 0;
796 }
797
798 // You can tell something is an artefact, because it'll have a
799 // description which rules out anything else.
800 if (is_artefact(item))
801 return 2;
802
803 // All unknown jewellery is worth looking at.
804 if (item.base_type == OBJ_JEWELLERY)
805 {
806 if (is_useless_item(item))
807 return 0;
808
809 return 1;
810 }
811
812 if (item_type_known(item))
813 {
814 if (item_is_branded(item))
815 return 1;
816 return 0;
817 }
818
819 if (item.flags & ISFLAG_COSMETIC_MASK)
820 return 1;
821
822 return 0;
823 }
824
_maybe_give_corpse_hint(const item_def & item)825 static void _maybe_give_corpse_hint(const item_def& item)
826 {
827 if (!crawl_state.game_is_hints_tutorial())
828 return;
829
830 if (item.is_type(OBJ_CORPSES, CORPSE_BODY)
831 && you.has_spell(SPELL_ANIMATE_SKELETON))
832 {
833 learned_something_new(HINT_ANIMATE_CORPSE_SKELETON);
834 }
835 }
836
item_message(vector<const item_def * > const & items)837 string item_message(vector<const item_def *> const &items)
838 {
839 if (static_cast<int>(items.size()) >= Options.item_stack_summary_minimum)
840 {
841 string out_string;
842 vector<unsigned int> item_chars;
843 for (unsigned int i = 0; i < items.size() && i < 50; ++i)
844 {
845 cglyph_t g = get_item_glyph(*items[i]);
846 item_chars.push_back(g.ch * 0x100 +
847 (10 - _item_name_specialness(*(items[i]))));
848 }
849 sort(item_chars.begin(), item_chars.end());
850
851 int cur_state = -1;
852 string colour = "";
853 for (unsigned int i = 0; i < item_chars.size(); ++i)
854 {
855 const int specialness = 10 - (item_chars[i] % 0x100);
856 if (specialness != cur_state)
857 {
858 if (!colour.empty())
859 out_string += "</" + colour + ">";
860 switch (specialness)
861 {
862 case 2: colour = "yellow"; break; // artefact
863 case 1: colour = "white"; break; // glowing/runed
864 case 0: colour = "darkgrey"; break; // mundane
865 }
866 if (!colour.empty())
867 out_string += "<" + colour + ">";
868 cur_state = specialness;
869 }
870
871 out_string += stringize_glyph(item_chars[i] / 0x100);
872 if (i + 1 < item_chars.size()
873 && (item_chars[i] / 0x100) != (item_chars[i+1] / 0x100))
874 {
875 out_string += ' ';
876 }
877 }
878 if (!colour.empty())
879 out_string += "</" + colour + ">";
880
881 return out_string;
882 }
883
884 vector<string> colour_names;
885 for (const item_def *it : items)
886 colour_names.push_back(menu_colour_item_name(*it, DESC_A));
887
888 return join_strings(colour_names.begin(), colour_names.end(), "; ");
889 }
890
item_check()891 void item_check()
892 {
893 describe_floor();
894 origin_set(you.pos());
895
896 ostream& strm = msg::streams(MSGCH_FLOOR_ITEMS);
897
898 auto items = item_list_on_square(you.visible_igrd(you.pos()));
899
900 if (items.empty())
901 return;
902
903 // Special case
904 if (items.size() == 1)
905 {
906 const item_def& it(*items[0]);
907 string name = menu_colour_item_name(it, DESC_A);
908 strm << "You see here " << name << '.' << endl;
909 _maybe_give_corpse_hint(it);
910 return;
911 }
912
913 string desc_string = item_message(items);
914 // Stack summary case
915 if (static_cast<int>(items.size()) >= Options.item_stack_summary_minimum)
916 mprf_nojoin(MSGCH_FLOOR_ITEMS, "Items here: %s.", desc_string.c_str());
917 else if (items.size() <= msgwin_lines() - 1)
918 {
919 mpr_nojoin(MSGCH_FLOOR_ITEMS, "Things that are here:");
920 mprf_nocap("%s", desc_string.c_str());
921 }
922 else
923 strm << "There are many items here." << endl;
924
925 if (items.size() > 2 && crawl_state.game_is_hints_tutorial())
926 {
927 // If there are 2 or more non-corpse items here, we might need
928 // a hint.
929 int count = 0;
930 for (const item_def *it : items)
931 {
932 _maybe_give_corpse_hint(*it);
933 if (it->base_type == OBJ_CORPSES)
934 continue;
935
936 if (++count > 1)
937 {
938 learned_something_new(HINT_MULTI_PICKUP);
939 break;
940 }
941 }
942 }
943 }
944
identify_item(item_def & item)945 void identify_item(item_def& item)
946 {
947 // items_stack() has strict flag conditions to prevent a shop info leak,
948 // so we need set_ident_type() here to permit stacking shop purchases.
949 if (is_stackable_item(item))
950 set_ident_type(item, true);
951
952 set_ident_flags(item, ISFLAG_IDENT_MASK);
953
954 if (is_artefact(item) && !(item.flags & ISFLAG_NOTED_ID))
955 {
956 item.flags |= ISFLAG_NOTED_ID;
957
958 // Make a note of it.
959 take_note(Note(NOTE_ID_ITEM, 0, 0, item.name(DESC_A),
960 origin_desc(item)));
961 }
962 }
963
964 // Identify the object the player stepped on.
965 // Books are fully identified.
966 // Wands are only type-identified.
967 // Equipment items are fully identified,
968 // but artefact equipment skips some type-id checks.
_id_floor_item(item_def & item)969 static bool _id_floor_item(item_def &item)
970 {
971 if (item.base_type == OBJ_BOOKS)
972 return true;
973 if (item.base_type == OBJ_WANDS)
974 {
975 if (!get_ident_type(item))
976 {
977 // If the player doesn't want unknown wands picked up, assume
978 // they won't want this wand after it is identified.
979 bool should_pickup = item_needs_autopickup(item);
980 set_ident_type(item, true);
981 if (!should_pickup)
982 set_item_autopickup(item, AP_FORCE_OFF);
983 return true;
984 }
985 }
986 else if (item_type_is_equipment(item.base_type))
987 {
988 if (fully_identified(item))
989 return false;
990
991 // autopickup hack for previously-unknown items
992 if (item_needs_autopickup(item))
993 item.props["needs_autopickup"] = true;
994 identify_item(item);
995 // but skip ones that we discover to be useless
996 if (item.props.exists("needs_autopickup") && is_useless_item(item))
997 item.props.erase("needs_autopickup");
998 return true;
999 }
1000
1001 return false;
1002 }
1003
1004 /// Auto-ID whatever stuff the player stands on.
id_floor_items()1005 void id_floor_items()
1006 {
1007 for (stack_iterator si(you.pos()); si; ++si)
1008 _id_floor_item(*si);
1009 }
1010
pickup_menu(int item_link)1011 void pickup_menu(int item_link)
1012 {
1013 int n_did_pickup = 0;
1014 int n_tried_pickup = 0;
1015
1016 auto items = item_list_on_square(item_link);
1017 ASSERT(items.size());
1018
1019 string prompt = "Pick up what? " + slot_description()
1020 #ifdef TOUCH_UI
1021 + " (<Enter> or tap header to pick up)"
1022 #else
1023 + " (_ for help)"
1024 #endif
1025 ;
1026
1027 if (items.size() == 1 && items[0]->quantity > 1)
1028 prompt = "Select pick up quantity by entering a number, then select the item";
1029 vector<SelItem> selected = select_items(items, prompt.c_str(), false,
1030 menu_type::pickup);
1031 if (selected.empty())
1032 canned_msg(MSG_OK);
1033 redraw_screen();
1034 update_screen();
1035
1036 string pickup_warning;
1037 for (const SelItem &sel : selected)
1038 {
1039 // Moving the item might destroy it, in which case we can't
1040 // rely on the link.
1041 short next;
1042 for (int j = item_link; j != NON_ITEM; j = next)
1043 {
1044 next = env.item[j].link;
1045 if (&env.item[j] == sel.item)
1046 {
1047 if (j == item_link)
1048 item_link = next;
1049
1050 int num_to_take = sel.quantity;
1051 const bool take_all = (num_to_take == env.item[j].quantity);
1052 iflags_t oldflags = env.item[j].flags;
1053 clear_item_pickup_flags(env.item[j]);
1054
1055 // If we cleared any flags on the items, but the pickup was
1056 // partial, reset the flags for the items that remain on the
1057 // floor.
1058 if (!move_item_to_inv(j, num_to_take))
1059 {
1060 n_tried_pickup++;
1061 pickup_warning = "You can't carry that many items.";
1062 if (env.item[j].defined())
1063 env.item[j].flags = oldflags;
1064 }
1065 else
1066 {
1067 n_did_pickup++;
1068 // If we deliberately chose to take only part of a
1069 // pile, we consider the rest to have been
1070 // "dropped."
1071 if (!take_all && env.item[j].defined())
1072 env.item[j].flags |= ISFLAG_DROPPED;
1073 }
1074 }
1075 }
1076 }
1077
1078 if (!pickup_warning.empty())
1079 {
1080 mpr(pickup_warning);
1081 learned_something_new(HINT_FULL_INVENTORY);
1082 }
1083
1084 if (n_did_pickup)
1085 you.turn_is_over = true;
1086 }
1087
origin_known(const item_def & item)1088 bool origin_known(const item_def &item)
1089 {
1090 return item.orig_place != level_id();
1091 }
1092
origin_reset(item_def & item)1093 void origin_reset(item_def &item)
1094 {
1095 item.orig_place.clear();
1096 item.orig_monnum = 0;
1097 }
1098
1099 // We have no idea where the player found this item.
origin_set_unknown(item_def & item)1100 void origin_set_unknown(item_def &item)
1101 {
1102 if (!origin_known(item))
1103 {
1104 item.orig_place = level_id(BRANCH_DUNGEON, 0);
1105 item.orig_monnum = 0;
1106 }
1107 }
1108
1109 // This item is starting equipment.
origin_set_startequip(item_def & item)1110 void origin_set_startequip(item_def &item)
1111 {
1112 if (!origin_known(item))
1113 {
1114 item.orig_place = level_id(BRANCH_DUNGEON, 0);
1115 item.orig_monnum = -IT_SRC_START;
1116 }
1117 }
1118
origin_set_monster(item_def & item,const monster * mons)1119 void origin_set_monster(item_def &item, const monster* mons)
1120 {
1121 if (!origin_known(item))
1122 {
1123 if (!item.orig_monnum)
1124 item.orig_monnum = mons->type;
1125 item.orig_place = level_id::current();
1126 }
1127 }
1128
origin_purchased(item_def & item)1129 void origin_purchased(item_def &item)
1130 {
1131 // We don't need to check origin_known if it's a shop purchase
1132 item.orig_place = level_id::current();
1133 item.orig_monnum = -IT_SRC_SHOP;
1134 }
1135
origin_acquired(item_def & item,int agent)1136 void origin_acquired(item_def &item, int agent)
1137 {
1138 // We don't need to check origin_known if it's a divine gift
1139 item.orig_place = level_id::current();
1140 item.orig_monnum = -agent;
1141 }
1142
_milestone_rune(const item_def & item)1143 static string _milestone_rune(const item_def &item)
1144 {
1145 return string("found ") + item.name(DESC_A) + ".";
1146 }
1147
_milestone_check(const item_def & item)1148 static void _milestone_check(const item_def &item)
1149 {
1150 if (item.base_type == OBJ_RUNES)
1151 mark_milestone("rune", _milestone_rune(item));
1152 else if (item_is_orb(item))
1153 mark_milestone("orb", "found the Orb of Zot!");
1154 }
1155
_check_note_item(item_def & item)1156 static void _check_note_item(item_def &item)
1157 {
1158 if (item.flags & (ISFLAG_NOTED_GET | ISFLAG_NOTED_ID))
1159 return;
1160
1161 if (item.base_type == OBJ_RUNES || item_is_orb(item) || is_artefact(item))
1162 {
1163 take_note(Note(NOTE_GET_ITEM, 0, 0, item.name(DESC_A),
1164 origin_desc(item)));
1165 item.flags |= ISFLAG_NOTED_GET;
1166
1167 // If it's already fully identified when picked up, don't take
1168 // further notes.
1169 if (fully_identified(item))
1170 item.flags |= ISFLAG_NOTED_ID;
1171 _milestone_check(item);
1172 }
1173 }
1174
origin_set(const coord_def & where)1175 void origin_set(const coord_def& where)
1176 {
1177 for (stack_iterator si(where); si; ++si)
1178 {
1179 if (origin_known(*si))
1180 continue;
1181
1182 si->orig_place = level_id::current();
1183 }
1184 }
1185
_origin_freeze(item_def & item)1186 static void _origin_freeze(item_def &item)
1187 {
1188 if (!origin_known(item))
1189 {
1190 item.orig_place = level_id::current();
1191 _check_note_item(item);
1192 }
1193 }
1194
_origin_monster_name(const item_def & item)1195 static string _origin_monster_name(const item_def &item)
1196 {
1197 const monster_type monnum = static_cast<monster_type>(item.orig_monnum);
1198 if (monnum == MONS_PLAYER_GHOST)
1199 return "a player ghost";
1200 else if (monnum == MONS_PANDEMONIUM_LORD)
1201 return "a pandemonium lord";
1202 return mons_type_name(monnum, DESC_A);
1203 }
1204
_origin_place_desc(const item_def & item)1205 static string _origin_place_desc(const item_def &item)
1206 {
1207 return prep_branch_level_name(item.orig_place);
1208 }
1209
_origin_is_special(const item_def & item)1210 static bool _origin_is_special(const item_def &item)
1211 {
1212 return item.orig_place == level_id(BRANCH_DUNGEON, 0);
1213 }
1214
origin_describable(const item_def & item)1215 bool origin_describable(const item_def &item)
1216 {
1217 return origin_known(item)
1218 && !_origin_is_special(item)
1219 && !is_stackable_item(item)
1220 && item.quantity == 1
1221 && item.base_type != OBJ_CORPSES;
1222 }
1223
_article_it(const item_def &)1224 static string _article_it(const item_def &/*item*/)
1225 {
1226 // "it" is always correct, since gloves and boots also come in pairs.
1227 return "it";
1228 }
1229
_origin_is_original_equip(const item_def & item)1230 static bool _origin_is_original_equip(const item_def &item)
1231 {
1232 return _origin_is_special(item) && item.orig_monnum == -IT_SRC_START;
1233 }
1234
1235 /**
1236 * What god gifted this item to the player?
1237 *
1238 * @param item The item in question.
1239 * @returns The god that gifted this item to the player, if any;
1240 * else GOD_NO_GOD.
1241 */
origin_as_god_gift(const item_def & item)1242 god_type origin_as_god_gift(const item_def& item)
1243 {
1244 const god_type ogod = static_cast<god_type>(-item.orig_monnum);
1245 if (ogod <= GOD_NO_GOD || ogod >= NUM_GODS)
1246 return GOD_NO_GOD;
1247 return ogod;
1248 }
1249
origin_is_acquirement(const item_def & item,item_source_type * type)1250 bool origin_is_acquirement(const item_def& item, item_source_type *type)
1251 {
1252 item_source_type junk;
1253 if (type == nullptr)
1254 type = &junk;
1255 *type = IT_SRC_NONE;
1256
1257 const int iorig = -item.orig_monnum;
1258 #if TAG_MAJOR_VERSION == 34
1259 // Copy pasting is bad but this will autoupdate on version bump
1260 if (iorig == AQ_CARD_GENIE)
1261 {
1262 *type = static_cast<item_source_type>(iorig);
1263 return true;
1264 }
1265
1266 #endif
1267 if (iorig == AQ_SCROLL || iorig == AQ_WIZMODE)
1268 {
1269 *type = static_cast<item_source_type>(iorig);
1270 return true;
1271 }
1272
1273 return false;
1274 }
1275
origin_desc(const item_def & item)1276 string origin_desc(const item_def &item)
1277 {
1278 if (!origin_describable(item))
1279 return "";
1280
1281 if (_origin_is_original_equip(item))
1282 return "Original Equipment";
1283
1284 string desc;
1285 if (item.orig_monnum)
1286 {
1287 if (item.orig_monnum < 0)
1288 {
1289 int iorig = -item.orig_monnum;
1290 switch (iorig)
1291 {
1292 case IT_SRC_SHOP:
1293 desc += "You bought " + _article_it(item) + " in a shop ";
1294 break;
1295 case IT_SRC_START:
1296 desc += "Buggy Original Equipment: ";
1297 break;
1298 case AQ_SCROLL:
1299 desc += "You acquired " + _article_it(item) + " ";
1300 break;
1301 #if TAG_MAJOR_VERSION == 34
1302 case AQ_CARD_GENIE:
1303 desc += "You drew the Genie ";
1304 break;
1305 #endif
1306 case AQ_WIZMODE:
1307 desc += "Your wizardly powers created "+ _article_it(item)+ " ";
1308 break;
1309 default:
1310 if (iorig > GOD_NO_GOD && iorig < NUM_GODS)
1311 {
1312 desc += god_name(static_cast<god_type>(iorig))
1313 + " gifted " + _article_it(item) + " to you ";
1314 }
1315 else
1316 {
1317 // Bug really.
1318 desc += "You stumbled upon " + _article_it(item) + " ";
1319 }
1320 break;
1321 }
1322 }
1323 else if (item.orig_monnum == MONS_DANCING_WEAPON)
1324 desc += "You subdued it ";
1325 else
1326 {
1327 desc += "You took " + _article_it(item) + " off "
1328 + _origin_monster_name(item) + " ";
1329 }
1330 }
1331 else
1332 desc += "You found " + _article_it(item) + " ";
1333
1334 desc += _origin_place_desc(item);
1335 return desc;
1336 }
1337
1338 /**
1339 * Pickup a single item stack at the given location link
1340 *
1341 * @param link The location link
1342 * @param qty If 0, prompt for quantity of that item to pick up, if < 0,
1343 * pick up the entire stack, otherwise pick up qty of the item.
1344 * @return True if any item was picked up, false otherwise.
1345 */
pickup_single_item(int link,int qty)1346 bool pickup_single_item(int link, int qty)
1347 {
1348 ASSERT(link != NON_ITEM);
1349
1350 item_def* item = &env.item[link];
1351 if (item_is_stationary(env.item[link]))
1352 {
1353 mpr("You can't pick that up.");
1354 return false;
1355 }
1356 if (item->base_type == OBJ_GOLD && !qty && !i_feel_safe()
1357 && !yesno("Are you sure you want to pick up this pile of gold now?",
1358 true, 'n'))
1359 {
1360 canned_msg(MSG_OK);
1361 return false;
1362 }
1363 if (qty == 0 && item->quantity > 1 && item->base_type != OBJ_GOLD)
1364 {
1365 const string prompt
1366 = make_stringf("Pick up how many of %s (; or enter for all)? ",
1367 item->name(DESC_THE, false,
1368 false, false).c_str());
1369
1370 qty = prompt_for_quantity(prompt.c_str());
1371 if (qty == -1)
1372 qty = item->quantity;
1373 else if (qty == 0)
1374 {
1375 canned_msg(MSG_OK);
1376 return false;
1377 }
1378 else if (qty < item->quantity)
1379 {
1380 // Mark rest item as not eligible for autopickup.
1381 item->flags |= ISFLAG_DROPPED;
1382 item->flags &= ~ISFLAG_THROWN;
1383 }
1384 }
1385
1386 if (qty < 1 || qty > item->quantity)
1387 qty = item->quantity;
1388
1389 iflags_t oldflags = item->flags;
1390 clear_item_pickup_flags(*item);
1391 const bool pickup_succ = move_item_to_inv(link, qty);
1392 if (item->defined())
1393 item->flags = oldflags;
1394
1395 if (!pickup_succ)
1396 {
1397 mpr("You can't carry that many items.");
1398 learned_something_new(HINT_FULL_INVENTORY);
1399 return false;
1400 }
1401 return true;
1402 }
1403
player_on_single_stack()1404 bool player_on_single_stack()
1405 {
1406 int o = you.visible_igrd(you.pos());
1407 if (o == NON_ITEM)
1408 return false;
1409 else
1410 return env.item[o].link == NON_ITEM && env.item[o].quantity > 1;
1411 }
1412
1413 /**
1414 * Do the pickup command.
1415 *
1416 * @param partial_quantity If true, prompt for a quantity to pick up when
1417 * picking up a single stack.
1418 */
pickup(bool partial_quantity)1419 void pickup(bool partial_quantity)
1420 {
1421 int keyin = 'x';
1422
1423 int o = you.visible_igrd(you.pos());
1424 const int num_items = count_movable_items(o);
1425
1426 // Store last_pickup in case we need to restore it.
1427 // Then clear it to fill with items picked up.
1428 map<int,int> tmp_l_p = you.last_pickup;
1429 you.last_pickup.clear();
1430
1431 if (o == NON_ITEM)
1432 mpr("There are no items here.");
1433 else if (you.form == transformation::ice_beast
1434 && env.grid(you.pos()) == DNGN_DEEP_WATER)
1435 {
1436 mpr("You can't reach the bottom while floating on water.");
1437 }
1438 else if (num_items == 1) // just one movable item?
1439 {
1440 // Get the link to the movable item in the pile.
1441 while (item_is_stationary(env.item[o]))
1442 o = env.item[o].link;
1443 pickup_single_item(o, partial_quantity ? 0 : env.item[o].quantity);
1444 }
1445 else if (Options.pickup_menu_limit
1446 && num_items > (Options.pickup_menu_limit > 0
1447 ? Options.pickup_menu_limit
1448 : Options.item_stack_summary_minimum - 1))
1449 {
1450 pickup_menu(o);
1451 }
1452 else
1453 {
1454 int next;
1455 if (num_items == 0)
1456 mpr("There are no objects that can be picked up here.");
1457 else
1458 mpr("There are several objects here.");
1459 string pickup_warning;
1460 bool any_selectable = false;
1461 while (o != NON_ITEM)
1462 {
1463 // Must save this because pickup can destroy the item.
1464 next = env.item[o].link;
1465
1466 if (item_is_stationary(env.item[o]))
1467 {
1468 o = next;
1469 continue;
1470 }
1471 any_selectable = true;
1472
1473 if (keyin != 'a')
1474 {
1475 string prompt = "Pick up %s? ((y)es/(n)o/(a)ll/(m)enu/*?g,/q)";
1476
1477 mprf(MSGCH_PROMPT, prompt.c_str(),
1478 menu_colour_item_name(env.item[o], DESC_A).c_str());
1479
1480 mouse_control mc(MOUSE_MODE_YESNO);
1481 keyin = getch_ck();
1482 }
1483
1484 if (keyin == '*' || keyin == '?' || keyin == ',' || keyin == 'g'
1485 || keyin == 'm' || keyin == CK_MOUSE_CLICK)
1486 {
1487 pickup_menu(o);
1488 break;
1489 }
1490
1491 if (keyin == 'q' || key_is_escape(keyin))
1492 {
1493 canned_msg(MSG_OK);
1494 break;
1495 }
1496
1497 if (keyin == 'y' || keyin == 'a')
1498 {
1499 int num_to_take = env.item[o].quantity;
1500 const iflags_t old_flags(env.item[o].flags);
1501 clear_item_pickup_flags(env.item[o]);
1502
1503 // attempt to actually pick up the object.
1504 if (!move_item_to_inv(o, num_to_take))
1505 {
1506 pickup_warning = "You can't carry that many items.";
1507 env.item[o].flags = old_flags;
1508 }
1509 }
1510
1511 o = next;
1512
1513 if (o == NON_ITEM && keyin != 'y' && keyin != 'a')
1514 canned_msg(MSG_OK);
1515 }
1516
1517 // If there were no selectable items (all corpses, for example),
1518 // list them.
1519 if (!any_selectable)
1520 {
1521 for (stack_iterator si(you.pos(), true); si; ++si)
1522 mprf_nocap("%s", menu_colour_item_name(*si, DESC_A).c_str());
1523 }
1524
1525 if (!pickup_warning.empty())
1526 mpr(pickup_warning);
1527 }
1528 if (you.last_pickup.empty())
1529 you.last_pickup = tmp_l_p;
1530 }
1531
is_stackable_item(const item_def & item)1532 bool is_stackable_item(const item_def &item)
1533 {
1534 if (!item.defined())
1535 return false;
1536
1537 switch (item.base_type)
1538 {
1539 case OBJ_MISSILES:
1540 case OBJ_SCROLLS:
1541 case OBJ_POTIONS:
1542 case OBJ_GOLD:
1543 #if TAG_MAJOR_VERSION == 34
1544 case OBJ_FOOD:
1545 #endif
1546 return true;
1547 case OBJ_MISCELLANY:
1548 switch (item.sub_type)
1549 {
1550 case MISC_ZIGGURAT:
1551 #if TAG_MAJOR_VERSION == 34
1552 case MISC_SACK_OF_SPIDERS:
1553 #endif
1554 return true;
1555 default:
1556 break;
1557 }
1558 default:
1559 break;
1560 }
1561 return false;
1562 }
1563
items_similar(const item_def & item1,const item_def & item2)1564 bool items_similar(const item_def &item1, const item_def &item2)
1565 {
1566 // Base and sub-types must always be the same to stack.
1567 if (item1.base_type != item2.base_type || item1.sub_type != item2.sub_type)
1568 return false;
1569
1570 if (item1.base_type == OBJ_GOLD || item1.base_type == OBJ_RUNES)
1571 return true;
1572
1573 if (is_artefact(item1) != is_artefact(item2))
1574 return false;
1575 else if (is_artefact(item1)
1576 && get_artefact_name(item1) != get_artefact_name(item2))
1577 {
1578 return false;
1579 }
1580
1581 // Missiles with different egos shouldn't merge.
1582 if (item1.base_type == OBJ_MISSILES && item1.brand != item2.brand)
1583 return false;
1584
1585 // Don't merge trapping nets with other nets.
1586 if (item1.is_type(OBJ_MISSILES, MI_THROWING_NET)
1587 && item1.net_placed != item2.net_placed)
1588 {
1589 return false;
1590 }
1591
1592 #define NO_MERGE_FLAGS (ISFLAG_MIMIC | ISFLAG_SUMMONED)
1593 if ((item1.flags & NO_MERGE_FLAGS) != (item2.flags & NO_MERGE_FLAGS))
1594 return false;
1595
1596 // The inscriptions can differ if one of them is blank, but if they
1597 // are differing non-blank inscriptions then don't stack.
1598 if (item1.inscription != item2.inscription
1599 && !item1.inscription.empty() && !item2.inscription.empty())
1600 {
1601 return false;
1602 }
1603
1604 return true;
1605 }
1606
items_stack(const item_def & item1,const item_def & item2)1607 bool items_stack(const item_def &item1, const item_def &item2)
1608 {
1609 // Both items must be stackable.
1610 if (!is_stackable_item(item1) || !is_stackable_item(item2)
1611 || static_cast<long long>(item1.quantity) + item2.quantity
1612 > numeric_limits<decltype(item1.quantity)>::max())
1613 {
1614 return false;
1615 }
1616
1617 return items_similar(item1, item2)
1618 // Don't leak information when checking if an "(unknown)" shop item
1619 // matches an unidentified item in inventory.
1620 && fully_identified(item1) == fully_identified(item2);
1621 }
1622
_userdef_find_free_slot(const item_def & i)1623 static int _userdef_find_free_slot(const item_def &i)
1624 {
1625 int slot = -1;
1626 if (!clua.callfn("c_assign_invletter", "i>d", &i, &slot))
1627 return -1;
1628
1629 return slot;
1630 }
1631
find_free_slot(const item_def & i)1632 int find_free_slot(const item_def &i)
1633 {
1634 #define slotisfree(s) \
1635 ((s) >= 0 && (s) < ENDOFPACK && !you.inv[s].defined())
1636
1637 bool searchforward = false;
1638 // If we're doing Lua, see if there's a Lua function that can give
1639 // us a free slot.
1640 int slot = _userdef_find_free_slot(i);
1641 if (slot == -2 || Options.assign_item_slot == SS_FORWARD)
1642 searchforward = true;
1643
1644 if (slotisfree(slot))
1645 return slot;
1646
1647 // See if the item remembers where it's been. Lua code can play with
1648 // this field so be extra careful.
1649 if (isaalpha(i.slot))
1650 slot = letter_to_index(i.slot);
1651
1652 if (slotisfree(slot))
1653 return slot;
1654
1655 FixedBitVector<ENDOFPACK> disliked;
1656 if (i.base_type == OBJ_POTIONS)
1657 disliked.set('y' - 'a');
1658
1659 if (!searchforward)
1660 {
1661 // This is the new default free slot search. We look for the last
1662 // available slot that does not leave a gap in the inventory.
1663 for (slot = ENDOFPACK - 1; slot >= 0; --slot)
1664 {
1665 if (you.inv[slot].defined())
1666 {
1667 if (slot + 1 < ENDOFPACK && !you.inv[slot + 1].defined()
1668 && !disliked[slot + 1])
1669 {
1670 return slot + 1;
1671 }
1672 }
1673 else
1674 {
1675 if (slot + 1 < ENDOFPACK && you.inv[slot + 1].defined()
1676 && !disliked[slot])
1677 {
1678 return slot;
1679 }
1680 }
1681 }
1682 }
1683
1684 // Either searchforward is true, or search backwards failed and
1685 // we re-try searching the opposite direction.
1686
1687 int badslot = -1;
1688 // Return first free slot
1689 for (slot = 0; slot < ENDOFPACK; ++slot)
1690 if (!you.inv[slot].defined())
1691 {
1692 if (disliked[slot])
1693 badslot = slot;
1694 else
1695 return slot;
1696 }
1697
1698 // If the least preferred slot is the only choice, so be it.
1699 return badslot;
1700 #undef slotisfree
1701 }
1702
_got_item(item_def & item)1703 static void _got_item(item_def& item)
1704 {
1705 seen_item(item);
1706 shopping_list.cull_identical_items(item);
1707 item.flags |= ISFLAG_HANDLED;
1708
1709 if (item.props.exists("needs_autopickup"))
1710 item.props.erase("needs_autopickup");
1711 }
1712
get_gold(const item_def & item,int quant,bool quiet)1713 void get_gold(const item_def& item, int quant, bool quiet)
1714 {
1715 you.attribute[ATTR_GOLD_FOUND] += quant;
1716
1717 if (you_worship(GOD_ZIN))
1718 quant -= zin_tithe(item, quant, quiet);
1719 if (quant <= 0)
1720 return;
1721 you.add_gold(quant);
1722
1723 if (!quiet)
1724 {
1725 const string gain = quant != you.gold
1726 ? make_stringf(" (gained %d)", quant)
1727 : "";
1728
1729 mprf("You now have %d gold piece%s%s.",
1730 you.gold, you.gold != 1 ? "s" : "", gain.c_str());
1731 learned_something_new(HINT_SEEN_GOLD);
1732 }
1733 }
1734
note_inscribe_item(item_def & item)1735 void note_inscribe_item(item_def &item)
1736 {
1737 _autoinscribe_item(item);
1738 _origin_freeze(item);
1739 _check_note_item(item);
1740 }
1741
_put_item_in_inv(item_def & it,int quant_got,bool quiet,bool & put_in_inv)1742 static bool _put_item_in_inv(item_def& it, int quant_got, bool quiet, bool& put_in_inv)
1743 {
1744 put_in_inv = false;
1745 if (item_is_stationary(it))
1746 {
1747 if (!quiet)
1748 mpr("You can't pick that up.");
1749 // Fake a successful pickup (return 1), so we can continue to
1750 // pick up anything else that might be on this square.
1751 return true;
1752 }
1753
1754 // sanity
1755 if (quant_got > it.quantity || quant_got <= 0)
1756 quant_got = it.quantity;
1757
1758 // attempt to put the item into your inventory.
1759 int inv_slot;
1760 if (_merge_items_into_inv(it, quant_got, inv_slot, quiet))
1761 {
1762 put_in_inv = true;
1763
1764 // cleanup items that ended up in an inventory slot (not gold, etc)
1765 if (inv_slot != -1)
1766 _got_item(you.inv[inv_slot]);
1767 else if (it.base_type == OBJ_BOOKS)
1768 _got_item(it);
1769 _check_note_item(inv_slot == -1 ? it : you.inv[inv_slot]);
1770 return true;
1771 }
1772
1773 return false;
1774 }
1775
1776
1777 // Currently only used for moving shop items into inventory, since they are
1778 // not in env.item. This doesn't work with partial pickup, because that requires
1779 // an env.item slot...
move_item_to_inv(item_def & item)1780 bool move_item_to_inv(item_def& item)
1781 {
1782 bool junk;
1783 return _put_item_in_inv(item, item.quantity, false, junk);
1784 }
1785
1786 /**
1787 * Move the given item and quantity to the player's inventory.
1788 *
1789 * @param obj The item index in env.item.
1790 * @param quant_got The quantity of this item to move.
1791 * @param quiet If true, most messages notifying the player of item pickup (or
1792 * item pickup failure) aren't printed.
1793 * @returns false if items failed to be picked up because of a full inventory,
1794 * true otherwise (even if nothing was picked up).
1795 */
move_item_to_inv(int obj,int quant_got,bool quiet)1796 bool move_item_to_inv(int obj, int quant_got, bool quiet)
1797 {
1798 item_def &it = env.item[obj];
1799 const coord_def old_item_pos = it.pos;
1800
1801 bool actually_went_in = false;
1802 const bool keep_going = _put_item_in_inv(it, quant_got, quiet, actually_went_in);
1803
1804 if ((it.base_type == OBJ_RUNES || item_is_orb(it) || in_bounds(old_item_pos))
1805 && actually_went_in)
1806 {
1807 dungeon_events.fire_position_event(dgn_event(DET_ITEM_PICKUP,
1808 you.pos(), 0, obj,
1809 -1),
1810 you.pos());
1811
1812 // XXX: Waiting until now to decrement the quantity may give Windows
1813 // tiles players the opportunity to close the window and duplicate the
1814 // item (a variant of bug #6486). However, we can't decrement the
1815 // quantity before firing the position event, because the latter needs
1816 // the object's index.
1817 dec_mitm_item_quantity(obj, quant_got);
1818
1819 you.turn_is_over = true;
1820 }
1821
1822 return keep_going;
1823 }
1824
_get_book(item_def & it)1825 static void _get_book(item_def& it)
1826 {
1827 if (it.sub_type != BOOK_MANUAL)
1828 {
1829 if (you.has_mutation(MUT_INNATE_CASTER))
1830 {
1831 mprf("%s burns to shimmering ash in your grasp.",
1832 it.name(DESC_THE).c_str());
1833 return;
1834 }
1835 mprf("You pick up %s and begin reading...", it.name(DESC_A).c_str());
1836
1837 if (!library_add_spells(spells_in_book(it)))
1838 mpr("Unfortunately, you learned nothing new.");
1839
1840 taken_new_item(it.base_type);
1841
1842 return;
1843 }
1844 // This is mainly for save compat: if a manual generated somehow that is not
1845 // id'd, the following message is completely useless
1846 set_ident_flags(it, ISFLAG_IDENT_MASK);
1847 const skill_type sk = static_cast<skill_type>(it.plus);
1848
1849 if (is_useless_skill(sk))
1850 {
1851 mprf("You pick up %s. Unfortunately, it's quite useless to you.",
1852 it.name(DESC_A).c_str());
1853 return;
1854 }
1855
1856 if (you.skills[sk] >= MAX_SKILL_LEVEL)
1857 {
1858 mprf("You pick up %s, but it has nothing more to teach you.",
1859 it.name(DESC_A).c_str());
1860 return;
1861 }
1862
1863 if (you.skill_manual_points[sk])
1864 mprf("You pick up another %s and continue studying.", it.name(DESC_PLAIN).c_str());
1865 else
1866 mprf("You pick up %s and begin studying.", it.name(DESC_A).c_str());
1867 you.skill_manual_points[sk] += it.skill_points;
1868 you.skills_to_show.insert(sk);
1869 }
1870
1871 // Adds all books in the player's inventory to library.
1872 // Declared here for use by tags to load old saves.
add_held_books_to_library()1873 void add_held_books_to_library()
1874 {
1875 for (item_def& it : you.inv)
1876 {
1877 if (it.base_type == OBJ_BOOKS)
1878 {
1879 _get_book(it);
1880 destroy_item(it);
1881 }
1882 }
1883 }
1884
1885 /**
1886 * Place a rune into the player's inventory.
1887 *
1888 * @param it The item (rune) to pick up.
1889 * @param quiet Whether to suppress (most?) messages.
1890 */
_get_rune(const item_def & it,bool quiet)1891 static void _get_rune(const item_def& it, bool quiet)
1892 {
1893 if (!you.runes[it.sub_type])
1894 you.runes.set(it.sub_type);
1895
1896 if (!quiet)
1897 {
1898 flash_view_delay(UA_PICKUP, rune_colour(it.sub_type), 300);
1899 mprf("You pick up the %s rune and feel its power.",
1900 rune_type_name(it.sub_type));
1901 int nrunes = runes_in_pack();
1902 if (nrunes >= you.obtainable_runes)
1903 mpr("You have collected all the runes! Now go and win!");
1904 else if (nrunes == ZOT_ENTRY_RUNES)
1905 {
1906 // might be inappropriate in new Sprints, please change it then
1907 mprf("%d runes! That's enough to enter the realm of Zot.",
1908 nrunes);
1909 }
1910 else if (nrunes > 1)
1911 mprf("You now have %d runes.", nrunes);
1912
1913 mpr("Press } to see all the runes you have collected.");
1914 }
1915
1916 if (it.sub_type == RUNE_ABYSSAL)
1917 mpr("You feel the abyssal rune guiding you out of this place.");
1918 }
1919
1920 /**
1921 * Place the Orb of Zot into the player's inventory.
1922 */
_get_orb()1923 static void _get_orb()
1924 {
1925 run_animation(ANIMATION_ORB, UA_PICKUP);
1926
1927 mprf(MSGCH_ORB, "You pick up the Orb of Zot!");
1928
1929 if (bezotted())
1930 mpr("Zot can harm you no longer.");
1931
1932 env.orb_pos = you.pos(); // can be wrong in wizmode
1933 orb_pickup_noise(you.pos(), 30);
1934
1935 start_orb_run(CHAPTER_ESCAPING, "Now all you have to do is get back out "
1936 "of the dungeon!");
1937 }
1938
1939 /**
1940 * Attempt to merge a stackable item into an existing stack in the player's
1941 * inventory.
1942 *
1943 * @param it[in] The stack to merge.
1944 * @param quant_got The quantity of this item to place.
1945 * @param inv_slot[out] The inventory slot the item was placed in. -1 if
1946 * not placed.
1947 * @param quiet Whether to suppress pickup messages.
1948 */
_merge_stackable_item_into_inv(const item_def & it,int quant_got,int & inv_slot,bool quiet)1949 static bool _merge_stackable_item_into_inv(const item_def &it, int quant_got,
1950 int &inv_slot, bool quiet)
1951 {
1952 for (inv_slot = 0; inv_slot < ENDOFPACK; inv_slot++)
1953 {
1954 if (!items_stack(you.inv[inv_slot], it))
1955 continue;
1956
1957 // If the object on the ground is inscribed, but not
1958 // the one in inventory, then the inventory object
1959 // picks up the other's inscription.
1960 if (!(it.inscription).empty()
1961 && you.inv[inv_slot].inscription.empty())
1962 {
1963 you.inv[inv_slot].inscription = it.inscription;
1964 }
1965
1966 inc_inv_item_quantity(inv_slot, quant_got);
1967 you.last_pickup[inv_slot] = quant_got;
1968
1969 if (!quiet)
1970 {
1971 #ifdef USE_SOUND
1972 parse_sound(PICKUP_SOUND);
1973 #endif
1974 mprf_nocap("%s (gained %d)",
1975 menu_colour_item_name(you.inv[inv_slot],
1976 DESC_INVENTORY).c_str(),
1977 quant_got);
1978 }
1979 auto_assign_item_slot(you.inv[inv_slot]);
1980
1981 return true;
1982 }
1983
1984 inv_slot = -1;
1985 return false;
1986 }
1987
1988 /**
1989 * Attempt to merge a wands charges into an existing wand of the same type in
1990 * inventory.
1991 *
1992 * @param it[in] The wand to merge.
1993 * @param inv_slot[out] The inventory slot the wand was placed in. -1 if
1994 * not placed.
1995 * @param quiet Whether to suppress pickup messages.
1996 */
_merge_wand_charges(const item_def & it,int & inv_slot,bool quiet)1997 static bool _merge_wand_charges(const item_def &it, int &inv_slot, bool quiet)
1998 {
1999 for (inv_slot = 0; inv_slot < ENDOFPACK; inv_slot++)
2000 {
2001 if (you.inv[inv_slot].base_type != OBJ_WANDS
2002 || you.inv[inv_slot].sub_type != it.sub_type)
2003 {
2004 continue;
2005 }
2006
2007 you.inv[inv_slot].charges += it.charges;
2008
2009 if (!quiet)
2010 {
2011 #ifdef USE_SOUND
2012 parse_sound(PICKUP_SOUND);
2013 #endif
2014 mprf_nocap("%s (gained %d charge%s)",
2015 menu_colour_item_name(you.inv[inv_slot],
2016 DESC_INVENTORY).c_str(),
2017 it.charges, it.charges == 1 ? "" : "s");
2018 }
2019
2020 return true;
2021 }
2022
2023 inv_slot = -1;
2024 return false;
2025 }
2026
2027 /**
2028 * Maybe move an item to the slot given by the item_slot option.
2029 *
2030 * @param[in] item the item to be checked. Note that any references to this
2031 * item will be invalidated by the swap_inv_slots call!
2032 * @returns the new location of the item if it was moved, null otherwise.
2033 */
auto_assign_item_slot(item_def & item)2034 item_def *auto_assign_item_slot(item_def& item)
2035 {
2036 if (!item.defined())
2037 return nullptr;
2038 if (!in_inventory(item))
2039 return nullptr;
2040
2041 int newslot = -1;
2042 bool overwrite = true;
2043 // check to see whether we've chosen an automatic label:
2044 for (auto& mapping : Options.auto_item_letters)
2045 {
2046 if (!mapping.first.matches(item.name(DESC_QUALNAME))
2047 && !mapping.first.matches(item_prefix(item)
2048 + " " + item.name(DESC_A)))
2049 {
2050 continue;
2051 }
2052 for (char i : mapping.second)
2053 {
2054 if (i == '+')
2055 overwrite = true;
2056 else if (i == '-')
2057 overwrite = false;
2058 else if (isaalpha(i))
2059 {
2060 const int index = letter_to_index(i);
2061 auto &iitem = you.inv[index];
2062
2063 // Slot is empty, or overwrite is on and the rule doesn't
2064 // match the item already there.
2065 if (!iitem.defined()
2066 || overwrite
2067 && !mapping.first.matches(iitem.name(DESC_QUALNAME))
2068 && !mapping.first.matches(item_prefix(iitem)
2069 + " " + iitem.name(DESC_A)))
2070 {
2071 newslot = index;
2072 break;
2073 }
2074 }
2075 }
2076 if (newslot != -1 && newslot != item.link)
2077 {
2078 swap_inv_slots(item.link, newslot, you.num_turns);
2079 return &you.inv[newslot];
2080 }
2081 }
2082 return nullptr;
2083 }
2084
2085 /**
2086 * Move the given item and quantity to a free slot in the player's inventory.
2087 * If the item_slot option tells us to put it in a specific slot, it will move
2088 * there and push out the item that was in it before instead.
2089 *
2090 * @param it[in] The item to be placed into the player's inventory.
2091 * @param quant_got The quantity of this item to place.
2092 * @param quiet Suppresses pickup messages.
2093 * @return The inventory slot the item was placed in.
2094 */
_place_item_in_free_slot(item_def & it,int quant_got,bool quiet)2095 static int _place_item_in_free_slot(item_def &it, int quant_got,
2096 bool quiet)
2097 {
2098 int freeslot = find_free_slot(it);
2099 ASSERT_RANGE(freeslot, 0, ENDOFPACK);
2100 ASSERT(!you.inv[freeslot].defined());
2101
2102 item_def &item = you.inv[freeslot];
2103 // Copy item.
2104 item = it;
2105 item.link = freeslot;
2106 item.quantity = quant_got;
2107 item.slot = index_to_letter(item.link);
2108 item.pos = ITEM_IN_INVENTORY;
2109 // Remove "unobtainable" as it was just proven false.
2110 item.flags &= ~ISFLAG_UNOBTAINABLE;
2111
2112 god_id_item(item);
2113 if (item.base_type == OBJ_WANDS)
2114 {
2115 set_ident_type(item, true);
2116 set_ident_flags(item, ISFLAG_KNOW_PLUSES);
2117 }
2118
2119 maybe_identify_base_type(item);
2120 if (item.base_type == OBJ_BOOKS)
2121 set_ident_flags(item, ISFLAG_IDENT_MASK);
2122
2123 note_inscribe_item(item);
2124
2125 if (crawl_state.game_is_hints())
2126 {
2127 taken_new_item(item.base_type);
2128 if (is_artefact(item))
2129 learned_something_new(HINT_SEEN_RANDART);
2130 }
2131
2132 you.last_pickup[item.link] = quant_got;
2133 quiver::on_actions_changed(true);
2134 item_skills(item, you.skills_to_show);
2135
2136 if (const item_def* newitem = auto_assign_item_slot(item))
2137 return newitem->link;
2138 else if (!quiet)
2139 {
2140 #ifdef USE_SOUND
2141 parse_sound(PICKUP_SOUND);
2142 #endif
2143 mprf_nocap("%s", menu_colour_item_name(item, DESC_INVENTORY).c_str());
2144 }
2145
2146 return item.link;
2147 }
2148
2149 /**
2150 * Move the given item and quantity to the player's inventory.
2151 * DOES NOT change the original item; the caller must handle any cleanup!
2152 *
2153 * @param it[in] The item to be placed into the player's inventory.
2154 * @param quant_got The quantity of this item to place.
2155 * @param inv_slot[out] The inventory slot the item was placed in. -1 if
2156 * not placed.
2157 * @param quiet If true, most messages notifying the player of item pickup (or
2158 * item pickup failure) aren't printed.
2159 * @return Whether something was successfully picked up.
2160 */
_merge_items_into_inv(item_def & it,int quant_got,int & inv_slot,bool quiet)2161 static bool _merge_items_into_inv(item_def &it, int quant_got,
2162 int &inv_slot, bool quiet)
2163 {
2164 inv_slot = -1;
2165
2166 // sanity
2167 if (quant_got > it.quantity || quant_got <= 0)
2168 quant_got = it.quantity;
2169
2170 // Gold has no mass, so we handle it first.
2171 if (it.base_type == OBJ_GOLD)
2172 {
2173 get_gold(it, quant_got, quiet);
2174 return true;
2175 }
2176 if (it.base_type == OBJ_BOOKS)
2177 {
2178 _get_book(it);
2179 return true;
2180 }
2181 // Runes are also massless.
2182 if (it.base_type == OBJ_RUNES)
2183 {
2184 _get_rune(it, quiet);
2185 return true;
2186 }
2187 // The Orb is also handled specially.
2188 if (item_is_orb(it))
2189 {
2190 _get_orb();
2191 return true;
2192 }
2193
2194 // attempt to merge into an existing stack, if possible
2195 if (is_stackable_item(it)
2196 && _merge_stackable_item_into_inv(it, quant_got, inv_slot, quiet))
2197 {
2198 return true;
2199 }
2200
2201 // attempt to merge into an existing stack, if possible
2202 if (it.base_type == OBJ_WANDS
2203 && _merge_wand_charges(it, inv_slot, quiet))
2204 {
2205 quant_got = 1;
2206 return true;
2207 }
2208
2209 // Can't combine, check for slot space.
2210 if (inv_count() >= ENDOFPACK)
2211 return false;
2212
2213 inv_slot = _place_item_in_free_slot(it, quant_got, quiet);
2214 return true;
2215 }
2216
mark_items_non_pickup_at(const coord_def & pos)2217 void mark_items_non_pickup_at(const coord_def &pos)
2218 {
2219 int item = env.igrid(pos);
2220 while (item != NON_ITEM)
2221 {
2222 env.item[item].flags |= ISFLAG_DROPPED;
2223 env.item[item].flags &= ~ISFLAG_THROWN;
2224 item = env.item[item].link;
2225 }
2226 }
2227
clear_item_pickup_flags(item_def & item)2228 void clear_item_pickup_flags(item_def &item)
2229 {
2230 item.flags &= ~(ISFLAG_THROWN | ISFLAG_DROPPED | ISFLAG_NO_PICKUP);
2231 }
2232
2233 // Move gold to the the top of a pile if following Gozag.
_gozag_move_gold_to_top(const coord_def p)2234 static void _gozag_move_gold_to_top(const coord_def p)
2235 {
2236 if (have_passive(passive_t::detect_gold))
2237 {
2238 for (int gold = env.igrid(p); gold != NON_ITEM;
2239 gold = env.item[gold].link)
2240 {
2241 if (env.item[gold].base_type == OBJ_GOLD)
2242 {
2243 unlink_item(gold);
2244 move_item_to_grid(&gold, p, true);
2245 break;
2246 }
2247 }
2248 }
2249 }
2250
2251 // Moves env.item[obj] to p... will modify the value of obj to
2252 // be the index of the final object (possibly different).
2253 //
2254 // Done this way in the hopes that it will be obvious from
2255 // calling code that "obj" is possibly modified.
2256 //
2257 // Returns false on error or level full - cases where you
2258 // keep the item.
move_item_to_grid(int * const obj,const coord_def & p,bool silent)2259 bool move_item_to_grid(int *const obj, const coord_def& p, bool silent)
2260 {
2261 ASSERT_IN_BOUNDS(p);
2262
2263 int& ob(*obj);
2264
2265 // Must be a valid reference to a valid object.
2266 if (ob == NON_ITEM || !env.item[ob].defined())
2267 return false;
2268
2269 item_def& item(env.item[ob]);
2270 bool move_below = item_is_stationary(item) && !item_is_stationary_net(item);
2271
2272 if (!silenced(p) && !silent)
2273 feat_splash_noise(env.grid(p));
2274
2275 if (feat_destroys_items(env.grid(p)))
2276 {
2277 item_was_destroyed(item);
2278 destroy_item(ob);
2279 ob = NON_ITEM;
2280
2281 return true;
2282 }
2283
2284 // If it's a stackable type or stationary item that's not a net...
2285 int movable_ind = -1;
2286 if (move_below || is_stackable_item(item))
2287 {
2288 // Look for similar item to stack:
2289 for (stack_iterator si(p); si; ++si)
2290 {
2291 // Check if item already linked here -- don't want to unlink it.
2292 if (ob == si->index())
2293 return false;
2294
2295 if (items_stack(item, *si))
2296 {
2297 // Add quantity to item already here, and dispose
2298 // of obj, while returning the found item. -- bwr
2299 inc_mitm_item_quantity(si->index(), item.quantity);
2300 destroy_item(ob);
2301 ob = si->index();
2302 _gozag_move_gold_to_top(p);
2303 if (you.see_cell(p))
2304 {
2305 // XXX: Is it actually necessary to identify when the
2306 // new item merged with a stack?
2307 god_id_item(*si);
2308 maybe_identify_base_type(*si);
2309 }
2310 return true;
2311 }
2312 if (move_below
2313 && (!item_is_stationary(*si) || item_is_stationary_net(*si)))
2314 {
2315 movable_ind = si->index();
2316 }
2317 }
2318 }
2319 else
2320 ASSERT(item.quantity == 1);
2321
2322 ASSERT(ob != NON_ITEM);
2323
2324 // Need to actually move object, so first unlink from old position.
2325 unlink_item(ob);
2326
2327 // Move item to coord.
2328 item.pos = p;
2329
2330 // Need to move this stationary item to the position in the pile
2331 // below the lowest non-stationary, non-net item.
2332 if (move_below && movable_ind >= 0)
2333 {
2334 item.link = env.item[movable_ind].link;
2335 env.item[movable_ind].link = item.index();
2336 }
2337 // Movable item or no movable items in pile, link item to top of list.
2338 else
2339 {
2340 item.link = env.igrid(p);
2341 env.igrid(p) = ob;
2342 }
2343
2344 if (item_is_orb(item))
2345 env.orb_pos = p;
2346
2347 if (item.base_type != OBJ_GOLD)
2348 _gozag_move_gold_to_top(p);
2349
2350 if (you.see_cell(p))
2351 {
2352 god_id_item(item);
2353 maybe_identify_base_type(item);
2354 }
2355
2356 if (p == you.pos() && _id_floor_item(item))
2357 mprf("You see here %s.", item.name(DESC_A).c_str());
2358
2359 return true;
2360 }
2361
move_item_stack_to_grid(const coord_def & from,const coord_def & to)2362 void move_item_stack_to_grid(const coord_def& from, const coord_def& to)
2363 {
2364 if (env.igrid(from) == NON_ITEM)
2365 return;
2366
2367 // Tell all items in stack what the new coordinate is.
2368 for (stack_iterator si(from); si; ++si)
2369 {
2370 si->pos = to;
2371
2372 // Link last of the stack to the top of the old stack.
2373 if (si->link == NON_ITEM && env.igrid(to) != NON_ITEM)
2374 {
2375 si->link = env.igrid(to);
2376 break;
2377 }
2378 }
2379
2380 env.igrid(to) = env.igrid(from);
2381 env.igrid(from) = NON_ITEM;
2382 }
2383
2384 // Returns false if no items could be dropped.
copy_item_to_grid(item_def & item,const coord_def & p,int quant_drop,bool mark_dropped,bool silent)2385 bool copy_item_to_grid(item_def &item, const coord_def& p,
2386 int quant_drop, bool mark_dropped, bool silent)
2387 {
2388 ASSERT_IN_BOUNDS(p);
2389
2390 if (quant_drop == 0)
2391 return false;
2392
2393 if (!silenced(p) && !silent)
2394 feat_splash_noise(env.grid(p));
2395
2396 if (feat_destroys_items(env.grid(p)))
2397 {
2398 item_was_destroyed(item);
2399 return true;
2400 }
2401
2402 // default quant_drop == -1 => drop all
2403 if (quant_drop < 0)
2404 quant_drop = item.quantity;
2405
2406 // Loop through items at current location.
2407 if (is_stackable_item(item))
2408 {
2409 for (stack_iterator si(p); si; ++si)
2410 {
2411 if (items_stack(item, *si))
2412 {
2413 item_def copy = item;
2414 inc_mitm_item_quantity(si->index(), quant_drop);
2415
2416 if (mark_dropped)
2417 {
2418 // If the items on the floor already have a nonzero slot,
2419 // leave it as such, otherwise set the slot.
2420 if (!si->slot)
2421 si->slot = index_to_letter(item.link);
2422
2423 si->flags |= ISFLAG_DROPPED;
2424 si->flags &= ~ISFLAG_THROWN;
2425 }
2426 return true;
2427 }
2428 }
2429 }
2430
2431 // Item not found in current stack, add new item to top.
2432 int new_item_idx = get_mitm_slot(10);
2433 if (new_item_idx == NON_ITEM)
2434 return false;
2435 item_def& new_item = env.item[new_item_idx];
2436
2437 // Copy item.
2438 new_item = item;
2439
2440 // Set quantity, and set the item as unlinked.
2441 new_item.quantity = quant_drop;
2442 new_item.pos.reset();
2443 new_item.link = NON_ITEM;
2444
2445 if (mark_dropped)
2446 {
2447 new_item.slot = index_to_letter(item.link);
2448 new_item.flags |= ISFLAG_DROPPED;
2449 new_item.flags &= ~ISFLAG_THROWN;
2450 origin_set_unknown(new_item);
2451 }
2452
2453 move_item_to_grid(&new_item_idx, p, true);
2454
2455 return true;
2456 }
2457
item_pos(const item_def & item)2458 coord_def item_pos(const item_def &item)
2459 {
2460 coord_def pos = item.pos;
2461 if (pos == ITEM_IN_MONSTER_INVENTORY)
2462 {
2463 if (const monster *mon = item.holding_monster())
2464 pos = mon->pos();
2465 else
2466 die("item held by an invalid monster");
2467 }
2468 else if (pos == ITEM_IN_INVENTORY)
2469 pos = you.pos();
2470 return pos;
2471 }
2472
2473 /**
2474 * Move the top item of a stack to a new location.
2475 *
2476 * @param pos the location of the stack
2477 * @param dest the position to be moved to
2478 * @return whether there were any items at pos to be moved.
2479 */
move_top_item(const coord_def & pos,const coord_def & dest)2480 bool move_top_item(const coord_def &pos, const coord_def &dest)
2481 {
2482 int item = env.igrid(pos);
2483 if (item == NON_ITEM)
2484 return false;
2485
2486 dungeon_events.fire_position_event(
2487 dgn_event(DET_ITEM_MOVED, pos, 0, item, -1, dest), pos);
2488
2489 // Now move the item to its new position...
2490 move_item_to_grid(&item, dest);
2491
2492 return true;
2493 }
2494
top_item_at(const coord_def & where)2495 const item_def* top_item_at(const coord_def& where)
2496 {
2497 const int link = you.visible_igrd(where);
2498 return (link == NON_ITEM) ? nullptr : &env.item[link];
2499 }
2500
multiple_items_at(const coord_def & where)2501 bool multiple_items_at(const coord_def& where)
2502 {
2503 int found_count = 0;
2504
2505 for (stack_iterator si(where); si && found_count < 2; ++si)
2506 ++found_count;
2507
2508 return found_count > 1;
2509 }
2510
2511 /**
2512 * Drop an item, possibly starting up a delay to do so.
2513 *
2514 * @param item_dropped the inventory index of the item to drop
2515 * @param quant_drop the number of items to drop, -1 to drop the whole stack.
2516 *
2517 * @return True if we took time, either because we dropped the item
2518 * or because we took a preliminary step (removing a ring, etc.).
2519 */
drop_item(int item_dropped,int quant_drop)2520 bool drop_item(int item_dropped, int quant_drop)
2521 {
2522 item_def &item = you.inv[item_dropped];
2523
2524 if (quant_drop < 0 || quant_drop > item.quantity)
2525 quant_drop = item.quantity;
2526
2527 if (item_dropped == you.equip[EQ_LEFT_RING]
2528 || item_dropped == you.equip[EQ_RIGHT_RING]
2529 || item_dropped == you.equip[EQ_AMULET]
2530 || item_dropped == you.equip[EQ_RING_ONE]
2531 || item_dropped == you.equip[EQ_RING_TWO]
2532 || item_dropped == you.equip[EQ_RING_THREE]
2533 || item_dropped == you.equip[EQ_RING_FOUR]
2534 || item_dropped == you.equip[EQ_RING_FIVE]
2535 || item_dropped == you.equip[EQ_RING_SIX]
2536 || item_dropped == you.equip[EQ_RING_SEVEN]
2537 || item_dropped == you.equip[EQ_RING_EIGHT]
2538 || item_dropped == you.equip[EQ_RING_AMULET])
2539 {
2540 if (!Options.easy_unequip)
2541 mpr("You will have to take that off first.");
2542 else if (remove_ring(item_dropped, true))
2543 {
2544 // The delay handles the case where the item disappeared.
2545 start_delay<DropItemDelay>(1, item);
2546 // We didn't actually succeed yet, but remove_ring took time,
2547 // so return true anyway.
2548 return true;
2549 }
2550
2551 return false;
2552 }
2553
2554 if (item_dropped == you.equip[EQ_WEAPON]
2555 && item.base_type == OBJ_WEAPONS && item.cursed())
2556 {
2557 mprf("%s is stuck to you!", item.name(DESC_THE).c_str());
2558 return false;
2559 }
2560
2561 for (int i = EQ_MIN_ARMOUR; i <= EQ_MAX_ARMOUR; i++)
2562 {
2563 if (item_dropped == you.equip[i] && you.equip[i] != -1)
2564 {
2565 if (!Options.easy_unequip)
2566 mpr("You will have to take that off first.");
2567 else if (check_warning_inscriptions(item, OPER_TAKEOFF))
2568 {
2569 // If we take off the item, cue up the item being dropped
2570 if (takeoff_armour(item_dropped))
2571 {
2572 // The delay handles the case where the item disappeared.
2573 start_delay<DropItemDelay>(1, item);
2574 // We didn't actually succeed yet, but takeoff_armour
2575 // took a turn to start up, so return true anyway.
2576 return true;
2577 }
2578 }
2579 return false;
2580 }
2581 }
2582
2583 // [ds] easy_unequip does not apply to weapons.
2584 //
2585 // Unwield needs to be done before copy in order to clear things
2586 // like temporary brands. -- bwr
2587 if (item_dropped == you.equip[EQ_WEAPON] && quant_drop >= item.quantity)
2588 {
2589 if (!wield_weapon(true, SLOT_BARE_HANDS, true, true, true, false))
2590 return false;
2591 // May have been destroyed by removal. Returning true because we took
2592 // time to swap away.
2593 else if (!item.defined())
2594 return true;
2595 }
2596
2597 ASSERT(item.defined());
2598
2599 if (!copy_item_to_grid(item, you.pos(), quant_drop, true, true))
2600 {
2601 mpr("Too many items on this level, not dropping the item.");
2602 return false;
2603 }
2604
2605 mprf("You drop %s.", quant_name(item, quant_drop, DESC_A).c_str());
2606
2607 // If you drop an item in as a merfolk, it is below the water line and
2608 // makes no noise falling.
2609 if (!you.swimming())
2610 feat_splash_noise(env.grid(you.pos()));
2611
2612 dec_inv_item_quantity(item_dropped, quant_drop);
2613
2614 you.turn_is_over = true;
2615
2616 you.last_pickup.erase(item_dropped);
2617 if (you.last_unequip == item.link)
2618 you.last_unequip = -1;
2619
2620 return true;
2621 }
2622
drop_last()2623 void drop_last()
2624 {
2625 vector<SelItem> items_to_drop;
2626
2627 for (const auto &entry : you.last_pickup)
2628 {
2629 const item_def* item = &you.inv[entry.first];
2630 if (item->quantity > 0)
2631 items_to_drop.emplace_back(entry.first, entry.second, item);
2632 }
2633
2634 if (items_to_drop.empty())
2635 mpr("No item to drop.");
2636 else
2637 {
2638 you.last_pickup.clear();
2639 _multidrop(items_to_drop);
2640 }
2641 }
2642
2643 /** Get the equipment slot an item is equipped in. If the item is not
2644 * equipped by the player, return -1 instead.
2645 *
2646 * @param item The item to check.
2647 *
2648 * @returns The equipment slot (equipment_type) the item is in or -1
2649 * (EQ_NONE)
2650 */
get_equip_slot(const item_def * item)2651 int get_equip_slot(const item_def *item)
2652 {
2653 int worn = -1;
2654 if (item && in_inventory(*item))
2655 {
2656 for (int i = EQ_FIRST_EQUIP; i < NUM_EQUIP; ++i)
2657 {
2658 if (you.equip[i] == item->link)
2659 {
2660 worn = i;
2661 break;
2662 }
2663 }
2664 }
2665 return worn;
2666 }
2667
get_mon_equip_slot(const monster * mon,const item_def & item)2668 mon_inv_type get_mon_equip_slot(const monster* mon, const item_def &item)
2669 {
2670 ASSERT(mon->alive());
2671
2672 mon_inv_type slot = item_to_mslot(item);
2673
2674 if (slot == NUM_MONSTER_SLOTS)
2675 return NUM_MONSTER_SLOTS;
2676
2677 if (mon->mslot_item(slot) == &item)
2678 return slot;
2679
2680 if (slot == MSLOT_WEAPON && mon->mslot_item(MSLOT_ALT_WEAPON) == &item)
2681 return MSLOT_ALT_WEAPON;
2682
2683 return NUM_MONSTER_SLOTS;
2684 }
2685
2686 // This has to be of static storage class, so that the value isn't lost when a
2687 // MultidropDelay is interrupted.
2688 static vector<SelItem> items_for_multidrop;
2689
2690 // Arrange items that have been selected for multidrop so that
2691 // equipped items are dropped after other items, and equipped items
2692 // are dropped in the same order as their EQ_ slots are numbered.
_drop_item_order(const SelItem & first,const SelItem & second)2693 static bool _drop_item_order(const SelItem &first, const SelItem &second)
2694 {
2695 const item_def &i1 = you.inv[first.slot];
2696 const item_def &i2 = you.inv[second.slot];
2697
2698 const int slot1 = get_equip_slot(&i1),
2699 slot2 = get_equip_slot(&i2);
2700
2701 if (slot1 != -1 && slot2 != -1)
2702 return slot1 < slot2;
2703 else if (slot1 != -1 && slot2 == -1)
2704 return false;
2705 else if (slot2 != -1 && slot1 == -1)
2706 return true;
2707
2708 return first.slot < second.slot;
2709 }
2710
set_item_autopickup(const item_def & item,autopickup_level_type ap)2711 void set_item_autopickup(const item_def &item, autopickup_level_type ap)
2712 {
2713 you.force_autopickup[item.base_type][_autopickup_subtype(item)] = ap;
2714 }
2715
item_autopickup_level(const item_def & item)2716 int item_autopickup_level(const item_def &item)
2717 {
2718 return you.force_autopickup[item.base_type][_autopickup_subtype(item)];
2719 }
2720
_disable_autopickup_for_starred_items(vector<SelItem> & items)2721 static void _disable_autopickup_for_starred_items(vector<SelItem> &items)
2722 {
2723 int autopickup_remove_count = 0;
2724 const item_def *last_touched_item;
2725 for (SelItem &si : items)
2726 {
2727 if (si.has_star && item_autopickup_level(si.item[0]) != AP_FORCE_OFF)
2728 {
2729 last_touched_item = si.item;
2730 ++autopickup_remove_count;
2731 set_item_autopickup(*last_touched_item, AP_FORCE_OFF);
2732 }
2733 }
2734 if (autopickup_remove_count == 1)
2735 {
2736 mprf("Autopickup disabled for %s.",
2737 pluralise(last_touched_item->name(DESC_DBNAME)).c_str());
2738 }
2739 else if (autopickup_remove_count > 1)
2740 mprf("Autopickup disabled for %d items.", autopickup_remove_count);
2741 }
2742
2743 /**
2744 * Prompts the user for an item to drop.
2745 */
drop()2746 void drop()
2747 {
2748 if (inv_count() < 1 && you.gold == 0)
2749 {
2750 canned_msg(MSG_NOTHING_CARRIED);
2751 return;
2752 }
2753
2754 vector<SelItem> tmp_items;
2755
2756 tmp_items = prompt_drop_items(items_for_multidrop);
2757
2758 if (tmp_items.empty())
2759 {
2760 canned_msg(MSG_OK);
2761 return;
2762 }
2763
2764 _disable_autopickup_for_starred_items(tmp_items);
2765 _multidrop(tmp_items);
2766 }
2767
_multidrop(vector<SelItem> tmp_items)2768 static void _multidrop(vector<SelItem> tmp_items)
2769 {
2770 // Sort the dropped items so we don't see weird behaviour when
2771 // dropping a worn robe before a cloak (old behaviour: remove
2772 // cloak, remove robe, wear cloak, drop robe, remove cloak, drop
2773 // cloak).
2774 sort(tmp_items.begin(), tmp_items.end(), _drop_item_order);
2775
2776 // If the user answers "no" to an item an with a warning inscription,
2777 // then remove it from the list of items to drop by not copying it
2778 // over to items_for_multidrop.
2779 items_for_multidrop.clear();
2780 for (SelItem& si : tmp_items)
2781 {
2782 const int item_quant = si.item->quantity;
2783
2784 // EVIL HACK: Fix item quantity to match the quantity we will drop,
2785 // in order to prevent misleading messages when dropping
2786 // 15 of 25 arrows inscribed with {!d}.
2787 if (si.quantity && si.quantity != item_quant)
2788 const_cast<item_def*>(si.item)->quantity = si.quantity;
2789
2790 // Check if we can add it to the multidrop list.
2791 bool warning_ok = check_warning_inscriptions(*(si.item), OPER_DROP);
2792
2793 // Restore the item quantity if we mangled it.
2794 if (item_quant != si.item->quantity)
2795 const_cast<item_def*>(si.item)->quantity = item_quant;
2796
2797 if (warning_ok)
2798 items_for_multidrop.push_back(si);
2799 }
2800
2801 if (items_for_multidrop.empty()) // no items.
2802 {
2803 canned_msg(MSG_OK);
2804 return;
2805 }
2806
2807 if (items_for_multidrop.size() == 1) // only one item
2808 {
2809 drop_item(items_for_multidrop[0].slot, items_for_multidrop[0].quantity);
2810 items_for_multidrop.clear();
2811 }
2812 else
2813 start_delay<MultidropDelay>(items_for_multidrop.size(), items_for_multidrop);
2814 }
2815
_autoinscribe_item(item_def & item)2816 static void _autoinscribe_item(item_def& item)
2817 {
2818 // If there's an inscription already, do nothing - except
2819 // for automatically generated inscriptions
2820 if (!item.inscription.empty())
2821 return;
2822 const string old_inscription = item.inscription;
2823 item.inscription.clear();
2824
2825 string iname = _autopickup_item_name(item);
2826
2827 for (const auto &ai_entry : Options.autoinscriptions)
2828 {
2829 if (ai_entry.first.matches(iname))
2830 {
2831 // Don't autoinscribe dropped items on ground with
2832 // "=g". If the item matches a rule which adds "=g",
2833 // "=g" got added to it before it was dropped, and
2834 // then the user explicitly removed it because they
2835 // don't want to autopickup it again.
2836 string str = ai_entry.second;
2837 if ((item.flags & ISFLAG_DROPPED) && !in_inventory(item))
2838 str = replace_all(str, "=g", "");
2839
2840 // Note that this might cause the item inscription to
2841 // pass 80 characters.
2842 item.inscription += str;
2843 }
2844 }
2845 if (!old_inscription.empty())
2846 {
2847 if (item.inscription.empty())
2848 item.inscription = old_inscription;
2849 else
2850 item.inscription = old_inscription + ", " + item.inscription;
2851 }
2852 }
2853
_autoinscribe_floor_items()2854 static void _autoinscribe_floor_items()
2855 {
2856 for (stack_iterator si(you.pos()); si; ++si)
2857 _autoinscribe_item(*si);
2858 }
2859
_autoinscribe_inventory()2860 static void _autoinscribe_inventory()
2861 {
2862 for (auto &item : you.inv)
2863 if (item.defined())
2864 _autoinscribe_item(item);
2865 }
2866
need_to_autoinscribe()2867 bool need_to_autoinscribe()
2868 {
2869 return will_autoinscribe;
2870 }
2871
request_autoinscribe(bool do_inscribe)2872 void request_autoinscribe(bool do_inscribe)
2873 {
2874 will_autoinscribe = do_inscribe;
2875 }
2876
autoinscribe()2877 void autoinscribe()
2878 {
2879 _autoinscribe_floor_items();
2880 _autoinscribe_inventory();
2881
2882 will_autoinscribe = false;
2883 }
2884
2885 /**
2886 * Resolve an item's subtype to an appropriate value for autopickup.
2887 * @param item The item to check.
2888 * @returns The actual sub_type for items that either have an identified
2889 * sub_type or where the sub_type is always known. Otherwise the value of the
2890 * max subtype.
2891 */
_autopickup_subtype(const item_def & item)2892 static int _autopickup_subtype(const item_def &item)
2893 {
2894 // Sensed items.
2895 if (item.base_type >= NUM_OBJECT_CLASSES)
2896 return MAX_SUBTYPES - 1;
2897
2898 const int max_type = get_max_subtype(item.base_type);
2899
2900 // item_defs of unknown subtype.
2901 if (max_type > 0 && item.sub_type >= max_type)
2902 return max_type;
2903
2904 // Only where item_type_known() refers to the subtype (as opposed to the
2905 // brand, for example) do we have to check it. For weapons etc. we always
2906 // know the subtype.
2907 switch (item.base_type)
2908 {
2909 case OBJ_WANDS:
2910 case OBJ_SCROLLS:
2911 case OBJ_JEWELLERY:
2912 case OBJ_POTIONS:
2913 case OBJ_STAVES:
2914 return item_type_known(item) ? item.sub_type : max_type;
2915 case OBJ_BOOKS:
2916 if (item.sub_type == BOOK_MANUAL)
2917 return item.sub_type;
2918 else
2919 return 0;
2920 #if TAG_MAJOR_VERSION == 34
2921 case OBJ_RODS:
2922 #endif
2923 case OBJ_GOLD:
2924 case OBJ_RUNES:
2925 return max_type;
2926 default:
2927 return item.sub_type;
2928 }
2929 }
2930
_is_option_autopickup(const item_def & item,bool ignore_force)2931 static bool _is_option_autopickup(const item_def &item, bool ignore_force)
2932 {
2933 if (item.base_type < NUM_OBJECT_CLASSES)
2934 {
2935 const int force = item_autopickup_level(item);
2936 if (!ignore_force && force != AP_FORCE_NONE)
2937 return force == AP_FORCE_ON;
2938 }
2939 else
2940 return false;
2941
2942 // the special-cased gold here is because this call can become very heavy
2943 // for gozag players under extreme circumstances
2944 const string iname = item.base_type == OBJ_GOLD
2945 ? "{gold}"
2946 : _autopickup_item_name(item);
2947
2948 maybe_bool res = clua.callmaybefn("ch_force_autopickup", "is",
2949 &item, iname.c_str());
2950 if (!clua.error.empty())
2951 {
2952 mprf(MSGCH_ERROR, "ch_force_autopickup failed: %s",
2953 clua.error.c_str());
2954 }
2955
2956 if (res == MB_TRUE)
2957 return true;
2958
2959 if (res == MB_FALSE)
2960 return false;
2961
2962 // Check for initial settings
2963 for (const pair<text_pattern, bool>& option : Options.force_autopickup)
2964 if (option.first.matches(iname))
2965 return option.second;
2966
2967 return Options.autopickups[item.base_type];
2968 }
2969
2970 /** Is the item something that we should try to autopickup?
2971 *
2972 * @param ignore_force If true, ignore force_autopickup settings from the
2973 * \ menu (default false).
2974 * @return True if the object should be picked up.
2975 */
item_needs_autopickup(const item_def & item,bool ignore_force)2976 bool item_needs_autopickup(const item_def &item, bool ignore_force)
2977 {
2978 if (in_inventory(item))
2979 return false;
2980
2981 if (item_is_stationary(item))
2982 return false;
2983
2984 if (item.inscription.find("=g") != string::npos)
2985 return true;
2986
2987 if ((item.flags & ISFLAG_THROWN) && Options.pickup_thrown)
2988 return true;
2989
2990 if (item.flags & ISFLAG_DROPPED)
2991 return false;
2992
2993 if (item.props.exists("needs_autopickup"))
2994 return true;
2995
2996 return _is_option_autopickup(item, ignore_force);
2997 }
2998
can_autopickup()2999 bool can_autopickup()
3000 {
3001 // [ds] Checking for autopickups == 0 is a bad idea because
3002 // autopickup is still possible with inscriptions and
3003 // pickup_thrown.
3004 if (Options.autopickup_on <= 0)
3005 return false;
3006
3007 if (!i_feel_safe())
3008 return false;
3009
3010 return true;
3011 }
3012
3013 typedef bool (*item_comparer)(const item_def& pickup_item,
3014 const item_def& inv_item);
3015
_identical_types(const item_def & pickup_item,const item_def & inv_item)3016 static bool _identical_types(const item_def& pickup_item,
3017 const item_def& inv_item)
3018 {
3019 return pickup_item.is_type(inv_item.base_type, inv_item.sub_type);
3020 }
3021
_similar_equip(const item_def & pickup_item,const item_def & inv_item)3022 static bool _similar_equip(const item_def& pickup_item,
3023 const item_def& inv_item)
3024 {
3025 const equipment_type inv_slot = get_item_slot(inv_item);
3026
3027 if (inv_slot == EQ_NONE)
3028 return false;
3029
3030 if (get_item_slot(pickup_item) != inv_slot)
3031 return false;
3032
3033 // Just filling the same slot is enough for armour to be considered
3034 // similar.
3035 if (pickup_item.base_type == OBJ_ARMOUR)
3036 return true;
3037
3038 return item_attack_skill(pickup_item) == item_attack_skill(inv_item)
3039 && get_damage_type(pickup_item) == get_damage_type(inv_item);
3040 }
3041
_similar_wands(const item_def & pickup_item,const item_def & inv_item)3042 static bool _similar_wands(const item_def& pickup_item,
3043 const item_def& inv_item)
3044 {
3045 if (inv_item.base_type != OBJ_WANDS)
3046 return false;
3047
3048 if (pickup_item.sub_type != inv_item.sub_type)
3049 return false;
3050 #if TAG_MAJOR_VERSION == 34
3051 // Not similar if wand in inventory is empty.
3052 return !is_known_empty_wand(inv_item);
3053 #else
3054 return true;
3055 #endif
3056 }
3057
_similar_jewellery(const item_def & pickup_item,const item_def & inv_item)3058 static bool _similar_jewellery(const item_def& pickup_item,
3059 const item_def& inv_item)
3060 {
3061 if (inv_item.base_type != OBJ_JEWELLERY)
3062 return false;
3063
3064 if (pickup_item.sub_type != inv_item.sub_type)
3065 return false;
3066
3067 // For jewellery of the same sub-type, unidentified jewellery is
3068 // always considered similar, as is identified jewellery whose
3069 // effect doesn't stack.
3070 return !item_type_known(inv_item)
3071 || (!jewellery_is_amulet(inv_item)
3072 && !ring_has_stackable_effect(inv_item));
3073 }
3074
_item_different_than_inv(const item_def & pickup_item,item_comparer comparer)3075 static bool _item_different_than_inv(const item_def& pickup_item,
3076 item_comparer comparer)
3077 {
3078 return none_of(begin(you.inv), end(you.inv),
3079 [&] (const item_def &inv_item) -> bool
3080 {
3081 return inv_item.defined()
3082 && comparer(pickup_item, inv_item);
3083 });
3084 }
3085
_interesting_explore_pickup(const item_def & item)3086 static bool _interesting_explore_pickup(const item_def& item)
3087 {
3088 if (!(Options.explore_stop & ES_GREEDY_PICKUP_MASK))
3089 return false;
3090
3091 if (item.base_type == OBJ_GOLD)
3092 return Options.explore_stop & ES_GREEDY_PICKUP_GOLD;
3093
3094 if ((Options.explore_stop & ES_GREEDY_PICKUP_THROWN)
3095 && (item.flags & ISFLAG_THROWN))
3096 {
3097 return true;
3098 }
3099
3100 vector<text_pattern> &ignores = Options.explore_stop_pickup_ignore;
3101 if (!ignores.empty())
3102 {
3103 const string name = item.name(DESC_PLAIN);
3104
3105 for (const text_pattern &pat : ignores)
3106 if (pat.matches(name))
3107 return false;
3108 }
3109
3110 if (!(Options.explore_stop & ES_GREEDY_PICKUP_SMART))
3111 return true;
3112 // "Smart" code follows.
3113
3114 // If ES_GREEDY_PICKUP_THROWN isn't set, then smart greedy pickup
3115 // will ignore thrown items.
3116 if (item.flags & ISFLAG_THROWN)
3117 return false;
3118
3119 if (is_artefact(item))
3120 return true;
3121
3122 // Possbible ego items.
3123 if (!item_type_known(item) && (item.flags & ISFLAG_COSMETIC_MASK))
3124 return true;
3125
3126 switch (item.base_type)
3127 {
3128 case OBJ_WEAPONS:
3129 case OBJ_MISSILES:
3130 case OBJ_ARMOUR:
3131 // Ego items.
3132 if (item.brand != 0)
3133 return true;
3134 break;
3135
3136 default:
3137 break;
3138 }
3139
3140 switch (item.base_type)
3141 {
3142 case OBJ_WEAPONS:
3143 case OBJ_ARMOUR:
3144 return _item_different_than_inv(item, _similar_equip);
3145
3146 case OBJ_WANDS:
3147 return _item_different_than_inv(item, _similar_wands);
3148
3149 case OBJ_JEWELLERY:
3150 return _item_different_than_inv(item, _similar_jewellery);
3151
3152 case OBJ_MISCELLANY:
3153 case OBJ_SCROLLS:
3154 case OBJ_POTIONS:
3155 case OBJ_STAVES:
3156 // Item is boring only if there's an identical one in inventory.
3157 return _item_different_than_inv(item, _identical_types);
3158
3159 case OBJ_BOOKS:
3160 // Books always start out unidentified.
3161 return true;
3162
3163 case OBJ_ORBS:
3164 // Orb is always interesting.
3165 return true;
3166
3167 case OBJ_RUNES:
3168 // Runes are always interesting.
3169 return true;
3170
3171 default:
3172 break;
3173 }
3174
3175 return false;
3176 }
3177
_do_autopickup()3178 static void _do_autopickup()
3179 {
3180 bool did_pickup = false;
3181 int n_did_pickup = 0;
3182 int n_tried_pickup = 0;
3183
3184 // Store last_pickup in case we need to restore it.
3185 // Then clear it to fill with items picked up.
3186 map<int,int> tmp_l_p = you.last_pickup;
3187 you.last_pickup.clear();
3188
3189 int o = you.visible_igrd(you.pos());
3190
3191 string pickup_warning;
3192 while (o != NON_ITEM)
3193 {
3194 const int next = env.item[o].link;
3195 item_def& mi = env.item[o];
3196
3197 if (item_needs_autopickup(mi))
3198 {
3199 // Do this before it's picked up, otherwise the picked up
3200 // item will be in inventory and _interesting_explore_pickup()
3201 // will always return false.
3202 const bool interesting_pickup
3203 = _interesting_explore_pickup(mi);
3204
3205 const iflags_t iflags(mi.flags);
3206 if ((iflags & ISFLAG_THROWN))
3207 learned_something_new(HINT_AUTOPICKUP_THROWN);
3208
3209 clear_item_pickup_flags(mi);
3210
3211 const bool pickup_result = move_item_to_inv(o, mi.quantity);
3212
3213 if (pickup_result)
3214 {
3215 did_pickup = true;
3216 if (interesting_pickup)
3217 n_did_pickup++;
3218 }
3219 else
3220 {
3221 n_tried_pickup++;
3222 pickup_warning = "Your pack is full.";
3223 mi.flags = iflags;
3224 }
3225 }
3226 o = next;
3227 }
3228
3229 if (!pickup_warning.empty())
3230 mpr(pickup_warning);
3231
3232 if (did_pickup)
3233 you.turn_is_over = true;
3234
3235 if (you.last_pickup.empty())
3236 you.last_pickup = tmp_l_p;
3237
3238 item_check();
3239
3240 explore_pickup_event(n_did_pickup, n_tried_pickup);
3241 }
3242
autopickup(bool forced)3243 void autopickup(bool forced)
3244 {
3245 _autoinscribe_floor_items();
3246
3247 will_autopickup = false;
3248 // pick up things when forced (by input ;;), or when you feel save
3249 if (forced || can_autopickup())
3250 _do_autopickup();
3251 else
3252 item_check();
3253 }
3254
inv_count()3255 int inv_count()
3256 {
3257 return count_if(begin(you.inv), end(you.inv), mem_fn(&item_def::defined));
3258 }
3259
3260 // sub_type == -1 means look for any item of the class
find_floor_item(object_class_type cls,int sub_type)3261 item_def *find_floor_item(object_class_type cls, int sub_type)
3262 {
3263 for (int y = 0; y < GYM; ++y)
3264 for (int x = 0; x < GXM; ++x)
3265 for (stack_iterator si(coord_def(x,y)); si; ++si)
3266 if (si->defined()
3267 && (si->is_type(cls, sub_type)
3268 || si->base_type == cls && sub_type == -1)
3269 && !(si->flags & ISFLAG_MIMIC))
3270 {
3271 return &*si;
3272 }
3273
3274 return nullptr;
3275 }
3276
item_on_floor(const item_def & item,const coord_def & where)3277 int item_on_floor(const item_def &item, const coord_def& where)
3278 {
3279 // Check if the item is on the floor and reachable.
3280 for (int link = env.igrid(where); link != NON_ITEM; link = env.item[link].link)
3281 if (&env.item[link] == &item)
3282 return link;
3283
3284 return NON_ITEM;
3285 }
3286
get_max_subtype(object_class_type base_type)3287 int get_max_subtype(object_class_type base_type)
3288 {
3289 static int max_subtype[] =
3290 {
3291 NUM_WEAPONS,
3292 NUM_MISSILES,
3293 NUM_ARMOURS,
3294 NUM_WANDS,
3295 #if TAG_MAJOR_VERSION == 34
3296 NUM_FOODS,
3297 #endif
3298 NUM_SCROLLS,
3299 NUM_JEWELLERY,
3300 NUM_POTIONS,
3301 NUM_BOOKS,
3302 NUM_STAVES,
3303 1, // Orbs -- only one
3304 NUM_MISCELLANY,
3305 -1, // corpses -- handled specially
3306 1, // gold -- handled specially
3307 #if TAG_MAJOR_VERSION == 34
3308 NUM_RODS,
3309 #endif
3310 NUM_RUNE_TYPES,
3311 };
3312 COMPILE_CHECK(ARRAYSZ(max_subtype) == NUM_OBJECT_CLASSES);
3313
3314 ASSERT_RANGE(base_type, 0, NUM_OBJECT_CLASSES);
3315
3316 return max_subtype[base_type];
3317 }
3318
item_equip_slot(const item_def & item)3319 equipment_type item_equip_slot(const item_def& item)
3320 {
3321 if (!in_inventory(item))
3322 return EQ_NONE;
3323
3324 for (int i = EQ_FIRST_EQUIP; i < NUM_EQUIP; i++)
3325 if (item.link == you.equip[i])
3326 return static_cast<equipment_type>(i);
3327
3328 return EQ_NONE;
3329 }
3330
3331 // Includes melded items.
item_is_equipped(const item_def & item,bool quiver_too)3332 bool item_is_equipped(const item_def &item, bool quiver_too)
3333 {
3334 return item_equip_slot(item) != EQ_NONE
3335 || quiver_too
3336 && (you.quiver_action.item_is_quivered(item)
3337 || you.launcher_action.item_is_quivered(item));
3338 }
3339
item_is_melded(const item_def & item)3340 bool item_is_melded(const item_def& item)
3341 {
3342 equipment_type eq = item_equip_slot(item);
3343 return eq != EQ_NONE && you.melded[eq];
3344 }
3345
3346 ////////////////////////////////////////////////////////////////////////
3347 // item_def functions.
3348
has_spells() const3349 bool item_def::has_spells() const
3350 {
3351 return item_is_spellbook(*this);
3352 }
3353
cursed() const3354 bool item_def::cursed() const
3355 {
3356 return flags & ISFLAG_CURSED;
3357 }
3358
launched_by(const item_def & launcher) const3359 bool item_def::launched_by(const item_def &launcher) const
3360 {
3361 if (base_type != OBJ_MISSILES)
3362 return false;
3363 const missile_type mt = fires_ammo_type(launcher);
3364 return sub_type == mt || (mt == MI_STONE && sub_type == MI_SLING_BULLET);
3365 }
3366
index() const3367 int item_def::index() const
3368 {
3369 return this - env.item.buffer();
3370 }
3371
armour_rating() const3372 int item_def::armour_rating() const
3373 {
3374 if (!defined() || base_type != OBJ_ARMOUR)
3375 return 0;
3376
3377 return property(*this, PARM_AC) + plus;
3378 }
3379
holding_monster() const3380 monster* item_def::holding_monster() const
3381 {
3382 if (pos != ITEM_IN_MONSTER_INVENTORY)
3383 return nullptr;
3384 const int midx = link - NON_ITEM - 1;
3385 if (invalid_monster_index(midx))
3386 return nullptr;
3387
3388 return &env.mons[midx];
3389 }
3390
set_holding_monster(const monster & mon)3391 void item_def::set_holding_monster(const monster& mon)
3392 {
3393 pos = ITEM_IN_MONSTER_INVENTORY;
3394 link = NON_ITEM + 1 + mon.mindex();
3395 }
3396
3397 // Note: should not check env.mons, since it may be called by link_items() from
3398 // tags.cc before monsters are unmarshalled.
held_by_monster() const3399 bool item_def::held_by_monster() const
3400 {
3401 return pos == ITEM_IN_MONSTER_INVENTORY
3402 && !invalid_monster_index(link - NON_ITEM - 1);
3403 }
3404
3405 // Note: This function is to isolate all the checks to see if
3406 // an item is valid (often just checking the quantity).
3407 //
3408 // It shouldn't be used a a substitute for those cases
3409 // which actually want to check the quantity (as the
3410 // rules for unused objects might change).
defined() const3411 bool item_def::defined() const
3412 {
3413 return base_type != OBJ_UNASSIGNED && quantity > 0;
3414 }
3415 /**
3416 * Has this item's appearance been initialized?
3417 */
appearance_initialized() const3418 bool item_def::appearance_initialized() const
3419 {
3420 return rnd != 0 || is_unrandom_artefact(*this);
3421 }
3422
3423
3424 /**
3425 * Assuming this item is a randart weapon/armour, what colour is it?
3426 */
randart_colour() const3427 colour_t item_def::randart_colour() const
3428 {
3429 ASSERT(is_artefact(*this));
3430 static colour_t colours[] = { YELLOW, LIGHTGREEN, LIGHTRED, LIGHTMAGENTA };
3431 return colours[rnd % ARRAYSZ(colours)];
3432 }
3433
3434 /**
3435 * Assuming this item is a weapon, what colour is it?
3436 */
weapon_colour() const3437 colour_t item_def::weapon_colour() const
3438 {
3439 ASSERT(base_type == OBJ_WEAPONS);
3440
3441 // random artefact
3442 if (is_artefact(*this))
3443 return randart_colour();
3444
3445 if (is_demonic(*this))
3446 return LIGHTRED;
3447
3448 switch (item_attack_skill(*this))
3449 {
3450 case SK_BOWS:
3451 return BLUE;
3452 case SK_CROSSBOWS:
3453 return LIGHTBLUE;
3454 case SK_THROWING:
3455 return WHITE;
3456 case SK_SLINGS:
3457 return BROWN;
3458 case SK_SHORT_BLADES:
3459 return CYAN;
3460 case SK_LONG_BLADES:
3461 return LIGHTCYAN;
3462 case SK_AXES:
3463 return MAGENTA;
3464 case SK_MACES_FLAILS:
3465 return LIGHTGREY;
3466 case SK_POLEARMS:
3467 return RED;
3468 case SK_STAVES:
3469 return GREEN;
3470 default:
3471 die("Unknown weapon attack skill %d", item_attack_skill(*this));
3472 // XXX: give more info!
3473 }
3474 }
3475
3476 /**
3477 * Assuming this item is a missile (stone/arrow/bolt/etc), what colour is it?
3478 */
missile_colour() const3479 colour_t item_def::missile_colour() const
3480 {
3481 ASSERT(base_type == OBJ_MISSILES);
3482
3483 // TODO: move this into item-prop.cc
3484 switch (sub_type)
3485 {
3486 case MI_STONE:
3487 return BROWN;
3488 case MI_SLING_BULLET:
3489 return CYAN;
3490 case MI_LARGE_ROCK:
3491 return LIGHTGREY;
3492 case MI_ARROW:
3493 return BLUE;
3494 #if TAG_MAJOR_VERSION == 34
3495 case MI_NEEDLE:
3496 #endif
3497 case MI_DART:
3498 return WHITE;
3499 case MI_BOLT:
3500 return LIGHTBLUE;
3501 case MI_JAVELIN:
3502 return RED;
3503 case MI_THROWING_NET:
3504 return MAGENTA;
3505 case MI_BOOMERANG:
3506 return GREEN;
3507 case NUM_SPECIAL_MISSILES:
3508 default:
3509 die("invalid missile type");
3510 }
3511 }
3512
3513 /**
3514 * Assuming this item is a piece of armour, what colour is it?
3515 */
armour_colour() const3516 colour_t item_def::armour_colour() const
3517 {
3518 ASSERT(base_type == OBJ_ARMOUR);
3519
3520 if (is_artefact(*this))
3521 return randart_colour();
3522
3523 if (armour_type_is_hide((armour_type)sub_type))
3524 return mons_class_colour(monster_for_hide((armour_type)sub_type));
3525
3526
3527 // TODO: move (some of?) this into item-prop.cc
3528 switch (sub_type)
3529 {
3530 case ARM_CLOAK:
3531 case ARM_SCARF:
3532 return WHITE;
3533 case ARM_BARDING:
3534 return GREEN;
3535 case ARM_ROBE:
3536 return RED;
3537 #if TAG_MAJOR_VERSION == 34
3538 case ARM_CAP:
3539 #endif
3540 case ARM_HAT:
3541 case ARM_HELMET:
3542 return MAGENTA;
3543 case ARM_BOOTS:
3544 return BLUE;
3545 case ARM_GLOVES:
3546 return LIGHTBLUE;
3547 case ARM_LEATHER_ARMOUR:
3548 return BROWN;
3549 case ARM_ANIMAL_SKIN:
3550 return LIGHTGREY;
3551 case ARM_CRYSTAL_PLATE_ARMOUR:
3552 return WHITE;
3553 case ARM_KITE_SHIELD:
3554 case ARM_TOWER_SHIELD:
3555 case ARM_BUCKLER:
3556 return CYAN;
3557 default:
3558 return LIGHTCYAN;
3559 }
3560 }
3561
3562 /**
3563 * Assuming this item is a wand, what colour is it?
3564 */
wand_colour() const3565 colour_t item_def::wand_colour() const
3566 {
3567 ASSERT(base_type == OBJ_WANDS);
3568
3569 // this is very odd... a linleyism?
3570 // TODO: associate colours directly with names
3571 // (use an array of [name, colour] tuples/structs)
3572 switch (subtype_rnd % NDSC_WAND_PRI)
3573 {
3574 case 0: //"iron wand"
3575 return CYAN;
3576 case 1: //"brass wand"
3577 case 5: //"gold wand"
3578 return YELLOW;
3579 case 3: //"wooden wand"
3580 case 4: //"copper wand"
3581 case 7: //"bronze wand"
3582 return BROWN;
3583 case 6: //"silver wand"
3584 return WHITE;
3585 case 11: //"fluorescent wand"
3586 return LIGHTGREEN;
3587 case 2: //"bone wand"
3588 case 8: //"ivory wand"
3589 case 9: //"glass wand"
3590 case 10: //"lead wand"
3591 default:
3592 return LIGHTGREY;
3593 }
3594 }
3595
3596 /**
3597 * Assuming this item is a potion, what colour is it?
3598 */
potion_colour() const3599 colour_t item_def::potion_colour() const
3600 {
3601 ASSERT(base_type == OBJ_POTIONS);
3602
3603 // TODO: associate colours directly with names
3604 // (use an array of [name, colour] tuples/structs)
3605 static const COLOURS potion_colours[] =
3606 {
3607 #if TAG_MAJOR_VERSION == 34
3608 // clear
3609 LIGHTGREY,
3610 #endif
3611 // blue, black, silvery, cyan, purple, orange
3612 BLUE, LIGHTGREY, WHITE, CYAN, MAGENTA, LIGHTRED,
3613 // inky, red, yellow, green, brown, pink, white
3614 BLUE, RED, YELLOW, GREEN, BROWN, LIGHTMAGENTA, WHITE,
3615 // emerald, grey, pink, copper, gold, dark, puce
3616 LIGHTGREEN, LIGHTGREY, LIGHTRED, YELLOW, YELLOW, BROWN, BROWN,
3617 // amethyst, sapphire
3618 MAGENTA, BLUE
3619 };
3620 COMPILE_CHECK(ARRAYSZ(potion_colours) == NDSC_POT_PRI);
3621 return potion_colours[subtype_rnd % NDSC_POT_PRI];
3622 }
3623
3624 /**
3625 * Assuming this item is a ring, what colour is it?
3626 */
ring_colour() const3627 colour_t item_def::ring_colour() const
3628 {
3629 ASSERT(!jewellery_is_amulet(*this));
3630 // jewellery_is_amulet asserts base type
3631
3632 // TODO: associate colours directly with names
3633 // (use an array of [name, colour] tuples/structs)
3634 switch (subtype_rnd % NDSC_JEWEL_PRI)
3635 {
3636 case 1: // "silver ring"
3637 case 8: // "granite ring"
3638 case 9: // "ivory ring"
3639 case 15: // "bone ring"
3640 case 16: // "diamond ring"
3641 case 20: // "opal ring"
3642 case 21: // "pearl ring"
3643 case 26: // "onyx ring"
3644 return LIGHTGREY;
3645 case 3: // "iron ring"
3646 case 4: // "steel ring"
3647 case 13: // "glass ring"
3648 return CYAN;
3649 case 5: // "tourmaline ring"
3650 case 22: // "coral ring"
3651 return MAGENTA;
3652 case 10: // "ruby ring"
3653 case 19: // "garnet ring"
3654 return RED;
3655 case 11: // "marble ring"
3656 case 12: // "jade ring"
3657 case 14: // "agate ring"
3658 case 17: // "emerald ring"
3659 case 18: // "peridot ring"
3660 return GREEN;
3661 case 23: // "sapphire ring"
3662 case 24: // "cabochon ring"
3663 case 28: // "moonstone ring"
3664 return BLUE;
3665 case 0: // "wooden ring"
3666 case 2: // "golden ring"
3667 case 6: // "brass ring"
3668 case 7: // "copper ring"
3669 case 25: // "gilded ring"
3670 case 27: // "bronze ring"
3671 default:
3672 return BROWN;
3673 }
3674 }
3675
3676 /**
3677 * Assuming this item is an amulet, what colour is it?
3678 */
amulet_colour() const3679 colour_t item_def::amulet_colour() const
3680 {
3681 ASSERT(jewellery_is_amulet(*this));
3682 // jewellery_is_amulet asserts base type
3683
3684 // TODO: associate colours directly with names
3685 // (use an array of [name, colour] tuples/structs)
3686 switch (subtype_rnd % NDSC_JEWEL_PRI)
3687 {
3688 case 1: // "zirconium amulet"
3689 case 10: // "bone amulet"
3690 case 11: // "platinum amulet"
3691 case 16: // "pearl amulet"
3692 case 20: // "diamond amulet"
3693 return LIGHTGREY;
3694 case 0: // "sapphire amulet"
3695 case 17: // "blue amulet"
3696 case 26: // "lapis lazuli amulet"
3697 return BLUE;
3698 case 3: // "emerald amulet"
3699 case 12: // "jade amulet"
3700 case 18: // "peridot amulet"
3701 case 21: // "malachite amulet"
3702 case 25: // "soapstone amulet"
3703 case 28: // "beryl amulet"
3704 return GREEN;
3705 case 4: // "garnet amulet"
3706 case 8: // "ruby amulet"
3707 case 19: // "jasper amulet"
3708 case 15: // "cameo amulet"
3709 return RED;
3710 case 22: // "steel amulet"
3711 case 24: // "silver amulet"
3712 case 27: // "filigree amulet"
3713 return CYAN;
3714 case 13: // "fluorescent amulet"
3715 case 14: // "amethyst amulet"
3716 case 23: // "cabochon amulet"
3717 return MAGENTA;
3718 case 2: // "golden amulet"
3719 case 5: // "bronze amulet"
3720 case 6: // "brass amulet"
3721 case 7: // "copper amulet"
3722 case 9: // "citrine amulet"
3723 default:
3724 return BROWN;
3725 }
3726 }
3727
3728 /**
3729 * Assuming this is a piece of jewellery (ring or amulet), what colour is it?
3730 */
jewellery_colour() const3731 colour_t item_def::jewellery_colour() const
3732 {
3733 ASSERT(base_type == OBJ_JEWELLERY);
3734
3735 //randarts are bright, normal jewellery is dark
3736 if (is_random_artefact(*this))
3737 return LIGHTGREEN + (rnd % (WHITE - LIGHTGREEN + 1));
3738
3739 if (jewellery_is_amulet(*this))
3740 return amulet_colour();
3741 return ring_colour();
3742 }
3743
3744 /**
3745 * Assuming this item is a book, what colour is it?
3746 */
book_colour() const3747 colour_t item_def::book_colour() const
3748 {
3749 ASSERT(base_type == OBJ_BOOKS);
3750
3751 if (sub_type == BOOK_MANUAL)
3752 return WHITE;
3753
3754 switch (rnd % NDSC_BOOK_PRI)
3755 {
3756 case 0:
3757 return BROWN;
3758 case 1:
3759 return CYAN;
3760 case 2:
3761 return LIGHTGREY;
3762 case 3:
3763 case 4:
3764 default:
3765 {
3766 /// everything but BLACK, WHITE (manuals), and DARKGREY (useless)
3767 static const colour_t colours[] = {
3768 BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGREY, LIGHTBLUE,
3769 LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW
3770 };
3771 return colours[rnd % ARRAYSZ(colours)];
3772 }
3773 }
3774 }
3775
3776 /**
3777 * Assuming this item is a Rune of Zot, what colour is it?
3778 */
rune_colour() const3779 colour_t item_def::rune_colour() const
3780 {
3781 switch (sub_type)
3782 {
3783 case RUNE_DIS: // iron
3784 return ETC_IRON;
3785
3786 case RUNE_COCYTUS: // icy
3787 return ETC_ICE;
3788
3789 case RUNE_TARTARUS: // bone
3790 case RUNE_SPIDER:
3791 return ETC_BONE;
3792
3793 case RUNE_SLIME: // slimy
3794 return ETC_SLIME;
3795
3796 case RUNE_SNAKE: // serpentine
3797 return ETC_POISON;
3798
3799 case RUNE_ELF: // elven
3800 return ETC_ELVEN;
3801
3802 case RUNE_VAULTS: // silver
3803 return ETC_SILVER;
3804
3805 case RUNE_TOMB: // golden
3806 return ETC_GOLD;
3807
3808 case RUNE_SWAMP: // decaying
3809 return ETC_DECAY;
3810
3811 case RUNE_SHOALS: // barnacled
3812 return ETC_WATER;
3813
3814 // This one is hardly unique, but colour isn't used for
3815 // stacking, so we don't have to worry too much about this.
3816 // - bwr
3817 case RUNE_DEMONIC: // random Pandemonium lords
3818 {
3819 static const element_type types[] =
3820 {ETC_EARTH, ETC_ELECTRICITY, ETC_ENCHANT, ETC_HEAL, ETC_BLOOD,
3821 ETC_DEATH, ETC_UNHOLY, ETC_VEHUMET, ETC_BEOGH, ETC_CRYSTAL,
3822 ETC_SMOKE, ETC_DWARVEN, ETC_ORCISH, ETC_FLASH};
3823
3824 return types[rnd % ARRAYSZ(types)];
3825 }
3826
3827 case RUNE_ABYSSAL:
3828 return ETC_RANDOM;
3829
3830 case RUNE_MNOLEG: // glowing
3831 return ETC_MUTAGENIC;
3832
3833 case RUNE_LOM_LOBON: // magical
3834 return ETC_MAGIC;
3835
3836 case RUNE_CEREBOV: // fiery
3837 return ETC_FIRE;
3838
3839 case RUNE_GEHENNA: // obsidian
3840 case RUNE_GLOORX_VLOQ: // dark
3841 default:
3842 return ETC_DARK;
3843 }
3844 }
3845
_zigfig_colour()3846 static colour_t _zigfig_colour()
3847 {
3848 const int zigs = you.zigs_completed;
3849 return zigs >= 27 ? ETC_JEWEL :
3850 zigs >= 9 ? ETC_FLASH :
3851 zigs >= 3 ? ETC_MAGIC :
3852 zigs >= 1 ? ETC_SHIMMER_BLUE :
3853 ETC_BONE;
3854 }
3855
3856 /**
3857 * Assuming this item is a miscellaneous item (evocations item or a rune), what
3858 * colour is it?
3859 */
miscellany_colour() const3860 colour_t item_def::miscellany_colour() const
3861 {
3862 ASSERT(base_type == OBJ_MISCELLANY);
3863
3864 switch (sub_type)
3865 {
3866 #if TAG_MAJOR_VERSION == 34
3867 case MISC_FAN_OF_GALES:
3868 return CYAN;
3869 case MISC_BOTTLED_EFREET:
3870 return RED;
3871 #endif
3872 case MISC_PHANTOM_MIRROR:
3873 return RED;
3874 #if TAG_MAJOR_VERSION == 34
3875 case MISC_STONE_OF_TREMORS:
3876 return BROWN;
3877 #endif
3878 case MISC_LIGHTNING_ROD:
3879 return LIGHTGREY;
3880 case MISC_PHIAL_OF_FLOODS:
3881 return LIGHTBLUE;
3882 case MISC_BOX_OF_BEASTS:
3883 return LIGHTGREEN; // ugh, but we're out of other options
3884 #if TAG_MAJOR_VERSION == 34
3885 case MISC_CRYSTAL_BALL_OF_ENERGY:
3886 return LIGHTCYAN;
3887 #endif
3888 case MISC_HORN_OF_GERYON:
3889 return LIGHTRED;
3890 #if TAG_MAJOR_VERSION == 34
3891 case MISC_LAMP_OF_FIRE:
3892 return YELLOW;
3893 case MISC_SACK_OF_SPIDERS:
3894 return WHITE;
3895 case MISC_BUGGY_LANTERN_OF_SHADOWS:
3896 case MISC_BUGGY_EBONY_CASKET:
3897 return DARKGREY;
3898 #endif
3899 case MISC_TIN_OF_TREMORSTONES:
3900 return BROWN;
3901 case MISC_CONDENSER_VANE:
3902 return WHITE;
3903 case MISC_XOMS_CHESSBOARD:
3904 return ETC_RANDOM;
3905 case MISC_QUAD_DAMAGE:
3906 return ETC_DARK;
3907 case MISC_ZIGGURAT:
3908 return _zigfig_colour();
3909 default:
3910 return LIGHTGREEN;
3911 }
3912 }
3913
3914 /**
3915 * Assuming this item is a corpse, what colour is it?
3916 */
corpse_colour() const3917 colour_t item_def::corpse_colour() const
3918 {
3919 ASSERT(base_type == OBJ_CORPSES);
3920
3921 switch (sub_type)
3922 {
3923 case CORPSE_SKELETON:
3924 return LIGHTGREY;
3925 case CORPSE_BODY:
3926 {
3927 const colour_t class_colour = mons_class_colour(mon_type);
3928 #if TAG_MAJOR_VERSION == 34
3929 if (class_colour == COLOUR_UNDEF)
3930 return LIGHTRED;
3931 #else
3932 ASSERT(class_colour != COLOUR_UNDEF);
3933 #endif
3934 return class_colour;
3935 }
3936 default:
3937 die("Unknown corpse type: %d", sub_type); // XXX: add more info
3938 }
3939 }
3940
3941 /**
3942 * What colour is this item?
3943 *
3944 * @return The colour that the item should be displayed as.
3945 * Used for console glyphs.
3946 */
get_colour() const3947 colour_t item_def::get_colour() const
3948 {
3949 // props take first priority
3950 if (props.exists(FORCED_ITEM_COLOUR_KEY))
3951 {
3952 const colour_t colour = props[FORCED_ITEM_COLOUR_KEY].get_int();
3953 ASSERT(colour);
3954 return colour;
3955 }
3956
3957 // unrands get to override everything else (wrt colour)
3958 if (is_unrandom_artefact(*this))
3959 {
3960 const unrandart_entry *unrand = get_unrand_entry(
3961 find_unrandart_index(*this));
3962 ASSERT(unrand);
3963 ASSERT(unrand->colour);
3964 return unrand->colour;
3965 }
3966
3967 switch (base_type)
3968 {
3969 case OBJ_WEAPONS:
3970 return weapon_colour();
3971 case OBJ_MISSILES:
3972 return missile_colour();
3973 case OBJ_ARMOUR:
3974 return armour_colour();
3975 case OBJ_WANDS:
3976 return wand_colour();
3977 case OBJ_POTIONS:
3978 return potion_colour();
3979 #if TAG_MAJOR_VERSION == 34
3980 case OBJ_FOOD:
3981 return LIGHTRED;
3982 #endif
3983 case OBJ_JEWELLERY:
3984 return jewellery_colour();
3985 case OBJ_SCROLLS:
3986 return LIGHTGREY;
3987 case OBJ_BOOKS:
3988 return book_colour();
3989 #if TAG_MAJOR_VERSION == 34
3990 case OBJ_RODS:
3991 return YELLOW;
3992 #endif
3993 case OBJ_STAVES:
3994 return BROWN;
3995 case OBJ_ORBS:
3996 return ETC_MUTAGENIC;
3997 case OBJ_CORPSES:
3998 return corpse_colour();
3999 case OBJ_MISCELLANY:
4000 return miscellany_colour();
4001 case OBJ_GOLD:
4002 return YELLOW;
4003 case OBJ_RUNES:
4004 return rune_colour();
4005 case OBJ_DETECTED:
4006 return Options.detected_item_colour;
4007 case NUM_OBJECT_CLASSES:
4008 case OBJ_UNASSIGNED:
4009 case OBJ_RANDOM: // not sure what to do with these three
4010 default:
4011 return LIGHTGREY;
4012 }
4013 }
4014
item_type_has_unidentified(object_class_type base_type)4015 bool item_type_has_unidentified(object_class_type base_type)
4016 {
4017 return base_type == OBJ_WANDS
4018 || base_type == OBJ_SCROLLS
4019 || base_type == OBJ_JEWELLERY
4020 || base_type == OBJ_POTIONS
4021 || base_type == OBJ_BOOKS
4022 || base_type == OBJ_STAVES
4023 || base_type == OBJ_MISCELLANY
4024 #if TAG_MAJOR_VERSION == 34
4025 || base_type == OBJ_RODS
4026 #endif
4027 ;
4028 }
4029
4030 // Checks whether the item is actually a good one.
4031 // TODO: check brands, etc.
is_valid(bool iinfo) const4032 bool item_def::is_valid(bool iinfo) const
4033 {
4034 if (base_type == OBJ_DETECTED)
4035 {
4036 if (!iinfo)
4037 dprf("weird detected item");
4038 return iinfo;
4039 }
4040 else if (!defined())
4041 {
4042 dprf("undefined");
4043 return false;
4044 }
4045 const int max_sub = get_max_subtype(base_type);
4046 if (max_sub != -1 && sub_type >= max_sub)
4047 {
4048 if (!iinfo || sub_type > max_sub || !item_type_has_unidentified(base_type))
4049 {
4050 if (!iinfo)
4051 dprf("weird subtype and no info");
4052 if (sub_type > max_sub)
4053 dprf("huge subtype");
4054 if (!item_type_has_unidentified(base_type))
4055 dprf("unided item of a type that can't be");
4056 return false;
4057 }
4058 }
4059 if (get_colour() == 0)
4060 {
4061 dprf("black item");
4062 return false; // No black items.
4063 }
4064 if (!appearance_initialized())
4065 {
4066 dprf("no rnd");
4067 return false; // no items with uninitialized rnd
4068 }
4069 return true;
4070 }
4071
4072 // The Orb of Zot and unique runes are considered critical.
is_critical() const4073 bool item_def::is_critical() const
4074 {
4075 if (!defined())
4076 return false;
4077
4078 if (base_type == OBJ_ORBS)
4079 return true;
4080
4081 return item_is_unique_rune(*this);
4082 }
4083
4084 // Is item something that no one would usually bother enchanting?
is_mundane() const4085 bool item_def::is_mundane() const
4086 {
4087 switch (base_type)
4088 {
4089 case OBJ_WEAPONS:
4090 if (sub_type == WPN_CLUB
4091 || is_giant_club_type(sub_type))
4092 {
4093 return true;
4094 }
4095 break;
4096
4097 case OBJ_ARMOUR:
4098 if (sub_type == ARM_ANIMAL_SKIN)
4099 return true;
4100 break;
4101
4102 default:
4103 break;
4104 }
4105
4106 return false;
4107 }
4108
_rune_from_specs(const char * _specs,item_def & item)4109 static void _rune_from_specs(const char* _specs, item_def &item)
4110 {
4111 char specs[80];
4112
4113 if (strstr(_specs, "rune of zot"))
4114 {
4115 strlcpy(specs, _specs, min(strlen(_specs) - strlen(" of zot") + 1,
4116 sizeof(specs)));
4117 }
4118 else
4119 strlcpy(specs, _specs, sizeof(specs));
4120
4121 if (strlen(specs) > 4)
4122 {
4123 for (int i = 0; i < NUM_RUNE_TYPES; ++i)
4124 {
4125 item.sub_type = i;
4126
4127 if (lowercase_string(item.name(DESC_PLAIN)).find(specs) != string::npos)
4128 return;
4129 }
4130 }
4131
4132 while (true)
4133 {
4134 string line;
4135 for (int i = 0; i < NUM_RUNE_TYPES; i++)
4136 {
4137 line += make_stringf("[%c] %-10s ", i + 'a', rune_type_name(i));
4138 if (i % 5 == 4 || i == NUM_RUNE_TYPES - 1)
4139 {
4140 mprf(MSGCH_PROMPT, "%s", line.c_str());
4141 line.clear();
4142 }
4143 }
4144 mprf(MSGCH_PROMPT, "Which rune (ESC to exit)? ");
4145
4146 int keyin = toalower(get_ch());
4147
4148 if (key_is_escape(keyin) || keyin == ' '
4149 || keyin == '\r' || keyin == '\n')
4150 {
4151 canned_msg(MSG_OK);
4152 item.base_type = OBJ_UNASSIGNED;
4153 return;
4154 }
4155
4156 if (keyin < 'a' || keyin >= 'a' + NUM_RUNE_TYPES)
4157 continue;
4158
4159 item.sub_type = keyin - 'a';
4160
4161 return;
4162 }
4163 }
4164
_book_from_spell(const char * specs,item_def & item)4165 static bool _book_from_spell(const char* specs, item_def &item)
4166 {
4167 spell_type type = spell_by_name(specs, true);
4168
4169 if (type == SPELL_NO_SPELL)
4170 return false;
4171
4172 for (int i = 0; i < NUM_BOOKS; ++i)
4173 {
4174 const auto bt = static_cast<book_type>(i);
4175 if (!book_exists(bt))
4176 continue;
4177 for (spell_type sp : spellbook_template(bt))
4178 {
4179 if (sp == type)
4180 {
4181 item.sub_type = i;
4182 return true;
4183 }
4184 }
4185 }
4186
4187 return false;
4188 }
4189
get_item_by_name(item_def * item,const char * specs,object_class_type class_wanted,bool create_for_real)4190 bool get_item_by_name(item_def *item, const char* specs,
4191 object_class_type class_wanted, bool create_for_real)
4192 {
4193 // used only for wizmode and item lookup
4194
4195 int type_wanted = -1;
4196 int special_wanted = 0;
4197
4198 // In order to get the sub-type, we'll fill out the base type...
4199 // then we're going to iterate over all possible subtype values
4200 // and see if we get a winner. -- bwr
4201 item->base_type = class_wanted;
4202 item->sub_type = 0;
4203 item->plus = 0;
4204 item->plus2 = 0;
4205 item->special = 0;
4206 item->flags = 0;
4207 item->quantity = 1;
4208 // Don't use set_ident_flags(), to avoid getting a spurious ID note.
4209 item->flags |= ISFLAG_IDENT_MASK;
4210
4211 if (class_wanted == OBJ_RUNES && strstr(specs, "rune"))
4212 {
4213 _rune_from_specs(specs, *item);
4214
4215 // Rune creation cancelled, clean up item->
4216 if (item->base_type == OBJ_UNASSIGNED)
4217 return false;
4218 }
4219
4220 if (!item->sub_type)
4221 {
4222 type_wanted = -1;
4223 size_t best_index = 10000;
4224
4225 for (const auto i : all_item_subtypes(item->base_type))
4226 {
4227 item->sub_type = i;
4228 size_t pos = lowercase_string(item->name(DESC_PLAIN)).find(specs);
4229 if (pos != string::npos)
4230 {
4231 // Earliest match is the winner.
4232 if (pos < best_index)
4233 {
4234 if (create_for_real)
4235 mpr(item->name(DESC_PLAIN));
4236 type_wanted = i;
4237 best_index = pos;
4238 }
4239 }
4240 }
4241
4242 if (type_wanted != -1)
4243 {
4244 item->sub_type = type_wanted;
4245 if (!create_for_real)
4246 return true;
4247 }
4248 else
4249 {
4250 switch (class_wanted)
4251 {
4252 case OBJ_BOOKS:
4253 // Try if we get a match against a spell.
4254 if (_book_from_spell(specs, *item))
4255 type_wanted = item->sub_type;
4256 break;
4257
4258 // Search for a matching unrandart.
4259 case OBJ_WEAPONS:
4260 case OBJ_ARMOUR:
4261 case OBJ_JEWELLERY:
4262 {
4263 // XXX: if we ever allow ?/ lookup of unrands, change this,
4264 // since at present, it'll mark any matching unrands as
4265 // created & prevent them from showing up in the game!
4266 for (int unrand = 0; unrand < NUM_UNRANDARTS; ++unrand)
4267 {
4268 int index = unrand + UNRAND_START;
4269 const unrandart_entry* entry = get_unrand_entry(index);
4270
4271 size_t pos = lowercase_string(entry->name).find(specs);
4272 if (pos != string::npos && entry->base_type == class_wanted)
4273 {
4274 make_item_unrandart(*item, index);
4275 if (create_for_real)
4276 {
4277 mprf("%s (%s)", entry->name,
4278 debug_art_val_str(*item).c_str());
4279 }
4280 return true;
4281 }
4282 }
4283
4284 // Reset base type to class_wanted, if nothing found.
4285 item->base_type = class_wanted;
4286 item->sub_type = 0;
4287 break;
4288 }
4289
4290 default:
4291 break;
4292 }
4293 }
4294
4295 if (type_wanted == -1)
4296 {
4297 // ds -- If specs is a valid int, try using that.
4298 // Since zero is atoi's copout, the wizard
4299 // must enter (subtype + 1).
4300 if (!(type_wanted = atoi(specs)))
4301 return false;
4302
4303 type_wanted--;
4304
4305 item->sub_type = type_wanted;
4306 }
4307 }
4308
4309 if (!create_for_real)
4310 return true;
4311
4312 switch (item->base_type)
4313 {
4314 case OBJ_MISSILES:
4315 item->quantity = 30;
4316 // intentional fall-through
4317 case OBJ_WEAPONS:
4318 case OBJ_ARMOUR:
4319 {
4320 char buf[80];
4321 msgwin_get_line_autohist("What ego type? ", buf, sizeof(buf));
4322
4323 if (buf[0] != '\0')
4324 {
4325 string buf_lwr = lowercase_string(buf);
4326 special_wanted = 0;
4327 size_t best_index = 10000;
4328
4329 for (int i = SPWPN_NORMAL + 1; i < SPWPN_DEBUG_RANDART; ++i)
4330 {
4331 item->brand = i;
4332 size_t pos = lowercase_string(item->name(DESC_PLAIN)).find(buf_lwr);
4333 if (pos != string::npos)
4334 {
4335 // earliest match is the winner
4336 if (pos < best_index)
4337 {
4338 if (create_for_real)
4339 mpr(item->name(DESC_PLAIN));
4340 special_wanted = i;
4341 best_index = pos;
4342 }
4343 }
4344 }
4345
4346 item->brand = special_wanted;
4347 }
4348 break;
4349 }
4350
4351 case OBJ_BOOKS:
4352 if (item->sub_type == BOOK_MANUAL)
4353 {
4354 skill_type skill =
4355 debug_prompt_for_skill("A manual for which skill? ");
4356
4357 if (skill != SK_NONE)
4358 item->skill = skill;
4359 else
4360 {
4361 mpr("Sorry, no books on that skill today.");
4362 item->skill = SK_FIGHTING; // Was probably that anyway.
4363 }
4364 item->skill_points = random_range(2000, 3000);
4365 }
4366 else if (type_wanted == BOOK_RANDART_THEME)
4367 build_themed_book(*item, capped_spell_filter(20));
4368 else if (type_wanted == BOOK_RANDART_LEVEL)
4369 {
4370 int level = random_range(1, 9);
4371 make_book_level_randart(*item, level);
4372 }
4373 break;
4374
4375 case OBJ_WANDS:
4376 item->plus = wand_charge_value(item->sub_type);
4377 break;
4378
4379 case OBJ_POTIONS:
4380 item->quantity = 12;
4381 break;
4382
4383 case OBJ_SCROLLS:
4384 item->quantity = 12;
4385 break;
4386
4387 case OBJ_JEWELLERY:
4388 if (jewellery_is_amulet(*item))
4389 break;
4390
4391 switch (item->sub_type)
4392 {
4393 case RING_SLAYING:
4394 case RING_PROTECTION:
4395 case RING_EVASION:
4396 case RING_STRENGTH:
4397 case RING_DEXTERITY:
4398 case RING_INTELLIGENCE:
4399 item->plus = 5;
4400 default:
4401 break;
4402 }
4403
4404 default:
4405 break;
4406 }
4407
4408 item_set_appearance(*item);
4409
4410 return true;
4411 }
4412
get_item_by_exact_name(item_def & item,const char * name)4413 bool get_item_by_exact_name(item_def &item, const char* name)
4414 {
4415 item.clear();
4416 item.quantity = 1;
4417 // Don't use set_ident_flags(), to avoid getting a spurious ID note.
4418 item.flags |= ISFLAG_IDENT_MASK;
4419
4420 string name_lc = lowercase_string(string(name));
4421
4422 for (int i = 0; i < NUM_OBJECT_CLASSES; ++i)
4423 {
4424 if (i == OBJ_RUNES) // runes aren't shown in ?/I
4425 continue;
4426
4427 item.base_type = static_cast<object_class_type>(i);
4428 item.sub_type = 0;
4429
4430 if (!item.sub_type)
4431 {
4432 for (const auto j : all_item_subtypes(item.base_type))
4433 {
4434 item.sub_type = j;
4435 if (lowercase_string(item.name(DESC_DBNAME)) == name_lc)
4436 return true;
4437 }
4438 }
4439 }
4440 return false;
4441 }
4442
move_items(const coord_def r,const coord_def p)4443 void move_items(const coord_def r, const coord_def p)
4444 {
4445 ASSERT_IN_BOUNDS(r);
4446 ASSERT_IN_BOUNDS(p);
4447
4448 int it = env.igrid(r);
4449
4450 if (it == NON_ITEM)
4451 return;
4452
4453 while (it != NON_ITEM)
4454 {
4455 env.item[it].pos.x = p.x;
4456 env.item[it].pos.y = p.y;
4457 if (env.item[it].link == NON_ITEM)
4458 {
4459 // Link to the stack on the target grid p,
4460 // or NON_ITEM, if empty.
4461 env.item[it].link = env.igrid(p);
4462 break;
4463 }
4464 it = env.item[it].link;
4465 }
4466
4467 // Move entire stack over to p.
4468 env.igrid(p) = env.igrid(r);
4469 env.igrid(r) = NON_ITEM;
4470 }
4471
4472 // erase everything the player doesn't know
get_item_known_info(const item_def & item)4473 item_def get_item_known_info(const item_def& item)
4474 {
4475 item_def ii;
4476
4477 ii.base_type = item.base_type;
4478 ii.quantity = item.quantity;
4479 ii.inscription = item.inscription;
4480 ii.flags = item.flags & (0
4481 | ISFLAG_IDENT_MASK
4482 | ISFLAG_ARTEFACT_MASK | ISFLAG_DROPPED | ISFLAG_THROWN
4483 | ISFLAG_COSMETIC_MASK);
4484
4485 if (in_inventory(item))
4486 {
4487 ii.link = item.link;
4488 ii.slot = item.slot;
4489 ii.pos = ITEM_IN_INVENTORY;
4490 }
4491 else
4492 ii.pos = item.pos;
4493
4494 ii.rnd = item.rnd; // XXX: may (?) leak cosmetic (?) info...?
4495 if (ii.rnd == 0)
4496 ii.rnd = 1; // don't leave "uninitialized" item infos around
4497
4498 // keep god number
4499 if (item.orig_monnum < 0)
4500 ii.orig_monnum = item.orig_monnum;
4501
4502 if (is_unrandom_artefact(item))
4503 {
4504 // Unrandart index
4505 // Since the appearance of unrandarts is fixed anyway, this
4506 // is not an information leak.
4507 ii.unrand_idx = item.unrand_idx;
4508 }
4509
4510 switch (item.base_type)
4511 {
4512 case OBJ_MISSILES:
4513 if (item_ident(ii, ISFLAG_KNOW_PLUSES))
4514 ii.net_placed = item.net_placed;
4515 // intentional fall-through
4516 case OBJ_WEAPONS:
4517 ii.sub_type = item.sub_type;
4518 if (item_ident(ii, ISFLAG_KNOW_PLUSES))
4519 ii.plus = item.plus;
4520 if (item_type_known(item))
4521 ii.brand = item.brand;
4522 break;
4523 case OBJ_ARMOUR:
4524 ii.sub_type = item.sub_type;
4525 if (item_ident(ii, ISFLAG_KNOW_PLUSES))
4526 ii.plus = item.plus;
4527 if (item_type_known(item))
4528 ii.brand = item.brand;
4529 break;
4530 case OBJ_WANDS:
4531 if (item_type_known(item))
4532 {
4533 ii.sub_type = item.sub_type;
4534 ii.charges = item.charges;
4535 }
4536 else
4537 ii.sub_type = NUM_WANDS;
4538 ii.subtype_rnd = item.subtype_rnd;
4539 break;
4540 case OBJ_POTIONS:
4541 if (item_type_known(item))
4542 ii.sub_type = item.sub_type;
4543 else
4544 ii.sub_type = NUM_POTIONS;
4545 ii.subtype_rnd = item.subtype_rnd;
4546 break;
4547 case OBJ_CORPSES:
4548 ii.sub_type = item.sub_type;
4549 ii.mon_type = item.mon_type;
4550 ii.freshness = 100;
4551 break;
4552 case OBJ_SCROLLS:
4553 if (item_type_known(item))
4554 ii.sub_type = item.sub_type;
4555 else
4556 ii.sub_type = NUM_SCROLLS;
4557 ii.subtype_rnd = item.subtype_rnd; // name seed
4558 break;
4559 case OBJ_JEWELLERY:
4560 if (item_type_known(item))
4561 {
4562 ii.sub_type = item.sub_type;
4563 if (jewellery_has_pluses(item))
4564 ii.plus = item.plus;
4565 }
4566 else
4567 ii.sub_type = jewellery_is_amulet(item) ? NUM_JEWELLERY : NUM_RINGS;
4568 ii.subtype_rnd = item.subtype_rnd;
4569 break;
4570 case OBJ_BOOKS:
4571 ii.sub_type = item.sub_type;
4572 ii.subtype_rnd = item.subtype_rnd;
4573 if (item.sub_type == BOOK_MANUAL && item_type_known(item))
4574 ii.skill = item.skill; // manual skill
4575 break;
4576 #if TAG_MAJOR_VERSION == 34
4577 case OBJ_RODS:
4578 ii.sub_type = NUM_RODS;
4579 break;
4580 #endif
4581 case OBJ_STAVES:
4582 ii.sub_type = item_type_known(item) ? item.sub_type : int{NUM_STAVES};
4583 ii.subtype_rnd = item.subtype_rnd;
4584 break;
4585 case OBJ_MISCELLANY:
4586 if (item_type_known(item))
4587 ii.sub_type = item.sub_type;
4588 else
4589 ii.sub_type = item.sub_type;
4590 break;
4591 case OBJ_GOLD:
4592 ii.sub_type = item.sub_type;
4593 break;
4594 case OBJ_ORBS:
4595 case OBJ_RUNES:
4596 default:
4597 ii.sub_type = item.sub_type;
4598 break;
4599 }
4600
4601 if (item_type_known(item))
4602 {
4603 ii.flags |= ISFLAG_KNOW_TYPE;
4604
4605 if (item.props.exists(ARTEFACT_NAME_KEY))
4606 ii.props[ARTEFACT_NAME_KEY] = item.props[ARTEFACT_NAME_KEY];
4607 }
4608
4609 static const char* copy_props[] =
4610 {
4611 ARTEFACT_APPEAR_KEY, KNOWN_PROPS_KEY, CORPSE_NAME_KEY,
4612 CORPSE_NAME_TYPE_KEY, "item_tile", "item_tile_name",
4613 "worn_tile", "worn_tile_name", "needs_autopickup",
4614 FORCED_ITEM_COLOUR_KEY, SPELL_LIST_KEY,
4615 };
4616 for (const char *prop : copy_props)
4617 if (item.props.exists(prop))
4618 ii.props[prop] = item.props[prop];
4619
4620 static const char* copy_ident_props[] = {"spell_list"};
4621 if (item_ident(item, ISFLAG_KNOW_TYPE))
4622 {
4623 for (const char *prop : copy_ident_props)
4624 if (item.props.exists(prop))
4625 ii.props[prop] = item.props[prop];
4626 }
4627
4628 if (item.props.exists(ARTEFACT_PROPS_KEY))
4629 {
4630 CrawlVector props = item.props[ARTEFACT_PROPS_KEY].get_vector();
4631 const CrawlVector &known = item.props[KNOWN_PROPS_KEY].get_vector();
4632
4633 if (!item_ident(item, ISFLAG_KNOW_PROPERTIES))
4634 {
4635 for (unsigned i = 0; i < props.size(); ++i)
4636 {
4637 if (i >= known.size() || !known[i].get_bool())
4638 props[i] = (short)0;
4639 }
4640 }
4641
4642 ii.props[ARTEFACT_PROPS_KEY] = props;
4643 }
4644
4645 return ii;
4646 }
4647
runes_in_pack()4648 int runes_in_pack()
4649 {
4650 return static_cast<int>(you.runes.count());
4651 }
4652
get_random_item_mimic_type()4653 object_class_type get_random_item_mimic_type()
4654 {
4655 return random_choose(OBJ_GOLD, OBJ_WEAPONS, OBJ_ARMOUR, OBJ_SCROLLS,
4656 OBJ_POTIONS, OBJ_BOOKS, OBJ_STAVES,
4657 OBJ_MISCELLANY, OBJ_JEWELLERY);
4658 }
4659
4660 /**
4661 * How many types of identifiable item exist in the same category as the
4662 * given item? (E.g., wands, scrolls, rings, etc.)
4663 *
4664 * @param item The item in question.
4665 * @return The number of item enums in the same category.
4666 * If the item isn't in a category of identifiable items,
4667 * returns 0.
4668 */
_items_in_category(const item_def & item)4669 static int _items_in_category(const item_def &item)
4670 {
4671 switch (item.base_type)
4672 {
4673 case OBJ_WANDS:
4674 return NUM_WANDS;
4675 case OBJ_STAVES:
4676 return NUM_STAVES;
4677 case OBJ_POTIONS:
4678 return NUM_POTIONS;
4679 case OBJ_SCROLLS:
4680 return NUM_SCROLLS;
4681 case OBJ_JEWELLERY:
4682 if (jewellery_is_amulet(item.sub_type))
4683 return NUM_JEWELLERY - AMU_FIRST_AMULET;
4684 return NUM_RINGS - RING_FIRST_RING;
4685 default:
4686 return 0;
4687 }
4688 }
4689
4690 /**
4691 * What's the first enum for the given item's category?
4692 *
4693 * @param item The item in question.
4694 * @return The enum value for the first item of the given type.
4695 */
_get_item_base(const item_def & item)4696 static int _get_item_base(const item_def &item)
4697 {
4698 if (item.base_type != OBJ_JEWELLERY)
4699 return 0; // XXX: dubious
4700 if (jewellery_is_amulet(item))
4701 return AMU_FIRST_AMULET;
4702 return RING_FIRST_RING;
4703 }
4704
4705 /**
4706 * Autoidentify the (given) last item in its category.
4707 *
4708 8 @param item The item to identify.
4709 */
_identify_last_item(item_def & item)4710 static void _identify_last_item(item_def &item)
4711 {
4712 if (!in_inventory(item) && item_needs_autopickup(item)
4713 && (item.base_type == OBJ_STAVES
4714 || item.base_type == OBJ_JEWELLERY))
4715 {
4716 item.props["needs_autopickup"] = true;
4717 }
4718
4719 set_ident_type(item, true);
4720
4721 if (item.props.exists("needs_autopickup") && is_useless_item(item))
4722 item.props.erase("needs_autopickup");
4723
4724 const string class_name = item.base_type == OBJ_JEWELLERY ?
4725 item_base_name(item) :
4726 item_class_name(item.base_type, true);
4727 mprf("You have identified the last %s.", class_name.c_str());
4728
4729 if (in_inventory(item))
4730 {
4731 mprf_nocap("%s", item.name(DESC_INVENTORY_EQUIP).c_str());
4732 auto_assign_item_slot(item);
4733 }
4734 }
4735
4736
4737 /**
4738 * Check to see if there's only one unidentified subtype left in the given
4739 * item's object type. If so, automatically identify it.
4740 *
4741 * @param item The item in question.
4742 * @return Whether the item was identified.
4743 */
maybe_identify_base_type(item_def & item)4744 bool maybe_identify_base_type(item_def &item)
4745 {
4746 if (is_artefact(item))
4747 return false;
4748 if (get_ident_type(item))
4749 return false;
4750
4751 const int item_count = _items_in_category(item);
4752 if (!item_count)
4753 return false;
4754
4755 // What's the enum of the first item in the category?
4756 const int item_base = _get_item_base(item);
4757
4758 int ident_count = 0;
4759
4760 for (int i = item_base; i < item_count + item_base; i++)
4761 {
4762 const bool identified = you.type_ids[item.base_type][i];
4763 ident_count += identified ? 1 : 0;
4764 }
4765
4766 if (ident_count < item_count - 1)
4767 return false;
4768
4769 _identify_last_item(item);
4770 return true;
4771 }
4772