/** * 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; }
/** * Read a monster */ static bool rd_monster(struct chunk *c, struct monster *mon) { byte tmp8u; u16b tmp16u; char race_name[80]; size_t j; /* Read the monster race */ rd_string(race_name, sizeof(race_name)); mon->race = lookup_monster(race_name); if (!mon->race) { note(format("Monster race %s no longer exists!", race_name)); return (-1); } /* Read the other information */ rd_byte(&mon->fy); rd_byte(&mon->fx); rd_s16b(&mon->hp); rd_s16b(&mon->maxhp); rd_byte(&mon->mspeed); rd_byte(&mon->energy); rd_byte(&tmp8u); for (j = 0; j < tmp8u; j++) rd_s16b(&mon->m_timed[j]); /* Read and extract the flag */ for (j = 0; j < mflag_size; j++) rd_byte(&mon->mflag[j]); for (j = 0; j < of_size; j++) rd_byte(&mon->known_pstate.flags[j]); for (j = 0; j < elem_max; j++) rd_s16b(&mon->known_pstate.el_info[j].res_level); rd_u16b(&tmp16u); if (tmp16u) { /* Find and set the mimicked object */ struct object *square_obj = square_object(c, mon->fy, mon->fx); /* Try and find the mimicked object; if we fail, create a new one */ while (square_obj) { if (square_obj->mimicking_m_idx == tmp16u) break; square_obj = square_obj->next; } if (square_obj) { mon->mimicked_obj = square_obj; } else { mon_create_mimicked_object(c, mon, tmp16u); } } /* Read all the held objects (order is unimportant) */ while (true) { struct object *obj = rd_item(); if (!obj) break; pile_insert(&mon->held_obj, obj); assert(obj->oidx); assert(c->objects[obj->oidx] == NULL); c->objects[obj->oidx] = obj; } return true; }
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; }