#lang scheme
(require "common.ss")
(define d20
(make-dice 20 #f))
(provide d20)
(define (simulate-test/attribute attribute [generator (current-pseudo-random-generator)])
(let ([result (d20 generator)])
(make-test-result (<= result (max 1 (min attribute 19)))
(case result
[(1 20)
#t]
[else
#f])
result)))
(define (analyze-test/attribute attribute)
(make-test-statistics (* 1/20 (max 1 (min attribute 19)))
2/20
21/2))
(provide/contract [simulate-test/attribute (->* (exact-integer?)
(pseudo-random-generator?)
test-result?)]
[analyze-test/attribute (-> exact-integer?
test-statistics?)])
(define (simulate-test/talent attribute-0 attribute-1 attribute-2 talent [generator (current-pseudo-random-generator)])
(let* ([result-0 (simulate-test/attribute (+ attribute-0 talent))]
[result-1 (simulate-test/attribute (+ attribute-1 talent))]
[result-2 (simulate-test/attribute (+ attribute-2 talent))]
[remaining-talent (- talent
(max (- (test-result-value result-0) attribute-0) 0)
(max (- (test-result-value result-1) attribute-1) 0)
(max (- (test-result-value result-2) attribute-2) 0))])
(make-test-result (and (test-result-successful? result-0)
(test-result-successful? result-1)
(test-result-successful? result-2)
(or (<= talent 0)
(>= remaining-talent 0)))
(and (test-result-critical? result-0)
(test-result-critical? result-1)
(test-result-critical? result-2))
remaining-talent)))
(define (analyze-test/talent attribute-0 attribute-1 attribute-2 talent)
(let-values ([(probability expectation) (for*/fold ([success 0] [expectation 0]) ([result-0 (in-range 1 21)]
[result-1 (in-range 1 21)]
[result-2 (in-range 1 21)])
(let ([remaining-talent (- talent
(max (- result-0 attribute-0) 0)
(max (- result-1 attribute-1) 0)
(max (- result-2 attribute-2) 0))])
(values (if (and (<= result-0 (max 1 (min (+ attribute-0 talent) 19)))
(<= result-1 (max 1 (min (+ attribute-1 talent) 19)))
(<= result-2 (max 1 (min (+ attribute-2 talent) 19)))
(or (<= talent 0)
(>= remaining-talent 0)))
(+ success 1/8000)
success)
(+ expectation (* 1/8000 remaining-talent)))))])
(make-test-statistics probability 2/8000 expectation)))
(provide/contract [simulate-test/talent (->* (exact-integer? exact-integer? exact-integer?
exact-integer?)
(pseudo-random-generator?)
test-result?)]
[analyze-test/talent (-> exact-integer? exact-integer? exact-integer?
exact-integer?
test-statistics?)])