/
suit.go
120 lines (112 loc) · 2.33 KB
/
suit.go
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package bridge
import (
"fmt"
"os"
)
type Suit byte
type Points byte
const (
Jack Suit = 1 << iota
Queen
King
Ace
)
// The following are bigger than we need, but that seems nicer than
// risking panics.
var (
stringTable [256]string
HCP [256]Points
DistPoints [256]Points
PointCount [256]Points
)
func init() {
for s:=Suit(0); s<255; s++ {
l := int(s >> 4)
// First, let's generate the friendly output...
str := make([]byte, int(s >> 4))
for i := range str {
str[i] = 'x'
}
cnum := 0
if s & Ace != 0 && cnum < l {
str[cnum] = 'A'
cnum++
}
if s & King != 0 && cnum < l {
str[cnum] = 'K'
cnum++
}
if s & Queen != 0 && cnum < l {
str[cnum] = 'Q'
cnum++
}
if s & Jack != 0 && cnum < l {
str[cnum] = 'J'
cnum++
}
stringTable[s] = string(str)
// Now let's count high card points...
HCP[s] = Points(((Ace & s) >> 1) + ((Jack + Queen) & s) + ((King & s) >> 1) + ((King & s) >> 2))
// Distributional points are easy...
if l < 3 {
DistPoints[s] = Points(3 - l)
} else {
DistPoints[s] = 0
}
// "Reasonable" point count
PointCount[s] = HCP[s] + DistPoints[s]
if l < 3 && Jack & s != 0 {
PointCount[s] -= 1
} else if l == 2 && Queen & s != 0 {
PointCount[s] -= 1
} else if l == 1 && Queen & s != 0 {
PointCount[s] -= 2
} else if l == 1 && King & s != 0 {
PointCount[s] -= 2
}
}
}
func (s Suit) UnStopped() (badness Score) {
hcp := HCP[s]
length := s >> 4
if length < 3 {
badness += Score(3-length)*SuitLengthProblem
}
if hcp < 3 {
badness += Score(3-hcp)*PointValueProblem
}
return
}
// We implement fmt.Formatter interface just so we can left-align the cards.
func (s Suit) Format(f fmt.State, c int) {
x := stringTable[s]
f.Write([]byte(x))
if w,ok := f.Width(); ok {
for i:=0; i<w-len(x); i++ {
f.Write([]byte{' '})
}
}
}
func (s Suit) String() string {
return stringTable[s]
}
func ReadSuit(x string) Suit {
if x == "~" || x == "-" {
return Suit(0) // special name for void suit
}
out := Suit(len(x) << 4)
for _,c := range x {
switch c {
case 'A','a': out = out | Ace // Be cautious in case duplicate cards show up
case 'K','k': out = out | King
case 'Q','q': out = out | Queen
case 'J','j': out = out | Jack
}
}
return out
}
func (s *Suit) Scan(st fmt.ScanState, x int) os.Error {
str, e := st.Token()
*s = ReadSuit(str)
return e
}