Search in sources :

Example 16 with SOCPlayer

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

the class SOCRobotBrain method handlePUTPIECE_updateTrackers.

/**
 * Handle a PUTPIECE for this game, by updating {@link SOCPlayerTracker}s.
 * Also handles the "move piece to here" part of MOVEPIECE.
 *<P>
 * For initial placement of our own pieces, this method also checks
 * and clears expectPUTPIECE_FROM_START1A, and sets expectSTART1B, etc.
 * The final initial putpiece clears expectPUTPIECE_FROM_START2B and sets expectROLL_OR_CARD.
 * As part of the PUTPIECE request, brain set those expectPUTPIECE flags in {@link #placeIfExpectPlacing()}.
 *<P>
 * For initial settlements, won't track here:
 * Delay tracking until the corresponding road is placed,
 * in {@link #handlePUTPIECE_updateGameData(SOCPutPiece)}.
 * This prevents the need for tracker "undo" work if a human
 * player changes their mind on where to place the settlement.
 *
 * @param pn  Piece's player number
 * @param coord  Piece coordinate
 * @param pieceType  Piece type, as in {@link SOCPlayingPiece#SETTLEMENT}
 * @since 1.1.08
 */
private void handlePUTPIECE_updateTrackers(final int pn, final int coord, final int pieceType) {
    switch(pieceType) {
        case SOCPlayingPiece.ROAD:
            SOCRoad newRoad = new SOCRoad(game.getPlayer(pn), coord, null);
            trackNewRoadOrShip(newRoad, false);
            break;
        case SOCPlayingPiece.SETTLEMENT:
            SOCPlayer newSettlementPl = game.getPlayer(pn);
            SOCSettlement newSettlement = new SOCSettlement(newSettlementPl, coord, null);
            if ((game.getGameState() == SOCGame.START1B) || (game.getGameState() == SOCGame.START2B) || (game.getGameState() == SOCGame.START3B)) {
                // Track it soon, after the road is placed
                // (in handlePUTPIECE_updateGameData)
                // but not yet, in case player cancels placement.
                SOCPlayerTracker tr = playerTrackers.get(Integer.valueOf(newSettlementPl.getPlayerNumber()));
                tr.setPendingInitSettlement(newSettlement);
            } else {
                // Track it now
                trackNewSettlement(newSettlement, false);
            }
            break;
        case SOCPlayingPiece.CITY:
            SOCCity newCity = new SOCCity(game.getPlayer(pn), coord, null);
            trackNewCity(newCity, false);
            break;
        case SOCPlayingPiece.SHIP:
            SOCShip newShip = new SOCShip(game.getPlayer(pn), coord, null);
            trackNewRoadOrShip(newShip, false);
            break;
        case SOCPlayingPiece.VILLAGE:
            // <--- Early return: Piece is part of board initial layout, not tracked player info ---
            return;
    }
    if (D.ebugOn) {
        SOCPlayerTracker.playerTrackersDebug(playerTrackers);
    }
    if (pn != ourPlayerNumber) {
        // <---- Not our piece ----
        return;
    }
    if (expectPUTPIECE_FROM_START1A && (pieceType == SOCPlayingPiece.SETTLEMENT) && (coord == ourPlayerData.getLastSettlementCoord())) {
        expectPUTPIECE_FROM_START1A = false;
        expectSTART1B = true;
    }
    if (expectPUTPIECE_FROM_START1B && ((pieceType == SOCPlayingPiece.ROAD) || (pieceType == SOCPlayingPiece.SHIP)) && (coord == ourPlayerData.getLastRoadCoord())) {
        expectPUTPIECE_FROM_START1B = false;
        expectSTART2A = true;
    }
    if (expectPUTPIECE_FROM_START2A && (pieceType == SOCPlayingPiece.SETTLEMENT) && (coord == ourPlayerData.getLastSettlementCoord())) {
        expectPUTPIECE_FROM_START2A = false;
        expectSTART2B = true;
    }
    if (expectPUTPIECE_FROM_START2B && ((pieceType == SOCPlayingPiece.ROAD) || (pieceType == SOCPlayingPiece.SHIP)) && (coord == ourPlayerData.getLastRoadCoord())) {
        expectPUTPIECE_FROM_START2B = false;
        if (!game.isGameOptionSet(SOCGameOption.K_SC_3IP))
            // wait for regular game play to start; other players might still place first
            expectROLL_OR_CARD = true;
        else
            expectSTART3A = true;
    }
    if (expectPUTPIECE_FROM_START3A && (pieceType == SOCPlayingPiece.SETTLEMENT) && (coord == ourPlayerData.getLastSettlementCoord())) {
        expectPUTPIECE_FROM_START3A = false;
        expectSTART3B = true;
    }
    if (expectPUTPIECE_FROM_START3B && ((pieceType == SOCPlayingPiece.ROAD) || (pieceType == SOCPlayingPiece.SHIP)) && (coord == ourPlayerData.getLastRoadCoord())) {
        expectPUTPIECE_FROM_START3B = false;
        expectROLL_OR_CARD = true;
    }
}
Also used : SOCSettlement(soc.game.SOCSettlement) SOCCity(soc.game.SOCCity) SOCShip(soc.game.SOCShip) SOCPlayer(soc.game.SOCPlayer) SOCRoad(soc.game.SOCRoad)

Example 17 with SOCPlayer

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

the class SOCRobotBrain method handleCANCELBUILDREQUEST.

/**
 * Handle a CANCELBUILDREQUEST for this game.
 *<P>
 *<b> During game startup</b> (START1B, START2B, or START3B): <BR>
 *    When sent from server to client, CANCELBUILDREQUEST means the current
 *    player wants to undo the placement of their initial settlement.
 *    This handler method calls {@link SOCGame#undoPutInitSettlement(SOCPlayingPiece)}
 *    and {@link SOCPlayerTracker#setPendingInitSettlement(SOCSettlement) tracker.setPendingInitSettlement(null)}.
 *<P>
 *<b> During piece placement</b> (PLACING_ROAD, PLACING_CITY, PLACING_SETTLEMENT,
 *                         PLACING_FREE_ROAD1, or PLACING_FREE_ROAD2): <BR>
 *    When sent from server to client, CANCELBUILDREQUEST means the player
 *    has sent an illegal PUTPIECE (bad building location).
 *    Humans can probably decide a better place to put their road,
 *    but robots must cancel the build request and decide on a new plan.
 *
 * @since 1.1.08
 */
private void handleCANCELBUILDREQUEST(SOCCancelBuildRequest mes) {
    final int gstate = game.getGameState();
    switch(gstate) {
        case SOCGame.START1A:
        case SOCGame.START2A:
        case SOCGame.START3A:
            if (ourTurn) {
                cancelWrongPiecePlacement(mes);
            }
            break;
        case SOCGame.START1B:
        case SOCGame.START2B:
        case SOCGame.START3B:
            if (ourTurn) {
                cancelWrongPiecePlacement(mes);
            } else {
                // 
                // Human player placed, then cancelled placement
                // (assume mes.getPieceType() == SOCPlayingPiece.SETTLEMENT).
                // Our robot wouldn't do that, and if it's ourTurn,
                // the cancel happens only if we try an illegal placement.
                // 
                final int pnum = game.getCurrentPlayerNumber();
                SOCPlayer pl = game.getPlayer(pnum);
                SOCSettlement pp = new SOCSettlement(pl, pl.getLastSettlementCoord(), null);
                game.undoPutInitSettlement(pp);
                // 
                // "forget" to track this cancelled initial settlement.
                // Wait for human player to place a new one.
                // 
                SOCPlayerTracker tr = playerTrackers.get(Integer.valueOf(pnum));
                tr.setPendingInitSettlement(null);
            }
            break;
        // asked to build, hasn't given location yet -> resources
        case SOCGame.PLAY1:
        // has given location -> is bad location
        case SOCGame.PLACING_ROAD:
        case SOCGame.PLACING_SETTLEMENT:
        case SOCGame.PLACING_CITY:
        case SOCGame.PLACING_SHIP:
        // JM TODO how to break out?
        case SOCGame.PLACING_FREE_ROAD1:
        // JM TODO how to break out?
        case SOCGame.PLACING_FREE_ROAD2:
        case SOCGame.SPECIAL_BUILDING:
            // 
            // We've asked for an illegal piece placement.
            // (Must be a bug.) Cancel and invalidate this
            // planned piece, make a new plan.
            // 
            // Can also happen in special building, if another
            // player has placed since we requested special building.
            // If our PUTPIECE request is denied, server sends us
            // CANCELBUILDREQUEST.  We need to ask to cancel the
            // placement, and also set variables to end our SBP turn.
            // 
            cancelWrongPiecePlacement(mes);
            break;
        default:
            if (game.isSpecialBuilding()) {
                cancelWrongPiecePlacement(mes);
            } else {
                // Should not occur
                System.err.println("L2521 SOCRobotBrain: " + client.getNickname() + ": Unhandled CANCELBUILDREQUEST at state " + gstate);
            }
    }
// switch (gameState)
}
Also used : SOCSettlement(soc.game.SOCSettlement) SOCPlayer(soc.game.SOCPlayer)

Example 18 with SOCPlayer

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

the class SOCRobotClient method treat.

/**
 * Treat the incoming messages.
 * Messages of unknown type are ignored. All {@link SOCGameServerText} are ignored.
 * ({@code mes} will be null from {@link SOCMessage#toMsg(String)}).
 *<P>
 *<B>Note:</B> Currently, does not call {@link SOCDisplaylessPlayerClient#treat(SOCMessage)}.
 * New message types should be added to both methods if both displayless and robot should handle them.
 * The robot treat's switch case can call super.treat before or after any robot-specific handling.
 *
 * @param mes    the message
 */
@Override
public void treat(SOCMessage mes) {
    if (mes == null)
        // Message syntax error or unknown type
        return;
    // Using debugRandomPause?
    if (debugRandomPause && (!robotBrains.isEmpty()) && (mes instanceof SOCMessageForGame) && !(mes instanceof SOCGameTextMsg) && !(mes instanceof SOCGameServerText) && !(mes instanceof SOCTurn)) {
        final String ga = ((SOCMessageForGame) mes).getGame();
        if (ga != null) {
            SOCRobotBrain brain = robotBrains.get(ga);
            if (brain != null) {
                if (!debugRandomPauseActive) {
                    // random chance of doing so
                    if ((Math.random() < DEBUGRANDOMPAUSE_FREQ) && ((debugRandomPauseQueue == null) || (debugRandomPauseQueue.isEmpty()))) {
                        SOCGame gm = games.get(ga);
                        final int cpn = gm.getCurrentPlayerNumber();
                        SOCPlayer rpl = gm.getPlayer(nickname);
                        if ((rpl != null) && (cpn == rpl.getPlayerNumber()) && (gm.getGameState() >= SOCGame.ROLL_OR_CARD)) {
                            // we're current player, pause us
                            debugRandomPauseActive = true;
                            debugRandomPauseUntil = System.currentTimeMillis() + (1000L * DEBUGRANDOMPAUSE_SECONDS);
                            if (debugRandomPauseQueue == null)
                                debugRandomPauseQueue = new Vector<SOCMessage>();
                            System.err.println("L379 -> do random pause: " + nickname);
                            sendText(gm, "debugRandomPauseActive for " + DEBUGRANDOMPAUSE_SECONDS + " seconds");
                        }
                    }
                }
            }
        }
    }
    if (debugRandomPause && debugRandomPauseActive) {
        if ((System.currentTimeMillis() < debugRandomPauseUntil) && !(mes instanceof SOCTurn)) {
            // time hasn't arrived yet, and still our turn:
            // Add message to queue (even non-game and SOCGameTextMsg)
            debugRandomPauseQueue.addElement(mes);
            // <--- Early return: debugRandomPauseActive ---
            return;
        }
        // time to resume the queue
        debugRandomPauseActive = false;
        while (!debugRandomPauseQueue.isEmpty()) {
            // calling ourself is safe, because
            // ! queue.isEmpty; thus won't decide
            // to set debugRandomPauseActive=true again.
            treat(debugRandomPauseQueue.firstElement());
            debugRandomPauseQueue.removeElementAt(0);
        }
    // Don't return from this method yet,
    // we still need to process mes.
    }
    if ((debugTraffic || D.ebugIsEnabled()) && !((mes instanceof SOCServerPing) && (nextServerPingExpectedAt != 0) && (Math.abs(System.currentTimeMillis() - nextServerPingExpectedAt) <= 66000))) // within 66 seconds of the expected time; see displaylesscli.handleSERVERPING
    {
        soc.debug.D.ebugPrintln("IN - " + nickname + " - " + mes);
    }
    try {
        switch(mes.getType()) {
            /**
             * status message
             */
            case SOCMessage.STATUSMESSAGE:
                handleSTATUSMESSAGE((SOCStatusMessage) mes);
                break;
            /**
             * admin ping
             */
            case SOCMessage.ADMINPING:
                handleADMINPING((SOCAdminPing) mes);
                break;
            /**
             * admin reset
             */
            case SOCMessage.ADMINRESET:
                handleADMINRESET((SOCAdminReset) mes);
                break;
            /**
             * update the current robot parameters
             */
            case SOCMessage.UPDATEROBOTPARAMS:
                handleUPDATEROBOTPARAMS((SOCUpdateRobotParams) mes);
                break;
            /**
             * join game authorization
             */
            case SOCMessage.JOINGAMEAUTH:
                handleJOINGAMEAUTH((SOCJoinGameAuth) mes, (sLocal != null));
                break;
            /**
             * game has been destroyed
             */
            case SOCMessage.DELETEGAME:
                handleDELETEGAME((SOCDeleteGame) mes);
                break;
            /**
             * list of game members
             */
            case SOCMessage.GAMEMEMBERS:
                handleGAMEMEMBERS((SOCGameMembers) mes);
                break;
            /**
             * game text message (bot debug commands)
             */
            case SOCMessage.GAMETEXTMSG:
                handleGAMETEXTMSG((SOCGameTextMsg) mes);
                break;
            /**
             * someone is sitting down
             */
            case SOCMessage.SITDOWN:
                handleSITDOWN((SOCSitDown) mes);
                break;
            /**
             * update the state of the game
             */
            case SOCMessage.GAMESTATE:
                handleGAMESTATE((SOCGameState) mes);
                break;
            /**
             * a player built something
             */
            case SOCMessage.PUTPIECE:
                handlePUTPIECE((SOCPutPiece) mes);
                break;
            /**
             * the server is requesting that we join a game
             */
            case SOCMessage.BOTJOINGAMEREQUEST:
                handleBOTJOINGAMEREQUEST((SOCBotJoinGameRequest) mes);
                break;
            /**
             * message that means the server wants us to leave the game
             */
            case SOCMessage.ROBOTDISMISS:
                handleROBOTDISMISS((SOCRobotDismiss) mes);
                break;
            /**
             * handle board reset (new game with same players, same game name, new layout).
             */
            case SOCMessage.RESETBOARDAUTH:
                handleRESETBOARDAUTH((SOCResetBoardAuth) mes);
                break;
            /**
             * generic "simple request" responses or announcements from the server.
             * Message type added 2013-02-17 for v1.1.18,
             * bot ignored these until 2015-10-10 for v2.0.00 SC_PIRI
             * and for PROMPT_PICK_RESOURCES from gold hex.
             */
            case SOCMessage.SIMPLEREQUEST:
                super.handleSIMPLEREQUEST(games, (SOCSimpleRequest) mes);
                handlePutBrainQ((SOCSimpleRequest) mes);
                break;
            /**
             * generic "simple action" announcements from the server.
             * Added 2013-09-04 for v1.1.19.
             */
            case SOCMessage.SIMPLEACTION:
                super.handleSIMPLEACTION(games, (SOCSimpleAction) mes);
                handlePutBrainQ((SOCSimpleAction) mes);
                break;
            /**
             * a special inventory item action: either add or remove,
             * or we cannot play our requested item.
             * Added 2013-11-26 for v2.0.00.
             */
            case SOCMessage.INVENTORYITEMACTION:
                {
                    final boolean isReject = super.handleINVENTORYITEMACTION(games, (SOCInventoryItemAction) mes);
                    if (isReject)
                        handlePutBrainQ((SOCInventoryItemAction) mes);
                }
                break;
            /**
             * Special Item change announcements.
             * Added 2014-04-16 for v2.0.00.
             */
            case SOCMessage.SETSPECIALITEM:
                super.handleSETSPECIALITEM(games, (SOCSetSpecialItem) mes);
                handlePutBrainQ((SOCSetSpecialItem) mes);
                break;
            case SOCMessage.ACCEPTOFFER:
            // current player has cancelled an initial settlement
            case SOCMessage.CANCELBUILDREQUEST:
            // server wants our player to choose to rob cloth or rob resources from victim
            case SOCMessage.CHOOSEPLAYER:
            case SOCMessage.CHOOSEPLAYERREQUEST:
            case SOCMessage.CLEAROFFER:
            // either draw, play, or add to hand, or cannot play our requested dev card
            case SOCMessage.DEVCARDACTION:
            case SOCMessage.DICERESULT:
            case SOCMessage.DISCARDREQUEST:
            case SOCMessage.BANKTRADE:
            case SOCMessage.MAKEOFFER:
            // move a previously placed ship; will update game data and player trackers
            case SOCMessage.MOVEPIECE:
            case SOCMessage.MOVEROBBER:
            case SOCMessage.PLAYERELEMENT:
            // apply multiple PLAYERELEMENT updates; added 2017-12-10 for v2.0.00
            case SOCMessage.PLAYERELEMENTS:
            case SOCMessage.REJECTOFFER:
            case SOCMessage.RESOURCECOUNT:
            // added 2017-12-18 for v2.0.00 when gameState became a field of this message
            case SOCMessage.STARTGAME:
            // server's 1x/second timing ping
            case SOCMessage.TIMINGPING:
            case SOCMessage.TURN:
                handlePutBrainQ((SOCMessageForGame) mes);
                break;
            case SOCMessage.BCASTTEXTMSG:
            case SOCMessage.CHANGEFACE:
            case SOCMessage.CHANNELMEMBERS:
            // If bot ever uses CHANNELS, update SOCChannels class javadoc
            case SOCMessage.CHANNELS:
            case SOCMessage.CHANNELTEXTMSG:
            case SOCMessage.DELETECHANNEL:
            case SOCMessage.GAMES:
            // SOCGameServerText contents are ignored by bots
            case SOCMessage.GAMESERVERTEXT:
            // (but not SOCGameTextMsg, which is used solely for debug commands)
            case SOCMessage.GAMESTATS:
            case SOCMessage.JOINCHANNEL:
            case SOCMessage.JOINCHANNELAUTH:
            case SOCMessage.LEAVECHANNEL:
            case SOCMessage.NEWCHANNEL:
            case SOCMessage.NEWGAME:
            case SOCMessage.SETSEATLOCK:
                // ignore this message type
                break;
            /**
             * Call SOCDisplaylessClient.treat for all other message types.
             * For types relevant to robots, it will update data from the message contents.
             * Other message types will be ignored.
             */
            default:
                super.treat(mes, true);
        }
    } catch (Throwable e) {
        System.err.println("SOCRobotClient treat ERROR - " + e + " " + e.getMessage());
        e.printStackTrace();
        while (e.getCause() != null) {
            e = e.getCause();
            System.err.println(" -> nested: " + e.getClass());
            e.printStackTrace();
        }
        System.err.println("-- end stacktrace --");
        System.out.println("  For message: " + mes);
    }
}
Also used : SOCPlayer(soc.game.SOCPlayer) SOCGame(soc.game.SOCGame) Vector(java.util.Vector)

Example 19 with SOCPlayer

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

the class SOCBoardAtServer method startGame_putInitPieces.

/**
 * For scenario game option {@link SOCGameOption#K_SC_PIRI _SC_PIRI},
 * place each player's initial pieces.  For {@link SOCGameOption#K_SC_FTRI _SC_FTRI},
 * set aside some dev cards to be claimed later at Special Edges.
 * Otherwise do nothing.
 *<P>
 * For {@code _SC_PIRI}, also calls each player's {@link SOCPlayer#addLegalSettlement(int, boolean)}
 * for their Lone Settlement location (adds layout part "LS").
 * Vacant player numbers get 0 for their {@code "LS"} element.
 *<P>
 * Called only at server. For a method called during game start
 * at server and clients, see {@link SOCGame#updateAtBoardLayout()}.
 *<P>
 * Called from {@link SOCGameHandler#startGame(SOCGame)} for those
 * scenario game options; if you need it called for your game, add
 * a check there for your scenario's {@link SOCGameOption}.
 *<P>
 * This is called after {@link #makeNewBoard(Map)} and before
 * {@link SOCGameHandler#getBoardLayoutMessage}.  So if needed,
 * it can call {@link SOCBoardLarge#setAddedLayoutPart(String, int[])}.
 *<P>
 * If ship placement is restricted by the scenario, please call each player's
 * {@link SOCPlayer#setRestrictedLegalShips(int[])} before calling this method,
 * so the legal and potential arrays will be initialized.
 *
 * @see #getLegalSeaEdges(SOCGame, int)
 */
public void startGame_putInitPieces(SOCGame ga) {
    if (ga.isGameOptionSet(SOCGameOption.K_SC_FTRI)) {
        // Set aside dev cards for players to be given when reaching "CE" Special Edges.
        final int cpn = ga.getCurrentPlayerNumber();
        // to call buyDevCard without giving it to a player
        ga.setCurrentPlayerNumber(-1);
        drawStack = new Stack<Integer>();
        final int n = FOR_TRI_DEV_CARD_EDGES[(ga.maxPlayers > 4) ? 1 : 0].length;
        for (int i = 0; i < n; ++i) drawStack.push(ga.buyDevCard());
        ga.setCurrentPlayerNumber(cpn);
        return;
    }
    if (!ga.isGameOptionSet(SOCGameOption.K_SC_PIRI))
        return;
    final int gstate = ga.getGameState();
    // prevent ga.putPiece from advancing turn
    ga.setGameState(SOCGame.READY);
    final int[] inits = PIR_ISL_INIT_PIECES[(ga.maxPlayers > 4) ? 1 : 0];
    // lone possible-settlement node on the way to the island.
    int[] possiLoneSettles = new int[ga.maxPlayers];
    // vacant players will get 0 here, will not get free settlement, ship, or pirate fortress.
    // iterate i only when player present, to avoid spacing gaps from vacant players
    int i = 0;
    for (int pn = 0; pn < ga.maxPlayers; ++pn) {
        if (ga.isSeatVacant(pn))
            continue;
        SOCPlayer pl = ga.getPlayer(pn);
        ga.putPiece(new SOCSettlement(pl, inits[i], this));
        ++i;
        ga.putPiece(new SOCShip(pl, inits[i], this));
        ++i;
        ga.putPiece(new SOCFortress(pl, inits[i], this));
        ++i;
        possiLoneSettles[pn] = inits[i];
        ga.getPlayer(pn).addLegalSettlement(inits[i], false);
        ++i;
    }
    setAddedLayoutPart("LS", possiLoneSettles);
    ga.setGameState(gstate);
}
Also used : SOCSettlement(soc.game.SOCSettlement) SOCShip(soc.game.SOCShip) SOCPlayer(soc.game.SOCPlayer) SOCFortress(soc.game.SOCFortress)

Example 20 with SOCPlayer

use of soc.game.SOCPlayer 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)

Aggregations

SOCPlayer (soc.game.SOCPlayer)61 SOCGame (soc.game.SOCGame)17 SOCShip (soc.game.SOCShip)12 SOCSettlement (soc.game.SOCSettlement)11 SOCRoad (soc.game.SOCRoad)9 SOCResourceSet (soc.game.SOCResourceSet)8 SOCCity (soc.game.SOCCity)7 SOCBoardLarge (soc.game.SOCBoardLarge)6 SOCFortress (soc.game.SOCFortress)5 ArrayList (java.util.ArrayList)4 SOCBoard (soc.game.SOCBoard)4 Connection (soc.server.genericServer.Connection)4 SOCInventoryItem (soc.game.SOCInventoryItem)3 SOCVillage (soc.game.SOCVillage)3 SQLException (java.sql.SQLException)2 Iterator (java.util.Iterator)2 Stack (java.util.Stack)2 SOCLRPathData (soc.game.SOCLRPathData)2 SOCPlayingPiece (soc.game.SOCPlayingPiece)2 SOCSpecialItem (soc.game.SOCSpecialItem)2