return; }   if (ae.isImmobile()) { phaseReport.append("    Charge cancelled as the attacker has been immobilized.\n");
    private void resolveChargeAttack(ChargeAttackAction caa, int lastEntityId) {        final Entity ae = game.getEntity(caa.getEntityId());        final Entity te = game.getEntity(caa.getTargetId());                // is the attacker dead?  because that sure messes up the calculations        if (ae == null) {            return;        }                final int direction = ae.getFacing();        // entity isn't charging any more        ae.setDisplacementAttack(null);        if (lastEntityId != caa.getEntityId()) {            phaseReport.append("\nPhysical attacks for " + ae.getDisplayName() + "\n");        }        // should we even bother?        if (te == null || te.isDestroyed() || te.isDoomed() || te.crew.isDead()) {            phaseReport.append("    Charge cancelled as the target has been destroyed.\n");            return;        }        // attacker fell down?        if (ae.isProne()) {            phaseReport.append("    Charge cancelled as the attacker has fallen.\n");            return;        }        phaseReport.append("    Charging " + te.getDisplayName());                // target still in the same position?        if (!te.getPosition().equals(caa.getTargetPos())) {            phaseReport.append(" but the target has moved.\n");            return;        }                // compute to-hit        ToHitData toHit = Compute.toHitCharge(game, caa);        // if the attacker's prone, fudge the roll        int roll;        if (toHit.getValue() == ToHitData.IMPOSSIBLE) {            roll = -12;            phaseReport.append(", but the charge is impossible (" + toHit.getDesc() + ") : ");        } else {            // roll            roll = Compute.d6(2);            phaseReport.append("; needs " + toHit.getValue() + ", ");            phaseReport.append("rolls " + roll + " : ");        }        // do we hit?        if (roll < toHit.getValue()) {            Coords src = ae.getPosition();            Coords dest = Compute.getMissedChargeDisplacement(game, ae.getId(), src, direction);            phaseReport.append("misses.\n");            // move attacker to side hex            doEntityDisplacement(ae, src, dest, null);            return;        }        // we hit...        int damage = Compute.getChargeDamageFor(ae);        int damageTaken = Compute.getChargeDamageTakenBy(ae, te);        phaseReport.append("hits.");        phaseReport.append("\n  Defender takes " + damage + " damage" + toHit.getTableDesc() + ".");        while (damage > 0) {            int cluster = Math.min(5, damage);            HitData hit = te.rollHitLocation(toHit.getHitTable(), toHit.getSideTable());            phaseReport.append(damageEntity(te, hit, cluster));            damage -= cluster;        }        phaseReport.append("\n  Attacker takes " + damageTaken + " damage.");        while (damageTaken > 0) {            int cluster = Math.min(5, damageTaken);            HitData hit = ae.rollHitLocation(ToHitData.HIT_NORMAL, toHit.SIDE_FRONT);            phaseReport.append(damageEntity(ae, hit, cluster));            damageTaken -= cluster;        }        // move attacker and target, if possible        Coords src = te.getPosition();        Coords dest = src.translated(direction);                    if (Compute.isValidDisplacement(game, te.getId(), te.getPosition(), direction)) {                phaseReport.append("\n");            doEntityDisplacement(te, src, dest, new PilotingRollData(te.getId(), 2, "was charged"));            doEntityDisplacement(ae, ae.getPosition(), src, new PilotingRollData(ae.getId(), 2, "charging"));        } else {          pilotRolls.addElement(new PilotingRollData(ae.getId(), 2, "charging"));          if (game.getOptions().booleanOption("push_off_board") && !game.board.contains(dest)) {            game.moveToGraveyard(te.getId());            send(createRemoveEntityPacket(te.getId()));            phaseReport.append("\n*** " + te.getDisplayName() + " target has been forced from the field. ***\n");            doEntityDisplacement(ae, ae.getPosition(), src, new PilotingRollData(ae.getId(), 2, "charging"));          } else {                // they stil have to roll            pilotRolls.addElement(new PilotingRollData(te.getId(), 2, "was charged"));          }        }        phaseReport.append("\n");    }