/** * Sense the existence of objects on a grid in the current level */ void floor_pile_sense(struct chunk *c, int y, int x) { struct object *obj; if (c != cave) return; /* Sense 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 sensed objects where necessary */ if (known_obj == NULL) { /* Make and list the new object */ struct object *new_obj = object_new(); cave_k->objects[obj->oidx] = new_obj; new_obj->oidx = obj->oidx; obj->known = new_obj; new_obj->number = 1; /* Give it a fake kind */ if (tval_is_money(obj)) new_obj->kind = unknown_gold_kind; else new_obj->kind = unknown_item_kind; /* Attach it to the current floor pile */ new_obj->iy = y; new_obj->ix = x; pile_insert_end(&cave_k->squares[y][x].obj, new_obj); } } }
/** * Let the floor carry an object, deleting old ignored items if necessary. * The calling function must deal with the dropped object on failure. * * Optionally put the object at the top or bottom of the pile */ bool floor_carry(struct chunk *c, int y, int x, struct object *drop, bool last) { int n = 0; struct object *obj, *ignore = floor_get_oldest_ignored(y, x); /* Fail if the square can't hold objects */ if (!square_isobjectholding(c, y, x)) return false; /* Scan objects in that grid for combination */ for (obj = square_object(c, y, x); obj; obj = obj->next) { /* Check for combination */ if (object_similar(obj, drop, OSTACK_FLOOR)) { /* Combine the items */ object_absorb(obj, drop); /* Result */ return true; } /* Count objects */ n++; } /* The stack is already too large */ if (n >= z_info->floor_size || (!OPT(player, birth_stacking) && n)) { /* Delete the oldest ignored object */ if (ignore) { square_excise_object(c, y, x, ignore); delist_object(c, ignore); object_delete(&ignore); } else return false; } /* Location */ drop->iy = y; drop->ix = x; /* Forget monster */ drop->held_m_idx = 0; /* Link to the first or last object in the pile */ if (last) pile_insert_end(&c->squares[y][x].obj, drop); else pile_insert(&c->squares[y][x].obj, drop); /* Record in the level list */ list_object(c, drop); /* Redraw */ square_note_spot(c, y, x); square_light_spot(c, y, x); /* Result */ return true; }
void gear_insert_end(struct object *obj) { pile_insert_end(&player->gear, obj); pile_insert_end(&player->gear_k, obj->known); }
/** * 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; } }
NOTEARDOWN /* Testing the linked list functions in obj-pile.c */ int test_obj_piles(void *state) { struct object *pile = NULL; struct object *o1 = object_new(); struct object *o2 = object_new(); struct object *o3 = object_new(); struct object *o4 = object_new(); pile_insert(&pile, o1); eq(pile_contains(pile, o1), TRUE); eq(pile_contains(pile, o2), FALSE); ptreq(pile, o1); ptreq(pile_last_item(pile), o1); pile_insert_end(&pile, o2); eq(pile_contains(pile, o1), TRUE); eq(pile_contains(pile, o2), TRUE); eq(pile_contains(pile, o3), FALSE); ptreq(pile, o1); ptreq(pile_last_item(pile), o2); pile_insert_end(&pile, o3); eq(pile_contains(pile, o1), TRUE); eq(pile_contains(pile, o2), TRUE); eq(pile_contains(pile, o3), TRUE); ptreq(pile, o1); ptreq(pile_last_item(pile)->prev, o2); ptreq(pile_last_item(pile), o3); /* Now let's try excision */ /* From the top */ pile_excise(&pile, o1); ptreq(pile, o2); eq(pile_contains(pile, o1), FALSE); /* Now put it back */ pile_insert(&pile, o1); /* From the end */ pile_excise(&pile, o3); ptreq(pile, o1); eq(pile_contains(pile, o3), FALSE); ptreq(pile_last_item(pile), o2); ptreq(pile_last_item(pile)->prev, o1); object_delete(o3); /* Now put it back, and add another */ o3 = object_new(); pile_insert_end(&pile, o3); pile_insert_end(&pile, o4); /* Try removing from the middle */ pile_excise(&pile, o3); ptreq(pile, o1); /* Now the list should look like o1 <-> o2 <-> o4, so check that */ ptreq(o1->prev, NULL); ptreq(o1->next, o2); ptreq(o2->prev, o1); ptreq(o2->next, o4); ptreq(o3->prev, NULL); ptreq(o3->next, NULL); ptreq(o4->prev, o2); ptreq(o4->next, NULL); /* Free up */ object_pile_free(pile); ok; }