Search in sources :

Example 16 with SOCBoardLarge

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

the class SOCBoardPanel method mouseMoved.

/**
 * Based on the board's current {@link #mode}, update the hovering 'hilight' piece ({@link #hilight}).
 * Trigger a {@link #repaint()} if the mouse moved or the hilight changes.
 */
public void mouseMoved(MouseEvent e) {
    try {
        int x = e.getX();
        int y = e.getY();
        int xb, yb;
        // get (xb, yb) internal board-pixel coordinates from (x, y):
        if (isScaled) {
            xb = scaleFromActual(x - panelMarginX);
            yb = scaleFromActual(y - panelMarginY);
        } else {
            xb = x - panelMarginX;
            yb = y - panelMarginY;
        }
        if (isRotated) {
            // (ccw): P'=(y, panelMinBW-x)
            int xb1 = yb;
            // offset for similar reasons as -HEXHEIGHT in drawHex
            yb = panelMinBW - xb - HEXY_OFF_SLOPE_HEIGHT;
            xb = xb1;
        }
        int edgeNum;
        int nodeNum;
        int hexNum;
        switch(mode) {
            case PLACE_INIT_ROAD:
                /**
                 ** Code for finding an edge *******
                 */
                edgeNum = 0;
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    boolean isShip = false;
                    edgeNum = findEdge(xb, yb, true);
                    if (edgeNum < 0) {
                        edgeNum = -edgeNum;
                        if ((player != null) && game.canPlaceShip(player, edgeNum))
                            isShip = true;
                    } else {
                        // check potential roads, not ships, to keep it false if coastal edge
                        isShip = ((player != null) && !player.isPotentialRoad(edgeNum));
                    }
                    // It must be attached to the last settlement
                    if ((player == null) || (!(player.isPotentialRoad(edgeNum) || game.canPlaceShip(player, edgeNum))) || (!(game.isDebugFreePlacement() || board.isEdgeAdjacentToNode(initSettlementNode, (edgeNum != -1) ? edgeNum : 0)))) {
                        edgeNum = 0;
                    }
                    if ((hilight != edgeNum) || (hilightIsShip != isShip)) {
                        hilight = edgeNum;
                        hilightIsShip = isShip;
                        if (debugShowCoordsTooltip) {
                            // "" shows tip, null hides it.
                            String blank = (edgeNum != 0) ? "" : null;
                            // also repaints
                            hoverTip.setHoverText(blank, edgeNum, x, y);
                        } else {
                            repaint();
                        }
                    }
                }
                break;
            case PLACE_ROAD:
            case PLACE_FREE_ROAD_OR_SHIP:
            case MOVE_SHIP:
                /**
                 ** Code for finding an edge; see also PLACE_SHIP, SC_FTRI_PLACE_PORT *******
                 */
                edgeNum = 0;
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    edgeNum = findEdge(xb, yb, true);
                    final boolean hasShips = (player != null) && (player.getNumPieces(SOCPlayingPiece.SHIP) > 0);
                    final boolean canPlaceShip = hasShips && game.canPlaceShip(player, Math.abs(edgeNum));
                    if ((mode == PLACE_FREE_ROAD_OR_SHIP) && canPlaceShip && (edgeNum > 0) && (player.getNumPieces(SOCPlayingPiece.ROAD) == 0)) {
                        // If this edge is coastal, force ship (not road) if we
                        // have no roads remaining to freely place
                        edgeNum = -edgeNum;
                    }
                    boolean isShip;
                    if (edgeNum < 0) {
                        edgeNum = -edgeNum;
                        isShip = canPlaceShip || ((mode == PLACE_FREE_ROAD_OR_SHIP) && hasShips && player.isPotentialShip(edgeNum));
                    } else {
                        isShip = false;
                    }
                    if ((edgeNum != 0) && (player != null)) {
                        if (mode == MOVE_SHIP) {
                            isShip = true;
                            if (!player.isPotentialShipMoveTo(edgeNum, moveShip_fromEdge))
                                edgeNum = 0;
                            // Check edgeNum vs pirate hex:
                            final SOCBoardLarge bL = (SOCBoardLarge) board;
                            final int ph = bL.getPirateHex();
                            if ((ph != 0) && bL.isEdgeAdjacentToHex(edgeNum, ph))
                                edgeNum = 0;
                        } else {
                            if ((player.isPotentialRoad(edgeNum) && (player.getNumPieces(SOCPlayingPiece.ROAD) > 0)) || ((mode == PLACE_FREE_ROAD_OR_SHIP) && canPlaceShip)) {
                                if (!isShip) {
                                    // check potential roads, not ships, to keep it false if coastal edge
                                    isShip = (player != null) && canPlaceShip && !player.isPotentialRoad(edgeNum);
                                }
                            } else {
                                edgeNum = 0;
                            }
                        }
                    }
                    if ((hilight != edgeNum) || (hilightIsShip != isShip)) {
                        hilight = edgeNum;
                        hilightIsShip = isShip;
                        if (debugShowCoordsTooltip) {
                            // "" shows tip, null hides it.
                            String blank = (edgeNum != 0) ? "" : null;
                            // also repaints
                            hoverTip.setHoverText(blank, edgeNum, x, y);
                        } else {
                            repaint();
                        }
                    }
                }
                break;
            case PLACE_SETTLEMENT:
            case PLACE_INIT_SETTLEMENT:
                /**
                 ** Code for finding a node ********
                 */
                nodeNum = 0;
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    nodeNum = findNode(xb, yb);
                    if ((player == null) || !player.canPlaceSettlement(nodeNum)) {
                        nodeNum = 0;
                    }
                    if (hilight != nodeNum) {
                        hilight = nodeNum;
                        hilightIsShip = false;
                        if ((mode == PLACE_INIT_SETTLEMENT) && !debugShowCoordsTooltip)
                            hoverTip.handleHover(x, y, xb, yb);
                        else if (debugShowCoordsTooltip)
                            hoverTip.setHoverText(((nodeNum != 0) ? "" : null), nodeNum, x, y);
                        else
                            repaint();
                    } else if (mode == PLACE_INIT_SETTLEMENT) {
                        if (debugShowCoordsTooltip && (nodeNum != 0))
                            hoverTip.setHoverText("", nodeNum, x, y);
                        else
                            // Will call repaint() if needed
                            hoverTip.handleHover(x, y, xb, yb);
                    }
                }
                break;
            case PLACE_CITY:
                /**
                 ** Code for finding a node ********
                 */
                nodeNum = 0;
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    nodeNum = findNode(xb, yb);
                    if ((player == null) || !player.isPotentialCity(nodeNum)) {
                        nodeNum = 0;
                    }
                    if (hilight != nodeNum) {
                        hilight = nodeNum;
                        hilightIsShip = false;
                        if (debugShowCoordsTooltip) {
                            // "" shows tip, null hides it.
                            String blank = (nodeNum != 0) ? "" : null;
                            // also repaints
                            hoverTip.setHoverText(blank, nodeNum, x, y);
                        } else {
                            repaint();
                        }
                    }
                }
                break;
            case PLACE_SHIP:
                /**
                 ** Code for finding an edge; see also PLACE_ROAD *******
                 */
                edgeNum = 0;
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    edgeNum = findEdge(xb, yb, false);
                    if (edgeNum != 0) {
                        if ((player == null) || (player.getNumPieces(SOCPlayingPiece.SHIP) < 1) || !game.canPlaceShip(player, edgeNum))
                            edgeNum = 0;
                    }
                    if (hilight != edgeNum) {
                        hilight = edgeNum;
                        hilightIsShip = true;
                        if (debugShowCoordsTooltip) {
                            // "" shows tip, null hides it.
                            String blank = (edgeNum != 0) ? "" : null;
                            // also repaints
                            hoverTip.setHoverText(blank, edgeNum, x, y);
                        } else {
                            repaint();
                        }
                    }
                }
                break;
            case PLACE_ROBBER:
            case PLACE_PIRATE:
                /**
                 ** Code for finding a hex ********
                 */
                hexNum = 0;
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    hexNum = findHex(xb, yb);
                    final boolean canMove = (mode == PLACE_ROBBER) ? game.canMoveRobber(playerNumber, hexNum) : game.canMovePirate(playerNumber, hexNum);
                    if (!canMove) {
                        // Not a hex, or can't move to this hex (water, etc)
                        if (hexNum != 0) {
                            if ((board instanceof SOCBoardLarge) && ((SOCBoardLarge) board).isHexInLandAreas(hexNum, ((SOCBoardLarge) board).getRobberExcludedLandAreas())) {
                                hoverTip.setHoverText(strings.get("board.robber.not.here"), hexNum);
                            // "Cannot move the robber here."
                            } else {
                                // clear any previous
                                hoverTip.setHoverText(null, 0);
                            }
                            hexNum = 0;
                        }
                    }
                    if (hilight != hexNum) {
                        hilight = hexNum;
                        hilightIsShip = false;
                        hoverTip.handleHover(x, y, xb, yb);
                        repaint();
                    } else {
                        // calls repaint
                        hoverTip.positionToMouse(x, y);
                    }
                }
                break;
            case SC_FTRI_PLACE_PORT:
                /**
                 ** Code for finding an edge; see also PLACE_ROAD, PLACE_SHIP *******
                 */
                edgeNum = 0;
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    edgeNum = findEdge(xb, yb, false);
                }
                if (edgeNum != 0) {
                    final boolean edgeNeg1;
                    if (edgeNum == -1) {
                        edgeNum = 0;
                        edgeNeg1 = true;
                    } else {
                        edgeNeg1 = false;
                    }
                    if (!game.canPlacePort(player, edgeNum)) {
                        // not valid for placement
                        edgeNum = 0;
                    } else {
                        if (edgeNeg1)
                            edgeNum = -1;
                    }
                }
                if (edgeNum != hilight) {
                    hilight = edgeNum;
                    if (debugShowCoordsTooltip) {
                        // "" shows tip, null hides it.
                        String blank = (edgeNum != 0) ? "" : null;
                        // also repaints
                        hoverTip.setHoverText(blank, edgeNum, x, y);
                    } else {
                        repaint();
                    }
                }
                break;
            case CONSIDER_LM_SETTLEMENT:
            case CONSIDER_LT_SETTLEMENT:
                /**
                 ** Code for finding a node ********
                 */
                nodeNum = 0;
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    nodeNum = findNode(xb, yb);
                    // nodeNum = 0;
                    if (hilight != nodeNum) {
                        hilight = nodeNum;
                        hilightIsShip = false;
                        repaint();
                    }
                }
                break;
            case CONSIDER_LM_ROAD:
            case CONSIDER_LT_ROAD:
                /**
                 ** Code for finding an edge *******
                 */
                edgeNum = 0;
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    edgeNum = findEdge(xb, yb, false);
                    if (!otherPlayer.isPotentialRoad(edgeNum)) {
                        edgeNum = 0;
                    }
                    if (hilight != edgeNum) {
                        hilight = edgeNum;
                        hilightIsShip = false;
                        repaint();
                    }
                }
                break;
            case CONSIDER_LM_CITY:
            case CONSIDER_LT_CITY:
                /**
                 ** Code for finding a node ********
                 */
                nodeNum = 0;
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    nodeNum = findNode(xb, yb);
                    if (!otherPlayer.isPotentialCity(nodeNum)) {
                        nodeNum = 0;
                    }
                    if (hilight != nodeNum) {
                        hilight = nodeNum;
                        hilightIsShip = false;
                        repaint();
                    }
                }
                break;
            case NONE:
            case TURN_STARTING:
            case GAME_OVER:
                // see hover
                if ((ptrOldX != x) || (ptrOldY != y)) {
                    ptrOldX = x;
                    ptrOldY = y;
                    hoverTip.handleHover(x, y, xb, yb);
                }
                break;
            case GAME_FORMING:
                // No hover for forming
                break;
        }
    } catch (Throwable th) {
        playerInterface.chatPrintStackTrace(th);
    }
}
Also used : SOCBoardLarge(soc.game.SOCBoardLarge)

Example 17 with SOCBoardLarge

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

the class SOCPlayerTracker method recalcScenario_SC_PIRI_nextPotentialShip.

/**
 * For scenario {@code _SC_PIRI}, get the player's next potential ship towards their Fortress.
 * If fortress was already defeated, or they have no boats, returns {@code null}.
 *<P>
 * This is calculated every time, not cached, because potential-ships list may change often.
 * Calls {@link #updateScenario_SC_PIRI_closestShipToFortress(SOCShip, boolean)} if closest ship not known.
 *
 * @return Next potential ship, or {@code null}
 * @since 2.0.00
 */
SOCPossibleShip recalcScenario_SC_PIRI_nextPotentialShip() {
    // may be null towards end of game
    final SOCFortress fort = player.getFortress();
    if (fort == null)
        // <--- Early return: already defeated fortress ---
        return null;
    final int fortR = fort.getCoordinates() >> 8;
    if (scen_SC_PIRI_closestShipToFortress == null)
        updateScenario_SC_PIRI_closestShipToFortress(null, false);
    final SOCShip closest = scen_SC_PIRI_closestShipToFortress;
    if (closest == null)
        // <--- Early return: no ships ---
        return null;
    final List<Integer> closestAdjacs = ((SOCBoardLarge) game.getBoard()).getAdjacentEdgesToEdge(closest.getCoordinates());
    SOCPossibleShip nextShip = null;
    int nextR = -1, nextC = -1;
    for (Integer edge : closestAdjacs) {
        final SOCPossibleRoad rs = possibleRoads.get(edge);
        if ((rs == null) || !(rs instanceof SOCPossibleShip))
            continue;
        final int shipEdge = rs.getCoordinates();
        final int shipR = shipEdge >> 8, shipC = shipEdge & 0xFF;
        if ((nextShip == null) || (shipC < nextC) || ((shipC == nextC) && (Math.abs(shipR - fortR) < Math.abs(nextR - fortR)))) {
            nextShip = (SOCPossibleShip) rs;
            nextR = shipR;
            nextC = shipC;
        }
    }
    return nextShip;
}
Also used : SOCBoardLarge(soc.game.SOCBoardLarge) SOCShip(soc.game.SOCShip) SOCFortress(soc.game.SOCFortress)

Example 18 with SOCBoardLarge

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

the class SOCPlayerTracker method expandRoadOrShip.

/**
 * Expand a possible road or ship, to see what placements it makes possible.
 *<UL>
 *<LI> Creates {@code dummyRoad}: A copy of {@code targetRoad} owned by {@code dummy}
 *<LI> Calls {@link SOCPlayer#putPiece(SOCPlayingPiece, boolean) dummy.putPiece(dummyRoad, true)}
 *<LI> Adds to or updates {@link #possibleSettlements} at <tt>targetRoad</tt>'s nodes, if potential
 *<LI> If {@code level > 0}: Calls itself recursively to go more levels out from the current pieces,
 *   adding/updating {@link #possibleRoads} and {@link #possibleSettlements}
 *<LI> Calls {@link SOCPlayer#removePiece(SOCPlayingPiece, SOCPlayingPiece) dummy.removePiece(dummyRoad, null)}
 *</UL>
 *<P>
 * <b>Scenario {@code _SC_PIRI}</b>: Ships in this scenario never expand east (never away from the
 * pirate fortress). Scenario rules require the route to be as short as possible. Even if another (human)
 * player might want to do so, they couldn't interfere with the bot's own route, so we don't track
 * that possibility.
 *
 * @param targetRoad   the possible road
 * @param player    the player who owns the original road
 * @param dummy     the dummy player used to see what's legal; created by caller copying {@code player}
 * @param trackers  player trackers
 * @param level     how many levels (additional pieces) to expand;
 *                  0 to only check <tt>targetRoad</tt> for potential settlements
 *                  and not expand past it for new roads, ships, or further settlements.
 *                  If {@code level > 0} but {@code dummy} has no more roads or ships
 *                  (depending on {@link SOCPossibleRoad#isRoadNotShip() targetRoad.isRoadNotShip()}),
 *                  acts as if {@code level == 0}.
 */
public void expandRoadOrShip(final SOCPossibleRoad targetRoad, final SOCPlayer player, final SOCPlayer dummy, HashMap<Integer, SOCPlayerTracker> trackers, final int level) {
    // D.ebugPrintln("$$$ expandRoad at "+Integer.toHexString(targetRoad.getCoordinates())+" level="+level);
    final SOCBoard board = game.getBoard();
    final int tgtRoadEdge = targetRoad.getCoordinates();
    final boolean isRoadNotShip = targetRoad.isRoadNotShip();
    final SOCRoad dummyRoad;
    if (isRoadNotShip || ((targetRoad instanceof SOCPossibleShip) && ((SOCPossibleShip) targetRoad).isCoastalRoadAndShip))
        dummyRoad = new SOCRoad(dummy, tgtRoadEdge, board);
    else
        // TODO better handling for coastal roads/ships
        dummyRoad = new SOCShip(dummy, tgtRoadEdge, board);
    dummy.putPiece(dummyRoad, true);
    // 
    for (Integer adjNode : board.getAdjacentNodesToEdge(tgtRoadEdge)) {
        if (dummy.canPlaceSettlement(adjNode.intValue())) {
            // 
            // see if possible settlement is already in the list
            // 
            // D.ebugPrintln("$$$ seeing if "+Integer.toHexString(adjNode.intValue())+" is already in the list");
            SOCPossibleSettlement posSet = possibleSettlements.get(adjNode);
            if (posSet != null) {
                // 
                if (!(posSet.getNecessaryRoads().isEmpty() || posSet.getNecessaryRoads().contains(targetRoad))) {
                    // 
                    // add target road to settlement's nr list and this settlement to the road's np list
                    // 
                    // D.ebugPrintln("$$$ adding road "+Integer.toHexString(targetRoad.getCoordinates())+" to the settlement "+Integer.toHexString(posSet.getCoordinates()));
                    posSet.addNecessaryRoad(targetRoad);
                    targetRoad.addNewPossibility(posSet);
                    // 
                    if ((targetRoad.getNumberOfNecessaryRoads() + 1) < posSet.getNumberOfNecessaryRoads()) {
                        posSet.setNumberOfNecessaryRoads(targetRoad.getNumberOfNecessaryRoads() + 1);
                    }
                }
            } else {
                // 
                // else, add new possible settlement
                // 
                // D.ebugPrintln("$$$ adding new possible settlement at "+Integer.toHexString(adjNode.intValue()));
                List<SOCPossibleRoad> nr = new ArrayList<SOCPossibleRoad>();
                nr.add(targetRoad);
                SOCPossibleSettlement newPosSet = new SOCPossibleSettlement(player, adjNode.intValue(), nr);
                newPosSet.setNumberOfNecessaryRoads(targetRoad.getNumberOfNecessaryRoads() + 1);
                possibleSettlements.put(adjNode, newPosSet);
                targetRoad.addNewPossibility(newPosSet);
                updateSettlementConflicts(newPosSet, trackers);
            }
        }
    }
    if ((level > 0) && (0 < dummy.getNumPieces(isRoadNotShip ? SOCPlayingPiece.ROAD : SOCPlayingPiece.SHIP))) {
        // 
        // check for new possible roads or ships.
        // The above getNumPieces check ignores any possible ship <-> road transition at a coastal settlement.
        // 
        ArrayList<SOCPossibleRoad> newPossibleRoads = new ArrayList<SOCPossibleRoad>();
        ArrayList<SOCPossibleRoad> roadsToExpand = new ArrayList<SOCPossibleRoad>();
        // ships in _SC_PIRI never expand east
        final boolean isShipInSC_PIRI = (!isRoadNotShip) && game.isGameOptionSet(SOCGameOption.K_SC_PIRI);
        // D.ebugPrintln("$$$ checking roads adjacent to "+Integer.toHexString(targetRoad.getCoordinates()));
        // 
        // check adjacent edges to road or ship
        // 
        Enumeration<Integer> adjEdgesEnum = board.getAdjacentEdgesToEdge(tgtRoadEdge).elements();
        while (adjEdgesEnum.hasMoreElements()) {
            Integer adjEdge = adjEdgesEnum.nextElement();
            final int edge = adjEdge.intValue();
            if (isShipInSC_PIRI) {
                final int tgtEdgeCol = tgtRoadEdge & 0xFF, adjEdgeCol = edge & 0xFF;
                if (// adjacent goes north/south from eastern node of diagonal target edge
                (adjEdgeCol > tgtEdgeCol) || ((adjEdgeCol == tgtEdgeCol) && ((tgtRoadEdge & 0x100) != 0))) // adjacent goes northeast/southeast from vertical target edge (tgtRoadEdge is on odd row)
                {
                    // <--- Ignore this eastern adjacent edge ---
                    continue;
                }
            }
            // D.ebugPrintln("$$$ edge "+Integer.toHexString(adjEdge.intValue())+" is legal:"+dummy.isPotentialRoad(adjEdge.intValue()));
            // 
            // see if edge is a potential road
            // or ship to continue this route
            // 
            boolean edgeIsPotentialRoute = (isRoadNotShip) ? dummy.isPotentialRoad(edge) : dummy.isPotentialShip(edge);
            // If true, this edge transitions
            // between ships <-> roads, at a
            // coastal settlement
            boolean edgeRequiresCoastalSettlement = false;
            if ((!edgeIsPotentialRoute) && game.hasSeaBoard) {
                // Determine if can transition ship <-> road
                // at a coastal settlement
                final int nodeBetween = ((SOCBoardLarge) board).getNodeBetweenAdjacentEdges(tgtRoadEdge, edge);
                if (dummy.canPlaceSettlement(nodeBetween)) {
                    // check opposite type at transition
                    edgeIsPotentialRoute = (isRoadNotShip) ? dummy.isPotentialShip(edge) : dummy.isPotentialRoad(edge);
                    if (edgeIsPotentialRoute)
                        edgeRequiresCoastalSettlement = true;
                }
            }
            if (edgeIsPotentialRoute) {
                // Add 1 to road distance, unless
                // it requires a coastal settlement
                // (extra effort to build that)
                final int incrDistance = edgeRequiresCoastalSettlement ? 3 : 1;
                // 
                // see if possible road is already in the list
                // 
                SOCPossibleRoad pr = possibleRoads.get(adjEdge);
                if (pr != null) {
                    // For now, can't differ along a coastal route.
                    if (edgeRequiresCoastalSettlement && (isRoadNotShip != pr.isRoadNotShip())) {
                        // <--- road vs ship mismatch ---
                        continue;
                    }
                    // 
                    // if so, and it needs 1 or more roads other than this one,
                    // 
                    // D.ebugPrintln("$$$ pr "+Integer.toHexString(pr.getCoordinates())+" already in list");
                    List<SOCPossibleRoad> nr = pr.getNecessaryRoads();
                    if (!(nr.isEmpty() || nr.contains(targetRoad))) {
                        // 
                        // add the target road to its nr list and the new road to the target road's np list
                        // 
                        // D.ebugPrintln("$$$    adding "+Integer.toHexString(targetRoad.getCoordinates())+" to nr list");
                        nr.add(targetRoad);
                        targetRoad.addNewPossibility(pr);
                        // 
                        if ((targetRoad.getNumberOfNecessaryRoads() + incrDistance) < pr.getNumberOfNecessaryRoads()) {
                            pr.setNumberOfNecessaryRoads(targetRoad.getNumberOfNecessaryRoads() + incrDistance);
                        }
                    }
                    if (!pr.hasBeenExpanded()) {
                        roadsToExpand.add(pr);
                        pr.setExpandedFlag();
                    }
                } else {
                    // 
                    // else, add new possible road or ship
                    // 
                    // D.ebugPrintln("$$$ adding new pr at "+Integer.toHexString(adjEdge.intValue()));
                    ArrayList<SOCPossibleRoad> neededRoads = new ArrayList<SOCPossibleRoad>();
                    neededRoads.add(targetRoad);
                    SOCPossibleRoad newPR;
                    boolean isRoad = isRoadNotShip;
                    if (edgeRequiresCoastalSettlement)
                        isRoad = !isRoad;
                    // use coastal road/ship type (isCoastalRoadAndShip) only if the road/ship
                    // being expanded is coastal, or if we can require a coastal settlement to
                    // switch from road-only or ship-only
                    final boolean isCoastal = dummy.isPotentialRoad(edge) && dummy.isPotentialShip(edge) && (edgeRequiresCoastalSettlement || ((targetRoad instanceof SOCPossibleShip) && ((SOCPossibleShip) targetRoad).isCoastalRoadAndShip));
                    if (isRoad && !isCoastal) {
                        newPR = new SOCPossibleRoad(player, edge, neededRoads);
                    } else {
                        newPR = new SOCPossibleShip(player, edge, isCoastal, neededRoads);
                        System.err.println("L1072: " + toString() + ": new PossibleShip(" + isCoastal + ") at 0x" + Integer.toHexString(edge));
                    }
                    newPR.setNumberOfNecessaryRoads(targetRoad.getNumberOfNecessaryRoads() + incrDistance);
                    targetRoad.addNewPossibility(newPR);
                    newPossibleRoads.add(newPR);
                    roadsToExpand.add(newPR);
                    newPR.setExpandedFlag();
                }
            }
        }
        // 
        for (SOCPossibleRoad newPR : newPossibleRoads) {
            possibleRoads.put(Integer.valueOf(newPR.getCoordinates()), newPR);
        }
        // 
        for (SOCPossibleRoad expandPR : roadsToExpand) {
            expandRoadOrShip(expandPR, player, dummy, trackers, level - 1);
        }
    }
    // 
    // remove the dummy road
    // 
    dummy.removePiece(dummyRoad, null);
}
Also used : SOCBoardLarge(soc.game.SOCBoardLarge) SOCBoard(soc.game.SOCBoard) SOCShip(soc.game.SOCShip) ArrayList(java.util.ArrayList) SOCRoad(soc.game.SOCRoad)

Example 19 with SOCBoardLarge

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

the class SOCPlayerTracker method addOurNewRoadOrShip.

/**
 * Add one of our roads or ships that has just been built.
 * Look for new adjacent possible settlements.
 * Calls {@link #expandRoadOrShip(SOCPossibleRoad, SOCPlayer, SOCPlayer, HashMap, int)}
 * on newly possible adjacent roads or ships.
 *
 * @param road         the road or ship
 * @param trackers     player trackers for the players
 * @param expandLevel  how far out we should expand roads/ships;
 *                     passed to {@link #expandRoadOrShip(SOCPossibleRoad, SOCPlayer, SOCPlayer, HashMap, int)}
 */
private void addOurNewRoadOrShip(SOCRoad road, HashMap<Integer, SOCPlayerTracker> trackers, int expandLevel) {
    // D.ebugPrintln("$$$ addOurNewRoad : "+road);
    // 
    // see if the new road was a possible road
    // 
    Iterator<SOCPossibleRoad> prIter = possibleRoads.values().iterator();
    while (prIter.hasNext()) {
        SOCPossibleRoad pr = prIter.next();
        // 
        // reset all expanded flags for possible roads
        // 
        pr.resetExpandedFlag();
        if (pr.getCoordinates() == road.getCoordinates()) {
            // 
            // if so, remove it
            // 
            // D.ebugPrintln("$$$ removing "+Integer.toHexString(road.getCoordinates()));
            possibleRoads.remove(Integer.valueOf(pr.getCoordinates()));
            removeFromNecessaryRoads(pr);
            break;
        }
    }
    // D.ebugPrintln("$$$ checking for possible settlements");
    // 
    // see if this road/ship adds any new possible settlements
    // 
    // check adjacent nodes to road for potential settlements
    // 
    final SOCBoard board = game.getBoard();
    Collection<Integer> adjNodeEnum = board.getAdjacentNodesToEdge(road.getCoordinates());
    for (Integer adjNode : adjNodeEnum) {
        if (player.canPlaceSettlement(adjNode.intValue())) {
            // 
            // see if possible settlement is already in the list
            // 
            // D.ebugPrintln("$$$ seeing if "+Integer.toHexString(adjNode.intValue())+" is already in the list");
            SOCPossibleSettlement posSet = possibleSettlements.get(adjNode);
            if (posSet != null) {
                // 
                // if so, clear necessary road list and remove from np lists
                // 
                // D.ebugPrintln("$$$ found it");
                removeFromNecessaryRoads(posSet);
                posSet.getNecessaryRoads().clear();
                posSet.setNumberOfNecessaryRoads(0);
            } else {
                // 
                // else, add new possible settlement
                // 
                // D.ebugPrintln("$$$ adding new possible settlement at "+Integer.toHexString(adjNode.intValue()));
                SOCPossibleSettlement newPosSet = new SOCPossibleSettlement(player, adjNode.intValue(), null);
                newPosSet.setNumberOfNecessaryRoads(0);
                possibleSettlements.put(adjNode, newPosSet);
                updateSettlementConflicts(newPosSet, trackers);
            }
        }
    }
    // D.ebugPrintln("$$$ checking roads adjacent to "+Integer.toHexString(road.getCoordinates()));
    // 
    // see if this road adds any new possible roads
    // 
    ArrayList<SOCPossibleRoad> newPossibleRoads = new ArrayList<SOCPossibleRoad>();
    ArrayList<SOCPossibleRoad> roadsToExpand = new ArrayList<SOCPossibleRoad>();
    // 
    for (Integer adjEdge : board.getAdjacentEdgesToEdge(road.getCoordinates())) {
        final int edge = adjEdge.intValue();
        // D.ebugPrintln("$$$ edge "+Integer.toHexString(adjEdge.intValue())+" is legal:"+player.isPotentialRoad(adjEdge.intValue()));
        // 
        // see if edge is a potential road
        // or ship to continue this route
        // 
        boolean edgeIsPotentialRoute = (road.isRoadNotShip()) ? player.isPotentialRoad(edge) : player.isPotentialShip(edge);
        // If true, this edge transitions
        // between ships <-> roads, at a
        // coastal settlement
        boolean edgeRequiresCoastalSettlement = false;
        if ((!edgeIsPotentialRoute) && game.hasSeaBoard) {
            // Determine if can transition ship <-> road
            // at a coastal settlement
            final int nodeBetween = ((SOCBoardLarge) board).getNodeBetweenAdjacentEdges(road.getCoordinates(), edge);
            if (player.canPlaceSettlement(nodeBetween)) {
                // check opposite type at transition
                edgeIsPotentialRoute = (road.isRoadNotShip()) ? player.isPotentialShip(edge) : player.isPotentialRoad(edge);
                if (edgeIsPotentialRoute)
                    edgeRequiresCoastalSettlement = true;
            }
        }
        if (edgeIsPotentialRoute) {
            // 
            // see if possible road is already in the list
            // 
            SOCPossibleRoad pr = possibleRoads.get(adjEdge);
            if (pr != null) {
                // For now, can't differ along a coastal route.
                if (edgeRequiresCoastalSettlement && (pr.isRoadNotShip() != road.isRoadNotShip())) {
                    // <--- road vs ship mismatch ---
                    continue;
                }
                // D.ebugPrintln("$$$ pr "+Integer.toHexString(pr.getCoordinates())+" already in list");
                if (!pr.getNecessaryRoads().isEmpty()) {
                    // D.ebugPrintln("$$$    clearing nr list");
                    removeFromNecessaryRoads(pr);
                    pr.getNecessaryRoads().clear();
                    pr.setNumberOfNecessaryRoads(0);
                }
                roadsToExpand.add(pr);
                pr.setExpandedFlag();
            } else {
                // 
                // else, add new possible road
                // 
                // D.ebugPrintln("$$$ adding new pr at "+Integer.toHexString(adjEdge.intValue()));
                SOCPossibleRoad newPR;
                // for effort if requires settlement
                final int roadsBetween;
                boolean isRoad = road.isRoadNotShip();
                if (edgeRequiresCoastalSettlement) {
                    isRoad = !isRoad;
                    // roughly account for effort & cost of new settlement
                    roadsBetween = 2;
                } else {
                    roadsBetween = 0;
                }
                // use coastal road/ship type (isCoastalRoadAndShip) only if we can
                // require a coastal settlement to switch from road-only or ship-only
                final boolean isCoastal = edgeRequiresCoastalSettlement && player.isPotentialRoad(edge) && player.isPotentialShip(edge);
                if (isRoad && !isCoastal) {
                    newPR = new SOCPossibleRoad(player, edge, null);
                } else {
                    newPR = new SOCPossibleShip(player, edge, isCoastal, null);
                    System.err.println("L793: " + toString() + ": new PossibleShip(" + isCoastal + ") at 0x" + Integer.toHexString(edge));
                }
                // 0 unless requires settlement
                newPR.setNumberOfNecessaryRoads(roadsBetween);
                newPossibleRoads.add(newPR);
                roadsToExpand.add(newPR);
                newPR.setExpandedFlag();
            }
        }
    }
    // 
    for (SOCPossibleRoad newPR : newPossibleRoads) {
        possibleRoads.put(Integer.valueOf(newPR.getCoordinates()), newPR);
    }
    // 
    // expand possible roads that we've touched or added
    // 
    SOCPlayer dummy = new SOCPlayer(player);
    for (SOCPossibleRoad expandPR : roadsToExpand) {
        expandRoadOrShip(expandPR, player, dummy, trackers, expandLevel);
    }
    dummy.destroyPlayer();
    // 
    if ((road instanceof SOCShip) && game.isGameOptionSet(SOCGameOption.K_SC_PIRI))
        updateScenario_SC_PIRI_closestShipToFortress((SOCShip) road, true);
}
Also used : SOCBoardLarge(soc.game.SOCBoardLarge) SOCBoard(soc.game.SOCBoard) ArrayList(java.util.ArrayList) SOCShip(soc.game.SOCShip) SOCPlayer(soc.game.SOCPlayer)

Aggregations

SOCBoardLarge (soc.game.SOCBoardLarge)19 SOCBoard (soc.game.SOCBoard)6 SOCPlayer (soc.game.SOCPlayer)6 SOCShip (soc.game.SOCShip)6 SOCGame (soc.game.SOCGame)5 ArrayList (java.util.ArrayList)4 SOCRoad (soc.game.SOCRoad)4 Graphics2D (java.awt.Graphics2D)3 SOCCity (soc.game.SOCCity)3 SOCFortress (soc.game.SOCFortress)3 SOCVillage (soc.game.SOCVillage)3 Color (java.awt.Color)2 HashSet (java.util.HashSet)2 Vector (java.util.Vector)2 SOCInventoryItem (soc.game.SOCInventoryItem)2 SOCResourceSet (soc.game.SOCResourceSet)2 SOCSettlement (soc.game.SOCSettlement)2 AlphaComposite (java.awt.AlphaComposite)1 BasicStroke (java.awt.BasicStroke)1 Composite (java.awt.Composite)1