use of soc.game.SOCPlayingPiece in project JSettlers2 by jdmonin.
the class SOCGameMessageHandler method handlePUTPIECE.
/**
* handle "put piece" message.
*<P>
* Because the current player changes during initial placement,
* this method has a simplified version of some of the logic from
* {@link SOCGameHandler#endGameTurn(SOCGame, SOCPlayer, boolean)}
* to detect and announce the new turn.
*
* @param c the connection that sent the message
* @param mes the message
* @since 1.0.0
*/
private void handlePUTPIECE(SOCGame ga, Connection c, SOCPutPiece mes) {
ga.takeMonitor();
try {
final String gaName = ga.getName();
final String plName = c.getData();
SOCPlayer player = ga.getPlayer(plName);
/**
* make sure the player can do it
*/
if (handler.checkTurn(c, ga)) {
boolean sendDenyReply = false;
/*
if (D.ebugOn) {
D.ebugPrintln("BEFORE");
for (int pn = 0; pn < SOCGame.MAXPLAYERS; pn++) {
SOCPlayer tmpPlayer = ga.getPlayer(pn);
D.ebugPrintln("Player # "+pn);
for (int i = 0x22; i < 0xCC; i++) {
if (tmpPlayer.isPotentialRoad(i))
D.ebugPrintln("### POTENTIAL ROAD AT "+Integer.toHexString(i));
}
}
}
*/
int gameState = ga.getGameState();
final int coord = mes.getCoordinates();
final int pieceType = mes.getPieceType();
final int pn = player.getPlayerNumber();
final boolean isBuyAndPut = (gameState == SOCGame.PLAY1) || (gameState == SOCGame.SPECIAL_BUILDING);
if (isBuyAndPut) {
if (!handleBUILDREQUEST(ga, player, c, pieceType, false)) {
// <--- Can't build right now ---
return;
// will call ga.releaseMonitor() in finally-block before returning
}
// updated by handleBUILDREQUEST
gameState = ga.getGameState();
}
switch(pieceType) {
case SOCPlayingPiece.ROAD:
if ((gameState == SOCGame.START1B) || (gameState == SOCGame.START2B) || (gameState == SOCGame.START3B) || (gameState == SOCGame.PLACING_ROAD) || (gameState == SOCGame.PLACING_FREE_ROAD1) || (gameState == SOCGame.PLACING_FREE_ROAD2)) {
if (player.isPotentialRoad(coord) && (player.getNumPieces(SOCPlayingPiece.ROAD) >= 1)) {
final SOCRoad rd = new SOCRoad(player, coord, null);
// Changes game state and (if initial placement) player
ga.putPiece(rd);
// If placing this piece reveals a fog hex, putPiece will call srv.gameEvent
// which will send a SOCRevealFogHex message to the game.
/*
if (D.ebugOn) {
D.ebugPrintln("AFTER");
for (int pn = 0; pn < SOCGame.MAXPLAYERS; pn++) {
SOCPlayer tmpPlayer = ga.getPlayer(pn);
D.ebugPrintln("Player # "+pn);
for (int i = 0x22; i < 0xCC; i++) {
if (tmpPlayer.isPotentialRoad(i))
D.ebugPrintln("### POTENTIAL ROAD AT "+Integer.toHexString(i));
}
}
}
*/
srv.gameList.takeMonitorForGame(gaName);
// "Joe built a road."
srv.messageToGameKeyed(ga, false, "action.built.road", plName);
srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, pn, SOCPlayingPiece.ROAD, coord));
if (!ga.pendingMessagesOut.isEmpty())
handler.sendGamePendingMessages(ga, false);
srv.gameList.releaseMonitorForGame(gaName);
// If needed, call sendTurn or send SOCRollDicePrompt
handler.sendTurnStateAtInitialPlacement(ga, player, c, gameState);
int newState = ga.getGameState();
if ((newState == SOCGame.STARTS_WAITING_FOR_PICK_GOLD_RESOURCE) || (newState == SOCGame.WAITING_FOR_PICK_GOLD_RESOURCE)) {
// gold hex revealed from fog (scenario SC_FOG)
handler.sendGameState_sendGoldPickAnnounceText(ga, gaName, c, null);
}
} else {
D.ebugPrintln("ILLEGAL ROAD: 0x" + Integer.toHexString(coord) + ": player " + pn);
if (player.isRobot() && D.ebugOn) {
D.ebugPrintln(" - pl.isPotentialRoad: " + player.isPotentialRoad(coord));
SOCPlayingPiece pp = ga.getBoard().roadAtEdge(coord);
D.ebugPrintln(" - roadAtEdge: " + ((pp != null) ? pp : "none"));
}
srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.there.road");
// "You can't build a road there."
sendDenyReply = true;
}
} else {
srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.now.road");
// "You can't build a road now."
}
break;
case SOCPlayingPiece.SETTLEMENT:
if ((gameState == SOCGame.START1A) || (gameState == SOCGame.START2A) || (gameState == SOCGame.START3A) || (gameState == SOCGame.PLACING_SETTLEMENT)) {
if (player.canPlaceSettlement(coord) && (player.getNumPieces(SOCPlayingPiece.SETTLEMENT) >= 1)) {
final SOCSettlement se = new SOCSettlement(player, coord, null);
// Changes game state and (if initial placement) player
ga.putPiece(se);
srv.gameList.takeMonitorForGame(gaName);
// "Joe built a settlement."
srv.messageToGameKeyed(ga, false, "action.built.stlmt", plName);
srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, pn, SOCPlayingPiece.SETTLEMENT, coord));
if (!ga.pendingMessagesOut.isEmpty())
handler.sendGamePendingMessages(ga, false);
srv.gameList.releaseMonitorForGame(gaName);
// Check player and send new game state
if (!handler.checkTurn(c, ga))
// Announce new state and new current player
handler.sendTurn(ga, false);
else
handler.sendGameState(ga);
if (ga.hasSeaBoard && (ga.getGameState() == SOCGame.STARTS_WAITING_FOR_PICK_GOLD_RESOURCE)) {
// Prompt to pick from gold: send text and SOCSimpleRequest(PROMPT_PICK_RESOURCES)
handler.sendGameState_sendGoldPickAnnounceText(ga, gaName, c, null);
}
} else {
D.ebugPrintln("ILLEGAL SETTLEMENT: 0x" + Integer.toHexString(coord) + ": player " + pn);
if (player.isRobot() && D.ebugOn) {
D.ebugPrintln(" - pl.isPotentialSettlement: " + player.isPotentialSettlement(coord));
SOCPlayingPiece pp = ga.getBoard().settlementAtNode(coord);
D.ebugPrintln(" - settlementAtNode: " + ((pp != null) ? pp : "none"));
}
srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.there.stlmt");
// "You can't build a settlement there."
sendDenyReply = true;
}
} else {
srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.now.stlmt");
// "You can't build a settlement now."
}
break;
case SOCPlayingPiece.CITY:
if (gameState == SOCGame.PLACING_CITY) {
if (player.isPotentialCity(coord) && (player.getNumPieces(SOCPlayingPiece.CITY) >= 1)) {
boolean houseRuleFirstCity = ga.isGameOptionSet("N7C") && !ga.hasBuiltCity();
if (houseRuleFirstCity && ga.isGameOptionSet("N7") && (ga.getRoundCount() < ga.getGameOptionIntValue("N7"))) {
// If "No 7s for first # rounds" is active, and this isn't its last round, 7s won't
// be rolled soon: Don't announce "Starting next turn, dice rolls of 7 may occur"
houseRuleFirstCity = false;
}
final SOCCity ci = new SOCCity(player, coord, null);
// changes game state and maybe player
ga.putPiece(ci);
srv.gameList.takeMonitorForGame(gaName);
// "Joe built a city."
srv.messageToGameKeyed(ga, false, "action.built.city", plName);
srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, pn, SOCPlayingPiece.CITY, coord));
if (!ga.pendingMessagesOut.isEmpty())
handler.sendGamePendingMessages(ga, false);
if (houseRuleFirstCity)
srv.messageToGameKeyed(ga, false, "action.built.nextturn.7.houserule");
// "Starting next turn, dice rolls of 7 may occur (house rule)."
srv.gameList.releaseMonitorForGame(gaName);
// Check player and send new game state
if (!handler.checkTurn(c, ga))
// Announce new state and new current player
handler.sendTurn(ga, false);
else
handler.sendGameState(ga);
} else {
D.ebugPrintln("ILLEGAL CITY: 0x" + Integer.toHexString(coord) + ": player " + pn);
if (player.isRobot() && D.ebugOn) {
D.ebugPrintln(" - pl.isPotentialCity: " + player.isPotentialCity(coord));
SOCPlayingPiece pp = ga.getBoard().settlementAtNode(coord);
D.ebugPrintln(" - city/settlementAtNode: " + ((pp != null) ? pp : "none"));
}
srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.there.city");
// "You can't build a city there."
sendDenyReply = true;
}
} else {
srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.now.city");
// "You can't build a city now."
}
break;
case SOCPlayingPiece.SHIP:
if ((gameState == SOCGame.START1B) || (gameState == SOCGame.START2B) || (gameState == SOCGame.START3B) || (gameState == SOCGame.PLACING_SHIP) || (gameState == SOCGame.PLACING_FREE_ROAD1) || (gameState == SOCGame.PLACING_FREE_ROAD2)) {
// Place it if we can; canPlaceShip checks potentials and pirate ship location
if (ga.canPlaceShip(player, coord) && (player.getNumPieces(SOCPlayingPiece.SHIP) >= 1)) {
final SOCShip sh = new SOCShip(player, coord, null);
// Changes game state and (during initial placement) sometimes player
ga.putPiece(sh);
srv.gameList.takeMonitorForGame(gaName);
// "Joe built a ship."
srv.messageToGameKeyed(ga, false, "action.built.ship", plName);
srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, pn, SOCPlayingPiece.SHIP, coord));
if (!ga.pendingMessagesOut.isEmpty())
handler.sendGamePendingMessages(ga, false);
srv.gameList.releaseMonitorForGame(gaName);
// If needed, call sendTurn or send SOCRollDicePrompt
handler.sendTurnStateAtInitialPlacement(ga, player, c, gameState);
int newState = ga.getGameState();
if ((newState == SOCGame.STARTS_WAITING_FOR_PICK_GOLD_RESOURCE) || (newState == SOCGame.WAITING_FOR_PICK_GOLD_RESOURCE)) {
// gold hex revealed from fog (scenario SC_FOG)
handler.sendGameState_sendGoldPickAnnounceText(ga, gaName, c, null);
}
} else {
D.ebugPrintln("ILLEGAL SHIP: 0x" + Integer.toHexString(coord) + ": player " + pn);
if (player.isRobot() && D.ebugOn) {
D.ebugPrintln(" - pl.isPotentialShip: " + player.isPotentialShip(coord));
SOCPlayingPiece pp = ga.getBoard().roadAtEdge(coord);
D.ebugPrintln(" - ship/roadAtEdge: " + ((pp != null) ? pp : "none"));
}
srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.there.ship");
// "You can't build a ship there."
sendDenyReply = true;
}
} else {
srv.messageToPlayerKeyed(c, gaName, "action.build.cannot.now.ship");
// "You can't build a ship now."
}
break;
}
if (sendDenyReply) {
if (isBuyAndPut)
// is probably now PLACING_*, was PLAY1 or SPECIAL_BUILDING
handler.sendGameState(ga);
srv.messageToPlayer(c, new SOCCancelBuildRequest(gaName, mes.getPieceType()));
if (player.isRobot()) {
// Set the "force end turn soon" field
ga.lastActionTime = 0L;
}
}
} else {
// "It's not your turn."
srv.messageToPlayerKeyed(c, gaName, "reply.not.your.turn");
}
} catch (Exception e) {
D.ebugPrintStackTrace(e, "Exception caught in handlePUTPIECE");
} finally {
ga.releaseMonitor();
}
}
use of soc.game.SOCPlayingPiece in project JSettlers2 by jdmonin.
the class SOCRobotBrain method cancelWrongPiecePlacement.
/**
* We've asked for an illegal piece placement.
* Cancel and invalidate this planned piece, make a new plan.
* If {@link SOCGame#isSpecialBuilding()}, will set variables to
* force the end of our special building turn.
* Also handles illegal requests to buy development cards
* (piece type -2 in {@link SOCCancelBuildRequest}).
*<P>
* Must update game data by calling {@link SOCGame#setGameState(int)} before calling this method.
*<P>
* This method increments {@link #failedBuildingAttempts},
* but won't leave the game if we've failed too many times.
* The brain's run loop should make that decision.
*<UL>
* <LI> If {@link SOCGame#getGameState()} is {@link SOCGame#PLAY1},
* server likely denied us due to resources, not due to building plan
* being interrupted by another player's building before our special building phase.
* (Could also be due to a bug in the chosen building plan.)
* Will clear our building plan so we'll make a new one.
* <LI> In other gamestates, assumes requested piece placement location was illegal.
* Will call {@link #cancelWrongPiecePlacementLocal(SOCPlayingPiece)}
* so we don't try again to build there.
* <LI> Either way, sends a {@link CancelBuildRequest} message to the server.
*</UL>
*
* @param mes Cancel message from server, including piece type
*/
protected void cancelWrongPiecePlacement(SOCCancelBuildRequest mes) {
// == -2
final boolean cancelBuyDevCard = (mes.getPieceType() == SOCPossiblePiece.CARD);
if (cancelBuyDevCard) {
waitingForDevCard = false;
} else {
whatWeFailedToBuild = whatWeWantToBuild;
++failedBuildingAttempts;
}
waitingForGameState = false;
final int gameState = game.getGameState();
/**
* if true, server likely denied us due to resources, not due to building plan
* being interrupted by another player's building before our special building phase.
* (Could also be due to a bug in the chosen building plan.)
*/
final boolean gameStateIsPLAY1 = (gameState == SOCGame.PLAY1);
if (!(gameStateIsPLAY1 || cancelBuyDevCard)) {
int coord = -1;
switch(gameState) {
case SOCGame.START1A:
case SOCGame.START1B:
case SOCGame.START2A:
case SOCGame.START2B:
case SOCGame.START3A:
case SOCGame.START3B:
coord = lastStartingPieceCoord;
break;
default:
if (whatWeWantToBuild != null)
coord = whatWeWantToBuild.getCoordinates();
}
if (coord != -1) {
SOCPlayingPiece cancelPiece;
/**
* First, invalidate that piece in trackers, so we don't try again to
* build it. If we treat it like another player's new placement, we
* can remove any of our planned pieces depending on this one.
*/
switch(mes.getPieceType()) {
case SOCPlayingPiece.ROAD:
cancelPiece = new SOCRoad(dummyCancelPlayerData, coord, null);
break;
case SOCPlayingPiece.SETTLEMENT:
cancelPiece = new SOCSettlement(dummyCancelPlayerData, coord, null);
break;
case SOCPlayingPiece.CITY:
cancelPiece = new SOCCity(dummyCancelPlayerData, coord, null);
break;
case SOCPlayingPiece.SHIP:
cancelPiece = new SOCShip(dummyCancelPlayerData, coord, null);
break;
default:
// To satisfy javac
cancelPiece = null;
}
cancelWrongPiecePlacementLocal(cancelPiece);
}
} else {
/**
* stop trying to build it now, but don't prevent
* us from trying later to build it.
*/
whatWeWantToBuild = null;
buildingPlan.clear();
}
if (gameStateIsPLAY1 || game.isSpecialBuilding()) {
// Shouldn't have asked to build this piece at this time.
// End our confusion by ending our current turn. Can re-plan on next turn.
failedBuildingAttempts = MAX_DENIED_BUILDING_PER_TURN;
expectPLACING_ROAD = false;
expectPLACING_SETTLEMENT = false;
expectPLACING_CITY = false;
expectPLACING_SHIP = false;
decidedIfSpecialBuild = true;
if (!cancelBuyDevCard) {
// special building, currently in state PLACING_* ;
// get our resources back, get state PLAY1 or SPECIALBUILD
waitingForGameState = true;
expectPLAY1 = true;
client.cancelBuildRequest(game, mes.getPieceType());
}
} else if (gameState <= SOCGame.START3B) {
switch(gameState) {
case SOCGame.START1A:
expectPUTPIECE_FROM_START1A = false;
expectSTART1A = true;
break;
case SOCGame.START1B:
expectPUTPIECE_FROM_START1B = false;
expectSTART1B = true;
break;
case SOCGame.START2A:
expectPUTPIECE_FROM_START2A = false;
expectSTART2A = true;
break;
case SOCGame.START2B:
expectPUTPIECE_FROM_START2B = false;
expectSTART2B = true;
break;
case SOCGame.START3A:
expectPUTPIECE_FROM_START3A = false;
expectSTART3A = true;
break;
case SOCGame.START3B:
expectPUTPIECE_FROM_START3B = false;
expectSTART3B = true;
break;
}
// The run loop will check if failedBuildingAttempts > (2 * MAX_DENIED_BUILDING_PER_TURN).
// This bot will leave the game there if it can't recover.
} else {
expectPLAY1 = true;
waitingForGameState = true;
counter = 0;
client.cancelBuildRequest(game, mes.getPieceType());
// Now wait for the play1 message, then can re-plan another piece.
}
}
use of soc.game.SOCPlayingPiece in project JSettlers2 by jdmonin.
the class SOCRobotDM method recalcLongestRoadETAAux.
/**
* Does a depth first search of legal possible road edges from the end point of the longest
* path connecting a graph of nodes, and returns which roads or how many roads
* would need to be built to take longest road.
*<P>
* Do not call if {@link SOCGameOption#K_SC_0RVP} is set, because
* this method needs {@link SOCPlayer#getLRPaths()} which will be empty.
*<P>
* Combined implementation for use by SOCRobotDM and {@link SOCPlayerTracker}.
*
* @param pl Calculate this player's longest road;
* typically SOCRobotDM.ourPlayerData or SOCPlayerTracker.player
* @param wantsStack If true, return the Stack; otherwise, return numRoads.
* @param startNode the path endpoint, such as from
* {@link SOCPlayer#getLRPaths()}.(i){@link SOCLRPathData#getBeginning() .getBeginning()}
* or {@link SOCLRPathData#getEnd() .getEnd()}
* @param pathLength the length of that path
* @param lrLength length of longest road in the game
* @param searchDepth how many roads out to search
*
* @return if <tt>wantsStack</tt>: a {@link Stack} containing the path of roads with the last one
* (farthest from <tt>startNode</tt>) on top, or <tt>null</tt> if it can't be done.
* If ! <tt>wantsStack</tt>: Integer: the number of roads needed, or 500 if it can't be done
*/
static Object recalcLongestRoadETAAux(SOCPlayer pl, final boolean wantsStack, final int startNode, final int pathLength, final int lrLength, final int searchDepth) {
// D.ebugPrintln("=== recalcLongestRoadETAAux("+Integer.toHexString(startNode)+","+pathLength+","+lrLength+","+searchDepth+")");
//
// We're doing a depth first search of all possible road paths.
// For similar code, see SOCPlayer.calcLongestRoad2
// Both methods rely on a stack holding NodeLenVis (pop to curNode in loop);
// they differ in actual element type within the stack because they are
// gathering slightly different results (length or a stack of edges).
//
int longest = 0;
int numRoads = 500;
Pair<NodeLenVis<Integer>, List<Integer>> bestPathNode = null;
final SOCBoard board = pl.getGame().getBoard();
Stack<Pair<NodeLenVis<Integer>, List<Integer>>> pending = new Stack<Pair<NodeLenVis<Integer>, List<Integer>>>();
// Holds as-yet unvisited nodes:
// Pair members are <NodeLenVis, null or node-coordinate list of all parents (from DFS traversal order)>.
// Lists have most-distant node at beginning (item 0), and most-immediate at end of list (n-1).
// That list is used at the end to build the returned Stack which is the road path needed.
pending.push(new Pair<NodeLenVis<Integer>, List<Integer>>(new NodeLenVis<Integer>(startNode, pathLength, new Vector<Integer>()), null));
while (!pending.empty()) {
final Pair<NodeLenVis<Integer>, List<Integer>> dataPair = pending.pop();
final NodeLenVis<Integer> curNode = dataPair.getA();
// D.ebugPrintln("curNode = "+curNode);
final int coord = curNode.node;
int len = curNode.len;
final Vector<Integer> visited = curNode.vis;
boolean pathEnd = false;
//
if (len > 0) {
final int pn = pl.getPlayerNumber();
SOCPlayingPiece p = board.settlementAtNode(coord);
if ((p != null) && (p.getPlayerNumber() != pn)) {
pathEnd = true;
// D.ebugPrintln("^^^ path end at "+Integer.toHexString(coord));
}
}
if (!pathEnd) {
//
// check if we've connected to another road graph of this player
//
Iterator<SOCLRPathData> lrPathsIter = pl.getLRPaths().iterator();
while (lrPathsIter.hasNext()) {
SOCLRPathData pathData = lrPathsIter.next();
if ((startNode != pathData.getBeginning()) && (startNode != pathData.getEnd()) && ((coord == pathData.getBeginning()) || (coord == pathData.getEnd()))) {
pathEnd = true;
len += pathData.getLength();
break;
}
}
}
if (!pathEnd) {
//
if ((len - pathLength) >= searchDepth) {
pathEnd = true;
}
// D.ebugPrintln("Reached search depth");
}
if (!pathEnd) {
/**
* For each of the 3 adjacent edges of coord's node,
* check for unvisited legal road possibilities.
* When they are found, push that edge's far-end node
* onto the pending stack.
*/
pathEnd = true;
for (int dir = 0; dir < 3; ++dir) {
int j = board.getAdjacentEdgeToNode(coord, dir);
if (pl.isLegalRoad(j)) {
final Integer edge = new Integer(j);
boolean match = false;
for (Enumeration<Integer> ev = visited.elements(); ev.hasMoreElements(); ) {
Integer vis = ev.nextElement();
if (vis.equals(edge)) {
match = true;
break;
}
}
if (!match) {
Vector<Integer> newVis = new Vector<Integer>(visited);
newVis.addElement(edge);
List<Integer> nodeParentList = dataPair.getB();
if (nodeParentList == null)
nodeParentList = new ArrayList<Integer>();
else
// clone before we add to it
nodeParentList = new ArrayList<Integer>(nodeParentList);
// curNode's coord will be parent to new pending element
nodeParentList.add(coord);
// edge's other node
j = board.getAdjacentNodeToNode(coord, dir);
pending.push(new Pair<NodeLenVis<Integer>, List<Integer>>(new NodeLenVis<Integer>(j, len + 1, newVis), nodeParentList));
pathEnd = false;
}
}
}
}
if (pathEnd) {
if (len > longest) {
longest = len;
numRoads = curNode.len - pathLength;
bestPathNode = dataPair;
} else if ((len == longest) && (curNode.len < numRoads)) {
numRoads = curNode.len - pathLength;
bestPathNode = dataPair;
}
}
}
if (!wantsStack) {
// As used by SOCPlayerTracker.
int rv;
if (longest > lrLength)
rv = numRoads;
else
rv = 500;
// <-- Early return: ! wantsStack ---
return new Integer(rv);
}
if ((longest > lrLength) && (bestPathNode != null)) {
// D.ebugPrintln("Converting nodes to road coords.");
//
// Return the path in a stack, with the last road (the one from bestPathNode) on top.
// Convert pairs of node coords to edge coords for roads.
// List is ordered from farthest parent at 0 to bestPathNode's parent at (n-1),
// so iterate same way to build the stack.
//
Stack<SOCPossibleRoad> path = new Stack<SOCPossibleRoad>();
int coordC, coordP;
List<Integer> nodeList = bestPathNode.getB();
if ((nodeList == null) || nodeList.isEmpty())
// <--- early return, no node list: should not happen ---
return null;
// append bestPathNode
nodeList.add(new Integer(bestPathNode.getA().node));
final int L = nodeList.size();
// root ancestor
coordP = nodeList.get(0);
for (int i = 1; i < L; ++i) {
coordC = nodeList.get(i);
path.push(new SOCPossibleRoad(pl, board.getEdgeBetweenAdjacentNodes(coordC, coordP), null));
coordP = coordC;
}
return path;
}
return null;
}
use of soc.game.SOCPlayingPiece in project JSettlers2 by jdmonin.
the class SOCPlayerInterface method updateAtPutPiece.
/**
* Handle updates after putting a piece on the board,
* or moving a ship that was already placed.
* Place or move the piece within our {@link SOCGame}
* and visually on our {@link SOCBoardPanel}.
*
* @param mesPn The piece's player number
* @param coord The piece's coordinate. If <tt>isMove</tt>, the coordinate to move <em>from</em>.
* @param pieceType Piece type, like {@link SOCPlayingPiece#CITY}
* @param isMove If true, it's a move, not a new placement; valid only for ships.
* @param moveToCoord If <tt>isMove</tt>, the coordinate to move <em>to</em>. Otherwise ignored.
*
* @see #updateAtPiecesChanged()
* @since 2.0.00
*/
public void updateAtPutPiece(final int mesPn, final int coord, final int pieceType, final boolean isMove, final int moveToCoord) {
// TODO consider more effic way for flushBoardLayoutAndRepaint, without the =null
final SOCPlayer pl = (pieceType != SOCPlayingPiece.VILLAGE) ? game.getPlayer(mesPn) : null;
final SOCPlayer oldLongestRoadPlayer = game.getPlayerWithLongestRoad();
final SOCHandPanel mesHp = (pieceType != SOCPlayingPiece.VILLAGE) ? getPlayerHandPanel(mesPn) : null;
final boolean[] debugShowPotentials = boardPanel.debugShowPotentials;
final SOCPlayingPiece pp;
switch(pieceType) {
case SOCPlayingPiece.ROAD:
pp = new SOCRoad(pl, coord, null);
game.putPiece(pp);
mesHp.updateValue(PlayerClientListener.UpdateType.Road);
if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7])
boardPanel.flushBoardLayoutAndRepaint();
break;
case SOCPlayingPiece.SETTLEMENT:
pp = new SOCSettlement(pl, coord, null);
game.putPiece(pp);
mesHp.updateValue(PlayerClientListener.UpdateType.Settlement);
/**
* if this is the second initial settlement, then update the resource display
*/
mesHp.updateValue(PlayerClientListener.UpdateType.ResourceTotalAndDetails);
if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7] || debugShowPotentials[6])
boardPanel.flushBoardLayoutAndRepaint();
break;
case SOCPlayingPiece.CITY:
pp = new SOCCity(pl, coord, null);
game.putPiece(pp);
mesHp.updateValue(PlayerClientListener.UpdateType.Settlement);
mesHp.updateValue(PlayerClientListener.UpdateType.City);
if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7] || debugShowPotentials[6])
boardPanel.flushBoardLayoutAndRepaint();
break;
case SOCPlayingPiece.SHIP:
pp = new SOCShip(pl, coord, null);
if (!isMove) {
game.putPiece(pp);
mesHp.updateValue(PlayerClientListener.UpdateType.Ship);
} else {
game.moveShip((SOCShip) pp, moveToCoord);
if (mesHp == clientHand)
// just in case; it probably wasn't enabled
mesHp.disableBankUndoButton();
}
if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7])
boardPanel.flushBoardLayoutAndRepaint();
break;
case SOCPlayingPiece.VILLAGE:
// no need to refresh boardPanel after receiving each village
pp = new SOCVillage(coord, game.getBoard());
game.putPiece(pp);
// <--- Early return: Piece is part of board initial layout, not player info ---
return;
case SOCPlayingPiece.FORTRESS:
pp = new SOCFortress(pl, coord, game.getBoard());
game.putPiece(pp);
// <--- Early return: Piece is part of board initial layout, not added during game ---
return;
default:
chatPrintDebug("* Unknown piece type " + pieceType + " at coord 0x" + Integer.toHexString(coord));
// <--- Early return ---
return;
}
mesHp.updateValue(PlayerClientListener.UpdateType.VictoryPoints);
boardPanel.repaint();
buildingPanel.updateButtonStatus();
if (game.isDebugFreePlacement() && game.isInitialPlacement())
// update here, since gamestate doesn't change to trigger update
boardPanel.updateMode();
if (hasCalledBegan && (game.getGameState() >= SOCGame.START1A))
playSound(SOUND_PUT_PIECE);
/**
* Check for and announce change in longest road; update all players' victory points.
*/
SOCPlayer newLongestRoadPlayer = game.getPlayerWithLongestRoad();
if (newLongestRoadPlayer != oldLongestRoadPlayer) {
updateLongestLargest(true, oldLongestRoadPlayer, newLongestRoadPlayer);
}
}
Aggregations