use of soc.game.SOCRoad 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;
}
use of soc.game.SOCRoad in project JSettlers2 by jdmonin.
the class SOCPlayerInterface method updateAtPutPiece.
/**
* Handle updates after putting a piece on the board,
* or moving a ship that was already placed.
* Place or move the piece within our {@link SOCGame}
* and visually on our {@link SOCBoardPanel}.
*
* @param mesPn The piece's player number
* @param coord The piece's coordinate. If <tt>isMove</tt>, the coordinate to move <em>from</em>.
* @param pieceType Piece type, like {@link SOCPlayingPiece#CITY}
* @param isMove If true, it's a move, not a new placement; valid only for ships.
* @param moveToCoord If <tt>isMove</tt>, the coordinate to move <em>to</em>. Otherwise ignored.
*
* @see #updateAtPiecesChanged()
* @since 2.0.00
*/
public void updateAtPutPiece(final int mesPn, final int coord, final int pieceType, final boolean isMove, final int moveToCoord) {
// TODO consider more effic way for flushBoardLayoutAndRepaint, without the =null
final SOCPlayer pl = (pieceType != SOCPlayingPiece.VILLAGE) ? game.getPlayer(mesPn) : null;
final SOCPlayer oldLongestRoadPlayer = game.getPlayerWithLongestRoad();
final SOCHandPanel mesHp = (pieceType != SOCPlayingPiece.VILLAGE) ? getPlayerHandPanel(mesPn) : null;
final boolean[] debugShowPotentials = boardPanel.debugShowPotentials;
final SOCPlayingPiece pp;
switch(pieceType) {
case SOCPlayingPiece.ROAD:
pp = new SOCRoad(pl, coord, null);
game.putPiece(pp);
mesHp.updateValue(PlayerClientListener.UpdateType.Road);
if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7])
boardPanel.flushBoardLayoutAndRepaint();
break;
case SOCPlayingPiece.SETTLEMENT:
pp = new SOCSettlement(pl, coord, null);
game.putPiece(pp);
mesHp.updateValue(PlayerClientListener.UpdateType.Settlement);
/**
* if this is the second initial settlement, then update the resource display
*/
mesHp.updateValue(PlayerClientListener.UpdateType.ResourceTotalAndDetails);
if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7] || debugShowPotentials[6])
boardPanel.flushBoardLayoutAndRepaint();
break;
case SOCPlayingPiece.CITY:
pp = new SOCCity(pl, coord, null);
game.putPiece(pp);
mesHp.updateValue(PlayerClientListener.UpdateType.Settlement);
mesHp.updateValue(PlayerClientListener.UpdateType.City);
if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7] || debugShowPotentials[6])
boardPanel.flushBoardLayoutAndRepaint();
break;
case SOCPlayingPiece.SHIP:
pp = new SOCShip(pl, coord, null);
if (!isMove) {
game.putPiece(pp);
mesHp.updateValue(PlayerClientListener.UpdateType.Ship);
} else {
game.moveShip((SOCShip) pp, moveToCoord);
if (mesHp == clientHand)
// just in case; it probably wasn't enabled
mesHp.disableBankUndoButton();
}
if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7])
boardPanel.flushBoardLayoutAndRepaint();
break;
case SOCPlayingPiece.VILLAGE:
// no need to refresh boardPanel after receiving each village
pp = new SOCVillage(coord, game.getBoard());
game.putPiece(pp);
// <--- Early return: Piece is part of board initial layout, not player info ---
return;
case SOCPlayingPiece.FORTRESS:
pp = new SOCFortress(pl, coord, game.getBoard());
game.putPiece(pp);
// <--- Early return: Piece is part of board initial layout, not added during game ---
return;
default:
chatPrintDebug("* Unknown piece type " + pieceType + " at coord 0x" + Integer.toHexString(coord));
// <--- Early return ---
return;
}
mesHp.updateValue(PlayerClientListener.UpdateType.VictoryPoints);
boardPanel.repaint();
buildingPanel.updateButtonStatus();
if (game.isDebugFreePlacement() && game.isInitialPlacement())
// update here, since gamestate doesn't change to trigger update
boardPanel.updateMode();
if (hasCalledBegan && (game.getGameState() >= SOCGame.START1A))
playSound(SOUND_PUT_PIECE);
/**
* Check for and announce change in longest road; update all players' victory points.
*/
SOCPlayer newLongestRoadPlayer = game.getPlayerWithLongestRoad();
if (newLongestRoadPlayer != oldLongestRoadPlayer) {
updateLongestLargest(true, oldLongestRoadPlayer, newLongestRoadPlayer);
}
}
use of soc.game.SOCRoad in project JSettlers2 by jdmonin.
the class SOCDisplaylessPlayerClient method handlePUTPIECE.
/**
* handle the "put piece" message
*<P>
* This method is public static for access by
* {@code SOCRobotBrain.handlePUTPIECE_updateGameData(SOCPutPiece)}.
* @param mes the message
* @param ga Message's game from {@link SOCPutPiece#getGame()}; if {@code null}, message is ignored
*/
public static void handlePUTPIECE(final SOCPutPiece mes, SOCGame ga) {
if (ga != null) {
final int pieceType = mes.getPieceType();
final int coord = mes.getCoordinates();
final SOCPlayer pl = (pieceType != SOCPlayingPiece.VILLAGE) ? ga.getPlayer(mes.getPlayerNumber()) : null;
switch(pieceType) {
case SOCPlayingPiece.ROAD:
ga.putPiece(new SOCRoad(pl, coord, null));
break;
case SOCPlayingPiece.SETTLEMENT:
ga.putPiece(new SOCSettlement(pl, coord, null));
break;
case SOCPlayingPiece.CITY:
ga.putPiece(new SOCCity(pl, coord, null));
break;
case SOCPlayingPiece.SHIP:
ga.putPiece(new SOCShip(pl, coord, null));
break;
case SOCPlayingPiece.FORTRESS:
ga.putPiece(new SOCFortress(pl, coord, ga.getBoard()));
break;
case SOCPlayingPiece.VILLAGE:
ga.putPiece(new SOCVillage(coord, ga.getBoard()));
break;
default:
System.err.println("Displayless.handlePUTPIECE: game " + ga.getName() + ": Unknown pieceType " + pieceType);
}
}
}
use of soc.game.SOCRoad in project JSettlers2 by jdmonin.
the class SOCPlayerTracker method updateLRPotential.
/**
* update the potential LR value of a possible road or ship
* by placing dummy roads/ships and calculating LR (longest road).
* If <tt>level</tt> > 0, add the new roads or ships adjacent
* to <tt>dummy</tt> and recurse.
*
* @param posRoad the possible road or ship
* @param dummy the dummy player
* @param lrLength the current LR length
* @param level how many levels of recursion, or 0 to not recurse
*/
public void updateLRPotential(SOCPossibleRoad posRoad, SOCPlayer dummy, SOCRoad dummyRoad, final int lrLength, final int level) {
// D.ebugPrintln("$$$ updateLRPotential for road at "+Integer.toHexString(posRoad.getCoordinates())+" level="+level);
//
// if we've reached the bottom level of recursion,
// or if there are no more roads to place from this one.
// then calc potential LR value
//
SOCBoard board = game.getBoard();
boolean noMoreExpansion;
if (level <= 0) {
noMoreExpansion = true;
} else {
noMoreExpansion = false;
Enumeration<Integer> adjEdgeEnum = board.getAdjacentEdgesToEdge(dummyRoad.getCoordinates()).elements();
while (adjEdgeEnum.hasMoreElements()) {
final int adjEdge = adjEdgeEnum.nextElement().intValue();
if ((dummyRoad.isRoadNotShip() && dummy.isPotentialRoad(adjEdge)) || ((!dummyRoad.isRoadNotShip()) && dummy.isPotentialShip(adjEdge))) {
noMoreExpansion = false;
break;
}
}
}
if (noMoreExpansion) {
//
// only update the potential LR if it's bigger than the
// current value
//
int newPotentialLRValue = dummy.calcLongestRoad2() - lrLength;
// D.ebugPrintln("$$$ newPotentialLRValue = "+newPotentialLRValue);
if (newPotentialLRValue > posRoad.getLRPotential()) {
posRoad.setLRPotential(newPotentialLRValue);
}
} else {
//
// we need to add new roads/ships adjacent to dummyRoad, and recurse
//
Enumeration<Integer> adjEdgeEnum = board.getAdjacentEdgesToEdge(dummyRoad.getCoordinates()).elements();
while (adjEdgeEnum.hasMoreElements()) {
final int adjEdge = adjEdgeEnum.nextElement().intValue();
if ((dummyRoad.isRoadNotShip() && dummy.isPotentialRoad(adjEdge)) || ((!dummyRoad.isRoadNotShip()) && dummy.isPotentialShip(adjEdge))) {
SOCRoad newDummyRoad;
if (dummyRoad.isRoadNotShip())
newDummyRoad = new SOCRoad(dummy, adjEdge, board);
else
newDummyRoad = new SOCShip(dummy, adjEdge, board);
dummy.putPiece(newDummyRoad, true);
updateLRPotential(posRoad, dummy, newDummyRoad, lrLength, level - 1);
dummy.removePiece(newDummyRoad, null);
}
}
}
}
use of soc.game.SOCRoad 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);
}
Aggregations