use of soc.game.SOCBoardLarge in project JSettlers2 by jdmonin.
the class SOCBoardPanel method mouseMoved.
/**
* Based on the board's current {@link #mode}, update the hovering 'hilight' piece ({@link #hilight}).
* Trigger a {@link #repaint()} if the mouse moved or the hilight changes.
*/
public void mouseMoved(MouseEvent e) {
try {
int x = e.getX();
int y = e.getY();
int xb, yb;
// get (xb, yb) internal board-pixel coordinates from (x, y):
if (isScaled) {
xb = scaleFromActual(x - panelMarginX);
yb = scaleFromActual(y - panelMarginY);
} else {
xb = x - panelMarginX;
yb = y - panelMarginY;
}
if (isRotated) {
// (ccw): P'=(y, panelMinBW-x)
int xb1 = yb;
// offset for similar reasons as -HEXHEIGHT in drawHex
yb = panelMinBW - xb - HEXY_OFF_SLOPE_HEIGHT;
xb = xb1;
}
int edgeNum;
int nodeNum;
int hexNum;
switch(mode) {
case PLACE_INIT_ROAD:
/**
** Code for finding an edge *******
*/
edgeNum = 0;
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
boolean isShip = false;
edgeNum = findEdge(xb, yb, true);
if (edgeNum < 0) {
edgeNum = -edgeNum;
if ((player != null) && game.canPlaceShip(player, edgeNum))
isShip = true;
} else {
// check potential roads, not ships, to keep it false if coastal edge
isShip = ((player != null) && !player.isPotentialRoad(edgeNum));
}
// It must be attached to the last settlement
if ((player == null) || (!(player.isPotentialRoad(edgeNum) || game.canPlaceShip(player, edgeNum))) || (!(game.isDebugFreePlacement() || board.isEdgeAdjacentToNode(initSettlementNode, (edgeNum != -1) ? edgeNum : 0)))) {
edgeNum = 0;
}
if ((hilight != edgeNum) || (hilightIsShip != isShip)) {
hilight = edgeNum;
hilightIsShip = isShip;
if (debugShowCoordsTooltip) {
// "" shows tip, null hides it.
String blank = (edgeNum != 0) ? "" : null;
// also repaints
hoverTip.setHoverText(blank, edgeNum, x, y);
} else {
repaint();
}
}
}
break;
case PLACE_ROAD:
case PLACE_FREE_ROAD_OR_SHIP:
case MOVE_SHIP:
/**
** Code for finding an edge; see also PLACE_SHIP, SC_FTRI_PLACE_PORT *******
*/
edgeNum = 0;
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
edgeNum = findEdge(xb, yb, true);
final boolean hasShips = (player != null) && (player.getNumPieces(SOCPlayingPiece.SHIP) > 0);
final boolean canPlaceShip = hasShips && game.canPlaceShip(player, Math.abs(edgeNum));
if ((mode == PLACE_FREE_ROAD_OR_SHIP) && canPlaceShip && (edgeNum > 0) && (player.getNumPieces(SOCPlayingPiece.ROAD) == 0)) {
// If this edge is coastal, force ship (not road) if we
// have no roads remaining to freely place
edgeNum = -edgeNum;
}
boolean isShip;
if (edgeNum < 0) {
edgeNum = -edgeNum;
isShip = canPlaceShip || ((mode == PLACE_FREE_ROAD_OR_SHIP) && hasShips && player.isPotentialShip(edgeNum));
} else {
isShip = false;
}
if ((edgeNum != 0) && (player != null)) {
if (mode == MOVE_SHIP) {
isShip = true;
if (!player.isPotentialShipMoveTo(edgeNum, moveShip_fromEdge))
edgeNum = 0;
// Check edgeNum vs pirate hex:
final SOCBoardLarge bL = (SOCBoardLarge) board;
final int ph = bL.getPirateHex();
if ((ph != 0) && bL.isEdgeAdjacentToHex(edgeNum, ph))
edgeNum = 0;
} else {
if ((player.isPotentialRoad(edgeNum) && (player.getNumPieces(SOCPlayingPiece.ROAD) > 0)) || ((mode == PLACE_FREE_ROAD_OR_SHIP) && canPlaceShip)) {
if (!isShip) {
// check potential roads, not ships, to keep it false if coastal edge
isShip = (player != null) && canPlaceShip && !player.isPotentialRoad(edgeNum);
}
} else {
edgeNum = 0;
}
}
}
if ((hilight != edgeNum) || (hilightIsShip != isShip)) {
hilight = edgeNum;
hilightIsShip = isShip;
if (debugShowCoordsTooltip) {
// "" shows tip, null hides it.
String blank = (edgeNum != 0) ? "" : null;
// also repaints
hoverTip.setHoverText(blank, edgeNum, x, y);
} else {
repaint();
}
}
}
break;
case PLACE_SETTLEMENT:
case PLACE_INIT_SETTLEMENT:
/**
** Code for finding a node ********
*/
nodeNum = 0;
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
nodeNum = findNode(xb, yb);
if ((player == null) || !player.canPlaceSettlement(nodeNum)) {
nodeNum = 0;
}
if (hilight != nodeNum) {
hilight = nodeNum;
hilightIsShip = false;
if ((mode == PLACE_INIT_SETTLEMENT) && !debugShowCoordsTooltip)
hoverTip.handleHover(x, y, xb, yb);
else if (debugShowCoordsTooltip)
hoverTip.setHoverText(((nodeNum != 0) ? "" : null), nodeNum, x, y);
else
repaint();
} else if (mode == PLACE_INIT_SETTLEMENT) {
if (debugShowCoordsTooltip && (nodeNum != 0))
hoverTip.setHoverText("", nodeNum, x, y);
else
// Will call repaint() if needed
hoverTip.handleHover(x, y, xb, yb);
}
}
break;
case PLACE_CITY:
/**
** Code for finding a node ********
*/
nodeNum = 0;
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
nodeNum = findNode(xb, yb);
if ((player == null) || !player.isPotentialCity(nodeNum)) {
nodeNum = 0;
}
if (hilight != nodeNum) {
hilight = nodeNum;
hilightIsShip = false;
if (debugShowCoordsTooltip) {
// "" shows tip, null hides it.
String blank = (nodeNum != 0) ? "" : null;
// also repaints
hoverTip.setHoverText(blank, nodeNum, x, y);
} else {
repaint();
}
}
}
break;
case PLACE_SHIP:
/**
** Code for finding an edge; see also PLACE_ROAD *******
*/
edgeNum = 0;
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
edgeNum = findEdge(xb, yb, false);
if (edgeNum != 0) {
if ((player == null) || (player.getNumPieces(SOCPlayingPiece.SHIP) < 1) || !game.canPlaceShip(player, edgeNum))
edgeNum = 0;
}
if (hilight != edgeNum) {
hilight = edgeNum;
hilightIsShip = true;
if (debugShowCoordsTooltip) {
// "" shows tip, null hides it.
String blank = (edgeNum != 0) ? "" : null;
// also repaints
hoverTip.setHoverText(blank, edgeNum, x, y);
} else {
repaint();
}
}
}
break;
case PLACE_ROBBER:
case PLACE_PIRATE:
/**
** Code for finding a hex ********
*/
hexNum = 0;
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
hexNum = findHex(xb, yb);
final boolean canMove = (mode == PLACE_ROBBER) ? game.canMoveRobber(playerNumber, hexNum) : game.canMovePirate(playerNumber, hexNum);
if (!canMove) {
// Not a hex, or can't move to this hex (water, etc)
if (hexNum != 0) {
if ((board instanceof SOCBoardLarge) && ((SOCBoardLarge) board).isHexInLandAreas(hexNum, ((SOCBoardLarge) board).getRobberExcludedLandAreas())) {
hoverTip.setHoverText(strings.get("board.robber.not.here"), hexNum);
// "Cannot move the robber here."
} else {
// clear any previous
hoverTip.setHoverText(null, 0);
}
hexNum = 0;
}
}
if (hilight != hexNum) {
hilight = hexNum;
hilightIsShip = false;
hoverTip.handleHover(x, y, xb, yb);
repaint();
} else {
// calls repaint
hoverTip.positionToMouse(x, y);
}
}
break;
case SC_FTRI_PLACE_PORT:
/**
** Code for finding an edge; see also PLACE_ROAD, PLACE_SHIP *******
*/
edgeNum = 0;
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
edgeNum = findEdge(xb, yb, false);
}
if (edgeNum != 0) {
final boolean edgeNeg1;
if (edgeNum == -1) {
edgeNum = 0;
edgeNeg1 = true;
} else {
edgeNeg1 = false;
}
if (!game.canPlacePort(player, edgeNum)) {
// not valid for placement
edgeNum = 0;
} else {
if (edgeNeg1)
edgeNum = -1;
}
}
if (edgeNum != hilight) {
hilight = edgeNum;
if (debugShowCoordsTooltip) {
// "" shows tip, null hides it.
String blank = (edgeNum != 0) ? "" : null;
// also repaints
hoverTip.setHoverText(blank, edgeNum, x, y);
} else {
repaint();
}
}
break;
case CONSIDER_LM_SETTLEMENT:
case CONSIDER_LT_SETTLEMENT:
/**
** Code for finding a node ********
*/
nodeNum = 0;
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
nodeNum = findNode(xb, yb);
// nodeNum = 0;
if (hilight != nodeNum) {
hilight = nodeNum;
hilightIsShip = false;
repaint();
}
}
break;
case CONSIDER_LM_ROAD:
case CONSIDER_LT_ROAD:
/**
** Code for finding an edge *******
*/
edgeNum = 0;
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
edgeNum = findEdge(xb, yb, false);
if (!otherPlayer.isPotentialRoad(edgeNum)) {
edgeNum = 0;
}
if (hilight != edgeNum) {
hilight = edgeNum;
hilightIsShip = false;
repaint();
}
}
break;
case CONSIDER_LM_CITY:
case CONSIDER_LT_CITY:
/**
** Code for finding a node ********
*/
nodeNum = 0;
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
nodeNum = findNode(xb, yb);
if (!otherPlayer.isPotentialCity(nodeNum)) {
nodeNum = 0;
}
if (hilight != nodeNum) {
hilight = nodeNum;
hilightIsShip = false;
repaint();
}
}
break;
case NONE:
case TURN_STARTING:
case GAME_OVER:
// see hover
if ((ptrOldX != x) || (ptrOldY != y)) {
ptrOldX = x;
ptrOldY = y;
hoverTip.handleHover(x, y, xb, yb);
}
break;
case GAME_FORMING:
// No hover for forming
break;
}
} catch (Throwable th) {
playerInterface.chatPrintStackTrace(th);
}
}
use of soc.game.SOCBoardLarge in project JSettlers2 by jdmonin.
the class SOCPlayerTracker method recalcScenario_SC_PIRI_nextPotentialShip.
/**
* For scenario {@code _SC_PIRI}, get the player's next potential ship towards their Fortress.
* If fortress was already defeated, or they have no boats, returns {@code null}.
*<P>
* This is calculated every time, not cached, because potential-ships list may change often.
* Calls {@link #updateScenario_SC_PIRI_closestShipToFortress(SOCShip, boolean)} if closest ship not known.
*
* @return Next potential ship, or {@code null}
* @since 2.0.00
*/
SOCPossibleShip recalcScenario_SC_PIRI_nextPotentialShip() {
// may be null towards end of game
final SOCFortress fort = player.getFortress();
if (fort == null)
// <--- Early return: already defeated fortress ---
return null;
final int fortR = fort.getCoordinates() >> 8;
if (scen_SC_PIRI_closestShipToFortress == null)
updateScenario_SC_PIRI_closestShipToFortress(null, false);
final SOCShip closest = scen_SC_PIRI_closestShipToFortress;
if (closest == null)
// <--- Early return: no ships ---
return null;
final List<Integer> closestAdjacs = ((SOCBoardLarge) game.getBoard()).getAdjacentEdgesToEdge(closest.getCoordinates());
SOCPossibleShip nextShip = null;
int nextR = -1, nextC = -1;
for (Integer edge : closestAdjacs) {
final SOCPossibleRoad rs = possibleRoads.get(edge);
if ((rs == null) || !(rs instanceof SOCPossibleShip))
continue;
final int shipEdge = rs.getCoordinates();
final int shipR = shipEdge >> 8, shipC = shipEdge & 0xFF;
if ((nextShip == null) || (shipC < nextC) || ((shipC == nextC) && (Math.abs(shipR - fortR) < Math.abs(nextR - fortR)))) {
nextShip = (SOCPossibleShip) rs;
nextR = shipR;
nextC = shipC;
}
}
return nextShip;
}
use of soc.game.SOCBoardLarge in project JSettlers2 by jdmonin.
the class SOCPlayerTracker method expandRoadOrShip.
/**
* Expand a possible road or ship, to see what placements it makes possible.
*<UL>
*<LI> Creates {@code dummyRoad}: A copy of {@code targetRoad} owned by {@code dummy}
*<LI> Calls {@link SOCPlayer#putPiece(SOCPlayingPiece, boolean) dummy.putPiece(dummyRoad, true)}
*<LI> Adds to or updates {@link #possibleSettlements} at <tt>targetRoad</tt>'s nodes, if potential
*<LI> If {@code level > 0}: Calls itself recursively to go more levels out from the current pieces,
* adding/updating {@link #possibleRoads} and {@link #possibleSettlements}
*<LI> Calls {@link SOCPlayer#removePiece(SOCPlayingPiece, SOCPlayingPiece) dummy.removePiece(dummyRoad, null)}
*</UL>
*<P>
* <b>Scenario {@code _SC_PIRI}</b>: Ships in this scenario never expand east (never away from the
* pirate fortress). Scenario rules require the route to be as short as possible. Even if another (human)
* player might want to do so, they couldn't interfere with the bot's own route, so we don't track
* that possibility.
*
* @param targetRoad the possible road
* @param player the player who owns the original road
* @param dummy the dummy player used to see what's legal; created by caller copying {@code player}
* @param trackers player trackers
* @param level how many levels (additional pieces) to expand;
* 0 to only check <tt>targetRoad</tt> for potential settlements
* and not expand past it for new roads, ships, or further settlements.
* If {@code level > 0} but {@code dummy} has no more roads or ships
* (depending on {@link SOCPossibleRoad#isRoadNotShip() targetRoad.isRoadNotShip()}),
* acts as if {@code level == 0}.
*/
public void expandRoadOrShip(final SOCPossibleRoad targetRoad, final SOCPlayer player, final SOCPlayer dummy, HashMap<Integer, SOCPlayerTracker> trackers, final int level) {
// D.ebugPrintln("$$$ expandRoad at "+Integer.toHexString(targetRoad.getCoordinates())+" level="+level);
final SOCBoard board = game.getBoard();
final int tgtRoadEdge = targetRoad.getCoordinates();
final boolean isRoadNotShip = targetRoad.isRoadNotShip();
final SOCRoad dummyRoad;
if (isRoadNotShip || ((targetRoad instanceof SOCPossibleShip) && ((SOCPossibleShip) targetRoad).isCoastalRoadAndShip))
dummyRoad = new SOCRoad(dummy, tgtRoadEdge, board);
else
// TODO better handling for coastal roads/ships
dummyRoad = new SOCShip(dummy, tgtRoadEdge, board);
dummy.putPiece(dummyRoad, true);
//
for (Integer adjNode : board.getAdjacentNodesToEdge(tgtRoadEdge)) {
if (dummy.canPlaceSettlement(adjNode.intValue())) {
//
// see if possible settlement is already in the list
//
// D.ebugPrintln("$$$ seeing if "+Integer.toHexString(adjNode.intValue())+" is already in the list");
SOCPossibleSettlement posSet = possibleSettlements.get(adjNode);
if (posSet != null) {
//
if (!(posSet.getNecessaryRoads().isEmpty() || posSet.getNecessaryRoads().contains(targetRoad))) {
//
// add target road to settlement's nr list and this settlement to the road's np list
//
// D.ebugPrintln("$$$ adding road "+Integer.toHexString(targetRoad.getCoordinates())+" to the settlement "+Integer.toHexString(posSet.getCoordinates()));
posSet.addNecessaryRoad(targetRoad);
targetRoad.addNewPossibility(posSet);
//
if ((targetRoad.getNumberOfNecessaryRoads() + 1) < posSet.getNumberOfNecessaryRoads()) {
posSet.setNumberOfNecessaryRoads(targetRoad.getNumberOfNecessaryRoads() + 1);
}
}
} else {
//
// else, add new possible settlement
//
// D.ebugPrintln("$$$ adding new possible settlement at "+Integer.toHexString(adjNode.intValue()));
List<SOCPossibleRoad> nr = new ArrayList<SOCPossibleRoad>();
nr.add(targetRoad);
SOCPossibleSettlement newPosSet = new SOCPossibleSettlement(player, adjNode.intValue(), nr);
newPosSet.setNumberOfNecessaryRoads(targetRoad.getNumberOfNecessaryRoads() + 1);
possibleSettlements.put(adjNode, newPosSet);
targetRoad.addNewPossibility(newPosSet);
updateSettlementConflicts(newPosSet, trackers);
}
}
}
if ((level > 0) && (0 < dummy.getNumPieces(isRoadNotShip ? SOCPlayingPiece.ROAD : SOCPlayingPiece.SHIP))) {
//
// check for new possible roads or ships.
// The above getNumPieces check ignores any possible ship <-> road transition at a coastal settlement.
//
ArrayList<SOCPossibleRoad> newPossibleRoads = new ArrayList<SOCPossibleRoad>();
ArrayList<SOCPossibleRoad> roadsToExpand = new ArrayList<SOCPossibleRoad>();
// ships in _SC_PIRI never expand east
final boolean isShipInSC_PIRI = (!isRoadNotShip) && game.isGameOptionSet(SOCGameOption.K_SC_PIRI);
// D.ebugPrintln("$$$ checking roads adjacent to "+Integer.toHexString(targetRoad.getCoordinates()));
//
// check adjacent edges to road or ship
//
Enumeration<Integer> adjEdgesEnum = board.getAdjacentEdgesToEdge(tgtRoadEdge).elements();
while (adjEdgesEnum.hasMoreElements()) {
Integer adjEdge = adjEdgesEnum.nextElement();
final int edge = adjEdge.intValue();
if (isShipInSC_PIRI) {
final int tgtEdgeCol = tgtRoadEdge & 0xFF, adjEdgeCol = edge & 0xFF;
if (// adjacent goes north/south from eastern node of diagonal target edge
(adjEdgeCol > tgtEdgeCol) || ((adjEdgeCol == tgtEdgeCol) && ((tgtRoadEdge & 0x100) != 0))) // adjacent goes northeast/southeast from vertical target edge (tgtRoadEdge is on odd row)
{
// <--- Ignore this eastern adjacent edge ---
continue;
}
}
// D.ebugPrintln("$$$ edge "+Integer.toHexString(adjEdge.intValue())+" is legal:"+dummy.isPotentialRoad(adjEdge.intValue()));
//
// see if edge is a potential road
// or ship to continue this route
//
boolean edgeIsPotentialRoute = (isRoadNotShip) ? dummy.isPotentialRoad(edge) : dummy.isPotentialShip(edge);
// If true, this edge transitions
// between ships <-> roads, at a
// coastal settlement
boolean edgeRequiresCoastalSettlement = false;
if ((!edgeIsPotentialRoute) && game.hasSeaBoard) {
// Determine if can transition ship <-> road
// at a coastal settlement
final int nodeBetween = ((SOCBoardLarge) board).getNodeBetweenAdjacentEdges(tgtRoadEdge, edge);
if (dummy.canPlaceSettlement(nodeBetween)) {
// check opposite type at transition
edgeIsPotentialRoute = (isRoadNotShip) ? dummy.isPotentialShip(edge) : dummy.isPotentialRoad(edge);
if (edgeIsPotentialRoute)
edgeRequiresCoastalSettlement = true;
}
}
if (edgeIsPotentialRoute) {
// Add 1 to road distance, unless
// it requires a coastal settlement
// (extra effort to build that)
final int incrDistance = edgeRequiresCoastalSettlement ? 3 : 1;
//
// see if possible road is already in the list
//
SOCPossibleRoad pr = possibleRoads.get(adjEdge);
if (pr != null) {
// For now, can't differ along a coastal route.
if (edgeRequiresCoastalSettlement && (isRoadNotShip != pr.isRoadNotShip())) {
// <--- road vs ship mismatch ---
continue;
}
//
// if so, and it needs 1 or more roads other than this one,
//
// D.ebugPrintln("$$$ pr "+Integer.toHexString(pr.getCoordinates())+" already in list");
List<SOCPossibleRoad> nr = pr.getNecessaryRoads();
if (!(nr.isEmpty() || nr.contains(targetRoad))) {
//
// add the target road to its nr list and the new road to the target road's np list
//
// D.ebugPrintln("$$$ adding "+Integer.toHexString(targetRoad.getCoordinates())+" to nr list");
nr.add(targetRoad);
targetRoad.addNewPossibility(pr);
//
if ((targetRoad.getNumberOfNecessaryRoads() + incrDistance) < pr.getNumberOfNecessaryRoads()) {
pr.setNumberOfNecessaryRoads(targetRoad.getNumberOfNecessaryRoads() + incrDistance);
}
}
if (!pr.hasBeenExpanded()) {
roadsToExpand.add(pr);
pr.setExpandedFlag();
}
} else {
//
// else, add new possible road or ship
//
// D.ebugPrintln("$$$ adding new pr at "+Integer.toHexString(adjEdge.intValue()));
ArrayList<SOCPossibleRoad> neededRoads = new ArrayList<SOCPossibleRoad>();
neededRoads.add(targetRoad);
SOCPossibleRoad newPR;
boolean isRoad = isRoadNotShip;
if (edgeRequiresCoastalSettlement)
isRoad = !isRoad;
// use coastal road/ship type (isCoastalRoadAndShip) only if the road/ship
// being expanded is coastal, or if we can require a coastal settlement to
// switch from road-only or ship-only
final boolean isCoastal = dummy.isPotentialRoad(edge) && dummy.isPotentialShip(edge) && (edgeRequiresCoastalSettlement || ((targetRoad instanceof SOCPossibleShip) && ((SOCPossibleShip) targetRoad).isCoastalRoadAndShip));
if (isRoad && !isCoastal) {
newPR = new SOCPossibleRoad(player, edge, neededRoads);
} else {
newPR = new SOCPossibleShip(player, edge, isCoastal, neededRoads);
System.err.println("L1072: " + toString() + ": new PossibleShip(" + isCoastal + ") at 0x" + Integer.toHexString(edge));
}
newPR.setNumberOfNecessaryRoads(targetRoad.getNumberOfNecessaryRoads() + incrDistance);
targetRoad.addNewPossibility(newPR);
newPossibleRoads.add(newPR);
roadsToExpand.add(newPR);
newPR.setExpandedFlag();
}
}
}
//
for (SOCPossibleRoad newPR : newPossibleRoads) {
possibleRoads.put(Integer.valueOf(newPR.getCoordinates()), newPR);
}
//
for (SOCPossibleRoad expandPR : roadsToExpand) {
expandRoadOrShip(expandPR, player, dummy, trackers, level - 1);
}
}
//
// remove the dummy road
//
dummy.removePiece(dummyRoad, null);
}
use of soc.game.SOCBoardLarge in project JSettlers2 by jdmonin.
the class SOCPlayerTracker method addOurNewRoadOrShip.
/**
* Add one of our roads or ships that has just been built.
* Look for new adjacent possible settlements.
* Calls {@link #expandRoadOrShip(SOCPossibleRoad, SOCPlayer, SOCPlayer, HashMap, int)}
* on newly possible adjacent roads or ships.
*
* @param road the road or ship
* @param trackers player trackers for the players
* @param expandLevel how far out we should expand roads/ships;
* passed to {@link #expandRoadOrShip(SOCPossibleRoad, SOCPlayer, SOCPlayer, HashMap, int)}
*/
private void addOurNewRoadOrShip(SOCRoad road, HashMap<Integer, SOCPlayerTracker> trackers, int expandLevel) {
// D.ebugPrintln("$$$ addOurNewRoad : "+road);
//
// see if the new road was a possible road
//
Iterator<SOCPossibleRoad> prIter = possibleRoads.values().iterator();
while (prIter.hasNext()) {
SOCPossibleRoad pr = prIter.next();
//
// reset all expanded flags for possible roads
//
pr.resetExpandedFlag();
if (pr.getCoordinates() == road.getCoordinates()) {
//
// if so, remove it
//
// D.ebugPrintln("$$$ removing "+Integer.toHexString(road.getCoordinates()));
possibleRoads.remove(Integer.valueOf(pr.getCoordinates()));
removeFromNecessaryRoads(pr);
break;
}
}
// D.ebugPrintln("$$$ checking for possible settlements");
//
// see if this road/ship adds any new possible settlements
//
// check adjacent nodes to road for potential settlements
//
final SOCBoard board = game.getBoard();
Collection<Integer> adjNodeEnum = board.getAdjacentNodesToEdge(road.getCoordinates());
for (Integer adjNode : adjNodeEnum) {
if (player.canPlaceSettlement(adjNode.intValue())) {
//
// see if possible settlement is already in the list
//
// D.ebugPrintln("$$$ seeing if "+Integer.toHexString(adjNode.intValue())+" is already in the list");
SOCPossibleSettlement posSet = possibleSettlements.get(adjNode);
if (posSet != null) {
//
// if so, clear necessary road list and remove from np lists
//
// D.ebugPrintln("$$$ found it");
removeFromNecessaryRoads(posSet);
posSet.getNecessaryRoads().clear();
posSet.setNumberOfNecessaryRoads(0);
} else {
//
// else, add new possible settlement
//
// D.ebugPrintln("$$$ adding new possible settlement at "+Integer.toHexString(adjNode.intValue()));
SOCPossibleSettlement newPosSet = new SOCPossibleSettlement(player, adjNode.intValue(), null);
newPosSet.setNumberOfNecessaryRoads(0);
possibleSettlements.put(adjNode, newPosSet);
updateSettlementConflicts(newPosSet, trackers);
}
}
}
// D.ebugPrintln("$$$ checking roads adjacent to "+Integer.toHexString(road.getCoordinates()));
//
// see if this road adds any new possible roads
//
ArrayList<SOCPossibleRoad> newPossibleRoads = new ArrayList<SOCPossibleRoad>();
ArrayList<SOCPossibleRoad> roadsToExpand = new ArrayList<SOCPossibleRoad>();
//
for (Integer adjEdge : board.getAdjacentEdgesToEdge(road.getCoordinates())) {
final int edge = adjEdge.intValue();
// D.ebugPrintln("$$$ edge "+Integer.toHexString(adjEdge.intValue())+" is legal:"+player.isPotentialRoad(adjEdge.intValue()));
//
// see if edge is a potential road
// or ship to continue this route
//
boolean edgeIsPotentialRoute = (road.isRoadNotShip()) ? player.isPotentialRoad(edge) : player.isPotentialShip(edge);
// If true, this edge transitions
// between ships <-> roads, at a
// coastal settlement
boolean edgeRequiresCoastalSettlement = false;
if ((!edgeIsPotentialRoute) && game.hasSeaBoard) {
// Determine if can transition ship <-> road
// at a coastal settlement
final int nodeBetween = ((SOCBoardLarge) board).getNodeBetweenAdjacentEdges(road.getCoordinates(), edge);
if (player.canPlaceSettlement(nodeBetween)) {
// check opposite type at transition
edgeIsPotentialRoute = (road.isRoadNotShip()) ? player.isPotentialShip(edge) : player.isPotentialRoad(edge);
if (edgeIsPotentialRoute)
edgeRequiresCoastalSettlement = true;
}
}
if (edgeIsPotentialRoute) {
//
// see if possible road is already in the list
//
SOCPossibleRoad pr = possibleRoads.get(adjEdge);
if (pr != null) {
// For now, can't differ along a coastal route.
if (edgeRequiresCoastalSettlement && (pr.isRoadNotShip() != road.isRoadNotShip())) {
// <--- road vs ship mismatch ---
continue;
}
// D.ebugPrintln("$$$ pr "+Integer.toHexString(pr.getCoordinates())+" already in list");
if (!pr.getNecessaryRoads().isEmpty()) {
// D.ebugPrintln("$$$ clearing nr list");
removeFromNecessaryRoads(pr);
pr.getNecessaryRoads().clear();
pr.setNumberOfNecessaryRoads(0);
}
roadsToExpand.add(pr);
pr.setExpandedFlag();
} else {
//
// else, add new possible road
//
// D.ebugPrintln("$$$ adding new pr at "+Integer.toHexString(adjEdge.intValue()));
SOCPossibleRoad newPR;
// for effort if requires settlement
final int roadsBetween;
boolean isRoad = road.isRoadNotShip();
if (edgeRequiresCoastalSettlement) {
isRoad = !isRoad;
// roughly account for effort & cost of new settlement
roadsBetween = 2;
} else {
roadsBetween = 0;
}
// use coastal road/ship type (isCoastalRoadAndShip) only if we can
// require a coastal settlement to switch from road-only or ship-only
final boolean isCoastal = edgeRequiresCoastalSettlement && player.isPotentialRoad(edge) && player.isPotentialShip(edge);
if (isRoad && !isCoastal) {
newPR = new SOCPossibleRoad(player, edge, null);
} else {
newPR = new SOCPossibleShip(player, edge, isCoastal, null);
System.err.println("L793: " + toString() + ": new PossibleShip(" + isCoastal + ") at 0x" + Integer.toHexString(edge));
}
// 0 unless requires settlement
newPR.setNumberOfNecessaryRoads(roadsBetween);
newPossibleRoads.add(newPR);
roadsToExpand.add(newPR);
newPR.setExpandedFlag();
}
}
}
//
for (SOCPossibleRoad newPR : newPossibleRoads) {
possibleRoads.put(Integer.valueOf(newPR.getCoordinates()), newPR);
}
//
// expand possible roads that we've touched or added
//
SOCPlayer dummy = new SOCPlayer(player);
for (SOCPossibleRoad expandPR : roadsToExpand) {
expandRoadOrShip(expandPR, player, dummy, trackers, expandLevel);
}
dummy.destroyPlayer();
//
if ((road instanceof SOCShip) && game.isGameOptionSet(SOCGameOption.K_SC_PIRI))
updateScenario_SC_PIRI_closestShipToFortress((SOCShip) road, true);
}
Aggregations