/** * Calculate what resources this player will get on each die roll, optionally taking the robber * into account. * * @param numbers the numbers that the player is touching * @param robberHex Robber location from {@link SOCBoard#getRobberHex()}, or -1 to ignore the * robber */ public void recalculateResourcesForRoll(SOCPlayerNumbers numbers, final int robberHex) { // D.ebugPrintln("@@@@@@@@ recalculateResourcesForRoll"); // D.ebugPrintln("@@@@@@@@ numbers = "+numbers); // D.ebugPrintln("@@@@@@@@ robberHex = "+Integer.toHexString(robberHex)); recalc = true; for (int diceResult = 2; diceResult <= 12; diceResult++) { Vector<Integer> resources = (robberHex != -1) ? numbers.getResourcesForNumber(diceResult, robberHex) : numbers.getResourcesForNumber(diceResult); if (resources != null) { SOCResourceSet resourceSet = resourcesForRoll[diceResult]; if (resourceSet == null) { resourceSet = new SOCResourceSet(); resourcesForRoll[diceResult] = resourceSet; } else { resourceSet.clear(); } Enumeration<Integer> resourcesEnum = resources.elements(); while (resourcesEnum.hasMoreElements()) { Integer resourceInt = resourcesEnum.nextElement(); resourceSet.add(1, resourceInt.intValue()); } // D.ebugPrintln("### resources for "+diceResult+" = "+resourceSet); } } }
/** * Takes a table of nodes and adds a weighted score to each node score in the table. Nodes * touching hexes with better numbers get better scores. Also numbers that the player isn't * touching yet are better than ones that the player is already touching. * * @param nodes the table of nodes with scores: Hashtable<Integer,Integer> . Contents will * be modified by the scoring. * @param player the player that we are doing the rating for, or <tt>null</tt>; will give a bonus * to numbers the player isn't already touching * @param weight a number that is multiplied by the score */ protected void bestSpotForNumbers( Hashtable<Integer, Integer> nodes, SOCPlayer player, int weight) { final int[] numRating = SOCNumberProbabilities.INT_VALUES; final SOCPlayerNumbers playerNumbers = (player != null) ? player.getNumbers() : null; final SOCBoard board = game.getBoard(); // 80 is highest practical score (40 if player == null) final int maxScore = (player != null) ? 80 : 40; int oldScore; Enumeration<Integer> nodesEnum = nodes.keys(); while (nodesEnum.hasMoreElements()) { final Integer node = nodesEnum.nextElement(); // log.debug("BSN - looking at node "+Integer.toHexString(node.intValue())); oldScore = nodes.get(node).intValue(); int score = 0; Enumeration<Integer> hexesEnum = board.getAdjacentHexesToNode(node.intValue()).elements(); while (hexesEnum.hasMoreElements()) { final int hex = hexesEnum.nextElement().intValue(); final int number = board.getNumberOnHexFromCoord(hex); score += numRating[number]; if ((number != 0) && (playerNumbers != null) && !playerNumbers.hasNumber(number)) { /** add a bonus for numbers that the player doesn't already have */ // log.debug("ADDING BONUS FOR NOT HAVING "+number); score += numRating[number]; } // log.debug(" -- -- Adding "+numRating[board.getNumberOnHexFromCoord(hex)]); } /* * normalize score and multiply by weight * 80 is highest practical score (40 if player == null) * lowest score is 0 */ final int nScore = ((score * 100) / maxScore) * weight; final Integer finalScore = new Integer(nScore + oldScore); nodes.put(node, finalScore); // log.debug("BSN -- put node "+Integer.toHexString(node.intValue())+" with old score // "+oldScore+" + new score "+nScore); } }
/** * Calculate the rollsPerResource estimates, optionally considering the robber's location. * * @param numbers the numbers that the player is touching * @param robberHex Robber location from {@link SOCBoard#getRobberHex()}, or -1 to ignore the * robber */ public void recalculateRollsPerResource(SOCPlayerNumbers numbers, final int robberHex) { // D.ebugPrintln("@@@@@@@@ recalculateRollsPerResource"); // D.ebugPrintln("@@@@@@@@ numbers = " + numbers); // D.ebugPrintln("@@@@@@@@ robberHex = " + Integer.toHexString(robberHex)); recalc = true; /** figure out how many resources we get per roll */ for (int resource = SOCResourceConstants.CLAY; resource <= SOCResourceConstants.WOOD; resource++) { // D.ebugPrintln("resource: " + resource); float totalProbability = 0.0f; Enumeration<Integer> numbersEnum = ((robberHex != -1) ? numbers.getNumbersForResource(resource, robberHex) : numbers.getNumbersForResource(resource)) .elements(); while (numbersEnum.hasMoreElements()) { Integer number = numbersEnum.nextElement(); totalProbability += SOCNumberProbabilities.FLOAT_VALUES[number.intValue()]; } // D.ebugPrintln("totalProbability: " + totalProbability); if (totalProbability != 0.0f) { rollsPerResource[resource] = Math.round(1.0f / totalProbability); } else { rollsPerResource[resource] = 55555; } // D.ebugPrintln("rollsPerResource: " + rollsPerResource[resource]); } }
/** figure out where to place the two settlements */ public int planInitialSettlements(SOCGame game, SOCPlayer ourPlayerData) { log.debug("--- planInitialSettlements"); int[] rolls; Enumeration hexes; // Integers int speed; boolean allTheWay; firstSettlement = 0; secondSettlement = 0; int bestSpeed = 4 * SOCBuildingSpeedEstimate.DEFAULT_ROLL_LIMIT; SOCBoard board = game.getBoard(); SOCResourceSet emptySet = new SOCResourceSet(); SOCPlayerNumbers playerNumbers = new SOCPlayerNumbers(board.getBoardEncodingFormat()); int probTotal; int bestProbTotal; boolean[] ports = new boolean[SOCBoard.WOOD_PORT + 1]; SOCBuildingSpeedEstimate estimate = new SOCBuildingSpeedEstimate(); int[] prob = SOCNumberProbabilities.INT_VALUES; bestProbTotal = 0; for (int firstNode = board.getMinNode(); firstNode <= SOCBoard.MAXNODE; firstNode++) { if (ourPlayerData.isPotentialSettlement(firstNode)) { Integer firstNodeInt = new Integer(firstNode); // // this is just for testing purposes // log.debug("FIRST NODE -----------"); log.debug("firstNode = " + board.nodeCoordToString(firstNode)); StringBuffer sb = new StringBuffer(); sb.append("numbers:["); playerNumbers.clear(); probTotal = 0; hexes = SOCBoard.getAdjacentHexesToNode(firstNode).elements(); while (hexes.hasMoreElements()) { Integer hex = (Integer) hexes.nextElement(); int number = board.getNumberOnHexFromCoord(hex.intValue()); int resource = board.getHexTypeFromCoord(hex.intValue()); playerNumbers.addNumberForResource(number, resource, hex.intValue()); probTotal += prob[number]; sb.append(number + " "); } sb.append("]"); log.debug(sb.toString()); sb = new StringBuffer(); sb.append("ports: "); for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) { if (board.getPortCoordinates(portType).contains(firstNodeInt)) { ports[portType] = true; } else { ports[portType] = false; } sb.append(ports[portType] + " "); } log.debug(sb.toString()); log.debug("probTotal = " + probTotal); estimate.recalculateEstimates(playerNumbers); speed = 0; allTheWay = false; try { speed += estimate.calculateRollsFast(emptySet, SOCGame.SETTLEMENT_SET, 300, ports).getRolls(); speed += estimate.calculateRollsFast(emptySet, SOCGame.CITY_SET, 300, ports).getRolls(); speed += estimate.calculateRollsFast(emptySet, SOCGame.CARD_SET, 300, ports).getRolls(); speed += estimate.calculateRollsFast(emptySet, SOCGame.ROAD_SET, 300, ports).getRolls(); } catch (CutoffExceededException e) { } rolls = estimate.getEstimatesFromNothingFast(ports, 300); sb = new StringBuffer(); sb.append(" road: " + rolls[SOCBuildingSpeedEstimate.ROAD]); sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]); sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]); sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]); log.debug(sb.toString()); log.debug("speed = " + speed); // // end test // for (int secondNode = firstNode + 1; secondNode <= SOCBoard.MAXNODE; secondNode++) { if ((ourPlayerData.isPotentialSettlement(secondNode)) && (!board.getAdjacentNodesToNode(secondNode).contains(firstNodeInt))) { log.debug("firstNode = " + board.nodeCoordToString(firstNode)); log.debug("secondNode = " + board.nodeCoordToString(secondNode)); Integer secondNodeInt = new Integer(secondNode); /** get the numbers for these settlements */ sb = new StringBuffer(); sb.append("numbers:["); playerNumbers.clear(); probTotal = 0; hexes = SOCBoard.getAdjacentHexesToNode(firstNode).elements(); while (hexes.hasMoreElements()) { Integer hex = (Integer) hexes.nextElement(); int number = board.getNumberOnHexFromCoord(hex.intValue()); int resource = board.getHexTypeFromCoord(hex.intValue()); playerNumbers.addNumberForResource(number, resource, hex.intValue()); probTotal += prob[number]; sb.append(number + " "); } sb.append("] ["); hexes = SOCBoard.getAdjacentHexesToNode(secondNode).elements(); while (hexes.hasMoreElements()) { Integer hex = (Integer) hexes.nextElement(); int number = board.getNumberOnHexFromCoord(hex.intValue()); int resource = board.getHexTypeFromCoord(hex.intValue()); playerNumbers.addNumberForResource(number, resource, hex.intValue()); probTotal += prob[number]; sb.append(number + " "); } sb.append("]"); log.debug(sb.toString()); /** see if the settlements are on any ports */ sb = new StringBuffer(); sb.append("ports: "); for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) { if ((board.getPortCoordinates(portType).contains(firstNodeInt)) || (board.getPortCoordinates(portType).contains(secondNodeInt))) { ports[portType] = true; } else { ports[portType] = false; } sb.append(ports[portType] + " "); } log.debug(sb.toString()); log.debug("probTotal = " + probTotal); /** estimate the building speed for this pair */ estimate.recalculateEstimates(playerNumbers); speed = 0; allTheWay = false; try { speed += estimate .calculateRollsFast(emptySet, SOCGame.SETTLEMENT_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsFast(emptySet, SOCGame.CITY_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsFast(emptySet, SOCGame.CARD_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsFast(emptySet, SOCGame.ROAD_SET, bestSpeed, ports) .getRolls(); allTheWay = true; } } } } catch (CutoffExceededException e) { speed = bestSpeed; } rolls = estimate.getEstimatesFromNothingFast(ports, bestSpeed); sb = new StringBuffer(); sb.append(" road: " + rolls[SOCBuildingSpeedEstimate.ROAD]); sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]); sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]); sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]); log.debug(sb.toString()); log.debug("allTheWay = " + allTheWay); log.debug("speed = " + speed); /** keep the settlements with the best speed */ if (speed < bestSpeed) { firstSettlement = firstNode; secondSettlement = secondNode; bestSpeed = speed; bestProbTotal = probTotal; log.debug("bestSpeed = " + bestSpeed); log.debug("bestProbTotal = " + bestProbTotal); } else if ((speed == bestSpeed) && allTheWay) { if (probTotal > bestProbTotal) { log.debug("Equal speed, better prob"); firstSettlement = firstNode; secondSettlement = secondNode; bestSpeed = speed; bestProbTotal = probTotal; log.debug("firstSettlement = " + Integer.toHexString(firstSettlement)); log.debug("secondSettlement = " + Integer.toHexString(secondSettlement)); log.debug("bestSpeed = " + bestSpeed); log.debug("bestProbTotal = " + bestProbTotal); } } } } } } /** choose which settlement to place first */ playerNumbers.clear(); hexes = SOCBoard.getAdjacentHexesToNode(firstSettlement).elements(); while (hexes.hasMoreElements()) { int hex = ((Integer) hexes.nextElement()).intValue(); int number = board.getNumberOnHexFromCoord(hex); int resource = board.getHexTypeFromCoord(hex); playerNumbers.addNumberForResource(number, resource, hex); } Integer firstSettlementInt = new Integer(firstSettlement); for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) { if (board.getPortCoordinates(portType).contains(firstSettlementInt)) { ports[portType] = true; } else { ports[portType] = false; } } estimate.recalculateEstimates(playerNumbers); int firstSpeed = 0; int cutoff = 100; try { firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.SETTLEMENT_SET, cutoff, ports).getRolls(); } catch (CutoffExceededException e) { firstSpeed += cutoff; } try { firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CITY_SET, cutoff, ports).getRolls(); } catch (CutoffExceededException e) { firstSpeed += cutoff; } try { firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CARD_SET, cutoff, ports).getRolls(); } catch (CutoffExceededException e) { firstSpeed += cutoff; } try { firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.ROAD_SET, cutoff, ports).getRolls(); } catch (CutoffExceededException e) { firstSpeed += cutoff; } playerNumbers.clear(); hexes = SOCBoard.getAdjacentHexesToNode(secondSettlement).elements(); while (hexes.hasMoreElements()) { int hex = ((Integer) hexes.nextElement()).intValue(); int number = board.getNumberOnHexFromCoord(hex); int resource = board.getHexTypeFromCoord(hex); playerNumbers.addNumberForResource(number, resource, hex); } Integer secondSettlementInt = new Integer(secondSettlement); for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) { if (board.getPortCoordinates(portType).contains(secondSettlementInt)) { ports[portType] = true; } else { ports[portType] = false; } } estimate.recalculateEstimates(playerNumbers); int secondSpeed = 0; try { secondSpeed += estimate .calculateRollsFast(emptySet, SOCGame.SETTLEMENT_SET, bestSpeed, ports) .getRolls(); } catch (CutoffExceededException e) { secondSpeed += cutoff; } try { secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CITY_SET, bestSpeed, ports).getRolls(); } catch (CutoffExceededException e) { secondSpeed += cutoff; } try { secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CARD_SET, bestSpeed, ports).getRolls(); } catch (CutoffExceededException e) { secondSpeed += cutoff; } try { secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.ROAD_SET, bestSpeed, ports).getRolls(); } catch (CutoffExceededException e) { secondSpeed += cutoff; } if (firstSpeed > secondSpeed) { int tmp = firstSettlement; firstSettlement = secondSettlement; secondSettlement = tmp; } log.debug( board.nodeCoordToString(firstSettlement) + ":" + firstSpeed + ", " + board.nodeCoordToString(secondSettlement) + ":" + secondSpeed); return firstSettlement; }
/** figure out where to place the second settlement */ public int planSecondSettlement(SOCGame game, SOCPlayer ourPlayerData) { log.debug("--- planSecondSettlement"); int bestSpeed = 4 * SOCBuildingSpeedEstimate.DEFAULT_ROLL_LIMIT; SOCBoard board = game.getBoard(); SOCResourceSet emptySet = new SOCResourceSet(); SOCPlayerNumbers playerNumbers = new SOCPlayerNumbers(board.getBoardEncodingFormat()); boolean[] ports = new boolean[SOCBoard.WOOD_PORT + 1]; SOCBuildingSpeedEstimate estimate = new SOCBuildingSpeedEstimate(); int probTotal; int bestProbTotal; int[] prob = SOCNumberProbabilities.INT_VALUES; int firstNode = firstSettlement; Integer firstNodeInt = new Integer(firstNode); bestProbTotal = 0; secondSettlement = -1; for (int secondNode = board.getMinNode(); secondNode <= SOCBoard.MAXNODE; secondNode++) { if ((ourPlayerData.isPotentialSettlement(secondNode)) && (!board.getAdjacentNodesToNode(secondNode).contains(firstNodeInt))) { Integer secondNodeInt = new Integer(secondNode); /** get the numbers for these settlements */ StringBuffer sb = new StringBuffer(); sb.append("numbers: "); playerNumbers.clear(); probTotal = 0; Enumeration hexes = SOCBoard.getAdjacentHexesToNode(firstNode).elements(); // Integers while (hexes.hasMoreElements()) { final int hex = ((Integer) hexes.nextElement()).intValue(); int number = board.getNumberOnHexFromCoord(hex); int resource = board.getHexTypeFromCoord(hex); playerNumbers.addNumberForResource(number, resource, hex); probTotal += prob[number]; sb.append(number + " "); } hexes = SOCBoard.getAdjacentHexesToNode(secondNode).elements(); while (hexes.hasMoreElements()) { final int hex = ((Integer) hexes.nextElement()).intValue(); int number = board.getNumberOnHexFromCoord(hex); int resource = board.getHexTypeFromCoord(hex); playerNumbers.addNumberForResource(number, resource, hex); probTotal += prob[number]; sb.append(number + " "); } /** see if the settlements are on any ports */ sb.append("ports: "); for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) { if ((board.getPortCoordinates(portType).contains(firstNodeInt)) || (board.getPortCoordinates(portType).contains(secondNodeInt))) { ports[portType] = true; } else { ports[portType] = false; } sb.append(ports[portType] + " "); } log.debug(sb.toString()); log.debug("probTotal = " + probTotal); /** estimate the building speed for this pair */ estimate.recalculateEstimates(playerNumbers); int speed = 0; try { speed += estimate .calculateRollsFast(emptySet, SOCGame.SETTLEMENT_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsFast(emptySet, SOCGame.CITY_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsFast(emptySet, SOCGame.CARD_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsFast(emptySet, SOCGame.ROAD_SET, bestSpeed, ports) .getRolls(); } } } } catch (CutoffExceededException e) { speed = bestSpeed; } log.debug( Integer.toHexString(firstNode) + ", " + Integer.toHexString(secondNode) + ":" + speed); /** keep the settlements with the best speed */ if ((speed < bestSpeed) || (secondSettlement < 0)) { firstSettlement = firstNode; secondSettlement = secondNode; bestSpeed = speed; bestProbTotal = probTotal; log.debug("firstSettlement = " + Integer.toHexString(firstSettlement)); log.debug("secondSettlement = " + Integer.toHexString(secondSettlement)); int[] rolls = estimate.getEstimatesFromNothingFast(ports); sb = new StringBuffer(); sb.append("road: " + rolls[SOCBuildingSpeedEstimate.ROAD]); sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]); sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]); sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]); log.debug(sb.toString()); log.debug("bestSpeed = " + bestSpeed); } else if (speed == bestSpeed) { if (probTotal > bestProbTotal) { firstSettlement = firstNode; secondSettlement = secondNode; bestSpeed = speed; bestProbTotal = probTotal; log.debug("firstSettlement = " + Integer.toHexString(firstSettlement)); log.debug("secondSettlement = " + Integer.toHexString(secondSettlement)); int[] rolls = estimate.getEstimatesFromNothingFast(ports); sb = new StringBuffer(); sb.append("road: " + rolls[SOCBuildingSpeedEstimate.ROAD]); sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]); sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]); sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]); log.debug(sb.toString()); log.debug("bestSpeed = " + bestSpeed); } } } } return secondSettlement; }
/** * figure out where to place the second settlement * * @return {@link #secondSettlement}, or -1 if none */ public int planSecondSettlement() { log.debug("--- planSecondSettlement"); int bestSpeed = 4 * SOCBuildingSpeedEstimate.DEFAULT_ROLL_LIMIT; final SOCBoard board = game.getBoard(); SOCResourceSet emptySet = new SOCResourceSet(); SOCPlayerNumbers playerNumbers = new SOCPlayerNumbers(board); boolean[] ports = new boolean[SOCBoard.WOOD_PORT + 1]; SOCBuildingSpeedEstimate estimate = new SOCBuildingSpeedEstimate(); int probTotal; int bestProbTotal; final int[] prob = SOCNumberProbabilities.INT_VALUES; final int firstNode = firstSettlement; bestProbTotal = 0; secondSettlement = -1; final int[] ourPotentialSettlements = ourPlayerData.getPotentialSettlements_arr(); if (ourPotentialSettlements == null) return -1; // Should not occur for (int i = 0; i < ourPotentialSettlements.length; ++i) { final int secondNode = ourPotentialSettlements[i]; // assert: ourPlayerData.isPotentialSettlement(secondNode) if (board.isNodeAdjacentToNode(secondNode, firstNode)) continue; // <-- too close to firstNode to build -- /** get the numbers for these settlements */ StringBuffer sb = new StringBuffer(); sb.append("numbers: "); playerNumbers.clear(); probTotal = playerNumbers.updateNumbersAndProbability(firstNode, board, prob, sb); probTotal += playerNumbers.updateNumbersAndProbability(secondNode, board, prob, sb); /** see if the settlements are on any ports */ // sb.append("ports: "); Arrays.fill(ports, false); int portType = board.getPortTypeFromNodeCoord(firstNode); if (portType != -1) ports[portType] = true; portType = board.getPortTypeFromNodeCoord(secondNode); if (portType != -1) ports[portType] = true; // log.debug(sb.toString()); log.debug("probTotal = " + probTotal); /** estimate the building speed for this pair */ estimate.recalculateEstimates(playerNumbers); int speed = 0; try { speed += estimate .calculateRollsAndRsrcFast(emptySet, SOCGame.SETTLEMENT_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsAndRsrcFast(emptySet, SOCGame.CITY_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsAndRsrcFast(emptySet, SOCGame.CARD_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsAndRsrcFast(emptySet, SOCGame.ROAD_SET, bestSpeed, ports) .getRolls(); } } } // because of addition, speed might be as much as (bestSpeed - 1) + bestSpeed } catch (CutoffExceededException e) { speed = bestSpeed; } log.debug( Integer.toHexString(firstNode) + ", " + Integer.toHexString(secondNode) + ":" + speed); /** keep the settlements with the best speed */ if ((speed < bestSpeed) || (secondSettlement < 0)) { firstSettlement = firstNode; secondSettlement = secondNode; bestSpeed = speed; bestProbTotal = probTotal; log.debug("firstSettlement = " + Integer.toHexString(firstSettlement)); log.debug("secondSettlement = " + Integer.toHexString(secondSettlement)); int[] rolls = estimate.getEstimatesFromNothingFast(ports); sb = new StringBuffer(); sb.append("road: " + rolls[SOCBuildingSpeedEstimate.ROAD]); sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]); sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]); sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]); log.debug(sb.toString()); log.debug("bestSpeed = " + bestSpeed); } else if (speed == bestSpeed) { if (probTotal > bestProbTotal) { firstSettlement = firstNode; secondSettlement = secondNode; bestSpeed = speed; bestProbTotal = probTotal; log.debug("firstSettlement = " + Integer.toHexString(firstSettlement)); log.debug("secondSettlement = " + Integer.toHexString(secondSettlement)); int[] rolls = estimate.getEstimatesFromNothingFast(ports); sb = new StringBuffer(); sb.append("road: " + rolls[SOCBuildingSpeedEstimate.ROAD]); sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]); sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]); sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]); log.debug(sb.toString()); log.debug("bestSpeed = " + bestSpeed); } } } // for (i in ourPotentialSettlements[]) return secondSettlement; }
/** * figure out where to place the two settlements * * @return {@link #firstSettlement}, or 0 if no potential settlements for our player */ public int planInitialSettlements() { log.debug("--- planInitialSettlements"); int speed; boolean allTheWay; firstSettlement = 0; secondSettlement = 0; int bestSpeed = 4 * SOCBuildingSpeedEstimate.DEFAULT_ROLL_LIMIT; SOCBoard board = game.getBoard(); SOCResourceSet emptySet = new SOCResourceSet(); SOCPlayerNumbers playerNumbers = new SOCPlayerNumbers(board); int probTotal; int bestProbTotal; boolean[] ports = new boolean[SOCBoard.WOOD_PORT + 1]; SOCBuildingSpeedEstimate estimate = new SOCBuildingSpeedEstimate(); final int[] prob = SOCNumberProbabilities.INT_VALUES; bestProbTotal = 0; final int[] ourPotentialSettlements = ourPlayerData.getPotentialSettlements_arr(); if (ourPotentialSettlements == null) return 0; // Should not occur for (int i = 0; i < ourPotentialSettlements.length; ++i) { final int firstNode = ourPotentialSettlements[i]; // assert: ourPlayerData.isPotentialSettlement(firstNode) final Integer firstNodeInt = new Integer(firstNode); // // this is just for testing purposes // log.debug("FIRST NODE -----------"); log.debug("firstNode = " + board.nodeCoordToString(firstNode)); StringBuffer sb = new StringBuffer(); sb.append("numbers:["); playerNumbers.clear(); probTotal = playerNumbers.updateNumbersAndProbability(firstNode, board, prob, sb); sb.append("]"); log.debug(sb.toString()); sb = new StringBuffer(); sb.append("ports: "); for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) { ports[portType] = (board.getPortCoordinates(portType).contains(firstNodeInt)); sb.append(ports[portType] + " "); } log.debug(sb.toString()); log.debug("probTotal = " + probTotal); estimate.recalculateEstimates(playerNumbers); speed = 0; allTheWay = false; try { speed += estimate .calculateRollsAndRsrcFast(emptySet, SOCGame.SETTLEMENT_SET, 300, ports) .getRolls(); speed += estimate.calculateRollsAndRsrcFast(emptySet, SOCGame.CITY_SET, 300, ports).getRolls(); speed += estimate.calculateRollsAndRsrcFast(emptySet, SOCGame.CARD_SET, 300, ports).getRolls(); speed += estimate.calculateRollsAndRsrcFast(emptySet, SOCGame.ROAD_SET, 300, ports).getRolls(); } catch (CutoffExceededException e) { } if (D.ebugOn) { final int[] rolls = estimate.getEstimatesFromNothingFast(ports, 300); sb = new StringBuffer(); sb.append(" road: " + rolls[SOCBuildingSpeedEstimate.ROAD]); sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]); sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]); sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]); log.debug(sb.toString()); log.debug("speed = " + speed); } // // end test // // // calculate pairs of first and second settlement together // for (int j = 1 + i; j < ourPotentialSettlements.length; ++j) { final int secondNode = ourPotentialSettlements[j]; // assert: ourPlayerData.isPotentialSettlement(secondNode) if (board.isNodeAdjacentToNode(secondNode, firstNode)) continue; // <-- too close to firstNode to build -- log.debug("firstNode = " + board.nodeCoordToString(firstNode)); log.debug("secondNode = " + board.nodeCoordToString(secondNode)); /** get the numbers for these settlements */ sb = new StringBuffer(); sb.append("numbers:["); playerNumbers.clear(); probTotal = playerNumbers.updateNumbersAndProbability(firstNode, board, prob, sb); sb.append("] ["); probTotal += playerNumbers.updateNumbersAndProbability(secondNode, board, prob, sb); sb.append("]"); log.debug(sb.toString()); /** see if the settlements are on any ports */ // sb = new StringBuffer(); // sb.append("ports: "); Arrays.fill(ports, false); int portType = board.getPortTypeFromNodeCoord(firstNode); if (portType != -1) ports[portType] = true; portType = board.getPortTypeFromNodeCoord(secondNode); if (portType != -1) ports[portType] = true; // log.debug(sb.toString()); log.debug("probTotal = " + probTotal); /** estimate the building speed for this pair */ estimate.recalculateEstimates(playerNumbers); speed = 0; allTheWay = false; try { speed += estimate .calculateRollsAndRsrcFast(emptySet, SOCGame.SETTLEMENT_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsAndRsrcFast(emptySet, SOCGame.CITY_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsAndRsrcFast(emptySet, SOCGame.CARD_SET, bestSpeed, ports) .getRolls(); if (speed < bestSpeed) { speed += estimate .calculateRollsAndRsrcFast(emptySet, SOCGame.ROAD_SET, bestSpeed, ports) .getRolls(); allTheWay = true; } } } // because of addition, speed might be as much as (bestSpeed - 1) + bestSpeed } catch (CutoffExceededException e) { speed = bestSpeed; } if (D.ebugOn) { final int[] rolls = estimate.getEstimatesFromNothingFast(ports, bestSpeed); sb = new StringBuffer(); sb.append(" road: " + rolls[SOCBuildingSpeedEstimate.ROAD]); sb.append(" stlmt: " + rolls[SOCBuildingSpeedEstimate.SETTLEMENT]); sb.append(" city: " + rolls[SOCBuildingSpeedEstimate.CITY]); sb.append(" card: " + rolls[SOCBuildingSpeedEstimate.CARD]); log.debug(sb.toString()); log.debug("allTheWay = " + allTheWay); log.debug("speed = " + speed); } /** keep the settlements with the best speed */ if (speed < bestSpeed) { firstSettlement = firstNode; secondSettlement = secondNode; bestSpeed = speed; bestProbTotal = probTotal; log.debug("bestSpeed = " + bestSpeed); log.debug("bestProbTotal = " + bestProbTotal); } else if ((speed == bestSpeed) && allTheWay) { if (probTotal > bestProbTotal) { log.debug("Equal speed, better prob"); firstSettlement = firstNode; secondSettlement = secondNode; bestSpeed = speed; bestProbTotal = probTotal; log.debug("firstSettlement = " + Integer.toHexString(firstSettlement)); log.debug("secondSettlement = " + Integer.toHexString(secondSettlement)); log.debug("bestSpeed = " + bestSpeed); log.debug("bestProbTotal = " + bestProbTotal); } } } // for (j past i in ourPotentialSettlements[]) } // for (i in ourPotentialSettlements[]) /** choose which settlement to place first */ playerNumbers.clear(); playerNumbers.updateNumbers(firstSettlement, board); final Integer firstSettlementInt = new Integer(firstSettlement); for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) { ports[portType] = (board.getPortCoordinates(portType).contains(firstSettlementInt)); } estimate.recalculateEstimates(playerNumbers); int firstSpeed = 0; final int cutoff = 100; firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.SETTLEMENT_SET, cutoff, ports); firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CITY_SET, cutoff, ports); firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CARD_SET, cutoff, ports); firstSpeed += estimate.calculateRollsFast(emptySet, SOCGame.ROAD_SET, cutoff, ports); playerNumbers.clear(); playerNumbers.updateNumbers(secondSettlement, board); final Integer secondSettlementInt = new Integer(secondSettlement); for (int portType = SOCBoard.MISC_PORT; portType <= SOCBoard.WOOD_PORT; portType++) { ports[portType] = (board.getPortCoordinates(portType).contains(secondSettlementInt)); } estimate.recalculateEstimates(playerNumbers); int secondSpeed = 0; secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.SETTLEMENT_SET, bestSpeed, ports); secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CITY_SET, bestSpeed, ports); secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.CARD_SET, bestSpeed, ports); secondSpeed += estimate.calculateRollsFast(emptySet, SOCGame.ROAD_SET, bestSpeed, ports); if (firstSpeed > secondSpeed) { int tmp = firstSettlement; firstSettlement = secondSettlement; secondSettlement = tmp; } log.debug( board.nodeCoordToString(firstSettlement) + ":" + firstSpeed + ", " + board.nodeCoordToString(secondSettlement) + ":" + secondSpeed); return firstSettlement; }