use of soc.game.SOCShip in project JSettlers2 by jdmonin.
the class SOCRobotBrain method handlePUTPIECE_updateTrackers.
/**
* Handle a PUTPIECE for this game, by updating {@link SOCPlayerTracker}s.
* Also handles the "move piece to here" part of MOVEPIECE.
*<P>
* For initial placement of our own pieces, this method also checks
* and clears expectPUTPIECE_FROM_START1A, and sets expectSTART1B, etc.
* The final initial putpiece clears expectPUTPIECE_FROM_START2B and sets expectROLL_OR_CARD.
* As part of the PUTPIECE request, brain set those expectPUTPIECE flags in {@link #placeIfExpectPlacing()}.
*<P>
* For initial settlements, won't track here:
* Delay tracking until the corresponding road is placed,
* in {@link #handlePUTPIECE_updateGameData(SOCPutPiece)}.
* This prevents the need for tracker "undo" work if a human
* player changes their mind on where to place the settlement.
*
* @param pn Piece's player number
* @param coord Piece coordinate
* @param pieceType Piece type, as in {@link SOCPlayingPiece#SETTLEMENT}
* @since 1.1.08
*/
private void handlePUTPIECE_updateTrackers(final int pn, final int coord, final int pieceType) {
switch(pieceType) {
case SOCPlayingPiece.ROAD:
SOCRoad newRoad = new SOCRoad(game.getPlayer(pn), coord, null);
trackNewRoadOrShip(newRoad, false);
break;
case SOCPlayingPiece.SETTLEMENT:
SOCPlayer newSettlementPl = game.getPlayer(pn);
SOCSettlement newSettlement = new SOCSettlement(newSettlementPl, coord, null);
if ((game.getGameState() == SOCGame.START1B) || (game.getGameState() == SOCGame.START2B) || (game.getGameState() == SOCGame.START3B)) {
// Track it soon, after the road is placed
// (in handlePUTPIECE_updateGameData)
// but not yet, in case player cancels placement.
SOCPlayerTracker tr = playerTrackers.get(Integer.valueOf(newSettlementPl.getPlayerNumber()));
tr.setPendingInitSettlement(newSettlement);
} else {
// Track it now
trackNewSettlement(newSettlement, false);
}
break;
case SOCPlayingPiece.CITY:
SOCCity newCity = new SOCCity(game.getPlayer(pn), coord, null);
trackNewCity(newCity, false);
break;
case SOCPlayingPiece.SHIP:
SOCShip newShip = new SOCShip(game.getPlayer(pn), coord, null);
trackNewRoadOrShip(newShip, false);
break;
case SOCPlayingPiece.VILLAGE:
// <--- Early return: Piece is part of board initial layout, not tracked player info ---
return;
}
if (D.ebugOn) {
SOCPlayerTracker.playerTrackersDebug(playerTrackers);
}
if (pn != ourPlayerNumber) {
// <---- Not our piece ----
return;
}
if (expectPUTPIECE_FROM_START1A && (pieceType == SOCPlayingPiece.SETTLEMENT) && (coord == ourPlayerData.getLastSettlementCoord())) {
expectPUTPIECE_FROM_START1A = false;
expectSTART1B = true;
}
if (expectPUTPIECE_FROM_START1B && ((pieceType == SOCPlayingPiece.ROAD) || (pieceType == SOCPlayingPiece.SHIP)) && (coord == ourPlayerData.getLastRoadCoord())) {
expectPUTPIECE_FROM_START1B = false;
expectSTART2A = true;
}
if (expectPUTPIECE_FROM_START2A && (pieceType == SOCPlayingPiece.SETTLEMENT) && (coord == ourPlayerData.getLastSettlementCoord())) {
expectPUTPIECE_FROM_START2A = false;
expectSTART2B = true;
}
if (expectPUTPIECE_FROM_START2B && ((pieceType == SOCPlayingPiece.ROAD) || (pieceType == SOCPlayingPiece.SHIP)) && (coord == ourPlayerData.getLastRoadCoord())) {
expectPUTPIECE_FROM_START2B = false;
if (!game.isGameOptionSet(SOCGameOption.K_SC_3IP))
// wait for regular game play to start; other players might still place first
expectROLL_OR_CARD = true;
else
expectSTART3A = true;
}
if (expectPUTPIECE_FROM_START3A && (pieceType == SOCPlayingPiece.SETTLEMENT) && (coord == ourPlayerData.getLastSettlementCoord())) {
expectPUTPIECE_FROM_START3A = false;
expectSTART3B = true;
}
if (expectPUTPIECE_FROM_START3B && ((pieceType == SOCPlayingPiece.ROAD) || (pieceType == SOCPlayingPiece.SHIP)) && (coord == ourPlayerData.getLastRoadCoord())) {
expectPUTPIECE_FROM_START3B = false;
expectROLL_OR_CARD = true;
}
}
use of soc.game.SOCShip 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.SOCShip in project JSettlers2 by jdmonin.
the class SOCRobotDM method getWinGameETABonusForRoad.
/**
* For {@link #SMART_STRATEGY}, add a bonus to the road or ship score
* based on the change in win game ETA for this one road or ship
* (possible settlements are 1 road closer, longest road bonus, etc).
*<UL>
* <LI> Calls {@link SOCPlayerTracker#tryPutPiece(SOCPlayingPiece, SOCGame, HashMap)}
* which makes a copy of the player trackers and puts the piece there.
* This also updates our player's VP total, including any special VP from placement.
* <LI> Calls {@link SOCPlayerTracker#updateWinGameETAs(HashMap)} on that copy
* <LI> Calls {@link #calcWGETABonus(HashMap, HashMap)} to compare WGETA before and after placement
* <LI> Calls {@link #getETABonus(int, int, float)} to weigh that bonus
* <LI> Adds that to {@code posRoad}'s {@link SOCPossiblePiece#getScore()}
* <LI> Cleans up with {@link SOCPlayerTracker#undoTryPutPiece(SOCPlayingPiece, SOCGame)}
*</UL>
*
* @param posRoad the possible piece that we're scoring
* @param roadETA the ETA for a road or ship, from building speed estimates
* @param leadersCurrentWGETA the leaders current WGETA
* @param playerTrackers the player trackers (for figuring out road building plan and bonus/ETA)
*/
protected float getWinGameETABonusForRoad(final SOCPossibleRoad posRoad, final int roadETA, final int leadersCurrentWGETA, HashMap<Integer, SOCPlayerTracker> playerTrackers) {
D.ebugPrintln("--- addWinGameETABonusForRoad");
int ourCurrentWGETA = ourPlayerTracker.getWinGameETA();
D.ebugPrintln("ourCurrentWGETA = " + ourCurrentWGETA);
HashMap<Integer, SOCPlayerTracker> trackersCopy = null;
SOCRoad tmpRoad1 = null;
// Building road or ship? TODO Better ETA calc for coastal road/ship
final boolean isShip = (posRoad instanceof SOCPossibleShip) && !((SOCPossibleShip) posRoad).isCoastalRoadAndShip;
final SOCResourceSet rsrcs = (isShip ? SOCShip.COST : SOCRoad.COST);
D.ebugPrintln("--- before [start] ---");
SOCResourceSet originalResources = ourPlayerData.getResources().copy();
SOCBuildingSpeedEstimate estimate = new SOCBuildingSpeedEstimate(ourPlayerData.getNumbers());
// SOCPlayerTracker.playerTrackersDebug(playerTrackers);
D.ebugPrintln("--- before [end] ---");
try {
SOCResSetBuildTimePair btp = estimate.calculateRollsAndRsrcFast(ourPlayerData.getResources(), rsrcs, 50, ourPlayerData.getPortFlags());
btp.getResources().subtract(rsrcs);
ourPlayerData.getResources().setAmounts(btp.getResources());
} catch (CutoffExceededException e) {
D.ebugPrintln("crap in getWinGameETABonusForRoad - " + e);
}
tmpRoad1 = (isShip) ? new SOCShip(ourPlayerData, posRoad.getCoordinates(), null) : new SOCRoad(ourPlayerData, posRoad.getCoordinates(), null);
trackersCopy = SOCPlayerTracker.tryPutPiece(tmpRoad1, game, playerTrackers);
SOCPlayerTracker.updateWinGameETAs(trackersCopy);
float score = calcWGETABonus(playerTrackers, trackersCopy);
if (!posRoad.getThreats().isEmpty()) {
score *= threatMultiplier;
D.ebugPrintln("*** (THREAT MULTIPLIER) score * " + threatMultiplier + " = " + score);
}
D.ebugPrintln("*** ETA for road = " + roadETA);
float etaBonus = getETABonus(roadETA, leadersCurrentWGETA, score);
D.ebugPrintln("$$$ score = " + score);
D.ebugPrintln("etaBonus = " + etaBonus);
posRoad.addToScore(etaBonus);
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().record("ETA = " + roadETA);
brain.getDRecorder().record("WGETA Score = " + df1.format(score));
brain.getDRecorder().record("Total road score = " + df1.format(etaBonus));
}
D.ebugPrintln("--- after [end] ---");
SOCPlayerTracker.undoTryPutPiece(tmpRoad1, game);
ourPlayerData.getResources().clear();
ourPlayerData.getResources().add(originalResources);
D.ebugPrintln("--- cleanup done ---");
return etaBonus;
}
use of soc.game.SOCShip in project JSettlers2 by jdmonin.
the class SOCRobotDM method planRoadBuildingTwoRoads.
/**
* For {@link #planStuff(int)}, if we have a road building card, make sure we build two roads first.
* Pick 2 good potential roads, and push them onto {@link #buildingPlan}.
*<P>
* Call only when our {@code SOCPlayer}:
*<UL>
* <LI> Has 2 more more road pieces left
* <LI> Has an old {@link SOCDevCardConstants#ROADS} card to play
* <LI> ! {@link SOCPlayer#hasPlayedDevCard() hasPlayedDevCard()}
*</UL>
* @since 2.0.00
*/
private final void planRoadBuildingTwoRoads() {
SOCPossibleRoad secondFavoriteRoad = null;
D.ebugPrintln("*** making a plan for road building");
// /
if (favoriteRoad != null) {
//
// pretend to put the favorite road down,
// and then score the new pos roads
//
// TODO for now, coastal roads/ships are always built as roads not ships
//
final SOCRoad tmpRoad;
if ((favoriteRoad instanceof SOCPossibleShip) && !((SOCPossibleShip) favoriteRoad).isCoastalRoadAndShip)
tmpRoad = new SOCShip(ourPlayerData, favoriteRoad.getCoordinates(), null);
else
tmpRoad = new SOCRoad(ourPlayerData, favoriteRoad.getCoordinates(), null);
HashMap<Integer, SOCPlayerTracker> trackersCopy = SOCPlayerTracker.tryPutPiece(tmpRoad, game, playerTrackers);
SOCPlayerTracker.updateWinGameETAs(trackersCopy);
SOCPlayerTracker ourPlayerTrackerCopy = trackersCopy.get(Integer.valueOf(ourPlayerNumber));
final int ourCurrentWGETACopy = ourPlayerTrackerCopy.getWinGameETA();
D.ebugPrintln("ourCurrentWGETACopy = " + ourCurrentWGETACopy);
int leadersCurrentWGETACopy = ourCurrentWGETACopy;
Iterator<SOCPlayerTracker> trackersCopyIter = trackersCopy.values().iterator();
while (trackersCopyIter.hasNext()) {
SOCPlayerTracker tracker = trackersCopyIter.next();
int wgeta = tracker.getWinGameETA();
if (wgeta < leadersCurrentWGETACopy) {
leadersCurrentWGETACopy = wgeta;
}
}
for (SOCPossiblePiece newPos : favoriteRoad.getNewPossibilities()) {
if (newPos instanceof SOCPossibleRoad) {
newPos.resetScore();
// float wgetaScore = getWinGameETABonusForRoad
// ((SOCPossibleRoad)newPos, currentBuildingETAs[SOCBuildingSpeedEstimate.ROAD], leadersCurrentWGETACopy, trackersCopy);
// +" has a score of "+newPos.getScore());
D.ebugPrintln("$$$ new pos road at " + Integer.toHexString(newPos.getCoordinates()));
if (favoriteRoad.getCoordinates() != newPos.getCoordinates()) {
if (secondFavoriteRoad == null) {
secondFavoriteRoad = (SOCPossibleRoad) newPos;
} else {
if (newPos.getScore() > secondFavoriteRoad.getScore()) {
secondFavoriteRoad = (SOCPossibleRoad) newPos;
}
}
}
}
}
for (SOCPossibleRoad threatenedRoad : threatenedRoads) {
D.ebugPrintln("$$$ threatened road at " + Integer.toHexString(threatenedRoad.getCoordinates()));
//
// see how building this piece impacts our winETA
//
threatenedRoad.resetScore();
// float wgetaScore = getWinGameETABonusForRoad
// (threatenedRoad, currentBuildingETAs[SOCBuildingSpeedEstimate.ROAD], leadersCurrentWGETA, playerTrackers);
// +threatenedRoad.getScore());
D.ebugPrintln("$$$ final score = 0");
if (favoriteRoad.getCoordinates() != threatenedRoad.getCoordinates()) {
if (secondFavoriteRoad == null) {
secondFavoriteRoad = threatenedRoad;
} else {
if (threatenedRoad.getScore() > secondFavoriteRoad.getScore()) {
secondFavoriteRoad = threatenedRoad;
}
}
}
}
for (SOCPossibleRoad goodRoad : goodRoads) {
D.ebugPrintln("$$$ good road at " + Integer.toHexString(goodRoad.getCoordinates()));
//
// see how building this piece impacts our winETA
//
goodRoad.resetScore();
// float wgetaScore = getWinGameETABonusForRoad
// (goodRoad, currentBuildingETAs[SOCBuildingSpeedEstimate.ROAD], leadersCurrentWGETA, playerTrackers);
// +goodRoad.getScore());
D.ebugPrintln("$$$ final score = 0");
if (favoriteRoad.getCoordinates() != goodRoad.getCoordinates()) {
if (secondFavoriteRoad == null) {
secondFavoriteRoad = goodRoad;
} else {
if (goodRoad.getScore() > secondFavoriteRoad.getScore()) {
secondFavoriteRoad = goodRoad;
}
}
}
}
SOCPlayerTracker.undoTryPutPiece(tmpRoad, game);
if (!buildingPlan.empty()) {
SOCPossiblePiece planPeek = buildingPlan.peek();
if ((planPeek == null) || (!(planPeek instanceof SOCPossibleRoad))) {
if (secondFavoriteRoad != null) {
D.ebugPrintln("### SECOND FAVORITE ROAD IS AT " + Integer.toHexString(secondFavoriteRoad.getCoordinates()));
D.ebugPrintln("### WITH A SCORE OF " + secondFavoriteRoad.getScore());
D.ebugPrintln("$ PUSHING " + secondFavoriteRoad);
buildingPlan.push(secondFavoriteRoad);
D.ebugPrintln("$ PUSHING " + favoriteRoad);
buildingPlan.push(favoriteRoad);
}
} else if (secondFavoriteRoad != null) {
SOCPossiblePiece tmp = buildingPlan.pop();
D.ebugPrintln("$ POPPED OFF");
D.ebugPrintln("### SECOND FAVORITE ROAD IS AT " + Integer.toHexString(secondFavoriteRoad.getCoordinates()));
D.ebugPrintln("### WITH A SCORE OF " + secondFavoriteRoad.getScore());
D.ebugPrintln("$ PUSHING " + secondFavoriteRoad);
buildingPlan.push(secondFavoriteRoad);
D.ebugPrintln("$ PUSHING " + tmp);
buildingPlan.push(tmp);
}
}
}
}
use of soc.game.SOCShip in project JSettlers2 by jdmonin.
the class SOCBoardAtServer method startGame_putInitPieces.
/**
* For scenario game option {@link SOCGameOption#K_SC_PIRI _SC_PIRI},
* place each player's initial pieces. For {@link SOCGameOption#K_SC_FTRI _SC_FTRI},
* set aside some dev cards to be claimed later at Special Edges.
* Otherwise do nothing.
*<P>
* For {@code _SC_PIRI}, also calls each player's {@link SOCPlayer#addLegalSettlement(int, boolean)}
* for their Lone Settlement location (adds layout part "LS").
* Vacant player numbers get 0 for their {@code "LS"} element.
*<P>
* Called only at server. For a method called during game start
* at server and clients, see {@link SOCGame#updateAtBoardLayout()}.
*<P>
* Called from {@link SOCGameHandler#startGame(SOCGame)} for those
* scenario game options; if you need it called for your game, add
* a check there for your scenario's {@link SOCGameOption}.
*<P>
* This is called after {@link #makeNewBoard(Map)} and before
* {@link SOCGameHandler#getBoardLayoutMessage}. So if needed,
* it can call {@link SOCBoardLarge#setAddedLayoutPart(String, int[])}.
*<P>
* If ship placement is restricted by the scenario, please call each player's
* {@link SOCPlayer#setRestrictedLegalShips(int[])} before calling this method,
* so the legal and potential arrays will be initialized.
*
* @see #getLegalSeaEdges(SOCGame, int)
*/
public void startGame_putInitPieces(SOCGame ga) {
if (ga.isGameOptionSet(SOCGameOption.K_SC_FTRI)) {
// Set aside dev cards for players to be given when reaching "CE" Special Edges.
final int cpn = ga.getCurrentPlayerNumber();
// to call buyDevCard without giving it to a player
ga.setCurrentPlayerNumber(-1);
drawStack = new Stack<Integer>();
final int n = FOR_TRI_DEV_CARD_EDGES[(ga.maxPlayers > 4) ? 1 : 0].length;
for (int i = 0; i < n; ++i) drawStack.push(ga.buyDevCard());
ga.setCurrentPlayerNumber(cpn);
return;
}
if (!ga.isGameOptionSet(SOCGameOption.K_SC_PIRI))
return;
final int gstate = ga.getGameState();
// prevent ga.putPiece from advancing turn
ga.setGameState(SOCGame.READY);
final int[] inits = PIR_ISL_INIT_PIECES[(ga.maxPlayers > 4) ? 1 : 0];
// lone possible-settlement node on the way to the island.
int[] possiLoneSettles = new int[ga.maxPlayers];
// vacant players will get 0 here, will not get free settlement, ship, or pirate fortress.
// iterate i only when player present, to avoid spacing gaps from vacant players
int i = 0;
for (int pn = 0; pn < ga.maxPlayers; ++pn) {
if (ga.isSeatVacant(pn))
continue;
SOCPlayer pl = ga.getPlayer(pn);
ga.putPiece(new SOCSettlement(pl, inits[i], this));
++i;
ga.putPiece(new SOCShip(pl, inits[i], this));
++i;
ga.putPiece(new SOCFortress(pl, inits[i], this));
++i;
possiLoneSettles[pn] = inits[i];
ga.getPlayer(pn).addLegalSettlement(inits[i], false);
++i;
}
setAddedLayoutPart("LS", possiLoneSettles);
ga.setGameState(gstate);
}
Aggregations