public static void update(ViewGroup group, Actor actor) {
    TableLayout actorinfo_stats_table =
        (TableLayout) group.findViewById(R.id.actorinfo_stats_table);

    updateTraitsTable(
        actorinfo_stats_table,
        actor.getMoveCost(),
        actor.getAttackCost(),
        actor.getAttackChance(),
        actor.getDamagePotential(),
        actor.getCriticalSkill(),
        actor.getCriticalMultiplier(),
        actor.getBlockChance(),
        actor.getDamageResistance(),
        actor.isImmuneToCriticalHits());

    TextView actorinfo_currentconditions_title =
        (TextView) group.findViewById(R.id.actorinfo_currentconditions_title);
    ActorConditionList actorinfo_currentconditions =
        (ActorConditionList) group.findViewById(R.id.actorinfo_currentconditions);
    if (actor.conditions.isEmpty()) {
      actorinfo_currentconditions_title.setVisibility(View.GONE);
      actorinfo_currentconditions.setVisibility(View.GONE);
    } else {
      actorinfo_currentconditions_title.setVisibility(View.VISIBLE);
      actorinfo_currentconditions.setVisibility(View.VISIBLE);
      actorinfo_currentconditions.update(actor.conditions);
    }
  }
 private static float getAverageDamagePerHit(Actor attacker, Actor target) {
   float result =
       (float) (getAttackHitChance(attacker, target))
           * attacker.getDamagePotential().average()
           / 100;
   if (hasCriticalAttack(attacker, target)) {
     result +=
         (float) attacker.getEffectiveCriticalChance()
             * result
             * attacker.getCriticalMultiplier()
             / 100;
   }
   result -= target.getDamageResistance();
   return result;
 }
  private void applyAttackHitStatusEffects(Actor attacker, Actor target) {
    ItemTraits_OnUse[] onHitEffects = attacker.getOnHitEffects();
    if (onHitEffects == null) return;

    for (ItemTraits_OnUse e : onHitEffects) {
      controllers.actorStatsController.applyUseEffect(attacker, target, e);
    }
  }
  public void applyAbilityEffects(Actor actor, AbilityModifierTraits effects, int multiplier) {
    if (effects == null) return;

    addActorMaxHealth(actor, effects.increaseMaxHP * multiplier, false);
    addActorMaxAP(actor, effects.increaseMaxAP * multiplier, false);

    addActorMoveCost(actor, effects.increaseMoveCost * multiplier);
    addActorAttackCost(actor, effects.increaseAttackCost * multiplier);
    // criticalMultiplier should not be increased. It is always defined by the weapon in use.
    actor.attackChance += effects.increaseAttackChance * multiplier;
    actor.criticalSkill += effects.increaseCriticalSkill * multiplier;
    actor.damagePotential.add(effects.increaseMinDamage * multiplier, true);
    actor.damagePotential.addToMax(effects.increaseMaxDamage * multiplier);
    actor.blockChance += effects.increaseBlockChance * multiplier;
    actor.damageResistance += effects.increaseDamageResistance * multiplier;

    if (actor.attackChance < 0) actor.attackChance = 0;
    if (actor.damagePotential.max < 0) actor.damagePotential.set(0, 0);
  }
  private AttackResult attack(final Actor attacker, final Actor target) {
    int hitChance = getAttackHitChance(attacker, target);
    if (!Constants.roll100(hitChance)) return AttackResult.MISS;

    int damage = Constants.rollValue(attacker.getDamagePotential());
    boolean isCriticalHit = false;
    if (hasCriticalAttack(attacker, target)) {
      isCriticalHit = Constants.roll100(attacker.getEffectiveCriticalChance());
      if (isCriticalHit) {
        damage *= attacker.getCriticalMultiplier();
      }
    }
    damage -= target.getDamageResistance();
    if (damage < 0) damage = 0;
    controllers.actorStatsController.removeActorHealth(target, damage);

    applyAttackHitStatusEffects(attacker, target);

    return new AttackResult(true, isCriticalHit, damage, target.isDead());
  }
  private static int getTurnsToKillTarget(Actor attacker, Actor target) {
    if (hasCriticalAttack(attacker, target)) {
      if (attacker.getDamagePotential().max * attacker.getCriticalMultiplier()
          <= target.getDamageResistance()) return 999;
    } else {
      if (attacker.getDamagePotential().max <= target.getDamageResistance()) return 999;
    }

    float averageDamagePerTurn = getAverageDamagePerTurn(attacker, target);
    if (averageDamagePerTurn <= 0) return 100;
    return (int) FloatMath.ceil(target.getMaxHP() / averageDamagePerTurn);
  }
  public static void updateTraitsTable(
      ViewGroup group,
      int moveCost,
      int attackCost,
      int attackChance,
      Range damagePotential,
      int criticalSkill,
      float criticalMultiplier,
      int blockChance,
      int damageResistance,
      boolean isImmuneToCriticalHits) {
    TableRow row;
    TextView tv;

    tv = (TextView) group.findViewById(R.id.traitsinfo_move_cost);
    tv.setText(Integer.toString(moveCost));

    tv = (TextView) group.findViewById(R.id.traitsinfo_attack_cost);
    tv.setText(Integer.toString(attackCost));

    row = (TableRow) group.findViewById(R.id.traitsinfo_attack_chance_row);
    if (attackChance == 0) {
      row.setVisibility(View.GONE);
    } else {
      row.setVisibility(View.VISIBLE);
      tv = (TextView) group.findViewById(R.id.traitsinfo_attack_chance);
      tv.setText(Integer.toString(attackChance) + '%');
    }

    row = (TableRow) group.findViewById(R.id.traitsinfo_attack_damage_row);
    if (damagePotential != null && damagePotential.max != 0) {
      row.setVisibility(View.VISIBLE);
      tv = (TextView) group.findViewById(R.id.traitsinfo_attack_damage);
      tv.setText(damagePotential.toMinMaxString());
    } else {
      row.setVisibility(View.GONE);
    }

    row = (TableRow) group.findViewById(R.id.traitsinfo_criticalhit_skill_row);
    if (criticalSkill == 0) {
      row.setVisibility(View.GONE);
    } else {
      row.setVisibility(View.VISIBLE);
      tv = (TextView) group.findViewById(R.id.traitsinfo_criticalhit_skill);
      tv.setText(Integer.toString(criticalSkill));
    }

    row = (TableRow) group.findViewById(R.id.traitsinfo_criticalhit_multiplier_row);
    if (criticalMultiplier != 0 && criticalMultiplier != 1) {
      row.setVisibility(View.VISIBLE);
      tv = (TextView) group.findViewById(R.id.traitsinfo_criticalhit_multiplier);
      tv.setText(Float.toString(criticalMultiplier));
    } else {
      row.setVisibility(View.GONE);
    }

    row = (TableRow) group.findViewById(R.id.traitsinfo_criticalhit_effectivechance_row);
    if (criticalSkill != 0 && criticalMultiplier != 0 && criticalMultiplier != 1) {
      row.setVisibility(View.VISIBLE);
      tv = (TextView) group.findViewById(R.id.traitsinfo_criticalhit_effectivechance);
      tv.setText(Integer.toString(Actor.getEffectiveCriticalChance(criticalSkill)) + '%');
    } else {
      row.setVisibility(View.GONE);
    }

    row = (TableRow) group.findViewById(R.id.traitsinfo_block_chance_row);
    if (blockChance == 0) {
      row.setVisibility(View.GONE);
    } else {
      row.setVisibility(View.VISIBLE);
      tv = (TextView) group.findViewById(R.id.traitsinfo_block_chance);
      tv.setText(Integer.toString(blockChance) + '%');
    }

    row = (TableRow) group.findViewById(R.id.traitsinfo_damageresist_row);
    if (damageResistance == 0) {
      row.setVisibility(View.GONE);
    } else {
      row.setVisibility(View.VISIBLE);
      tv = (TextView) group.findViewById(R.id.traitsinfo_damageresist);
      tv.setText(Integer.toString(damageResistance));
    }

    row = (TableRow) group.findViewById(R.id.traitsinfo_is_immune_to_critical_hits_row);
    row.setVisibility(isImmuneToCriticalHits ? View.VISIBLE : View.GONE);
  }
 public void addActorAttackCost(Actor actor, int amount) {
   if (amount == 0) return;
   actor.attackCost += amount;
   if (actor.attackCost <= 0) actor.attackCost = 1;
   actorStatsListeners.onActorAttackCostChanged(actor, actor.attackCost);
 }
 private static int getAttackHitChance(final Actor attacker, final Actor target) {
   final int c = attacker.getAttackChance() - target.getBlockChance();
   // (2/pi)*atan(..) will vary from -1 to +1 .
   return (int) (50 * (1 + two_divided_by_PI * (float) Math.atan((float) (c - n) / F)));
 }
 private static float getAverageDamagePerTurn(Actor attacker, Actor target) {
   return getAverageDamagePerHit(attacker, target) * attacker.getAttacksPerTurn();
 }
 private static boolean hasCriticalAttack(Actor attacker, Actor target) {
   if (!attacker.hasCriticalAttacks()) return false;
   if (target.isImmuneToCriticalHits()) return false;
   return true;
 }