aboutsummaryrefslogtreecommitdiff
path: root/calculette_aoo/lib/roll.ml
diff options
context:
space:
mode:
authorSébastien Dailly <sebastien@dailly.me>2024-03-04 21:07:51 +0100
committerSébastien Dailly <sebastien@dailly.me>2024-03-04 21:07:51 +0100
commitfe13ea5ce39b24b2d49b43c384ed01b013d683db (patch)
tree92b4a01e97c22318b376c2b576ca783af4a9db9e /calculette_aoo/lib/roll.ml
parentef9beb0814c36cda979a4ed7e9175e72e69540ac (diff)
calculette_aoo: now evaluate the exact frequency, some corrections
Diffstat (limited to 'calculette_aoo/lib/roll.ml')
-rw-r--r--calculette_aoo/lib/roll.ml81
1 files changed, 81 insertions, 0 deletions
diff --git a/calculette_aoo/lib/roll.ml b/calculette_aoo/lib/roll.ml
new file mode 100644
index 0000000..00d8465
--- /dev/null
+++ b/calculette_aoo/lib/roll.ml
@@ -0,0 +1,81 @@
+open StdLabels
+
+(** Evaluate the coefficient for the product of two polynamials *)
+let mul p1 p2 =
+ let n1 = Array.length p1 and n2 = Array.length p2 in
+ let n = n1 + n2 in
+ let res = Array.make n 0 in
+ for i = 0 to n1 - 1 do
+ for j = 0 to n2 - 1 do
+ res.(i + j + 1) <- res.(i + j + 1) + (p1.(i) * p2.(j))
+ done
+ done;
+ res
+
+(** Apply a power function over a polynomial *)
+let pow p1 n =
+ let result = ref p1 in
+ for _ = 1 to n - 1 do
+ result := mul !result p1
+ done;
+ !result
+
+(** Evaluate the odd to win agains a give difficulty *)
+let against : int -> int array -> Q.t array =
+ fun n difficulties ->
+ match n with
+ | 0 -> Array.map ~f:(fun _ -> Q.zero) difficulties
+ | _ ->
+ (* Create the polynomial with the odd ratio for the given caracteristic *)
+ let arr = Array.make 3 1 in
+ let frequencies = pow arr n in
+ let ratio = Z.(of_int 3 ** n) in
+
+ let get_chances difficulty =
+ (* Evaluate the ratio to win the roll *)
+ let chances = ref Z.zero in
+ for i = difficulty - 1 to Array.length frequencies - 1 do
+ (* The index in the table is the odd to get exactly this value in the roll.
+ Here, we just add every value in the array from the index strarting from
+ the given difficulty. *)
+ chances := Z.(!chances + of_int frequencies.(i))
+ done;
+ Q.make !chances ratio
+ in
+ Array.map ~f:get_chances difficulties
+
+(** Compare two caracteristics.
+ [compare v1 v2] will evaluate the odds to win if the player has the
+ caracteristics [v1] against the openent [v2].
+
+ In case of equality, the win is given to [v1] *)
+let compare : int -> int -> Q.t =
+ fun carac1 carac2 ->
+ let arr = Array.make 3 1 in
+ let z3 = Z.of_int 3 in
+
+ let ordinal1 = Z.(z3 ** carac1)
+ and ordinal2 = Z.(z3 ** carac2)
+ (*Number of possibles values for each caracteristc *)
+ and elements1 = 3 * carac1
+ and elements2 = 3 * carac2 in
+
+ (* The number of iterations to do is elements1 × elements2. For every iteration of elements2, we have ordinal1 points to get. *)
+ let cases = Z.(ordinal1 * ordinal2) in
+
+ let frequencies_1 = pow arr carac1 |> Array.map ~f:(fun v -> Z.(of_int v))
+ and frequencies_2 = pow arr carac2 |> Array.map ~f:(fun v -> Z.(of_int v)) in
+
+ (* Now, compare for each values the probabily to win *)
+ let res = ref Z.zero in
+ let () =
+ for i = 0 to elements1 - 1 do
+ for j = 0 to elements2 - 1 do
+ if i >= j then
+ (* Number of times this combinaison is occuring *)
+ let freq = Z.(frequencies_1.(i) * frequencies_2.(j)) in
+ Z.(res := !res + freq)
+ done
+ done
+ in
+ Q.make !res cases