#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "emlen.h"

#define ARC  8

int headp;
int bodyp;
int legsp;
int armsp;

bool 
onepass_grab_armor (CHAR_DATA * ch, int attack_type)
{
  SINGLE_OBJECT *o;
  I_ARMOR *r;
  int protect = 0;
  int mod = 10;
  int tprotect = 0;

  if (attack_type > 1000)
    attack_type -= 1000;

  if (IS_PLAYER (ch))
    {
      tprotect = (100 - ch->armor) / ARC;
      headp = tprotect;
      bodyp = tprotect;
      legsp = tprotect;
      armsp = tprotect;
    }
  if (HAS_HANDS_ARMOR_IMPLANT (ch))
    armsp += 3;
  if (HAS_BODY_ARMOR_IMPLANT (ch))
    bodyp += 3;

  for (o = ch->carrying; o != NULL; o = o->next_content)
    {
      if (o->wear_loc == -1)
	continue;
      if (o->pIndexData->item_type != ITEM_ARMOR)
	continue;
      r = (I_ARMOR *) o->more;
      if (r->protects_arms > 0)
	{
	  if (attack_type < 0)
	    mod = 10;
	  else if (attack_type == 1 || attack_type == 3)
	    mod = r->slash_rating;
	  else if (attack_type == 2 || attack_type == 11)
	    mod = r->pierce_rating;
	  else if (attack_type == 4)
	    mod = 10;
	  else
	    mod = r->pound_rating;
	  protect = (r->protects_arms * mod) / 10;
	  if (r->max_condition == 0)
	    armsp += protect;
	  else
	    armsp += ((protect * ((r->condition_now * 10) / r->max_condition)) / 10);
	}
      if (r->protects_legs > 0)
	{
	  if (attack_type < 0)
	    mod = 10;
	  else if (attack_type == 1 || attack_type == 3)
	    mod = r->slash_rating;
	  else if (attack_type == 2 || attack_type == 11)
	    mod = r->pierce_rating;
	  else if (attack_type == 4)
	    mod = 10;
	  else
	    mod = r->pound_rating;
	  protect = (r->protects_legs * mod) / 10;
	  if (r->max_condition == 0)
	    legsp += protect;
	  else
	    legsp += ((protect * ((r->condition_now * 10) / r->max_condition)) / 10);
	}
      if (r->protects_head > 0)
	{
	  if (attack_type < 0)
	    mod = 10;
	  else if (attack_type == 1 || attack_type == 3)
	    mod = r->slash_rating;
	  else if (attack_type == 2 || attack_type == 11)
	    mod = r->pierce_rating;
	  else if (attack_type == 4)
	    mod = 10;
	  else
	    mod = r->pound_rating;
	  protect = (r->protects_head * mod) / 10;
	  if (r->max_condition == 0)
	    headp += protect;
	  else
	    headp += ((protect * ((r->condition_now * 10) / r->max_condition)) / 10);
	}
      if (r->protects_body > 0)
	{
	  if (attack_type < 0)
	    mod = 10;
	  else if (attack_type == 1 || attack_type == 3)
	    mod = r->slash_rating;
	  else if (attack_type == 2 || attack_type == 11)
	    mod = r->pierce_rating;
	  else if (attack_type == 4)
	    mod = 10;
	  else
	    mod = r->pound_rating;
	  protect = (r->protects_body * mod) / 10;
	  if (r->max_condition == 0)
	    bodyp += protect;
	  else
	    bodyp += ((protect * ((r->condition_now * 10) / r->max_condition)) / 10);
	}
    }
  return (armsp + legsp + headp + bodyp) / 4;
}


int 
find_arm_protection (CHAR_DATA * ch, int attack_type)
{
  SINGLE_OBJECT *o;
  I_ARMOR *r;
  int protect = 0;
  int mod = 10;
  int tprotect = 0;

  if (attack_type > 1000)
    attack_type -= 1000;

  if (IS_PLAYER (ch))
    tprotect = (100 - ch->armor) / ARC;
  if (HAS_HANDS_ARMOR_IMPLANT (ch))
    tprotect += 3;

  for (o = ch->carrying; o != NULL; o = o->next_content)
    {
      if (o->wear_loc == -1)
	continue;
      if (o->pIndexData->item_type != ITEM_ARMOR)
	continue;
      r = (I_ARMOR *) o->more;
      if (r->protects_arms < 1)
	continue;

      if (attack_type < 0)
	mod = 10;
      else if (attack_type == 1 || attack_type == 3)
	mod = r->slash_rating;
      else if (attack_type == 2 || attack_type == 11)
	mod = r->pierce_rating;
      else if (attack_type == 4)
	mod = 10;
      else
	mod = r->pound_rating;

      protect = (r->protects_arms * mod) / 10;
      if (r->max_condition == 0)
	tprotect += protect;
      else
	tprotect += ((protect * ((r->condition_now * 10) / r->max_condition)) / 10);
    }

  return tprotect;
}



int 
find_leg_protection (CHAR_DATA * ch, int attack_type)
{
  SINGLE_OBJECT *o;
  I_ARMOR *r;
  int protect = 0;
  int mod = 10;
  int tprotect = 0;

  if (attack_type > 1000)
    attack_type -= 1000;

  if (IS_PLAYER (ch))
    tprotect = (100 - ch->armor) / ARC;

  for (o = ch->carrying; o != NULL; o = o->next_content)
    {
      if (o->wear_loc == -1)
	continue;
      if (o->pIndexData->item_type != ITEM_ARMOR)
	continue;
      r = (I_ARMOR *) o->more;
      if (r->protects_legs < 1)
	continue;

      if (attack_type < 0)
	mod = 10;
      else if (attack_type == 1 || attack_type == 3)
	mod = r->slash_rating;
      else if (attack_type == 2 || attack_type == 11)
	mod = r->pierce_rating;
      else if (attack_type == 4)
	mod = 10;
      else
	mod = r->pound_rating;

      protect = (r->protects_legs * mod) / 10;
      if (r->max_condition == 0)
	tprotect += protect;
      else
	tprotect += ((protect * ((r->condition_now * 10) / r->max_condition)) / 10);
    }

  return tprotect;
}



int 
find_body_protection (CHAR_DATA * ch, int attack_type)
{
  SINGLE_OBJECT *o;
  I_ARMOR *r;
  int protect = 0;
  int mod = 10;
  int tprotect = 0;

  if (attack_type > 1000)
    attack_type -= 1000;
  if (IS_PLAYER (ch))
    tprotect = (100 - ch->armor) / ARC;
  if (HAS_BODY_ARMOR_IMPLANT (ch))
    tprotect += 3;

  for (o = ch->carrying; o != NULL; o = o->next_content)
    {
      if (o->wear_loc == -1)
	continue;
      if (o->pIndexData->item_type != ITEM_ARMOR)
	continue;
      r = (I_ARMOR *) o->more;
      if (r->protects_body < 1)
	continue;

      if (attack_type < 0)
	mod = 10;
      else if (attack_type == 1 || attack_type == 3)
	mod = r->slash_rating;
      else if (attack_type == 2 || attack_type == 11)
	mod = r->pierce_rating;
      else if (attack_type == 4)
	mod = 10;
      else
	mod = r->pound_rating;

      protect = (r->protects_body * mod) / 10;
      if (r->max_condition == 0)
	tprotect += protect;
      else
	tprotect += ((protect * ((r->condition_now * 10) / r->max_condition)) / 10);
    }

  return tprotect;
}



int 
find_head_protection (CHAR_DATA * ch, int attack_type)
{
  SINGLE_OBJECT *o;
  I_ARMOR *r;
  int protect = 0;
  int mod = 10;
  int tprotect = 0;

  if (attack_type > 1000)
    attack_type -= 1000;
  if (IS_PLAYER (ch))
    tprotect = (100 - ch->armor) / ARC;

  for (o = ch->carrying; o != NULL; o = o->next_content)
    {
      if (o->wear_loc == -1)
	continue;
      if (o->pIndexData->item_type != ITEM_ARMOR)
	continue;
      r = (I_ARMOR *) o->more;
      if (r->protects_head < 1)
	continue;

      if (attack_type < 0)
	mod = 10;
      else if (attack_type == 1 || attack_type == 3)
	mod = r->slash_rating;
      else if (attack_type == 2 || attack_type == 11)
	mod = r->pierce_rating;
      else if (attack_type == 4)
	mod = 10;
      else
	mod = r->pound_rating;

      protect = (r->protects_head * mod) / 10;
      if (r->max_condition == 0)
	tprotect += protect;
      else
	tprotect += ((protect * ((r->condition_now * 10) / r->max_condition)) / 10);
    }

  return tprotect;
}


int 
general_ac (CHAR_DATA * ch)
{
  return onepass_grab_armor (ch, -1);
}


int 
new_damage_2 (CHAR_DATA * ch, int damage, int hit_loc, int dt)
{
  int i = 0;
  int prot;
  if (hit_loc == STRIKE_BODY)
    i = find_body_protection (ch, dt);
  if (hit_loc == STRIKE_HEAD)
    i = find_head_protection (ch, dt);
  if (hit_loc == STRIKE_LEGS)
    i = find_head_protection (ch, dt);
  if (hit_loc == STRIKE_ARMS)
    i = find_head_protection (ch, dt);
  if (IS_MOB (ch))
    {
      i += ((60 - ch->armor) / 12);
      if (i < 0)
	return damage;
    }
  if (i > 9)
    i = 8;
  prot = number_range (0, i);
  if (prot >= damage)
    return 1;
  return (damage - prot);
}

int 
new_damage (CHAR_DATA * ch, int damage, int hit_loc, int dt)
{
  int i = 0;
  int prot;
  if (hit_loc == STRIKE_BODY)
    i = find_body_protection (ch, dt);
  if (hit_loc == STRIKE_HEAD)
    i = find_head_protection (ch, dt);
  if (hit_loc == STRIKE_LEGS)
    i = find_head_protection (ch, dt);
  if (hit_loc == STRIKE_ARMS)
    i = find_head_protection (ch, dt);
  if (IS_MOB (ch))
    {
      i += ((60 - ch->armor) / 12);
      if (i < 0)
	return damage;
    }
  prot = number_range (0, i);
  if (prot >= damage)
    return 1;
  return (damage - prot);
}

char *
pval (int i)
{
  static char rv[50];
  int j;
  rv[0] = '\0';
  for (j = 0; j < 20; j++)
    {
      if (pow.armor_lev_word[j] && i >= pow.armor_lev_min[j] && i <= pow.armor_lev_max[j])
	{
	  sprintf (rv, pow.armor_lev_word[j]);
	  return rv;
	}
    }
  return rv;
}


void 
do_armor (CHAR_DATA * ch, char *argy)
{
  char tmp[500];
  int head;
  int body;
  int legs;
  int arms;
  int tt;
  DEFINE_COMMAND ("armor", do_armor, POSITION_DEAD, 0, LOG_NORMAL, "This command shows your current armor protection levels.")
    tt = onepass_grab_armor (ch, -1);

  sprintf (tmp, "   O         <-- Head/Neck:  %s\n\r", pval (headp));
  send_to_char (tmp, ch);
  sprintf (tmp, "/--|--\\      <-- Arms/Hands: %s\n\r", pval (armsp));
  send_to_char (tmp, ch);
  sprintf (tmp, "   |         <-- Body/Waist: %s\n\r", pval (bodyp));
  send_to_char (tmp, ch);
  sprintf (tmp, "  / \\        <-- Legs/Feet:  %s\n\r", pval (legsp));
  send_to_char (tmp, ch);
  sprintf (tmp, "_/   \\_          ------------------------\n\r");
  send_to_char (tmp, ch);
  sprintf (tmp, "                 %s\n\r", (pval (tt)));
  send_to_char (tmp, ch);
  if (IS_PLAYER (ch) && (ch->pcdata->implants_1 != 0 || ch->pcdata->implants_2 != 0))
    {
      send_to_char ("Implants:\n\r", ch);
      if (HAS_ARMS_STRENGTH_IMPLANT (ch))
	send_to_char ("Enhanced Arm Strength.\n\r", ch);
      if (HAS_LEGS_STRENGTH_IMPLANT (ch))
	send_to_char ("Enhanced Leg Strength.\n\r", ch);
      if (HAS_HANDS_STRENGTH_IMPLANT (ch))
	send_to_char ("Enhanced Hand Strength.\n\r", ch);
      if (HAS_BODY_STRENGTH_IMPLANT (ch))
	send_to_char ("Enhanced Body/Torso Muscle.\n\r", ch);
      if (HAS_ARMS_DEXTERITY_IMPLANT (ch))
	send_to_char ("Enhanced Dexterity in Arms.\n\r", ch);
      if (HAS_LEGS_RUNNING_IMPLANT (ch))
	send_to_char ("Enhanced Leg Durability.\n\r", ch);
      if (HAS_HEAD_BRAIN_IMPLANT (ch))
	send_to_char ("Intelli+ Brain Microchip.\n\r", ch);
      if (HAS_FEET_IMPLANT (ch))
	send_to_char ("Bionic Feet and Ankles.\n\r", ch);
      if (HAS_HANDS_ARMOR_IMPLANT (ch))
	send_to_char ("Sub-Dermal Metal Hand Plates.\n\r", ch);
      if (HAS_BODY_ARMOR_IMPLANT (ch))
	send_to_char ("Titanium Sternum and Rib Replacement.\n\r", ch);
    }
  return;
}

void 
get_condition (SINGLE_OBJECT * obj)
{
  char buf[500];
  condition_var[0] = '\0';
  if (obj->pIndexData->item_type == ITEM_ARMOR)
    {
      I_ARMOR *armor = (I_ARMOR *) obj->more;
      int percent;
      strcpy (buf, "Unknown");
      if (armor->max_condition == 0 && armor->condition_now == 0)
	strcpy (buf, "Indestructable");
      else
	{
	  percent = PERCENTAGE (armor->condition_now, armor->max_condition);
	  if (percent < 10)
	    strcpy (buf, "Almost unusable");
	  else if (percent < 30)
	    strcpy (buf, "Falling apart");
	  else if (percent < 50)
	    strcpy (buf, "Poor condition");
	  else if (percent < 65)
	    strcpy (buf, "Fair condition");
	  else if (percent < 90)
	    strcpy (buf, "Good condition");
	  else
	    strcpy (buf, "Brand new");
	}
    }
  if (obj->pIndexData->item_type == ITEM_WEAPON)
    {
      I_WEAPON *weap = (I_WEAPON *) obj->more;
      if (weap->damage_p < 3)
	strcpy (buf, "Broken");
      else if (weap->damage_p < 10)
	strcpy (buf, "Almost broken");
      else if (weap->damage_p < 40)
	strcpy (buf, "Badly damaged");
      else if (weap->damage_p < 70)
	strcpy (buf, "Damaged");
      else if (weap->damage_p < 90)
	strcpy (buf, "Good condition");
      else
	strcpy (buf, "Brand new");
    }
  strcpy (condition_var, buf);
  return;
}


char *
format_obj_to (SINGLE_OBJECT * obj, CHAR_DATA * ch, bool fShort)
{
  static char buf[STD_LENGTH];
  buf[0] = '\0';
  if (fShort)
    {
      char duh[500];
      sprintf (duh, "%s\x1B[37;0m", ans_uppercase (OOSTR (obj, short_descr)));
      strcat (buf, duh);

      if (obj->pIndexData->item_type == ITEM_ARMOR)
	{
	  I_ARMOR *armor = (I_ARMOR *) obj->more;
	  int percent;
	  if (armor->max_condition == 0 && armor->condition_now == 0)
	    strcat (buf, " (indestructable)");
	  else
	    {
	      percent = PERCENTAGE (armor->condition_now, armor->max_condition);
	      if (percent < 10)
		strcat (buf, " (almost unusable)");
	      else if (percent < 30)
		strcat (buf, " (falling apart)");
	      else if (percent < 50)
		strcat (buf, " (poor condition)");
	      else if (percent < 65)
		strcat (buf, " (fair condition)");
	      else if (percent < 90)
		strcat (buf, " (good condition)");
	      else
		strcat (buf, " (brand new)");
	    }
	}
      if (obj->pIndexData->item_type == ITEM_WEAPON)
	{
	  I_WEAPON *weap = (I_WEAPON *) obj->more;
	  if (weap->damage_p < 1)
	    strcat (buf, " (broken)");
	  else if (weap->damage_p < 10)
	    strcat (buf, " (almst broken)");
	  else if (weap->damage_p < 40)
	    strcat (buf, " (badly damged)");
	  else if (weap->damage_p < 64)
	    strcat (buf, " (damaged)");
	  else if (weap->damage_p < 90)
	    strcat (buf, " (good cond)");
	  else
	    strcat (buf, " (brand new)");
	}
      if (obj->pIndexData->item_type == ITEM_GEM)
	{
	  I_GEM *gem = (I_GEM *) obj->more;
	  if (gem->mana_now < 10)
	    strcat (buf, " (very dim)");
	  else if (gem->mana_now < 20)
	    strcat (buf, " (dim)");
	  else if (gem->mana_now < 65)
	    strcat (buf, " (soft glow)");
	  else if (gem->mana_now < 100)
	    strcat (buf, " (bright glow)");
	  else if (gem->mana_now < 140)
	    strcat (buf, " (intense glow)");
	  else
	    strcat (buf, " (radiating power)");
	}
      if (obj->pIndexData->item_type == ITEM_LIGHT && IS_LIT (obj))
	{
	  int percent;
	  I_LIGHT *lgt = (I_LIGHT *) obj->more;
	  percent = (PERCENTAGE (lgt->light_now, lgt->max_light) / 10);
	  switch (percent)
	    {
	    case 0:
	      strcat (buf, " (very dim)");
	      break;
	    case 1:
	      strcat (buf, " (dim)");
	      break;
	    case 2:
	      strcat (buf, " (flickering)");
	      break;
	    default:
	      strcat (buf, "\x1B[33;1m (brightly lit)\x1B[37;0m");
	      break;
	    }
	}
      if (obj->pIndexData->item_type == ITEM_WAND || obj->pIndexData->item_type == ITEM_STAFF)
	{
	  I_WAND *ws = (I_WAND *) obj->more;
	  int percent;
	  percent = ws->current_charges;
	  switch (percent)
	    {
	    case 0:
	      strcat (buf, " (powerless)");
	      break;
	    case 1:
	      strcat (buf, " (dim glow)");
	      break;
	    case 2:
	      strcat (buf, " (glowing)");
	      break;
	    default:
	      strcat (buf, "\x1B[33;1m (bright glow)\x1B[37;0m");
	      break;
	    }
	}
      strcat (buf, "\x1B[0m");
      if (!(IS_OBJ_STAT (obj, ITEM_GLOW) || IS_OBJ_STAT (obj, ITEM_HUM) || IS_OBJ_STAT (obj, ITEM_INVIS) || IS_OBJ_STAT (obj, ITEM_UNSEEN)))
	strcat (buf, "\n\r");
    }
  else
    {
      if (obj->pIndexData->item_type == ITEM_LIGHT && IS_LIT (obj))
	{
	  I_LIGHT *light = (I_LIGHT *) obj->more;
	  int percent;
	  percent = (PERCENTAGE (light->light_now, light->max_light) / 10);
	  switch (percent)
	    {
	    case 0:
	      strcat (buf, "(Very dim)-> ");
	      break;
	    case 1:
	      strcat (buf, "(Dim)-> ");
	      break;
	    case 2:
	      strcat (buf, "(Flickering)-> ");
	      break;
	    default:
	      strcat (buf, "\x1B[33;1m(Brightly lit)->\x1B[36;0m ");
	      break;
	    }
	}
      strcat (buf, STR (obj, description));
    }
  if (!IS_OBJ_STAT (obj, ITEM_INVIS) && !IS_OBJ_STAT (obj, ITEM_UNSEEN) &&
   (!(IS_AFFECTED (ch, AFF_DETECT_EVIL) && IS_OBJ_STAT (obj, ITEM_EVIL))) &&
   (!(IS_AFFECTED (ch, AFF_DETECT_GOOD) && IS_OBJ_STAT (obj, ITEM_GOOD))) &&
    (!(IS_AFFECTED (ch, AFF_DETECT_MAGIC) && IS_OBJ_STAT (obj, ITEM_MAGIC)))
      && !IS_OBJ_STAT (obj, ITEM_GLOW) && !IS_OBJ_STAT (obj, ITEM_HUM)
      && !IS_OBJ_STAT (obj, ITEM_UNSEEN)
    )
    return buf;
  if (IS_OBJ_STAT (obj, ITEM_GLOW) && IS_OBJ_STAT (obj, ITEM_HUM))
    {
      strcat (buf, "\x1B[1m..it Glows and Hums with power! \x1B[0m");
    }
  else
    {
      if (IS_OBJ_STAT (obj, ITEM_GLOW))
	strcat (buf, "\x1B[1m..it Glows with energy! \x1B[0m");
      if (IS_OBJ_STAT (obj, ITEM_HUM))
	strcat (buf, "\x1B[1m..it Hums with power! \x1B[0m");
    }
  if (!IS_OBJ_STAT (obj, ITEM_INVIS) && !IS_OBJ_STAT (obj, ITEM_UNSEEN) &&
   (!(IS_AFFECTED (ch, AFF_DETECT_EVIL) && IS_OBJ_STAT (obj, ITEM_EVIL))) &&
   (!(IS_AFFECTED (ch, AFF_DETECT_GOOD) && IS_OBJ_STAT (obj, ITEM_GOOD))) &&
   (!(IS_AFFECTED (ch, AFF_DETECT_MAGIC) && IS_OBJ_STAT (obj, ITEM_MAGIC))))
    {
      strcat (buf, "\n\r");
      return buf;
    }
  if (IS_OBJ_STAT (obj, ITEM_INVIS))
    {
      strcat (buf, "\x1B[1;30m (Invis) \x1B[0m");
      if (!IS_OBJ_STAT (obj, ITEM_UNSEEN) &&
	  (!(IS_AFFECTED (ch, AFF_DETECT_EVIL) && IS_OBJ_STAT (obj, ITEM_EVIL))) &&
	  (!(IS_AFFECTED (ch, AFF_DETECT_GOOD) && IS_OBJ_STAT (obj, ITEM_GOOD))) &&
	  (!(IS_AFFECTED (ch, AFF_DETECT_MAGIC) && IS_OBJ_STAT (obj, ITEM_MAGIC))))
	{
	  strcat (buf, "\n\r");
	  return buf;
	}
    }
  if (IS_OBJ_STAT (obj, ITEM_UNSEEN))
    {
      strcat (buf, "\x1B[1;30m (Unseen) \x1B[0m");
      if (
	   (!(IS_AFFECTED (ch, AFF_DETECT_EVIL) && IS_OBJ_STAT (obj, ITEM_EVIL))) &&
	   (!(IS_AFFECTED (ch, AFF_DETECT_GOOD) && IS_OBJ_STAT (obj, ITEM_GOOD))) &&
	   (!(IS_AFFECTED (ch, AFF_DETECT_MAGIC) && IS_OBJ_STAT (obj, ITEM_MAGIC))))
	{
	  strcat (buf, "\n\r");
	  return buf;
	}
    }
  if (IS_AFFECTED (ch, AFF_DETECT_GOOD)
      && IS_OBJ_STAT (obj, ITEM_GOOD))
    {
      strcat (buf, "\x1B[33;1m (Gold Aura) \x1B[0m");
      if (
	   (!(IS_AFFECTED (ch, AFF_DETECT_EVIL) && IS_OBJ_STAT (obj, ITEM_EVIL))) &&
	   (!(IS_AFFECTED (ch, AFF_DETECT_MAGIC) && IS_OBJ_STAT (obj, ITEM_MAGIC))))
	{
	  strcat (buf, "\n\r");
	  return buf;
	}
    }
  if (IS_AFFECTED (ch, AFF_DETECT_EVIL)
      && IS_OBJ_STAT (obj, ITEM_EVIL))
    {
      strcat (buf, "\x1B[31m (Red Aura) \x1B[0m");
      if ((!(IS_AFFECTED (ch, AFF_DETECT_MAGIC) && IS_OBJ_STAT (obj, ITEM_MAGIC))))
	{
	  strcat (buf, "\n\r");
	  return buf;
	}
    }
  if (IS_AFFECTED (ch, AFF_DETECT_MAGIC)
      && IS_OBJ_STAT (obj, ITEM_MAGIC))
    strcat (buf, "\x1B[33;1m (Magical) \x1B[0m\n\r");
  return buf;
}