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