Обсуждение:貓貓鬼差
Версия от 22:39, 25 октября 2024; Demetrius (обсуждение | вклад) (Новая страница: «== Подсчёт таблицы вероятностей == Вот мой алгоритм для подсчёта таблицы вероятностей. Он…»)
Подсчёт таблицы вероятностей
Вот мой алгоритм для подсчёта таблицы вероятностей. Он работает через перебор грубой силы, поэтому может работать медленно — впрочем, вряд ли кто-то будет запускать его часто.
function addD6Roll(rollOutcomes) { return [1, 2, 3, 4, 5, 6].map(d6Value => rollOutcomes.map(outcomes => [...outcomes, d6Value])).flat() } var allPossibleRolls = addD6Roll(addD6Roll(addD6Roll([[1], [2], [3], [4], [5], [6]]))) // возвращает либо false, либо массив с двумя другими бросками (дубль убирает) // если выпало два дубля, возвращает больший (меньший убирает) function isDouble(rolls) { const doubledNumbers = rolls.filter( (number, index) => rolls.findIndex( (otherNumber, otherIndex) => otherIndex > index && otherNumber === number ) > -1 ) if (doubledNumbers.length < 1) return false doubledNumbers.sort() const [ doubledNumber ] = doubledNumbers let numRemoved = 0 otherRolls = rolls.filter((item) => { if (item !== doubledNumber || numRemoved >= 2) { return true; } numRemoved++; return false }) return otherRolls } function determineOutcome(rollResult, requiredDifficulty) { const doubleResult = isDouble(rollResult) if (!doubleResult) return 'fail'; const sum = doubleResult.reduce((r, x) => r+x, 0); if (sum === 3) return 'dramaticFail'; return sum >= requiredDifficulty ? 'success' : 'fail'; } function doesAddingPlusOneGiveSucceess(rolls, requiredDifficulty) { for (i = 0; i < rolls.length; i++) { if (rolls[i] >= 6) continue; const changedRolls = [...rolls]; changedRolls[i]++ const outcome = determineOutcome(changedRolls, requiredDifficulty) if (outcome === 'success') return true } return false } function calculateResultChances(rolls, requiredDifficulty) { const numOutcomes = { success: 0, fail: 0, dramaticFail: 0, successWithRerolls: 0 }; const percentages = {} rolls.forEach((roll, index) => { const outcome = determineOutcome(roll, requiredDifficulty) numOutcomes[outcome]++; if (outcome === 'success' || doesAddingPlusOneGiveSucceess(roll, requiredDifficulty)) { numOutcomes.successWithRerolls++; } }) Object.entries(numOutcomes).forEach(([type, count]) => { percentages[type] = count / rolls.length; }) return percentages; } function formatPercentage(n) { return (Math.round(n * 10000) / 100) + '%' } function percentagesForDifficulties(requiredDifficulty) { const { success, fail, dramaticFail, successWithRerolls } = calculateResultChances(allPossibleRolls, requiredDifficulty); const cells = [ requiredDifficulty, formatPercentage(success), formatPercentage(successWithRerolls), formatPercentage(fail), formatPercentage(dramaticFail), ] return '| ' + cells.join(' || ') } function range(fromVal, toVal) { const result = [] for (i = fromVal; i <= toVal; i++) { result.push(i) } return result } const tableData = range(1, 13).map(i => percentagesForDifficulties(i)).join('\n|-\n'); const result = `{| class="wikitable" style="margin:auto" ! rowspan="2" | Сложность (минус бонус) !! colspan="2" | Шанс успеха !! colspan="2" | Шанс неудачи |- ! Обычный успех !! С прибавлением +1 !! Обычная неудача !! Драматический провал |- ${tableData} |} ` console.log(result)