1 // Copyright 2010 Bill Burdick. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // dice is a program that uses seq to calculate some probabilities for a game:
6 // each player rolls 3 dice, each of which can have 4, 6, 8, or 10 sides
7 // then, they compare the maximum numbers. The one with the highest number wins
8 // this program calculates probabilities of winning by a certain margin (which can be from 1 - 9)
14 import "container/vector"
16 import . "github.com/zot/bills-tools/seq"
19 func add(i
int, s Seq
) Seq
{
20 return s
.Map(func(el El
)El
{
25 func max(a
, b
int) int {
33 d4
:= add(1, AUpto(4))
34 d6
:= add(1, AUpto(6))
35 d8
:= add(1, AUpto(8))
36 d10
:= add(1, AUpto(10))
37 names
:= map[interface{}]string{d4
:"d4", d6
:"d6", d8
:"d8", d10
:"d10"}
38 dice
:= From(d4
, d6
, d8
, d10
)
39 rank
:= map[Seq
]int{d4
:0, d6
:1, d8
:2, d10
:3}
40 sets
:= map[string]int{}
41 //attempts is [[label, [score, ...]]...]
42 attempts
:= Map(Filter(Product(From(dice
, dice
, dice
)), func(d El
)bool{
45 Do(d
.(Seq
), func(set El
){
46 newRank
:= rank
[set
.(Seq
)]
47 result
= result
&& newRank
>= oldRank
52 buf
:= bytes
.NewBuffer(make([]byte, 0, 10))
53 io
.WriteString(buf
, "<")
54 Pretty(el
.(Seq
), names
, buf
)
55 io
.WriteString(buf
, ">")
56 return From(buf
.String(), Map(Product(el
.(Seq
)), func(el El
)El
{
57 return Fold(el
.(Seq
), 0, func(acc
, el El
)El
{return max(acc
.(int), el
.(int))})
61 println("#sets:", len(sets
))
62 fmt
.Println("#Attempts:", Len(attempts
))
64 Do(attempts
, func(el El
){
65 label
, rolls
:= First2(el
.(Seq
))
66 fmt
.Printf("%s: %d\n", label
, Len(rolls
.(Seq
)))
68 Do(CFlatMap(attempts
, func(el El
) Seq
{
69 label
, sc
:= First2(el
.(Seq
))
70 return CMap(attempts
, func(del El
) El
{
72 margins
:= map[int]int{}
73 dlabel
, dsc
:= First2(del
.(Seq
))
74 Do(Product(From(sc
,dsc
)), func(rel El
){
76 attack
, defense
:= First2(rel
.(Seq
))
77 margin
:= attack
.(int) - defense
.(int)
84 return From(label
, dlabel
, rolls
, wins
, margins
)
87 l
, d
, r
, w
, m
:= First5(el
.(Seq
))
88 printResult(l
.(string), d
.(string), r
.(int), w
.(int), m
.(map[int]int))
92 func printResult(label
string, dlabel
string, rolls
int, wins
int, margins
map[int]int) {
93 fmt
.Printf("%s vs %s rolls: %d wins: %d margins:", label
, dlabel
, rolls
, wins
)
94 for i
:= 1; i
<= 9; i
++ {
97 fmt
.Printf(" %d %.2f", v
, float(v
)*100/float(wins
))
101 dumpMargin(wins
, margins
)
105 func round(value
float) int {
107 if value
- float(floor
) > 0.5 {
116 func dumpMargin(totMargin
int, margins
map[int]int) {
117 for k
:= 1; k
<= 9; k
++ {
120 percent
:= float(v
)*100/float(totMargin
)
121 fmt
.Printf("%d: %10d (%6.2f) ", k
, v
, percent
)
122 for i
:= 0; i
< int(round(percent
)); i
++ {
129 func dumpResults(totMargin
int, margins
map[string]map[int]int) {
130 vec
:= vector
.StringVector(make([]string, 0, 32))
131 for k
:= range margins
{
134 sort
.StringArray(vec
).Sort()
135 for _
, dice
:= range vec
{
136 println("Margins for", dice
)
137 dumpMargin(totMargin
, margins
[dice
])