aboutsummaryrefslogtreecommitdiff
path: root/calculette_aoo/lib/roll.ml
blob: 00d84655a157c4c8667fe41e5acdefc40da839a8 (plain)
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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