use of soc.game.SOCPlayer in project JSettlers2 by jdmonin.
the class SOCGameMessageHandler method handleENDTURN.
// / Flow of Game ///
/**
* handle "end turn" message.
* This normally ends a player's normal turn (phase {@link SOCGame#PLAY1}).
* On the 6-player board, it ends their placements during the
* {@link SOCGame#SPECIAL_BUILDING Special Building Phase}.
*
* @param c the connection that sent the message
* @param mes the message
* @since 1.0.0
*/
private void handleENDTURN(SOCGame ga, Connection c, final SOCEndTurn mes) {
final String gname = ga.getName();
if (ga.isDebugFreePlacement()) {
// turn that off before ending current turn
handler.processDebugCommand_freePlace(c, gname, "0");
}
ga.takeMonitor();
try {
final String plName = c.getData();
if (ga.getGameState() == SOCGame.OVER) {
// Should not happen; is here just in case.
SOCPlayer pl = ga.getPlayer(plName);
if (pl != null) {
String msg = ga.gameOverMessageToPlayer(pl);
// msg = "The game is over; you are the winner!";
// msg = "The game is over; <someone> won.";
// msg = "The game is over; no one won.";
srv.messageToPlayer(c, gname, msg);
}
} else if (handler.checkTurn(c, ga)) {
SOCPlayer pl = ga.getPlayer(plName);
if ((pl != null) && ga.canEndTurn(pl.getPlayerNumber()))
handler.endGameTurn(ga, pl, true);
else
srv.messageToPlayer(c, gname, "You can't end your turn yet.");
} else {
srv.messageToPlayer(c, gname, "It's not your turn.");
}
} catch (Exception e) {
D.ebugPrintStackTrace(e, "Exception caught at handleENDTURN");
}
ga.releaseMonitor();
}
use of soc.game.SOCPlayer in project JSettlers2 by jdmonin.
the class SOCPlayerTracker method recalcLargestArmyETA.
/**
* calculate the largest army ETA
*/
public void recalcLargestArmyETA() {
int laSize = 0;
SOCPlayer laPlayer = game.getPlayerWithLargestArmy();
if (laPlayer == null) {
// /
// / no one has largest army
// /
laSize = 3;
} else if (laPlayer.getPlayerNumber() == playerNumber) {
// /
// / we have largest army
// /
largestArmyETA = 0;
return;
} else {
laSize = laPlayer.getNumKnights() + 1;
}
// /
// / figure out how many knights we need to buy
// /
knightsToBuy = 0;
if (// OLD + NEW knights
(player.getNumKnights() + player.getInventory().getAmount(SOCDevCardConstants.KNIGHT)) < laSize) {
knightsToBuy = laSize - (player.getNumKnights() + player.getInventory().getAmount(SOCInventory.OLD, SOCDevCardConstants.KNIGHT));
}
if (game.getNumDevCards() >= knightsToBuy) {
// /
// / figure out how long it takes to buy this many knights
// /
SOCBuildingSpeedEstimate bse = new SOCBuildingSpeedEstimate(player.getNumbers());
int[] ourBuildingSpeed = bse.getEstimatesFromNothingFast(player.getPortFlags());
int cardETA = ourBuildingSpeed[SOCBuildingSpeedEstimate.CARD];
largestArmyETA = (cardETA + 1) * knightsToBuy;
} else {
// /
// / not enough dev cards left
// /
largestArmyETA = 500;
}
}
use of soc.game.SOCPlayer in project JSettlers2 by jdmonin.
the class RobberStrategy method getBestRobberHex.
/**
* Determine the best hex to move the robber.
*/
public static int getBestRobberHex(SOCGame game, SOCPlayer ourPlayerData, HashMap<Integer, SOCPlayerTracker> playerTrackers, Random rand) {
log.debug("%%% MOVEROBBER");
final int[] hexes = game.getBoard().getLandHexCoords();
final int prevRobberHex = game.getBoard().getRobberHex();
/**
* decide which player we want to thwart
*/
int[] winGameETAs = new int[game.maxPlayers];
for (int i = game.maxPlayers - 1; i >= 0; --i) winGameETAs[i] = 100;
Iterator<SOCPlayerTracker> trackersIter = playerTrackers.values().iterator();
while (trackersIter.hasNext()) {
SOCPlayerTracker tracker = trackersIter.next();
final int trackerPN = tracker.getPlayer().getPlayerNumber();
log.debug("%%%%%%%%% TRACKER FOR PLAYER " + trackerPN);
try {
tracker.recalcWinGameETA();
winGameETAs[trackerPN] = tracker.getWinGameETA();
log.debug("winGameETA = " + tracker.getWinGameETA());
} catch (NullPointerException e) {
log.debug("Null Pointer Exception calculating winGameETA");
winGameETAs[trackerPN] = 500;
}
}
final int ourPlayerNumber = ourPlayerData.getPlayerNumber();
int victimNum = -1;
for (int pnum = 0; pnum < game.maxPlayers; pnum++) {
if (game.isSeatVacant(pnum))
continue;
if ((victimNum < 0) && (pnum != ourPlayerNumber)) {
// The first pick
log.debug("Picking a robber victim: pnum=" + pnum);
victimNum = pnum;
} else if ((pnum != ourPlayerNumber) && (winGameETAs[pnum] < winGameETAs[victimNum])) {
// A better pick
log.debug("Picking a better robber victim: pnum=" + pnum);
victimNum = pnum;
}
}
// Postcondition: victimNum != -1 due to "First pick" in loop.
/**
* figure out the best way to thwart that player
*/
SOCPlayer victim = game.getPlayer(victimNum);
SOCBuildingSpeedEstimate estimate = new SOCBuildingSpeedEstimate();
int bestHex = prevRobberHex;
int worstSpeed = 0;
// can't move robber to desert
final boolean skipDeserts = game.isGameOptionSet("RD");
SOCBoard gboard = (skipDeserts ? game.getBoard() : null);
for (int i = 0; i < hexes.length; i++) {
/**
* only check hexes that we're not touching,
* and not the robber hex, and possibly not desert hexes
*/
if ((hexes[i] != prevRobberHex) && ourPlayerData.getNumbers().hasNoResourcesForHex(hexes[i]) && !(skipDeserts && (gboard.getHexTypeFromCoord(hexes[i]) == SOCBoard.DESERT_HEX))) {
estimate.recalculateEstimates(victim.getNumbers(), hexes[i]);
int[] speeds = estimate.getEstimatesFromNothingFast(victim.getPortFlags());
int totalSpeed = 0;
for (int j = SOCBuildingSpeedEstimate.MIN; j < SOCBuildingSpeedEstimate.MAXPLUSONE; j++) {
totalSpeed += speeds[j];
}
log.debug("total Speed = " + totalSpeed);
if (totalSpeed > worstSpeed) {
bestHex = hexes[i];
worstSpeed = totalSpeed;
log.debug("bestHex = " + Integer.toHexString(bestHex));
log.debug("worstSpeed = " + worstSpeed);
}
}
}
log.debug("%%% bestHex = " + Integer.toHexString(bestHex));
/**
* Pick a spot at random if we can't decide.
* Don't pick deserts if the game option is set.
* Don't pick one of our hexes if at all possible.
* It's not likely we'll need to pick one of our hexes
* (we try 30 times to avoid it), so there isn't code here
* to pick the 'least bad' one.
* (TODO) consider that: It would be late in the game
* if the board's that crowded with pieces.
* Use similar algorithm as picking for opponent,
* but apply it worst vs best.
*/
if (bestHex == prevRobberHex) {
int numRand = 0;
while ((bestHex == prevRobberHex) || (skipDeserts && (gboard.getHexTypeFromCoord(bestHex) == SOCBoard.DESERT_HEX)) || ((numRand < 30) && ourPlayerData.getNumbers().hasNoResourcesForHex(bestHex))) {
bestHex = hexes[Math.abs(rand.nextInt()) % hexes.length];
log.debug("%%% random pick = " + Integer.toHexString(bestHex));
++numRand;
}
}
return bestHex;
}
use of soc.game.SOCPlayer in project JSettlers2 by jdmonin.
the class SOCPlayerTracker method updateLRValues.
/**
* update the longest road values for all possible roads/ships.
*<P>
* longest road value is how much this
* road/ship would increase our longest road
* if it were built.
*<P>
* the longest road potential is how much
* this road/ship would increase our LR value
* if other roads supported by this one were
* built.
*/
public void updateLRValues() {
SOCPlayer dummy = new SOCPlayer(player);
int lrLength = player.getLongestRoadLength();
//
// for each possible road with no necessary roads
//
Iterator<SOCPossibleRoad> posRoadsIter = possibleRoads.values().iterator();
while (posRoadsIter.hasNext()) {
SOCPossibleRoad posRoad = posRoadsIter.next();
if (posRoad.getNecessaryRoads().isEmpty()) {
//
// calc longest road value
//
SOCRoad dummyRoad;
if (posRoad.isRoadNotShip() || ((posRoad instanceof SOCPossibleShip) && ((SOCPossibleShip) posRoad).isCoastalRoadAndShip))
// TODO better coastal handling
dummyRoad = new SOCRoad(dummy, posRoad.getCoordinates(), null);
else
dummyRoad = new SOCShip(dummy, posRoad.getCoordinates(), null);
dummy.putPiece(dummyRoad, true);
int newLRLength = dummy.calcLongestRoad2();
if (newLRLength <= lrLength) {
posRoad.setLRValue(0);
} else {
posRoad.setLRValue(newLRLength - lrLength);
}
// D.ebugPrintln("$$ updateLRValue for "+Integer.toHexString(posRoad.getCoordinates())+" is "+posRoad.getLRValue());
//
// update potential LR value
//
posRoad.setLRPotential(0);
updateLRPotential(posRoad, dummy, dummyRoad, lrLength, LR_CALC_LEVEL);
dummy.removePiece(dummyRoad, null);
} else {
posRoad.setLRValue(0);
posRoad.setLRPotential(0);
}
}
dummy.destroyPlayer();
}
use of soc.game.SOCPlayer 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