Source:
private boolean checkEndOfBranch(final StepUnits units) { checkEndOfBattle(units); if (hasResult) { averageUnits = units; averageUnits.recordChances(); averageRounds = round + 1; return true; } final BattleStep cachedBattleStep = nodeCache.get(units); if (cachedBattleStep != null) { if (cachedBattleStep.hasResult) { this.winProbability = cachedBattleStep.winProbability; this.loseProbability = cachedBattleStep.loseProbability; this.tieProbability = cachedBattleStep.tieProbability; this.badProbability = cachedBattleStep.badProbability; this.averageUnits = cachedBattleStep.averageUnits; this.averageRounds = round + 1; } else { final double[] siblingResults = new double[5]; siblingResults[0] = cachedBattleStep.winProbability; siblingResults[1] = cachedBattleStep.loseProbability; siblingResults[2] = cachedBattleStep.tieProbability; siblingResults[3] = cachedBattleStep.averageRounds; siblingResults[4] = 1.0; final StepUnits siblingUnits = cachedBattleStep.averageUnits.swapSides(); calculateSiblingResultsForRecursiveEnd( cachedBattleStep.children, siblingResults, siblingUnits); this.averageUnits = units; for (int level = 0; level < 6; level++) { this.winProbability += siblingResults[0] * Math.pow(siblingResults[4], level); this.loseProbability += siblingResults[1] * Math.pow(siblingResults[4], level); this.tieProbability += siblingResults[2] * Math.pow(siblingResults[4], level); this.averageRounds += siblingResults[3] * Math.pow(siblingResults[4], level); this.averageUnits.updateUnitChances(siblingUnits, Math.pow(siblingResults[4], level)); } this.badProbability = 1.0 - (this.winProbability + this.loseProbability + this.tieProbability); nodeCache.put(units, this); } this.hasResult = true; return true; } if (round >= MAX_ROUNDS) { System.out.println("Reached max rounds"); hasResult = true; badProbability = 1.0; return true; } nodeCache.put(units, this); return false; }

Target:
private boolean checkEndOfBranch(final StepUnits units) { checkEndOfBattle(units); if (hasResult) { averageUnits = units; averageUnits.recordChances(); averageRounds = round + 1; return true; } final BattleStep cachedBattleStep = nodeCache.get(units); if (cachedBattleStep != null) { if (cachedBattleStep.hasResult) { this.winProbability = cachedBattleStep.winProbability; this.loseProbability = cachedBattleStep.loseProbability; this.tieProbability = cachedBattleStep.tieProbability; this.badProbability = cachedBattleStep.badProbability; this.averageUnits = cachedBattleStep.averageUnits; this.averageRounds = round + 1; } else { this.averageUnits = units; final BattleStepSiblings siblingResults = new BattleStepSiblings(); siblingResults.probability = 1.0; siblingResults.winProbability = cachedBattleStep.winProbability; siblingResults.loseProbability = cachedBattleStep.loseProbability; siblingResults.tieProbability = cachedBattleStep.tieProbability; siblingResults.averageRounds = cachedBattleStep.averageRounds; siblingResults.units = cachedBattleStep.averageUnits.swapSides(); calculateSiblingResultsForRecursiveEnd(cachedBattleStep.children, siblingResults); final double gap = 1.0 - siblingResults.probability; this.winProbability = siblingResults.winProbability / gap; this.loseProbability = siblingResults.loseProbability / gap; this.tieProbability = siblingResults.tieProbability / gap; this.averageRounds = siblingResults.averageRounds / gap; this.averageUnits.updateWithChildUnitChances(siblingResults.units, 1.0 / gap); nodeCache.put(units, this); } this.hasResult = true; return true; } if (round >= MAX_ROUNDS) { System.out.println("Reached max rounds"); hasResult = true; badProbability = 1.0; return true; } nodeCache.put(units, this); return false; }