Search in sources :

Example 1 with SOCPlayingPiece

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

the class SOCGameMessageHandler method handlePUTPIECE.

/**
 * handle "put piece" message.
 *<P>
 * Because the current player changes during initial placement,
 * this method has a simplified version of some of the logic from
 * {@link SOCGameHandler#endGameTurn(SOCGame, SOCPlayer, boolean)}
 * to detect and announce the new turn.
 *
 * @param c  the connection that sent the message
 * @param mes  the message
 * @since 1.0.0
 */
private void handlePUTPIECE(SOCGame ga, Connection c, SOCPutPiece mes) {
    ga.takeMonitor();
    try {
        final String gaName = ga.getName();
        final String plName = c.getData();
        SOCPlayer player = ga.getPlayer(plName);
        /**
         * make sure the player can do it
         */
        if (handler.checkTurn(c, ga)) {
            boolean sendDenyReply = false;
            /*
                   if (D.ebugOn) {
                   D.ebugPrintln("BEFORE");
                   for (int pn = 0; pn < SOCGame.MAXPLAYERS; pn++) {
                   SOCPlayer tmpPlayer = ga.getPlayer(pn);
                   D.ebugPrintln("Player # "+pn);
                   for (int i = 0x22; i < 0xCC; i++) {
                   if (tmpPlayer.isPotentialRoad(i))
                   D.ebugPrintln("### POTENTIAL ROAD AT "+Integer.toHexString(i));
                   }
                   }
                   }
                 */
            int gameState = ga.getGameState();
            final int coord = mes.getCoordinates();
            final int pieceType = mes.getPieceType();
            final int pn = player.getPlayerNumber();
            final boolean isBuyAndPut = (gameState == SOCGame.PLAY1) || (gameState == SOCGame.SPECIAL_BUILDING);
            if (isBuyAndPut) {
                if (!handleBUILDREQUEST(ga, player, c, pieceType, false)) {
                    // <--- Can't build right now ---
                    return;
                // will call ga.releaseMonitor() in finally-block before returning
                }
                // updated by handleBUILDREQUEST
                gameState = ga.getGameState();
            }
            switch(pieceType) {
                case SOCPlayingPiece.ROAD:
                    if ((gameState == SOCGame.START1B) || (gameState == SOCGame.START2B) || (gameState == SOCGame.START3B) || (gameState == SOCGame.PLACING_ROAD) || (gameState == SOCGame.PLACING_FREE_ROAD1) || (gameState == SOCGame.PLACING_FREE_ROAD2)) {
                        if (player.isPotentialRoad(coord) && (player.getNumPieces(SOCPlayingPiece.ROAD) >= 1)) {
                            final SOCRoad rd = new SOCRoad(player, coord, null);
                            // Changes game state and (if initial placement) player
                            ga.putPiece(rd);
                            // If placing this piece reveals a fog hex, putPiece will call srv.gameEvent
                            // which will send a SOCRevealFogHex message to the game.
                            /*
                               if (D.ebugOn) {
                               D.ebugPrintln("AFTER");
                               for (int pn = 0; pn < SOCGame.MAXPLAYERS; pn++) {
                               SOCPlayer tmpPlayer = ga.getPlayer(pn);
                               D.ebugPrintln("Player # "+pn);
                               for (int i = 0x22; i < 0xCC; i++) {
                               if (tmpPlayer.isPotentialRoad(i))
                               D.ebugPrintln("### POTENTIAL ROAD AT "+Integer.toHexString(i));
                               }
                               }
                               }
                             */
                            srv.gameList.takeMonitorForGame(gaName);
                            // "Joe built a road."
                            srv.messageToGameKeyed(ga, false, "action.built.road", plName);
                            srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, pn, SOCPlayingPiece.ROAD, coord));
                            if (!ga.pendingMessagesOut.isEmpty())
                                handler.sendGamePendingMessages(ga, false);
                            srv.gameList.releaseMonitorForGame(gaName);
                            // If needed, call sendTurn or send SOCRollDicePrompt
                            handler.sendTurnStateAtInitialPlacement(ga, player, c, gameState);
                            int newState = ga.getGameState();
                            if ((newState == SOCGame.STARTS_WAITING_FOR_PICK_GOLD_RESOURCE) || (newState == SOCGame.WAITING_FOR_PICK_GOLD_RESOURCE)) {
                                // gold hex revealed from fog (scenario SC_FOG)
                                handler.sendGameState_sendGoldPickAnnounceText(ga, gaName, c, null);
                            }
                        } else {
                            D.ebugPrintln("ILLEGAL ROAD: 0x" + Integer.toHexString(coord) + ": player " + pn);
                            if (player.isRobot() && D.ebugOn) {
                                D.ebugPrintln(" - pl.isPotentialRoad: " + player.isPotentialRoad(coord));
                                SOCPlayingPiece pp = ga.getBoard().roadAtEdge(coord);
                                D.ebugPrintln(" - roadAtEdge: " + ((pp != null) ? pp : "none"));
                            }
                            srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.there.road");
                            // "You can't build a road there."
                            sendDenyReply = true;
                        }
                    } else {
                        srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.now.road");
                    // "You can't build a road now."
                    }
                    break;
                case SOCPlayingPiece.SETTLEMENT:
                    if ((gameState == SOCGame.START1A) || (gameState == SOCGame.START2A) || (gameState == SOCGame.START3A) || (gameState == SOCGame.PLACING_SETTLEMENT)) {
                        if (player.canPlaceSettlement(coord) && (player.getNumPieces(SOCPlayingPiece.SETTLEMENT) >= 1)) {
                            final SOCSettlement se = new SOCSettlement(player, coord, null);
                            // Changes game state and (if initial placement) player
                            ga.putPiece(se);
                            srv.gameList.takeMonitorForGame(gaName);
                            // "Joe built a settlement."
                            srv.messageToGameKeyed(ga, false, "action.built.stlmt", plName);
                            srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, pn, SOCPlayingPiece.SETTLEMENT, coord));
                            if (!ga.pendingMessagesOut.isEmpty())
                                handler.sendGamePendingMessages(ga, false);
                            srv.gameList.releaseMonitorForGame(gaName);
                            // Check player and send new game state
                            if (!handler.checkTurn(c, ga))
                                // Announce new state and new current player
                                handler.sendTurn(ga, false);
                            else
                                handler.sendGameState(ga);
                            if (ga.hasSeaBoard && (ga.getGameState() == SOCGame.STARTS_WAITING_FOR_PICK_GOLD_RESOURCE)) {
                                // Prompt to pick from gold: send text and SOCSimpleRequest(PROMPT_PICK_RESOURCES)
                                handler.sendGameState_sendGoldPickAnnounceText(ga, gaName, c, null);
                            }
                        } else {
                            D.ebugPrintln("ILLEGAL SETTLEMENT: 0x" + Integer.toHexString(coord) + ": player " + pn);
                            if (player.isRobot() && D.ebugOn) {
                                D.ebugPrintln(" - pl.isPotentialSettlement: " + player.isPotentialSettlement(coord));
                                SOCPlayingPiece pp = ga.getBoard().settlementAtNode(coord);
                                D.ebugPrintln(" - settlementAtNode: " + ((pp != null) ? pp : "none"));
                            }
                            srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.there.stlmt");
                            // "You can't build a settlement there."
                            sendDenyReply = true;
                        }
                    } else {
                        srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.now.stlmt");
                    // "You can't build a settlement now."
                    }
                    break;
                case SOCPlayingPiece.CITY:
                    if (gameState == SOCGame.PLACING_CITY) {
                        if (player.isPotentialCity(coord) && (player.getNumPieces(SOCPlayingPiece.CITY) >= 1)) {
                            boolean houseRuleFirstCity = ga.isGameOptionSet("N7C") && !ga.hasBuiltCity();
                            if (houseRuleFirstCity && ga.isGameOptionSet("N7") && (ga.getRoundCount() < ga.getGameOptionIntValue("N7"))) {
                                // If "No 7s for first # rounds" is active, and this isn't its last round, 7s won't
                                // be rolled soon: Don't announce "Starting next turn, dice rolls of 7 may occur"
                                houseRuleFirstCity = false;
                            }
                            final SOCCity ci = new SOCCity(player, coord, null);
                            // changes game state and maybe player
                            ga.putPiece(ci);
                            srv.gameList.takeMonitorForGame(gaName);
                            // "Joe built a city."
                            srv.messageToGameKeyed(ga, false, "action.built.city", plName);
                            srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, pn, SOCPlayingPiece.CITY, coord));
                            if (!ga.pendingMessagesOut.isEmpty())
                                handler.sendGamePendingMessages(ga, false);
                            if (houseRuleFirstCity)
                                srv.messageToGameKeyed(ga, false, "action.built.nextturn.7.houserule");
                            // "Starting next turn, dice rolls of 7 may occur (house rule)."
                            srv.gameList.releaseMonitorForGame(gaName);
                            // Check player and send new game state
                            if (!handler.checkTurn(c, ga))
                                // Announce new state and new current player
                                handler.sendTurn(ga, false);
                            else
                                handler.sendGameState(ga);
                        } else {
                            D.ebugPrintln("ILLEGAL CITY: 0x" + Integer.toHexString(coord) + ": player " + pn);
                            if (player.isRobot() && D.ebugOn) {
                                D.ebugPrintln(" - pl.isPotentialCity: " + player.isPotentialCity(coord));
                                SOCPlayingPiece pp = ga.getBoard().settlementAtNode(coord);
                                D.ebugPrintln(" - city/settlementAtNode: " + ((pp != null) ? pp : "none"));
                            }
                            srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.there.city");
                            // "You can't build a city there."
                            sendDenyReply = true;
                        }
                    } else {
                        srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.now.city");
                    // "You can't build a city now."
                    }
                    break;
                case SOCPlayingPiece.SHIP:
                    if ((gameState == SOCGame.START1B) || (gameState == SOCGame.START2B) || (gameState == SOCGame.START3B) || (gameState == SOCGame.PLACING_SHIP) || (gameState == SOCGame.PLACING_FREE_ROAD1) || (gameState == SOCGame.PLACING_FREE_ROAD2)) {
                        // Place it if we can; canPlaceShip checks potentials and pirate ship location
                        if (ga.canPlaceShip(player, coord) && (player.getNumPieces(SOCPlayingPiece.SHIP) >= 1)) {
                            final SOCShip sh = new SOCShip(player, coord, null);
                            // Changes game state and (during initial placement) sometimes player
                            ga.putPiece(sh);
                            srv.gameList.takeMonitorForGame(gaName);
                            // "Joe built a ship."
                            srv.messageToGameKeyed(ga, false, "action.built.ship", plName);
                            srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, pn, SOCPlayingPiece.SHIP, coord));
                            if (!ga.pendingMessagesOut.isEmpty())
                                handler.sendGamePendingMessages(ga, false);
                            srv.gameList.releaseMonitorForGame(gaName);
                            // If needed, call sendTurn or send SOCRollDicePrompt
                            handler.sendTurnStateAtInitialPlacement(ga, player, c, gameState);
                            int newState = ga.getGameState();
                            if ((newState == SOCGame.STARTS_WAITING_FOR_PICK_GOLD_RESOURCE) || (newState == SOCGame.WAITING_FOR_PICK_GOLD_RESOURCE)) {
                                // gold hex revealed from fog (scenario SC_FOG)
                                handler.sendGameState_sendGoldPickAnnounceText(ga, gaName, c, null);
                            }
                        } else {
                            D.ebugPrintln("ILLEGAL SHIP: 0x" + Integer.toHexString(coord) + ": player " + pn);
                            if (player.isRobot() && D.ebugOn) {
                                D.ebugPrintln(" - pl.isPotentialShip: " + player.isPotentialShip(coord));
                                SOCPlayingPiece pp = ga.getBoard().roadAtEdge(coord);
                                D.ebugPrintln(" - ship/roadAtEdge: " + ((pp != null) ? pp : "none"));
                            }
                            srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.there.ship");
                            // "You can't build a ship there."
                            sendDenyReply = true;
                        }
                    } else {
                        srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.now.ship");
                    // "You can't build a ship now."
                    }
                    break;
            }
            if (sendDenyReply) {
                if (isBuyAndPut)
                    // is probably now PLACING_*, was PLAY1 or SPECIAL_BUILDING
                    handler.sendGameState(ga);
                srv.messageToPlayer(c, new SOCCancelBuildRequest(gaName, mes.getPieceType()));
                if (player.isRobot()) {
                    // Set the "force end turn soon" field
                    ga.lastActionTime = 0L;
                }
            }
        } else {
            // "It's not your turn."
            srv.messageToPlayerKeyed(c, gaName, "reply.not.your.turn");
        }
    } catch (Exception e) {
        D.ebugPrintStackTrace(e, "Exception caught in handlePUTPIECE");
    } finally {
        ga.releaseMonitor();
    }
}
Also used : SOCSettlement(soc.game.SOCSettlement) SOCCity(soc.game.SOCCity) SOCPlayingPiece(soc.game.SOCPlayingPiece) SOCShip(soc.game.SOCShip) SOCPlayer(soc.game.SOCPlayer) SOCRoad(soc.game.SOCRoad)

Example 2 with SOCPlayingPiece

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

the class SOCRobotBrain method cancelWrongPiecePlacement.

/**
 *  We've asked for an illegal piece placement.
 *  Cancel and invalidate this planned piece, make a new plan.
 *  If {@link SOCGame#isSpecialBuilding()}, will set variables to
 *  force the end of our special building turn.
 *  Also handles illegal requests to buy development cards
 *  (piece type -2 in {@link SOCCancelBuildRequest}).
 *<P>
 *  Must update game data by calling {@link SOCGame#setGameState(int)} before calling this method.
 *<P>
 *  This method increments {@link #failedBuildingAttempts},
 *  but won't leave the game if we've failed too many times.
 *  The brain's run loop should make that decision.
 *<UL>
 * <LI> If {@link SOCGame#getGameState()} is {@link SOCGame#PLAY1},
 *   server likely denied us due to resources, not due to building plan
 *   being interrupted by another player's building before our special building phase.
 *   (Could also be due to a bug in the chosen building plan.)
 *   Will clear our building plan so we'll make a new one.
 * <LI> In other gamestates, assumes requested piece placement location was illegal.
 *   Will call {@link #cancelWrongPiecePlacementLocal(SOCPlayingPiece)}
 *   so we don't try again to build there.
 * <LI> Either way, sends a {@link CancelBuildRequest} message to the server.
 *</UL>
 *
 * @param mes  Cancel message from server, including piece type
 */
protected void cancelWrongPiecePlacement(SOCCancelBuildRequest mes) {
    // == -2
    final boolean cancelBuyDevCard = (mes.getPieceType() == SOCPossiblePiece.CARD);
    if (cancelBuyDevCard) {
        waitingForDevCard = false;
    } else {
        whatWeFailedToBuild = whatWeWantToBuild;
        ++failedBuildingAttempts;
    }
    waitingForGameState = false;
    final int gameState = game.getGameState();
    /**
     * if true, server likely denied us due to resources, not due to building plan
     * being interrupted by another player's building before our special building phase.
     * (Could also be due to a bug in the chosen building plan.)
     */
    final boolean gameStateIsPLAY1 = (gameState == SOCGame.PLAY1);
    if (!(gameStateIsPLAY1 || cancelBuyDevCard)) {
        int coord = -1;
        switch(gameState) {
            case SOCGame.START1A:
            case SOCGame.START1B:
            case SOCGame.START2A:
            case SOCGame.START2B:
            case SOCGame.START3A:
            case SOCGame.START3B:
                coord = lastStartingPieceCoord;
                break;
            default:
                if (whatWeWantToBuild != null)
                    coord = whatWeWantToBuild.getCoordinates();
        }
        if (coord != -1) {
            SOCPlayingPiece cancelPiece;
            /**
             * First, invalidate that piece in trackers, so we don't try again to
             * build it. If we treat it like another player's new placement, we
             * can remove any of our planned pieces depending on this one.
             */
            switch(mes.getPieceType()) {
                case SOCPlayingPiece.ROAD:
                    cancelPiece = new SOCRoad(dummyCancelPlayerData, coord, null);
                    break;
                case SOCPlayingPiece.SETTLEMENT:
                    cancelPiece = new SOCSettlement(dummyCancelPlayerData, coord, null);
                    break;
                case SOCPlayingPiece.CITY:
                    cancelPiece = new SOCCity(dummyCancelPlayerData, coord, null);
                    break;
                case SOCPlayingPiece.SHIP:
                    cancelPiece = new SOCShip(dummyCancelPlayerData, coord, null);
                    break;
                default:
                    // To satisfy javac
                    cancelPiece = null;
            }
            cancelWrongPiecePlacementLocal(cancelPiece);
        }
    } else {
        /**
         *  stop trying to build it now, but don't prevent
         *  us from trying later to build it.
         */
        whatWeWantToBuild = null;
        buildingPlan.clear();
    }
    if (gameStateIsPLAY1 || game.isSpecialBuilding()) {
        // Shouldn't have asked to build this piece at this time.
        // End our confusion by ending our current turn. Can re-plan on next turn.
        failedBuildingAttempts = MAX_DENIED_BUILDING_PER_TURN;
        expectPLACING_ROAD = false;
        expectPLACING_SETTLEMENT = false;
        expectPLACING_CITY = false;
        expectPLACING_SHIP = false;
        decidedIfSpecialBuild = true;
        if (!cancelBuyDevCard) {
            // special building, currently in state PLACING_* ;
            // get our resources back, get state PLAY1 or SPECIALBUILD
            waitingForGameState = true;
            expectPLAY1 = true;
            client.cancelBuildRequest(game, mes.getPieceType());
        }
    } else if (gameState <= SOCGame.START3B) {
        switch(gameState) {
            case SOCGame.START1A:
                expectPUTPIECE_FROM_START1A = false;
                expectSTART1A = true;
                break;
            case SOCGame.START1B:
                expectPUTPIECE_FROM_START1B = false;
                expectSTART1B = true;
                break;
            case SOCGame.START2A:
                expectPUTPIECE_FROM_START2A = false;
                expectSTART2A = true;
                break;
            case SOCGame.START2B:
                expectPUTPIECE_FROM_START2B = false;
                expectSTART2B = true;
                break;
            case SOCGame.START3A:
                expectPUTPIECE_FROM_START3A = false;
                expectSTART3A = true;
                break;
            case SOCGame.START3B:
                expectPUTPIECE_FROM_START3B = false;
                expectSTART3B = true;
                break;
        }
    // The run loop will check if failedBuildingAttempts > (2 * MAX_DENIED_BUILDING_PER_TURN).
    // This bot will leave the game there if it can't recover.
    } else {
        expectPLAY1 = true;
        waitingForGameState = true;
        counter = 0;
        client.cancelBuildRequest(game, mes.getPieceType());
    // Now wait for the play1 message, then can re-plan another piece.
    }
}
Also used : SOCSettlement(soc.game.SOCSettlement) SOCCity(soc.game.SOCCity) SOCPlayingPiece(soc.game.SOCPlayingPiece) SOCShip(soc.game.SOCShip) SOCRoad(soc.game.SOCRoad)

Example 3 with SOCPlayingPiece

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

the class SOCRobotDM method recalcLongestRoadETAAux.

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

Example 4 with SOCPlayingPiece

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

the class SOCPlayerInterface method updateAtPutPiece.

/**
 * Handle updates after putting a piece on the board,
 * or moving a ship that was already placed.
 * Place or move the piece within our {@link SOCGame}
 * and visually on our {@link SOCBoardPanel}.
 *
 * @param mesPn  The piece's player number
 * @param coord  The piece's coordinate.  If <tt>isMove</tt>, the coordinate to move <em>from</em>.
 * @param pieceType  Piece type, like {@link SOCPlayingPiece#CITY}
 * @param isMove   If true, it's a move, not a new placement; valid only for ships.
 * @param moveToCoord  If <tt>isMove</tt>, the coordinate to move <em>to</em>.  Otherwise ignored.
 *
 * @see #updateAtPiecesChanged()
 * @since 2.0.00
 */
public void updateAtPutPiece(final int mesPn, final int coord, final int pieceType, final boolean isMove, final int moveToCoord) {
    // TODO consider more effic way for flushBoardLayoutAndRepaint, without the =null
    final SOCPlayer pl = (pieceType != SOCPlayingPiece.VILLAGE) ? game.getPlayer(mesPn) : null;
    final SOCPlayer oldLongestRoadPlayer = game.getPlayerWithLongestRoad();
    final SOCHandPanel mesHp = (pieceType != SOCPlayingPiece.VILLAGE) ? getPlayerHandPanel(mesPn) : null;
    final boolean[] debugShowPotentials = boardPanel.debugShowPotentials;
    final SOCPlayingPiece pp;
    switch(pieceType) {
        case SOCPlayingPiece.ROAD:
            pp = new SOCRoad(pl, coord, null);
            game.putPiece(pp);
            mesHp.updateValue(PlayerClientListener.UpdateType.Road);
            if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7])
                boardPanel.flushBoardLayoutAndRepaint();
            break;
        case SOCPlayingPiece.SETTLEMENT:
            pp = new SOCSettlement(pl, coord, null);
            game.putPiece(pp);
            mesHp.updateValue(PlayerClientListener.UpdateType.Settlement);
            /**
             * if this is the second initial settlement, then update the resource display
             */
            mesHp.updateValue(PlayerClientListener.UpdateType.ResourceTotalAndDetails);
            if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7] || debugShowPotentials[6])
                boardPanel.flushBoardLayoutAndRepaint();
            break;
        case SOCPlayingPiece.CITY:
            pp = new SOCCity(pl, coord, null);
            game.putPiece(pp);
            mesHp.updateValue(PlayerClientListener.UpdateType.Settlement);
            mesHp.updateValue(PlayerClientListener.UpdateType.City);
            if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7] || debugShowPotentials[6])
                boardPanel.flushBoardLayoutAndRepaint();
            break;
        case SOCPlayingPiece.SHIP:
            pp = new SOCShip(pl, coord, null);
            if (!isMove) {
                game.putPiece(pp);
                mesHp.updateValue(PlayerClientListener.UpdateType.Ship);
            } else {
                game.moveShip((SOCShip) pp, moveToCoord);
                if (mesHp == clientHand)
                    // just in case; it probably wasn't enabled
                    mesHp.disableBankUndoButton();
            }
            if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7])
                boardPanel.flushBoardLayoutAndRepaint();
            break;
        case SOCPlayingPiece.VILLAGE:
            // no need to refresh boardPanel after receiving each village
            pp = new SOCVillage(coord, game.getBoard());
            game.putPiece(pp);
            // <--- Early return: Piece is part of board initial layout, not player info ---
            return;
        case SOCPlayingPiece.FORTRESS:
            pp = new SOCFortress(pl, coord, game.getBoard());
            game.putPiece(pp);
            // <--- Early return: Piece is part of board initial layout, not added during game ---
            return;
        default:
            chatPrintDebug("* Unknown piece type " + pieceType + " at coord 0x" + Integer.toHexString(coord));
            // <--- Early return ---
            return;
    }
    mesHp.updateValue(PlayerClientListener.UpdateType.VictoryPoints);
    boardPanel.repaint();
    buildingPanel.updateButtonStatus();
    if (game.isDebugFreePlacement() && game.isInitialPlacement())
        // update here, since gamestate doesn't change to trigger update
        boardPanel.updateMode();
    if (hasCalledBegan && (game.getGameState() >= SOCGame.START1A))
        playSound(SOUND_PUT_PIECE);
    /**
     * Check for and announce change in longest road; update all players' victory points.
     */
    SOCPlayer newLongestRoadPlayer = game.getPlayerWithLongestRoad();
    if (newLongestRoadPlayer != oldLongestRoadPlayer) {
        updateLongestLargest(true, oldLongestRoadPlayer, newLongestRoadPlayer);
    }
}
Also used : SOCSettlement(soc.game.SOCSettlement) SOCVillage(soc.game.SOCVillage) SOCCity(soc.game.SOCCity) SOCPlayingPiece(soc.game.SOCPlayingPiece) SOCShip(soc.game.SOCShip) SOCPlayer(soc.game.SOCPlayer) SOCFortress(soc.game.SOCFortress) SOCRoad(soc.game.SOCRoad)

Aggregations

SOCPlayingPiece (soc.game.SOCPlayingPiece)4 SOCCity (soc.game.SOCCity)3 SOCRoad (soc.game.SOCRoad)3 SOCSettlement (soc.game.SOCSettlement)3 SOCShip (soc.game.SOCShip)3 SOCPlayer (soc.game.SOCPlayer)2 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Stack (java.util.Stack)1 Vector (java.util.Vector)1 SOCBoard (soc.game.SOCBoard)1 SOCFortress (soc.game.SOCFortress)1 SOCLRPathData (soc.game.SOCLRPathData)1 SOCVillage (soc.game.SOCVillage)1 NodeLenVis (soc.util.NodeLenVis)1 Pair (soc.util.Pair)1