* getobj returns: * struct obj *xxx: object to do something with. * (struct obj *) 0 error return: no object. * &hands_obj explicitly no object (as in w-). * The obj_ok callback should not have side effects (apart from * abnormal-behavior things like impossible calls); it can be called multiple * times on the same object during the execution of this
| 1749 | * case. |
| 1750 | */ |
| 1751 | struct obj * |
| 1752 | getobj( |
| 1753 | const char *word, /* usually a direct verb such as "drop" */ |
| 1754 | int (*obj_ok)(OBJ_P), /* callback to classify an object's suitability */ |
| 1755 | unsigned int ctrlflags) /* some control to fine-tune the behavior */ |
| 1756 | { |
| 1757 | struct obj *otmp; |
| 1758 | char ilet = 0; |
| 1759 | char buf[BUFSZ], qbuf[QBUFSZ]; |
| 1760 | char lets[BUFSZ], altlets[BUFSZ]; |
| 1761 | int suggested = 0; |
| 1762 | char *bp = buf, *ap = altlets; |
| 1763 | boolean allowcnt = (ctrlflags & GETOBJ_ALLOWCNT), |
| 1764 | forceprompt = (ctrlflags & GETOBJ_PROMPT), |
| 1765 | allownone = FALSE; |
| 1766 | int inaccess = 0; /* counts GETOBJ_EXCLUDE_INACCESS items to decide |
| 1767 | * between "you don't have anything to <foo>" |
| 1768 | * versus "you don't have anything _else_ to <foo>" |
| 1769 | * (also used for GETOBJ_EXCLUDE_NONINVENT) */ |
| 1770 | long cnt = 0L; |
| 1771 | boolean cntgiven = FALSE; |
| 1772 | boolean msggiven = FALSE; |
| 1773 | boolean oneloop = FALSE; |
| 1774 | Loot *sortedinvent, *srtinv; |
| 1775 | struct _cmd_queue cq, *cmdq; |
| 1776 | boolean need_more_cq = FALSE; |
| 1777 | |
| 1778 | need_more_cq: |
| 1779 | if ((cmdq = cmdq_pop()) != 0) { |
| 1780 | cq = *cmdq; |
| 1781 | free(cmdq); |
| 1782 | /* user-input means pick something interactively now, with more |
| 1783 | in the command queue for after that; if not user-input, it |
| 1784 | has to be a key here */ |
| 1785 | if (cq.typ != CMDQ_USER_INPUT) { |
| 1786 | otmp = 0; /* in case of non-key or lookup failure */ |
| 1787 | if (cq.typ == CMDQ_KEY) { |
| 1788 | int v; |
| 1789 | |
| 1790 | if (cq.key == HANDS_SYM) { |
| 1791 | /* check whether the hands/self choice is suitable */ |
| 1792 | v = (*obj_ok)((struct obj *) 0); |
| 1793 | if (v == GETOBJ_SUGGEST || v == GETOBJ_DOWNPLAY) |
| 1794 | otmp = &hands_obj; |
| 1795 | } else { |
| 1796 | /* there could be more than one match if key is '#'; |
| 1797 | take first one which passes the obj_ok callback */ |
| 1798 | for (otmp = gi.invent; otmp; otmp = otmp->nobj) |
| 1799 | if (otmp->invlet == cq.key) { |
| 1800 | v = (*obj_ok)(otmp); |
| 1801 | if (v == GETOBJ_SUGGEST || v == GETOBJ_DOWNPLAY) |
| 1802 | break; |
| 1803 | } |
| 1804 | } |
| 1805 | } else if (cq.typ == CMDQ_INT) { |
| 1806 | /* getting a partial stack */ |
| 1807 | if (!cntgiven && allowcnt) { |
| 1808 | cnt = (long) cq.intval; |
no test coverage detected