void CreatureAttributes::consume(Creature* self, const CreatureAttributes& other) {
  Debug() << name->bare() << " consume " << other.name->bare();
  self->you(MsgType::CONSUME, other.name->the());
  consumeBodyParts(self, other);
  if (other.isHumanoid() && !isHumanoid() && numBodyParts(BodyPart::ARM) >= 2 && numBodyParts(BodyPart::LEG) >= 2
      && numBodyParts(BodyPart::HEAD) >= 1) {
    self->you(MsgType::BECOME, "a humanoid");
    self->addPersonalEvent(getName().the() + " turns into a humanoid");
    humanoid = true;
  }
  vector<string> adjectives;
  for (auto t : ENUM_ALL(AttrType))
    consumeAttr(attr[t], other.attr[t], adjectives, getAttrNameMore(t));
  consumeAttr(*size, *other.size, adjectives, "larger");
  consumeAttr(*weight, *other.weight, adjectives, "");
  consumeAttr(barehandedDamage, other.barehandedDamage, adjectives, "more dangerous");
  consumeAttr(barehandedAttack, other.barehandedAttack, adjectives, "");
  consumeAttr(attackEffect, other.attackEffect, adjectives, "");
  consumeAttr(passiveAttack, other.passiveAttack, adjectives, "");
  consumeAttr(gender, other.gender, adjectives);
  consumeAttr(skills, other.skills, adjectives);
  if (!adjectives.empty()) {
    self->you(MsgType::BECOME, combine(adjectives));
    self->addPersonalEvent(getName().the() + " becomes " + combine(adjectives));
  }
  consumeBodyParts(self,other);
  consumeEffects(other.permanentEffects);
}
string CreatureAttributes::bodyDescription() const {
  vector<string> ret;
  bool anyLimbs = false;
  auto listParts = {BodyPart::ARM, BodyPart::LEG, BodyPart::WING};
  if (*humanoid)
    listParts = {BodyPart::WING};
  for (BodyPart part : listParts)
    if (int num = numBodyParts(part)) {
      ret.push_back(getPluralText(getBodyPartName(part), num));
      anyLimbs = true;
    }
  if (*humanoid) {
    bool noArms = numBodyParts(BodyPart::ARM) == 0;
    bool noLegs = numBodyParts(BodyPart::LEG) == 0;
    if (noArms && noLegs)
      ret.push_back("no limbs");
    else if (noArms)
      ret.push_back("no arms");
    else if (noLegs)
      ret.push_back("no legs");
  } else
  if (!anyLimbs)
    ret.push_back("no limbs");
  if (numBodyParts(BodyPart::HEAD) == 0)
    ret.push_back("no head");
  if (ret.size() > 0)
    return " with " + combine(ret);
  else
    return "";
}
string CreatureAttributes::bodyDescription() const {
  vector<string> ret;
  for (BodyPart part : {BodyPart::ARM, BodyPart::LEG, BodyPart::WING})
    if (int num = numBodyParts(part))
      ret.push_back(getPlural(getBodyPartName(part), num));
  if (isHumanoid() && numBodyParts(BodyPart::HEAD) == 0)
    ret.push_back("no head");
  if (ret.size() > 0)
    return " with " + combine(ret);
  else
    return "";
}
vector<PItem> CreatureAttributes::getCorpseItem(Creature::Id id) {
  return makeVec<PItem>(
      ItemFactory::corpse(getName().bare() + " corpse", getName().bare() + " skeleton", *weight,
        isMinionFood() ? ItemClass::FOOD : ItemClass::CORPSE,
        {id, true, numBodyParts(BodyPart::HEAD) > 0, false}));
}
int CreatureAttributes::numGood(BodyPart part) const {
  return numBodyParts(part) - numInjured(part);
}