Search in sources :

Example 1 with SOCLRPathData

use of soc.game.SOCLRPathData in project JSettlers2 by jdmonin.

the class SOCRobotDM method smartGameStrategy.

/**
 * Plan building for the smart game strategy ({@link #SMART_STRATEGY}).
 * use player trackers' Win Game ETAs (WGETA) to determine best move
 * and update {@link #buildingPlan}.
 *<P>
 * For example, if {@link #favoriteSettlement} is chosen,
 * it's chosen from {@link #goodSettlements} or {@link #threatenedSettlements}.
 *<P>
 * Some scenarios require special moves or certain actions to win the game.  If we're playing in
 * such a scenario, after calculating {@link #favoriteSettlement}, {@link #favoriteCity}, etc, calls
 * {@link #scenarioGameStrategyPlan(float, float, boolean, boolean, SOCBuildingSpeedEstimate, int, boolean)}.
 * See that method for the list of scenarios which need such planning.
 *
 *<H4>Outline:</H4>
 *<UL>
 * <LI> Determine our Win Game ETA, leading player's WGETA
 * <LI> {@link #scorePossibleSettlements(int, int) scorePossibleSettlements(BuildETAs, leaderWGETA)}:
 *      For each settlement we can build now (no roads/ships needed), add its ETA bonus to its score
 * <LI> Build {@link #goodRoads} from possibleRoads' roads & ships we can build now
 * <LI> Pick a {@link #favoriteSettlement} from threatened/good settlements, with the highest
 *      {@link SOCPossiblePiece#getScore() getScore()}  (ETA bonus)
 * <LI> Pick a {@link #favoriteRoad} from threatened/good, with highest getWinGameETABonusForRoad
 * <LI> Pick a {@link #favoriteCity} from our possibleCities, with highest score (ETA bonus)
 * <LI> If {@code favoriteCity} has the best score (best ETA if tied), choose to build the city
 * <LI> Otherwise choose {@code favoriteRoad} or {@code favoriteSettlement} based on their scores
 * <LI> If buying a dev card scores higher than the chosen piece, choose to buy one instead of building
 * <LI> Check for and calc any scenario-specific {@code buildingPlan}
 *</UL>
 *
 * @param buildingETAs  the ETAs for building each piece type
 * @see #dumbFastGameStrategy(int[])
 */
protected void smartGameStrategy(final int[] buildingETAs) {
    D.ebugPrintln("***** smartGameStrategy *****");
    // If this game is on the 6-player board, check whether we're planning for
    // the Special Building Phase.  Can't buy cards or trade in that phase.
    final boolean forSpecialBuildingPhase = game.isSpecialBuilding() || (game.getCurrentPlayerNumber() != ourPlayerNumber);
    // 
    // save the lr paths list to restore later
    // 
    @SuppressWarnings("unchecked") List<SOCLRPathData>[] savedLRPaths = new List[game.maxPlayers];
    for (int pn = 0; pn < game.maxPlayers; pn++) {
        savedLRPaths[pn] = new ArrayList<SOCLRPathData>();
        savedLRPaths[pn].addAll(game.getPlayer(pn).getLRPaths());
    }
    int ourCurrentWGETA = ourPlayerTracker.getWinGameETA();
    D.ebugPrintln("ourCurrentWGETA = " + ourCurrentWGETA);
    int leadersCurrentWGETA = ourCurrentWGETA;
    Iterator<SOCPlayerTracker> trackersIter = playerTrackers.values().iterator();
    while (trackersIter.hasNext()) {
        SOCPlayerTracker tracker = trackersIter.next();
        int wgeta = tracker.getWinGameETA();
        if (wgeta < leadersCurrentWGETA) {
            leadersCurrentWGETA = wgeta;
        }
    }
    // /
    if (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) > 0) {
        scorePossibleSettlements(buildingETAs[SOCBuildingSpeedEstimate.SETTLEMENT], leadersCurrentWGETA);
    }
    // /
    if (ourPlayerData.getNumPieces(SOCPlayingPiece.ROAD) > 0) {
        Iterator<SOCPossibleRoad> posRoadsIter = ourPlayerTracker.getPossibleRoads().values().iterator();
        while (posRoadsIter.hasNext()) {
            SOCPossibleRoad posRoad = posRoadsIter.next();
            if (!posRoad.isRoadNotShip())
                // ignore ships in this loop, ships have other conditions to check
                continue;
            if ((posRoad.getNecessaryRoads().isEmpty()) && (!threatenedRoads.contains(posRoad)) && (!goodRoads.contains(posRoad))) {
                goodRoads.add(posRoad);
            }
        }
    }
    // /
    if (ourPlayerData.getNumPieces(SOCPlayingPiece.SHIP) > 0) {
        final SOCBoard board = game.getBoard();
        final int pirateHex = (board instanceof SOCBoardLarge) ? ((SOCBoardLarge) board).getPirateHex() : 0;
        final int[] pirateEdges = (pirateHex != 0) ? ((SOCBoardLarge) board).getAdjacentEdgesToHex_arr(pirateHex) : null;
        Iterator<SOCPossibleRoad> posRoadsIter = ourPlayerTracker.getPossibleRoads().values().iterator();
        while (posRoadsIter.hasNext()) {
            final SOCPossibleRoad posRoad = posRoadsIter.next();
            if (posRoad.isRoadNotShip())
                // ignore roads in this loop, we want ships
                continue;
            if (posRoad.getNecessaryRoads().isEmpty() && (!threatenedRoads.contains(posRoad)) && (!goodRoads.contains(posRoad))) {
                boolean edgeOK = true;
                if (pirateEdges != null) {
                    final int edge = posRoad.getCoordinates();
                    for (int i = 0; i < pirateEdges.length; ++i) {
                        if (edge == pirateEdges[i]) {
                            edgeOK = false;
                            break;
                        }
                    }
                }
                if (edgeOK)
                    goodRoads.add(posRoad);
            }
        }
    }
    /*
    ///
    /// check everything
    ///
    Enumeration threatenedSetEnum = threatenedSettlements.elements();
    while (threatenedSetEnum.hasMoreElements()) {
      SOCPossibleSettlement threatenedSet = (SOCPossibleSettlement)threatenedSetEnum.nextElement();
      D.ebugPrintln("*** threatened settlement at "+Integer.toHexString(threatenedSet.getCoordinates())+" has a score of "+threatenedSet.getScore());
      if (threatenedSet.getNecessaryRoads().isEmpty() &&
	  ! ourPlayerData.isPotentialSettlement(threatenedSet.getCoordinates())) {
	D.ebugPrintln("POTENTIAL SETTLEMENT ERROR");
	//System.exit(0);
      }
    }
    Enumeration goodSetEnum = goodSettlements.elements();
    while (goodSetEnum.hasMoreElements()) {
      SOCPossibleSettlement goodSet = (SOCPossibleSettlement)goodSetEnum.nextElement();
      D.ebugPrintln("*** good settlement at "+Integer.toHexString(goodSet.getCoordinates())+" has a score of "+goodSet.getScore());
      if (goodSet.getNecessaryRoads().isEmpty() &&
	  ! ourPlayerData.isPotentialSettlement(goodSet.getCoordinates())) {
	D.ebugPrintln("POTENTIAL SETTLEMENT ERROR");
	//System.exit(0);
      }
    }
    Enumeration threatenedRoadEnum = threatenedRoads.elements();
    while (threatenedRoadEnum.hasMoreElements()) {
      SOCPossibleRoad threatenedRoad = (SOCPossibleRoad)threatenedRoadEnum.nextElement();
      D.ebugPrintln("*** threatened road at "+Integer.toHexString(threatenedRoad.getCoordinates())+" has a score of "+threatenedRoad.getScore());
      if (threatenedRoad.getNecessaryRoads().isEmpty() &&
	  ! ourPlayerData.isPotentialRoad(threatenedRoad.getCoordinates())) {
	D.ebugPrintln("POTENTIAL ROAD ERROR");
	//System.exit(0);
      }
    }
    Enumeration goodRoadEnum = goodRoads.elements();
    while (goodRoadEnum.hasMoreElements()) {
      SOCPossibleRoad goodRoad = (SOCPossibleRoad)goodRoadEnum.nextElement();
      D.ebugPrintln("*** good road at "+Integer.toHexString(goodRoad.getCoordinates())+" has a score of "+goodRoad.getScore());
      if (goodRoad.getNecessaryRoads().isEmpty() &&
	  ! ourPlayerData.isPotentialRoad(goodRoad.getCoordinates())) {
	D.ebugPrintln("POTENTIAL ROAD ERROR");
	//System.exit(0);
      }
    }
    */
    D.ebugPrintln("PICKING WHAT TO BUILD");
    // /
    if (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) > 0) {
        for (SOCPossibleSettlement threatenedSet : threatenedSettlements) {
            if (threatenedSet.getNecessaryRoads().isEmpty()) {
                D.ebugPrintln("$$$$$ threatened settlement at " + Integer.toHexString(threatenedSet.getCoordinates()) + " has a score of " + threatenedSet.getScore());
                if ((favoriteSettlement == null) || (threatenedSet.getScore() > favoriteSettlement.getScore())) {
                    favoriteSettlement = threatenedSet;
                }
            }
        }
        for (SOCPossibleSettlement goodSet : goodSettlements) {
            if (goodSet.getNecessaryRoads().isEmpty()) {
                D.ebugPrintln("$$$$$ good settlement at " + Integer.toHexString(goodSet.getCoordinates()) + " has a score of " + goodSet.getScore());
                if ((favoriteSettlement == null) || (goodSet.getScore() > favoriteSettlement.getScore())) {
                    favoriteSettlement = goodSet;
                }
            }
        }
    }
    // 
    // restore the LRPath list
    // 
    D.ebugPrintln("%%% RESTORING LRPATH LIST %%%");
    for (int pn = 0; pn < game.maxPlayers; pn++) {
        game.getPlayer(pn).setLRPaths(savedLRPaths[pn]);
    }
    // /
    if (ourPlayerData.getNumPieces(SOCPlayingPiece.ROAD) > 0) {
        for (SOCPossibleRoad threatenedRoad : threatenedRoads) {
            D.ebugPrintln("$$$$$ threatened road at " + Integer.toHexString(threatenedRoad.getCoordinates()));
            if ((brain != null) && (brain.getDRecorder().isOn())) {
                brain.getDRecorder().startRecording("ROAD" + threatenedRoad.getCoordinates());
                brain.getDRecorder().record("Estimate value of road at " + game.getBoard().edgeCoordToString(threatenedRoad.getCoordinates()));
            }
            // 
            // see how building this piece impacts our winETA
            // 
            threatenedRoad.resetScore();
            float wgetaScore = getWinGameETABonusForRoad(threatenedRoad, buildingETAs[SOCBuildingSpeedEstimate.ROAD], leadersCurrentWGETA, playerTrackers);
            if ((brain != null) && (brain.getDRecorder().isOn())) {
                brain.getDRecorder().stopRecording();
            }
            D.ebugPrintln("wgetaScore = " + wgetaScore);
            if (favoriteRoad == null) {
                favoriteRoad = threatenedRoad;
            } else {
                if (threatenedRoad.getScore() > favoriteRoad.getScore()) {
                    favoriteRoad = threatenedRoad;
                }
            }
        }
        for (SOCPossibleRoad goodRoad : goodRoads) {
            D.ebugPrintln("$$$$$ good road at " + Integer.toHexString(goodRoad.getCoordinates()));
            if ((brain != null) && (brain.getDRecorder().isOn())) {
                brain.getDRecorder().startRecording("ROAD" + goodRoad.getCoordinates());
                brain.getDRecorder().record("Estimate value of road at " + game.getBoard().edgeCoordToString(goodRoad.getCoordinates()));
            }
            // 
            // see how building this piece impacts our winETA
            // 
            // TODO better ETA scoring for coastal ships/roads
            // 
            goodRoad.resetScore();
            final int etype = ((goodRoad instanceof SOCPossibleShip) && !((SOCPossibleShip) goodRoad).isCoastalRoadAndShip) ? SOCBuildingSpeedEstimate.ROAD : SOCBuildingSpeedEstimate.SHIP;
            float wgetaScore = getWinGameETABonusForRoad(goodRoad, buildingETAs[etype], leadersCurrentWGETA, playerTrackers);
            if ((brain != null) && (brain.getDRecorder().isOn())) {
                brain.getDRecorder().stopRecording();
            }
            D.ebugPrintln("wgetaScore = " + wgetaScore);
            if (favoriteRoad == null) {
                favoriteRoad = goodRoad;
            } else {
                if (goodRoad.getScore() > favoriteRoad.getScore()) {
                    favoriteRoad = goodRoad;
                }
            }
        }
    }
    // 
    // restore the LRPath list
    // 
    D.ebugPrintln("%%% RESTORING LRPATH LIST %%%");
    for (int pn = 0; pn < game.maxPlayers; pn++) {
        game.getPlayer(pn).setLRPaths(savedLRPaths[pn]);
    }
    // /
    if (ourPlayerData.getNumPieces(SOCPlayingPiece.CITY) > 0) {
        HashMap<Integer, SOCPlayerTracker> trackersCopy = SOCPlayerTracker.copyPlayerTrackers(playerTrackers);
        SOCPlayerTracker ourTrackerCopy = trackersCopy.get(Integer.valueOf(ourPlayerNumber));
        int[] originalWGETAs = new int[game.maxPlayers];
        int[] WGETAdiffs = new int[game.maxPlayers];
        Vector<SOCPlayerTracker> leaders = new Vector<SOCPlayerTracker>();
        int bestWGETA = 1000;
        // int bonus = 0;
        Iterator<SOCPossibleCity> posCitiesIter = ourPlayerTracker.getPossibleCities().values().iterator();
        while (posCitiesIter.hasNext()) {
            SOCPossibleCity posCity = posCitiesIter.next();
            if ((brain != null) && (brain.getDRecorder().isOn())) {
                brain.getDRecorder().startRecording("CITY" + posCity.getCoordinates());
                brain.getDRecorder().record("Estimate value of city at " + game.getBoard().nodeCoordToString(posCity.getCoordinates()));
            }
            // 
            // see how building this piece impacts our winETA
            // 
            leaders.clear();
            if ((brain != null) && (brain.getDRecorder().isOn())) {
                brain.getDRecorder().suspend();
            }
            SOCPlayerTracker.updateWinGameETAs(trackersCopy);
            // TODO refactor? This section is like a copy of calcWGETABonus, with something added in the middle
            Iterator<SOCPlayerTracker> trackersBeforeIter = trackersCopy.values().iterator();
            while (trackersBeforeIter.hasNext()) {
                SOCPlayerTracker trackerBefore = trackersBeforeIter.next();
                final int pn = trackerBefore.getPlayer().getPlayerNumber();
                D.ebugPrintln("$$$ win game ETA for player " + pn + " = " + trackerBefore.getWinGameETA());
                originalWGETAs[pn] = trackerBefore.getWinGameETA();
                WGETAdiffs[pn] = trackerBefore.getWinGameETA();
                if (trackerBefore.getWinGameETA() < bestWGETA) {
                    bestWGETA = trackerBefore.getWinGameETA();
                    leaders.removeAllElements();
                    leaders.addElement(trackerBefore);
                } else if (trackerBefore.getWinGameETA() == bestWGETA) {
                    leaders.addElement(trackerBefore);
                }
            }
            D.ebugPrintln("^^^^ bestWGETA = " + bestWGETA);
            if ((brain != null) && (brain.getDRecorder().isOn())) {
                brain.getDRecorder().resume();
            }
            // 
            // place the city
            // 
            SOCCity tmpCity = new SOCCity(ourPlayerData, posCity.getCoordinates(), null);
            game.putTempPiece(tmpCity);
            ourTrackerCopy.addOurNewCity(tmpCity);
            SOCPlayerTracker.updateWinGameETAs(trackersCopy);
            float wgetaScore = calcWGETABonusAux(originalWGETAs, trackersCopy, leaders);
            // 
            // remove the city
            // 
            ourTrackerCopy.undoAddOurNewCity(posCity);
            game.undoPutTempPiece(tmpCity);
            D.ebugPrintln("*** ETA for city = " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
            if ((brain != null) && (brain.getDRecorder().isOn())) {
                brain.getDRecorder().record("ETA = " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
            }
            float etaBonus = getETABonus(buildingETAs[SOCBuildingSpeedEstimate.CITY], leadersCurrentWGETA, wgetaScore);
            D.ebugPrintln("etaBonus = " + etaBonus);
            posCity.addToScore(etaBonus);
            if ((brain != null) && (brain.getDRecorder().isOn())) {
                brain.getDRecorder().record("WGETA score = " + df1.format(wgetaScore));
                brain.getDRecorder().record("Total city score = " + df1.format(etaBonus));
                brain.getDRecorder().stopRecording();
            }
            D.ebugPrintln("$$$  final score = " + posCity.getScore());
            D.ebugPrintln("$$$$$ possible city at " + Integer.toHexString(posCity.getCoordinates()) + " has a score of " + posCity.getScore());
            if ((favoriteCity == null) || (posCity.getScore() > favoriteCity.getScore())) {
                favoriteCity = posCity;
            }
        }
    }
    if (favoriteSettlement != null) {
        D.ebugPrintln("### FAVORITE SETTLEMENT IS AT " + Integer.toHexString(favoriteSettlement.getCoordinates()));
        D.ebugPrintln("###   WITH A SCORE OF " + favoriteSettlement.getScore());
        D.ebugPrintln("###   WITH AN ETA OF " + buildingETAs[SOCBuildingSpeedEstimate.SETTLEMENT]);
        D.ebugPrintln("###   WITH A TOTAL SPEEDUP OF " + favoriteSettlement.getSpeedupTotal());
    }
    if (favoriteCity != null) {
        D.ebugPrintln("### FAVORITE CITY IS AT " + Integer.toHexString(favoriteCity.getCoordinates()));
        D.ebugPrintln("###   WITH A SCORE OF " + favoriteCity.getScore());
        D.ebugPrintln("###   WITH AN ETA OF " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
        D.ebugPrintln("###   WITH A TOTAL SPEEDUP OF " + favoriteCity.getSpeedupTotal());
    }
    final int road_eta_type = ((favoriteRoad != null) && (favoriteRoad instanceof SOCPossibleShip) && // TODO better ETA calc for coastal roads/ships
    !((SOCPossibleShip) favoriteRoad).isCoastalRoadAndShip) ? SOCBuildingSpeedEstimate.SHIP : SOCBuildingSpeedEstimate.ROAD;
    if (favoriteRoad != null) {
        D.ebugPrintln("### FAVORITE ROAD IS AT " + Integer.toHexString(favoriteRoad.getCoordinates()));
        D.ebugPrintln("###   WITH AN ETA OF " + buildingETAs[road_eta_type]);
        D.ebugPrintln("###   WITH A SCORE OF " + favoriteRoad.getScore());
    }
    // piece type, if any, to be pushed onto buildingPlan;
    int pick = -1;
    // use ROAD for road or ship, use MAXPLUSONE for dev card
    // getScore() of picked piece
    float pickScore = 0f;
    // /
    if ((favoriteCity != null) && (ourPlayerData.getNumPieces(SOCPlayingPiece.CITY) > 0) && (favoriteCity.getScore() > 0) && ((favoriteSettlement == null) || (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) == 0) || (favoriteCity.getScore() > favoriteSettlement.getScore()) || ((favoriteCity.getScore() == favoriteSettlement.getScore()) && (buildingETAs[SOCBuildingSpeedEstimate.CITY] < buildingETAs[SOCBuildingSpeedEstimate.SETTLEMENT]))) && ((favoriteRoad == null) || (ourPlayerData.getNumPieces(favoriteRoad.getType()) == 0) || (favoriteCity.getScore() > favoriteRoad.getScore()) || ((favoriteCity.getScore() == favoriteRoad.getScore()) && (buildingETAs[SOCBuildingSpeedEstimate.CITY] < buildingETAs[road_eta_type])))) {
        D.ebugPrintln("### PICKED FAVORITE CITY");
        pick = SOCPlayingPiece.CITY;
        pickScore = favoriteCity.getScore();
    } else // /
    if ((favoriteRoad != null) && (ourPlayerData.getNumPieces(favoriteRoad.getType()) > 0) && (favoriteRoad.getScore() > 0) && ((favoriteSettlement == null) || (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) == 0) || (favoriteSettlement.getScore() < favoriteRoad.getScore()))) {
        D.ebugPrintln("### PICKED FAVORITE ROAD");
        // also represents SHIP here
        pick = SOCPlayingPiece.ROAD;
        pickScore = favoriteRoad.getScore();
    } else if ((favoriteSettlement != null) && (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) > 0)) {
        D.ebugPrintln("### PICKED FAVORITE SETTLEMENT");
        pick = SOCPlayingPiece.SETTLEMENT;
        pickScore = favoriteSettlement.getScore();
    }
    // /
    // / if buying a card is better than building...
    // /
    // 
    // see how buying a card improves our win game ETA
    // 
    float devCardScore = 0;
    if ((game.getNumDevCards() > 0) && !forSpecialBuildingPhase) {
        if ((brain != null) && (brain.getDRecorder().isOn())) {
            brain.getDRecorder().startRecording("DEVCARD");
            brain.getDRecorder().record("Estimate value of a dev card");
        }
        possibleCard = getDevCardScore(buildingETAs[SOCBuildingSpeedEstimate.CARD], leadersCurrentWGETA);
        devCardScore = possibleCard.getScore();
        D.ebugPrintln("### DEV CARD SCORE: " + devCardScore);
        if ((brain != null) && (brain.getDRecorder().isOn())) {
            brain.getDRecorder().stopRecording();
        }
        if ((pick == -1) || (devCardScore > pickScore)) {
            D.ebugPrintln("### BUY DEV CARD");
            pick = SOCPlayingPiece.MAXPLUSONE;
            pickScore = devCardScore;
        }
    }
    if (game.isGameOptionSet(SOCGameOption.K_SC_PIRI) || game.isGameOptionSet(SOCGameOption.K_SC_WOND)) {
        if (scenarioGameStrategyPlan(pickScore, devCardScore, true, (pick == SOCPlayingPiece.MAXPLUSONE), new SOCBuildingSpeedEstimate(ourPlayerData.getNumbers()), leadersCurrentWGETA, forSpecialBuildingPhase))
            // <--- Early return: Scenario-specific buildingPlan was pushed ---
            return;
    }
    // 
    switch(pick) {
        case SOCPlayingPiece.ROAD:
            D.ebugPrintln("$ PUSHING " + favoriteRoad);
            buildingPlan.push(favoriteRoad);
            break;
        case SOCPlayingPiece.SETTLEMENT:
            D.ebugPrintln("$ PUSHING " + favoriteSettlement);
            buildingPlan.push(favoriteSettlement);
            break;
        case SOCPlayingPiece.CITY:
            D.ebugPrintln("$ PUSHING " + favoriteCity);
            buildingPlan.push(favoriteCity);
            break;
        case SOCPlayingPiece.MAXPLUSONE:
            D.ebugPrintln("$ PUSHING " + possibleCard);
            buildingPlan.push(possibleCard);
            break;
    }
}
Also used : SOCBoard(soc.game.SOCBoard) ArrayList(java.util.ArrayList) List(java.util.List) Vector(java.util.Vector) SOCBoardLarge(soc.game.SOCBoardLarge) SOCCity(soc.game.SOCCity) SOCLRPathData(soc.game.SOCLRPathData)

Example 2 with SOCLRPathData

use of soc.game.SOCLRPathData in project JSettlers2 by jdmonin.

the class SOCPlayerTracker method recalcLongestRoadETA.

/**
 * Calculate the longest road ETA.
 * Always 500 or more if {@link SOCGameOption#K_SC_0RVP} is set.
 * Updates fields for {@link #getLongestRoadETA()} and {@link #getRoadsToGo()}.
 */
public void recalcLongestRoadETA() {
    // TODO handle ships here (different resources, etc)
    D.ebugPrintln("===  recalcLongestRoadETA for player " + playerNumber);
    final int roadETA;
    SOCBuildingSpeedEstimate bse = new SOCBuildingSpeedEstimate(player.getNumbers());
    roadETA = bse.calculateRollsFast(SOCGame.EMPTY_RESOURCES, SOCRoad.COST, 500, player.getPortFlags());
    roadsToGo = 500;
    longestRoadETA = 500;
    int longestRoadLength;
    SOCPlayer lrPlayer = game.getPlayerWithLongestRoad();
    if ((lrPlayer != null) && (lrPlayer.getPlayerNumber() == playerNumber)) {
        // /
        // / we have longest road
        // /
        // D.ebugPrintln("===  we have longest road");
        longestRoadETA = 0;
        roadsToGo = 0;
    } else if (!game.isGameOptionSet(SOCGameOption.K_SC_0RVP)) {
        if (lrPlayer == null) {
            // /
            // / no one has longest road
            // /
            longestRoadLength = Math.max(4, player.getLongestRoadLength());
        } else {
            longestRoadLength = lrPlayer.getLongestRoadLength();
        }
        Iterator<SOCLRPathData> lrPathsIter = player.getLRPaths().iterator();
        int depth;
        while (lrPathsIter.hasNext()) {
            SOCLRPathData pathData = lrPathsIter.next();
            depth = Math.min(((longestRoadLength + 1) - pathData.getLength()), player.getNumPieces(SOCPlayingPiece.ROAD));
            int minRoads = recalcLongestRoadETAAux(pathData.getBeginning(), pathData.getLength(), longestRoadLength, depth);
            roadsToGo = Math.min(minRoads, roadsToGo);
            minRoads = recalcLongestRoadETAAux(pathData.getEnd(), pathData.getLength(), longestRoadLength, depth);
            roadsToGo = Math.min(minRoads, roadsToGo);
        }
    }
    D.ebugPrintln("--- roadsToGo = " + roadsToGo);
    longestRoadETA = roadsToGo * roadETA;
}
Also used : Iterator(java.util.Iterator) SOCPlayer(soc.game.SOCPlayer) SOCLRPathData(soc.game.SOCLRPathData)

Example 3 with SOCLRPathData

use of soc.game.SOCLRPathData in project JSettlers2 by jdmonin.

the class SOCRobotDM method dumbFastGameStrategy.

/**
 * Plan building for the dumbFastGameStrategy ({@link #FAST_STRATEGY}).
 * uses rules to determine what to build next
 * and update {@link #buildingPlan}.
 *<P>
 * For example, if {@link #favoriteSettlement} is chosen,
 * it's chosen from {@link #ourPlayerTracker}{@link SOCPlayerTracker#getPossibleSettlements() .getPossibleSettlements()}.
 *
 *<H4>Outline:</H4>
 * Possible cities and settlements are looked at first.
 * Find the city with best {@link SOCPossibleCity#getSpeedupTotal()}, then check each possible
 * settlement's {@link SOCPossiblePiece#getETA()} against the city's ETA to possibly choose one to build.
 * (If one is chosen, its {@link SOCPossibleSettlement#getNecessaryRoads()}
 * will also be chosen here.)  Then, Knights or Dev Cards.
 * Only then would roads or ships be looked at, for Longest Route
 * (and only if we're at 5 VP or more).
 *<P>
 * This method never directly checks
 * {@code ourPlayerTracker}{@link SOCPlayerTracker#getPossibleRoads() .getPossibleRoads()}, instead
 * it adds the roads or ships from {@link SOCPossibleSettlement#getNecessaryRoads()} to {@link #buildingPlan}
 * when a possible settlement is picked to build.
 *<P>
 * Some scenarios require special moves or certain actions to win the game.  If we're playing in
 * such a scenario, after calculating {@link #favoriteSettlement}, {@link #favoriteCity}, etc, calls
 * {@link #scenarioGameStrategyPlan(float, float, boolean, boolean, SOCBuildingSpeedEstimate, int, boolean)}.
 * See that method for the list of scenarios which need such planning.
 *
 * @param buildingETAs  the ETAs for building each piece type
 * @see #smartGameStrategy(int[])
 */
protected void dumbFastGameStrategy(final int[] buildingETAs) {
    D.ebugPrintln("***** dumbFastGameStrategy *****");
    // If this game is on the 6-player board, check whether we're planning for
    // the Special Building Phase.  Can't buy cards or trade in that phase.
    final boolean forSpecialBuildingPhase = game.isSpecialBuilding() || (game.getCurrentPlayerNumber() != ourPlayerNumber);
    int bestETA = 500;
    SOCBuildingSpeedEstimate ourBSE = new SOCBuildingSpeedEstimate(ourPlayerData.getNumbers());
    if (ourPlayerData.getTotalVP() < 5) {
        // 
        if (ourPlayerData.getNumPieces(SOCPlayingPiece.CITY) > 0) {
            Iterator<SOCPossibleCity> posCitiesIter = ourPlayerTracker.getPossibleCities().values().iterator();
            while (posCitiesIter.hasNext()) {
                SOCPossibleCity posCity = posCitiesIter.next();
                D.ebugPrintln("Estimate speedup of city at " + game.getBoard().nodeCoordToString(posCity.getCoordinates()));
                D.ebugPrintln("Speedup = " + posCity.getSpeedupTotal());
                D.ebugPrintln("ETA = " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
                if ((brain != null) && brain.getDRecorder().isOn()) {
                    brain.getDRecorder().startRecording("CITY" + posCity.getCoordinates());
                    brain.getDRecorder().record("Estimate speedup of city at " + game.getBoard().nodeCoordToString(posCity.getCoordinates()));
                    brain.getDRecorder().record("Speedup = " + posCity.getSpeedupTotal());
                    brain.getDRecorder().record("ETA = " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
                    brain.getDRecorder().stopRecording();
                }
                if ((favoriteCity == null) || (posCity.getSpeedupTotal() > favoriteCity.getSpeedupTotal())) {
                    favoriteCity = posCity;
                    bestETA = buildingETAs[SOCBuildingSpeedEstimate.CITY];
                }
            }
        }
        // 
        // score the possible settlements
        // 
        scoreSettlementsForDumb(buildingETAs[SOCBuildingSpeedEstimate.SETTLEMENT], ourBSE);
        // 
        // pick something to build
        // 
        Iterator<SOCPossibleSettlement> posSetsIter = ourPlayerTracker.getPossibleSettlements().values().iterator();
        while (posSetsIter.hasNext()) {
            SOCPossibleSettlement posSet = posSetsIter.next();
            if ((brain != null) && brain.getDRecorder().isOn()) {
                brain.getDRecorder().startRecording("SETTLEMENT" + posSet.getCoordinates());
                brain.getDRecorder().record("Estimate speedup of stlmt at " + game.getBoard().nodeCoordToString(posSet.getCoordinates()));
                brain.getDRecorder().record("Speedup = " + posSet.getSpeedupTotal());
                brain.getDRecorder().record("ETA = " + posSet.getETA());
                Stack<SOCPossibleRoad> roadPath = posSet.getRoadPath();
                if (roadPath != null) {
                    brain.getDRecorder().record("Path:");
                    Iterator<SOCPossibleRoad> rpIter = roadPath.iterator();
                    while (rpIter.hasNext()) {
                        SOCPossibleRoad posRoad = rpIter.next();
                        brain.getDRecorder().record("Road at " + game.getBoard().edgeCoordToString(posRoad.getCoordinates()));
                    }
                }
                brain.getDRecorder().stopRecording();
            }
            if (posSet.getETA() < bestETA) {
                bestETA = posSet.getETA();
                favoriteSettlement = posSet;
            } else if (posSet.getETA() == bestETA) {
                if (favoriteSettlement == null) {
                    if ((favoriteCity == null) || (posSet.getSpeedupTotal() > favoriteCity.getSpeedupTotal())) {
                        favoriteSettlement = posSet;
                    }
                } else {
                    if (posSet.getSpeedupTotal() > favoriteSettlement.getSpeedupTotal()) {
                        favoriteSettlement = posSet;
                    }
                }
            }
        }
        if (favoriteSettlement != null) {
            // 
            // we want to build a settlement
            // 
            D.ebugPrintln("Picked favorite settlement at " + game.getBoard().nodeCoordToString(favoriteSettlement.getCoordinates()));
            buildingPlan.push(favoriteSettlement);
            if (!favoriteSettlement.getNecessaryRoads().isEmpty()) {
                // 
                // we need to build roads first
                // 
                Stack<SOCPossibleRoad> roadPath = favoriteSettlement.getRoadPath();
                while (!roadPath.empty()) {
                    buildingPlan.push(roadPath.pop());
                }
            }
        } else if (favoriteCity != null) {
            // 
            // we want to build a city
            // 
            D.ebugPrintln("Picked favorite city at " + game.getBoard().nodeCoordToString(favoriteCity.getCoordinates()));
            buildingPlan.push(favoriteCity);
        } else {
            // 
            if ((game.getNumDevCards() > 0) && !forSpecialBuildingPhase) {
                // 
                // buy a card if there are any left
                // 
                D.ebugPrintln("Buy a card");
                SOCPossibleCard posCard = new SOCPossibleCard(ourPlayerData, buildingETAs[SOCBuildingSpeedEstimate.CARD]);
                buildingPlan.push(posCard);
            }
        }
    } else {
        // 
        // we have more than 4 points
        // 
        int choice = -1;
        // 
        // consider Largest Army
        // 
        D.ebugPrintln("Calculating Largest Army ETA");
        int laETA = 500;
        int laSize = 0;
        SOCPlayer laPlayer = game.getPlayerWithLargestArmy();
        if (laPlayer == null) {
            // /
            // / no one has largest army
            // /
            laSize = 3;
        } else if (laPlayer.getPlayerNumber() == ourPlayerNumber) {
            // /
            // / we have largest army
            // /
            D.ebugPrintln("We have largest army");
        } else {
            laSize = laPlayer.getNumKnights() + 1;
        }
        // /
        // / figure out how many knights we need to buy
        // /
        int knightsToBuy = 0;
        if ((ourPlayerData.getNumKnights() + // OLD + NEW knights
        ourPlayerData.getInventory().getAmount(SOCDevCardConstants.KNIGHT)) < laSize) {
            knightsToBuy = laSize - (ourPlayerData.getNumKnights() + ourPlayerData.getInventory().getAmount(SOCInventory.OLD, SOCDevCardConstants.KNIGHT));
        }
        D.ebugPrintln("knightsToBuy = " + knightsToBuy);
        if (ourPlayerData.getGame().getNumDevCards() >= knightsToBuy) {
            // /
            // / figure out how long it takes to buy this many knights
            // /
            SOCResourceSet targetResources = new SOCResourceSet();
            for (int i = 0; i < knightsToBuy; i++) {
                targetResources.add(SOCDevCard.COST);
            }
            laETA = ourBSE.calculateRollsFast(ourPlayerData.getResources(), targetResources, 100, ourPlayerData.getPortFlags());
        } else {
        // /
        // / not enough dev cards left
        // /
        }
        if ((laETA < bestETA) && !forSpecialBuildingPhase) {
            bestETA = laETA;
            choice = LA_CHOICE;
        }
        D.ebugPrintln("laETA = " + laETA);
        // 
        // consider Longest Road
        // 
        D.ebugPrintln("Calculating Longest Road ETA");
        int lrETA = 500;
        Stack<?> bestLRPath = null;
        int lrLength;
        SOCPlayer lrPlayer = game.getPlayerWithLongestRoad();
        if ((lrPlayer != null) && (lrPlayer.getPlayerNumber() == ourPlayerNumber)) {
            // /
            // / we have longest road
            // /
            D.ebugPrintln("We have longest road");
        } else if (!game.isGameOptionSet(SOCGameOption.K_SC_0RVP)) {
            if (lrPlayer == null) {
                // /
                // / no one has longest road
                // /
                lrLength = Math.max(4, ourPlayerData.getLongestRoadLength());
            } else {
                lrLength = lrPlayer.getLongestRoadLength();
            }
            Iterator<SOCLRPathData> lrPathsIter = ourPlayerData.getLRPaths().iterator();
            int depth;
            while (lrPathsIter.hasNext()) {
                Stack<?> path;
                SOCLRPathData pathData = lrPathsIter.next();
                depth = Math.min(((lrLength + 1) - pathData.getLength()), ourPlayerData.getNumPieces(SOCPlayingPiece.ROAD));
                path = (Stack<?>) recalcLongestRoadETAAux(ourPlayerData, true, pathData.getBeginning(), pathData.getLength(), lrLength, depth);
                if ((path != null) && ((bestLRPath == null) || (path.size() < bestLRPath.size()))) {
                    bestLRPath = path;
                }
                path = (Stack<?>) recalcLongestRoadETAAux(ourPlayerData, true, pathData.getEnd(), pathData.getLength(), lrLength, depth);
                if ((path != null) && ((bestLRPath == null) || (path.size() < bestLRPath.size()))) {
                    bestLRPath = path;
                }
            }
            if (bestLRPath != null) {
                // 
                // calculate LR eta
                // 
                D.ebugPrintln("Number of roads: " + bestLRPath.size());
                SOCResourceSet targetResources = new SOCResourceSet();
                for (int i = 0; i < bestLRPath.size(); i++) {
                    targetResources.add(SOCRoad.COST);
                }
                lrETA = ourBSE.calculateRollsFast(ourPlayerData.getResources(), targetResources, 100, ourPlayerData.getPortFlags());
            }
        }
        if (lrETA < bestETA) {
            bestETA = lrETA;
            choice = LR_CHOICE;
        }
        D.ebugPrintln("lrETA = " + lrETA);
        // 
        if ((ourPlayerData.getNumPieces(SOCPlayingPiece.CITY) > 0) && (buildingETAs[SOCBuildingSpeedEstimate.CITY] <= bestETA)) {
            Iterator<SOCPossibleCity> posCitiesIter = ourPlayerTracker.getPossibleCities().values().iterator();
            while (posCitiesIter.hasNext()) {
                SOCPossibleCity posCity = posCitiesIter.next();
                if ((brain != null) && brain.getDRecorder().isOn()) {
                    brain.getDRecorder().startRecording("CITY" + posCity.getCoordinates());
                    brain.getDRecorder().record("Estimate speedup of city at " + game.getBoard().nodeCoordToString(posCity.getCoordinates()));
                    brain.getDRecorder().record("Speedup = " + posCity.getSpeedupTotal());
                    brain.getDRecorder().record("ETA = " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
                    brain.getDRecorder().stopRecording();
                }
                if ((favoriteCity == null) || (posCity.getSpeedupTotal() > favoriteCity.getSpeedupTotal())) {
                    favoriteCity = posCity;
                    bestETA = buildingETAs[SOCBuildingSpeedEstimate.CITY];
                    choice = CITY_CHOICE;
                }
            }
        }
        // 
        if (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) > 0) {
            scoreSettlementsForDumb(buildingETAs[SOCBuildingSpeedEstimate.SETTLEMENT], ourBSE);
            Iterator<SOCPossibleSettlement> posSetsIter = ourPlayerTracker.getPossibleSettlements().values().iterator();
            while (posSetsIter.hasNext()) {
                SOCPossibleSettlement posSet = posSetsIter.next();
                if ((brain != null) && brain.getDRecorder().isOn()) {
                    brain.getDRecorder().startRecording("SETTLEMENT" + posSet.getCoordinates());
                    brain.getDRecorder().record("Estimate speedup of stlmt at " + game.getBoard().nodeCoordToString(posSet.getCoordinates()));
                    brain.getDRecorder().record("Speedup = " + posSet.getSpeedupTotal());
                    brain.getDRecorder().record("ETA = " + posSet.getETA());
                    Stack<SOCPossibleRoad> roadPath = posSet.getRoadPath();
                    if (roadPath != null) {
                        brain.getDRecorder().record("Path:");
                        Iterator<SOCPossibleRoad> rpIter = roadPath.iterator();
                        while (rpIter.hasNext()) {
                            SOCPossibleRoad posRoad = rpIter.next();
                            brain.getDRecorder().record("Road at " + game.getBoard().edgeCoordToString(posRoad.getCoordinates()));
                        }
                    }
                    brain.getDRecorder().stopRecording();
                }
                if ((posSet.getRoadPath() == null) || (ourPlayerData.getNumPieces(SOCPlayingPiece.ROAD) >= posSet.getRoadPath().size())) {
                    if (posSet.getETA() < bestETA) {
                        bestETA = posSet.getETA();
                        favoriteSettlement = posSet;
                        choice = SETTLEMENT_CHOICE;
                    } else if (posSet.getETA() == bestETA) {
                        if (favoriteSettlement == null) {
                            if ((favoriteCity == null) || (posSet.getSpeedupTotal() > favoriteCity.getSpeedupTotal())) {
                                favoriteSettlement = posSet;
                                choice = SETTLEMENT_CHOICE;
                            }
                        } else {
                            if (posSet.getSpeedupTotal() > favoriteSettlement.getSpeedupTotal()) {
                                favoriteSettlement = posSet;
                            }
                        }
                    }
                }
            }
        }
        if (game.isGameOptionSet(SOCGameOption.K_SC_PIRI) || game.isGameOptionSet(SOCGameOption.K_SC_WOND)) {
            if (scenarioGameStrategyPlan(bestETA, -1f, false, (choice == LA_CHOICE), ourBSE, 0, forSpecialBuildingPhase))
                // <--- Early return: Scenario-specific buildingPlan was pushed ---
                return;
        }
        // 
        switch(choice) {
            case LA_CHOICE:
                D.ebugPrintln("Picked LA");
                if (!forSpecialBuildingPhase) {
                    for (int i = 0; i < knightsToBuy; i++) {
                        SOCPossibleCard posCard = new SOCPossibleCard(ourPlayerData, 1);
                        buildingPlan.push(posCard);
                    }
                }
                break;
            case LR_CHOICE:
                D.ebugPrintln("Picked LR");
                while (!bestLRPath.empty()) {
                    SOCPossibleRoad pr = (SOCPossibleRoad) bestLRPath.pop();
                    D.ebugPrintln("LR road at " + game.getBoard().edgeCoordToString(pr.getCoordinates()));
                    buildingPlan.push(pr);
                }
                break;
            case CITY_CHOICE:
                D.ebugPrintln("Picked favorite city at " + game.getBoard().nodeCoordToString(favoriteCity.getCoordinates()));
                buildingPlan.push(favoriteCity);
                break;
            case SETTLEMENT_CHOICE:
                D.ebugPrintln("Picked favorite settlement at " + game.getBoard().nodeCoordToString(favoriteSettlement.getCoordinates()));
                buildingPlan.push(favoriteSettlement);
                if (!favoriteSettlement.getNecessaryRoads().isEmpty()) {
                    // 
                    // we need to build roads first
                    // 
                    Stack<SOCPossibleRoad> roadPath = favoriteSettlement.getRoadPath();
                    while (!roadPath.empty()) {
                        SOCPossibleRoad pr = roadPath.pop();
                        D.ebugPrintln("Nec road at " + game.getBoard().edgeCoordToString(pr.getCoordinates()));
                        buildingPlan.push(pr);
                    }
                }
        }
    }
}
Also used : Stack(java.util.Stack) Iterator(java.util.Iterator) SOCPlayer(soc.game.SOCPlayer) SOCResourceSet(soc.game.SOCResourceSet) SOCLRPathData(soc.game.SOCLRPathData)

Example 4 with SOCLRPathData

use of soc.game.SOCLRPathData in project JSettlers2 by jdmonin.

the class SOCRobotDM method recalcLongestRoadETAAux.

/**
 * Does a depth first search of legal possible road edges from the end point of the longest
 * path connecting a graph of nodes, and returns which roads or how many roads
 * would need to be built to take longest road.
 *<P>
 * Do not call if {@link SOCGameOption#K_SC_0RVP} is set, because
 * this method needs {@link SOCPlayer#getLRPaths()} which will be empty.
 *<P>
 * Combined implementation for use by SOCRobotDM and {@link SOCPlayerTracker}.
 *
 * @param pl            Calculate this player's longest road;
 *             typically SOCRobotDM.ourPlayerData or SOCPlayerTracker.player
 * @param wantsStack    If true, return the Stack; otherwise, return numRoads.
 * @param startNode     the path endpoint, such as from
 *             {@link SOCPlayer#getLRPaths()}.(i){@link SOCLRPathData#getBeginning() .getBeginning()}
 *             or {@link SOCLRPathData#getEnd() .getEnd()}
 * @param pathLength    the length of that path
 * @param lrLength      length of longest road in the game
 * @param searchDepth   how many roads out to search
 *
 * @return if <tt>wantsStack</tt>: a {@link Stack} containing the path of roads with the last one
 *         (farthest from <tt>startNode</tt>) on top, or <tt>null</tt> if it can't be done.
 *         If ! <tt>wantsStack</tt>: Integer: the number of roads needed, or 500 if it can't be done
 */
static Object recalcLongestRoadETAAux(SOCPlayer pl, final boolean wantsStack, final int startNode, final int pathLength, final int lrLength, final int searchDepth) {
    // D.ebugPrintln("=== recalcLongestRoadETAAux("+Integer.toHexString(startNode)+","+pathLength+","+lrLength+","+searchDepth+")");
    // 
    // We're doing a depth first search of all possible road paths.
    // For similar code, see SOCPlayer.calcLongestRoad2
    // Both methods rely on a stack holding NodeLenVis (pop to curNode in loop);
    // they differ in actual element type within the stack because they are
    // gathering slightly different results (length or a stack of edges).
    // 
    int longest = 0;
    int numRoads = 500;
    Pair<NodeLenVis<Integer>, List<Integer>> bestPathNode = null;
    final SOCBoard board = pl.getGame().getBoard();
    Stack<Pair<NodeLenVis<Integer>, List<Integer>>> pending = new Stack<Pair<NodeLenVis<Integer>, List<Integer>>>();
    // Holds as-yet unvisited nodes:
    // Pair members are <NodeLenVis, null or node-coordinate list of all parents (from DFS traversal order)>.
    // Lists have most-distant node at beginning (item 0), and most-immediate at end of list (n-1).
    // That list is used at the end to build the returned Stack which is the road path needed.
    pending.push(new Pair<NodeLenVis<Integer>, List<Integer>>(new NodeLenVis<Integer>(startNode, pathLength, new Vector<Integer>()), null));
    while (!pending.empty()) {
        final Pair<NodeLenVis<Integer>, List<Integer>> dataPair = pending.pop();
        final NodeLenVis<Integer> curNode = dataPair.getA();
        // D.ebugPrintln("curNode = "+curNode);
        final int coord = curNode.node;
        int len = curNode.len;
        final Vector<Integer> visited = curNode.vis;
        boolean pathEnd = false;
        // 
        if (len > 0) {
            final int pn = pl.getPlayerNumber();
            SOCPlayingPiece p = board.settlementAtNode(coord);
            if ((p != null) && (p.getPlayerNumber() != pn)) {
                pathEnd = true;
            // D.ebugPrintln("^^^ path end at "+Integer.toHexString(coord));
            }
        }
        if (!pathEnd) {
            // 
            // check if we've connected to another road graph of this player
            // 
            Iterator<SOCLRPathData> lrPathsIter = pl.getLRPaths().iterator();
            while (lrPathsIter.hasNext()) {
                SOCLRPathData pathData = lrPathsIter.next();
                if ((startNode != pathData.getBeginning()) && (startNode != pathData.getEnd()) && ((coord == pathData.getBeginning()) || (coord == pathData.getEnd()))) {
                    pathEnd = true;
                    len += pathData.getLength();
                    break;
                }
            }
        }
        if (!pathEnd) {
            // 
            if ((len - pathLength) >= searchDepth) {
                pathEnd = true;
            }
        // D.ebugPrintln("Reached search depth");
        }
        if (!pathEnd) {
            /**
             * For each of the 3 adjacent edges of coord's node,
             * check for unvisited legal road possibilities.
             * When they are found, push that edge's far-end node
             * onto the pending stack.
             */
            pathEnd = true;
            for (int dir = 0; dir < 3; ++dir) {
                int j = board.getAdjacentEdgeToNode(coord, dir);
                if (pl.isLegalRoad(j)) {
                    final Integer edge = new Integer(j);
                    boolean match = false;
                    for (Enumeration<Integer> ev = visited.elements(); ev.hasMoreElements(); ) {
                        Integer vis = ev.nextElement();
                        if (vis.equals(edge)) {
                            match = true;
                            break;
                        }
                    }
                    if (!match) {
                        Vector<Integer> newVis = new Vector<Integer>(visited);
                        newVis.addElement(edge);
                        List<Integer> nodeParentList = dataPair.getB();
                        if (nodeParentList == null)
                            nodeParentList = new ArrayList<Integer>();
                        else
                            // clone before we add to it
                            nodeParentList = new ArrayList<Integer>(nodeParentList);
                        // curNode's coord will be parent to new pending element
                        nodeParentList.add(coord);
                        // edge's other node
                        j = board.getAdjacentNodeToNode(coord, dir);
                        pending.push(new Pair<NodeLenVis<Integer>, List<Integer>>(new NodeLenVis<Integer>(j, len + 1, newVis), nodeParentList));
                        pathEnd = false;
                    }
                }
            }
        }
        if (pathEnd) {
            if (len > longest) {
                longest = len;
                numRoads = curNode.len - pathLength;
                bestPathNode = dataPair;
            } else if ((len == longest) && (curNode.len < numRoads)) {
                numRoads = curNode.len - pathLength;
                bestPathNode = dataPair;
            }
        }
    }
    if (!wantsStack) {
        // As used by SOCPlayerTracker.
        int rv;
        if (longest > lrLength)
            rv = numRoads;
        else
            rv = 500;
        // <-- Early return: ! wantsStack ---
        return new Integer(rv);
    }
    if ((longest > lrLength) && (bestPathNode != null)) {
        // D.ebugPrintln("Converting nodes to road coords.");
        // 
        // Return the path in a stack, with the last road (the one from bestPathNode) on top.
        // Convert pairs of node coords to edge coords for roads.
        // List is ordered from farthest parent at 0 to bestPathNode's parent at (n-1),
        // so iterate same way to build the stack.
        // 
        Stack<SOCPossibleRoad> path = new Stack<SOCPossibleRoad>();
        int coordC, coordP;
        List<Integer> nodeList = bestPathNode.getB();
        if ((nodeList == null) || nodeList.isEmpty())
            // <--- early return, no node list: should not happen ---
            return null;
        // append bestPathNode
        nodeList.add(new Integer(bestPathNode.getA().node));
        final int L = nodeList.size();
        // root ancestor
        coordP = nodeList.get(0);
        for (int i = 1; i < L; ++i) {
            coordC = nodeList.get(i);
            path.push(new SOCPossibleRoad(pl, board.getEdgeBetweenAdjacentNodes(coordC, coordP), null));
            coordP = coordC;
        }
        return path;
    }
    return null;
}
Also used : NodeLenVis(soc.util.NodeLenVis) SOCBoard(soc.game.SOCBoard) SOCPlayingPiece(soc.game.SOCPlayingPiece) ArrayList(java.util.ArrayList) Stack(java.util.Stack) ArrayList(java.util.ArrayList) List(java.util.List) SOCLRPathData(soc.game.SOCLRPathData) Vector(java.util.Vector) Pair(soc.util.Pair)

Aggregations

SOCLRPathData (soc.game.SOCLRPathData)4 ArrayList (java.util.ArrayList)2 Iterator (java.util.Iterator)2 List (java.util.List)2 Stack (java.util.Stack)2 Vector (java.util.Vector)2 SOCBoard (soc.game.SOCBoard)2 SOCPlayer (soc.game.SOCPlayer)2 SOCBoardLarge (soc.game.SOCBoardLarge)1 SOCCity (soc.game.SOCCity)1 SOCPlayingPiece (soc.game.SOCPlayingPiece)1 SOCResourceSet (soc.game.SOCResourceSet)1 NodeLenVis (soc.util.NodeLenVis)1 Pair (soc.util.Pair)1