} }   else { if (hex.contains(Terrain.SMOKE)) { if (hex.levelOf(Terrain.SMOKE) == 1) { los.lightSmoke++; } else if (hex.levelOf(Terrain.SMOKE) > 1) { los.heavySmoke++; } }  if (hex.levelOf(Terrain.WOODS) == 1) { los.lightWoods++; } else if (hex.levelOf(Terrain.WOODS) > 1) { los.heavyWoods++; }
    private static LosEffects losForCoords(Game game, AttackInfo ai,                                           Coords coords, Building thruBldg) {        LosEffects los = new LosEffects();                // ignore hexes not on board        if (!game.board.contains(coords)) {            return los;        }            // Is there a building in this hex?        Building bldg = game.board.getBuildingAt(coords);            // We're only tracing thru a single building if there        // is a building in this hex, and if it isn't the same        // building that we'be been tracing LOS thru.        if ( bldg != null && bldg.equals(thruBldg) ) {            los.setThruBldg( thruBldg );        }            // ignore hexes the attacker or target are in        if ( coords.equals(ai.attackPos) ||             coords.equals(ai.targetPos) ) {            return los;        }            Hex hex = game.board.getHex(coords);        int hexEl = ai.underWaterCombat ? hex.floor() : hex.surface();            // Handle building elevation.        // Attacks thru a building are not blocked by that building.        // ASSUMPTION: bridges don't block LOS.        int bldgEl = 0;        if ( null == los.getThruBldg() &&             hex.contains( Terrain.BLDG_ELEV ) ) {            bldgEl = hex.levelOf( Terrain.BLDG_ELEV );        }            // TODO: Identify when LOS travels *above* a building's hex.        //       Alternatively, force all building hexes to be same height.            // check for block by terrain        if ((hexEl + bldgEl > ai.attackAbsHeight && hexEl + bldgEl > ai.targetAbsHeight)        || (hexEl + bldgEl > ai.attackAbsHeight && ai.attackPos.distance(coords) == 1)        || (hexEl + bldgEl > ai.targetAbsHeight && ai.targetPos.distance(coords) == 1)) {            los.blocked = true;        }            // check for woods or smoke only if not under water        if (!ai.underWaterCombat) {            if ((hexEl + 2 > ai.attackAbsHeight && hexEl + 2 > ai.targetAbsHeight)            || (hexEl + 2 > ai.attackAbsHeight && ai.attackPos.distance(coords) == 1)            || (hexEl + 2 > ai.targetAbsHeight && ai.targetPos.distance(coords) == 1)) {                // smoke overrides any woods in the hex                if (hex.contains(Terrain.SMOKE)) {                    los.smoke++;                } else if (hex.levelOf(Terrain.WOODS) == 1) {                    los.lightWoods++;                } else if (hex.levelOf(Terrain.WOODS) > 1) {                    los.heavyWoods++;                }            }        }                // check for target partial cover        if ( ai.targetPos.distance(coords) == 1 &&             hexEl + bldgEl == ai.targetAbsHeight &&             ai.attackAbsHeight <= ai.targetAbsHeight && ai.targetHeight > 0) {            los.targetCover = true;        }            // check for attacker partial cover        if (ai.attackPos.distance(coords) == 1 &&            hexEl + bldgEl == ai.attackAbsHeight &&            ai.attackAbsHeight >= ai.targetAbsHeight && ai.attackHeight > 0) {            los.attackerCover = true;        }                return los;    }