```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 ``` ```import Data.Ratio import Numeric -- Standard combinatorics functions: factorial 0 = 1 factorial n = n * factorial (n - 1) choose n r = (factorial n) `div` (factorial r) `div` (factorial (n - r)) -- Probability of exactly r probability-p outcomes over n trials: exactly p n r | n >= r = (choose n r) % 1 * (p ^ r) * ((1 - p) ^ (n - r)) | otherwise = 0 -- Probability of exactly rp probability-p outcomes and rq probability-q outcomes over n trials, the outcomes being disjoint: exactly2 p q n rp rq = (exactly p n rp) * (exactly (q / (1 - p)) (n - rp) rq) -- Probability of more probability-p outcomes than probability-q outcomes over n trials, the outcomes being disjoint: more p q n = sum \$ map (uncurry \$ exactly2 p q n) \$ concatMap under [0 .. n] where under i = map ((,) i) [0 .. (i - 1)] -- Probability of fumbling under the old mechanic (rolling no successes and at least two 1s on d10s) with n dice and target t: old_fumble t n = (((t - 1) % 10) ^ n) * (sum \$ map (exactly (1 % (t - 1)) n) \$ [2 .. n]) -- Probability of succeeding under the old mechanic (roll at least one success on d10s) with n dice and target t: old_succeed t n = 1 - (((t - 1) % 10) ^ n) -- Probability of fumbling under the new mechanic (roll no "R"s and more "F"s than successes on d12s) with n dice and target t: new_fumble t n = ((11 % 12) ^ n) * (more (1 % 11) ((11 - t) % 11) n) -- Probability of succeeding under the new mechanic (roll an "R" or else more successes than "F"s on d12s) with n dice and target t: new_succeed t n = (1 - no_rs) + no_rs * (more ((11 - t) % 11) (1 % 11) n) where no_rs = ((11 % 12) ^ n) -- Table Ranges and Headings: targets = [5 .. 10] pool_sizes = [2 .. 10] row_headings = map format targets where format target = "Target " ++ (showInt target "") column_headings = map format pool_sizes where format pool_size = "Pool of " ++ (showInt pool_size "") -- Formatting: tabulate strings = (concatMap tab strings) ++ "\n" where tab string = string ++ "\t" prettify p = showFFloat (Just 4) (fromRational p) "\t" prettify_row heading row = tabulate \$ [heading] ++ map prettify row prettify_grid row_headings column_headings grid = (tabulate column_headings) ++ (concatMap (uncurry prettify_row) \$ zip row_headings grid) prettify_results title function = prettify_grid row_headings ([title] ++ column_headings) \$ map f targets where f target = map (function target) pool_sizes main = do putStrLn \$ prettify_results "Fumble (Old)" old_fumble putStrLn \$ prettify_results "Fumble (New)" new_fumble putStrLn \$ prettify_results "Succeed (Old)" old_succeed putStrLn \$ prettify_results "Succeed (New)" new_succeed ```
 ```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ``` ```Fumble (Old) Pool of 2 Pool of 3 Pool of 4 Pool of 5 Pool of 6 Pool of 7 Pool of 8 Pool of 9 Pool of 10 Target 5 0.0100 0.0100 0.0067 0.0038 0.0019 0.0009 0.0004 0.0002 0.0001 Target 6 0.0100 0.0130 0.0113 0.0082 0.0054 0.0033 0.0019 0.0011 0.0006 Target 7 0.0100 0.0160 0.0171 0.0153 0.0123 0.0092 0.0066 0.0046 0.0031 Target 8 0.0100 0.0190 0.0241 0.0255 0.0243 0.0217 0.0185 0.0152 0.0121 Target 9 0.0100 0.0220 0.0323 0.0396 0.0437 0.0450 0.0442 0.0420 0.0388 Target 10 0.0100 0.0250 0.0417 0.0580 0.0727 0.0851 0.0949 0.1022 0.1071 Fumble (New) Pool of 2 Pool of 3 Pool of 4 Pool of 5 Pool of 6 Pool of 7 Pool of 8 Pool of 9 Pool of 10 Target 5 0.0625 0.0457 0.0328 0.0235 0.0168 0.0121 0.0087 0.0062 0.0045 Target 6 0.0764 0.0613 0.0478 0.0369 0.0284 0.0218 0.0168 0.0129 0.0099 Target 7 0.0903 0.0804 0.0679 0.0563 0.0463 0.0379 0.0310 0.0253 0.0207 Target 8 0.1042 0.1030 0.0945 0.0840 0.0735 0.0639 0.0553 0.0478 0.0412 Target 9 0.1181 0.1291 0.1285 0.1225 0.1142 0.1050 0.0957 0.0869 0.0785 Target 10 0.1319 0.1586 0.1712 0.1751 0.1735 0.1684 0.1613 0.1531 0.1444 Succeed (Old) Pool of 2 Pool of 3 Pool of 4 Pool of 5 Pool of 6 Pool of 7 Pool of 8 Pool of 9 Pool of 10 Target 5 0.8400 0.9360 0.9744 0.9898 0.9959 0.9984 0.9993 0.9997 0.9999 Target 6 0.7500 0.8750 0.9375 0.9688 0.9844 0.9922 0.9961 0.9980 0.9990 Target 7 0.6400 0.7840 0.8704 0.9222 0.9533 0.9720 0.9832 0.9899 0.9940 Target 8 0.5100 0.6570 0.7599 0.8319 0.8824 0.9176 0.9424 0.9596 0.9718 Target 9 0.3600 0.4880 0.5904 0.6723 0.7379 0.7903 0.8322 0.8658 0.8926 Target 10 0.1900 0.2710 0.3439 0.4095 0.4686 0.5217 0.5695 0.6126 0.6513 Succeed (New) Pool of 2 Pool of 3 Pool of 4 Pool of 5 Pool of 6 Pool of 7 Pool of 8 Pool of 9 Pool of 10 Target 5 0.7431 0.8339 0.8888 0.9241 0.9476 0.9634 0.9743 0.9818 0.9871 Target 6 0.6806 0.7795 0.8425 0.8853 0.9153 0.9370 0.9527 0.9644 0.9730 Target 7 0.6042 0.7112 0.7816 0.8314 0.8682 0.8961 0.9175 0.9342 0.9472 Target 8 0.5139 0.6256 0.7021 0.7582 0.8012 0.8352 0.8624 0.8847 0.9029 Target 9 0.4097 0.5191 0.5987 0.6596 0.7080 0.7474 0.7803 0.8080 0.8317 Target 10 0.2917 0.3883 0.4652 0.5279 0.5802 0.6246 0.6628 0.6961 0.7255 ```