Search in sources :

Example 1 with SOCFortress

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

the class SOCGameMessageHandler method handleSIMPLEREQUEST.

/**
 * Handle the "simple request" message.
 * @param c  the connection
 * @param mes  the message
 * @since 1.1.18
 */
private void handleSIMPLEREQUEST(SOCGame ga, Connection c, final SOCSimpleRequest mes) {
    final String gaName = ga.getName();
    SOCPlayer clientPl = ga.getPlayer(c.getData());
    if (clientPl == null)
        return;
    final int pn = mes.getPlayerNumber();
    // probably required for most request types
    final boolean clientIsPN = (pn == clientPl.getPlayerNumber());
    final int reqtype = mes.getRequestType();
    final int cpn = ga.getCurrentPlayerNumber();
    // if true, reply with generic decline (pn = -1, reqtype, 0, 0)
    boolean replyDecline = false;
    switch(reqtype) {
        case SOCSimpleRequest.SC_PIRI_FORT_ATTACK:
            {
                final SOCShip adjac = ga.canAttackPirateFortress();
                if ((!clientIsPN) || (pn != cpn) || (adjac == null) || (adjac.getPlayerNumber() != cpn)) {
                    c.put(SOCSimpleRequest.toCmd(gaName, -1, reqtype, 0, 0));
                    // <--- early return: deny ---
                    return;
                }
                final int prevState = ga.getGameState();
                final SOCPlayer cp = ga.getPlayer(cpn);
                // in case some are lost, we'll announce that
                final int prevNumWarships = cp.getNumWarships();
                final SOCFortress fort = cp.getFortress();
                final int[] res = ga.attackPirateFortress(adjac);
                if (res.length > 1) {
                    // lost 1 or 2 ships adjacent to fortress.  res[1] == adjac.coordinate
                    srv.messageToGame(gaName, new SOCRemovePiece(gaName, adjac));
                    if (res.length > 2)
                        srv.messageToGame(gaName, new SOCRemovePiece(gaName, cpn, SOCPlayingPiece.SHIP, res[2]));
                    final int n = cp.getNumWarships();
                    if (n != prevNumWarships)
                        srv.messageToGame(gaName, new SOCPlayerElement(gaName, cpn, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_WARSHIP_COUNT, n));
                } else {
                    // player won
                    final int fortStrength = fort.getStrength();
                    srv.messageToGame(gaName, new SOCPieceValue(gaName, fort.getCoordinates(), fortStrength, 0));
                    if (0 == fortStrength)
                        srv.messageToGame(gaName, new SOCPutPiece(gaName, cpn, SOCPlayingPiece.SETTLEMENT, fort.getCoordinates()));
                }
                srv.messageToGame(gaName, new SOCSimpleAction(gaName, cpn, SOCSimpleAction.SC_PIRI_FORT_ATTACK_RESULT, res[0], res.length - 1));
                // check for end of player's turn
                if (!handler.checkTurn(c, ga)) {
                    handler.endGameTurn(ga, cp, false);
                } else {
                    // still player's turn, even if they won
                    final int gstate = ga.getGameState();
                    if (gstate != prevState)
                        // might be OVER, if player won
                        handler.sendGameState(ga);
                }
            }
            break;
        case SOCSimpleRequest.TRADE_PORT_PLACE:
            {
                if (clientIsPN && (pn == cpn)) {
                    final int edge = mes.getValue1();
                    if ((ga.getGameState() == SOCGame.PLACING_INV_ITEM) && ga.canPlacePort(clientPl, edge)) {
                        final int ptype = ga.placePort(edge);
                        // PLAY1 or SPECIAL_BUILDING
                        handler.sendGameState(ga);
                        srv.messageToGame(gaName, new SOCSimpleRequest(gaName, cpn, SOCSimpleRequest.TRADE_PORT_PLACE, edge, ptype));
                    } else {
                        // client will print a text message, no need to send one
                        replyDecline = true;
                    }
                } else {
                    srv.messageToPlayerKeyed(c, gaName, "reply.not.your.turn");
                    replyDecline = true;
                }
            }
            break;
        default:
            // deny unknown types
            replyDecline = true;
            System.err.println("handleSIMPLEREQUEST: Unknown type " + reqtype + " from " + c.getData() + " in game " + ga);
    }
    if (replyDecline)
        c.put(SOCSimpleRequest.toCmd(gaName, -1, reqtype, 0, 0));
}
Also used : SOCShip(soc.game.SOCShip) SOCPlayer(soc.game.SOCPlayer) SOCFortress(soc.game.SOCFortress)

Example 2 with SOCFortress

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

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

the class SOCPlayerTracker method updateScenario_SC_PIRI_closestShipToFortress.

/**
 * For scenario {@code _SC_PIRI}, update the player's ship closest to their Fortress.
 * Assumes no ship will ever be west of the fortress (smaller column number).
 * Must be called after adding or removing a ship from our player's {@link SOCPlayer#getRoads()}.
 * @param ship  Ship that was added or removed, or {@code null} to check all ships after removal
 * @param shipAdded  True if {@code ship} was added; false if {@code ship} or any other ship was removed
 *            or if we're updating Closest Ship without adding or removing a ship
 * @throws IllegalArgumentException if {@code shipAdded} is true, but null {@code ship}
 * @since 2.0.00
 */
void updateScenario_SC_PIRI_closestShipToFortress(final SOCShip ship, final boolean shipAdded) throws IllegalArgumentException {
    if (shipAdded && (ship == null))
        throw new IllegalArgumentException();
    if ((scen_SC_PIRI_closestShipToFortress == null) && (ship != null)) {
        if (shipAdded)
            // closest by default
            scen_SC_PIRI_closestShipToFortress = ship;
        // <--- Early return: no other ships to compare ---
        return;
    }
    if (!shipAdded) {
        if ((ship != null) && (scen_SC_PIRI_closestShipToFortress != null) && (ship.getCoordinates() != scen_SC_PIRI_closestShipToFortress.getCoordinates()))
            // <--- Early return: Not the closest ship ---
            return;
    }
    // may be null towards end of game
    final SOCFortress fort = player.getFortress();
    // If fort's null, we can still compare columns, just not rows, of ship coordinates.
    final int fortR = (fort != null) ? (fort.getCoordinates() >> 8) : -1;
    if (shipAdded) {
        final int shipEdge = ship.getCoordinates(), prevShipEdge = scen_SC_PIRI_closestShipToFortress.getCoordinates();
        final int shipR = shipEdge >> 8, shipC = shipEdge & 0xFF, prevR = prevShipEdge >> 8, prevC = prevShipEdge & 0xFF;
        if ((shipC < prevC) || ((shipC == prevC) && (fortR != -1) && (Math.abs(shipR - fortR) < Math.abs(prevR - fortR)))) {
            scen_SC_PIRI_closestShipToFortress = ship;
        }
    } else {
        // A ship has been removed.  We don't know which one.
        // So, check all ships for distance from fortress.
        Enumeration<SOCRoad> roadAndShipEnum = player.getRoads().elements();
        SOCShip closest = null;
        int closeR = -1, closeC = -1;
        while (roadAndShipEnum.hasMoreElements()) {
            final SOCRoad rs = roadAndShipEnum.nextElement();
            if (!(rs instanceof SOCShip))
                continue;
            final int shipEdge = rs.getCoordinates();
            final int shipR = shipEdge >> 8, shipC = shipEdge & 0xFF;
            if ((closest == null) || (shipC < closeC) || ((shipC == closeC) && (fortR != -1) && (Math.abs(shipR - fortR) < Math.abs(closeR - fortR)))) {
                closest = (SOCShip) rs;
                closeR = shipR;
                closeC = shipC;
            }
        }
        // null if no ships
        scen_SC_PIRI_closestShipToFortress = closest;
    }
}
Also used : SOCShip(soc.game.SOCShip) SOCFortress(soc.game.SOCFortress) SOCRoad(soc.game.SOCRoad)

Example 4 with SOCFortress

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

the class SOCPlayerTracker method getScenario_SC_PIRI_shipDistanceToFortress.

/**
 * For scenario {@code _SC_PIRI}, get the distance of this player's closest ship from their
 * {@code SOCFortress}. Since ships aren't placed diagonally, this is the distance along rows + columns.
 * The edge (r,c) has node (r,c) as its left end, at distance 0.
 * @param ship  Any ship, including {@link #getScenario_SC_PIRI_closestShipToFortress()}
 * @return row distance + column distance based on piece coordinates;
 *     or 0 if no fortress which would mean the fortress was reached
 *     (distance 0) and defeated already.
 * @since 2.0.00
 */
public int getScenario_SC_PIRI_shipDistanceToFortress(final SOCShip ship) {
    // may be null towards end of game
    final SOCFortress fort = player.getFortress();
    if (fort == null)
        return 0;
    final int fortNode = fort.getCoordinates(), shipEdge = ship.getCoordinates();
    final int fortR = fortNode >> 8, fortC = fortNode & 0xFF, shipR = shipEdge >> 8, shipC = shipEdge & 0xFF;
    return Math.abs(fortR - shipR) + Math.abs(fortC - shipC);
}
Also used : SOCFortress(soc.game.SOCFortress)

Example 5 with SOCFortress

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

the class SOCBoardPanel method drawBoard.

/**
 * Draw the whole board, including pieces and tooltip ({@link #hilight}, {@link #hoverTip}) if applicable.
 * The basic board without pieces is drawn just once, then buffered.
 * If the board layout changes (at start of game, for example),
 * call {@link #flushBoardLayoutAndRepaint()} to clear the buffered copy.
 *
 * @see #drawBoardEmpty(Graphics)
 */
private void drawBoard(Graphics g) {
    Image ebb = emptyBoardBuffer;
    if (scaledMissedImage || ebb == null) {
        if (ebb == null) {
            ebb = createImage(scaledPanelW, scaledPanelH);
            emptyBoardBuffer = ebb;
        }
        drawnEmptyAt = System.currentTimeMillis();
        // drawBoardEmpty, drawHex will set this flag if missed
        scaledMissedImage = false;
        drawBoardEmpty(ebb.getGraphics());
        ebb.flush();
        if (scaledMissedImage && (scaledAt != 0) && (RESCALE_MAX_RETRY_MS < (drawnEmptyAt - scaledAt)))
            // eventually give up scaling it
            scaledMissedImage = false;
    }
    // draw ebb from local variable, not emptyBoardBuffer field, to avoid occasional NPE
    g.setPaintMode();
    g.drawImage(ebb, 0, 0, this);
    // ask for antialiasing if available
    if (g instanceof Graphics2D)
        ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    final boolean xlat = (panelMarginX != 0) || (panelMarginY != 0);
    if (xlat)
        g.translate(panelMarginX, panelMarginY);
    final int gameState = game.getGameState();
    if (board.getRobberHex() != -1) {
        drawRobber(g, board.getRobberHex(), (gameState != SOCGame.PLACING_ROBBER), true);
    }
    if (board.getPreviousRobberHex() != -1) {
        drawRobber(g, board.getPreviousRobberHex(), (gameState != SOCGame.PLACING_ROBBER), false);
    }
    if (isLargeBoard) {
        int hex = ((SOCBoardLarge) board).getPirateHex();
        if (hex > 0) {
            drawRoadOrShip(g, hex, -2, (gameState == SOCGame.PLACING_PIRATE), false, false);
        }
        hex = ((SOCBoardLarge) board).getPreviousPirateHex();
        if (hex > 0) {
            drawRoadOrShip(g, hex, -3, (gameState == SOCGame.PLACING_PIRATE), false, false);
        }
    }
    /**
     * draw the roads and ships
     */
    if (!game.isGameOptionSet(SOCGameOption.K_SC_PIRI)) {
        for (SOCRoad r : board.getRoads()) {
            drawRoadOrShip(g, r.getCoordinates(), r.getPlayerNumber(), false, !(r instanceof SOCShip), false);
        }
    } else {
        for (int pn = 0; pn < game.maxPlayers; ++pn) {
            final SOCPlayer pl = game.getPlayer(pn);
            // count warships here, for efficiency, instead of calling SOCGame.isShipWarship for each one
            int numWarships = pl.getNumWarships();
            for (SOCRoad r : pl.getRoads()) {
                final boolean isShip = (r instanceof SOCShip);
                final boolean isWarship = isShip && (numWarships > 0);
                drawRoadOrShip(g, r.getCoordinates(), pn, false, !isShip, isWarship);
                if (isWarship)
                    // this works since warships begin with player's 1st-placed ship in getRoads()
                    --numWarships;
            }
            /**
             * draw the player's fortress, if any
             */
            SOCFortress fo = pl.getFortress();
            if (fo != null)
                drawFortress(g, fo, pn, false);
        }
    }
    /**
     * draw the settlements
     */
    for (SOCSettlement s : board.getSettlements()) {
        drawSettlement(g, s.getCoordinates(), s.getPlayerNumber(), false, false);
    }
    /**
     * draw the cities
     */
    for (SOCCity c : board.getCities()) {
        drawCity(g, c.getCoordinates(), c.getPlayerNumber(), false);
    }
    if (xlat)
        g.translate(-panelMarginX, -panelMarginY);
    /**
     * draw the current-player arrow after ("above") pieces,
     * but below any hilighted piece, in case of overlap at
     * edge of board. More likely on 6-player board for the
     * two players whose handpanels are vertically centered.
     */
    if (gameState != SOCGame.NEW) {
        drawArrow(g, game.getCurrentPlayerNumber(), game.getCurrentDice());
    }
    if (player != null) {
        if (xlat)
            g.translate(panelMarginX, panelMarginY);
        /**
         * Draw the hilight when in interactive mode;
         * No hilight when null player (before game started).
         * The "hovering" road/settlement/city are separately painted
         * in {@link soc.client.SOCBoardPanel.BoardToolTip#paint()}.
         */
        switch(mode) {
            case MOVE_SHIP:
                if (moveShip_fromEdge != 0)
                    drawRoadOrShip(g, moveShip_fromEdge, -1, false, false, moveShip_isWarship);
            case PLACE_ROAD:
            case PLACE_INIT_ROAD:
            case PLACE_FREE_ROAD_OR_SHIP:
                if (hilight != 0) {
                    drawRoadOrShip(g, hilight, playerNumber, true, !hilightIsShip, (moveShip_isWarship && (moveShip_fromEdge != 0)));
                }
                break;
            case PLACE_SETTLEMENT:
            case PLACE_INIT_SETTLEMENT:
                if (hilight > 0) {
                    drawSettlement(g, hilight, playerNumber, true, false);
                }
                break;
            case PLACE_CITY:
                if (hilight > 0) {
                    drawCity(g, hilight, playerNumber, true);
                }
                break;
            case PLACE_SHIP:
                if (hilight > 0) {
                    drawRoadOrShip(g, hilight, playerNumber, true, false, false);
                }
                break;
            case CONSIDER_LM_SETTLEMENT:
            case CONSIDER_LT_SETTLEMENT:
                if (hilight > 0) {
                    drawSettlement(g, hilight, otherPlayer.getPlayerNumber(), true, false);
                }
                break;
            case CONSIDER_LM_ROAD:
            case CONSIDER_LT_ROAD:
                if (hilight != 0) {
                    drawRoadOrShip(g, hilight, otherPlayer.getPlayerNumber(), false, true, false);
                }
                break;
            case CONSIDER_LM_CITY:
            case CONSIDER_LT_CITY:
                if (hilight > 0) {
                    drawCity(g, hilight, otherPlayer.getPlayerNumber(), true);
                }
                break;
            case PLACE_ROBBER:
                if (hilight > 0) {
                    drawRobber(g, hilight, true, true);
                }
                break;
            case PLACE_PIRATE:
                if (hilight > 0) {
                    drawRoadOrShip(g, hilight, -2, false, false, false);
                }
                break;
            case SC_FTRI_PLACE_PORT:
                drawBoard_SC_FTRI_placePort(g);
                break;
        }
        if (xlat)
            g.translate(-panelMarginX, -panelMarginY);
    }
    if (superText1 != null) {
        drawSuperText(g);
    }
    if (superTextTop != null) {
        drawSuperTextTop(g);
    }
}
Also used : SOCSettlement(soc.game.SOCSettlement) SOCBoardLarge(soc.game.SOCBoardLarge) SOCCity(soc.game.SOCCity) SOCShip(soc.game.SOCShip) SOCPlayer(soc.game.SOCPlayer) SOCFortress(soc.game.SOCFortress) Image(java.awt.Image) BufferedImage(java.awt.image.BufferedImage) SOCRoad(soc.game.SOCRoad) Graphics2D(java.awt.Graphics2D)

Aggregations

SOCFortress (soc.game.SOCFortress)11 SOCShip (soc.game.SOCShip)8 SOCPlayer (soc.game.SOCPlayer)5 SOCRoad (soc.game.SOCRoad)4 SOCSettlement (soc.game.SOCSettlement)4 SOCVillage (soc.game.SOCVillage)4 SOCBoardLarge (soc.game.SOCBoardLarge)3 SOCCity (soc.game.SOCCity)3 Image (java.awt.Image)2 BufferedImage (java.awt.image.BufferedImage)2 Graphics (java.awt.Graphics)1 Graphics2D (java.awt.Graphics2D)1 SOCBoard (soc.game.SOCBoard)1 SOCGame (soc.game.SOCGame)1 SOCPlayingPiece (soc.game.SOCPlayingPiece)1