use of soc.game.SOCVillage in project JSettlers2 by jdmonin.
the class SOCGameMessageHandler method handleROLLDICE.
// / Roll dice and pick resources ///
/**
* handle "roll dice" message.
*
* @param c the connection that sent the message
* @param mes the message
* @since 1.0.0
*/
private void handleROLLDICE(SOCGame ga, Connection c, final SOCRollDice mes) {
final String gn = ga.getName();
ga.takeMonitor();
try {
final String plName = c.getData();
final SOCPlayer pl = ga.getPlayer(plName);
if ((pl != null) && ga.canRollDice(pl.getPlayerNumber())) {
/**
* Roll dice, distribute resources in game
*/
SOCGame.RollResult roll = ga.rollDice();
/**
* Send roll results and then text to client.
* Note that only the total is sent, not the 2 individual dice.
* (Only the _SC_PIRI scenario cares about them indivdually, and
* in that case it prints the result when needed.)
*
* If a 7 is rolled, sendGameState will also say who must discard
* (in a GAMETEXTMSG).
* If a gold hex is rolled, sendGameState will also say who
* must pick resources to gain (in a GAMETEXTMSG).
*/
srv.messageToGame(gn, new SOCDiceResult(gn, ga.getCurrentDice()));
if (ga.clientVersionLowest < SOCGameTextMsg.VERSION_FOR_DICE_RESULT_INSTEAD) {
// backwards-compat: this text message is redundant to v2.0.00 and newer clients
// because they print the roll results from SOCDiceResult. Use SOCGameTextMsg
// because pre-2.0.00 clients don't understand SOCGameServerText messages.
srv.messageToGameForVersions(ga, 0, SOCGameTextMsg.VERSION_FOR_DICE_RESULT_INSTEAD - 1, new SOCGameTextMsg(gn, SOCGameTextMsg.SERVERNAME, // I18N
plName + " rolled a " + roll.diceA + " and a " + roll.diceB + "."), true);
}
// For 7, give visual feedback before sending discard request
handler.sendGameState(ga);
if (ga.isGameOptionSet(SOCGameOption.K_SC_PIRI)) {
// pirate moves on every roll
srv.messageToGame(gn, new SOCMoveRobber(gn, ga.getCurrentPlayerNumber(), -(((SOCBoardLarge) ga.getBoard()).getPirateHex())));
if (roll.sc_piri_fleetAttackVictim != null) {
final SOCResourceSet loot = roll.sc_piri_fleetAttackRsrcs;
final int lootTotal = (loot != null) ? loot.getTotal() : 0;
if (lootTotal != 0) {
// use same resource-loss messages sent in handleDISCARD
final boolean won = (loot.contains(SOCResourceConstants.GOLD_LOCAL));
SOCPlayer vic = roll.sc_piri_fleetAttackVictim;
final String vicName = vic.getName();
final Connection vCon = srv.getConnection(vicName);
final int vpn = vic.getPlayerNumber();
final int strength = (roll.diceA < roll.diceB) ? roll.diceA : roll.diceB;
if (won) {
srv.messageToGameKeyed(ga, true, "action.rolled.sc_piri.player.won.pick.free", vicName, strength);
// "{0} won against the pirate fleet (strength {1}) and will pick a free resource."
} else {
/**
* tell the victim client that the player lost the resources
*/
handler.reportRsrcGainLoss(gn, loot, true, true, vpn, -1, null, vCon);
srv.messageToPlayerKeyedSpecial(vCon, ga, "action.rolled.sc_piri.you.lost.rsrcs.to.fleet", loot, strength);
// "You lost {0,rsrcs} to the pirate fleet (strength {1,number})."
/**
* tell everyone else that the player lost unknown resources
*/
srv.messageToGameExcept(gn, vCon, new SOCPlayerElement(gn, vpn, SOCPlayerElement.LOSE, SOCPlayerElement.UNKNOWN, lootTotal), true);
srv.messageToGameKeyedSpecialExcept(ga, true, vCon, "action.rolled.sc_piri.player.lost.rsrcs.to.fleet", vicName, lootTotal, strength);
// "Joe lost 1 resource to pirate fleet attack (strength 3)." or
// "Joe lost 3 resources to pirate fleet attack (strength 3)."
}
}
}
}
/**
* if the roll is not 7, tell players what they got
* (if 7, sendGameState already told them what they lost).
*/
if (ga.getCurrentDice() != 7) {
boolean noPlayersGained = true;
/**
* Clients v2.0.00 and newer get an i18n-neutral SOCDiceResultResources message.
* Older clients get a string such as "Joe gets 3 sheep. Mike gets 1 clay."
*/
String rollRsrcTxtOldCli = null;
SOCDiceResultResources rollRsrcMsgNewCli = null;
if (ga.clientVersionHighest >= SOCDiceResultResources.VERSION_FOR_DICERESULTRESOURCES) {
rollRsrcMsgNewCli = SOCDiceResultResources.buildForGame(ga);
noPlayersGained = (rollRsrcMsgNewCli == null);
}
if (ga.clientVersionLowest < SOCDiceResultResources.VERSION_FOR_DICERESULTRESOURCES) {
// Build a string to announce to v1.x.xx clients
StringBuffer gainsText = new StringBuffer();
// for string spacing; might be false due to loop for new clients in game
noPlayersGained = true;
for (int pn = 0; pn < ga.maxPlayers; ++pn) {
if (!ga.isSeatVacant(pn)) {
SOCPlayer pp = ga.getPlayer(pn);
SOCResourceSet rsrcs = pp.getRolledResources();
if (rsrcs.getKnownTotal() != 0) {
if (noPlayersGained)
noPlayersGained = false;
else
gainsText.append(" ");
gainsText.append(c.getLocalizedSpecial(ga, "_nolocaliz.roll.gets.resources", pp.getName(), rsrcs));
// "{0} gets {1,rsrcs}."
// get it from any connection's StringManager, because that string is never localized
// Announce SOCPlayerElement.GAIN messages
handler.reportRsrcGainLoss(gn, rsrcs, false, false, pn, -1, null, null);
}
}
}
if (!noPlayersGained)
rollRsrcTxtOldCli = gainsText.toString();
}
if (noPlayersGained) {
String key;
if (roll.cloth == null)
// "No player gets anything."
key = "action.rolled.no.player.gets.anything";
else
// "No player gets resources."
key = "action.rolled.no.player.gets.resources";
// debug_printPieceDiceNumbers(ga, message);
srv.messageToGameKeyed(ga, true, key);
} else {
if (rollRsrcTxtOldCli == null)
srv.messageToGame(gn, rollRsrcMsgNewCli);
else if (rollRsrcMsgNewCli == null)
srv.messageToGame(gn, rollRsrcTxtOldCli);
else {
// neither is null: we have old and new clients
srv.messageToGameForVersions(ga, 0, (SOCDiceResultResources.VERSION_FOR_DICERESULTRESOURCES - 1), new SOCGameTextMsg(gn, SOCGameTextMsg.SERVERNAME, rollRsrcTxtOldCli), true);
srv.messageToGameForVersions(ga, SOCDiceResultResources.VERSION_FOR_DICERESULTRESOURCES, Integer.MAX_VALUE, rollRsrcMsgNewCli, true);
}
//
for (int pn = 0; pn < ga.maxPlayers; ++pn) {
final SOCPlayer pp = ga.getPlayer(pn);
Connection playerCon = srv.getConnection(pp.getName());
if (playerCon == null)
continue;
if (pp.getRolledResources().getKnownTotal() == 0)
// skip if player didn't gain; before v2.0.00 each player in game got these
continue;
// send CLAY, ORE, SHEEP, WHEAT, WOOD even if player's amount is 0
final SOCResourceSet resources = pp.getResources();
final int[] counts = resources.getAmounts(false);
if (playerCon.getVersion() >= SOCPlayerElements.MIN_VERSION)
srv.messageToPlayer(playerCon, new SOCPlayerElements(gn, pn, SOCPlayerElement.SET, SOCGameHandler.ELEM_RESOURCES, counts));
else
for (int i = 0; i < counts.length; ++i) srv.messageToPlayer(playerCon, new SOCPlayerElement(gn, pn, SOCPlayerElement.SET, SOCGameHandler.ELEM_RESOURCES[i], counts[i]));
if (ga.clientVersionLowest < SOCDiceResultResources.VERSION_FOR_DICERESULTRESOURCES)
srv.messageToGame(gn, new SOCResourceCount(gn, pn, resources.getTotal()));
// else, already-sent SOCDiceResultResources included players' new resource totals
// we'll send gold picks text, PLAYERELEMENT, and SIMPLEREQUEST(PROMPT_PICK_RESOURCES)
// after the per-player loop
}
}
if (roll.cloth != null) {
// Send village cloth trade distribution
final int coord = roll.cloth[1];
final SOCBoardLarge board = (SOCBoardLarge) (ga.getBoard());
SOCVillage vi = board.getVillageAtNode(coord);
if (vi != null)
srv.messageToGame(gn, new SOCPieceValue(gn, coord, vi.getCloth(), 0));
if (roll.cloth[0] > 0)
// some taken from board general supply
srv.messageToGame(gn, new SOCPlayerElement(gn, -1, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_CLOTH_COUNT, board.getCloth()));
// name of first player to receive cloth
String clplName = null;
// names of all players receiving cloth, if more than one
ArrayList<String> clpls = null;
for (int i = 2; i < roll.cloth.length; ++i) {
if (roll.cloth[i] == 0)
// this player didn't receive cloth
continue;
final int pn = i - 2;
final SOCPlayer clpl = ga.getPlayer(pn);
srv.messageToGame(gn, new SOCPlayerElement(gn, pn, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_CLOTH_COUNT, clpl.getCloth()));
if (clplName == null) {
// first pl to receive cloth
clplName = clpl.getName();
} else {
// second or further player
if (clpls == null) {
clpls = new ArrayList<String>();
clpls.add(clplName);
}
clpls.add(clpl.getName());
}
}
if (clpls == null)
srv.messageToGameKeyed(ga, true, "action.rolled.sc_clvi.received.cloth.1", clplName);
else
// "{0} received 1 cloth from a village."
srv.messageToGameKeyedSpecial(ga, true, "action.rolled.sc_clvi.received.cloth.n", clpls);
// "{0,list} each received 1 cloth from a village."
}
if (ga.getGameState() == SOCGame.WAITING_FOR_PICK_GOLD_RESOURCE)
// gold picks text, PLAYERELEMENT, and SIMPLEREQUEST(PROMPT_PICK_RESOURCES)s
handler.sendGameState_sendGoldPickAnnounceText(ga, gn, null, roll);
/*
if (D.ebugOn) {
for (int i=0; i < SOCGame.MAXPLAYERS; i++) {
SOCResourceSet rsrcs = ga.getPlayer(i).getResources();
String resourceMessage = "PLAYER "+i+" RESOURCES: ";
resourceMessage += rsrcs.getAmount(SOCResourceConstants.CLAY)+" ";
resourceMessage += rsrcs.getAmount(SOCResourceConstants.ORE)+" ";
resourceMessage += rsrcs.getAmount(SOCResourceConstants.SHEEP)+" ";
resourceMessage += rsrcs.getAmount(SOCResourceConstants.WHEAT)+" ";
resourceMessage += rsrcs.getAmount(SOCResourceConstants.WOOD)+" ";
resourceMessage += rsrcs.getAmount(SOCResourceConstants.UNKNOWN)+" ";
messageToGame(gn, new SOCGameTextMsg(gn, SERVERNAME, resourceMessage));
}
}
*/
} else {
/**
* player rolled 7
* If anyone needs to discard, prompt them.
*/
if (ga.getGameState() == SOCGame.WAITING_FOR_DISCARDS) {
handler.sendGameState_sendDiscardRequests(ga, gn);
} else if (ga.getGameState() == SOCGame.WAITING_FOR_PICK_GOLD_RESOURCE) {
// Used in _SC_PIRI, when 7 is rolled and a player wins against the pirate fleet
for (int pn = 0; pn < ga.maxPlayers; ++pn) {
final SOCPlayer pp = ga.getPlayer(pn);
final int numPick = pp.getNeedToPickGoldHexResources();
if ((!ga.isSeatVacant(pn)) && (numPick > 0)) {
Connection con = srv.getConnection(pp.getName());
if (con != null) {
srv.messageToGame(gn, new SOCPlayerElement(gn, pn, SOCPlayerElement.SET, SOCPlayerElement.NUM_PICK_GOLD_HEX_RESOURCES, numPick));
con.put(SOCSimpleRequest.toCmd(gn, pn, SOCSimpleRequest.PROMPT_PICK_RESOURCES, numPick, 0));
}
}
}
}
}
} else {
srv.messageToPlayer(c, gn, "You can't roll right now.");
}
} catch (Exception e) {
D.ebugPrintStackTrace(e, "Exception caught at handleROLLDICE" + e);
}
ga.releaseMonitor();
}
use of soc.game.SOCVillage in project JSettlers2 by jdmonin.
the class SOCDisplaylessPlayerClient method handlePIECEVALUE.
/**
* Update a village piece's value on the board (cloth remaining) in _SC_CLVI,
* or a pirate fortress's strength in _SC_PIRI.
* @since 2.0.00
*/
protected void handlePIECEVALUE(final SOCPieceValue mes) {
final String gaName = mes.getGame();
SOCGame ga = games.get(gaName);
if (ga == null)
// Not one of our games
return;
if (!ga.hasSeaBoard)
// should not happen
return;
final int coord = mes.getParam1();
final int pv = mes.getParam2();
if (ga.isGameOptionSet(SOCGameOption.K_SC_CLVI)) {
SOCVillage vi = ((SOCBoardLarge) (ga.getBoard())).getVillageAtNode(coord);
if (vi != null)
vi.setCloth(pv);
} else if (ga.isGameOptionSet(SOCGameOption.K_SC_PIRI)) {
SOCFortress fort = ga.getFortress(coord);
if (fort != null)
fort.setStrength(pv);
}
}
use of soc.game.SOCVillage 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);
}
}
use of soc.game.SOCVillage in project JSettlers2 by jdmonin.
the class SOCDisplaylessPlayerClient method handlePUTPIECE.
/**
* handle the "put piece" message
*<P>
* This method is public static for access by
* {@code SOCRobotBrain.handlePUTPIECE_updateGameData(SOCPutPiece)}.
* @param mes the message
* @param ga Message's game from {@link SOCPutPiece#getGame()}; if {@code null}, message is ignored
*/
public static void handlePUTPIECE(final SOCPutPiece mes, SOCGame ga) {
if (ga != null) {
final int pieceType = mes.getPieceType();
final int coord = mes.getCoordinates();
final SOCPlayer pl = (pieceType != SOCPlayingPiece.VILLAGE) ? ga.getPlayer(mes.getPlayerNumber()) : null;
switch(pieceType) {
case SOCPlayingPiece.ROAD:
ga.putPiece(new SOCRoad(pl, coord, null));
break;
case SOCPlayingPiece.SETTLEMENT:
ga.putPiece(new SOCSettlement(pl, coord, null));
break;
case SOCPlayingPiece.CITY:
ga.putPiece(new SOCCity(pl, coord, null));
break;
case SOCPlayingPiece.SHIP:
ga.putPiece(new SOCShip(pl, coord, null));
break;
case SOCPlayingPiece.FORTRESS:
ga.putPiece(new SOCFortress(pl, coord, ga.getBoard()));
break;
case SOCPlayingPiece.VILLAGE:
ga.putPiece(new SOCVillage(coord, ga.getBoard()));
break;
default:
System.err.println("Displayless.handlePUTPIECE: game " + ga.getName() + ": Unknown pieceType " + pieceType);
}
}
}
use of soc.game.SOCVillage in project JSettlers2 by jdmonin.
the class SOCBoardPanel method drawBoardEmpty.
/**
* Draw the whole board (water, hexes, ports, numbers) but no placed pieces.
* This is drawn once, then stored.
* If the board layout changes (at start of game or
* {@link SOCBoardLarge#FOG_HEX fog hex} reveal, for example),
* call {@link #flushBoardLayoutAndRepaint()} to clear the buffered copy.
*<P>
* For scenario option {@link SOCGameOption#K_SC_CLVI _SC_CLVI},
* <tt>drawBoardEmpty</tt> draws the board's {@link SOCVillage}s.
*<P>
* If {@link #panelMarginX} or {@link #panelMarginY} != 0, do not translate {@code g}
* before calling. This method will internally translate.
*
* @param g Graphics, typically from {@link #emptyBoardBuffer}
* @since 1.1.08
* @see SOCPlayerInterface#updateAtNewBoard()
*/
private void drawBoardEmpty(Graphics g) {
// ask for antialiasing if available
if (g instanceof Graphics2D)
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Set<Integer> landHexShow;
final int SC_6;
if (debugShowPotentials[8] && isLargeBoard) {
landHexShow = ((SOCBoardLarge) board).getLandHexCoordsSet();
SC_6 = scaleToActual(6);
} else {
// almost always null, unless debugging large board
landHexShow = null;
// unused unless debugging large board
SC_6 = 0;
}
g.setPaintMode();
g.setColor(getBackground());
g.fillRect(0, 0, scaledPanelW, scaledPanelH);
if (scaledPorts[0] == null) {
// Check if port graphics are ready. This probably isn't needed, because
// doLayout already called position/sizing methods which call rescaleBoard.
renderPortImages();
}
final boolean xlat = (panelMarginX != 0) || (panelMarginY != 0);
if (xlat)
g.translate(panelMarginX, panelMarginY);
// drawHex will set scaledMissedImage if missed.
if (!isLargeBoard) {
// Draw water hexes to all edges of the panel;
// these are outside the board coordinate system.
boolean isRowOffset = isRotated;
for (int hy = -deltaY; hy < panelMinBH; hy += deltaY, isRowOffset = !isRowOffset) {
int hx = 0;
if (isRowOffset)
hx -= halfdeltaX;
for (; hx < panelMinBW; hx += deltaX) if (0 == findHex(hx, hy))
drawHex(g, hx, hy, SOCBoard.WATER_HEX, -1, -1);
}
if (is6player)
drawPortsRing(g);
for (int i = 0; i < hexX.length; i++) if ((inactiveHexNums == null) || !inactiveHexNums[i])
drawHex(g, i);
} else {
// Large Board has a rectangular array of hexes.
// (r,c) are board coordinates.
// (x,y) are unscaled pixel coordinates.
// Top border rows:
final int bMarginX = scaleFromActual(panelMarginX), marginNumHex = (bMarginX + deltaX - 1) / deltaX;
// Top border ("row -2"): Needed only when panelMarginY is +1 or more "VS" units (1/4 or more of row height)
if (panelMarginY >= (halfdeltaY / 2)) {
final int y = -halfdeltaY - deltaY, xmin = -(deltaX * marginNumHex) - halfdeltaX;
for (int x = xmin; x < panelMinBW; x += deltaX) {
drawHex(g, x, y, SOCBoard.WATER_HEX, -1, -1);
}
}
// The initial x-coord formula aligns just enough water hexes to cover -panelMarginX.
for (int x = -(deltaX * marginNumHex); x < panelMinBW; x += deltaX) {
drawHex(g, x, -halfdeltaY, SOCBoard.WATER_HEX, -1, -1);
}
// In-bounds board hexes and bottom border:
final int bw = board.getBoardWidth(), bh = board.getBoardHeight();
for (int r = 1, y = halfdeltaY; r < bh || y < (scaledPanelH + HEXY_OFF_SLOPE_HEIGHT); r += 2, y += deltaY) {
final int rshift = (r << 8);
int c, x;
if (((r / 2) % 2) == 1) {
// odd hex rows start at 1
c = 1;
x = 0;
} else {
// top row, even rows start at 2
c = 2;
x = halfdeltaX;
}
if ((panelMarginX != 0) || (x != 0)) {
// xleft drawn at >= 0 after g.translate for panelMarginX
for (int xleft = x; xleft > -(panelMarginX + deltaX); xleft -= deltaX) drawHex(g, xleft, y, SOCBoard.WATER_HEX, -1, -1);
}
for (; c < bw; c += 2, x += deltaX) {
final int hexCoord = rshift | c;
final int hexType = (r < bh) ? board.getHexTypeFromCoord(hexCoord) : SOCBoard.WATER_HEX;
drawHex(g, x, y, hexType, -1, hexCoord);
if ((landHexShow != null) && landHexShow.contains(new Integer(hexCoord))) {
g.setColor(Color.RED);
g.drawRoundRect(scaleToActual(x + (halfdeltaX / 2)), scaleToActual(y + ((halfdeltaY + HEXY_OFF_SLOPE_HEIGHT) / 2) + 1), scaleToActual(halfdeltaX), scaleToActual(halfdeltaY + 1), SC_6, SC_6);
}
}
// If board is narrower than panel, fill in with water
int xmax = panelMinBW - 1;
if (panelMarginX < 0)
xmax -= panelMarginX;
while (x < xmax) {
final int hexCoord = rshift | c;
drawHex(g, x, y, SOCBoard.WATER_HEX, -1, hexCoord);
c += 2;
x += deltaX;
}
}
// All ports
drawPorts_LargeBoard(g);
// For scenario _SC_PIRI, check for the Pirate Path and Lone Settlement locations.
// Draw path only if the pirate fleet is still on the board
// Draw our player's permitted sea edges for ships, if restricted
{
final int[] ppath = ((SOCBoardLarge) board).getAddedLayoutPart("PP");
if ((ppath != null) && (0 != ((SOCBoardLarge) board).getPirateHex()))
drawBoardEmpty_drawPiratePath(g, ppath);
final int[] ls = ((SOCBoardLarge) board).getAddedLayoutPart("LS");
if (ls != null) {
for (int pn = 0; pn < ls.length; ++pn) if (ls[pn] != 0)
drawSettlement(g, ls[pn], pn, false, true);
}
final HashSet<Integer> lse = (player != null) ? player.getRestrictedLegalShips() : null;
if (lse != null)
drawSeaEdgeLines(g, null, lse);
}
// For scenario _SC_FTRI, draw markers at the SVP edges and dev card edges (added layout parts "CE", "VE")
if (((SOCBoardLarge) board).hasSpecialEdges())
drawBoardEmpty_specialEdges(g);
// For scenario _SC_CLVI, draw the cloth villages
HashMap<Integer, SOCVillage> villages = ((SOCBoardLarge) board).getVillages();
if (villages != null) {
Iterator<SOCVillage> villIter = villages.values().iterator();
while (villIter.hasNext()) drawVillage(g, villIter.next());
}
// For scenario _SC_WOND, draw special nodes (layout parts N1, N2, N3)
if (game.isGameOptionSet(SOCGameOption.K_SC_WOND)) {
// brown
drawBoardEmpty_specialNodes(g, "N1", new Color(180, 90, 40));
// violet
drawBoardEmpty_specialNodes(g, "N2", new Color(120, 40, 120));
drawBoardEmpty_specialNodes(g, "N3", Color.RED);
}
// check debugShowPotentials[0 - 9]
drawBoardEmpty_drawDebugShowPotentials(g);
}
if (xlat)
g.translate(-panelMarginX, -panelMarginY);
if (scaledMissedImage) {
// With recent board resize, one or more rescaled images still hasn't
// been completed after 7 seconds. We've asked for a new scaled copy
// of this image. Repaint now, and repaint 3 seconds later.
// (The delay gives time for the new scaling to complete.)
scaledAt = System.currentTimeMillis();
repaint();
new DelayedRepaint(this).start();
}
}
Aggregations