/** * Check if the given item is available for the player to use. */ bool item_is_available(struct object *obj) { if (object_is_carried(player, obj)) return true; if (cave && square_holds_object(cave, player->py, player->px, obj)) return true; return false; }
/** * Update the player's knowledge of the objects on a grid in the current level */ void square_know_pile(struct chunk *c, int y, int x) { struct object *obj; if (c != cave) return; object_lists_check_integrity(c, player->cave); /* Know every item on this grid, greater knowledge for the player grid */ for (obj = square_object(c, y, x); obj; obj = obj->next) { object_see(player, obj); if ((y == player->py) && (x == player->px)) { object_touch(player, obj); } } /* Remove known location of anything not on this grid */ obj = square_object(player->cave, y, x); while (obj) { struct object *next = obj->next; assert(c->objects[obj->oidx]); if (!square_holds_object(c, y, x, c->objects[obj->oidx])) { struct object *original = c->objects[obj->oidx]; square_excise_object(player->cave, y, x, obj); obj->iy = 0; obj->ix = 0; /* Delete objects which no longer exist anywhere */ if (obj->notice & OBJ_NOTICE_IMAGINED) { delist_object(player->cave, obj); object_delete(&obj); original->known = NULL; delist_object(c, original); object_delete(&original); } } obj = next; } }
/** * Pick up objects and treasure on the floor. -LM- * * Scan the list of objects in that floor grid. Pick up gold automatically. * Pick up objects automatically until backpack space is full if * auto-pickup option is on, otherwise, store objects on * floor in an array, and tally both how many there are and can be picked up. * * If not picking up anything, indicate objects on the floor. Do the same * thing if we don't have room for anything. * * Pick up multiple objects using Tim Baker's menu system. Recursively * call this function (forcing menus for any number of objects) until * objects are gone, backpack is full, or player is satisfied. * * We keep track of number of objects picked up to calculate time spent. * This tally is incremented even for automatic pickup, so we are careful * (in "dungeon.c" and elsewhere) to handle pickup as either a separate * automated move or a no-cost part of the stay still or 'g'et command. * * Note the lack of chance for the character to be disturbed by unmarked * objects. They are truly "unknown". * * \param obj is the object to pick up. * \param menu is whether to present a menu to the player */ static byte player_pickup_item(struct object *obj, bool menu) { int py = player->py; int px = player->px; struct object *current = NULL; int floor_max = z_info->floor_size + 1; struct object **floor_list = mem_zalloc(floor_max * sizeof(*floor_list)); int floor_num = 0; int i; int can_pickup = 0; bool call_function_again = FALSE; bool domsg = TRUE; /* Objects picked up. Used to determine time cost of command. */ byte objs_picked_up = 0; /* Always pickup gold, effortlessly */ player_pickup_gold(); /* Nothing else to pick up -- return */ if (!square_object(cave, py, px)) { mem_free(floor_list); return objs_picked_up; } /* Tally objects that can be picked up.*/ floor_num = scan_floor(floor_list, floor_max, py, px, 0x08, NULL); for (i = 0; i < floor_num; i++) if (inven_carry_okay(floor_list[i])) can_pickup++; if (!can_pickup) { /* Can't pick up, but probably want to know what's there. */ event_signal(EVENT_SEEFLOOR); mem_free(floor_list); return objs_picked_up; } /* Use the item that we are given, if it is on the floor. */ if (square_holds_object(cave, py, px, obj)) current = obj; /* Use a menu interface for multiple objects, or pickup single objects */ if (!menu && !current) { if (floor_num > 1) menu = TRUE; else current = floor_list[0]; } /* Display a list if requested. */ if (menu && !current) { const char *q, *s; struct object *obj1; /* Get an object or exit. */ q = "Get which item?"; s = "You see nothing there."; if (!get_item(&obj1, q, s, CMD_PICKUP, inven_carry_okay, USE_FLOOR)) { mem_free(floor_list); return (objs_picked_up); } current = obj1; call_function_again = TRUE; /* With a list, we do not need explicit pickup messages */ domsg = FALSE; } /* Pick up object, if legal */ if (current) { /* Pick up the object */ player_pickup_aux(current, domsg); /* Indicate an object picked up. */ objs_picked_up = 1; } /* * If requested, call this function recursively. Count objects picked * up. Force the display of a menu in all cases. */ if (call_function_again) objs_picked_up += player_pickup_item(NULL, TRUE); mem_free(floor_list); /* Indicate how many objects have been picked up. */ return (objs_picked_up); }
/** * Update the player's knowledge of the objects on a grid in the current level */ void floor_pile_know(struct chunk *c, int y, int x) { struct object *obj; if (c != cave) return; object_lists_check_integrity(); /* Know every item on this grid */ for (obj = square_object(c, y, x); obj; obj = obj->next) { struct object *known_obj = cave_k->objects[obj->oidx]; /* Make new known objects, fully know sensed ones, relocate old ones */ if (known_obj == NULL) { /* Make and/or list the new object */ struct object *new_obj; /* Check whether we need to make a new one or list the old one */ if (obj->known) { new_obj = obj->known; } else { new_obj = object_new(); obj->known = new_obj; object_set_base_known(obj); } cave_k->objects[obj->oidx] = new_obj; new_obj->oidx = obj->oidx; /* Attach it to the current floor pile */ new_obj->iy = y; new_obj->ix = x; new_obj->number = obj->number; if (!square_holds_object(cave_k, y, x, new_obj)) pile_insert_end(&cave_k->squares[y][x].obj, new_obj); } else if (known_obj->kind != obj->kind) { int iy = known_obj->iy; int ix = known_obj->ix; /* Make sure knowledge is correct */ assert(known_obj == obj->known); /* Detach from any old pile (possibly the correct one) */ if (iy && ix && square_holds_object(cave_k, iy, ix, known_obj)) square_excise_object(cave_k, iy, ix, known_obj); /* Copy over actual details */ object_set_base_known(obj); /* Attach it to the current floor pile */ known_obj->iy = y; known_obj->ix = x; known_obj->held_m_idx = 0; if (!square_holds_object(cave_k, y, x, known_obj)) pile_insert_end(&cave_k->squares[y][x].obj, known_obj); } else if (!square_holds_object(cave_k, y, x, known_obj)) { int iy = known_obj->iy; int ix = known_obj->ix; /* Make sure knowledge is correct */ assert(known_obj == obj->known); known_obj->number = obj->number; /* Detach from any old pile */ if (iy && ix && square_holds_object(cave_k, iy, ix, known_obj)) square_excise_object(cave_k, iy, ix, known_obj); /* Attach it to the current floor pile */ known_obj->iy = y; known_obj->ix = x; known_obj->held_m_idx = 0; pile_insert_end(&cave_k->squares[y][x].obj, known_obj); } } /* Remove known location of anything not on this grid */ obj = square_object(cave_k, y, x); while (obj) { struct object *next = obj->next; assert(c->objects[obj->oidx]); if (!square_holds_object(c, y, x, c->objects[obj->oidx])) { struct object *original = c->objects[obj->oidx]; square_excise_object(cave_k, y, x, obj); obj->iy = 0; obj->ix = 0; /* Delete objects which no longer exist anywhere */ if (obj->notice & OBJ_NOTICE_IMAGINED) { delist_object(cave_k, obj); object_delete(&obj); original->known = NULL; delist_object(c, original); object_delete(&original); } } obj = next; } }
/** * Wield or wear a single item from the pack or floor */ void inven_wield(struct object *obj, int slot) { struct object *wielded, *old = player->body.slots[slot].obj; const char *fmt; char o_name[80]; /* Increase equipment counter if empty slot */ if (old == NULL) player->upkeep->equip_cnt++; /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Split off a new object if necessary */ if (obj->number > 1) { /* Split off a new single object */ wielded = object_split(obj, 1); /* If it's a gear object, give the split item a list entry */ if (pile_contains(player->gear, obj)) { wielded->next = obj->next; obj->next = wielded; wielded->prev = obj; if (wielded->next) (wielded->next)->prev = wielded; } } else wielded = obj; /* Carry floor items, don't allow combining */ if (square_holds_object(cave, player->py, player->px, wielded)) { square_excise_object(cave, player->py, player->px, wielded); inven_carry(player, wielded, FALSE, FALSE); } /* Wear the new stuff */ player->body.slots[slot].obj = wielded; /* Do any ID-on-wield */ object_notice_on_wield(wielded); /* Where is the item now */ if (tval_is_melee_weapon(wielded)) fmt = "You are wielding %s (%c)."; else if (wielded->tval == TV_BOW) fmt = "You are shooting with %s (%c)."; else if (tval_is_light(wielded)) fmt = "Your light source is %s (%c)."; else fmt = "You are wearing %s (%c)."; /* Describe the result */ object_desc(o_name, sizeof(o_name), wielded, ODESC_PREFIX | ODESC_FULL); /* Message */ msgt(MSG_WIELD, fmt, o_name, I2A(slot)); /* Cursed! */ if (cursed_p(wielded->flags)) { /* Warn the player */ msgt(MSG_CURSED, "Oops! It feels deathly cold!"); /* Sense the object */ object_notice_curses(wielded); } /* See if we have to overflow the pack */ combine_pack(); pack_overflow(old); /* Recalculate bonuses, torch, mana, gear */ player->upkeep->notice |= (PN_IGNORE); player->upkeep->update |= (PU_BONUS | PU_INVEN); player->upkeep->redraw |= (PR_INVEN | PR_EQUIP | PR_ARMOR); player->upkeep->redraw |= (PR_STATS | PR_HP | PR_MANA | PR_SPEED); /* Disable repeats */ cmd_disable_repeat(); }