if (Compute.clubMechHas(from) != null) {
for(Iterator<Mounted> clubs=from.getClubs().iterator();clubs.hasNext();) { Mounted club = clubs.next();
    PhysicalOption getBestPhysicalAttack(Entity from, Entity to, IGame game) {        double bestDmg = 0, dmg, coll_damage, self_damage;        int damage;        int target_arc, location_table;        int bestType = PhysicalOption.PUNCH_LEFT;        // Infantry and tanks can't conduct any of these attacks        if ((from instanceof Infantry) || (from instanceof Tank)){            return null;        }                // Find arc the attack comes in        target_arc = CEntity.getThreatHitArc(to.getPosition(),                to.getFacing(), from.getPosition());                // Check for punches        // If the target is a Mech, must determine if punch lands on the punch, kick, or full table        if (to instanceof Mech){            if (!to.isProne()){                location_table = ToHitData.HIT_PUNCH;                if (to.getElevation() == from.getElevation()+1){                    location_table = ToHitData.HIT_KICK;                }            } else {                location_table = ToHitData.HIT_NORMAL;            }        } else {            location_table = ToHitData.HIT_NORMAL;        }                ToHitData odds = PunchAttackAction.toHit(game, from.getId(), to, PunchAttackAction.LEFT);        if (odds.getValue() != ToHitData.IMPOSSIBLE) {            damage = PunchAttackAction.getDamageFor(from, PunchAttackAction.LEFT);            bestDmg = Compute.oddsAbove(odds.getValue()) / 100.0 * damage;            // Adjust damage for targets armor            bestDmg *= punchThroughMod(to, game, location_table, target_arc, bestDmg, bestDmg);        }        odds = PunchAttackAction.toHit(game, from.getId(), to, PunchAttackAction.RIGHT);        if (odds.getValue() != ToHitData.IMPOSSIBLE) {            damage = PunchAttackAction.getDamageFor(from, PunchAttackAction.RIGHT);            dmg = Compute.oddsAbove(odds.getValue()) / 100.0 * damage;            // Adjust damage for targets armor            dmg *= punchThroughMod(to, game, location_table, target_arc, dmg, dmg);            if (dmg > bestDmg){                bestType = PhysicalOption.PUNCH_RIGHT;                bestDmg = dmg;            }        }                // Check for a double punch        odds = PunchAttackAction.toHit(game, from.getId(), to, PunchAttackAction.LEFT);        ToHitData odds_a = PunchAttackAction.toHit(game, from.getId(), to, PunchAttackAction.RIGHT);        if ((odds.getValue() != ToHitData.IMPOSSIBLE) && (odds_a.getValue() != ToHitData.IMPOSSIBLE)){            damage = PunchAttackAction.getDamageFor(from, PunchAttackAction.LEFT);            dmg = Compute.oddsAbove(odds.getValue()) / 100.0 * damage;            double dmg_a = Compute.oddsAbove(odds_a.getValue()) / 100.0 * damage;            dmg += dmg_a;            dmg *= punchThroughMod(to, game, location_table, target_arc, dmg, dmg/2);            if (dmg > bestDmg){                bestType = PhysicalOption.PUNCH_BOTH;                bestDmg = dmg;            }        }        // Check for a kick        // If the target is a Mech, must determine if it lands on the kick or punch table        if (to instanceof Mech){            location_table = ToHitData.HIT_KICK;            if (!to.isProne()){                if (to.getElevation() == from.getElevation()-1){                    location_table = ToHitData.HIT_PUNCH;                }            } else {                location_table = ToHitData.HIT_NORMAL;            }        } else {            location_table = ToHitData.HIT_NORMAL;        }        // Calculate collateral damage, due to possible target fall        // = chance of successful kick * chance of target falling * target falling damage        coll_damage = 0;        if (to instanceof Mech){            coll_damage = (Compute.oddsAbove(odds.getValue())/100.0) *                 (Compute.oddsAbove((1-to.getBasePilotingRoll().getValue()))/100.0) *                 to.getWeight() * 0.1;        }        odds = KickAttackAction.toHit(game, from.getId(), to, KickAttackAction.LEFT);        if (odds.getValue() != ToHitData.IMPOSSIBLE) {            self_damage = 0;            damage = KickAttackAction.getDamageFor(from, KickAttackAction.LEFT);            dmg = Compute.oddsAbove(odds.getValue()) / 100.0 * damage;            // Adjust damage for targets armor            dmg *= punchThroughMod(to, game, location_table, target_arc, dmg, dmg);            // Calculate self damage, due to possible fall from missing a kick            // Odds of missing the kick, odds of falling, falling damage, and            // a factor to account for how bad it is for this unit to be prone            self_damage = 1 - Compute.oddsAbove(odds.getValue()) / 100.0;            self_damage = self_damage * (1 - Compute.oddsAbove(from.getBasePilotingRoll().getValue())/100.0);            self_damage = self_damage * from.getWeight() * 0.1;            if (from.getWalkMP() > 0){                self_damage = self_damage * Math.sqrt((1/(double)from.getWalkMP()) + from.getJumpMP());            } else {                self_damage = self_damage * Math.sqrt(from.getJumpMP());            }            // Add together damage values for comparison            dmg = dmg + coll_damage - self_damage;            if (dmg > bestDmg) {                bestType = PhysicalOption.KICK_LEFT;                bestDmg = dmg;            }        }        odds = KickAttackAction.toHit(game, from.getId(), to, KickAttackAction.RIGHT);        if (odds.getValue() != ToHitData.IMPOSSIBLE) {            self_damage = 0;            damage = KickAttackAction.getDamageFor(from, KickAttackAction.RIGHT);            dmg = Compute.oddsAbove(odds.getValue()) / 100.0 * damage;            // Adjust damage for targets armor            dmg *= punchThroughMod(to, game, location_table, target_arc, dmg, dmg);            // Calculate self damage, due to possible fall from missing a kick            // Odds of missing the kick, odds of falling, falling damage, and            // a factor to account for how bad it is for this unit to be prone            self_damage = 1 - (Compute.oddsAbove(odds.getValue()) / 100.0);            self_damage = self_damage * (1 - Compute.oddsAbove(from.getBasePilotingRoll().getValue())/100.0);            self_damage = self_damage * from.getWeight() * 0.1;            if (from.getWalkMP() > 0){                self_damage = self_damage * Math.sqrt((1/(double)from.getWalkMP()) + from.getJumpMP());            } else {                self_damage = self_damage * Math.sqrt(from.getJumpMP());            }            // Add together damage values for comparison            dmg = dmg + coll_damage - self_damage;            if (dmg > bestDmg) {                bestType = PhysicalOption.KICK_RIGHT;                bestDmg = dmg;            }        }                // Check for mounted club-type weapon or carried improvised club        if (Compute.clubMechHas(from) != null) {                    // If the target is a Mech, must determine if it hits full body, punch, or kick table            if (to instanceof Mech){                location_table = ToHitData.HIT_NORMAL;                if ((to.getElevation() == from.getElevation()-1) && !(to.isProne())){                    location_table = ToHitData.HIT_PUNCH;                }                if ((to.getElevation() == from.getElevation()+1) && !(to.isProne())){                    location_table = ToHitData.HIT_KICK;                }            } else {                location_table = ToHitData.HIT_NORMAL;            }            odds = ClubAttackAction.toHit(game, from.getId(), to, Compute.clubMechHas(from));            if (odds.getValue() != ToHitData.IMPOSSIBLE) {                damage = ClubAttackAction.getDamageFor(from, Compute.clubMechHas(from));                dmg = Compute.oddsAbove(odds.getValue()) / 100.0 * damage;                // Adjust damage for targets armor                dmg *= punchThroughMod(to, game, location_table, target_arc, dmg, dmg);                // Some types of clubs, such as the mace, require a piloting check on a missed attack                // Calculate self damage in the same manner as a missed kick                if (dmg > bestDmg) {                    bestType = PhysicalOption.USE_CLUB;                    bestDmg = dmg;                }            }        }        // Check for a push attack        odds = PushAttackAction.toHit(game, from.getId(), to);        if (odds.getValue() != ToHitData.IMPOSSIBLE) {            int elev_diff = 1;            double breach = 1;            boolean water_landing = false;            dmg = 0;            int disp_dir = from.getPosition().direction(to.getPosition());            Coords disp_c = to.getPosition().translated(disp_dir);            // If the displacement hex is a valid one            if (Compute.isValidDisplacement(game, to.getId(), to.getPosition(), disp_c)){                // If the displacement hex is not on the map, credit damage                // against full target armor                if (!game.getBoard().contains(disp_c)){                    dmg = to.getTotalArmor() * Compute.oddsAbove(odds.getValue()) / 100.0;                }                if (game.getBoard().contains(disp_c)){                // Find the elevation difference                    elev_diff = game.getBoard().getHex(to.getPosition()).getElevation();                    elev_diff -= game.getBoard().getHex(disp_c).getElevation();                    if (elev_diff < 0){                        elev_diff = 0;                    }                // Set a flag if the displacement hex has water                    if (game.getBoard().getHex(disp_c).containsTerrain(Terrains.WATER)){                        water_landing = true;                    }                // Get the base damage from target falling -> chance of hitting,                // chance of target falling, falling damage                    dmg = Compute.oddsAbove(odds.getValue()) / 100.0;                    dmg = dmg * (1 - Compute.oddsAbove(elev_diff + to.getBasePilotingRoll().getValue())/100.0);                    dmg = dmg * to.getWeight() * 0.1 * (1 + elev_diff);                // Calculate breach factor of falling damage                    breach = punchThroughMod(to, game, ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT, dmg, Math.min(dmg, 5));                // If breach factor is > 1 and displacement hex has water                    if ((breach > 1) && water_landing){                        breach *= 2;                    }                // Modify damage to reflect how bad it is for target to be prone                    if (to.getWalkMP() > 0){                        dmg = dmg * Math.sqrt((1/(double)to.getWalkMP()) + to.getJumpMP());                    } else {                        dmg = dmg * Math.max(1, Math.sqrt(to.getJumpMP()));                    }                // Modify damage by breach factor                    dmg *= breach;                }            }            // If the displacement hex is not valid            if (!Compute.isValidDisplacement(game, to.getId(), to.getPosition(), disp_c)){                // Set a flag if the displacement hex has water                if (game.getBoard().getHex(to.getPosition()).containsTerrain(Terrains.WATER)){                    water_landing = true;                }                // Get the base damage from target falling -> chance of hitting,                // chance of target falling, falling damage                dmg = Compute.oddsAbove(odds.getValue()) / 100.0;                dmg = dmg * (1 - Compute.oddsAbove(to.getBasePilotingRoll().getValue())/100.0);                dmg = dmg * to.getWeight() * 0.1;                // Calculate breach factor of falling damage                breach = punchThroughMod(to, game, ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT, dmg, Math.min(dmg, 5));                // If breach factor is > 1 and target hex is in water                if ((breach > 1) && water_landing){                    breach *= 2;                }                // Modify damage to reflect how bad it is for target to be prone                if (to.getWalkMP() > 0){                    dmg = dmg * Math.sqrt((1/to.getWalkMP()) + to.getJumpMP());                } else {                    dmg = dmg * Math.max(1, Math.sqrt(to.getJumpMP()));                }                // Modify damage by breach factor                dmg *= breach;            }            // If damage is better than best damage            if (dmg > bestDmg) {                bestType = PhysicalOption.PUSH_ATTACK;                bestDmg = dmg;            }        }                // Conventional infantry in the open suffer double damage.        if ((to instanceof Infantry) && !(to instanceof BattleArmor)) {            IHex e_hex = game.getBoard().getHex(to.getPosition());            if (!e_hex.containsTerrain(Terrains.WOODS) && !e_hex.containsTerrain(Terrains.BUILDING)) {                bestDmg *= 2;            }        }        if (bestDmg > 0) {            return new PhysicalOption(from, to, bestDmg, bestType);        }        return null;    }