use of soc.game.SOCRoad in project JSettlers2 by jdmonin.
the class SOCRobotBrain method planAndPlaceInitRoad.
/**
* Plan and place a road attached to our most recently placed initial settlement,
* in game states {@link SOCGame#START1B START1B}, {@link SOCGame#START2B START2B}, {@link SOCGame#START3B START3B}.
* Calls {@link OpeningBuildStrategy#planInitRoad()}.
*<P>
* Road choice is based on the best nearby potential settlements, and doesn't
* directly check {@link SOCPlayer#isPotentialRoad(int) ourPlayerData.isPotentialRoad(edgeCoord)}.
* If the server rejects our road choice, then {@link #cancelWrongPiecePlacementLocal(SOCPlayingPiece)}
* will need to know which settlement node we were aiming for,
* and call {@link SOCPlayer#clearPotentialSettlement(int) ourPlayerData.clearPotentialSettlement(nodeCoord)}.
* The {@link #lastStartingRoadTowardsNode} field holds this coordinate.
*/
protected void planAndPlaceInitRoad() {
// TODO handle ships here
final int roadEdge = openingBuildStrategy.planInitRoad();
// D.ebugPrintln("!!! PUTTING INIT ROAD !!!");
pause(500);
// D.ebugPrintln("Trying to build a road at "+Integer.toHexString(roadEdge));
lastStartingPieceCoord = roadEdge;
lastStartingRoadTowardsNode = openingBuildStrategy.getPlannedInitRoadDestinationNode();
client.putPiece(game, new SOCRoad(ourPlayerData, roadEdge, null));
pause(1000);
}
use of soc.game.SOCRoad 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.SOCRoad 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.SOCRoad 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.SOCRoad in project JSettlers2 by jdmonin.
the class SOCPlayerTracker method updateScenario_SC_PIRI_closestShipToFortress.
/**
* For scenario {@code _SC_PIRI}, update the player's ship closest to their Fortress.
* Assumes no ship will ever be west of the fortress (smaller column number).
* Must be called after adding or removing a ship from our player's {@link SOCPlayer#getRoads()}.
* @param ship Ship that was added or removed, or {@code null} to check all ships after removal
* @param shipAdded True if {@code ship} was added; false if {@code ship} or any other ship was removed
* or if we're updating Closest Ship without adding or removing a ship
* @throws IllegalArgumentException if {@code shipAdded} is true, but null {@code ship}
* @since 2.0.00
*/
void updateScenario_SC_PIRI_closestShipToFortress(final SOCShip ship, final boolean shipAdded) throws IllegalArgumentException {
if (shipAdded && (ship == null))
throw new IllegalArgumentException();
if ((scen_SC_PIRI_closestShipToFortress == null) && (ship != null)) {
if (shipAdded)
// closest by default
scen_SC_PIRI_closestShipToFortress = ship;
// <--- Early return: no other ships to compare ---
return;
}
if (!shipAdded) {
if ((ship != null) && (scen_SC_PIRI_closestShipToFortress != null) && (ship.getCoordinates() != scen_SC_PIRI_closestShipToFortress.getCoordinates()))
// <--- Early return: Not the closest ship ---
return;
}
// may be null towards end of game
final SOCFortress fort = player.getFortress();
// If fort's null, we can still compare columns, just not rows, of ship coordinates.
final int fortR = (fort != null) ? (fort.getCoordinates() >> 8) : -1;
if (shipAdded) {
final int shipEdge = ship.getCoordinates(), prevShipEdge = scen_SC_PIRI_closestShipToFortress.getCoordinates();
final int shipR = shipEdge >> 8, shipC = shipEdge & 0xFF, prevR = prevShipEdge >> 8, prevC = prevShipEdge & 0xFF;
if ((shipC < prevC) || ((shipC == prevC) && (fortR != -1) && (Math.abs(shipR - fortR) < Math.abs(prevR - fortR)))) {
scen_SC_PIRI_closestShipToFortress = ship;
}
} else {
// A ship has been removed. We don't know which one.
// So, check all ships for distance from fortress.
Enumeration<SOCRoad> roadAndShipEnum = player.getRoads().elements();
SOCShip closest = null;
int closeR = -1, closeC = -1;
while (roadAndShipEnum.hasMoreElements()) {
final SOCRoad rs = roadAndShipEnum.nextElement();
if (!(rs instanceof SOCShip))
continue;
final int shipEdge = rs.getCoordinates();
final int shipR = shipEdge >> 8, shipC = shipEdge & 0xFF;
if ((closest == null) || (shipC < closeC) || ((shipC == closeC) && (fortR != -1) && (Math.abs(shipR - fortR) < Math.abs(closeR - fortR)))) {
closest = (SOCShip) rs;
closeR = shipR;
closeC = shipC;
}
}
// null if no ships
scen_SC_PIRI_closestShipToFortress = closest;
}
}
Aggregations