use of soc.game.SOCInventoryItem in project JSettlers2 by jdmonin.
the class SOCGameMessageHandler method handleINVENTORYITEMACTION.
// / Inventory Items and Special Items ///
/**
* Special inventory item action (play request) from a player.
* Ignored unless {@link SOCInventoryItemAction#action mes.action} == {@link SOCInventoryItemAction#PLAY PLAY}.
* Calls {@link SOCGame#canPlayInventoryItem(int, int)}, {@link SOCGame#playInventoryItem(int)}.
* If game state changes here, calls {@link SOCGameHandler#sendGameState(SOCGame)} just before returning.
*
* @param ga game with {@code c} as a client player
* @param c the connection sending the message
* @param mes the message
*/
private void handleINVENTORYITEMACTION(SOCGame ga, Connection c, final SOCInventoryItemAction mes) {
if (mes.action != SOCInventoryItemAction.PLAY)
return;
final String gaName = ga.getName();
SOCPlayer clientPl = ga.getPlayer(c.getData());
if (clientPl == null)
return;
final int pn = clientPl.getPlayerNumber();
final int replyCannot = ga.canPlayInventoryItem(pn, mes.itemType);
if (replyCannot != 0) {
srv.messageToPlayer(c, new SOCInventoryItemAction(gaName, -1, SOCInventoryItemAction.CANNOT_PLAY, mes.itemType, replyCannot));
return;
}
final int oldGameState = ga.getGameState();
// <--- Play the item ---
final SOCInventoryItem item = ga.playInventoryItem(mes.itemType);
if (item == null) {
// Wasn't able to play. Assume canPlay was recently called and returned OK; the most
// volatile of its conditions is player's inventory, so assume that's what changed.
srv.messageToPlayer(c, new SOCInventoryItemAction(gaName, -1, SOCInventoryItemAction.CANNOT_PLAY, mes.itemType, // 1 == item not in inventory
1));
return;
}
// Item played. Announce play and removal (or keep) from player's inventory.
// Announce game state if changed.
srv.messageToGame(gaName, new SOCInventoryItemAction(gaName, pn, SOCInventoryItemAction.PLAYED, item.itype, item.isKept(), item.isVPItem(), item.canCancelPlay));
final int gstate = ga.getGameState();
if (gstate != oldGameState)
handler.sendGameState(ga);
}
use of soc.game.SOCInventoryItem in project JSettlers2 by jdmonin.
the class SOCRobotBrain method run.
/**
* Here is the run method. Just keep receiving game events
* through {@link #gameEventQ} and deal with each one.
* Remember that we're sent a {@link SOCTimingPing} event once per second,
* incrementing {@link #counter}. That allows the bot to wait a certain
* time for other players before it decides whether to do something.
*<P>
* Nearly all bot actions start in this method; the overview of bot structures
* is in the {@link SOCRobotBrain class javadoc} for prominence.
* See comments within <tt>run()</tt> for minor details.
*<P>
* The brain thread will run until {@link #kill()} has been called or its pinger stops,
* or it receives a {@link SOCMessage#ROBOTDISMISS} request to exit the game.
*/
@Override
public void run() {
// Thread name for debug
try {
Thread.currentThread().setName("robotBrain-" + client.getNickname() + "-" + game.getName());
} catch (Throwable th) {
}
if (pinger != null) {
pinger.start();
while (alive) {
try {
// Sleeps until message received
final SOCMessage mes = gameEventQ.get();
final int mesType;
if (mes != null) {
// Debug aid: When looking at message contents or setting a per-message breakpoint,
// skip the pings; note (mesType != SOCMessage.TIMINGPING) here.
mesType = mes.getType();
if (mesType != SOCMessage.TIMINGPING)
turnEventsCurrent.addElement(mes);
if (D.ebugOn)
D.ebugPrintln("mes - " + mes);
} else {
mesType = -1;
}
if (waitingForTradeMsg && (counter > 10)) {
waitingForTradeMsg = false;
counter = 0;
}
if (waitingForTradeResponse && (counter > 100)) {
// Remember other players' responses, call client.clearOffer,
// clear waitingForTradeResponse and counter.
tradeStopWaitingClearOffer();
}
if (waitingForGameState && (counter > 10000)) {
// D.ebugPrintln("counter = "+counter);
// D.ebugPrintln("RESEND");
counter = 0;
client.resend();
}
if (mesType == SOCMessage.GAMESTATE) {
handleGAMESTATE(((SOCGameState) mes).getState());
// clears waitingForGameState, updates oldGameState, calls ga.setGameState
} else if (mesType == SOCMessage.STARTGAME) {
handleGAMESTATE(((SOCStartGame) mes).getGameState());
// clears waitingForGameState, updates oldGameState, calls ga.setGameState
} else if (mesType == SOCMessage.TURN) {
// Start of a new player's turn.
// Update game and reset most of our state fields.
// See also below: if ((mesType == SOCMessage.TURN) && ourTurn).
handleGAMESTATE(((SOCTurn) mes).getGameState());
// clears waitingForGameState, updates oldGameState, calls ga.setGameState
game.setCurrentPlayerNumber(((SOCTurn) mes).getPlayerNumber());
game.updateAtTurn();
//
// remove any expected states
//
expectROLL_OR_CARD = false;
expectPLAY1 = false;
expectPLACING_ROAD = false;
expectPLACING_SETTLEMENT = false;
expectPLACING_CITY = false;
expectPLACING_SHIP = false;
expectPLACING_ROBBER = false;
expectPLACING_FREE_ROAD1 = false;
expectPLACING_FREE_ROAD2 = false;
expectPLACING_INV_ITEM = false;
expectDICERESULT = false;
expectDISCARD = false;
expectMOVEROBBER = false;
expectWAITING_FOR_DISCOVERY = false;
expectWAITING_FOR_MONOPOLY = false;
//
if (robotParameters.getTradeFlag() == 1) {
doneTrading = false;
} else {
doneTrading = true;
}
waitingForTradeMsg = false;
waitingForTradeResponse = false;
negotiator.resetIsSelling();
negotiator.resetOffersMade();
waitingForPickSpecialItem = null;
waitingForSC_PIRI_FortressRequest = false;
//
// check or reset any special-building-phase decisions
//
decidedIfSpecialBuild = false;
if (game.getGameState() == SOCGame.SPECIAL_BUILDING) {
if (waitingForSpecialBuild && !buildingPlan.isEmpty()) {
// Keep the building plan.
// Will ask during loop body to build.
} else {
// We have no plan, but will call planBuilding()
// during the loop body. If buildingPlan still empty,
// bottom of loop will end our Special Building turn,
// just as it would in gamestate PLAY1. Otherwise,
// will ask to build after planBuilding.
}
} else {
//
// reset any plans we had
//
buildingPlan.clear();
}
negotiator.resetTargetPieces();
//
// swap the message-history queues
//
{
Vector<SOCMessage> oldPrev = turnEventsPrev;
turnEventsPrev = turnEventsCurrent;
oldPrev.clear();
turnEventsCurrent = oldPrev;
}
turnExceptionCount = 0;
}
if (game.getCurrentPlayerNumber() == ourPlayerNumber) {
ourTurn = true;
waitingForSpecialBuild = false;
} else {
ourTurn = false;
}
if ((mesType == SOCMessage.TURN) && ourTurn) {
waitingForOurTurn = false;
// Clear some per-turn variables.
// For others, see above: if (mesType == SOCMessage.TURN)
whatWeFailedToBuild = null;
failedBuildingAttempts = 0;
rejectedPlayDevCardType = -1;
rejectedPlayInvItem = null;
}
/**
* Handle some message types early.
*
* When reading the main flow of this method, skip past here;
* search for "it's time to decide to build or take other normal actions".
*/
switch(mesType) {
case SOCMessage.PLAYERELEMENT:
// If this during the ROLL_OR_CARD state, also updates the
// negotiator's is-selling flags.
// If our player is losing a resource needed for the buildingPlan,
// clear the plan if this is for the Special Building Phase (on the 6-player board).
// In normal game play, we clear the building plan at the start of each turn.
handlePLAYERELEMENT((SOCPlayerElement) mes);
break;
case SOCMessage.PLAYERELEMENTS:
// Multiple PLAYERELEMENT updates;
// see comment above for actions taken.
handlePLAYERELEMENTS((SOCPlayerElements) mes);
break;
case SOCMessage.RESOURCECOUNT:
handlePLAYERELEMENT(null, ((SOCResourceCount) mes).getPlayerNumber(), SOCPlayerElement.SET, SOCPlayerElement.RESOURCE_COUNT, ((SOCResourceCount) mes).getCount());
break;
case SOCMessage.DICERESULT:
game.setCurrentDice(((SOCDiceResult) mes).getResult());
break;
case SOCMessage.PUTPIECE:
handlePUTPIECE_updateGameData((SOCPutPiece) mes);
// For initial roads, also tracks their initial settlement in SOCPlayerTracker.
break;
case SOCMessage.MOVEPIECE:
{
SOCMovePiece mpm = (SOCMovePiece) mes;
SOCShip sh = new SOCShip(game.getPlayer(mpm.getPlayerNumber()), mpm.getFromCoord(), null);
game.moveShip(sh, mpm.getToCoord());
}
break;
case SOCMessage.CANCELBUILDREQUEST:
handleCANCELBUILDREQUEST((SOCCancelBuildRequest) mes);
break;
case SOCMessage.MOVEROBBER:
{
//
// Note: Don't call ga.moveRobber() because that will call the
// functions to do the stealing. We just want to set where
// the robber moved, without seeing if something was stolen.
// MOVEROBBER will be followed by PLAYERELEMENT messages to
// report the gain/loss of resources.
//
moveRobberOnSeven = false;
final int newHex = ((SOCMoveRobber) mes).getCoordinates();
if (newHex >= 0)
game.getBoard().setRobberHex(newHex, true);
else
((SOCBoardLarge) game.getBoard()).setPirateHex(-newHex, true);
}
break;
case SOCMessage.MAKEOFFER:
if (robotParameters.getTradeFlag() == 1)
handleMAKEOFFER((SOCMakeOffer) mes);
break;
case SOCMessage.CLEAROFFER:
if (robotParameters.getTradeFlag() == 1) {
final int pn = ((SOCClearOffer) mes).getPlayerNumber();
if (pn != -1) {
game.getPlayer(pn).setCurrentOffer(null);
} else {
for (int i = 0; i < game.maxPlayers; ++i) game.getPlayer(i).setCurrentOffer(null);
}
}
break;
case SOCMessage.ACCEPTOFFER:
if (waitingForTradeResponse && (robotParameters.getTradeFlag() == 1)) {
if ((ourPlayerNumber == (((SOCAcceptOffer) mes).getOfferingNumber())) || (ourPlayerNumber == ((SOCAcceptOffer) mes).getAcceptingNumber())) {
waitingForTradeResponse = false;
}
}
break;
case SOCMessage.REJECTOFFER:
if (robotParameters.getTradeFlag() == 1)
handleREJECTOFFER((SOCRejectOffer) mes);
break;
case SOCMessage.DEVCARDACTION:
{
SOCDevCardAction dcMes = (SOCDevCardAction) mes;
if (dcMes.getAction() != SOCDevCardAction.CANNOT_PLAY) {
handleDEVCARDACTION(dcMes);
} else {
// rejected by server, can't play our requested card
rejectedPlayDevCardType = dcMes.getCardType();
waitingForGameState = false;
expectPLACING_FREE_ROAD1 = false;
expectWAITING_FOR_DISCOVERY = false;
expectWAITING_FOR_MONOPOLY = false;
expectPLACING_ROBBER = false;
}
}
break;
case SOCMessage.SIMPLEREQUEST:
if (ourTurn && waitingForSC_PIRI_FortressRequest) {
final SOCSimpleRequest rqMes = (SOCSimpleRequest) mes;
if ((rqMes.getRequestType() == SOCSimpleRequest.SC_PIRI_FORT_ATTACK) && (rqMes.getPlayerNumber() == -1)) {
// Attack request was denied: End our turn now.
// Reset method sets waitingForGameState, which will bypass
// any further actions in the run() loop body.
waitingForSC_PIRI_FortressRequest = false;
resetFieldsAtEndTurn();
client.endTurn(game);
}
// else, from another player; we can ignore it
}
break;
case SOCMessage.SIMPLEACTION:
switch(((SOCSimpleAction) mes).getActionType()) {
case SOCSimpleAction.SC_PIRI_FORT_ATTACK_RESULT:
if (ourTurn && waitingForSC_PIRI_FortressRequest) {
// Our player has won or lost an attack on a pirate fortress.
// When we receive this message, other messages have already
// been sent to update related game state. End our turn now.
// Reset method sets waitingForGameState, which will bypass
// any further actions in the run() loop body.
waitingForSC_PIRI_FortressRequest = false;
resetFieldsAtEndTurn();
// client.endTurn not needed; making the attack implies sending endTurn
}
break;
}
break;
case SOCMessage.INVENTORYITEMACTION:
if (((SOCInventoryItemAction) mes).action == SOCInventoryItemAction.CANNOT_PLAY) {
final List<SOCInventoryItem> itms = ourPlayerData.getInventory().getByStateAndType(SOCInventory.PLAYABLE, ((SOCInventoryItemAction) mes).itemType);
if (itms != null)
// any item of same type# is similar enough here
rejectedPlayInvItem = itms.get(0);
waitingForGameState = false;
// in case was rejected placement (SC_FTRI gift port, etc)
expectPLACING_INV_ITEM = false;
}
break;
}
// switch(mesType)
debugInfo();
if ((game.getGameState() == SOCGame.ROLL_OR_CARD) && !waitingForGameState) {
rollOrPlayKnightOrExpectDice();
// On our turn, ask client to roll dice or play a knight;
// on other turns, update flags to expect dice result.
// Clears expectROLL_OR_CARD to false.
// Sets either expectDICERESULT, or expectPLACING_ROBBER and waitingForGameState.
}
if (ourTurn && (game.getGameState() == SOCGame.WAITING_FOR_ROBBER_OR_PIRATE) && !waitingForGameState) {
// TODO handle moving the pirate too
// For now, always decide to move the robber.
// Once we move the robber, will also need to deal with state WAITING_FOR_ROB_CLOTH_OR_RESOURCE.
expectPLACING_ROBBER = true;
waitingForGameState = true;
counter = 0;
client.choosePlayer(game, SOCChoosePlayer.CHOICE_MOVE_ROBBER);
pause(200);
} else if ((game.getGameState() == SOCGame.PLACING_ROBBER) && !waitingForGameState) {
expectPLACING_ROBBER = false;
if ((!waitingForOurTurn) && ourTurn) {
if (!((expectROLL_OR_CARD || expectPLAY1) && (counter < 4000))) {
if (moveRobberOnSeven) {
// robber moved because 7 rolled on dice
moveRobberOnSeven = false;
waitingForGameState = true;
counter = 0;
expectPLAY1 = true;
} else {
waitingForGameState = true;
counter = 0;
if (oldGameState == SOCGame.ROLL_OR_CARD) {
// robber moved from playing knight card before dice roll
expectROLL_OR_CARD = true;
} else if (oldGameState == SOCGame.PLAY1) {
// robber moved from playing knight card after dice roll
expectPLAY1 = true;
}
}
counter = 0;
moveRobber();
}
}
}
if ((game.getGameState() == SOCGame.WAITING_FOR_DISCOVERY) && !waitingForGameState) {
expectWAITING_FOR_DISCOVERY = false;
if ((!waitingForOurTurn) && ourTurn) {
if (!(expectPLAY1) && (counter < 4000)) {
waitingForGameState = true;
expectPLAY1 = true;
counter = 0;
client.pickResources(game, resourceChoices);
pause(1500);
}
}
}
if ((game.getGameState() == SOCGame.WAITING_FOR_MONOPOLY) && !waitingForGameState) {
expectWAITING_FOR_MONOPOLY = false;
if ((!waitingForOurTurn) && ourTurn) {
if (!(expectPLAY1) && (counter < 4000)) {
waitingForGameState = true;
expectPLAY1 = true;
counter = 0;
client.pickResourceType(game, monopolyStrategy.getMonopolyChoice());
pause(1500);
}
}
}
if (ourTurn && (!waitingForOurTurn) && (game.getGameState() == SOCGame.PLACING_INV_ITEM) && (!waitingForGameState)) {
// choose and send a placement location
planAndPlaceInvItem();
}
if (waitingForTradeMsg && (mesType == SOCMessage.BANKTRADE) && (((SOCBankTrade) mes).getPlayerNumber() == ourPlayerNumber)) {
//
// This is the bank/port trade confirmation announcement we've been waiting for
//
waitingForTradeMsg = false;
}
if (waitingForDevCard && (mesType == SOCMessage.SIMPLEACTION) && (((SOCSimpleAction) mes).getPlayerNumber() == ourPlayerNumber) && (((SOCSimpleAction) mes).getActionType() == SOCSimpleAction.DEVCARD_BOUGHT)) {
//
// This is the "dev card bought" message we've been waiting for
//
waitingForDevCard = false;
}
/**
* Planning: If our turn and not waiting for something,
* it's time to decide to build or take other normal actions.
*/
if (((game.getGameState() == SOCGame.PLAY1) || (game.getGameState() == SOCGame.SPECIAL_BUILDING)) && !(waitingForGameState || waitingForTradeMsg || waitingForTradeResponse || waitingForDevCard || expectPLACING_ROAD || expectPLACING_SETTLEMENT || expectPLACING_CITY || expectPLACING_SHIP || expectPLACING_FREE_ROAD1 || expectPLACING_FREE_ROAD2 || expectPLACING_ROBBER || expectWAITING_FOR_DISCOVERY || expectWAITING_FOR_MONOPOLY || waitingForSC_PIRI_FortressRequest || (waitingForPickSpecialItem != null))) {
expectPLAY1 = false;
// during other players' turns.
if ((!ourTurn) && waitingForOurTurn && gameIs6Player && (!decidedIfSpecialBuild) && (!expectPLACING_ROBBER)) {
decidedIfSpecialBuild = true;
if (buildingPlan.empty() && (ourPlayerData.getResources().getTotal() > 1) && (failedBuildingAttempts < MAX_DENIED_BUILDING_PER_TURN)) {
planBuilding();
if (!buildingPlan.empty()) {
// If we have the resources right now, ask to Special Build
final SOCPossiblePiece targetPiece = buildingPlan.peek();
final SOCResourceSet targetResources = targetPiece.getResourcesToBuild();
if ((ourPlayerData.getResources().contains(targetResources))) {
// Ask server for the Special Building Phase.
// (TODO) if FAST_STRATEGY: Maybe randomly don't ask, to lower opponent difficulty?
waitingForSpecialBuild = true;
client.buildRequest(game, -1);
pause(100);
}
}
}
}
if ((!waitingForOurTurn) && ourTurn) {
if (!(expectROLL_OR_CARD && (counter < 4000))) {
counter = 0;
// D.ebugPrintln("DOING PLAY1");
if (D.ebugOn) {
client.sendText(game, "================================");
// for each player in game:
// sendText and debug-prn game.getPlayer(i).getResources()
printResources();
}
/**
* if we haven't played a dev card yet,
* and we have a knight, and we can get
* largest army, play the knight.
* If we're in SPECIAL_BUILDING (not PLAY1),
* can't trade or play development cards.
*
* In scenario _SC_PIRI (which has no robber and
* no largest army), play one whenever we have
* it, someone else has resources, and we can
* convert a ship to a warship.
*/
if ((game.getGameState() == SOCGame.PLAY1) && !ourPlayerData.hasPlayedDevCard()) {
// might set expectPLACING_ROBBER and waitingForGameState
playKnightCardIfShould();
}
/**
* make a plan if we don't have one,
* and if we haven't given up building
* attempts this turn.
*/
if ((!expectPLACING_ROBBER) && buildingPlan.empty() && (ourPlayerData.getResources().getTotal() > 1) && (failedBuildingAttempts < MAX_DENIED_BUILDING_PER_TURN)) {
planBuilding();
/*
* planBuilding takes these actions, sets buildingPlan and other fields
* (see its javadoc):
*
decisionMaker.planStuff(robotParameters.getStrategyType());
if (! buildingPlan.empty())
{
lastTarget = (SOCPossiblePiece) buildingPlan.peek();
negotiator.setTargetPiece(ourPlayerNumber, buildingPlan.peek());
}
*/
}
// D.ebugPrintln("DONE PLANNING");
if ((!expectPLACING_ROBBER) && (!buildingPlan.empty())) {
// Time to build something.
// Either ask to build a piece, or use trading or development
// cards to get resources to build it. See javadoc for flags set
// (expectPLACING_ROAD, etc). In a future iteration of the run loop
// with the expected PLACING_ state, we'll build whatWeWantToBuild
// in placeIfExpectPlacing().
buildOrGetResourceByTradeOrCard();
}
/**
* see if we're done with our turn
*/
if (!(expectPLACING_SETTLEMENT || expectPLACING_FREE_ROAD1 || expectPLACING_FREE_ROAD2 || expectPLACING_ROAD || expectPLACING_CITY || expectPLACING_SHIP || expectWAITING_FOR_DISCOVERY || expectWAITING_FOR_MONOPOLY || expectPLACING_ROBBER || waitingForTradeMsg || waitingForTradeResponse || waitingForDevCard || waitingForGameState || (waitingForPickSpecialItem != null))) {
// Any last things for turn from game's scenario?
boolean scenActionTaken = false;
if (game.isGameOptionSet(SOCGameOption.K_SC_FTRI) || game.isGameOptionSet(SOCGameOption.K_SC_PIRI)) {
// possibly attack pirate fortress
// or place a gift port for better bank trades
scenActionTaken = considerScenarioTurnFinalActions();
}
if (!scenActionTaken) {
resetFieldsAtEndTurn();
/*
* These state fields are reset:
*
waitingForGameState = true;
counter = 0;
expectROLL_OR_CARD = true;
waitingForOurTurn = true;
doneTrading = (robotParameters.getTradeFlag() != 1);
//D.ebugPrintln("!!! ENDING TURN !!!");
negotiator.resetIsSelling();
negotiator.resetOffersMade();
buildingPlan.clear();
negotiator.resetTargetPieces();
*/
pause(1500);
client.endTurn(game);
}
}
}
}
}
/**
* Placement: Make various putPiece calls; server has told us it's OK to buy them.
* Call client.putPiece.
* Works when it's our turn and we have an expect flag set
* (such as expectPLACING_SETTLEMENT, in these game states:
* START1A - START2B or - START3B
* PLACING_SETTLEMENT, PLACING_ROAD, PLACING_CITY
* PLACING_FREE_ROAD1, PLACING_FREE_ROAD2
*/
if (!waitingForGameState) {
placeIfExpectPlacing();
}
/**
* Handle various message types here at bottom of loop.
*/
switch(mesType) {
case SOCMessage.PUTPIECE:
/**
* this is for player tracking
*
* For initial placement of our own pieces, also checks
* and clears expectPUTPIECE_FROM_START1A,
* and sets expectSTART1B, etc. The final initial putpiece
* clears expectPUTPIECE_FROM_START2B and sets expectROLL_OR_CARD.
*/
{
final SOCPutPiece mpp = (SOCPutPiece) mes;
final int pn = mpp.getPlayerNumber();
final int coord = mpp.getCoordinates();
final int pieceType = mpp.getPieceType();
handlePUTPIECE_updateTrackers(pn, coord, pieceType);
}
break;
case SOCMessage.MOVEPIECE:
/**
* this is for player tracking of moved ships
*/
{
final SOCMovePiece mpp = (SOCMovePiece) mes;
final int pn = mpp.getPlayerNumber();
final int coord = mpp.getToCoord();
final int pieceType = mpp.getPieceType();
// TODO what about getFromCoord()?
handlePUTPIECE_updateTrackers(pn, coord, pieceType);
}
break;
case SOCMessage.DICERESULT:
if (expectDICERESULT) {
expectDICERESULT = false;
if (((SOCDiceResult) mes).getResult() == 7) {
final boolean robWithoutRobber = game.isGameOptionSet(SOCGameOption.K_SC_PIRI);
if (!robWithoutRobber)
moveRobberOnSeven = true;
if (ourPlayerData.getResources().getTotal() > 7)
expectDISCARD = true;
else if (ourTurn) {
if (!robWithoutRobber)
expectPLACING_ROBBER = true;
else
expectPLAY1 = true;
}
} else {
expectPLAY1 = true;
}
}
break;
case SOCMessage.SIMPLEREQUEST:
// These messages can almost always be ignored by bots.
// Some request types are handled at the top of the loop body;
// search for SOCMessage.SIMPLEREQUEST
{
final SOCSimpleRequest rqMes = (SOCSimpleRequest) mes;
switch(rqMes.getRequestType()) {
case SOCSimpleRequest.PROMPT_PICK_RESOURCES:
// gold hex
counter = 0;
pickFreeResources(rqMes.getValue1());
waitingForGameState = true;
if (game.isInitialPlacement()) {
if (game.isGameOptionSet(SOCGameOption.K_SC_3IP))
expectSTART3B = true;
else
expectSTART2B = true;
} else {
expectPLAY1 = true;
}
break;
}
}
break;
case SOCMessage.DISCARDREQUEST:
expectDISCARD = false;
// {
if ((game.getCurrentDice() == 7) && ourTurn) {
if (!game.isGameOptionSet(SOCGameOption.K_SC_PIRI))
expectPLACING_ROBBER = true;
else
expectPLAY1 = true;
} else {
expectPLAY1 = true;
}
counter = 0;
client.discard(game, DiscardStrategy.discard(((SOCDiscardRequest) mes).getNumberOfDiscards(), buildingPlan, rand, ourPlayerData, robotParameters, decisionMaker, negotiator));
// }
break;
case SOCMessage.CHOOSEPLAYERREQUEST:
{
final int choicePl = RobberStrategy.chooseRobberVictim(((SOCChoosePlayerRequest) mes).getChoices(), game, playerTrackers);
counter = 0;
client.choosePlayer(game, choicePl);
}
break;
case SOCMessage.CHOOSEPLAYER:
{
final int vpn = ((SOCChoosePlayer) mes).getChoice();
// Cloth is more valuable.
// TODO decide when we should choose resources instead
client.choosePlayer(game, -(vpn + 1));
}
break;
case SOCMessage.SETSPECIALITEM:
if (waitingForPickSpecialItem != null) {
final SOCSetSpecialItem siMes = (SOCSetSpecialItem) mes;
if (siMes.typeKey.equals(waitingForPickSpecialItem)) {
switch(siMes.op) {
case SOCSetSpecialItem.OP_PICK:
waitingForPickSpecialItem = null;
// Any specific action needed? Not for SC_WOND.
break;
case SOCSetSpecialItem.OP_DECLINE:
waitingForPickSpecialItem = null;
// TODO how to prevent asking again? (similar to whatWeFailedtoBuild)
break;
}
}
}
break;
case SOCMessage.ROBOTDISMISS:
if ((!expectDISCARD) && (!expectPLACING_ROBBER)) {
client.leaveGame(game, "dismiss msg", false, false);
alive = false;
}
break;
case SOCMessage.TIMINGPING:
// Once-per-second message from the pinger thread
counter++;
break;
}
if (ourTurn && (counter > 15000)) {
// We've been waiting too long, must be a bug: Leave the game.
// This is a fallback, server has SOCForceEndTurnThread which
// should have already taken action.
// Before v1.1.20, would leave game even during other (human) players' turns.
client.leaveGame(game, "counter 15000", true, false);
alive = false;
}
if ((failedBuildingAttempts > (2 * MAX_DENIED_BUILDING_PER_TURN)) && game.isInitialPlacement()) {
// Apparently can't decide where we can initially place:
// Leave the game.
client.leaveGame(game, "failedBuildingAttempts at start", true, false);
alive = false;
}
/*
if (D.ebugOn) {
if (mes != null) {
debugInfo();
D.ebugPrintln("~~~~~~~~~~~~~~~~");
}
}
*/
yield();
} catch (Exception e) {
// Print exception; ignore errors due to game reset in another thread
if (alive && ((game == null) || (game.getGameState() != SOCGame.RESET_OLD))) {
// TODO end our turn if too many
++turnExceptionCount;
String eMsg = (turnExceptionCount == 1) ? "*** Robot caught an exception - " + e : "*** Robot caught an exception (" + turnExceptionCount + " this turn) - " + e;
D.ebugPrintln(eMsg);
System.out.println(eMsg);
e.printStackTrace();
}
}
}
} else {
System.out.println("AGG! NO PINGER!");
}
// D.ebugPrintln("STOPPING AND DEALLOCATING");
gameEventQ = null;
client.addCleanKill();
client = null;
game = null;
ourPlayerData = null;
dummyCancelPlayerData = null;
whatWeWantToBuild = null;
whatWeFailedToBuild = null;
rejectedPlayInvItem = null;
resourceChoices = null;
ourPlayerTracker = null;
playerTrackers = null;
pinger.stopPinger();
pinger = null;
}
use of soc.game.SOCInventoryItem in project JSettlers2 by jdmonin.
the class SOCRobotBrain method considerScenarioTurnFinalActions.
/**
* Look for and take any scenario-specific final actions before ending the turn.
*<P>
* For example, {@link SOCGameOption#K_SC_PIRI _SC_PIRI} will check if we've reached the fortress
* and have 5 or more warships, and if so will attack the fortress. Doing so ends the turn, so
* we don't try to attack before end of turn.
*<P>
* {@link SOCGameOption#K_SC_FTRI _SC_FTRI} can play a gift port from our inventory to place for
* better bank trades.
*<P>
* <B>NOTE:</B> For now this method assumes it's called only in the {@code SC_FTRI} or {@code SC_PIRI} scenario.
* Caller must check the game for any relevant scenario SOCGameOptions before calling.
* Also assumes not {@link #waitingForGameState} or any other pending action.
*
* @return true if an action was taken <B>and</B> turn shouldn't be ended yet, false otherwise
* @since 2.0.00
*/
private boolean considerScenarioTurnFinalActions() {
if (game.isGameOptionSet(SOCGameOption.K_SC_FTRI)) {
// SC_FTRI
// check inventory for gift ports
SOCInventoryItem itm = null;
for (SOCInventoryItem i : ourPlayerData.getInventory().getByState(SOCInventory.PLAYABLE)) {
if (i.itype > 0)
// not a port; most likely a SOCDevCard
continue;
if ((rejectedPlayInvItem != null) && (i.itype == rejectedPlayInvItem.itype))
continue;
itm = i;
// unlikely to have more than one in inventory
break;
}
if (itm != null) {
// Do we have somewhere to place one?
if (ourPlayerData.getPortMovePotentialLocations(false) == null)
return false;
// Set fields, make the request
return planAndPlaceInvItemPlacement_SC_FTRI(itm);
}
} else {
// require 5+ warships; game.canAttackPirateFortress checks that we've reached the fortress with adjacent ship
if ((ourPlayerData.getNumWarships() < 5) || (null == game.canAttackPirateFortress()))
return false;
waitingForSC_PIRI_FortressRequest = true;
client.simpleRequest(game, ourPlayerNumber, SOCSimpleRequest.SC_PIRI_FORT_ATTACK, 0, 0);
return true;
}
return false;
}
use of soc.game.SOCInventoryItem in project JSettlers2 by jdmonin.
the class SOCBoardPanel method drawBoard_SC_FTRI_placePort.
/**
* Scenario game option {@link SOCGameOption#K_SC_FTRI _SC_FTRI}: In board mode {@link #SC_FTRI_PLACE_PORT},
* draw the possible coastal edges where the port can be placed, and if the {@link #hilight} cursor is at
* such an edge, draw the port semi-transparently and a solid hilight line at the edge.
* @since 2.0.00
*/
private final void drawBoard_SC_FTRI_placePort(Graphics g) {
drawSeaEdgeLines(g, Color.WHITE, player.getPortMovePotentialLocations(true));
if (hilight == 0)
return;
// Draw the placing port semi-transparently if graphics support it.
// Draw hilight line with some thickness if possible.
int edge = hilight;
if (edge == -1)
edge = 0;
final SOCInventoryItem portItem = game.getPlacingItem();
if (portItem != null) {
// draw the port; similar code to drawPorts_largeBoard
final int landFacing = ((SOCBoardLarge) board).getPortFacingFromEdge(edge);
final int landHexCoord = board.getAdjacentHexToEdge(edge, landFacing);
int px = halfdeltaX * ((landHexCoord & 0xFF) - 1);
int py = halfdeltaY * (landHexCoord >> 8);
// now move 1 hex "backwards" from that hex's upper-left corner
px -= DELTAX_FACING[landFacing];
py -= DELTAY_FACING[landFacing];
final Composite prevComposite;
if (g instanceof Graphics2D) {
prevComposite = ((Graphics2D) g).getComposite();
((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f));
} else {
prevComposite = null;
}
drawHex(g, px, py, -portItem.itype, landFacing, -1);
if (prevComposite != null)
((Graphics2D) g).setComposite(prevComposite);
}
final Stroke prevStroke;
if (g instanceof Graphics2D) {
prevStroke = ((Graphics2D) g).getStroke();
((Graphics2D) g).setStroke(new BasicStroke(2.5f));
} else {
prevStroke = null;
}
g.setColor(Color.WHITE);
drawSeaEdgeLine(g, edge);
if (prevStroke != null)
((Graphics2D) g).setStroke(prevStroke);
}
use of soc.game.SOCInventoryItem in project JSettlers2 by jdmonin.
the class SOCHandPanel method updateDevCards.
/**
* Update the displayed list of player's development cards and other inventory items,
* and enable or disable the "Play Card" button.
*<P>
* Enables the "Play Card" button for {@link SOCInventory#PLAYABLE PLAYABLE} cards,
* and also for {@link SOCInventory#KEPT KEPT} cards (VP cards) so the user can
* pick those and get a message that that they've already been played, instead of
* wondering why they're listed but can't be played.
*<P>
* Updates {@link #inventory} and {@link #inventoryItems} to keep them in sync.
* @param addedPlayable True if the update added a dev card or item that's playable now
*/
public void updateDevCards(final boolean addedPlayable) {
SOCInventory items = player.getInventory();
boolean hasOldCards = false;
synchronized (inventory.getTreeLock()) {
inventory.removeAll();
inventoryItems.clear();
if (addedPlayable && !inventory.isEnabled())
// can become disabled in game state PLACING_INV_ITEM
inventory.setEnabled(true);
// show all new cards first, then all playable, then all kept (VP cards)
for (int cState = SOCInventory.NEW; cState <= SOCInventory.KEPT; ++cState) {
final boolean isNew = (cState == SOCInventory.NEW);
for (// almost always instanceof SOCDevCard
final SOCInventoryItem item : // almost always instanceof SOCDevCard
items.getByState(cState)) {
if (isNew) {
inventory.add(DEVCARD_NEW + item.getItemName(game, false, strings));
} else {
inventory.add(item.getItemName(game, false, strings));
hasOldCards = true;
}
inventoryItems.add(item);
}
}
}
playCardBut.setEnabled(hasOldCards && playerIsCurrent);
}
Aggregations