/** * this figures out how many rolls it would take this player to get the target set of resources * given a starting set * * @param startingResources the starting resources * @param targetResources the target resources * @param cutoff throw an exception if the total speed is greater than this * @param ports a list of port flags * @return the number of rolls and our resources when the target is reached. If {@link * SOCResourceSet#contains(SOCResourceSet) startingResources.contains(targetResources)}, * returns 0 rolls and a {@code null} resource set. * @throws CutoffExceededException if estimate more than {@code cutoff} turns to obtain {@code * targetResources} */ protected SOCResSetBuildTimePair calculateRollsAccurate( SOCResourceSet startingResources, SOCResourceSet targetResources, int cutoff, boolean[] ports) throws CutoffExceededException { D.ebugPrintln("calculateRollsAccurate"); D.ebugPrintln(" start: " + startingResources); D.ebugPrintln(" target: " + targetResources); SOCResourceSet ourResources = startingResources.copy(); int rolls = 0; @SuppressWarnings("unchecked") Hashtable<SOCResourceSet, Float>[] resourcesOnRoll = new Hashtable[2]; resourcesOnRoll[0] = new Hashtable<SOCResourceSet, Float>(); resourcesOnRoll[1] = new Hashtable<SOCResourceSet, Float>(); int lastRoll = 0; int thisRoll = 1; resourcesOnRoll[lastRoll].put(ourResources, new Float(1.0)); boolean targetReached = ourResources.contains(targetResources); SOCResourceSet targetReachedResources = null; float targetReachedProb = (float) 0.0; while (!targetReached) { if (D.ebugOn) { D.ebugPrintln("roll: " + rolls); D.ebugPrintln("resourcesOnRoll[lastRoll]:"); Enumeration<SOCResourceSet> roltEnum = resourcesOnRoll[lastRoll].keys(); while (roltEnum.hasMoreElements()) { SOCResourceSet rs = roltEnum.nextElement(); Float prob = resourcesOnRoll[lastRoll].get(rs); D.ebugPrintln("---- prob:" + prob); D.ebugPrintln("---- rsrcs:" + rs); D.ebugPrintln(); } D.ebugPrintln("targetReachedProb: " + targetReachedProb); D.ebugPrintln("==================================="); } rolls++; if (rolls > cutoff) { D.ebugPrintln( "startingResources=" + startingResources + "\ntargetResources=" + targetResources + "\ncutoff=" + cutoff + "\nourResources=" + ourResources); throw new CutoffExceededException(); } // // get our resources for the roll // for (int diceResult = 2; diceResult <= 12; diceResult++) { SOCResourceSet gainedResources = resourcesForRoll[diceResult]; float diceProb = SOCNumberProbabilities.FLOAT_VALUES[diceResult]; // // add the resources that we get on this roll to // each set of resources that we got on the last // roll and multiply the probabilities // Enumeration<SOCResourceSet> lastResourcesEnum = resourcesOnRoll[lastRoll].keys(); while (lastResourcesEnum.hasMoreElements()) { SOCResourceSet lastResources = lastResourcesEnum.nextElement(); Float lastProb = resourcesOnRoll[lastRoll].get(lastResources); SOCResourceSet newResources = lastResources.copy(); newResources.add(gainedResources); float newProb = lastProb.floatValue() * diceProb; if (!newResources.contains(targetResources)) { // // do any possible trading with the bank/ports // for (int giveResource = SOCResourceConstants.CLAY; giveResource <= SOCResourceConstants.WOOD; giveResource++) { if ((newResources.getAmount(giveResource) - targetResources.getAmount(giveResource)) > 1) { // // find the ratio at which we can trade // int tradeRatio; if (ports[giveResource]) { tradeRatio = 2; } else if (ports[SOCBoard.MISC_PORT]) { tradeRatio = 3; } else { tradeRatio = 4; } // // get the target resources // int numTrades = (newResources.getAmount(giveResource) - targetResources.getAmount(giveResource)) / tradeRatio; // D.ebugPrintln("))) ***"); // D.ebugPrintln("))) giveResource="+giveResource); // D.ebugPrintln("))) tradeRatio="+tradeRatio); // D.ebugPrintln("))) newResources="+newResources); // D.ebugPrintln("))) targetResources="+targetResources); // D.ebugPrintln("))) numTrades="+numTrades); for (int trades = 0; trades < numTrades; trades++) { // // find the most needed resource by looking at // which of the resources we still need takes the // longest to aquire // int mostNeededResource = -1; for (int resource = SOCResourceConstants.CLAY; resource <= SOCResourceConstants.WOOD; resource++) { if (newResources.getAmount(resource) < targetResources.getAmount(resource)) { if (mostNeededResource < 0) { mostNeededResource = resource; } else { if (rollsPerResource[resource] > rollsPerResource[mostNeededResource]) { mostNeededResource = resource; } } } } // // make the trade // // D.ebugPrintln("))) want to trade "+tradeRatio+" "+giveResource+" for a // "+mostNeededResource); if ((mostNeededResource != -1) && (newResources.getAmount(giveResource) >= tradeRatio)) { // D.ebugPrintln("))) trading..."); newResources.add(1, mostNeededResource); if (newResources.getAmount(giveResource) < tradeRatio) { System.err.println("@@@ rsrcs=" + newResources); System.err.println("@@@ tradeRatio=" + tradeRatio); System.err.println("@@@ giveResource=" + giveResource); System.err.println("@@@ target=" + targetResources); } newResources.subtract(tradeRatio, giveResource); // D.ebugPrintln("))) newResources="+newResources); } if (newResources.contains(targetResources)) { break; } } if (newResources.contains(targetResources)) { break; } } } } // // if this set of resources is already in the list // of possible outcomes, add this probability to // that one, else just add this to the list // Float probFloat = resourcesOnRoll[thisRoll].get(newResources); float newProb2 = newProb; if (probFloat != null) { newProb2 = probFloat.floatValue() + newProb; } // // check to see if we reached our target // if (newResources.contains(targetResources)) { D.ebugPrintln("-----> TARGET HIT *"); D.ebugPrintln("newResources: " + newResources); D.ebugPrintln("newProb: " + newProb); targetReachedProb += newProb; if (targetReachedResources == null) { targetReachedResources = newResources; } if (targetReachedProb >= 0.5) { targetReached = true; } } else { resourcesOnRoll[thisRoll].put(newResources, new Float(newProb2)); } } } // // copy the resourcesOnRoll[thisRoll] table to the // resourcesOnRoll[lastRoll] table and clear the // resourcesOnRoll[thisRoll] table // int tmp = lastRoll; lastRoll = thisRoll; thisRoll = tmp; resourcesOnRoll[thisRoll].clear(); } if (D.ebugOn) { float probSum = (float) 0.0; D.ebugPrintln("**************** TARGET REACHED ************"); D.ebugPrintln("targetReachedResources: " + targetReachedResources); D.ebugPrintln("targetReachedProb: " + targetReachedProb); D.ebugPrintln("roll: " + rolls); D.ebugPrintln("resourcesOnRoll[lastRoll]:"); Enumeration<SOCResourceSet> roltEnum = resourcesOnRoll[lastRoll].keys(); while (roltEnum.hasMoreElements()) { SOCResourceSet rs = roltEnum.nextElement(); Float prob = resourcesOnRoll[lastRoll].get(rs); probSum += prob.floatValue(); D.ebugPrintln("---- prob:" + prob); D.ebugPrintln("---- rsrcs:" + rs); D.ebugPrintln(); } D.ebugPrintln("probSum = " + probSum); D.ebugPrintln("==================================="); } return (new SOCResSetBuildTimePair(targetReachedResources, rolls)); }
/** * this figures out how many rolls it would take this player to get the target set of resources * given a starting set * * <p>Before v2.0.00, this was {@code calculateRollsFast}. * * @param startingResources the starting resources * @param targetResources the target resources * @param cutoff throw an exception if the total speed is greater than this * @param ports a list of port flags * @return the number of rolls, and startingResources after any trading. If {@link * SOCResourceSet#contains(SOCResourceSet) startingResources.contains(targetResources)}, * returns 0 rolls and a copy of {@code startingResources} with identical amounts. * @throws CutoffExceededException if total number of rolls > {@code cutoff} * @see #calculateRollsFast(SOCResourceSet, SOCResourceSet, int, boolean[]) */ protected SOCResSetBuildTimePair calculateRollsAndRsrcFast( final SOCResourceSet startingResources, final SOCResourceSet targetResources, final int cutoff, final boolean[] ports) throws CutoffExceededException { // D.ebugPrintln("calculateRolls"); // D.ebugPrintln(" start: "+startingResources); // D.ebugPrintln(" target: "+targetResources); SOCResourceSet ourResources = startingResources.copy(); int rolls = 0; if (!ourResources.contains(targetResources)) { /** do any possible trading with the bank/ports */ for (int giveResource = SOCResourceConstants.CLAY; giveResource <= SOCResourceConstants.WOOD; giveResource++) { /** find the ratio at which we can trade */ int tradeRatio; if (ports[giveResource]) { tradeRatio = 2; } else if (ports[SOCBoard.MISC_PORT]) { tradeRatio = 3; } else { tradeRatio = 4; } /** get the target resources */ int numTrades = (ourResources.getAmount(giveResource) - targetResources.getAmount(giveResource)) / tradeRatio; // D.ebugPrintln("))) ***"); // D.ebugPrintln("))) giveResource="+giveResource); // D.ebugPrintln("))) tradeRatio="+tradeRatio); // D.ebugPrintln("))) ourResources="+ourResources); // D.ebugPrintln("))) targetResources="+targetResources); // D.ebugPrintln("))) numTrades="+numTrades); for (int trades = 0; trades < numTrades; trades++) { /** * find the most needed resource by looking at which of the resources we still need takes * the longest to aquire */ int mostNeededResource = -1; for (int resource = SOCResourceConstants.CLAY; resource <= SOCResourceConstants.WOOD; resource++) { if (ourResources.getAmount(resource) < targetResources.getAmount(resource)) { if (mostNeededResource < 0) { mostNeededResource = resource; } else { if (rollsPerResource[resource] > rollsPerResource[mostNeededResource]) { mostNeededResource = resource; } } } } /** make the trade */ // D.ebugPrintln("))) want to trade "+tradeRatio+" "+giveResource+" for a // "+mostNeededResource); if ((mostNeededResource != -1) && (ourResources.getAmount(giveResource) >= tradeRatio)) { // D.ebugPrintln("))) trading..."); ourResources.add(1, mostNeededResource); if (ourResources.getAmount(giveResource) < tradeRatio) { System.err.println("@@@ rsrcs=" + ourResources); System.err.println("@@@ tradeRatio=" + tradeRatio); System.err.println("@@@ giveResource=" + giveResource); System.err.println("@@@ target=" + targetResources); } ourResources.subtract(tradeRatio, giveResource); // D.ebugPrintln("))) ourResources="+ourResources); } if (ourResources.contains(targetResources)) { break; } } if (ourResources.contains(targetResources)) { break; } } } while (!ourResources.contains(targetResources)) { // D.ebugPrintln("roll: "+rolls); // D.ebugPrintln("resources: "+ourResources); rolls++; if (rolls > cutoff) { // D.ebugPrintln("startingResources="+startingResources+"\ntargetResources="+targetResources+"\ncutoff="+cutoff+"\nourResources="+ourResources); throw new CutoffExceededException(); } for (int resource = SOCResourceConstants.CLAY; resource <= SOCResourceConstants.WOOD; resource++) { // D.ebugPrintln("resource: "+resource); // D.ebugPrintln("rollsPerResource: "+rollsPerResource[resource]); /** get our resources for the roll */ if ((rollsPerResource[resource] == 0) || ((rolls % rollsPerResource[resource]) == 0)) { ourResources.add(1, resource); } } if (!ourResources.contains(targetResources)) { /** do any possible trading with the bank/ports */ for (int giveResource = SOCResourceConstants.CLAY; giveResource <= SOCResourceConstants.WOOD; giveResource++) { /** find the ratio at which we can trade */ int tradeRatio; if (ports[giveResource]) { tradeRatio = 2; } else if (ports[SOCBoard.MISC_PORT]) { tradeRatio = 3; } else { tradeRatio = 4; } /** get the target resources */ int numTrades = (ourResources.getAmount(giveResource) - targetResources.getAmount(giveResource)) / tradeRatio; // D.ebugPrintln("))) ***"); // D.ebugPrintln("))) giveResource="+giveResource); // D.ebugPrintln("))) tradeRatio="+tradeRatio); // D.ebugPrintln("))) ourResources="+ourResources); // D.ebugPrintln("))) targetResources="+targetResources); // D.ebugPrintln("))) numTrades="+numTrades); for (int trades = 0; trades < numTrades; trades++) { /** * find the most needed resource by looking at which of the resources we still need * takes the longest to aquire */ int mostNeededResource = -1; for (int resource = SOCResourceConstants.CLAY; resource <= SOCResourceConstants.WOOD; resource++) { if (ourResources.getAmount(resource) < targetResources.getAmount(resource)) { if (mostNeededResource < 0) { mostNeededResource = resource; } else { if (rollsPerResource[resource] > rollsPerResource[mostNeededResource]) { mostNeededResource = resource; } } } } /** make the trade */ // D.ebugPrintln("))) want to trade "+tradeRatio+" "+giveResource+" for a // "+mostNeededResource); if ((mostNeededResource != -1) && (ourResources.getAmount(giveResource) >= tradeRatio)) { // D.ebugPrintln("))) trading..."); ourResources.add(1, mostNeededResource); if (ourResources.getAmount(giveResource) < tradeRatio) { System.err.println("@@@ rsrcs=" + ourResources); System.err.println("@@@ tradeRatio=" + tradeRatio); System.err.println("@@@ giveResource=" + giveResource); System.err.println("@@@ target=" + targetResources); } ourResources.subtract(tradeRatio, giveResource); // D.ebugPrintln("))) ourResources="+ourResources); } if (ourResources.contains(targetResources)) { break; } } if (ourResources.contains(targetResources)) { break; } } } } return (new SOCResSetBuildTimePair(ourResources, rolls)); }