Search in sources :

Example 1 with SOCSpecialItem

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

the class SOCGameMessageHandler method handleSETSPECIALITEM.

/**
 * Handle Special Item requests from a player.
 * Calls {@link SOCSpecialItem#playerPickItem(String, SOCGame, SOCPlayer, int, int)}
 * or {@link SOCSpecialItem#playerSetItem(String, SOCGame, SOCPlayer, int, int, boolean)}
 * which provide scenario-specific responses or decline the request.
 * @param c  the connection that sent the message
 * @param mes  the message
 */
private void handleSETSPECIALITEM(SOCGame ga, Connection c, final SOCSetSpecialItem mes) {
    final String gaName = ga.getName();
    final SOCPlayer pl = ga.getPlayer(c.getData());
    final String typeKey = mes.typeKey;
    final int op = mes.op, gi = mes.gameItemIndex, pi = mes.playerItemIndex;
    // don't trust mes.playerNumber
    final int pn = (pl != null) ? pl.getPlayerNumber() : -1;
    boolean sendDenyReply = false;
    try {
        SOCSpecialItem itm = null;
        // if true, itm's cost was paid by player to PICK or SET or CLEAR
        final boolean paidCost;
        ga.takeMonitor();
        if ((pl == null) || (op < SOCSetSpecialItem.OP_SET) || (op > SOCSetSpecialItem.OP_PICK)) {
            sendDenyReply = true;
            paidCost = false;
        } else {
            final int prevState = ga.getGameState();
            if (op == SOCSetSpecialItem.OP_PICK) {
                // field values to send in reply/announcement
                int pickCoord = -1, pickLevel = 0;
                // sv field value to send
                String pickSV = null;
                // When game index and player index are both given,
                // compare items before and after PICK in case they change
                final SOCSpecialItem gBefore, pBefore;
                if ((gi != -1) && (pi != -1)) {
                    gBefore = ga.getSpecialItem(typeKey, gi);
                    pBefore = pl.getSpecialItem(typeKey, pi);
                } else {
                    gBefore = null;
                    pBefore = null;
                }
                // Before pick, get item as per playerPickItem javadoc for cost, coord, level,
                // in case it's cleared by the pick. If not cleared, will get it again afterwards.
                itm = ga.getSpecialItem(typeKey, gi, pi, pn);
                if (itm != null) {
                    pickCoord = itm.getCoordinates();
                    pickLevel = itm.getLevel();
                    pickSV = itm.getStringValue();
                }
                // perform the PICK in game
                paidCost = SOCSpecialItem.playerPickItem(typeKey, ga, pl, gi, pi);
                // if cost paid, send resource-loss first
                if (paidCost && (itm != null))
                    handler.reportRsrcGainLoss(gaName, itm.getCost(), true, false, pn, -1, null, null);
                if ((gi == -1) || (pi == -1)) {
                    // request didn't specify both gi and pi: only 1 SET/CLEAR message to send
                    final SOCSpecialItem itmAfter = ga.getSpecialItem(typeKey, gi, pi, pn);
                    final SOCSetSpecialItem msg;
                    if (itmAfter != null) {
                        msg = new SOCSetSpecialItem(ga, SOCSetSpecialItem.OP_SET, typeKey, gi, pi, itmAfter);
                        pickCoord = itmAfter.getCoordinates();
                        pickLevel = itmAfter.getLevel();
                        pickSV = itmAfter.getStringValue();
                    } else {
                        msg = new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_CLEAR, typeKey, gi, pi, pn);
                    }
                    srv.messageToGame(gaName, msg);
                } else {
                    // request specified both gi and pi: might need to send 1 SET/CLEAR message if shared,
                    // or 2 messages if not the same object for both
                    final SOCSpecialItem gAfter, pAfter;
                    gAfter = ga.getSpecialItem(typeKey, gi);
                    pAfter = pl.getSpecialItem(typeKey, pi);
                    if (gAfter == pAfter) {
                        final SOCSetSpecialItem msg;
                        if (gAfter != null) {
                            msg = new SOCSetSpecialItem(ga, SOCSetSpecialItem.OP_SET, typeKey, gi, pi, gAfter);
                            pickCoord = gAfter.getCoordinates();
                            pickLevel = gAfter.getLevel();
                            pickSV = gAfter.getStringValue();
                        } else {
                            msg = new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_CLEAR, typeKey, gi, pi, pn);
                        }
                        srv.messageToGame(gaName, msg);
                    } else {
                        // gi and pi don't share the same object; might need to send 2 messages out if both changed.
                        boolean hasgAfterCoordLevel = false;
                        if (gAfter == null) {
                            if (gBefore != null)
                                srv.messageToGame(gaName, new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_CLEAR, typeKey, gi, -1, -1));
                        } else {
                            srv.messageToGame(gaName, new SOCSetSpecialItem(ga, SOCSetSpecialItem.OP_SET, typeKey, gi, -1, gAfter));
                            pickCoord = gAfter.getCoordinates();
                            pickLevel = gAfter.getLevel();
                            pickSV = gAfter.getStringValue();
                            hasgAfterCoordLevel = true;
                        }
                        if (pAfter == null) {
                            if (pBefore != null)
                                srv.messageToGame(gaName, new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_CLEAR, typeKey, -1, pi, pn));
                        } else {
                            srv.messageToGame(gaName, new SOCSetSpecialItem(ga, SOCSetSpecialItem.OP_SET, typeKey, -1, pi, pAfter));
                            if (!hasgAfterCoordLevel) {
                                pickCoord = pAfter.getCoordinates();
                                pickLevel = pAfter.getLevel();
                                pickSV = pAfter.getStringValue();
                            }
                        }
                    }
                }
                srv.messageToGame(gaName, new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_PICK, typeKey, gi, pi, pn, pickCoord, pickLevel, pickSV));
            } else {
                if (op == SOCSetSpecialItem.OP_CLEAR)
                    // get item before CLEAR
                    itm = ga.getSpecialItem(typeKey, gi, pi, pn);
                paidCost = SOCSpecialItem.playerSetItem(typeKey, ga, pl, gi, pi, (op == SOCSetSpecialItem.OP_SET));
                // if cost paid, send resource-loss first
                if (paidCost && (itm != null))
                    handler.reportRsrcGainLoss(gaName, itm.getCost(), true, false, pn, -1, null, null);
                // get item after SET, in case it's changed
                if (op != SOCSetSpecialItem.OP_CLEAR)
                    itm = ga.getSpecialItem(typeKey, gi, pi, pn);
                if ((op == SOCSetSpecialItem.OP_CLEAR) || (itm == null))
                    srv.messageToGame(gaName, new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_CLEAR, typeKey, gi, pi, pn));
                else
                    srv.messageToGame(gaName, new SOCSetSpecialItem(ga, op, typeKey, gi, pi, itm));
            }
            // check game state, check for winner
            final int gstate = ga.getGameState();
            if (gstate != prevState)
                // might be OVER, if player won
                handler.sendGameState(ga);
        }
    } catch (IllegalStateException e) {
        sendDenyReply = true;
    } catch (Exception e) {
        D.ebugPrintStackTrace(e, "Exception caught");
    } finally {
        ga.releaseMonitor();
    }
    if (sendDenyReply)
        c.put(new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_DECLINE, typeKey, gi, pi, mes.playerNumber).toCmd());
}
Also used : SOCPlayer(soc.game.SOCPlayer) SOCSpecialItem(soc.game.SOCSpecialItem)

Example 2 with SOCSpecialItem

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

the class SOCRobotDM method scenarioGameStrategyPlan_SC_WOND.

/**
 * {@link #scenarioGameStrategyPlan(float, float, boolean, boolean, SOCBuildingSpeedEstimate, int, boolean) scenarioGameStrategyPlan(..)}
 * for {@link SOCGameOption#K_SC_WOND _SC_WOND}.  See that method for parameter meanings and other info.
 * @since 2.0.00
 */
private final boolean scenarioGameStrategyPlan_SC_WOND(final float bestScoreOrETA, float cardScoreOrETA, final boolean isScoreNotETA, final boolean bestPlanIsDevCard, final SOCBuildingSpeedEstimate ourBSE, final int leadersCurrentWGETA, final boolean forSpecialBuildingPhase) throws IllegalArgumentException {
    final int ourVP = ourPlayerData.getTotalVP();
    if (ourVP < 4) {
        // <--- Early return: We don't have 4 VP, don't use resources to build wonders yet ---
        return false;
    }
    // evaluate game status (current VP, etc); calc scenario-specific options and scores
    // are we already building a wonder?
    // if not, should we pick one now?
    // To win, some work on a wonder is required, but we don't have to finish it,
    // only be farther along than any other player.
    // Look for what we could build based on wonder requirements;
    // calc scores/BSEs for them (if any); pick one.
    // Once building it, calc score/BSE to add a level when possible if another player's wonder level is close,
    // until we have 2 more levels than any other player.
    SOCSpecialItem bestWond = ourPlayerData.getSpecialItem(SOCGameOption.K_SC_WOND, 0);
    int bestETA;
    float bestWondScoreOrETA;
    // wonder's "game index" in Special Item interface
    int gi = -1;
    if (bestWond != null) {
        gi = bestWond.getGameIndex();
        // Calc score or ETA to continue building pWond
        bestETA = ourBSE.calculateRollsFast(ourPlayerData.getResources(), bestWond.getCost(), 100, ourPlayerData.getPortFlags());
        if (isScoreNotETA) {
            bestWondScoreOrETA = (100.0f / game.maxPlayers);
            bestWondScoreOrETA += getETABonus(bestETA, leadersCurrentWGETA, bestWondScoreOrETA);
        } else {
            bestWondScoreOrETA = bestETA;
        }
    } else {
        // No wonder has been chosen yet; look at all available ones.
        // these will be given their actual values when bestWond is first assigned
        int wETA = 0;
        float wScoreOrETA = 0f;
        final int numWonders = 1 + game.maxPlayers;
        for (int i = 0; i < numWonders; ++i) {
            SOCSpecialItem wond = game.getSpecialItem(SOCGameOption.K_SC_WOND, i + 1);
            if (wond.getPlayer() != null)
                // already claimed
                continue;
            if (!wond.checkRequirements(ourPlayerData, false))
                // TODO potentially could plan how to reach requirements (build a settlement or city, etc)
                continue;
            int eta = ourBSE.calculateRollsFast(ourPlayerData.getResources(), wond.getCost(), 100, ourPlayerData.getPortFlags());
            float scoreOrETA;
            if (isScoreNotETA) {
                scoreOrETA = (100.0f / game.maxPlayers);
                scoreOrETA += getETABonus(eta, leadersCurrentWGETA, scoreOrETA);
            } else {
                scoreOrETA = eta;
            }
            boolean isBetter;
            if (bestWond == null)
                isBetter = true;
            else if (isScoreNotETA)
                isBetter = (scoreOrETA > wScoreOrETA);
            else
                // is ETA
                isBetter = (scoreOrETA < wScoreOrETA);
            if (isBetter) {
                bestWond = wond;
                wETA = eta;
                wScoreOrETA = scoreOrETA;
                gi = i + 1;
            }
        }
        if (bestWond == null)
            // couldn't meet any unclaimed wonder's requirements
            return false;
        bestETA = wETA;
        bestWondScoreOrETA = wScoreOrETA;
    }
    // Compare bestWond's score or ETA to our current plans
    System.err.println("L2296 bot " + ourPlayerData.getName() + (isScoreNotETA ? ": best score " : ": best ETA ") + bestScoreOrETA + "; card " + cardScoreOrETA + ", wondScoreOrETA " + bestWondScoreOrETA);
    // If it scores highly: Push the scenario building plan, push it, return true
    if (isScoreNotETA) {
        if (bestScoreOrETA > bestWondScoreOrETA)
            return false;
    } else {
        if (bestScoreOrETA < bestWondScoreOrETA)
            return false;
    }
    System.err.println("L2297 -> add to buildingPlan: gi=" + gi);
    buildingPlan.add(new SOCPossiblePickSpecialItem(ourPlayerData, SOCGameOption.K_SC_WOND, gi, 0, bestETA, bestWond.getCost()));
    return true;
}
Also used : SOCSpecialItem(soc.game.SOCSpecialItem)

Example 3 with SOCSpecialItem

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

the class SOCDisplaylessPlayerClient method handleSETSPECIALITEM.

/**
 * Handle the "set special item" message.
 * This method handles only {@link SOCSetSpecialItem#OP_SET OP_SET} and {@link SOCSetSpecialItem#OP_CLEAR OP_CLEAR}
 * and ignores other operations, such as {@link SOCSetSpecialItem#OP_PICK OP_PICK}.  If your client needs to react
 * to those other operations, override this method.
 *
 * @param games  Games the client is playing, for method reuse by SOCPlayerClient
 * @param mes  the message
 * @since 2.0.00
 */
public static final void handleSETSPECIALITEM(final Map<String, SOCGame> games, SOCSetSpecialItem mes) {
    final SOCGame ga = games.get(mes.getGame());
    if (ga == null)
        return;
    final String typeKey = mes.typeKey;
    final int gi = mes.gameItemIndex, pi = mes.playerItemIndex, pn = mes.playerNumber;
    switch(mes.op) {
        case SOCSetSpecialItem.OP_CLEAR:
            {
                if (gi != -1)
                    ga.setSpecialItem(typeKey, gi, null);
                if ((pn != -1) && (pi != -1)) {
                    SOCPlayer pl = ga.getPlayer(pn);
                    if (pl != null)
                        pl.setSpecialItem(typeKey, pi, null);
                }
            }
            break;
        case SOCSetSpecialItem.OP_SET:
            {
                if ((gi == -1) && ((pi == -1) || (pn == -1))) {
                    // malformed message
                    return;
                }
                SOCSpecialItem item = ga.getSpecialItem(typeKey, gi, pi, pn);
                final SOCPlayer pl = (pn != -1) ? ga.getPlayer(pn) : null;
                if (item != null) {
                    item.setPlayer(pl);
                    item.setCoordinates(mes.coord);
                    item.setLevel(mes.level);
                    item.setStringValue(mes.sv);
                } else {
                    item = new SOCSpecialItem(pl, mes.coord, mes.level, mes.sv, null, null);
                }
                if (gi != -1) {
                    item.setGameIndex(gi);
                    ga.setSpecialItem(typeKey, gi, item);
                }
                if ((pi != -1) && (pl != null))
                    pl.setSpecialItem(typeKey, pi, item);
            }
            break;
    }
}
Also used : SOCPlayer(soc.game.SOCPlayer) SOCGame(soc.game.SOCGame) SOCSpecialItem(soc.game.SOCSpecialItem)

Example 4 with SOCSpecialItem

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

the class SOCHandPanel method updateValue.

/**
 * update the value of a player element.
 * Call this after updating game data.
 *<P>
 * If {@link #VICTORYPOINTS} is updated, and game state is {@link SOCGame#OVER}, check for winner
 * and update (player name label, victory-points tooltip, disable bank/trade btn)
 *
 * @param utype  the type of value update, such as {@link #VICTORYPOINTS}
 *            or {@link PlayerClientListener.UpdateType#Sheep}.
 */
public void updateValue(PlayerClientListener.UpdateType utype) {
    boolean updateTotalResCount = false;
    /**
     * We say that we're getting the total vp, but
     * for other players this will automatically get
     * the public vp because we will assume their
     * dev card vp total is zero.
     */
    switch(utype) {
        case VictoryPoints:
            {
                int newVP = player.getTotalVP();
                vpSq.setIntValue(newVP);
                if (game.getGameState() == SOCGame.OVER) {
                    if (game.getPlayerWithWin() == player) {
                        // "Winner with 12 victory points"
                        vpSq.setTooltipText(strings.get("hpan.winner.label.ttwithvp", newVP));
                        // "X - Winner"
                        pname.setText(strings.get("hpan.winner.label", player.getName()));
                    }
                    if (interactive) {
                        bankBut.setEnabled(false);
                        bankUndoBut.setEnabled(false);
                        playCardBut.setEnabled(false);
                    }
                    doneBut.setLabel(DONE_RESTART);
                    // In case it's another player's turn
                    doneBut.setEnabled(true);
                    doneButIsRestart = true;
                }
            }
            break;
        case SpecialVictoryPoints:
            if (svpSq != null) {
                final int newSVP = player.getSpecialVP();
                svpSq.setIntValue(newSVP);
                final boolean vis = (newSVP != 0) && !offerCounterHidingFace;
                svpSq.setVisible(vis);
                svpLab.setVisible(vis);
            }
            break;
        case LongestRoad:
            setLRoad(player.hasLongestRoad());
            break;
        case LargestArmy:
            setLArmy(player.hasLargestArmy());
            break;
        case Clay:
            claySq.setIntValue(player.getResources().getAmount(SOCResourceConstants.CLAY));
            updateTotalResCount = true;
            break;
        case Ore:
            oreSq.setIntValue(player.getResources().getAmount(SOCResourceConstants.ORE));
            updateTotalResCount = true;
            break;
        case Sheep:
            sheepSq.setIntValue(player.getResources().getAmount(SOCResourceConstants.SHEEP));
            updateTotalResCount = true;
            break;
        case Wheat:
            wheatSq.setIntValue(player.getResources().getAmount(SOCResourceConstants.WHEAT));
            updateTotalResCount = true;
            break;
        case Wood:
            woodSq.setIntValue(player.getResources().getAmount(SOCResourceConstants.WOOD));
            updateTotalResCount = true;
            break;
        case ResourceTotalAndDetails:
            if (playerIsClient) {
                // Update the 5 individual ones too, not just the total count
                final SOCResourceSet rsrc = player.getResources();
                claySq.setIntValue(rsrc.getAmount(SOCResourceConstants.CLAY));
                oreSq.setIntValue(rsrc.getAmount(SOCResourceConstants.ORE));
                sheepSq.setIntValue(rsrc.getAmount(SOCResourceConstants.SHEEP));
                wheatSq.setIntValue(rsrc.getAmount(SOCResourceConstants.WHEAT));
                woodSq.setIntValue(rsrc.getAmount(SOCResourceConstants.WOOD));
            }
        case Resources:
            updateTotalResCount = true;
            break;
        case Road:
            roadSq.setIntValue(player.getNumPieces(SOCPlayingPiece.ROAD));
            break;
        case Settlement:
            settlementSq.setIntValue(player.getNumPieces(SOCPlayingPiece.SETTLEMENT));
            if (playerIsClient)
                updateResourceTradeCosts(false);
            break;
        case City:
            citySq.setIntValue(player.getNumPieces(SOCPlayingPiece.CITY));
            break;
        case Ship:
            if (shipSq != null)
                shipSq.setIntValue(player.getNumPieces(SOCPlayingPiece.SHIP));
            break;
        case DevCards:
            developmentSq.setIntValue(player.getInventory().getTotal());
            break;
        case Knight:
            knightsSq.setIntValue(player.getNumKnights());
            break;
        case Cloth:
            if (clothSq != null)
                clothSq.setIntValue(player.getCloth());
            break;
        case WonderLevel:
            if (wonderLab != null) {
                SOCSpecialItem pWond = player.getSpecialItem(SOCGameOption.K_SC_WOND, 0);
                final int pLevel = (pWond != null) ? pWond.getLevel() : 0;
                if (pLevel == 0) {
                    wonderLab.setText("");
                    wonderLab.setToolTipText(null);
                } else {
                    String ofWonder = null;
                    try {
                        // "w3"
                        String sv = pWond.getStringValue();
                        if (sv != null)
                            // "of the Monument"
                            ofWonder = strings.get("game.specitem.sc_wond.of_" + sv);
                    } catch (MissingResourceException e) {
                        try {
                            // "of a Wonder"
                            ofWonder = strings.get("game.specitem.sc_wond.of_fallback");
                        } catch (MissingResourceException e2) {
                            ofWonder = "of a Wonder";
                        }
                    }
                    // "Wonder Level: #"
                    wonderLab.setText(strings.get("hpan.wonderlevel", pLevel));
                    wonderLab.setToolTipText(strings.get("hpan.wonderlevel.tip", pLevel, SOCSpecialItem.SC_WOND_WIN_LEVEL, ofWonder));
                // "Built # of # levels of the Monument"
                }
            }
            break;
        case GoldGains:
        case Warship:
        case Unknown:
    }
    if (updateTotalResCount) {
        resourceSq.setIntValue(player.getResources().getTotal());
        if (offerIsDiscardOrPickMessage) {
            final int gs = game.getGameState();
            if (gs != SOCGame.WAITING_FOR_PICK_GOLD_RESOURCE) {
                clearDiscardOrPickMsg();
            } else {
            // Clear pick-resources message is handled above
            // by updateValue(NUM_PICK_GOLD_HEX_RESOURCES)
            }
        }
    }
}
Also used : MissingResourceException(java.util.MissingResourceException) SOCResourceSet(soc.game.SOCResourceSet) SOCSpecialItem(soc.game.SOCSpecialItem)

Aggregations

SOCSpecialItem (soc.game.SOCSpecialItem)4 SOCPlayer (soc.game.SOCPlayer)2 MissingResourceException (java.util.MissingResourceException)1 SOCGame (soc.game.SOCGame)1 SOCResourceSet (soc.game.SOCResourceSet)1