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());
}
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;
}
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;
}
}
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)
}
}
}
}
Aggregations