Search in sources :

Example 1 with SOCBoard

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

the class SOCRobotBrain method trackNewSettlement.

/**
 * Run a newly placed settlement through the playerTrackers.
 * Called only after {@link SOCGame#putPiece(SOCPlayingPiece)}
 * or {@link SOCGame#putTempPiece(SOCPlayingPiece)}.
 *<P>
 * During initial board setup, settlements aren't tracked when placed.
 * They are deferred until their corresponding road placement, in case
 * a human player decides to cancel their settlement and place it elsewhere.
 *
 * During normal play, the settlements are tracked immediately when placed.
 *
 * (Code previously in body of the run method.)
 * Placing the code in its own method allows tracking that settlement when the
 * road's putPiece message arrives.
 *
 * @param newSettlement The newly placed settlement for the playerTrackers
 * @param isCancel Is this our own robot's settlement placement, rejected by the server?
 *     If so, this method call will cancel its placement within the game data / robot data.
 */
protected void trackNewSettlement(SOCSettlement newSettlement, final boolean isCancel) {
    Iterator<SOCPlayerTracker> trackersIter = playerTrackers.values().iterator();
    while (trackersIter.hasNext()) {
        SOCPlayerTracker tracker = trackersIter.next();
        if (!isCancel)
            tracker.addNewSettlement(newSettlement, playerTrackers);
        else
            tracker.cancelWrongSettlement(newSettlement);
    }
    trackersIter = playerTrackers.values().iterator();
    while (trackersIter.hasNext()) {
        SOCPlayerTracker tracker = trackersIter.next();
        Iterator<SOCPossibleRoad> posRoadsIter = tracker.getPossibleRoads().values().iterator();
        while (posRoadsIter.hasNext()) {
            posRoadsIter.next().clearThreats();
        }
        Iterator<SOCPossibleSettlement> posSetsIter = tracker.getPossibleSettlements().values().iterator();
        while (posSetsIter.hasNext()) {
            posSetsIter.next().clearThreats();
        }
    }
    trackersIter = playerTrackers.values().iterator();
    while (trackersIter.hasNext()) {
        SOCPlayerTracker tracker = trackersIter.next();
        tracker.updateThreats(playerTrackers);
    }
    if (isCancel) {
        // <--- Early return, nothing else to do ---
        return;
    }
    // /
    // / see if this settlement bisected someone else's road
    // /
    // Length should be SOCGame.MAXPLAYERS
    int[] roadCount = { 0, 0, 0, 0, 0, 0 };
    SOCBoard board = game.getBoard();
    Enumeration<Integer> adjEdgeEnum = board.getAdjacentEdgesToNode(newSettlement.getCoordinates()).elements();
    while (adjEdgeEnum.hasMoreElements()) {
        final int adjEdge = adjEdgeEnum.nextElement().intValue();
        Enumeration<SOCRoad> roadEnum = board.getRoads().elements();
        while (roadEnum.hasMoreElements()) {
            SOCRoad road = roadEnum.nextElement();
            if (road.getCoordinates() == adjEdge) {
                final int roadPN = road.getPlayerNumber();
                roadCount[roadPN]++;
                if (roadCount[roadPN] == 2) {
                    if (roadPN != ourPlayerNumber) {
                        // /
                        // / this settlement bisects another players road
                        // /
                        trackersIter = playerTrackers.values().iterator();
                        while (trackersIter.hasNext()) {
                            SOCPlayerTracker tracker = trackersIter.next();
                            if (tracker.getPlayer().getPlayerNumber() == roadPN) {
                            // D.ebugPrintln("$$ updating LR Value for player "+tracker.getPlayer().getPlayerNumber());
                            // tracker.updateLRValues();
                            }
                        // tracker.recalcLongestRoadETA();
                        }
                    }
                    break;
                }
            }
        }
    }
    final int pNum = newSettlement.getPlayerNumber();
    // /
    // / update the speedups from possible settlements
    // /
    trackersIter = playerTrackers.values().iterator();
    while (trackersIter.hasNext()) {
        SOCPlayerTracker tracker = trackersIter.next();
        if (tracker.getPlayer().getPlayerNumber() == pNum) {
            Iterator<SOCPossibleSettlement> posSetsIter = tracker.getPossibleSettlements().values().iterator();
            while (posSetsIter.hasNext()) {
                posSetsIter.next().updateSpeedup();
            }
            break;
        }
    }
    // /
    // / update the speedups from possible cities
    // /
    trackersIter = playerTrackers.values().iterator();
    while (trackersIter.hasNext()) {
        SOCPlayerTracker tracker = trackersIter.next();
        if (tracker.getPlayer().getPlayerNumber() == pNum) {
            Iterator<SOCPossibleCity> posCitiesIter = tracker.getPossibleCities().values().iterator();
            while (posCitiesIter.hasNext()) {
                posCitiesIter.next().updateSpeedup();
            }
            break;
        }
    }
}
Also used : SOCBoard(soc.game.SOCBoard) SOCRoad(soc.game.SOCRoad)

Example 2 with SOCBoard

use of soc.game.SOCBoard 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 3 with SOCBoard

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

the class SOCPlayerTracker method updateSettlementConflicts.

/**
 * update settlement conflicts
 *
 * @param ps        a possible settlement
 * @param trackers  player trackers for all players
 */
protected void updateSettlementConflicts(SOCPossibleSettlement ps, HashMap<Integer, SOCPlayerTracker> trackers) {
    // D.ebugPrintln("$$$ updateSettlementConflicts : "+Integer.toHexString(ps.getCoordinates()));
    /**
     * look at all adjacent nodes and update possible settlements on nodes
     */
    Iterator<SOCPlayerTracker> trackersIter = trackers.values().iterator();
    SOCBoard board = game.getBoard();
    while (trackersIter.hasNext()) {
        SOCPlayerTracker tracker = trackersIter.next();
        /**
         * if it's not our tracker...
         */
        if (tracker.getPlayer().getPlayerNumber() != ps.getPlayer().getPlayerNumber()) {
            SOCPossibleSettlement posSet = tracker.getPossibleSettlements().get(Integer.valueOf(ps.getCoordinates()));
            if (posSet != null) {
                // D.ebugPrintln("$$$ add conflict "+Integer.toHexString(posSet.getCoordinates()));
                ps.addConflict(posSet);
                posSet.addConflict(ps);
            }
        }
        /**
         * now look at adjacent settlements
         */
        for (Integer adjNode : board.getAdjacentNodesToNode(ps.getCoordinates())) {
            SOCPossibleSettlement posSet = tracker.getPossibleSettlements().get(adjNode);
            if (posSet != null) {
                // D.ebugPrintln("$$$ add conflict "+Integer.toHexString(posSet.getCoordinates()));
                ps.addConflict(posSet);
                posSet.addConflict(ps);
            }
        }
    }
}
Also used : SOCBoard(soc.game.SOCBoard)

Example 4 with SOCBoard

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

the class SOCPlayerTracker method recalcWinGameETA.

/**
 * Recalculate the tracked player's ETA for winning the game (WGETA) by making and simulating with a copy
 * of our current potential settlement/city locations, building speed estimates (BSEs), and dice numbers,
 * looping from player's current {@link SOCPlayer#getTotalVP()} to {@link SOCGame#vp_winner}.
 *<P>
 * Calculates the fields for {@link #getWinGameETA()}, {@link #needsLA()}, {@link #needsLR()}.
 *<P>
 * Each time through the loop, given potential locations and available pieces, pick the fastest ETA
 * among each of these 2-VP combinations:
 *<UL>
 * <LI> 2 settlements (including necessary roads' ETA)
 * <LI> 2 cities
 * <LI> 1 city, 1 settlement (+ roads)
 * <LI> 1 settlement (+ roads), 1 city
 * <LI> Buy enough cards for Largest Army
 * <LI> Build enough roads for Longest Road
 *</UL>
 * The temporary potential sets, port trade flags, BSEs and dice numbers are updated with the picked pieces.
 * The loop body doesn't add new potential roads/ships or potential settlements to its copy of those sets,
 * or call {@link #expandRoadOrShip(SOCPossibleRoad, SOCPlayer, SOCPlayer, HashMap, int)}, so it may run out
 * of potential locations before {@code vp_winner} is reached.  If the loop doesn't have the locations or
 * pieces to do anything, 500 ETA and 2 VP are added to the totals to keep things moving.
 *<P>
 * If the loop reaches {@link SOCGame#vp_winner} - 1, it calculates ETAs for 1 city or settlement (+ roads)
 * instead of 2, and Largest Army and Longest Road, to make its choice.
 */
public void recalcWinGameETA() {
    int oldWGETA = winGameETA;
    try {
        needLR = false;
        needLA = false;
        winGameETA = 0;
        SOCPlayerNumbers tempPlayerNumbers = new SOCPlayerNumbers(player.getNumbers());
        boolean[] tempPortFlags = new boolean[SOCBoard.WOOD_PORT + 1];
        for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
            tempPortFlags[portType] = player.getPortFlag(portType);
        }
        SOCBuildingSpeedEstimate[] tempSetBSE = new SOCBuildingSpeedEstimate[2];
        SOCBuildingSpeedEstimate[] tempCityBSE = new SOCBuildingSpeedEstimate[2];
        tempCityBSE[0] = new SOCBuildingSpeedEstimate();
        tempCityBSE[1] = new SOCBuildingSpeedEstimate();
        tempSetBSE[0] = new SOCBuildingSpeedEstimate();
        tempSetBSE[1] = new SOCBuildingSpeedEstimate();
        int[][] chosenSetBuildingSpeed = new int[2][SOCBuildingSpeedEstimate.MAXPLUSONE];
        int[][] chosenCityBuildingSpeed = new int[2][SOCBuildingSpeedEstimate.MAXPLUSONE];
        SOCBuildingSpeedEstimate tempBSE = new SOCBuildingSpeedEstimate();
        SOCBuildingSpeedEstimate ourBSE = new SOCBuildingSpeedEstimate(player.getNumbers());
        int[] ourBuildingSpeed = ourBSE.getEstimatesFromNothingFast(tempPortFlags);
        int cityETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.CITY];
        int settlementETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.SETTLEMENT];
        int roadETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.ROAD];
        int cardETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.CARD];
        // TODO shipETA, when ready
        int settlementPiecesLeft = player.getNumPieces(SOCPlayingPiece.SETTLEMENT);
        int cityPiecesLeft = player.getNumPieces(SOCPlayingPiece.CITY);
        int citySpotsLeft = possibleCities.size();
        boolean haveLA = false;
        boolean haveLR = false;
        int tempLargestArmyETA = largestArmyETA;
        int tempLongestRoadETA = longestRoadETA;
        SOCPlayer laPlayer = game.getPlayerWithLargestArmy();
        SOCPlayer lrPlayer = game.getPlayerWithLongestRoad();
        final SOCBoard board = game.getBoard();
        if (D.ebugOn) {
            if (laPlayer != null) {
                D.ebugPrintln("laPlayer # = " + laPlayer.getPlayerNumber());
            } else {
                D.ebugPrintln("laPlayer = null");
            }
            if (lrPlayer != null) {
                D.ebugPrintln("lrPlayer # = " + lrPlayer.getPlayerNumber());
            } else {
                D.ebugPrintln("lrPlayer = null");
            }
        }
        if ((laPlayer != null) && (playerNumber == laPlayer.getPlayerNumber())) {
            haveLA = true;
        }
        if ((lrPlayer != null) && (playerNumber == lrPlayer.getPlayerNumber())) {
            haveLR = true;
        }
        TreeMap<Integer, SOCPossibleSettlement> posSetsCopy = new TreeMap<Integer, SOCPossibleSettlement>(possibleSettlements);
        TreeMap<Integer, SOCPossibleCity> posCitiesCopy = new TreeMap<Integer, SOCPossibleCity>(possibleCities);
        int points = player.getTotalVP();
        int fastestETA;
        final int vp_winner = game.vp_winner;
        while (points < vp_winner) {
            D.ebugPrintln("WWW points = " + points);
            D.ebugPrintln("WWW settlementPiecesLeft = " + settlementPiecesLeft);
            D.ebugPrintln("WWW cityPiecesLeft = " + cityPiecesLeft);
            D.ebugPrintln("WWW settlementSpotsLeft = " + posSetsCopy.size());
            D.ebugPrintln("WWW citySpotsLeft = " + posCitiesCopy.size());
            if (D.ebugOn) {
                D.ebugPrint("WWW tempPortFlags: ");
                for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
                    D.ebugPrint(tempPortFlags[portType] + " ");
                }
                D.ebugPrintln();
            }
            D.ebugPrintln("WWW settlementETA = " + settlementETA);
            D.ebugPrintln("WWW cityETA = " + cityETA);
            D.ebugPrintln("WWW roadETA = " + roadETA);
            D.ebugPrintln("WWW cardETA = " + cardETA);
            if (points == (vp_winner - 1)) {
                fastestETA = 500;
                SOCPossibleSettlement chosenSet = null;
                if ((settlementPiecesLeft > 0) && (!posSetsCopy.isEmpty())) {
                    Iterator<SOCPossibleSettlement> posSetsIter = posSetsCopy.values().iterator();
                    while (posSetsIter.hasNext()) {
                        SOCPossibleSettlement posSet = posSetsIter.next();
                        int posSetETA = settlementETA + (posSet.getNumberOfNecessaryRoads() * roadETA);
                        if (posSetETA < fastestETA) {
                            fastestETA = posSetETA;
                            chosenSet = posSet;
                        }
                    }
                    // /
                    if (chosenSet != null) {
                        final int totalNecRoads = calcTotalNecessaryRoads(chosenSet);
                        fastestETA = (settlementETA + (totalNecRoads * roadETA));
                        D.ebugPrintln("WWW # necesesary roads = " + totalNecRoads);
                        D.ebugPrintln("WWW this settlement eta = " + (settlementETA + (totalNecRoads * roadETA)));
                        D.ebugPrintln("WWW settlement is " + chosenSet);
                        D.ebugPrintln("WWW settlement eta = " + fastestETA);
                    } else {
                        fastestETA = 500;
                    }
                }
                if ((cityPiecesLeft > 0) && (citySpotsLeft > 0) && (cityETA <= fastestETA)) {
                    D.ebugPrintln("WWW city eta = " + cityETA);
                    fastestETA = cityETA;
                }
                if (!haveLA && !needLA && (tempLargestArmyETA < fastestETA)) {
                    D.ebugPrintln("WWW LA eta = " + tempLargestArmyETA);
                    fastestETA = tempLargestArmyETA;
                }
                if (!haveLR && !needLR && (tempLongestRoadETA < fastestETA)) {
                    D.ebugPrintln("WWW LR eta = " + tempLongestRoadETA);
                    fastestETA = tempLongestRoadETA;
                }
                if (!haveLR && !needLR && (fastestETA == tempLongestRoadETA)) {
                    needLR = true;
                    if (brain.getDRecorder().isOn()) {
                        brain.getDRecorder().record(fastestETA + ": Longest Road");
                    }
                } else if (!haveLA && !needLA && (fastestETA == tempLargestArmyETA)) {
                    needLA = true;
                    if (brain.getDRecorder().isOn()) {
                        brain.getDRecorder().record(fastestETA + ": Largest Army");
                    }
                } else if ((cityPiecesLeft > 0) && (citySpotsLeft > 0) && (cityETA == fastestETA)) {
                    if (brain.getDRecorder().isOn()) {
                        brain.getDRecorder().record(fastestETA + ": City");
                    }
                } else if (chosenSet != null) {
                    if (brain.getDRecorder().isOn()) {
                        brain.getDRecorder().record(fastestETA + ": Stlmt at " + board.nodeCoordToString(chosenSet.getCoordinates()));
                    }
                }
                D.ebugPrintln("WWW Adding " + fastestETA + " to win eta");
                winGameETA += fastestETA;
                points += 2;
            } else {
                // 
                // This is for < 9 vp (not about to win with VP_WINNER points)
                // 
                // System.out.println("Old Player Numbers = "+tempPlayerNumbers);
                // System.out.print("Old Ports = ");
                // for (int i = 0; i <= SOCBoard.WOOD_PORT; i++) {
                // System.out.print(tempPortFlags[i]+",");
                // }
                // System.out.println();
                fastestETA = 500;
                SOCPossibleSettlement[] chosenSet = new SOCPossibleSettlement[2];
                boolean[][] tempPortFlagsSet = new boolean[2][SOCBoard.WOOD_PORT + 1];
                SOCPossibleCity[] chosenCity = new SOCPossibleCity[2];
                chosenSet[0] = null;
                chosenSet[1] = null;
                chosenCity[0] = null;
                chosenCity[1] = null;
                int twoSettlements = 0;
                int twoCities = 500;
                int oneOfEach = 0;
                int cityBeforeSettlement = 500;
                int settlementBeforeCity = 500;
                // /
                if ((cityPiecesLeft > 1) && (citySpotsLeft > 1)) {
                    // 
                    // get a more accurate estimate by taking the
                    // effect on building speed into account
                    // 
                    twoCities = 500;
                    Iterator<SOCPossibleCity> posCities0Iter = posCitiesCopy.values().iterator();
                    while (posCities0Iter.hasNext()) {
                        SOCPossibleCity posCity0 = posCities0Iter.next();
                        // 
                        // update our building speed estimate
                        // 
                        tempPlayerNumbers.updateNumbers(posCity0.getCoordinates(), board);
                        tempCityBSE[0].recalculateEstimates(tempPlayerNumbers);
                        chosenCityBuildingSpeed[0] = tempCityBSE[0].getEstimatesFromNothingFast(tempPortFlags);
                        int tempCityETA = chosenCityBuildingSpeed[0][SOCBuildingSpeedEstimate.CITY];
                        // 
                        if ((cityETA + tempCityETA) < twoCities) {
                            chosenCity[0] = posCity0;
                            twoCities = (cityETA + tempCityETA);
                        }
                        tempPlayerNumbers.undoUpdateNumbers(posCity0.getCoordinates(), board);
                    }
                    if (twoCities <= fastestETA) {
                        D.ebugPrintln("WWW twoCities = " + twoCities);
                        fastestETA = twoCities;
                    }
                }
                // /
                // / two settlements
                // /
                boolean canBuild2Settlements = false;
                if ((settlementPiecesLeft > 1) && (posSetsCopy.size() > 1)) {
                    canBuild2Settlements = true;
                    ArrayList<SOCPossibleSettlement> posSetsToPutBack = new ArrayList<SOCPossibleSettlement>();
                    for (int i = 0; i < 2; i++) {
                        int fastestSetETA = 500;
                        int bestSpeedupTotal = 0;
                        if (posSetsCopy.isEmpty()) {
                            canBuild2Settlements = false;
                        } else {
                            Iterator<SOCPossibleSettlement> posSetsIter = posSetsCopy.values().iterator();
                            while (posSetsIter.hasNext()) {
                                SOCPossibleSettlement posSet = posSetsIter.next();
                                int posSetETA = settlementETA + (posSet.getNumberOfNecessaryRoads() * roadETA);
                                final int posSetCoord = posSet.getCoordinates();
                                if (posSetETA < fastestSetETA) {
                                    fastestSetETA = posSetETA;
                                    tempPlayerNumbers.updateNumbers(posSetCoord, board);
                                    for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
                                        tempPortFlagsSet[i][portType] = tempPortFlags[portType];
                                    }
                                    int portType = board.getPortTypeFromNodeCoord(posSetCoord);
                                    if (portType != -1)
                                        tempPortFlagsSet[i][portType] = true;
                                    tempSetBSE[i].recalculateEstimates(tempPlayerNumbers);
                                    chosenSetBuildingSpeed[i] = tempSetBSE[i].getEstimatesFromNothingFast(tempPortFlagsSet[i]);
                                    for (int buildingType = SOCBuildingSpeedEstimate.MIN; buildingType < SOCBuildingSpeedEstimate.MAXPLUSONE; buildingType++) {
                                        if ((ourBuildingSpeed[buildingType] - chosenSetBuildingSpeed[i][buildingType]) > 0) {
                                            bestSpeedupTotal += (ourBuildingSpeed[buildingType] - chosenSetBuildingSpeed[i][buildingType]);
                                        }
                                    }
                                    tempPlayerNumbers.undoUpdateNumbers(posSetCoord, board);
                                    chosenSet[i] = posSet;
                                } else if (posSetETA == fastestSetETA) {
                                    boolean[] veryTempPortFlags = new boolean[SOCBoard.WOOD_PORT + 1];
                                    tempPlayerNumbers.updateNumbers(posSetCoord, board);
                                    for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
                                        veryTempPortFlags[portType] = tempPortFlags[portType];
                                    }
                                    int portType = board.getPortTypeFromNodeCoord(posSetCoord);
                                    if (portType != -1)
                                        veryTempPortFlags[portType] = true;
                                    tempBSE.recalculateEstimates(tempPlayerNumbers);
                                    int[] tempBuildingSpeed = tempBSE.getEstimatesFromNothingFast(veryTempPortFlags);
                                    int tempSpeedupTotal = 0;
                                    // boolean ok = true;
                                    for (int buildingType = SOCBuildingSpeedEstimate.MIN; buildingType < SOCBuildingSpeedEstimate.MAXPLUSONE; buildingType++) {
                                        if ((ourBuildingSpeed[buildingType] - tempBuildingSpeed[buildingType]) >= 0) {
                                            tempSpeedupTotal += (ourBuildingSpeed[buildingType] - tempBuildingSpeed[buildingType]);
                                        } else {
                                        // ok = false;
                                        }
                                    }
                                    // if (ok) {
                                    // good++;
                                    // } else {
                                    // bad++;
                                    // //
                                    // // output the player number data
                                    // //
                                    // System.out.println("New Player Numbers = "+tempPlayerNumbers);
                                    // System.out.print("New Ports = ");
                                    // for (int k = 0; k <= SOCBoard.WOOD_PORT; k++) {
                                    // System.out.print(veryTempPortFlags[k]+",");
                                    // }
                                    // System.out.println();
                                    // }
                                    tempPlayerNumbers.undoUpdateNumbers(posSetCoord, board);
                                    if (tempSpeedupTotal > bestSpeedupTotal) {
                                        fastestSetETA = posSetETA;
                                        bestSpeedupTotal = tempSpeedupTotal;
                                        for (int buildingType = SOCBuildingSpeedEstimate.MIN; buildingType < SOCBuildingSpeedEstimate.MAXPLUSONE; buildingType++) {
                                            chosenSetBuildingSpeed[i][buildingType] = tempBuildingSpeed[buildingType];
                                        }
                                        for (portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
                                            tempPortFlagsSet[i][portType] = veryTempPortFlags[portType];
                                        }
                                        chosenSet[i] = posSet;
                                    }
                                }
                            }
                            // /
                            // /  estimate setETA using building speed
                            // /  for settlements and roads from nothing
                            // /
                            // /  as long as this settlement needs roads
                            // /  add a roadETA to the ETA for this settlement
                            // /
                            int totalNecRoads = calcTotalNecessaryRoads(chosenSet[i]);
                            D.ebugPrintln("WWW # necesesary roads = " + totalNecRoads);
                            D.ebugPrintln("WWW this settlement eta = " + (settlementETA + (totalNecRoads * roadETA)));
                            if ((i == 0) && (chosenSet[0] != null)) {
                                posSetsCopy.remove(Integer.valueOf(chosenSet[0].getCoordinates()));
                                for (SOCPossibleSettlement conflict : chosenSet[0].getConflicts()) {
                                    Integer conflictInt = Integer.valueOf(conflict.getCoordinates());
                                    SOCPossibleSettlement possibleConflict = posSetsCopy.get(conflictInt);
                                    if (possibleConflict != null) {
                                        posSetsToPutBack.add(possibleConflict);
                                        posSetsCopy.remove(conflictInt);
                                    }
                                }
                                twoSettlements += (settlementETA + (totalNecRoads * roadETA));
                            }
                            if ((i == 1) && (chosenSet[1] != null)) {
                                // 
                                // get a more accurate estimate by taking the
                                // effect on building speed into account
                                // 
                                int tempSettlementETA = chosenSetBuildingSpeed[0][SOCBuildingSpeedEstimate.SETTLEMENT];
                                int tempRoadETA = chosenSetBuildingSpeed[0][SOCBuildingSpeedEstimate.ROAD];
                                twoSettlements += (tempSettlementETA + (totalNecRoads * tempRoadETA));
                            }
                        }
                    }
                    posSetsCopy.put(Integer.valueOf(chosenSet[0].getCoordinates()), chosenSet[0]);
                    for (SOCPossibleSettlement tmpPosSet : posSetsToPutBack) {
                        posSetsCopy.put(Integer.valueOf(tmpPosSet.getCoordinates()), tmpPosSet);
                    }
                    if (canBuild2Settlements && (twoSettlements <= fastestETA)) {
                        D.ebugPrintln("WWW 2 * settlement = " + twoSettlements);
                        fastestETA = twoSettlements;
                    }
                }
                // /
                if ((cityPiecesLeft > 0) && (((settlementPiecesLeft > 0) && (citySpotsLeft >= 0)) || ((settlementPiecesLeft >= 0) && (citySpotsLeft > 0))) && !posSetsCopy.isEmpty()) {
                    // 
                    if ((chosenCity[0] == null) && (citySpotsLeft > 0)) {
                        int bestCitySpeedupTotal = 0;
                        Iterator<SOCPossibleCity> posCities0Iter = posCitiesCopy.values().iterator();
                        while (posCities0Iter.hasNext()) {
                            SOCPossibleCity posCity0 = posCities0Iter.next();
                            tempPlayerNumbers.updateNumbers(posCity0.getCoordinates(), board);
                            tempBSE.recalculateEstimates(tempPlayerNumbers);
                            int[] tempBuildingSpeed = tempBSE.getEstimatesFromNothingFast(tempPortFlags);
                            int tempSpeedupTotal = 0;
                            // boolean ok = true;
                            for (int buildingType = SOCBuildingSpeedEstimate.MIN; buildingType < SOCBuildingSpeedEstimate.MAXPLUSONE; buildingType++) {
                                if ((ourBuildingSpeed[buildingType] - tempBuildingSpeed[buildingType]) >= 0) {
                                    tempSpeedupTotal += (ourBuildingSpeed[buildingType] - tempBuildingSpeed[buildingType]);
                                } else {
                                // ok = false;
                                }
                            }
                            // if (ok) {
                            // good++;
                            // } else {
                            // bad++;
                            // //
                            // // output the player number data
                            // //
                            // System.out.println("New Player Numbers = "+tempPlayerNumbers);
                            // System.out.print("New Ports = ");
                            // for (int i = 0; i <= SOCBoard.WOOD_PORT; i++) {
                            // System.out.print(tempPortFlags[i]+",");
                            // }
                            // System.out.println();
                            // }
                            tempPlayerNumbers.undoUpdateNumbers(posCity0.getCoordinates(), board);
                            if (tempSpeedupTotal >= bestCitySpeedupTotal) {
                                bestCitySpeedupTotal = tempSpeedupTotal;
                                for (int buildingType = SOCBuildingSpeedEstimate.MIN; buildingType < SOCBuildingSpeedEstimate.MAXPLUSONE; buildingType++) {
                                    chosenCityBuildingSpeed[0][buildingType] = tempBuildingSpeed[buildingType];
                                }
                                chosenCity[0] = posCity0;
                            }
                        }
                    }
                    // 
                    if (chosenSet[0] == null) {
                        int fastestSetETA = 500;
                        int bestSpeedupTotal = 0;
                        Iterator<SOCPossibleSettlement> posSetsIter = posSetsCopy.values().iterator();
                        while (posSetsIter.hasNext()) {
                            SOCPossibleSettlement posSet = posSetsIter.next();
                            int posSetETA = settlementETA + (posSet.getNumberOfNecessaryRoads() * roadETA);
                            if (posSetETA < fastestSetETA) {
                                fastestSetETA = posSetETA;
                                tempPlayerNumbers.updateNumbers(posSet.getCoordinates(), board);
                                for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
                                    tempPortFlagsSet[0][portType] = tempPortFlags[portType];
                                }
                                int portType = board.getPortTypeFromNodeCoord(posSet.getCoordinates());
                                if (portType != -1)
                                    tempPortFlagsSet[0][portType] = true;
                                tempSetBSE[0].recalculateEstimates(tempPlayerNumbers);
                                chosenSetBuildingSpeed[0] = tempSetBSE[0].getEstimatesFromNothingFast(tempPortFlagsSet[0]);
                                for (int buildingType = SOCBuildingSpeedEstimate.MIN; buildingType < SOCBuildingSpeedEstimate.MAXPLUSONE; buildingType++) {
                                    if ((ourBuildingSpeed[buildingType] - chosenSetBuildingSpeed[0][buildingType]) > 0) {
                                        bestSpeedupTotal += (ourBuildingSpeed[buildingType] - chosenSetBuildingSpeed[0][buildingType]);
                                    }
                                }
                                tempPlayerNumbers.undoUpdateNumbers(posSet.getCoordinates(), board);
                                chosenSet[0] = posSet;
                            } else if (posSetETA == fastestSetETA) {
                                boolean[] veryTempPortFlags = new boolean[SOCBoard.WOOD_PORT + 1];
                                tempPlayerNumbers.updateNumbers(posSet.getCoordinates(), board);
                                for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
                                    veryTempPortFlags[portType] = tempPortFlags[portType];
                                }
                                int portType = board.getPortTypeFromNodeCoord(posSet.getCoordinates());
                                if (portType != -1)
                                    veryTempPortFlags[portType] = true;
                                tempBSE.recalculateEstimates(tempPlayerNumbers);
                                int[] tempBuildingSpeed = tempBSE.getEstimatesFromNothingFast(veryTempPortFlags);
                                int tempSpeedupTotal = 0;
                                // boolean ok = true;
                                for (int buildingType = SOCBuildingSpeedEstimate.MIN; buildingType < SOCBuildingSpeedEstimate.MAXPLUSONE; buildingType++) {
                                    if ((ourBuildingSpeed[buildingType] - tempBuildingSpeed[buildingType]) >= 0) {
                                        tempSpeedupTotal += (ourBuildingSpeed[buildingType] - tempBuildingSpeed[buildingType]);
                                    } else {
                                    // ok = false;
                                    }
                                }
                                // if (ok) {
                                // good++;
                                // } else {
                                // bad++;
                                // //
                                // // output the player number data
                                // //
                                // System.out.println("New Player Numbers = "+tempPlayerNumbers);
                                // System.out.print("New Ports = ");
                                // for (int i = 0; i <= SOCBoard.WOOD_PORT; i++) {
                                // System.out.print(tempPortFlags[i]+",");
                                // }
                                // System.out.println();
                                // }
                                tempPlayerNumbers.undoUpdateNumbers(posSet.getCoordinates(), board);
                                if (tempSpeedupTotal > bestSpeedupTotal) {
                                    fastestSetETA = posSetETA;
                                    bestSpeedupTotal = tempSpeedupTotal;
                                    for (int buildingType = SOCBuildingSpeedEstimate.MIN; buildingType < SOCBuildingSpeedEstimate.MAXPLUSONE; buildingType++) {
                                        chosenSetBuildingSpeed[0][buildingType] = tempBuildingSpeed[buildingType];
                                    }
                                    for (portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) {
                                        tempPortFlagsSet[0][portType] = veryTempPortFlags[portType];
                                    }
                                    chosenSet[0] = posSet;
                                }
                            }
                        }
                    }
                    if (citySpotsLeft == 0) {
                        chosenCity[0] = new SOCPossibleCity(player, chosenSet[0].getCoordinates());
                    }
                    // /
                    // /  estimate setETA using building speed
                    // /  for settlements and roads from nothing
                    // /
                    // /  as long as this settlement needs roads
                    // /  add a roadETA to the ETA for this settlement
                    // /
                    int totalNecRoads = calcTotalNecessaryRoads(chosenSet[0]);
                    D.ebugPrintln("WWW # necesesary roads = " + totalNecRoads);
                    D.ebugPrintln("WWW this settlement eta = " + (settlementETA + (totalNecRoads * roadETA)));
                    // 
                    if ((settlementPiecesLeft > 0) && (citySpotsLeft >= 0)) {
                        int tempCityETA = chosenSetBuildingSpeed[0][SOCBuildingSpeedEstimate.CITY];
                        settlementBeforeCity = tempCityETA + (settlementETA + (totalNecRoads * roadETA));
                    }
                    if ((settlementPiecesLeft >= 0) && (citySpotsLeft > 0)) {
                        int tempSettlementETA = chosenCityBuildingSpeed[0][SOCBuildingSpeedEstimate.SETTLEMENT];
                        int tempRoadETA = chosenCityBuildingSpeed[0][SOCBuildingSpeedEstimate.ROAD];
                        cityBeforeSettlement = cityETA + (tempSettlementETA + (totalNecRoads * tempRoadETA));
                    }
                    if (settlementBeforeCity < cityBeforeSettlement) {
                        oneOfEach = settlementBeforeCity;
                    } else {
                        oneOfEach = cityBeforeSettlement;
                    }
                    if (oneOfEach <= fastestETA) {
                        D.ebugPrintln("WWW one of each = " + oneOfEach);
                        fastestETA = oneOfEach;
                    }
                }
                // /
                if (!haveLA && !needLA && (points > 5)) {
                    // 
                    // recalc LA eta given our new building speed
                    // 
                    int laSize = 0;
                    if (laPlayer == null) {
                        // /
                        // / no one has largest army
                        // /
                        laSize = 3;
                    } else if (laPlayer.getPlayerNumber() == playerNumber) {
                        // /
                        // / we have largest army
                        // /
                        D.ebugPrintln("WWW ERROR CALCULATING LA ETA");
                    } else {
                        laSize = laPlayer.getNumKnights() + 1;
                    }
                    // /
                    // / figure out how many knights we need to buy
                    // /
                    knightsToBuy = 0;
                    if ((player.getNumKnights() + player.getInventory().getAmount(SOCDevCardConstants.KNIGHT)) < // OLD + NEW knights
                    laSize) {
                        knightsToBuy = laSize - (player.getNumKnights() + player.getInventory().getAmount(SOCInventory.OLD, SOCDevCardConstants.KNIGHT));
                    }
                    // /
                    if (game.getNumDevCards() >= knightsToBuy) {
                        tempLargestArmyETA = (cardETA + 1) * knightsToBuy;
                    } else {
                        tempLargestArmyETA = 500;
                    }
                    D.ebugPrintln("WWW LA eta = " + tempLargestArmyETA);
                    if (tempLargestArmyETA < fastestETA) {
                        fastestETA = tempLargestArmyETA;
                    }
                }
                // 
                if (!haveLR && !needLR && (points > 5)) {
                    tempLongestRoadETA = roadETA * roadsToGo;
                    D.ebugPrintln("WWW LR eta = " + tempLongestRoadETA);
                    if (tempLongestRoadETA < fastestETA) {
                        fastestETA = tempLongestRoadETA;
                    }
                }
                // /
                // / implement the fastest scenario
                // /
                D.ebugPrintln("WWW Adding " + fastestETA + " to win eta");
                points += 2;
                winGameETA += fastestETA;
                D.ebugPrintln("WWW WGETA SO FAR FOR PLAYER " + playerNumber + " = " + winGameETA);
                if ((settlementPiecesLeft > 1) && (posSetsCopy.size() > 1) && canBuild2Settlements && (fastestETA == twoSettlements)) {
                    Integer chosenSet0Int = Integer.valueOf(chosenSet[0].getCoordinates());
                    Integer chosenSet1Int = Integer.valueOf(chosenSet[1].getCoordinates());
                    posSetsCopy.remove(chosenSet0Int);
                    posSetsCopy.remove(chosenSet1Int);
                    posCitiesCopy.put(chosenSet0Int, new SOCPossibleCity(player, chosenSet[0].getCoordinates()));
                    posCitiesCopy.put(chosenSet1Int, new SOCPossibleCity(player, chosenSet[1].getCoordinates()));
                    // 
                    for (SOCPossibleSettlement conflict : chosenSet[0].getConflicts()) {
                        Integer conflictInt = Integer.valueOf(conflict.getCoordinates());
                        posSetsCopy.remove(conflictInt);
                    }
                    for (SOCPossibleSettlement conflict : chosenSet[1].getConflicts()) {
                        Integer conflictInt = Integer.valueOf(conflict.getCoordinates());
                        posSetsCopy.remove(conflictInt);
                    }
                    settlementPiecesLeft -= 2;
                    citySpotsLeft += 2;
                    // 
                    // update our building speed estimate
                    // 
                    tempPlayerNumbers.updateNumbers(chosenSet[0].getCoordinates(), board);
                    tempPlayerNumbers.updateNumbers(chosenSet[1].getCoordinates(), board);
                    int portType = board.getPortTypeFromNodeCoord(chosenSet[0].getCoordinates());
                    if (portType != -1)
                        tempPortFlags[portType] = true;
                    portType = board.getPortTypeFromNodeCoord(chosenSet[1].getCoordinates());
                    if (portType != -1)
                        tempPortFlags[portType] = true;
                    ourBSE.recalculateEstimates(tempPlayerNumbers);
                    ourBuildingSpeed = ourBSE.getEstimatesFromNothingFast(tempPortFlags);
                    settlementETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.SETTLEMENT];
                    roadETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.ROAD];
                    cityETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.CITY];
                    cardETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.CARD];
                    D.ebugPrintln("WWW  * build two settlements");
                    D.ebugPrintln("WWW    settlement 1: " + board.nodeCoordToString(chosenSet[0].getCoordinates()));
                    D.ebugPrintln("WWW    settlement 2: " + board.nodeCoordToString(chosenSet[1].getCoordinates()));
                    if (brain.getDRecorder().isOn()) {
                        brain.getDRecorder().record(fastestETA + ": Stlmt at " + board.nodeCoordToString(chosenSet[0].getCoordinates()) + "; Stlmt at " + board.nodeCoordToString(chosenSet[1].getCoordinates()));
                    }
                } else if (((cityPiecesLeft > 0) && (((settlementPiecesLeft > 0) && (citySpotsLeft >= 0)) || ((settlementPiecesLeft >= 0) && (citySpotsLeft > 0))) && !posSetsCopy.isEmpty()) && (fastestETA == oneOfEach)) {
                    Integer chosenSet0Int = Integer.valueOf(chosenSet[0].getCoordinates());
                    posSetsCopy.remove(chosenSet0Int);
                    if (chosenSet[0].getCoordinates() != chosenCity[0].getCoordinates()) {
                        posCitiesCopy.put(chosenSet0Int, new SOCPossibleCity(player, chosenSet[0].getCoordinates()));
                    }
                    posCitiesCopy.remove(Integer.valueOf(chosenCity[0].getCoordinates()));
                    cityPiecesLeft -= 1;
                    // 
                    for (SOCPossibleSettlement conflict : chosenSet[0].getConflicts()) {
                        Integer conflictInt = Integer.valueOf(conflict.getCoordinates());
                        posSetsCopy.remove(conflictInt);
                    }
                    // 
                    // update our building speed estimate
                    // 
                    tempPlayerNumbers.updateNumbers(chosenSet[0].getCoordinates(), board);
                    int portType = board.getPortTypeFromNodeCoord(chosenSet[0].getCoordinates());
                    if (portType != -1)
                        tempPortFlags[portType] = true;
                    tempPlayerNumbers.updateNumbers(chosenCity[0].getCoordinates(), board);
                    ourBSE.recalculateEstimates(tempPlayerNumbers);
                    ourBuildingSpeed = ourBSE.getEstimatesFromNothingFast(tempPortFlags);
                    settlementETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.SETTLEMENT];
                    roadETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.ROAD];
                    cityETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.CITY];
                    cardETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.CARD];
                    D.ebugPrintln("WWW  * build a settlement and a city");
                    D.ebugPrintln("WWW    settlement at " + board.nodeCoordToString(chosenSet[0].getCoordinates()));
                    D.ebugPrintln("WWW    city at " + board.nodeCoordToString(chosenCity[0].getCoordinates()));
                    if (brain.getDRecorder().isOn()) {
                        if (fastestETA == settlementBeforeCity) {
                            brain.getDRecorder().record(fastestETA + ": Stlmt at " + board.nodeCoordToString(chosenSet[0].getCoordinates()) + "; City at " + board.nodeCoordToString(chosenCity[0].getCoordinates()));
                        } else {
                            brain.getDRecorder().record(fastestETA + ": City at " + board.nodeCoordToString(chosenCity[0].getCoordinates()) + "; Stlmt at " + board.nodeCoordToString(chosenSet[0].getCoordinates()));
                        }
                    }
                } else if ((cityPiecesLeft > 1) && (citySpotsLeft > 1) && (fastestETA == twoCities)) {
                    posCitiesCopy.remove(Integer.valueOf(chosenCity[0].getCoordinates()));
                    // 
                    // update our building speed estimate
                    // 
                    tempPlayerNumbers.updateNumbers(chosenCity[0].getCoordinates(), board);
                    // 
                    // pick the second city to build
                    // 
                    int bestCitySpeedupTotal = 0;
                    Iterator<SOCPossibleCity> posCities1Iter = posCitiesCopy.values().iterator();
                    while (posCities1Iter.hasNext()) {
                        SOCPossibleCity posCity1 = posCities1Iter.next();
                        tempPlayerNumbers.updateNumbers(posCity1.getCoordinates(), board);
                        D.ebugPrintln("tempPlayerNumbers = " + tempPlayerNumbers);
                        tempBSE.recalculateEstimates(tempPlayerNumbers);
                        int[] tempBuildingSpeed = tempBSE.getEstimatesFromNothingFast(tempPortFlags);
                        int tempSpeedupTotal = 0;
                        // boolean ok = true;
                        for (int buildingType = SOCBuildingSpeedEstimate.MIN; buildingType < SOCBuildingSpeedEstimate.MAXPLUSONE; buildingType++) {
                            D.ebugPrintln("ourBuildingSpeed[" + buildingType + "] = " + ourBuildingSpeed[buildingType]);
                            D.ebugPrintln("tempBuildingSpeed[" + buildingType + "] = " + tempBuildingSpeed[buildingType]);
                            if ((ourBuildingSpeed[buildingType] - tempBuildingSpeed[buildingType]) >= 0) {
                                tempSpeedupTotal += (ourBuildingSpeed[buildingType] - tempBuildingSpeed[buildingType]);
                            } else {
                            // ok = false;
                            }
                        }
                        // if (ok) {
                        // good++;
                        // } else {
                        // bad++;
                        // //
                        // // output the player number data
                        // //
                        // System.out.println("New Player Numbers = "+tempPlayerNumbers);
                        // System.out.print("New Ports = ");
                        // for (int i = 0; i <= SOCBoard.WOOD_PORT; i++) {
                        // System.out.print(tempPortFlags[i]+",");
                        // }
                        // System.out.println();
                        // }
                        tempPlayerNumbers.undoUpdateNumbers(posCity1.getCoordinates(), board);
                        D.ebugPrintln("tempPlayerNumbers = " + tempPlayerNumbers);
                        D.ebugPrintln("WWW City at " + board.nodeCoordToString(posCity1.getCoordinates()) + " has tempSpeedupTotal = " + tempSpeedupTotal);
                        if (tempSpeedupTotal >= bestCitySpeedupTotal) {
                            bestCitySpeedupTotal = tempSpeedupTotal;
                            chosenCity[1] = posCity1;
                        }
                    }
                    if (chosenCity[1] == null) {
                        System.out.println("OOPS!!!");
                    } else {
                        posCitiesCopy.remove(Integer.valueOf(chosenCity[1].getCoordinates()));
                    }
                    settlementPiecesLeft += 2;
                    cityPiecesLeft -= 2;
                    citySpotsLeft -= 2;
                    tempPlayerNumbers.updateNumbers(chosenCity[1].getCoordinates(), board);
                    ourBSE.recalculateEstimates(tempPlayerNumbers);
                    ourBuildingSpeed = ourBSE.getEstimatesFromNothingFast(tempPortFlags);
                    settlementETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.SETTLEMENT];
                    roadETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.ROAD];
                    cityETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.CITY];
                    cardETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.CARD];
                    D.ebugPrintln("WWW  * build 2 cities");
                    D.ebugPrintln("WWW    city 1: " + board.nodeCoordToString(chosenCity[0].getCoordinates()));
                    D.ebugPrintln("WWW    city 2: " + board.nodeCoordToString(chosenCity[1].getCoordinates()));
                    if (brain.getDRecorder().isOn()) {
                        brain.getDRecorder().record(fastestETA + ": City at " + board.nodeCoordToString(chosenCity[0].getCoordinates()) + "; City at " + board.nodeCoordToString(chosenCity[1].getCoordinates()));
                    }
                } else if (!haveLR && !needLR && (points > 5) && (fastestETA == tempLongestRoadETA)) {
                    needLR = true;
                    D.ebugPrintln("WWW  * take longest road");
                    if (brain.getDRecorder().isOn()) {
                        brain.getDRecorder().record(fastestETA + ": Longest Road");
                    }
                } else if (!haveLA && !needLA && (points > 5) && (fastestETA == tempLargestArmyETA)) {
                    needLA = true;
                    D.ebugPrintln("WWW  * take largest army");
                    if (brain.getDRecorder().isOn()) {
                        brain.getDRecorder().record(fastestETA + ": Largest Army");
                    }
                }
            }
        }
        D.ebugPrintln("WWW TOTAL WGETA FOR PLAYER " + playerNumber + " = " + winGameETA);
        if (brain.getDRecorder().isOn()) {
            brain.getDRecorder().record("Total WGETA for " + player.getName() + " = " + winGameETA);
            brain.getDRecorder().record("--------------------");
        }
    } catch (Exception e) {
        winGameETA = oldWGETA;
        System.out.println("Exception in recalcWinGameETA - " + e);
        e.printStackTrace();
    }
// System.out.println("good = "+good+" bad = "+bad);
// System.out.println();
}
Also used : SOCBoard(soc.game.SOCBoard) ArrayList(java.util.ArrayList) TreeMap(java.util.TreeMap) SOCPlayerNumbers(soc.game.SOCPlayerNumbers) SOCPlayer(soc.game.SOCPlayer)

Example 5 with SOCBoard

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

the class SOCPlayerTracker method updateThreats.

/**
 * update threats for pieces that need to be updated
 *
 * @param trackers  all of the player trackers
 */
public void updateThreats(HashMap<Integer, SOCPlayerTracker> trackers) {
    // D.ebugPrintln("&&&& updateThreats");
    /**
     * check roads that need updating and don't have necessary roads
     */
    SOCBoard board = game.getBoard();
    Iterator<SOCPossibleRoad> posRoadsIter = possibleRoads.values().iterator();
    while (posRoadsIter.hasNext()) {
        SOCPossibleRoad posRoad = posRoadsIter.next();
        if ((!posRoad.isThreatUpdated()) && posRoad.getNecessaryRoads().isEmpty()) {
            // D.ebugPrintln("&&&& examining road at "+Integer.toHexString(posRoad.getCoordinates()));
            /**
             * look for possible settlements that can block this road
             */
            final int[] adjNodesToPosRoad = board.getAdjacentNodesToEdge_arr(posRoad.getCoordinates());
            Enumeration<Integer> adjEdgeEnum = board.getAdjacentEdgesToEdge(posRoad.getCoordinates()).elements();
            while (adjEdgeEnum.hasMoreElements()) {
                final int adjEdge = adjEdgeEnum.nextElement().intValue();
                Enumeration<SOCRoad> realRoadEnum = player.getRoads().elements();
                while (realRoadEnum.hasMoreElements()) {
                    SOCRoad realRoad = realRoadEnum.nextElement();
                    if (adjEdge == realRoad.getCoordinates()) {
                        /**
                         * found an adjacent supporting road, now find the node between
                         * the supporting road and the possible road
                         */
                        final int[] adjNodesToRealRoad = realRoad.getAdjacentNodes();
                        for (int pi = 0; pi < 2; ++pi) {
                            final int adjNodeToPosRoad = adjNodesToPosRoad[pi];
                            for (int ri = 0; ri < 2; ++ri) {
                                final int adjNodeToRealRoad = adjNodesToRealRoad[ri];
                                if (adjNodeToPosRoad == adjNodeToRealRoad) {
                                    /**
                                     * we found the common node
                                     * now see if there is a possible enemy settlement
                                     */
                                    final Integer adjNodeToPosRoadInt = Integer.valueOf(adjNodeToPosRoad);
                                    Iterator<SOCPlayerTracker> trackersIter = trackers.values().iterator();
                                    while (trackersIter.hasNext()) {
                                        SOCPlayerTracker tracker = trackersIter.next();
                                        if (tracker.getPlayer().getPlayerNumber() != playerNumber) {
                                            SOCPossibleSettlement posEnemySet = tracker.getPossibleSettlements().get(adjNodeToPosRoadInt);
                                            if (posEnemySet != null) {
                                                /**
                                                 * we found a settlement that threatens our possible road
                                                 */
                                                // D.ebugPrintln("&&&& adding threat from settlement at "+Integer.toHexString(posEnemySet.getCoordinates()));
                                                posRoad.addThreat(posEnemySet);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            /**
             * look for enemy roads that can block this road
             */
            Iterator<SOCPlayerTracker> trackersIter = trackers.values().iterator();
            while (trackersIter.hasNext()) {
                SOCPlayerTracker tracker = trackersIter.next();
                if (tracker.getPlayer().getPlayerNumber() != playerNumber) {
                    SOCPossibleRoad posEnemyRoad = tracker.getPossibleRoads().get(Integer.valueOf(posRoad.getCoordinates()));
                    if (posEnemyRoad != null) {
                        /**
                         * we found a road that threatens our possible road
                         */
                        // D.ebugPrintln("&&&& adding threat from road at "+Integer.toHexString(posEnemyRoad.getCoordinates()));
                        posRoad.addThreat(posEnemyRoad);
                    }
                }
            }
            /**
             * look at all of the roads that this possible road supports.
             * if any of those roads are solely dependent on this
             * possible road, then all of the possible pieces that
             * threaten this road, also threaten those pieces
             */
            final List<SOCPossiblePiece> threats = posRoad.getThreats();
            final Stack<SOCPossiblePiece> stack = new Stack<SOCPossiblePiece>();
            stack.push(posRoad);
            while (!stack.empty()) {
                SOCPossiblePiece curPosPiece = stack.pop();
                if ((curPosPiece.getType() == SOCPossiblePiece.ROAD) || ((curPosPiece instanceof SOCPossibleShip) && ((SOCPossibleShip) curPosPiece).isCoastalRoadAndShip)) {
                    for (SOCPossiblePiece newPosPiece : ((SOCPossibleRoad) curPosPiece).getNewPossibilities()) {
                        if ((newPosPiece.getType() == SOCPossiblePiece.ROAD) || ((newPosPiece instanceof SOCPossibleShip) && ((SOCPossibleShip) newPosPiece).isCoastalRoadAndShip)) {
                            final List<SOCPossibleRoad> necRoadList = ((SOCPossibleRoad) newPosPiece).getNecessaryRoads();
                            if ((necRoadList.size() == 1) && (necRoadList.get(0) == curPosPiece)) {
                                // D.ebugPrintln("&&&& adding threats to road at "+Integer.toHexString(newPosPiece.getCoordinates()));
                                for (SOCPossiblePiece threat : threats) ((SOCPossibleRoad) newPosPiece).addThreat(threat);
                            }
                            /**
                             * put this piece on the stack
                             */
                            stack.push(newPosPiece);
                        }
                    }
                }
            }
            // D.ebugPrintln("&&&& done updating road at "+Integer.toHexString(posRoad.getCoordinates()));
            posRoad.threatUpdated();
        }
    }
    /**
     * check roads that need updating and DO have necessary roads
     */
    posRoadsIter = possibleRoads.values().iterator();
    while (posRoadsIter.hasNext()) {
        SOCPossibleRoad posRoad = posRoadsIter.next();
        if (!posRoad.isThreatUpdated()) {
            // D.ebugPrintln("&&&& examining road at "+Integer.toHexString(posRoad.getCoordinates()));
            /**
             * check for enemy roads with
             * the same coordinates
             */
            Iterator<SOCPlayerTracker> trackersIter = trackers.values().iterator();
            while (trackersIter.hasNext()) {
                SOCPlayerTracker tracker = trackersIter.next();
                if (tracker.getPlayer().getPlayerNumber() != playerNumber) {
                    SOCPossibleRoad posEnemyRoad = tracker.getPossibleRoads().get(Integer.valueOf(posRoad.getCoordinates()));
                    if (posEnemyRoad != null) {
                        /**
                         * we found a road that threatens our possible road
                         */
                        // D.ebugPrintln("&&&& adding threat from road at "+Integer.toHexString(posEnemyRoad.getCoordinates()));
                        posRoad.addThreat(posEnemyRoad);
                        posRoad.threatUpdated();
                    }
                }
            }
            /**
             * look for possible settlements that can block this road
             */
            /**
             * if this road has only one supporting road,
             * find the node between this and the supporting road
             */
            final List<SOCPossibleRoad> necRoadList = posRoad.getNecessaryRoads();
            if (necRoadList.size() == 1) {
                final SOCPossibleRoad necRoad = necRoadList.get(0);
                final int[] adjNodes1 = board.getAdjacentNodesToEdge_arr(posRoad.getCoordinates());
                for (int i1 = 0; i1 < 2; ++i1) {
                    final int adjNode1 = adjNodes1[i1];
                    final int[] adjNodes2 = board.getAdjacentNodesToEdge_arr(necRoad.getCoordinates());
                    for (int i2 = 0; i2 < 2; ++i2) {
                        final int adjNode2 = adjNodes2[i2];
                        if (adjNode1 == adjNode2) {
                            /**
                             * see if there is a possible enemy settlement at
                             * the node between the two possible roads
                             */
                            trackersIter = trackers.values().iterator();
                            final Integer adjNodeInt = Integer.valueOf(adjNode1);
                            while (trackersIter.hasNext()) {
                                SOCPlayerTracker tracker = trackersIter.next();
                                if (tracker.getPlayer().getPlayerNumber() != playerNumber) {
                                    SOCPossibleSettlement posEnemySet = tracker.getPossibleSettlements().get(adjNodeInt);
                                    if (posEnemySet != null) {
                                        /**
                                         * we found a settlement that threatens our possible road
                                         */
                                        // D.ebugPrintln("&&&& adding threat from settlement at "+Integer.toHexString(posEnemySet.getCoordinates()));
                                        posRoad.addThreat(posEnemySet);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            // D.ebugPrintln("&&&& done updating road at "+Integer.toHexString(posRoad.getCoordinates()));
            posRoad.threatUpdated();
        }
    }
    /**
     * check settlements that need updating
     */
    Iterator<SOCPossibleSettlement> posSetsIter = possibleSettlements.values().iterator();
    while (posSetsIter.hasNext()) {
        SOCPossibleSettlement posSet = posSetsIter.next();
        if (!posSet.isThreatUpdated()) {
            // D.ebugPrintln("&&&& examining settlement at "+Integer.toHexString(posSet.getCoordinates()));
            /**
             * see if there are enemy settlements with the same coords
             */
            Iterator<SOCPlayerTracker> trackersIter = trackers.values().iterator();
            while (trackersIter.hasNext()) {
                SOCPlayerTracker tracker = trackersIter.next();
                if (tracker.getPlayer().getPlayerNumber() != playerNumber) {
                    SOCPossibleSettlement posEnemySet = tracker.getPossibleSettlements().get(Integer.valueOf(posSet.getCoordinates()));
                    if (posEnemySet != null) {
                        // D.ebugPrintln("&&&& adding threat from settlement at "+Integer.toHexString(posEnemySet.getCoordinates()));
                        posSet.addThreat(posEnemySet);
                    }
                }
            }
            // 
            // if this settlement doesn't rely on anything, then we're done
            // 
            final List<SOCPossibleRoad> necRoadList = posSet.getNecessaryRoads();
            if (necRoadList.isEmpty()) {
                ;
            } else if (necRoadList.size() == 1) {
                for (SOCPossiblePiece nrThreat : necRoadList.get(0).getThreats()) posSet.addThreat(nrThreat);
            } else {
                // 
                // this settlement relies on more than one road.
                // if all of the roads have the same threat,
                // then add that threat to this settlement
                // 
                final SOCPossibleRoad nr = necRoadList.get(0);
                for (SOCPossiblePiece nrThreat : nr.getThreats()) {
                    boolean allHaveIt = true;
                    for (SOCPossibleRoad nr2 : necRoadList) {
                        if ((nr2 != nr) && !nr2.getThreats().contains(nrThreat)) {
                            allHaveIt = false;
                            break;
                        }
                    }
                    if (allHaveIt) {
                        // D.ebugPrintln("&&&& adding threat from "+Integer.toHexString(nrThreat.getCoordinates()));
                        posSet.addThreat(nrThreat);
                    }
                }
            }
            // D.ebugPrintln("&&&& done updating settlement at "+Integer.toHexString(posSet.getCoordinates()));
            posSet.threatUpdated();
        }
    }
}
Also used : SOCBoard(soc.game.SOCBoard) SOCRoad(soc.game.SOCRoad) Stack(java.util.Stack)

Aggregations

SOCBoard (soc.game.SOCBoard)16 ArrayList (java.util.ArrayList)6 SOCBoardLarge (soc.game.SOCBoardLarge)6 SOCRoad (soc.game.SOCRoad)5 SOCPlayer (soc.game.SOCPlayer)4 SOCShip (soc.game.SOCShip)4 SOCGame (soc.game.SOCGame)3 List (java.util.List)2 Stack (java.util.Stack)2 Vector (java.util.Vector)2 SOCLRPathData (soc.game.SOCLRPathData)2 TreeMap (java.util.TreeMap)1 SOCCity (soc.game.SOCCity)1 SOCFortress (soc.game.SOCFortress)1 SOCPlayerNumbers (soc.game.SOCPlayerNumbers)1 SOCPlayingPiece (soc.game.SOCPlayingPiece)1 SOCSettlement (soc.game.SOCSettlement)1 NodeLenVis (soc.util.NodeLenVis)1 Pair (soc.util.Pair)1