protected void spawnUnit(GPoint T) {
   if (T != null) {
     // spawns unit with random direction
     units[spawnUnitIndex].setXYCoordinate(T, map);
     units[spawnUnitIndex].setDirectionFacing(((int) (Math.random() * 4)));
     spawnUnitIndex++;
   }
 }
  protected void randomRotate(Unit U) {
    // random rotate while exploring

    didsomething = true;
    rando = (int) (Math.random() * 2);
    if (rando == 0) U.rotateLeft();
    else U.rotateRight();

    U.usePoints(U.getRotationCost());
  }
  protected void updateTurnPhase() {

    if (newTurn) {
      newTurn = false;

      for (int i = 0; i < UnitNoCombat.length; i++) UnitNoCombat[i] = true;

      // rotate based on hit indicators
      respondToHits();
    }

    endturnplz = true;

    for (int i = 0; i < units.length; i++) {
      if (!units[i].isDead) {
        // cheat peek
        strategize(units[i]);

        // if points left for an attack
        if (units[i].getPointsLeft() >= units[i].abilities[0].getCost()) {
          endturnplz = false;

          if (units[i].getUnitType() == Unit.UnitType.ASSAULT) assaultAction(units[i], i);
          else if (units[i].getUnitType() == Unit.UnitType.CQC) cqcAction(units[i], i);
          else if (units[i].getUnitType() == Unit.UnitType.MEDIC) medicAction(units[i], i);
          else if (units[i].getUnitType() == Unit.UnitType.RECON) reconAction(units[i], i);
          else if (units[i].getUnitType() == Unit.UnitType.SNIPER) sniperAction(units[i], i);
          else if (units[i].getUnitType() == Unit.UnitType.PRESIDENT) presidentAction(units[i], i);
        }
        // else if points left for move and unit has not been in combat. exploring
        else if ((units[i].getPointsLeft() >= units[i].getMovementCost()) && UnitNoCombat[i]) {
          useMovement(units[i]);

          // 1/5 chance of random rotate while exploring
          if (units[i].getPointsLeft() > 0) {
            rando = (int) (Math.random() * 5);
            if (rando == 0) randomRotate(units[i]);
          }
        }
      }
    }
    if (endturnplz) {
      newTurn = true;
      hitIndicators.clear(); // remove any hit indicators
      map.switchTurn();
    }
  }
  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 void strategize(Unit U) {
    // cheat peek. 1/30 chance to look left and right to see if there are any enemies there
    // without spending points. Then rotate using points if enemies found
    // helps prevent the npc from just walking straight across the map
    // seaching simulator

    rando = (int) (Math.random() * 30);
    if (rando == 0) {
      U.rotateLeft();
      target = findTarget(U.abilities[0], U);
      if (target != null) U.usePoints(U.getRotationCost());
      else {
        U.rotateRight();
        U.rotateRight();
        target = findTarget(U.abilities[0], U);
        if (target != null) U.usePoints(U.getRotationCost());
        else U.rotateLeft();
      }
    }
  }
  protected void reconAction(Unit U, int I) {
    // recon tries trick shot and then runs away, or does normal attack, or basic movement

    didsomething = false;

    if (U.pointsLeft >= U.abilities[1].getCost()) {
      defaultAction(U, U.abilities[1], I);

      if (U.pointsLeft > 0) {
        rando = (int) (Math.random() * 2);
        if (rando == 0) U.rotateLeft();
        else U.rotateRight();
      }
    }

    if (!didsomething) {
      if (U.pointsLeft >= U.abilities[0].getCost()) defaultAction(U, U.abilities[0], I);
    }

    if (!didsomething) useMovement(U);
  }
  protected void updateSetupPhase() {
    // spawns one unit per frame

    List<GPoint> base = new ArrayList<GPoint>();

    // gets possible spawn points
    for (int row = 0; row < map.getNum_vertical_tiles(); row++) {
      for (int col = 0; col < map.getNum_horizontal_tiles(); col++) {
        if (!isPlayerOne && map.getTile(row, col).getFeatureType() == MapFeature.PLAYER_TWO_BASE)
          if (!map.getTile(row, col).hasUnit()) base.add(new GPoint(row, col));
      }
    }

    // if more units to spawn, pick a random valid spawn point and spawn
    if (spawnUnitIndex < units.length) {
      rando = (int) (Math.random() * base.size());
      spawnUnit(base.get(rando));
      base.clear();
    } else {
      // if everything spawned, switch turn
      isSetupPhase = false;
      map.switchTurn();
    }
  }