protected void useAbility(Unit U, Ability A, GPoint T) {
    // uses the selected ability on the selected target
    // code copied from player class

    // decrement action points
    U.usePoints(A.getCost());

    // get the tiles that were affected by the attack
    List<AttackedTile> tilesAffected = A.getTilesAffected(U, T, map);

    for (int j = 0; j < tilesAffected.size(); j++) {
      MapTile tile = map.getTile(tilesAffected.get(j).tile);

      if (tile.hasUnit()) { // there is a unit on the tile
        int unitId = tile.getUnit_id();
        Unit unit = map.getUnit(unitId);

        // reduce unit health by attack dmg
        if (unit != null) {
          DamageDealt damageDone = unit.takeDamage(tilesAffected.get(j).damageTaken, map);
          healthIndicators.add(
              new HealthIndicator(
                  map,
                  new GPoint(tilesAffected.get(j).tile.row, tilesAffected.get(j).tile.col),
                  30,
                  damageDone.healthDamage,
                  indicatorPaint,
                  false));
          if (damageDone.isAttack && damageDone.armorDamage < 0) {
            healthIndicators.add(
                new HealthIndicator(
                    map,
                    new GPoint(tilesAffected.get(j).tile.row, tilesAffected.get(j).tile.col),
                    0,
                    damageDone.armorDamage,
                    indicatorPaint,
                    true));
          }
          if (U != unit && damageDone.isAttack) // don't send indicator for heals
          map.sendHitIndicator(new HitIndicator(U, A, unit, tilesAffected.get(j).tile, map), unit);
        }
      }
    }
  }
  protected GPoint findGrenadeTarget(Ability A, Unit U) {
    // searches for an attackable spot that would hit the most enemies for the most damage
    // must hit at least 2 enemies
    // 1/24 chance to see aoe

    int Cur_units = 0;
    int Cur_damage = 0;
    int New_units = 0;
    int New_damage = 0;

    GPoint itarget = null;

    rando = (int) (Math.random() * 24);
    if (rando == 0) vis = A.getTilesAttackable(U, map);
    else vis = Vision.getSprintVision(map, U, 3);

    for (int i = 0; i < vis.size(); i++) {
      List<AttackedTile> tilesAffected = A.getTilesAffected(U, vis.get(i), map);
      for (int j = 0; j < tilesAffected.size(); j++) {
        if (map.getTile(tilesAffected.get(j).tile).hasUnit()) {
          if (map.getTile(tilesAffected.get(j).tile).getPlayer_id() != playerId) {
            New_units++;
            New_damage += tilesAffected.get(j).damageTaken;
          }
        }
      }

      if ((itarget == null)
          || (New_units > Cur_units)
          || ((New_units == Cur_units) && (New_damage > Cur_damage))) {
        itarget = new GPoint(vis.get(i));
        Cur_units = New_units;
        Cur_damage = New_damage;
      }

      New_units = 0;
      New_damage = 0;
    }
    vis.clear();

    if (Cur_units < 2) itarget = null;

    return itarget;
  }
  protected GPoint findTarget(Ability A, Unit U) {
    // searches attackable tiles and picks the target with the least hp

    GPoint itarget = null;
    vis = A.getTilesAttackable(U, map);

    for (int i = 0; i < vis.size(); i++) {
      if (map.getTile(vis.get(i)).hasUnit())
        if (map.getTile(vis.get(i)).getPlayer_id() != playerId) {
          if (itarget == null) itarget = new GPoint(vis.get(i));

          if (map.getUnit(map.getTile(itarget).getUnit_id()).health
              > map.getUnit(map.getTile(vis.get(i)).getUnit_id()).health)
            itarget = new GPoint(vis.get(i));
        }
    }
    vis.clear();
    return itarget;
  }
  protected GPoint findHealTarget(Ability A, Unit U, int HP) {
    // searches for a target with less than the specified HP

    GPoint itarget = null;
    vis = A.getTilesAttackable(U, map);

    for (int i = 0; i < vis.size(); i++) {
      if (map.getTile(vis.get(i)).hasUnit())
        if (map.getTile(vis.get(i)).getPlayer_id() == playerId) {
          if (itarget == null) itarget = new GPoint(vis.get(i));

          if (map.getUnit(map.getTile(itarget).getUnit_id()).health
              > map.getUnit(map.getTile(vis.get(i)).getUnit_id()).health)
            itarget = new GPoint(vis.get(i));
        }
    }
    vis.clear();

    if (map.getUnit(map.getTile(itarget).getUnit_id()).health > HP) itarget = null;

    return itarget;
  }