/**
   * figure out where to place the second settlement
   *
   * @return {@link #secondSettlement}, or -1 if none
   */
  public int planSecondSettlement() {
    log.debug("--- planSecondSettlement");

    int bestSpeed = 4 * SOCBuildingSpeedEstimate.DEFAULT_ROLL_LIMIT;
    final SOCBoard board = game.getBoard();
    SOCResourceSet emptySet = new SOCResourceSet();
    SOCPlayerNumbers playerNumbers = new SOCPlayerNumbers(board);
    boolean[] ports = new boolean[SOCBoard.WOOD_PORT + 1];
    SOCBuildingSpeedEstimate estimate = new SOCBuildingSpeedEstimate();
    int probTotal;
    int bestProbTotal;
    final int[] prob = SOCNumberProbabilities.INT_VALUES;
    final int firstNode = firstSettlement;

    bestProbTotal = 0;
    secondSettlement = -1;

    final int[] ourPotentialSettlements = ourPlayerData.getPotentialSettlements_arr();
    if (ourPotentialSettlements == null) return -1; // Should not occur

    for (int i = 0; i < ourPotentialSettlements.length; ++i) {
      final int secondNode = ourPotentialSettlements[i];
      // assert: ourPlayerData.isPotentialSettlement(secondNode)

      if (board.isNodeAdjacentToNode(secondNode, firstNode))
        continue; // <-- too close to firstNode to build --

      /** get the numbers for these settlements */
      StringBuffer sb = new StringBuffer();
      sb.append("numbers: ");
      playerNumbers.clear();
      probTotal = playerNumbers.updateNumbersAndProbability(firstNode, board, prob, sb);
      probTotal += playerNumbers.updateNumbersAndProbability(secondNode, board, prob, sb);

      /** see if the settlements are on any ports */
      // sb.append("ports: ");

      Arrays.fill(ports, false);
      int portType = board.getPortTypeFromNodeCoord(firstNode);
      if (portType != -1) ports[portType] = true;
      portType = board.getPortTypeFromNodeCoord(secondNode);
      if (portType != -1) ports[portType] = true;

      // log.debug(sb.toString());
      log.debug("probTotal = " + probTotal);

      /** estimate the building speed for this pair */
      estimate.recalculateEstimates(playerNumbers);

      int speed = 0;

      try {
        speed +=
            estimate
                .calculateRollsAndRsrcFast(emptySet, SOCGame.SETTLEMENT_SET, bestSpeed, ports)
                .getRolls();

        if (speed < bestSpeed) {
          speed +=
              estimate
                  .calculateRollsAndRsrcFast(emptySet, SOCGame.CITY_SET, bestSpeed, ports)
                  .getRolls();

          if (speed < bestSpeed) {
            speed +=
                estimate
                    .calculateRollsAndRsrcFast(emptySet, SOCGame.CARD_SET, bestSpeed, ports)
                    .getRolls();

            if (speed < bestSpeed) {
              speed +=
                  estimate
                      .calculateRollsAndRsrcFast(emptySet, SOCGame.ROAD_SET, bestSpeed, ports)
                      .getRolls();
            }
          }
        }

        // because of addition, speed might be as much as (bestSpeed - 1) + bestSpeed
      } catch (CutoffExceededException e) {
        speed = bestSpeed;
      }

      log.debug(
          Integer.toHexString(firstNode) + ", " + Integer.toHexString(secondNode) + ":" + speed);

      /** keep the settlements with the best speed */
      if ((speed < bestSpeed) || (secondSettlement < 0)) {
        firstSettlement = firstNode;
        secondSettlement = secondNode;
        bestSpeed = speed;
        bestProbTotal = probTotal;
        log.debug("firstSettlement = " + Integer.toHexString(firstSettlement));
        log.debug("secondSettlement = " + Integer.toHexString(secondSettlement));

        int[] rolls = estimate.getEstimatesFromNothingFast(ports);
        sb = new StringBuffer();
        sb.append("road: " + rolls[SOCBuildingSpeedEstimate.ROAD]);
        sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]);
        sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]);
        sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]);
        log.debug(sb.toString());
        log.debug("bestSpeed = " + bestSpeed);
      } else if (speed == bestSpeed) {
        if (probTotal > bestProbTotal) {
          firstSettlement = firstNode;
          secondSettlement = secondNode;
          bestSpeed = speed;
          bestProbTotal = probTotal;
          log.debug("firstSettlement = " + Integer.toHexString(firstSettlement));
          log.debug("secondSettlement = " + Integer.toHexString(secondSettlement));

          int[] rolls = estimate.getEstimatesFromNothingFast(ports);
          sb = new StringBuffer();
          sb.append("road: " + rolls[SOCBuildingSpeedEstimate.ROAD]);
          sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]);
          sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]);
          sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]);
          log.debug(sb.toString());
          log.debug("bestSpeed = " + bestSpeed);
        }
      }
    } // for (i in ourPotentialSettlements[])

    return secondSettlement;
  }
  /**
   * figure out where to place the two settlements
   *
   * @return {@link #firstSettlement}, or 0 if no potential settlements for our player
   */
  public int planInitialSettlements() {
    log.debug("--- planInitialSettlements");

    int speed;
    boolean allTheWay;
    firstSettlement = 0;
    secondSettlement = 0;

    int bestSpeed = 4 * SOCBuildingSpeedEstimate.DEFAULT_ROLL_LIMIT;
    SOCBoard board = game.getBoard();
    SOCResourceSet emptySet = new SOCResourceSet();
    SOCPlayerNumbers playerNumbers = new SOCPlayerNumbers(board);
    int probTotal;
    int bestProbTotal;
    boolean[] ports = new boolean[SOCBoard.WOOD_PORT + 1];
    SOCBuildingSpeedEstimate estimate = new SOCBuildingSpeedEstimate();
    final int[] prob = SOCNumberProbabilities.INT_VALUES;

    bestProbTotal = 0;

    final int[] ourPotentialSettlements = ourPlayerData.getPotentialSettlements_arr();
    if (ourPotentialSettlements == null) return 0; // Should not occur

    for (int i = 0; i < ourPotentialSettlements.length; ++i) {
      final int firstNode = ourPotentialSettlements[i];
      // assert: ourPlayerData.isPotentialSettlement(firstNode)

      final Integer firstNodeInt = new Integer(firstNode);

      //
      // this is just for testing purposes
      //
      log.debug("FIRST NODE -----------");
      log.debug("firstNode = " + board.nodeCoordToString(firstNode));

      StringBuffer sb = new StringBuffer();
      sb.append("numbers:[");

      playerNumbers.clear();
      probTotal = playerNumbers.updateNumbersAndProbability(firstNode, board, prob, sb);

      sb.append("]");
      log.debug(sb.toString());
      sb = new StringBuffer();
      sb.append("ports: ");

      for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
        ports[portType] = (board.getPortCoordinates(portType).contains(firstNodeInt));

        sb.append(ports[portType] + "  ");
      }

      log.debug(sb.toString());
      log.debug("probTotal = " + probTotal);
      estimate.recalculateEstimates(playerNumbers);
      speed = 0;
      allTheWay = false;

      try {
        speed +=
            estimate
                .calculateRollsAndRsrcFast(emptySet, SOCGame.SETTLEMENT_SET, 300, ports)
                .getRolls();
        speed +=
            estimate.calculateRollsAndRsrcFast(emptySet, SOCGame.CITY_SET, 300, ports).getRolls();
        speed +=
            estimate.calculateRollsAndRsrcFast(emptySet, SOCGame.CARD_SET, 300, ports).getRolls();
        speed +=
            estimate.calculateRollsAndRsrcFast(emptySet, SOCGame.ROAD_SET, 300, ports).getRolls();
      } catch (CutoffExceededException e) {
      }

      if (D.ebugOn) {
        final int[] rolls = estimate.getEstimatesFromNothingFast(ports, 300);
        sb = new StringBuffer();
        sb.append(" road: " + rolls[SOCBuildingSpeedEstimate.ROAD]);
        sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]);
        sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]);
        sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]);
        log.debug(sb.toString());
        log.debug("speed = " + speed);
      }

      //
      // end test
      //

      //
      // calculate pairs of first and second settlement together
      //

      for (int j = 1 + i; j < ourPotentialSettlements.length; ++j) {
        final int secondNode = ourPotentialSettlements[j];
        // assert: ourPlayerData.isPotentialSettlement(secondNode)

        if (board.isNodeAdjacentToNode(secondNode, firstNode))
          continue; // <-- too close to firstNode to build --

        log.debug("firstNode = " + board.nodeCoordToString(firstNode));
        log.debug("secondNode = " + board.nodeCoordToString(secondNode));

        /** get the numbers for these settlements */
        sb = new StringBuffer();
        sb.append("numbers:[");

        playerNumbers.clear();
        probTotal = playerNumbers.updateNumbersAndProbability(firstNode, board, prob, sb);

        sb.append("] [");

        probTotal += playerNumbers.updateNumbersAndProbability(secondNode, board, prob, sb);

        sb.append("]");
        log.debug(sb.toString());

        /** see if the settlements are on any ports */
        // sb = new StringBuffer();
        // sb.append("ports: ");

        Arrays.fill(ports, false);
        int portType = board.getPortTypeFromNodeCoord(firstNode);
        if (portType != -1) ports[portType] = true;
        portType = board.getPortTypeFromNodeCoord(secondNode);
        if (portType != -1) ports[portType] = true;

        // log.debug(sb.toString());
        log.debug("probTotal = " + probTotal);

        /** estimate the building speed for this pair */
        estimate.recalculateEstimates(playerNumbers);
        speed = 0;
        allTheWay = false;

        try {
          speed +=
              estimate
                  .calculateRollsAndRsrcFast(emptySet, SOCGame.SETTLEMENT_SET, bestSpeed, ports)
                  .getRolls();

          if (speed < bestSpeed) {
            speed +=
                estimate
                    .calculateRollsAndRsrcFast(emptySet, SOCGame.CITY_SET, bestSpeed, ports)
                    .getRolls();

            if (speed < bestSpeed) {
              speed +=
                  estimate
                      .calculateRollsAndRsrcFast(emptySet, SOCGame.CARD_SET, bestSpeed, ports)
                      .getRolls();

              if (speed < bestSpeed) {
                speed +=
                    estimate
                        .calculateRollsAndRsrcFast(emptySet, SOCGame.ROAD_SET, bestSpeed, ports)
                        .getRolls();
                allTheWay = true;
              }
            }
          }

          // because of addition, speed might be as much as (bestSpeed - 1) + bestSpeed
        } catch (CutoffExceededException e) {
          speed = bestSpeed;
        }

        if (D.ebugOn) {
          final int[] rolls = estimate.getEstimatesFromNothingFast(ports, bestSpeed);
          sb = new StringBuffer();
          sb.append(" road: " + rolls[SOCBuildingSpeedEstimate.ROAD]);
          sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]);
          sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]);
          sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]);
          log.debug(sb.toString());
          log.debug("allTheWay = " + allTheWay);
          log.debug("speed = " + speed);
        }

        /** keep the settlements with the best speed */
        if (speed < bestSpeed) {
          firstSettlement = firstNode;
          secondSettlement = secondNode;
          bestSpeed = speed;
          bestProbTotal = probTotal;
          log.debug("bestSpeed = " + bestSpeed);
          log.debug("bestProbTotal = " + bestProbTotal);
        } else if ((speed == bestSpeed) && allTheWay) {
          if (probTotal > bestProbTotal) {
            log.debug("Equal speed, better prob");
            firstSettlement = firstNode;
            secondSettlement = secondNode;
            bestSpeed = speed;
            bestProbTotal = probTotal;
            log.debug("firstSettlement = " + Integer.toHexString(firstSettlement));
            log.debug("secondSettlement = " + Integer.toHexString(secondSettlement));
            log.debug("bestSpeed = " + bestSpeed);
            log.debug("bestProbTotal = " + bestProbTotal);
          }
        }
      } // for (j past i in ourPotentialSettlements[])
    } // for (i in ourPotentialSettlements[])

    /** choose which settlement to place first */
    playerNumbers.clear();
    playerNumbers.updateNumbers(firstSettlement, board);

    final Integer firstSettlementInt = new Integer(firstSettlement);

    for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
      ports[portType] = (board.getPortCoordinates(portType).contains(firstSettlementInt));
    }

    estimate.recalculateEstimates(playerNumbers);

    int firstSpeed = 0;
    final int cutoff = 100;

    firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.SETTLEMENT_SET, cutoff, ports);
    firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CITY_SET, cutoff, ports);
    firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CARD_SET, cutoff, ports);
    firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.ROAD_SET, cutoff, ports);

    playerNumbers.clear();
    playerNumbers.updateNumbers(secondSettlement, board);

    final Integer secondSettlementInt = new Integer(secondSettlement);

    for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
      ports[portType] = (board.getPortCoordinates(portType).contains(secondSettlementInt));
    }

    estimate.recalculateEstimates(playerNumbers);

    int secondSpeed = 0;

    secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.SETTLEMENT_SET, bestSpeed, ports);
    secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CITY_SET, bestSpeed, ports);
    secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CARD_SET, bestSpeed, ports);
    secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.ROAD_SET, bestSpeed, ports);

    if (firstSpeed > secondSpeed) {
      int tmp = firstSettlement;
      firstSettlement = secondSettlement;
      secondSettlement = tmp;
    }

    log.debug(
        board.nodeCoordToString(firstSettlement)
            + ":"
            + firstSpeed
            + ", "
            + board.nodeCoordToString(secondSettlement)
            + ":"
            + secondSpeed);
    return firstSettlement;
  }