use of soc.game.SOCBoard in project JSettlers2 by jdmonin.
the class SOCPlayerTracker method addOurNewSettlement.
/**
* Add one of our settlements, and newly possible pieces from it.
* Adds a new possible city; removes conflicting possible settlements (ours or other players).
* On the large Sea board, if this is a coastal settlement adds newly possible ships, and if
* we've just settled a new island, newly possible roads, because the coastal settlement is
* a roads {@literal <->} ships transition.
*<P>
* Newly possible roads or ships next to the settlement are expanded by calling
* {@link #expandRoadOrShip(SOCPossibleRoad, SOCPlayer, SOCPlayer, HashMap, int)}.
* {@link #EXPAND_LEVEL} is the basic expansion length, and ships add
* {@link #EXPAND_LEVEL_SHIP_EXTRA} to that for crossing the sea to nearby islands.
*<P>
* Called in 2 different conditions:
*<UL>
* <LI> To track an actual (not possible) settlement that's just been placed
* <LI> To see the effects of trying to placing a possible settlement, in a copy of the PlayerTracker
* ({@link #tryPutPiece(SOCPlayingPiece, SOCGame, HashMap)})
*</UL>
*
* @param settlement the new settlement
* @param trackers player trackers for all of the players
*/
public synchronized void addOurNewSettlement(SOCSettlement settlement, HashMap<Integer, SOCPlayerTracker> trackers) {
// D.ebugPrintln();
D.ebugPrintln("$$$ addOurNewSettlement : " + settlement);
SOCBoard board = game.getBoard();
final Integer settlementCoords = Integer.valueOf(settlement.getCoordinates());
/**
* add a new possible city
*/
possibleCities.put(settlementCoords, new SOCPossibleCity(player, settlement.getCoordinates()));
/**
* see if the new settlement was a possible settlement in
* the list. if so, remove it.
*/
SOCPossibleSettlement ps = possibleSettlements.get(settlementCoords);
if (ps != null) {
D.ebugPrintln("$$$ was a possible settlement");
/**
* copy a list of all the conflicting settlements
*/
List<SOCPossibleSettlement> conflicts = new ArrayList<SOCPossibleSettlement>(ps.getConflicts());
/**
* remove the possible settlement that is now a real settlement
*/
D.ebugPrintln("$$$ removing " + Integer.toHexString(settlement.getCoordinates()));
possibleSettlements.remove(settlementCoords);
removeFromNecessaryRoads(ps);
/**
* remove possible settlements that this one cancels out
*/
for (SOCPossibleSettlement conflict : conflicts) {
D.ebugPrintln("$$$ checking conflict with " + conflict.getPlayer().getPlayerNumber() + ":" + Integer.toHexString(conflict.getCoordinates()));
SOCPlayerTracker tracker = trackers.get(Integer.valueOf(conflict.getPlayer().getPlayerNumber()));
if (tracker != null) {
D.ebugPrintln("$$$ removing " + Integer.toHexString(conflict.getCoordinates()));
tracker.getPossibleSettlements().remove(Integer.valueOf(conflict.getCoordinates()));
removeFromNecessaryRoads(conflict);
/**
* remove the conflicts that this settlement made
*/
for (SOCPossibleSettlement otherConflict : conflict.getConflicts()) {
D.ebugPrintln("$$$ removing conflict " + Integer.toHexString(conflict.getCoordinates()) + " from " + Integer.toHexString(otherConflict.getCoordinates()));
otherConflict.removeConflict(conflict);
}
}
}
} else {
/**
* if the new settlement wasn't a possible settlement,
* we still need to cancel out other players possible settlements
*/
D.ebugPrintln("$$$ wasn't possible settlement");
ArrayList<SOCPossibleSettlement> trash = new ArrayList<SOCPossibleSettlement>();
List<Integer> adjNodes = board.getAdjacentNodesToNode(settlement.getCoordinates());
Iterator<SOCPlayerTracker> trackersIter = trackers.values().iterator();
while (trackersIter.hasNext()) {
SOCPlayerTracker tracker = trackersIter.next();
SOCPossibleSettlement posSet = tracker.getPossibleSettlements().get(settlementCoords);
D.ebugPrintln("$$$ tracker for player " + tracker.getPlayer().getPlayerNumber());
/**
* check the node that the settlement is on
*/
D.ebugPrintln("$$$ checking node " + Integer.toHexString(settlement.getCoordinates()));
if (posSet != null) {
D.ebugPrintln("$$$ trashing " + Integer.toHexString(posSet.getCoordinates()));
trash.add(posSet);
/**
* remove the conflicts that this settlement made
*/
for (SOCPossibleSettlement conflict : posSet.getConflicts()) {
D.ebugPrintln("$$$ removing conflict " + Integer.toHexString(posSet.getCoordinates()) + " from " + Integer.toHexString(conflict.getCoordinates()));
conflict.removeConflict(posSet);
}
}
/**
* check adjacent nodes
*/
for (Integer adjNode : adjNodes) {
D.ebugPrintln("$$$ checking node " + Integer.toHexString(adjNode.intValue()));
posSet = tracker.getPossibleSettlements().get(adjNode);
if (posSet != null) {
D.ebugPrintln("$$$ trashing " + Integer.toHexString(posSet.getCoordinates()));
trash.add(posSet);
/**
* remove the conflicts that this settlement made
*/
for (SOCPossibleSettlement conflict : posSet.getConflicts()) {
D.ebugPrintln("$$$ removing conflict " + Integer.toHexString(posSet.getCoordinates()) + " from " + Integer.toHexString(conflict.getCoordinates()));
conflict.removeConflict(posSet);
}
}
}
/**
* take out the trash
* (no-longer-possible settlements, roads that support it)
*/
D.ebugPrintln("$$$ removing trash for " + tracker.getPlayer().getPlayerNumber());
for (SOCPossibleSettlement pset : trash) {
D.ebugPrintln("$$$ removing " + Integer.toHexString(pset.getCoordinates()) + " owned by " + pset.getPlayer().getPlayerNumber());
tracker.getPossibleSettlements().remove(Integer.valueOf(pset.getCoordinates()));
removeFromNecessaryRoads(pset);
}
trash.clear();
}
}
/**
* Add possible road-ship transitions made possible by the new settlement.
* Normally a new settlement placement doesn't need to add possible roads or ships,
* because each road/ship placement adds possibles past the new far end of the route
* in addOurNewRoadOrShip.
*/
if (board instanceof SOCBoardLarge) {
ArrayList<SOCPossibleRoad> roadsToExpand = null;
/**
* Only add new possible roads if we're on a new island
* (that is, the newly placed settlement has no adjacent roads already).
* Coastal ships/roads may still be added even if settleAlreadyHasRoad.
*/
boolean settleAlreadyHasRoad = false;
ArrayList<SOCPossibleRoad> possibleNewIslandRoads = null;
final List<Integer> adjacEdges = board.getAdjacentEdgesToNode(settlementCoords);
// First, loop to check for settleAlreadyHasRoad
for (Integer edge : adjacEdges) {
if (possibleRoads.get(edge) != null)
// already a possible road or ship here
continue;
SOCRoad road = board.roadAtEdge(edge);
if ((road != null) && road.isRoadNotShip()) {
settleAlreadyHasRoad = true;
break;
}
}
// Now, possibly add new roads/ships/coastals
for (Integer edge : adjacEdges) {
// TODO remove these debug prints soon
// System.err.println("L1348: examine edge 0x"
// + Integer.toHexString(edge) + " for placed settle 0x"
// + Integer.toHexString(settlementCoords));
SOCPossibleRoad pRoad = possibleRoads.get(edge);
if (pRoad != null) {
// already a possible road or ship
continue;
}
if (board.roadAtEdge(edge) != null) {
// not new, something's already there
continue;
}
if (player.isPotentialRoad(edge)) {
// Add newly possible roads from settlement placement.
// Probably won't need to happen (usually added in addOurNewRoadOrShip, see newPossibleRoads)
// but could on a new island's first settlement
final boolean isCoastline = player.isPotentialShip(edge);
if (settleAlreadyHasRoad && !isCoastline)
continue;
if (possibleNewIslandRoads == null)
possibleNewIslandRoads = new ArrayList<SOCPossibleRoad>();
possibleNewIslandRoads.add((isCoastline) ? new SOCPossibleShip(player, edge, true, null) : new SOCPossibleRoad(player, edge, null));
if (isCoastline)
System.err.println("L1675: " + toString() + ": new PossibleShip(true) at 0x" + Integer.toHexString(edge));
} else if (player.isPotentialShip(edge)) {
// A way out to a new island
SOCPossibleShip newPS = new SOCPossibleShip(player, edge, false, null);
possibleRoads.put(edge, newPS);
System.err.println("L1685: " + toString() + ": new PossibleShip(false) at 0x" + Integer.toHexString(edge) + " from coastal settle 0x" + Integer.toHexString(settlementCoords));
if (roadsToExpand == null)
roadsToExpand = new ArrayList<SOCPossibleRoad>();
roadsToExpand.add(newPS);
newPS.setExpandedFlag();
}
}
if ((possibleNewIslandRoads != null) && !game.isInitialPlacement()) {
// (Make sure this isn't initial placement, where nothing has adjacent roads)
for (SOCPossibleRoad pr : possibleNewIslandRoads) {
possibleRoads.put(Integer.valueOf(pr.getCoordinates()), pr);
System.err.println("L1396: new possible road at edge 0x" + Integer.toHexString(pr.getCoordinates()) + " from coastal settle 0x" + Integer.toHexString(settlementCoords));
if (roadsToExpand == null)
roadsToExpand = new ArrayList<SOCPossibleRoad>();
roadsToExpand.add(pr);
pr.setExpandedFlag();
}
}
if (roadsToExpand != null) {
//
// expand possible ships/roads that we've added
//
SOCPlayer dummy = new SOCPlayer(player);
for (SOCPossibleRoad expandPR : roadsToExpand) {
final int expand = EXPAND_LEVEL + (expandPR.isRoadNotShip() ? 0 : EXPAND_LEVEL_SHIP_EXTRA);
expandRoadOrShip(expandPR, player, dummy, trackers, expand);
}
dummy.destroyPlayer();
}
}
}
use of soc.game.SOCBoard in project JSettlers2 by jdmonin.
the class SOCDisplaylessPlayerClient method handleSIMPLEACTION.
/**
* Update any game data from "simple action" announcements from the server.
* Currently ignores them except for:
*<UL>
* <LI> {@link SOCSimpleAction#TRADE_PORT_REMOVED TRADE_PORT_REMOVED}:
* Calls {@link SOCGame#removePort(SOCPlayer, int)}
*</UL>
*
* @param games Games the client is playing, for method reuse by SOCPlayerClient
* @param mes the message
* @since 1.1.19
*/
public static void handleSIMPLEACTION(final Map<String, SOCGame> games, final SOCSimpleAction mes) {
final String gaName = mes.getGame();
SOCGame ga = games.get(gaName);
if (ga == null)
// Not one of our games
return;
final int atype = mes.getActionType();
switch(atype) {
case SOCSimpleAction.BOARD_EDGE_SET_SPECIAL:
{
final SOCBoard bd = ga.getBoard();
if (bd instanceof SOCBoardLarge)
((SOCBoardLarge) bd).setSpecialEdge(mes.getValue1(), mes.getValue2());
}
break;
case SOCSimpleAction.TRADE_PORT_REMOVED:
if (ga.hasSeaBoard)
ga.removePort(null, mes.getValue1());
break;
case SOCSimpleAction.DEVCARD_BOUGHT:
case SOCSimpleAction.RSRC_TYPE_MONOPOLIZED:
case SOCSimpleAction.SC_PIRI_FORT_ATTACK_RESULT:
// game data updates are sent in preceding or following messages, can ignore this one
break;
default:
// ignore unknown types
// Since the bots and server are almost always the same version, this
// shouldn't often occur: print for debugging.
System.err.println("handleSIMPLEACTION: Unknown type ignored: " + atype + " in game " + gaName);
}
}
use of soc.game.SOCBoard in project JSettlers2 by jdmonin.
the class SOCDisplaylessPlayerClient method handleBOARDLAYOUT.
/**
* handle the "board layout" message
* @param mes the message
*/
protected void handleBOARDLAYOUT(SOCBoardLayout mes) {
SOCGame ga = games.get(mes.getGame());
if (ga != null) {
// BOARDLAYOUT is always the v1 board encoding (oldest format)
SOCBoard bd = ga.getBoard();
bd.setHexLayout(mes.getHexLayout());
bd.setNumberLayout(mes.getNumberLayout());
bd.setRobberHex(mes.getRobberHex(), false);
ga.updateAtBoardLayout();
}
}
use of soc.game.SOCBoard in project JSettlers2 by jdmonin.
the class SOCRobotDM method scenarioGameStrategyPlan_SC_PIRI_buildNextShip.
/**
* If possible, calculate where our next ship would be placed, and add it to {@link #buildingPlan}.
* Assumes our player's {@link SOCPlayer#getFortress()} is west of all boats we've already placed.
* If our line of ships has reached the fortress per {@link SOCPlayer#getMostRecentShip()},
* nothing to do: That goal is complete.
* @return True if next ship is possible and was added to {@link #buildingPlan}
* @since 2.0.00
*/
private final boolean scenarioGameStrategyPlan_SC_PIRI_buildNextShip() {
SOCShip prevShip = ourPlayerData.getMostRecentShip();
if (prevShip == null)
// player starts with 1 ship, so should never be null
return false;
final int fortressNode;
{
final SOCFortress fo = ourPlayerData.getFortress();
if (fo == null)
// already defeated it
return false;
fortressNode = fo.getCoordinates();
}
final int prevShipNode;
{
final int[] nodes = prevShip.getAdjacentNodes();
final int c0 = nodes[0] & 0xFF, c1 = nodes[1] & 0xFF;
if (c0 < c1)
prevShipNode = nodes[0];
else if (c1 < c0)
prevShipNode = nodes[1];
else {
// prevShip goes north-south; check its node rows vs fortress row
final int r0 = nodes[0] >> 8, r1 = nodes[1] >> 8, rFort = fortressNode >> 8;
if (Math.abs(rFort - r0) < Math.abs(rFort - r1))
prevShipNode = nodes[0];
else
prevShipNode = nodes[1];
}
}
if (prevShipNode == fortressNode) {
return false;
}
// Get the player's ship path towards fortressNode from prevShip.
// We need to head west, possibly north or south.
final HashSet<Integer> lse = ourPlayerData.getRestrictedLegalShips();
if (lse == null)
// null lse should not occur in _SC_PIRI
return false;
// Need 1 or 2 edges that are in lse and aren't prevShipEdge,
// and the edge's far node is either further west than prevShipNode,
// or is vertical and takes us closer north or south to the fortress.
int edge1 = -9, edge2 = -9;
final SOCBoard board = game.getBoard();
final int prevShipEdge = prevShip.getCoordinates();
int[] nextPossiEdges = board.getAdjacentEdgesToNode_arr(prevShipNode);
for (int i = 0; i < nextPossiEdges.length; ++i) {
final int edge = nextPossiEdges[i];
if ((edge == -9) || (edge == prevShipEdge) || !lse.contains(Integer.valueOf(edge)))
continue;
// be sure this edge takes us towards fortressNode
final int farNode = board.getAdjacentNodeFarEndOfEdge(edge, prevShipNode);
final int cShip = prevShipNode & 0xFF, cEdge = farNode & 0xFF;
if (cEdge > cShip) {
// farNode is east, not west
continue;
} else if (cEdge == cShip) {
final int rShip = prevShipNode >> 8, rEdge = farNode >> 8, rFort = fortressNode >> 8;
if (Math.abs(rFort - rEdge) > Math.abs(rFort - rShip))
// farNode isn't closer to fortress
continue;
}
// OK
if (edge1 == -9)
edge1 = edge;
else
edge2 = edge;
}
if (edge1 == -9)
// happens if we've built ships out to fortressNode already
return false;
final int newEdge;
if ((edge2 == -9) || (Math.random() < 0.5))
newEdge = edge1;
else
newEdge = edge2;
buildingPlan.add(new SOCPossibleShip(ourPlayerData, newEdge, false, null));
System.err.println("L2112 ** " + ourPlayerData.getName() + ": Planned possible ship at 0x" + Integer.toHexString(newEdge) + " towards fortress");
return true;
}
use of soc.game.SOCBoard in project JSettlers2 by jdmonin.
the class SOCRobotDM method scorePossibleSettlements.
/**
* Score possible settlements for for the smart game strategy ({@link #SMART_STRATEGY}),
* from {@link #ourPlayerTracker}{@link SOCPlayerTracker#getPossibleSettlements() .getPossibleSettlements()}
* into {@link #threatenedSettlements} and {@link #goodSettlements};
* calculate those settlements' {@link SOCPossiblePiece#getScore()}s.
* Ignores possible settlements that require roads or ships.
*
* @see #scoreSettlementsForDumb(int, SOCBuildingSpeedEstimate)
*/
protected void scorePossibleSettlements(final int settlementETA, final int leadersCurrentWGETA) {
D.ebugPrintln("****** scorePossibleSettlements");
// int ourCurrentWGETA = ourPlayerTracker.getWinGameETA();
/*
boolean goingToPlayRB = false;
if (! ourPlayerData.hasPlayedDevCard() &&
ourPlayerData.getNumPieces(SOCPlayingPiece.ROAD) >= 2 &&
ourPlayerData.getInventory().getAmount(SOCInventory.OLD, SOCDevCardConstants.ROADS) > 0) {
goingToPlayRB = true;
}
*/
Iterator<SOCPossibleSettlement> posSetsIter = ourPlayerTracker.getPossibleSettlements().values().iterator();
while (posSetsIter.hasNext()) {
SOCPossibleSettlement posSet = posSetsIter.next();
D.ebugPrintln("*** scoring possible settlement at " + Integer.toHexString(posSet.getCoordinates()));
if (!threatenedSettlements.contains(posSet)) {
threatenedSettlements.add(posSet);
} else if (!goodSettlements.contains(posSet)) {
goodSettlements.add(posSet);
}
//
if (posSet.getNecessaryRoads().isEmpty()) {
D.ebugPrintln("*** no roads needed");
//
// no roads needed
//
//
// get wgeta score
//
SOCBoard board = game.getBoard();
SOCSettlement tmpSet = new SOCSettlement(ourPlayerData, posSet.getCoordinates(), board);
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().startRecording("SETTLEMENT" + posSet.getCoordinates());
brain.getDRecorder().record("Estimate value of settlement at " + board.nodeCoordToString(posSet.getCoordinates()));
}
HashMap<Integer, SOCPlayerTracker> trackersCopy = SOCPlayerTracker.tryPutPiece(tmpSet, game, playerTrackers);
SOCPlayerTracker.updateWinGameETAs(trackersCopy);
float wgetaScore = calcWGETABonus(playerTrackers, trackersCopy);
D.ebugPrintln("*** wgetaScore = " + wgetaScore);
D.ebugPrintln("*** ETA for settlement = " + settlementETA);
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().record("ETA = " + settlementETA);
}
float etaBonus = getETABonus(settlementETA, leadersCurrentWGETA, wgetaScore);
D.ebugPrintln("etaBonus = " + etaBonus);
// posSet.addToScore(wgetaScore);
posSet.addToScore(etaBonus);
if ((brain != null) && (brain.getDRecorder().isOn())) {
brain.getDRecorder().record("WGETA score = " + df1.format(wgetaScore));
brain.getDRecorder().record("Total settlement score = " + df1.format(etaBonus));
brain.getDRecorder().stopRecording();
}
SOCPlayerTracker.undoTryPutPiece(tmpSet, game);
}
}
}
Aggregations