use of soc.game.SOCCity in project JSettlers2 by jdmonin.
the class SOCRobotDM method smartGameStrategy.
/**
* Plan building for the smart game strategy ({@link #SMART_STRATEGY}).
* use player trackers' Win Game ETAs (WGETA) to determine best move
* and update {@link #buildingPlan}.
*<P>
* For example, if {@link #favoriteSettlement} is chosen,
* it's chosen from {@link #goodSettlements} or {@link #threatenedSettlements}.
*<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.
*
*<H4>Outline:</H4>
*<UL>
* <LI> Determine our Win Game ETA, leading player's WGETA
* <LI> {@link #scorePossibleSettlements(int, int) scorePossibleSettlements(BuildETAs, leaderWGETA)}:
* For each settlement we can build now (no roads/ships needed), add its ETA bonus to its score
* <LI> Build {@link #goodRoads} from possibleRoads' roads & ships we can build now
* <LI> Pick a {@link #favoriteSettlement} from threatened/good settlements, with the highest
* {@link SOCPossiblePiece#getScore() getScore()} (ETA bonus)
* <LI> Pick a {@link #favoriteRoad} from threatened/good, with highest getWinGameETABonusForRoad
* <LI> Pick a {@link #favoriteCity} from our possibleCities, with highest score (ETA bonus)
* <LI> If {@code favoriteCity} has the best score (best ETA if tied), choose to build the city
* <LI> Otherwise choose {@code favoriteRoad} or {@code favoriteSettlement} based on their scores
* <LI> If buying a dev card scores higher than the chosen piece, choose to buy one instead of building
* <LI> Check for and calc any scenario-specific {@code buildingPlan}
*</UL>
*
* @param buildingETAs the ETAs for building each piece type
* @see #dumbFastGameStrategy(int[])
*/
protected void smartGameStrategy(final int[] buildingETAs) {
D.ebugPrintln("***** smartGameStrategy *****");
// 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);
//
// save the lr paths list to restore later
//
@SuppressWarnings("unchecked") List<SOCLRPathData>[] savedLRPaths = new List[game.maxPlayers];
for (int pn = 0; pn < game.maxPlayers; pn++) {
savedLRPaths[pn] = new ArrayList<SOCLRPathData>();
savedLRPaths[pn].addAll(game.getPlayer(pn).getLRPaths());
}
int ourCurrentWGETA = ourPlayerTracker.getWinGameETA();
D.ebugPrintln("ourCurrentWGETA = " + ourCurrentWGETA);
int leadersCurrentWGETA = ourCurrentWGETA;
Iterator<SOCPlayerTracker> trackersIter = playerTrackers.values().iterator();
while (trackersIter.hasNext()) {
SOCPlayerTracker tracker = trackersIter.next();
int wgeta = tracker.getWinGameETA();
if (wgeta < leadersCurrentWGETA) {
leadersCurrentWGETA = wgeta;
}
}
// /
if (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) > 0) {
scorePossibleSettlements(buildingETAs[SOCBuildingSpeedEstimate.SETTLEMENT], leadersCurrentWGETA);
}
// /
if (ourPlayerData.getNumPieces(SOCPlayingPiece.ROAD) > 0) {
Iterator<SOCPossibleRoad> posRoadsIter = ourPlayerTracker.getPossibleRoads().values().iterator();
while (posRoadsIter.hasNext()) {
SOCPossibleRoad posRoad = posRoadsIter.next();
if (!posRoad.isRoadNotShip())
// ignore ships in this loop, ships have other conditions to check
continue;
if ((posRoad.getNecessaryRoads().isEmpty()) && (!threatenedRoads.contains(posRoad)) && (!goodRoads.contains(posRoad))) {
goodRoads.add(posRoad);
}
}
}
// /
if (ourPlayerData.getNumPieces(SOCPlayingPiece.SHIP) > 0) {
final SOCBoard board = game.getBoard();
final int pirateHex = (board instanceof SOCBoardLarge) ? ((SOCBoardLarge) board).getPirateHex() : 0;
final int[] pirateEdges = (pirateHex != 0) ? ((SOCBoardLarge) board).getAdjacentEdgesToHex_arr(pirateHex) : null;
Iterator<SOCPossibleRoad> posRoadsIter = ourPlayerTracker.getPossibleRoads().values().iterator();
while (posRoadsIter.hasNext()) {
final SOCPossibleRoad posRoad = posRoadsIter.next();
if (posRoad.isRoadNotShip())
// ignore roads in this loop, we want ships
continue;
if (posRoad.getNecessaryRoads().isEmpty() && (!threatenedRoads.contains(posRoad)) && (!goodRoads.contains(posRoad))) {
boolean edgeOK = true;
if (pirateEdges != null) {
final int edge = posRoad.getCoordinates();
for (int i = 0; i < pirateEdges.length; ++i) {
if (edge == pirateEdges[i]) {
edgeOK = false;
break;
}
}
}
if (edgeOK)
goodRoads.add(posRoad);
}
}
}
/*
///
/// check everything
///
Enumeration threatenedSetEnum = threatenedSettlements.elements();
while (threatenedSetEnum.hasMoreElements()) {
SOCPossibleSettlement threatenedSet = (SOCPossibleSettlement)threatenedSetEnum.nextElement();
D.ebugPrintln("*** threatened settlement at "+Integer.toHexString(threatenedSet.getCoordinates())+" has a score of "+threatenedSet.getScore());
if (threatenedSet.getNecessaryRoads().isEmpty() &&
! ourPlayerData.isPotentialSettlement(threatenedSet.getCoordinates())) {
D.ebugPrintln("POTENTIAL SETTLEMENT ERROR");
//System.exit(0);
}
}
Enumeration goodSetEnum = goodSettlements.elements();
while (goodSetEnum.hasMoreElements()) {
SOCPossibleSettlement goodSet = (SOCPossibleSettlement)goodSetEnum.nextElement();
D.ebugPrintln("*** good settlement at "+Integer.toHexString(goodSet.getCoordinates())+" has a score of "+goodSet.getScore());
if (goodSet.getNecessaryRoads().isEmpty() &&
! ourPlayerData.isPotentialSettlement(goodSet.getCoordinates())) {
D.ebugPrintln("POTENTIAL SETTLEMENT ERROR");
//System.exit(0);
}
}
Enumeration threatenedRoadEnum = threatenedRoads.elements();
while (threatenedRoadEnum.hasMoreElements()) {
SOCPossibleRoad threatenedRoad = (SOCPossibleRoad)threatenedRoadEnum.nextElement();
D.ebugPrintln("*** threatened road at "+Integer.toHexString(threatenedRoad.getCoordinates())+" has a score of "+threatenedRoad.getScore());
if (threatenedRoad.getNecessaryRoads().isEmpty() &&
! ourPlayerData.isPotentialRoad(threatenedRoad.getCoordinates())) {
D.ebugPrintln("POTENTIAL ROAD ERROR");
//System.exit(0);
}
}
Enumeration goodRoadEnum = goodRoads.elements();
while (goodRoadEnum.hasMoreElements()) {
SOCPossibleRoad goodRoad = (SOCPossibleRoad)goodRoadEnum.nextElement();
D.ebugPrintln("*** good road at "+Integer.toHexString(goodRoad.getCoordinates())+" has a score of "+goodRoad.getScore());
if (goodRoad.getNecessaryRoads().isEmpty() &&
! ourPlayerData.isPotentialRoad(goodRoad.getCoordinates())) {
D.ebugPrintln("POTENTIAL ROAD ERROR");
//System.exit(0);
}
}
*/
D.ebugPrintln("PICKING WHAT TO BUILD");
// /
if (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) > 0) {
for (SOCPossibleSettlement threatenedSet : threatenedSettlements) {
if (threatenedSet.getNecessaryRoads().isEmpty()) {
D.ebugPrintln("$$$$$ threatened settlement at " + Integer.toHexString(threatenedSet.getCoordinates()) + " has a score of " + threatenedSet.getScore());
if ((favoriteSettlement == null) || (threatenedSet.getScore() > favoriteSettlement.getScore())) {
favoriteSettlement = threatenedSet;
}
}
}
for (SOCPossibleSettlement goodSet : goodSettlements) {
if (goodSet.getNecessaryRoads().isEmpty()) {
D.ebugPrintln("$$$$$ good settlement at " + Integer.toHexString(goodSet.getCoordinates()) + " has a score of " + goodSet.getScore());
if ((favoriteSettlement == null) || (goodSet.getScore() > favoriteSettlement.getScore())) {
favoriteSettlement = goodSet;
}
}
}
}
//
// restore the LRPath list
//
D.ebugPrintln("%%% RESTORING LRPATH LIST %%%");
for (int pn = 0; pn < game.maxPlayers; pn++) {
game.getPlayer(pn).setLRPaths(savedLRPaths[pn]);
}
// /
if (ourPlayerData.getNumPieces(SOCPlayingPiece.ROAD) > 0) {
for (SOCPossibleRoad threatenedRoad : threatenedRoads) {
D.ebugPrintln("$$$$$ threatened road at " + Integer.toHexString(threatenedRoad.getCoordinates()));
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().startRecording("ROAD" + threatenedRoad.getCoordinates());
brain.getDRecorder().record("Estimate value of road at " + game.getBoard().edgeCoordToString(threatenedRoad.getCoordinates()));
}
//
// see how building this piece impacts our winETA
//
threatenedRoad.resetScore();
float wgetaScore = getWinGameETABonusForRoad(threatenedRoad, buildingETAs[SOCBuildingSpeedEstimate.ROAD], leadersCurrentWGETA, playerTrackers);
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().stopRecording();
}
D.ebugPrintln("wgetaScore = " + wgetaScore);
if (favoriteRoad == null) {
favoriteRoad = threatenedRoad;
} else {
if (threatenedRoad.getScore() > favoriteRoad.getScore()) {
favoriteRoad = threatenedRoad;
}
}
}
for (SOCPossibleRoad goodRoad : goodRoads) {
D.ebugPrintln("$$$$$ good road at " + Integer.toHexString(goodRoad.getCoordinates()));
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().startRecording("ROAD" + goodRoad.getCoordinates());
brain.getDRecorder().record("Estimate value of road at " + game.getBoard().edgeCoordToString(goodRoad.getCoordinates()));
}
//
// see how building this piece impacts our winETA
//
// TODO better ETA scoring for coastal ships/roads
//
goodRoad.resetScore();
final int etype = ((goodRoad instanceof SOCPossibleShip) && !((SOCPossibleShip) goodRoad).isCoastalRoadAndShip) ? SOCBuildingSpeedEstimate.ROAD : SOCBuildingSpeedEstimate.SHIP;
float wgetaScore = getWinGameETABonusForRoad(goodRoad, buildingETAs[etype], leadersCurrentWGETA, playerTrackers);
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().stopRecording();
}
D.ebugPrintln("wgetaScore = " + wgetaScore);
if (favoriteRoad == null) {
favoriteRoad = goodRoad;
} else {
if (goodRoad.getScore() > favoriteRoad.getScore()) {
favoriteRoad = goodRoad;
}
}
}
}
//
// restore the LRPath list
//
D.ebugPrintln("%%% RESTORING LRPATH LIST %%%");
for (int pn = 0; pn < game.maxPlayers; pn++) {
game.getPlayer(pn).setLRPaths(savedLRPaths[pn]);
}
// /
if (ourPlayerData.getNumPieces(SOCPlayingPiece.CITY) > 0) {
HashMap<Integer, SOCPlayerTracker> trackersCopy = SOCPlayerTracker.copyPlayerTrackers(playerTrackers);
SOCPlayerTracker ourTrackerCopy = trackersCopy.get(Integer.valueOf(ourPlayerNumber));
int[] originalWGETAs = new int[game.maxPlayers];
int[] WGETAdiffs = new int[game.maxPlayers];
Vector<SOCPlayerTracker> leaders = new Vector<SOCPlayerTracker>();
int bestWGETA = 1000;
// int bonus = 0;
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 value of city at " + game.getBoard().nodeCoordToString(posCity.getCoordinates()));
}
//
// see how building this piece impacts our winETA
//
leaders.clear();
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().suspend();
}
SOCPlayerTracker.updateWinGameETAs(trackersCopy);
// TODO refactor? This section is like a copy of calcWGETABonus, with something added in the middle
Iterator<SOCPlayerTracker> trackersBeforeIter = trackersCopy.values().iterator();
while (trackersBeforeIter.hasNext()) {
SOCPlayerTracker trackerBefore = trackersBeforeIter.next();
final int pn = trackerBefore.getPlayer().getPlayerNumber();
D.ebugPrintln("$$$ win game ETA for player " + pn + " = " + trackerBefore.getWinGameETA());
originalWGETAs[pn] = trackerBefore.getWinGameETA();
WGETAdiffs[pn] = trackerBefore.getWinGameETA();
if (trackerBefore.getWinGameETA() < bestWGETA) {
bestWGETA = trackerBefore.getWinGameETA();
leaders.removeAllElements();
leaders.addElement(trackerBefore);
} else if (trackerBefore.getWinGameETA() == bestWGETA) {
leaders.addElement(trackerBefore);
}
}
D.ebugPrintln("^^^^ bestWGETA = " + bestWGETA);
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().resume();
}
//
// place the city
//
SOCCity tmpCity = new SOCCity(ourPlayerData, posCity.getCoordinates(), null);
game.putTempPiece(tmpCity);
ourTrackerCopy.addOurNewCity(tmpCity);
SOCPlayerTracker.updateWinGameETAs(trackersCopy);
float wgetaScore = calcWGETABonusAux(originalWGETAs, trackersCopy, leaders);
//
// remove the city
//
ourTrackerCopy.undoAddOurNewCity(posCity);
game.undoPutTempPiece(tmpCity);
D.ebugPrintln("*** ETA for city = " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().record("ETA = " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
}
float etaBonus = getETABonus(buildingETAs[SOCBuildingSpeedEstimate.CITY], leadersCurrentWGETA, wgetaScore);
D.ebugPrintln("etaBonus = " + etaBonus);
posCity.addToScore(etaBonus);
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().record("WGETA score = " + df1.format(wgetaScore));
brain.getDRecorder().record("Total city score = " + df1.format(etaBonus));
brain.getDRecorder().stopRecording();
}
D.ebugPrintln("$$$ final score = " + posCity.getScore());
D.ebugPrintln("$$$$$ possible city at " + Integer.toHexString(posCity.getCoordinates()) + " has a score of " + posCity.getScore());
if ((favoriteCity == null) || (posCity.getScore() > favoriteCity.getScore())) {
favoriteCity = posCity;
}
}
}
if (favoriteSettlement != null) {
D.ebugPrintln("### FAVORITE SETTLEMENT IS AT " + Integer.toHexString(favoriteSettlement.getCoordinates()));
D.ebugPrintln("### WITH A SCORE OF " + favoriteSettlement.getScore());
D.ebugPrintln("### WITH AN ETA OF " + buildingETAs[SOCBuildingSpeedEstimate.SETTLEMENT]);
D.ebugPrintln("### WITH A TOTAL SPEEDUP OF " + favoriteSettlement.getSpeedupTotal());
}
if (favoriteCity != null) {
D.ebugPrintln("### FAVORITE CITY IS AT " + Integer.toHexString(favoriteCity.getCoordinates()));
D.ebugPrintln("### WITH A SCORE OF " + favoriteCity.getScore());
D.ebugPrintln("### WITH AN ETA OF " + buildingETAs[SOCBuildingSpeedEstimate.CITY]);
D.ebugPrintln("### WITH A TOTAL SPEEDUP OF " + favoriteCity.getSpeedupTotal());
}
final int road_eta_type = ((favoriteRoad != null) && (favoriteRoad instanceof SOCPossibleShip) && // TODO better ETA calc for coastal roads/ships
!((SOCPossibleShip) favoriteRoad).isCoastalRoadAndShip) ? SOCBuildingSpeedEstimate.SHIP : SOCBuildingSpeedEstimate.ROAD;
if (favoriteRoad != null) {
D.ebugPrintln("### FAVORITE ROAD IS AT " + Integer.toHexString(favoriteRoad.getCoordinates()));
D.ebugPrintln("### WITH AN ETA OF " + buildingETAs[road_eta_type]);
D.ebugPrintln("### WITH A SCORE OF " + favoriteRoad.getScore());
}
// piece type, if any, to be pushed onto buildingPlan;
int pick = -1;
// use ROAD for road or ship, use MAXPLUSONE for dev card
// getScore() of picked piece
float pickScore = 0f;
// /
if ((favoriteCity != null) && (ourPlayerData.getNumPieces(SOCPlayingPiece.CITY) > 0) && (favoriteCity.getScore() > 0) && ((favoriteSettlement == null) || (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) == 0) || (favoriteCity.getScore() > favoriteSettlement.getScore()) || ((favoriteCity.getScore() == favoriteSettlement.getScore()) && (buildingETAs[SOCBuildingSpeedEstimate.CITY] < buildingETAs[SOCBuildingSpeedEstimate.SETTLEMENT]))) && ((favoriteRoad == null) || (ourPlayerData.getNumPieces(favoriteRoad.getType()) == 0) || (favoriteCity.getScore() > favoriteRoad.getScore()) || ((favoriteCity.getScore() == favoriteRoad.getScore()) && (buildingETAs[SOCBuildingSpeedEstimate.CITY] < buildingETAs[road_eta_type])))) {
D.ebugPrintln("### PICKED FAVORITE CITY");
pick = SOCPlayingPiece.CITY;
pickScore = favoriteCity.getScore();
} else // /
if ((favoriteRoad != null) && (ourPlayerData.getNumPieces(favoriteRoad.getType()) > 0) && (favoriteRoad.getScore() > 0) && ((favoriteSettlement == null) || (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) == 0) || (favoriteSettlement.getScore() < favoriteRoad.getScore()))) {
D.ebugPrintln("### PICKED FAVORITE ROAD");
// also represents SHIP here
pick = SOCPlayingPiece.ROAD;
pickScore = favoriteRoad.getScore();
} else if ((favoriteSettlement != null) && (ourPlayerData.getNumPieces(SOCPlayingPiece.SETTLEMENT) > 0)) {
D.ebugPrintln("### PICKED FAVORITE SETTLEMENT");
pick = SOCPlayingPiece.SETTLEMENT;
pickScore = favoriteSettlement.getScore();
}
// /
// / if buying a card is better than building...
// /
//
// see how buying a card improves our win game ETA
//
float devCardScore = 0;
if ((game.getNumDevCards() > 0) && !forSpecialBuildingPhase) {
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().startRecording("DEVCARD");
brain.getDRecorder().record("Estimate value of a dev card");
}
possibleCard = getDevCardScore(buildingETAs[SOCBuildingSpeedEstimate.CARD], leadersCurrentWGETA);
devCardScore = possibleCard.getScore();
D.ebugPrintln("### DEV CARD SCORE: " + devCardScore);
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().stopRecording();
}
if ((pick == -1) || (devCardScore > pickScore)) {
D.ebugPrintln("### BUY DEV CARD");
pick = SOCPlayingPiece.MAXPLUSONE;
pickScore = devCardScore;
}
}
if (game.isGameOptionSet(SOCGameOption.K_SC_PIRI) || game.isGameOptionSet(SOCGameOption.K_SC_WOND)) {
if (scenarioGameStrategyPlan(pickScore, devCardScore, true, (pick == SOCPlayingPiece.MAXPLUSONE), new SOCBuildingSpeedEstimate(ourPlayerData.getNumbers()), leadersCurrentWGETA, forSpecialBuildingPhase))
// <--- Early return: Scenario-specific buildingPlan was pushed ---
return;
}
//
switch(pick) {
case SOCPlayingPiece.ROAD:
D.ebugPrintln("$ PUSHING " + favoriteRoad);
buildingPlan.push(favoriteRoad);
break;
case SOCPlayingPiece.SETTLEMENT:
D.ebugPrintln("$ PUSHING " + favoriteSettlement);
buildingPlan.push(favoriteSettlement);
break;
case SOCPlayingPiece.CITY:
D.ebugPrintln("$ PUSHING " + favoriteCity);
buildingPlan.push(favoriteCity);
break;
case SOCPlayingPiece.MAXPLUSONE:
D.ebugPrintln("$ PUSHING " + possibleCard);
buildingPlan.push(possibleCard);
break;
}
}
use of soc.game.SOCCity in project JSettlers2 by jdmonin.
the class SOCPossibleCity method updateSpeedup.
/**
* calculate the speedup that this city gives.
* Call when any player's new city or settlement is added to the board.
* @see #getSpeedup()
*/
public void updateSpeedup() {
// D.ebugPrintln("****************************** (CITY) updateSpeedup at "+Integer.toHexString(coord));
SOCBuildingSpeedEstimate bse1 = new SOCBuildingSpeedEstimate(player.getNumbers());
int[] ourBuildingSpeed = bse1.getEstimatesFromNothingFast(player.getPortFlags());
SOCPlayerNumbers newNumbers = new SOCPlayerNumbers(player.getNumbers());
newNumbers.updateNumbers(new SOCCity(player, coord, null), player.getGame().getBoard());
SOCBuildingSpeedEstimate bse2 = new SOCBuildingSpeedEstimate(newNumbers);
int[] speed = bse2.getEstimatesFromNothingFast(player.getPortFlags());
for (int buildingType = SOCBuildingSpeedEstimate.MIN; buildingType < SOCBuildingSpeedEstimate.MAXPLUSONE; buildingType++) {
// D.ebugPrintln("!@#$% ourBuildingSpeed[buildingType]="+ourBuildingSpeed[buildingType]+" speed[buildingType]="+speed[buildingType]);
speedup[buildingType] = ourBuildingSpeed[buildingType] - speed[buildingType];
}
}
use of soc.game.SOCCity in project JSettlers2 by jdmonin.
the class SOCBoardPanel method drawBoard.
/**
* Draw the whole board, including pieces and tooltip ({@link #hilight}, {@link #hoverTip}) if applicable.
* The basic board without pieces is drawn just once, then buffered.
* If the board layout changes (at start of game, for example),
* call {@link #flushBoardLayoutAndRepaint()} to clear the buffered copy.
*
* @see #drawBoardEmpty(Graphics)
*/
private void drawBoard(Graphics g) {
Image ebb = emptyBoardBuffer;
if (scaledMissedImage || ebb == null) {
if (ebb == null) {
ebb = createImage(scaledPanelW, scaledPanelH);
emptyBoardBuffer = ebb;
}
drawnEmptyAt = System.currentTimeMillis();
// drawBoardEmpty, drawHex will set this flag if missed
scaledMissedImage = false;
drawBoardEmpty(ebb.getGraphics());
ebb.flush();
if (scaledMissedImage && (scaledAt != 0) && (RESCALE_MAX_RETRY_MS < (drawnEmptyAt - scaledAt)))
// eventually give up scaling it
scaledMissedImage = false;
}
// draw ebb from local variable, not emptyBoardBuffer field, to avoid occasional NPE
g.setPaintMode();
g.drawImage(ebb, 0, 0, this);
// ask for antialiasing if available
if (g instanceof Graphics2D)
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
final boolean xlat = (panelMarginX != 0) || (panelMarginY != 0);
if (xlat)
g.translate(panelMarginX, panelMarginY);
final int gameState = game.getGameState();
if (board.getRobberHex() != -1) {
drawRobber(g, board.getRobberHex(), (gameState != SOCGame.PLACING_ROBBER), true);
}
if (board.getPreviousRobberHex() != -1) {
drawRobber(g, board.getPreviousRobberHex(), (gameState != SOCGame.PLACING_ROBBER), false);
}
if (isLargeBoard) {
int hex = ((SOCBoardLarge) board).getPirateHex();
if (hex > 0) {
drawRoadOrShip(g, hex, -2, (gameState == SOCGame.PLACING_PIRATE), false, false);
}
hex = ((SOCBoardLarge) board).getPreviousPirateHex();
if (hex > 0) {
drawRoadOrShip(g, hex, -3, (gameState == SOCGame.PLACING_PIRATE), false, false);
}
}
/**
* draw the roads and ships
*/
if (!game.isGameOptionSet(SOCGameOption.K_SC_PIRI)) {
for (SOCRoad r : board.getRoads()) {
drawRoadOrShip(g, r.getCoordinates(), r.getPlayerNumber(), false, !(r instanceof SOCShip), false);
}
} else {
for (int pn = 0; pn < game.maxPlayers; ++pn) {
final SOCPlayer pl = game.getPlayer(pn);
// count warships here, for efficiency, instead of calling SOCGame.isShipWarship for each one
int numWarships = pl.getNumWarships();
for (SOCRoad r : pl.getRoads()) {
final boolean isShip = (r instanceof SOCShip);
final boolean isWarship = isShip && (numWarships > 0);
drawRoadOrShip(g, r.getCoordinates(), pn, false, !isShip, isWarship);
if (isWarship)
// this works since warships begin with player's 1st-placed ship in getRoads()
--numWarships;
}
/**
* draw the player's fortress, if any
*/
SOCFortress fo = pl.getFortress();
if (fo != null)
drawFortress(g, fo, pn, false);
}
}
/**
* draw the settlements
*/
for (SOCSettlement s : board.getSettlements()) {
drawSettlement(g, s.getCoordinates(), s.getPlayerNumber(), false, false);
}
/**
* draw the cities
*/
for (SOCCity c : board.getCities()) {
drawCity(g, c.getCoordinates(), c.getPlayerNumber(), false);
}
if (xlat)
g.translate(-panelMarginX, -panelMarginY);
/**
* draw the current-player arrow after ("above") pieces,
* but below any hilighted piece, in case of overlap at
* edge of board. More likely on 6-player board for the
* two players whose handpanels are vertically centered.
*/
if (gameState != SOCGame.NEW) {
drawArrow(g, game.getCurrentPlayerNumber(), game.getCurrentDice());
}
if (player != null) {
if (xlat)
g.translate(panelMarginX, panelMarginY);
/**
* Draw the hilight when in interactive mode;
* No hilight when null player (before game started).
* The "hovering" road/settlement/city are separately painted
* in {@link soc.client.SOCBoardPanel.BoardToolTip#paint()}.
*/
switch(mode) {
case MOVE_SHIP:
if (moveShip_fromEdge != 0)
drawRoadOrShip(g, moveShip_fromEdge, -1, false, false, moveShip_isWarship);
case PLACE_ROAD:
case PLACE_INIT_ROAD:
case PLACE_FREE_ROAD_OR_SHIP:
if (hilight != 0) {
drawRoadOrShip(g, hilight, playerNumber, true, !hilightIsShip, (moveShip_isWarship && (moveShip_fromEdge != 0)));
}
break;
case PLACE_SETTLEMENT:
case PLACE_INIT_SETTLEMENT:
if (hilight > 0) {
drawSettlement(g, hilight, playerNumber, true, false);
}
break;
case PLACE_CITY:
if (hilight > 0) {
drawCity(g, hilight, playerNumber, true);
}
break;
case PLACE_SHIP:
if (hilight > 0) {
drawRoadOrShip(g, hilight, playerNumber, true, false, false);
}
break;
case CONSIDER_LM_SETTLEMENT:
case CONSIDER_LT_SETTLEMENT:
if (hilight > 0) {
drawSettlement(g, hilight, otherPlayer.getPlayerNumber(), true, false);
}
break;
case CONSIDER_LM_ROAD:
case CONSIDER_LT_ROAD:
if (hilight != 0) {
drawRoadOrShip(g, hilight, otherPlayer.getPlayerNumber(), false, true, false);
}
break;
case CONSIDER_LM_CITY:
case CONSIDER_LT_CITY:
if (hilight > 0) {
drawCity(g, hilight, otherPlayer.getPlayerNumber(), true);
}
break;
case PLACE_ROBBER:
if (hilight > 0) {
drawRobber(g, hilight, true, true);
}
break;
case PLACE_PIRATE:
if (hilight > 0) {
drawRoadOrShip(g, hilight, -2, false, false, false);
}
break;
case SC_FTRI_PLACE_PORT:
drawBoard_SC_FTRI_placePort(g);
break;
}
if (xlat)
g.translate(-panelMarginX, -panelMarginY);
}
if (superText1 != null) {
drawSuperText(g);
}
if (superTextTop != null) {
drawSuperTextTop(g);
}
}
use of soc.game.SOCCity in project JSettlers2 by jdmonin.
the class SOCBoardPanel method mouseClicked.
/**
* DOCUMENT ME!
*
* @param evt DOCUMENT ME!
*/
public void mouseClicked(MouseEvent evt) {
try {
int x = evt.getX();
int y = evt.getY();
if (evt.isPopupTrigger()) {
popupMenuSystime = evt.getWhen();
evt.consume();
doBoardMenuPopup(x, y);
// <--- Pop up menu, nothing else to do ---
return;
}
if (evt.getWhen() < (popupMenuSystime + POPUP_MENU_IGNORE_MS)) {
// <--- Ignore click: too soon after popup click ---
return;
}
boolean tempChangedMode = false;
if ((mode == NONE) && hoverTip.isVisible()) {
if (game.isDebugFreePlacement()) {
if (hoverTip.hoverSettlementID != 0) {
hilight = hoverTip.hoverSettlementID;
hilightIsShip = false;
mode = PLACE_SETTLEMENT;
tempChangedMode = true;
} else if (hoverTip.hoverCityID != 0) {
hilight = hoverTip.hoverCityID;
hilightIsShip = false;
mode = PLACE_CITY;
tempChangedMode = true;
} else if (hoverTip.hoverRoadID != 0) {
hilight = hoverTip.hoverRoadID;
hilightIsShip = false;
mode = PLACE_ROAD;
tempChangedMode = true;
} else if (hoverTip.hoverShipID != 0) {
hilight = hoverTip.hoverShipID;
hilightIsShip = true;
mode = PLACE_SHIP;
tempChangedMode = true;
}
} else if (((evt.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) && (player != null) && (game.getCurrentPlayerNumber() == playerNumber) && (player.getPublicVP() == 2) && (hintShownCount_RightClickToBuild < 2)) {
// To help during the start of the game, display a hint message
// reminding new users to right-click to build (OSX: control-click).
// Show it at most twice to avoid annoying the user.
++hintShownCount_RightClickToBuild;
final String prompt = (SOCPlayerClient.isJavaOnOSX) ? "board.popup.hint_build_click.osx" : // "To build pieces, hold Control while clicking the build location."
"board.popup.hint_build_click";
// "To build pieces, right-click the build location."
NotifyDialog.createAndShow(playerInterface.getGameDisplay(), playerInterface, "\n" + strings.get(prompt), null, true);
// start prompt with \n to prevent it being a lengthy popup-dialog title
}
}
if ((hilight != 0) && (player != null) && (x == ptrOldX) && (y == ptrOldY)) {
SOCPlayerClient client = playerInterface.getClient();
switch(mode) {
case NONE:
break;
case TURN_STARTING:
break;
case PLACE_INIT_ROAD:
case PLACE_ROAD:
case PLACE_FREE_ROAD_OR_SHIP:
if (hilight == -1)
// Road on edge 0x00
hilight = 0;
if (player.isPotentialRoad(hilight) && !hilightIsShip) {
client.getGameManager().putPiece(game, new SOCRoad(player, hilight, board));
// Now that we've placed, clear the mode and the hilight.
clearModeAndHilight(SOCPlayingPiece.ROAD);
if (tempChangedMode)
hoverTip.hideHoverAndPieces();
} else if (// checks isPotentialShip, pirate ship
game.canPlaceShip(player, hilight)) {
if (game.isGameOptionSet(SOCGameOption.K_SC_FTRI) && ((SOCBoardLarge) board).canRemovePort(hilight)) {
java.awt.EventQueue.invokeLater(new ConfirmPlaceShipDialog(hilight, false, -1));
} else {
client.getGameManager().putPiece(game, new SOCShip(player, hilight, board));
// Now that we've placed, clear the mode and the hilight.
clearModeAndHilight(SOCPlayingPiece.SHIP);
}
if (tempChangedMode)
hoverTip.hideHoverAndPieces();
}
break;
case MOVE_SHIP:
// check and move ship to hilight from fromEdge;
// also sets moveShip_fromEdge = 0, calls clearModeAndHilight.
moveShip_toEdge = hilight;
tryMoveShipToEdge();
break;
case PLACE_INIT_SETTLEMENT:
if (playerNumber == playerInterface.getClientPlayerNumber()) {
initSettlementNode = hilight;
}
case PLACE_SETTLEMENT:
if (player.canPlaceSettlement(hilight)) {
client.getGameManager().putPiece(game, new SOCSettlement(player, hilight, board));
clearModeAndHilight(SOCPlayingPiece.SETTLEMENT);
if (tempChangedMode)
hoverTip.hideHoverAndPieces();
}
break;
case PLACE_CITY:
if (player.isPotentialCity(hilight)) {
client.getGameManager().putPiece(game, new SOCCity(player, hilight, board));
clearModeAndHilight(SOCPlayingPiece.CITY);
if (tempChangedMode)
hoverTip.hideHoverAndPieces();
}
break;
case PLACE_SHIP:
if (// checks isPotentialShip, pirate ship
game.canPlaceShip(player, hilight)) {
if (game.isGameOptionSet(SOCGameOption.K_SC_FTRI) && ((SOCBoardLarge) board).canRemovePort(hilight)) {
java.awt.EventQueue.invokeLater(new ConfirmPlaceShipDialog(hilight, false, -1));
} else {
client.getGameManager().putPiece(game, new SOCShip(player, hilight, board));
clearModeAndHilight(SOCPlayingPiece.SHIP);
}
if (tempChangedMode)
hoverTip.hideHoverAndPieces();
}
break;
case PLACE_ROBBER:
if (hilight != board.getRobberHex()) {
// do we have an adjacent settlement/city?
boolean cliAdjacent = false;
{
for (SOCPlayer pl : game.getPlayersOnHex(hilight)) {
if (pl.getPlayerNumber() == playerNumber) {
cliAdjacent = true;
break;
}
}
}
if (cliAdjacent) {
// ask player to confirm first
java.awt.EventQueue.invokeLater(new MoveRobberConfirmDialog(player, hilight));
} else {
// ask server to move it
client.getGameManager().moveRobber(game, player, hilight);
clearModeAndHilight(-1);
}
}
break;
case PLACE_PIRATE:
if (hilight != ((SOCBoardLarge) board).getPirateHex()) {
// do we have an adjacent ship?
boolean cliAdjacent = false;
{
for (SOCPlayer pl : game.getPlayersShipsOnHex(hilight)) {
if (pl.getPlayerNumber() == playerNumber) {
cliAdjacent = true;
break;
}
}
}
if (cliAdjacent) {
// ask player to confirm first
java.awt.EventQueue.invokeLater(new MoveRobberConfirmDialog(player, -hilight));
} else {
// ask server to move it
client.getGameManager().moveRobber(game, player, -hilight);
clearModeAndHilight(-1);
}
}
break;
case SC_FTRI_PLACE_PORT:
if (hilight != 0) {
int edge = hilight;
if (edge == -1)
edge = 0;
if (game.canPlacePort(player, edge)) {
// Ask server to place here.
client.getGameManager().sendSimpleRequest(player, SOCSimpleRequest.TRADE_PORT_PLACE, hilight, 0);
hilight = 0;
}
}
break;
case CONSIDER_LM_SETTLEMENT:
if (otherPlayer.canPlaceSettlement(hilight)) {
client.getGameManager().considerMove(game, otherPlayer.getName(), new SOCSettlement(otherPlayer, hilight, board));
clearModeAndHilight(SOCPlayingPiece.SETTLEMENT);
}
break;
case CONSIDER_LM_ROAD:
if (otherPlayer.isPotentialRoad(hilight)) {
client.getGameManager().considerMove(game, otherPlayer.getName(), new SOCRoad(otherPlayer, hilight, board));
clearModeAndHilight(SOCPlayingPiece.ROAD);
}
break;
case CONSIDER_LM_CITY:
if (otherPlayer.isPotentialCity(hilight)) {
client.getGameManager().considerMove(game, otherPlayer.getName(), new SOCCity(otherPlayer, hilight, board));
clearModeAndHilight(SOCPlayingPiece.CITY);
}
break;
case CONSIDER_LT_SETTLEMENT:
if (otherPlayer.canPlaceSettlement(hilight)) {
client.getGameManager().considerTarget(game, otherPlayer.getName(), new SOCSettlement(otherPlayer, hilight, board));
clearModeAndHilight(SOCPlayingPiece.SETTLEMENT);
}
break;
case CONSIDER_LT_ROAD:
if (otherPlayer.isPotentialRoad(hilight)) {
client.getGameManager().considerTarget(game, otherPlayer.getName(), new SOCRoad(otherPlayer, hilight, board));
clearModeAndHilight(SOCPlayingPiece.ROAD);
}
break;
case CONSIDER_LT_CITY:
if (otherPlayer.isPotentialCity(hilight)) {
client.getGameManager().considerTarget(game, otherPlayer.getName(), new SOCCity(otherPlayer, hilight, board));
clearModeAndHilight(SOCPlayingPiece.CITY);
}
break;
}
} else if ((player != null) && ((game.getCurrentPlayerNumber() == playerNumber) || game.isDebugFreePlacement())) {
// No hilight. But, they clicked the board, expecting something.
// It's possible the mode is incorrect.
// Update and wait for the next click.
updateMode();
ptrOldX = 0;
ptrOldY = 0;
// mouseMoved will establish hilight using click's x,y
mouseMoved(evt);
}
evt.consume();
if (tempChangedMode)
mode = NONE;
} catch (Throwable th) {
playerInterface.chatPrintStackTrace(th);
}
}
use of soc.game.SOCCity in project JSettlers2 by jdmonin.
the class SOCRobotDM method getWinGameETABonus.
/**
* add a bonus to the possible piece score based
* on the change in win game ETA
*
* @param posPiece the possible piece that we're scoring
*/
protected float getWinGameETABonus(final SOCPossiblePiece posPiece) {
HashMap<Integer, SOCPlayerTracker> trackersCopy = null;
SOCSettlement tmpSet = null;
SOCCity tmpCity = null;
// road or ship
SOCRoad tmpRoad = null;
float bonus = 0;
D.ebugPrintln("--- before [start] ---");
// SOCPlayerTracker.playerTrackersDebug(playerTrackers);
D.ebugPrintln("our player numbers = " + ourPlayerData.getNumbers());
D.ebugPrintln("--- before [end] ---");
switch(posPiece.getType()) {
case SOCPossiblePiece.SETTLEMENT:
tmpSet = new SOCSettlement(ourPlayerData, posPiece.getCoordinates(), null);
trackersCopy = SOCPlayerTracker.tryPutPiece(tmpSet, game, playerTrackers);
break;
case SOCPossiblePiece.CITY:
trackersCopy = SOCPlayerTracker.copyPlayerTrackers(playerTrackers);
tmpCity = new SOCCity(ourPlayerData, posPiece.getCoordinates(), null);
game.putTempPiece(tmpCity);
SOCPlayerTracker trackerCopy = trackersCopy.get(Integer.valueOf(ourPlayerNumber));
if (trackerCopy != null) {
trackerCopy.addOurNewCity(tmpCity);
}
break;
case SOCPossiblePiece.ROAD:
tmpRoad = new SOCRoad(ourPlayerData, posPiece.getCoordinates(), null);
trackersCopy = SOCPlayerTracker.tryPutPiece(tmpRoad, game, playerTrackers);
break;
case SOCPossiblePiece.SHIP:
tmpRoad = new SOCShip(ourPlayerData, posPiece.getCoordinates(), null);
trackersCopy = SOCPlayerTracker.tryPutPiece(tmpRoad, game, playerTrackers);
break;
}
// trackersCopyIter = trackersCopy.iterator();
// while (trackersCopyIter.hasNext()) {
// SOCPlayerTracker trackerCopy = (SOCPlayerTracker)trackersCopyIter.next();
// trackerCopy.updateThreats(trackersCopy);
// }
D.ebugPrintln("--- after [start] ---");
// SOCPlayerTracker.playerTrackersDebug(trackersCopy);
SOCPlayerTracker.updateWinGameETAs(trackersCopy);
float WGETABonus = calcWGETABonus(playerTrackers, trackersCopy);
D.ebugPrintln("$$$ win game ETA bonus : +" + WGETABonus);
bonus = WGETABonus;
D.ebugPrintln("our player numbers = " + ourPlayerData.getNumbers());
D.ebugPrintln("--- after [end] ---");
switch(posPiece.getType()) {
case SOCPossiblePiece.SETTLEMENT:
SOCPlayerTracker.undoTryPutPiece(tmpSet, game);
break;
case SOCPossiblePiece.CITY:
game.undoPutTempPiece(tmpCity);
break;
// fall through to ROAD
case SOCPossiblePiece.SHIP:
case SOCPossiblePiece.ROAD:
SOCPlayerTracker.undoTryPutPiece(tmpRoad, game);
break;
}
D.ebugPrintln("our player numbers = " + ourPlayerData.getNumbers());
D.ebugPrintln("--- cleanup done ---");
return bonus;
}
Aggregations