use of soc.game.SOCResourceSet in project JSettlers2 by jdmonin.
the class SOCRobotBrain method buildOrGetResourceByTradeOrCard.
/**
* Either ask to build a planned piece, or use trading or development cards to get resources to build it.
* Examines {@link #buildingPlan} for the next piece wanted.
* Sets {@link #whatWeWantToBuild} by calling {@link #buildRequestPlannedPiece()}
* or using a Road Building dev card.
*<P>
* If we need resources and we can't get them through the robber,
* the {@link SOCDevCardConstants#ROADS Road Building} or
* {@link SOCDevCardConstants#MONO Monopoly} or
* {@link SOCDevCardConstants#DISC Discovery} development cards,
* then trades with the bank ({@link #tradeToTarget2(SOCResourceSet)})
* or with other players ({@link #makeOffer(SOCPossiblePiece)}).
*<P>
* Call when these conditions are all true:
* <UL>
*<LI> {@link #ourTurn}
*<LI> {@link #planBuilding()} already called
*<LI> ! {@link #buildingPlan}.empty()
*<LI> gameState {@link SOCGame#PLAY1} or {@link SOCGame#SPECIAL_BUILDING}
*<LI> <tt>waitingFor...</tt> flags all false ({@link #waitingForGameState}, etc)
* except possibly {@link #waitingForSpecialBuild}
*<LI> <tt>expect...</tt> flags all false ({@link #expectPLACING_ROAD}, etc)
*<LI> ! {@link #waitingForOurTurn}
*<LI> ! ({@link #expectROLL_OR_CARD} && (counter < 4000))
*</UL>
*<P>
* May set any of these flags:
* <UL>
*<LI> {@link #waitingForGameState}, and {@link #expectWAITING_FOR_DISCOVERY} or {@link #expectWAITING_FOR_MONOPOLY}
*<LI> {@link #waitingForTradeMsg} or {@link #waitingForTradeResponse} or {@link #doneTrading}
*<LI> {@link #waitingForDevCard}, or {@link #waitingForGameState} and {@link #expectPLACING_SETTLEMENT} (etc).
*<LI> {@link #waitingForPickSpecialItem}
*<LI> Scenario actions such as {@link #waitingForSC_PIRI_FortressRequest}
*</UL>
*<P>
* In a future iteration of the run() loop with the expected {@code PLACING_} state, the
* bot will build {@link #whatWeWantToBuild} by calling {@link #placeIfExpectPlacing()}.
*
* @since 1.1.08
* @throws IllegalStateException if {@link #buildingPlan}{@link Stack#isEmpty() .isEmpty()}
*/
private void buildOrGetResourceByTradeOrCard() throws IllegalStateException {
if (buildingPlan.isEmpty())
throw new IllegalStateException("buildingPlan empty when called");
/**
* If we're in SPECIAL_BUILDING (not PLAY1),
* can't trade or play development cards.
*/
final boolean gameStatePLAY1 = (game.getGameState() == SOCGame.PLAY1);
/**
* check to see if this is a Road Building plan
*/
boolean roadBuildingPlan = false;
if (gameStatePLAY1 && (!ourPlayerData.hasPlayedDevCard()) && (ourPlayerData.getNumPieces(SOCPlayingPiece.ROAD) >= 2) && ourPlayerData.getInventory().hasPlayable(SOCDevCardConstants.ROADS) && (rejectedPlayDevCardType != SOCDevCardConstants.ROADS)) {
// D.ebugPrintln("** Checking for Road Building Plan **");
SOCPossiblePiece topPiece = buildingPlan.pop();
// D.ebugPrintln("$ POPPED "+topPiece);
if ((topPiece != null) && (topPiece instanceof SOCPossibleRoad)) {
SOCPossiblePiece secondPiece = (buildingPlan.isEmpty()) ? null : buildingPlan.peek();
// D.ebugPrintln("secondPiece="+secondPiece);
if ((secondPiece != null) && (secondPiece instanceof SOCPossibleRoad)) {
roadBuildingPlan = true;
// builds ships only if the 2 possible pieces are non-coastal ships
if ((topPiece instanceof SOCPossibleShip) && (!((SOCPossibleShip) topPiece).isCoastalRoadAndShip) && (secondPiece instanceof SOCPossibleShip) && (!((SOCPossibleShip) secondPiece).isCoastalRoadAndShip))
whatWeWantToBuild = new SOCShip(ourPlayerData, topPiece.getCoordinates(), null);
else
whatWeWantToBuild = new SOCRoad(ourPlayerData, topPiece.getCoordinates(), null);
if (!whatWeWantToBuild.equals(whatWeFailedToBuild)) {
waitingForGameState = true;
counter = 0;
expectPLACING_FREE_ROAD1 = true;
// D.ebugPrintln("!! PLAYING ROAD BUILDING CARD");
client.playDevCard(game, SOCDevCardConstants.ROADS);
} else {
// We already tried to build this.
roadBuildingPlan = false;
cancelWrongPiecePlacementLocal(whatWeWantToBuild);
// cancel sets whatWeWantToBuild = null;
}
} else {
// D.ebugPrintln("$ PUSHING "+topPiece);
buildingPlan.push(topPiece);
}
} else {
// D.ebugPrintln("$ PUSHING "+topPiece);
buildingPlan.push(topPiece);
}
}
if (roadBuildingPlan) {
// <---- Early return: Road Building dev card ----
return;
}
// /
// / figure out what resources we need
// /
SOCPossiblePiece targetPiece = buildingPlan.peek();
// may be null
SOCResourceSet targetResources = targetPiece.getResourcesToBuild();
// D.ebugPrintln("^^^ targetPiece = "+targetPiece);
// D.ebugPrintln("^^^ ourResources = "+ourPlayerData.getResources());
negotiator.setTargetPiece(ourPlayerNumber, targetPiece);
// /
if (gameStatePLAY1 && (!ourPlayerData.hasPlayedDevCard()) && ourPlayerData.getInventory().hasPlayable(SOCDevCardConstants.DISC) && (rejectedPlayDevCardType != SOCDevCardConstants.DISC)) {
if (chooseFreeResourcesIfNeeded(targetResources, 2, false)) {
// /
// / play the card
// /
expectWAITING_FOR_DISCOVERY = true;
waitingForGameState = true;
counter = 0;
client.playDevCard(game, SOCDevCardConstants.DISC);
pause(1500);
}
}
if (!expectWAITING_FOR_DISCOVERY) {
// /
if (gameStatePLAY1 && (!ourPlayerData.hasPlayedDevCard()) && ourPlayerData.getInventory().hasPlayable(SOCDevCardConstants.MONO) && (rejectedPlayDevCardType != SOCDevCardConstants.MONO) && monopolyStrategy.decidePlayMonopoly()) {
// /
// / play the card
// /
expectWAITING_FOR_MONOPOLY = true;
waitingForGameState = true;
counter = 0;
client.playDevCard(game, SOCDevCardConstants.MONO);
pause(1500);
}
if (!expectWAITING_FOR_MONOPOLY) {
if (gameStatePLAY1 && (!doneTrading) && (!ourPlayerData.getResources().contains(targetResources))) {
waitingForTradeResponse = false;
if (robotParameters.getTradeFlag() == 1) {
makeOffer(targetPiece);
// makeOffer will set waitingForTradeResponse or doneTrading.
}
}
if (gameStatePLAY1 && !waitingForTradeResponse) {
/**
* trade with the bank/ports
*/
if (tradeToTarget2(targetResources)) {
counter = 0;
waitingForTradeMsg = true;
pause(1500);
}
}
// /
if ((!(waitingForTradeMsg || waitingForTradeResponse)) && ourPlayerData.getResources().contains(targetResources)) {
// Remember that targetPiece == buildingPlan.peek().
// Calls buildingPlan.pop().
// Checks against whatWeFailedToBuild to see if server has rejected this already.
// Calls client.buyDevCard or client.buildRequest.
// Sets waitingForDevCard, or waitingForGameState and expectPLACING_SETTLEMENT (etc).
// Sets waitingForPickSpecialItem if target piece is SOCPossiblePickSpecialItem.
buildRequestPlannedPiece();
}
}
}
}
use of soc.game.SOCResourceSet in project JSettlers2 by jdmonin.
the class SOCRobotBrain method handlePLAYERELEMENT.
/**
* Handle a player information update from a {@link SOCPlayerElement} or {@link SOCPlayerElements} message:
* Update a player's amount of a resource or a building type.
*<P>
* If this during the {@link SOCGame#ROLL_OR_CARD} state, then update the
* {@link SOCRobotNegotiator}'s is-selling flags.
*<P>
* If our player is losing a resource needed for the {@link #buildingPlan},
* clear the plan if this is for the Special Building Phase (on the 6-player board).
* In normal game play, we clear the building plan at the start of each turn.
*<P>
* Otherwise, only the game data is updated, nothing brain-specific.
*
* @param pl Player to update; some elements take null. If null and {@code pn != -1}, will find {@code pl}
* using {@link SOCGame#getPlayer(int) game.getPlayer(pn)}.
* @param pn Player number from message (sometimes -1 for none or all)
* @param action {@link SOCPlayerElement#SET}, {@link SOCPlayerElement#GAIN GAIN},
* or {@link SOCPlayerElement#LOSE LOSE}
* @param etype Element type, such as {@link SOCPlayerElement#SETTLEMENTS} or {@link SOCPlayerElement#NUMKNIGHTS}
* @param amount The new value to set, or the delta to gain/lose
* @since 2.0.00
*/
private void handlePLAYERELEMENT(SOCPlayer pl, final int pn, final int action, final int etype, final int amount) {
if ((pl == null) && (pn != -1))
pl = game.getPlayer(pn);
switch(etype) {
case SOCPlayerElement.ROADS:
SOCDisplaylessPlayerClient.handlePLAYERELEMENT_numPieces(pl, action, SOCPlayingPiece.ROAD, amount);
break;
case SOCPlayerElement.SETTLEMENTS:
SOCDisplaylessPlayerClient.handlePLAYERELEMENT_numPieces(pl, action, SOCPlayingPiece.SETTLEMENT, amount);
break;
case SOCPlayerElement.CITIES:
SOCDisplaylessPlayerClient.handlePLAYERELEMENT_numPieces(pl, action, SOCPlayingPiece.CITY, amount);
break;
case SOCPlayerElement.SHIPS:
SOCDisplaylessPlayerClient.handlePLAYERELEMENT_numPieces(pl, action, SOCPlayingPiece.SHIP, amount);
break;
case SOCPlayerElement.NUMKNIGHTS:
// PLAYERELEMENT(NUMKNIGHTS) is sent after a Soldier card is played.
SOCDisplaylessPlayerClient.handlePLAYERELEMENT_numKnights(game, pl, action, amount);
break;
case SOCPlayerElement.CLAY:
handlePLAYERELEMENT_numRsrc(pl, action, SOCResourceConstants.CLAY, "CLAY", amount);
break;
case SOCPlayerElement.ORE:
handlePLAYERELEMENT_numRsrc(pl, action, SOCResourceConstants.ORE, "ORE", amount);
break;
case SOCPlayerElement.SHEEP:
handlePLAYERELEMENT_numRsrc(pl, action, SOCResourceConstants.SHEEP, "SHEEP", amount);
break;
case SOCPlayerElement.WHEAT:
handlePLAYERELEMENT_numRsrc(pl, action, SOCResourceConstants.WHEAT, "WHEAT", amount);
break;
case SOCPlayerElement.WOOD:
handlePLAYERELEMENT_numRsrc(pl, action, SOCResourceConstants.WOOD, "WOOD", amount);
break;
case SOCPlayerElement.UNKNOWN:
/**
* Note: if losing unknown resources, we first
* convert player's known resources to unknown resources,
* then remove mes's unknown resources from player.
*/
handlePLAYERELEMENT_numRsrc(pl, action, SOCResourceConstants.UNKNOWN, "UNKNOWN", amount);
break;
case SOCPlayerElement.RESOURCE_COUNT:
if (amount != pl.getResources().getTotal()) {
SOCResourceSet rsrcs = pl.getResources();
if (D.ebugOn) {
client.sendText(game, ">>> RESOURCE COUNT ERROR FOR PLAYER " + pl.getPlayerNumber() + ": " + amount + " != " + rsrcs.getTotal());
}
//
if (pl.getPlayerNumber() != ourPlayerNumber) {
rsrcs.clear();
rsrcs.setAmount(amount, SOCResourceConstants.UNKNOWN);
}
}
break;
case SOCPlayerElement.SCENARIO_WARSHIP_COUNT:
if (expectPLACING_ROBBER && (action == SOCPlayerElement.GAIN)) {
// warship card successfully played; clear the flag fields
expectPLACING_ROBBER = false;
waitingForGameState = false;
}
default:
// handle ASK_SPECIAL_BUILD, NUM_PICK_GOLD_HEX_RESOURCES, SCENARIO_CLOTH_COUNT, etc;
// those are all self-contained informational fields that don't need any reaction from a bot.
SOCDisplaylessPlayerClient.handlePLAYERELEMENT_simple(game, pl, pn, action, etype, amount, ourPlayerName);
break;
}
// /
if (game.getGameState() == SOCGame.ROLL_OR_CARD) {
negotiator.resetIsSelling();
}
}
use of soc.game.SOCResourceSet in project JSettlers2 by jdmonin.
the class SOCRobotBrain method handleMAKEOFFER.
/**
* Handle a MAKEOFFER for this game.
* if another player makes an offer, that's the
* same as a rejection, but still wants to deal.
* Call {@link #considerOffer(SOCTradeOffer)}, and if
* we accept, clear our {@link #buildingPlan} so we'll replan it.
* Ignore our own MAKEOFFERs echoed from server.
* @since 1.1.08
*/
private void handleMAKEOFFER(SOCMakeOffer mes) {
SOCTradeOffer offer = mes.getOffer();
game.getPlayer(offer.getFrom()).setCurrentOffer(offer);
if ((offer.getFrom() == ourPlayerNumber)) {
// <---- Ignore our own offers ----
return;
}
// /
// / record that this player wants to sell me the stuff
// /
SOCResourceSet giveSet = offer.getGiveSet();
for (int rsrcType = SOCResourceConstants.CLAY; rsrcType <= SOCResourceConstants.WOOD; rsrcType++) {
if (giveSet.contains(rsrcType)) {
D.ebugPrintln("%%% player " + offer.getFrom() + " wants to sell " + rsrcType);
negotiator.markAsWantsAnotherOffer(offer.getFrom(), rsrcType);
}
}
// /
// / record that this player is not selling the resources
// / he is asking for
// /
SOCResourceSet getSet = offer.getGetSet();
for (int rsrcType = SOCResourceConstants.CLAY; rsrcType <= SOCResourceConstants.WOOD; rsrcType++) {
if (getSet.contains(rsrcType)) {
D.ebugPrintln("%%% player " + offer.getFrom() + " wants to buy " + rsrcType + " and therefore does not want to sell it");
negotiator.markAsNotSelling(offer.getFrom(), rsrcType);
}
}
if (waitingForTradeResponse) {
offerRejections[offer.getFrom()] = true;
boolean everyoneRejected = true;
D.ebugPrintln("ourPlayerData.getCurrentOffer() = " + ourPlayerData.getCurrentOffer());
if (ourPlayerData.getCurrentOffer() != null) {
boolean[] offeredTo = ourPlayerData.getCurrentOffer().getTo();
for (int i = 0; i < game.maxPlayers; i++) {
D.ebugPrintln("offerRejections[" + i + "]=" + offerRejections[i]);
if (offeredTo[i] && !offerRejections[i])
everyoneRejected = false;
}
}
D.ebugPrintln("everyoneRejected=" + everyoneRejected);
if (everyoneRejected) {
negotiator.addToOffersMade(ourPlayerData.getCurrentOffer());
client.clearOffer(game);
waitingForTradeResponse = false;
}
}
// /
// / consider the offer
// /
int ourResponseToOffer = considerOffer(offer);
D.ebugPrintln("%%% ourResponseToOffer = " + ourResponseToOffer);
if (ourResponseToOffer < 0)
// <--- Early return: SOCRobotNegotiator.IGNORE_OFFER ---
return;
int delayLength = Math.abs(rand.nextInt() % 500) + 3500;
if (gameIs6Player && !waitingForTradeResponse) {
// usually, pause is half-length in 6-player
delayLength *= 2;
}
pause(delayLength);
switch(ourResponseToOffer) {
case SOCRobotNegotiator.ACCEPT_OFFER:
client.acceptOffer(game, offer.getFrom());
// /
// / clear our building plan, so that we replan
// /
buildingPlan.clear();
negotiator.setTargetPiece(ourPlayerNumber, null);
break;
case SOCRobotNegotiator.REJECT_OFFER:
if (!waitingForTradeResponse)
client.rejectOffer(game);
break;
case SOCRobotNegotiator.COUNTER_OFFER:
if (!makeCounterOffer(offer))
client.rejectOffer(game);
break;
}
}
use of soc.game.SOCResourceSet in project JSettlers2 by jdmonin.
the class SOCRobotDM method scoreSettlementsForDumb.
/**
* For each possible settlement in our {@link SOCPlayerTracker},
* update its {@link SOCPossiblePiece#getETA() getETA()} and
* its {@link SOCPossibleSettlement#getRoadPath() getRoadPath()}.
*<P>
* Each {@link SOCPossibleSettlement#getRoadPath()} is calculated
* here by finding the shortest path among its {@link SOCPossibleSettlement#getNecessaryRoads()}.
*<P>
* Calculates ETA by using our current {@link SOCBuildingSpeedEstimate} on the resources
* needed to buy the settlement plus roads/ships for its shortest path's length.
*
* @param settlementETA ETA for building a settlement from now if it doesn't require any roads or ships
* @param ourBSE Current building speed estimate, from our {@code SOCPlayer#getNumbers()}
*
* @see #scorePossibleSettlements(int, int)
*/
protected void scoreSettlementsForDumb(final int settlementETA, SOCBuildingSpeedEstimate ourBSE) {
D.ebugPrintln("-- scoreSettlementsForDumb --");
Queue<Pair<SOCPossibleRoad, List<SOCPossibleRoad>>> queue = new Queue<Pair<SOCPossibleRoad, List<SOCPossibleRoad>>>();
Iterator<SOCPossibleSettlement> posSetsIter = ourPlayerTracker.getPossibleSettlements().values().iterator();
while (posSetsIter.hasNext()) {
SOCPossibleSettlement posSet = posSetsIter.next();
if (D.ebugOn) {
D.ebugPrintln("Estimate speedup of stlmt at " + game.getBoard().nodeCoordToString(posSet.getCoordinates()));
D.ebugPrintln("*** speedup total = " + posSet.getSpeedupTotal());
}
// /
// / find the shortest path to this settlement
// /
final List<SOCPossibleRoad> necRoadList = posSet.getNecessaryRoads();
if (!necRoadList.isEmpty()) {
// will use for BFS if needed:
queue.clear();
for (SOCPossibleRoad necRoad : necRoadList) {
if (D.ebugOn)
D.ebugPrintln("-- queuing necessary road at " + game.getBoard().edgeCoordToString(necRoad.getCoordinates()));
queue.put(new Pair<SOCPossibleRoad, List<SOCPossibleRoad>>(necRoad, null));
}
//
// Do a BFS of the necessary road paths looking for the shortest one.
//
boolean pathTooLong = false;
for (int maxIter = 50; maxIter > 0 && !queue.empty(); --maxIter) {
Pair<SOCPossibleRoad, List<SOCPossibleRoad>> dataPair = queue.get();
SOCPossibleRoad curRoad = dataPair.getA();
final List<SOCPossibleRoad> possRoadsToCur = dataPair.getB();
if (D.ebugOn)
D.ebugPrintln("-- current road at " + game.getBoard().edgeCoordToString(curRoad.getCoordinates()));
final List<SOCPossibleRoad> necRoads = curRoad.getNecessaryRoads();
if (necRoads.isEmpty()) {
//
// we have a path
//
D.ebugPrintln("Found a path!");
Stack<SOCPossibleRoad> path = new Stack<SOCPossibleRoad>();
path.push(curRoad);
if (D.ebugOn)
D.ebugPrintln("possRoadsToCur = " + possRoadsToCur);
if (possRoadsToCur != null)
// push to path, iterating from nearest to curRoad until most distant
for (int i = possRoadsToCur.size() - 1; i >= 0; --i) path.push(possRoadsToCur.get(i));
posSet.setRoadPath(path);
queue.clear();
D.ebugPrintln("Done setting path.");
} else {
final List<SOCPossibleRoad> possRoadsAndCur = (possRoadsToCur != null) ? new ArrayList<SOCPossibleRoad>(possRoadsToCur) : new ArrayList<SOCPossibleRoad>();
possRoadsAndCur.add(curRoad);
if (queue.size() + necRoads.size() > 40) {
// Too many necessary, or dupes led to loop. Bug in necessary road construction?
System.err.println("rDM.scoreSettlementsForDumb: Necessary Road Path too long for road/ship 0x" + Integer.toHexString(curRoad.getCoordinates()) + " for settle 0x" + Integer.toHexString(posSet.getCoordinates()));
pathTooLong = true;
queue.clear();
break;
}
for (SOCPossibleRoad necRoad2 : necRoads) {
if (D.ebugOn)
D.ebugPrintln("-- queuing necessary road at " + game.getBoard().edgeCoordToString(necRoad2.getCoordinates()));
queue.put(new Pair<SOCPossibleRoad, List<SOCPossibleRoad>>(necRoad2, possRoadsAndCur));
}
}
}
if (!queue.empty()) {
System.err.println("rDM.scoreSettlementsForDumb: Necessary Road Path length unresolved for settle 0x" + Integer.toHexString(posSet.getCoordinates()));
pathTooLong = true;
}
D.ebugPrintln("Done searching for path.");
//
if (pathTooLong) {
posSet.setETA(500);
} else {
SOCResourceSet targetResources = new SOCResourceSet();
targetResources.add(SOCSettlement.COST);
Stack<SOCPossibleRoad> path = posSet.getRoadPath();
if (path != null) {
final int pathLength = path.size();
final SOCPossiblePiece pathFirst = (pathLength > 0) ? path.peek() : null;
SOCResourceSet rtype = ((pathFirst != null) && (pathFirst instanceof SOCPossibleShip) && // TODO better coastal ETA scoring
!((SOCPossibleShip) pathFirst).isCoastalRoadAndShip) ? SOCShip.COST : SOCRoad.COST;
for (int i = 0; i < pathLength; i++) targetResources.add(rtype);
}
posSet.setETA(ourBSE.calculateRollsFast(ourPlayerData.getResources(), targetResources, 100, ourPlayerData.getPortFlags()));
}
} else {
//
// no roads are necessary
//
posSet.setRoadPath(null);
posSet.setETA(settlementETA);
}
D.ebugPrintln("Settlement ETA = " + posSet.getETA());
}
}
use of soc.game.SOCResourceSet in project JSettlers2 by jdmonin.
the class SOCRobotDM method dumbFastGameStrategy.
/**
* Plan building for the dumbFastGameStrategy ({@link #FAST_STRATEGY}).
* uses rules to determine what to build next
* and update {@link #buildingPlan}.
*<P>
* For example, if {@link #favoriteSettlement} is chosen,
* it's chosen from {@link #ourPlayerTracker}{@link SOCPlayerTracker#getPossibleSettlements() .getPossibleSettlements()}.
*
*<H4>Outline:</H4>
* Possible cities and settlements are looked at first.
* Find the city with best {@link SOCPossibleCity#getSpeedupTotal()}, then check each possible
* settlement's {@link SOCPossiblePiece#getETA()} against the city's ETA to possibly choose one to build.
* (If one is chosen, its {@link SOCPossibleSettlement#getNecessaryRoads()}
* will also be chosen here.) Then, Knights or Dev Cards.
* Only then would roads or ships be looked at, for Longest Route
* (and only if we're at 5 VP or more).
*<P>
* This method never directly checks
* {@code ourPlayerTracker}{@link SOCPlayerTracker#getPossibleRoads() .getPossibleRoads()}, instead
* it adds the roads or ships from {@link SOCPossibleSettlement#getNecessaryRoads()} to {@link #buildingPlan}
* when a possible settlement is picked to build.
*<P>
* Some scenarios require special moves or certain actions to win the game. If we're playing in
* such a scenario, after calculating {@link #favoriteSettlement}, {@link #favoriteCity}, etc, calls
* {@link #scenarioGameStrategyPlan(float, float, boolean, boolean, SOCBuildingSpeedEstimate, int, boolean)}.
* See that method for the list of scenarios which need such planning.
*
* @param buildingETAs the ETAs for building each piece type
* @see #smartGameStrategy(int[])
*/
protected void dumbFastGameStrategy(final int[] buildingETAs) {
D.ebugPrintln("***** dumbFastGameStrategy *****");
// If this game is on the 6-player board, check whether we're planning for
// the Special Building Phase. Can't buy cards or trade in that phase.
final boolean forSpecialBuildingPhase = game.isSpecialBuilding() || (game.getCurrentPlayerNumber() != ourPlayerNumber);
int bestETA = 500;
SOCBuildingSpeedEstimate ourBSE = new SOCBuildingSpeedEstimate(ourPlayerData.getNumbers());
if (ourPlayerData.getTotalVP() < 5) {
//
if (ourPlayerData.getNumPieces(SOCPlayingPiece.CITY) > 0) {
Iterator<SOCPossibleCity> posCitiesIter = ourPlayerTracker.getPossibleCities().values().iterator();
while (posCitiesIter.hasNext()) {
SOCPossibleCity posCity = posCitiesIter.next();
D.ebugPrintln("Estimate speedup of city at " + game.getBoard().nodeCoordToString(posCity.getCoordinates()));
D.ebugPrintln("Speedup = " + posCity.getSpeedupTotal());
D.ebugPrintln("ETA = " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
if ((brain != null) && brain.getDRecorder().isOn()) {
brain.getDRecorder().startRecording("CITY" + posCity.getCoordinates());
brain.getDRecorder().record("Estimate speedup of city at " + game.getBoard().nodeCoordToString(posCity.getCoordinates()));
brain.getDRecorder().record("Speedup = " + posCity.getSpeedupTotal());
brain.getDRecorder().record("ETA = " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
brain.getDRecorder().stopRecording();
}
if ((favoriteCity == null) || (posCity.getSpeedupTotal() > favoriteCity.getSpeedupTotal())) {
favoriteCity = posCity;
bestETA = buildingETAs[SOCBuildingSpeedEstimate.CITY];
}
}
}
//
// score the possible settlements
//
scoreSettlementsForDumb(buildingETAs[SOCBuildingSpeedEstimate.SETTLEMENT], ourBSE);
//
// pick something to build
//
Iterator<SOCPossibleSettlement> posSetsIter = ourPlayerTracker.getPossibleSettlements().values().iterator();
while (posSetsIter.hasNext()) {
SOCPossibleSettlement posSet = posSetsIter.next();
if ((brain != null) && brain.getDRecorder().isOn()) {
brain.getDRecorder().startRecording("SETTLEMENT" + posSet.getCoordinates());
brain.getDRecorder().record("Estimate speedup of stlmt at " + game.getBoard().nodeCoordToString(posSet.getCoordinates()));
brain.getDRecorder().record("Speedup = " + posSet.getSpeedupTotal());
brain.getDRecorder().record("ETA = " + posSet.getETA());
Stack<SOCPossibleRoad> roadPath = posSet.getRoadPath();
if (roadPath != null) {
brain.getDRecorder().record("Path:");
Iterator<SOCPossibleRoad> rpIter = roadPath.iterator();
while (rpIter.hasNext()) {
SOCPossibleRoad posRoad = rpIter.next();
brain.getDRecorder().record("Road at " + game.getBoard().edgeCoordToString(posRoad.getCoordinates()));
}
}
brain.getDRecorder().stopRecording();
}
if (posSet.getETA() < bestETA) {
bestETA = posSet.getETA();
favoriteSettlement = posSet;
} else if (posSet.getETA() == bestETA) {
if (favoriteSettlement == null) {
if ((favoriteCity == null) || (posSet.getSpeedupTotal() > favoriteCity.getSpeedupTotal())) {
favoriteSettlement = posSet;
}
} else {
if (posSet.getSpeedupTotal() > favoriteSettlement.getSpeedupTotal()) {
favoriteSettlement = posSet;
}
}
}
}
if (favoriteSettlement != null) {
//
// we want to build a settlement
//
D.ebugPrintln("Picked favorite settlement at " + game.getBoard().nodeCoordToString(favoriteSettlement.getCoordinates()));
buildingPlan.push(favoriteSettlement);
if (!favoriteSettlement.getNecessaryRoads().isEmpty()) {
//
// we need to build roads first
//
Stack<SOCPossibleRoad> roadPath = favoriteSettlement.getRoadPath();
while (!roadPath.empty()) {
buildingPlan.push(roadPath.pop());
}
}
} else if (favoriteCity != null) {
//
// we want to build a city
//
D.ebugPrintln("Picked favorite city at " + game.getBoard().nodeCoordToString(favoriteCity.getCoordinates()));
buildingPlan.push(favoriteCity);
} else {
//
if ((game.getNumDevCards() > 0) && !forSpecialBuildingPhase) {
//
// buy a card if there are any left
//
D.ebugPrintln("Buy a card");
SOCPossibleCard posCard = new SOCPossibleCard(ourPlayerData, buildingETAs[SOCBuildingSpeedEstimate.CARD]);
buildingPlan.push(posCard);
}
}
} else {
//
// we have more than 4 points
//
int choice = -1;
//
// consider Largest Army
//
D.ebugPrintln("Calculating Largest Army ETA");
int laETA = 500;
int laSize = 0;
SOCPlayer laPlayer = game.getPlayerWithLargestArmy();
if (laPlayer == null) {
// /
// / no one has largest army
// /
laSize = 3;
} else if (laPlayer.getPlayerNumber() == ourPlayerNumber) {
// /
// / we have largest army
// /
D.ebugPrintln("We have largest army");
} else {
laSize = laPlayer.getNumKnights() + 1;
}
// /
// / figure out how many knights we need to buy
// /
int knightsToBuy = 0;
if ((ourPlayerData.getNumKnights() + // OLD + NEW knights
ourPlayerData.getInventory().getAmount(SOCDevCardConstants.KNIGHT)) < laSize) {
knightsToBuy = laSize - (ourPlayerData.getNumKnights() + ourPlayerData.getInventory().getAmount(SOCInventory.OLD, SOCDevCardConstants.KNIGHT));
}
D.ebugPrintln("knightsToBuy = " + knightsToBuy);
if (ourPlayerData.getGame().getNumDevCards() >= knightsToBuy) {
// /
// / figure out how long it takes to buy this many knights
// /
SOCResourceSet targetResources = new SOCResourceSet();
for (int i = 0; i < knightsToBuy; i++) {
targetResources.add(SOCDevCard.COST);
}
laETA = ourBSE.calculateRollsFast(ourPlayerData.getResources(), targetResources, 100, ourPlayerData.getPortFlags());
} else {
// /
// / not enough dev cards left
// /
}
if ((laETA < bestETA) && !forSpecialBuildingPhase) {
bestETA = laETA;
choice = LA_CHOICE;
}
D.ebugPrintln("laETA = " + laETA);
//
// consider Longest Road
//
D.ebugPrintln("Calculating Longest Road ETA");
int lrETA = 500;
Stack<?> bestLRPath = null;
int lrLength;
SOCPlayer lrPlayer = game.getPlayerWithLongestRoad();
if ((lrPlayer != null) && (lrPlayer.getPlayerNumber() == ourPlayerNumber)) {
// /
// / we have longest road
// /
D.ebugPrintln("We have longest road");
} else if (!game.isGameOptionSet(SOCGameOption.K_SC_0RVP)) {
if (lrPlayer == null) {
// /
// / no one has longest road
// /
lrLength = Math.max(4, ourPlayerData.getLongestRoadLength());
} else {
lrLength = lrPlayer.getLongestRoadLength();
}
Iterator<SOCLRPathData> lrPathsIter = ourPlayerData.getLRPaths().iterator();
int depth;
while (lrPathsIter.hasNext()) {
Stack<?> path;
SOCLRPathData pathData = lrPathsIter.next();
depth = Math.min(((lrLength + 1) - pathData.getLength()), ourPlayerData.getNumPieces(SOCPlayingPiece.ROAD));
path = (Stack<?>) recalcLongestRoadETAAux(ourPlayerData, true, pathData.getBeginning(), pathData.getLength(), lrLength, depth);
if ((path != null) && ((bestLRPath == null) || (path.size() < bestLRPath.size()))) {
bestLRPath = path;
}
path = (Stack<?>) recalcLongestRoadETAAux(ourPlayerData, true, pathData.getEnd(), pathData.getLength(), lrLength, depth);
if ((path != null) && ((bestLRPath == null) || (path.size() < bestLRPath.size()))) {
bestLRPath = path;
}
}
if (bestLRPath != null) {
//
// calculate LR eta
//
D.ebugPrintln("Number of roads: " + bestLRPath.size());
SOCResourceSet targetResources = new SOCResourceSet();
for (int i = 0; i < bestLRPath.size(); i++) {
targetResources.add(SOCRoad.COST);
}
lrETA = ourBSE.calculateRollsFast(ourPlayerData.getResources(), targetResources, 100, ourPlayerData.getPortFlags());
}
}
if (lrETA < bestETA) {
bestETA = lrETA;
choice = LR_CHOICE;
}
D.ebugPrintln("lrETA = " + lrETA);
//
if ((ourPlayerData.getNumPieces(SOCPlayingPiece.CITY) > 0) && (buildingETAs[SOCBuildingSpeedEstimate.CITY] <= bestETA)) {
Iterator<SOCPossibleCity> posCitiesIter = ourPlayerTracker.getPossibleCities().values().iterator();
while (posCitiesIter.hasNext()) {
SOCPossibleCity posCity = posCitiesIter.next();
if ((brain != null) && brain.getDRecorder().isOn()) {
brain.getDRecorder().startRecording("CITY" + posCity.getCoordinates());
brain.getDRecorder().record("Estimate speedup of city at " + game.getBoard().nodeCoordToString(posCity.getCoordinates()));
brain.getDRecorder().record("Speedup = " + posCity.getSpeedupTotal());
brain.getDRecorder().record("ETA = " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
brain.getDRecorder().stopRecording();
}
if ((favoriteCity == null) || (posCity.getSpeedupTotal() > favoriteCity.getSpeedupTotal())) {
favoriteCity = posCity;
bestETA = buildingETAs[SOCBuildingSpeedEstimate.CITY];
choice = CITY_CHOICE;
}
}
}
//
if (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) > 0) {
scoreSettlementsForDumb(buildingETAs[SOCBuildingSpeedEstimate.SETTLEMENT], ourBSE);
Iterator<SOCPossibleSettlement> posSetsIter = ourPlayerTracker.getPossibleSettlements().values().iterator();
while (posSetsIter.hasNext()) {
SOCPossibleSettlement posSet = posSetsIter.next();
if ((brain != null) && brain.getDRecorder().isOn()) {
brain.getDRecorder().startRecording("SETTLEMENT" + posSet.getCoordinates());
brain.getDRecorder().record("Estimate speedup of stlmt at " + game.getBoard().nodeCoordToString(posSet.getCoordinates()));
brain.getDRecorder().record("Speedup = " + posSet.getSpeedupTotal());
brain.getDRecorder().record("ETA = " + posSet.getETA());
Stack<SOCPossibleRoad> roadPath = posSet.getRoadPath();
if (roadPath != null) {
brain.getDRecorder().record("Path:");
Iterator<SOCPossibleRoad> rpIter = roadPath.iterator();
while (rpIter.hasNext()) {
SOCPossibleRoad posRoad = rpIter.next();
brain.getDRecorder().record("Road at " + game.getBoard().edgeCoordToString(posRoad.getCoordinates()));
}
}
brain.getDRecorder().stopRecording();
}
if ((posSet.getRoadPath() == null) || (ourPlayerData.getNumPieces(SOCPlayingPiece.ROAD) >= posSet.getRoadPath().size())) {
if (posSet.getETA() < bestETA) {
bestETA = posSet.getETA();
favoriteSettlement = posSet;
choice = SETTLEMENT_CHOICE;
} else if (posSet.getETA() == bestETA) {
if (favoriteSettlement == null) {
if ((favoriteCity == null) || (posSet.getSpeedupTotal() > favoriteCity.getSpeedupTotal())) {
favoriteSettlement = posSet;
choice = SETTLEMENT_CHOICE;
}
} else {
if (posSet.getSpeedupTotal() > favoriteSettlement.getSpeedupTotal()) {
favoriteSettlement = posSet;
}
}
}
}
}
}
if (game.isGameOptionSet(SOCGameOption.K_SC_PIRI) || game.isGameOptionSet(SOCGameOption.K_SC_WOND)) {
if (scenarioGameStrategyPlan(bestETA, -1f, false, (choice == LA_CHOICE), ourBSE, 0, forSpecialBuildingPhase))
// <--- Early return: Scenario-specific buildingPlan was pushed ---
return;
}
//
switch(choice) {
case LA_CHOICE:
D.ebugPrintln("Picked LA");
if (!forSpecialBuildingPhase) {
for (int i = 0; i < knightsToBuy; i++) {
SOCPossibleCard posCard = new SOCPossibleCard(ourPlayerData, 1);
buildingPlan.push(posCard);
}
}
break;
case LR_CHOICE:
D.ebugPrintln("Picked LR");
while (!bestLRPath.empty()) {
SOCPossibleRoad pr = (SOCPossibleRoad) bestLRPath.pop();
D.ebugPrintln("LR road at " + game.getBoard().edgeCoordToString(pr.getCoordinates()));
buildingPlan.push(pr);
}
break;
case CITY_CHOICE:
D.ebugPrintln("Picked favorite city at " + game.getBoard().nodeCoordToString(favoriteCity.getCoordinates()));
buildingPlan.push(favoriteCity);
break;
case SETTLEMENT_CHOICE:
D.ebugPrintln("Picked favorite settlement at " + game.getBoard().nodeCoordToString(favoriteSettlement.getCoordinates()));
buildingPlan.push(favoriteSettlement);
if (!favoriteSettlement.getNecessaryRoads().isEmpty()) {
//
// we need to build roads first
//
Stack<SOCPossibleRoad> roadPath = favoriteSettlement.getRoadPath();
while (!roadPath.empty()) {
SOCPossibleRoad pr = roadPath.pop();
D.ebugPrintln("Nec road at " + game.getBoard().edgeCoordToString(pr.getCoordinates()));
buildingPlan.push(pr);
}
}
}
}
}
Aggregations