use of soc.message.SOCPotentialSettlements in project JSettlers2 by jdmonin.
the class SOCGameHandler method startGame.
// javadoc inherited from GameHandler
/**
* {@inheritDoc}
*<P>
* If {@link SOCGame#hasSeaBoard}: Once the board is made, send the updated
* {@link SOCPotentialSettlements potential settlements}.
*<P>
* If this code changes, must also update {@link soctest.TestBoardLayouts#testSingleLayout(SOCScenario, int)}.
*/
public void startGame(SOCGame ga) {
if (ga == null)
return;
final String gaName = ga.getName();
// TODO once multiple handler threads, encapsulate this
srv.numberOfGamesStarted++;
/**
* start the game, place any initial pieces.
* If anything is added to this game object setup code,
* update soctest.TestBoardLayouts.testSingleLayout(..).
*/
// for playerEvent, gameEvent callbacks (since 2.0.00)
ga.setScenarioEventListener(this);
ga.startGame();
// used on sea board; if null, all are legal
final int[][] legalSeaEdges;
if (ga.hasSeaBoard) {
legalSeaEdges = SOCBoardAtServer.getLegalSeaEdges(ga, -1);
if (legalSeaEdges != null)
for (int pn = 0; pn < ga.maxPlayers; ++pn) ga.getPlayer(pn).setRestrictedLegalShips(legalSeaEdges[pn]);
if (ga.isGameOptionSet(SOCGameOption.K_SC_FTRI) || ga.isGameOptionSet(SOCGameOption.K_SC_PIRI)) {
// scenario has initial pieces
((SOCBoardAtServer) (ga.getBoard())).startGame_putInitPieces(ga);
}
} else {
legalSeaEdges = null;
}
srv.gameList.takeMonitorForGame(gaName);
try {
/**
* send the board layout
*/
try {
srv.messageToGameWithMon(gaName, getBoardLayoutMessage(ga));
// For scenario option _SC_CLVI, the board layout message
// includes villages and the general supply cloth count.
// For _SC_PIRI, it includes the Pirate Path (additional layout part "PP").
} catch (IllegalArgumentException e) {
System.err.println("startGame: Cannot send board for " + gaName + ": " + e.getMessage());
// the enclosing try-finally will releaseMonitorForGame(gaName) before returning
return;
}
if (ga.hasSeaBoard) {
// See also joinGame which has very similar code.
// Send the updated Potential/Legal Settlement node list
// Note: Assumes all players have same potential settlements
// (sends with playerNumber -1 == all)
final HashSet<Integer> psList = ga.getPlayer(0).getPotentialSettlements();
// Some boards may have multiple land areas.
final HashSet<Integer>[] lan;
final int pan;
boolean addedPsList = false;
final SOCBoardLarge bl = (SOCBoardLarge) ga.getBoard();
lan = bl.getLandAreasLegalNodes();
pan = bl.getStartingLandArea();
if ((lan != null) && (pan != 0) && !lan[pan].equals(psList)) {
// If potentials != legals[startingLandArea], send as legals[0]
lan[0] = psList;
addedPsList = true;
}
if (lan == null)
srv.messageToGameWithMon(gaName, new SOCPotentialSettlements(gaName, -1, new ArrayList<Integer>(psList)));
else
srv.messageToGameWithMon(gaName, new SOCPotentialSettlements(gaName, -1, pan, lan, legalSeaEdges));
if (addedPsList)
// Undo change to game's copy of landAreasLegalNodes
lan[0] = null;
}
/**
* send the player info
*/
boolean sentInitPiecesState = false;
for (int i = 0; i < ga.maxPlayers; i++) {
if (ga.isSeatVacant(i))
continue;
final SOCPlayer pl = ga.getPlayer(i);
final int[] counts = new int[(ga.hasSeaBoard) ? 4 : 3];
counts[0] = pl.getNumPieces(SOCPlayingPiece.ROAD);
counts[1] = pl.getNumPieces(SOCPlayingPiece.SETTLEMENT);
counts[2] = pl.getNumPieces(SOCPlayingPiece.CITY);
if (ga.hasSeaBoard) {
// Some scenarios like SC_PIRI may place initial pieces at fixed locations.
// Usually, pieces will be empty.
final Vector<SOCPlayingPiece> pieces = pl.getPieces();
if (!pieces.isEmpty()) {
if (!sentInitPiecesState) {
// Temporary state change, to avoid initial-piece placement actions.
// The actual game state will be sent soon.
srv.messageToGameWithMon(gaName, new SOCGameState(gaName, SOCGame.READY));
sentInitPiecesState = true;
}
for (SOCPlayingPiece pp : pieces) srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, i, pp.getType(), pp.getCoordinates()));
SOCPlayingPiece pp = pl.getFortress();
if (pp != null)
srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, i, pp.getType(), pp.getCoordinates()));
}
counts[3] = pl.getNumPieces(SOCPlayingPiece.SHIP);
}
if (ga.clientVersionLowest >= SOCPlayerElements.MIN_VERSION)
srv.messageToGameWithMon(gaName, new SOCPlayerElements(gaName, i, SOCPlayerElement.SET, (ga.hasSeaBoard) ? ELEM_PIECETYPES_SEA : ELEM_PIECETYPES_CLASSIC, counts));
else
for (int j = 0; j < counts.length; ++j) srv.messageToGameWithMon(gaName, new SOCPlayerElement(gaName, i, SOCPlayerElement.SET, ELEM_PIECETYPES_SEA[j], counts[j]));
if (ga.clientVersionLowest < SOCPlayerElement.VERSION_FOR_CARD_ELEMENTS)
srv.messageToGameWithMon(gaName, new SOCSetPlayedDevCard(gaName, i, false));
}
if (ga.clientVersionLowest >= SOCPlayerElement.VERSION_FOR_CARD_ELEMENTS)
srv.messageToGameWithMon(gaName, new SOCPlayerElement(gaName, -1, SOCPlayerElement.SET, SOCPlayerElement.PLAYED_DEV_CARD_FLAG, 0));
/**
* send the number of dev cards
*/
srv.messageToGameWithMon(gaName, (ga.clientVersionLowest >= SOCGameElements.MIN_VERSION) ? new SOCGameElements(gaName, SOCGameElements.DEV_CARD_COUNT, ga.getNumDevCards()) : new SOCDevCardCount(gaName, ga.getNumDevCards()));
/**
* ga.startGame() picks who goes first, but feedback is nice
*/
srv.messageToGameKeyed(ga, false, // "Randomly picking a starting player..."
"start.picking.random.starting.player");
} finally {
srv.gameList.releaseMonitorForGame(gaName);
}
/**
* send the game state and start the game.
* send game state and whose turn it is.
*/
if (ga.clientVersionLowest >= SOCGameState.VERSION_FOR_GAME_STATE_AS_FIELD) {
srv.messageToGame(gaName, new SOCStartGame(gaName, ga.getGameState()));
sendTurn(ga, false);
} else {
final int cpn = ga.getCurrentPlayerNumber();
final boolean sendRoll = sendGameState(ga, false, false);
srv.messageToGame(gaName, new SOCStartGame(gaName, 0));
srv.messageToGame(gaName, new SOCTurn(gaName, cpn, 0));
if (sendRoll)
srv.messageToGame(gaName, new SOCRollDicePrompt(gaName, cpn));
}
}
Aggregations