1 package bei
2
3 import "fmt"
4
5 const (
6 CommandBEI = "bei"
7 CommandList = "list"
8 CommandSet = "set"
9 CommandDouble = "double"
10 CommandMove = "move"
11 CommandChoose = "choose"
12 )
13
14 const (
15 StateHome1 = 0
16 StateHome2 = 25
17 StateBar1 = 26
18 StateBar2 = 27
19 StateRoll1 = 28
20 StateRoll2 = 29
21 StateRoll3 = 30
22 StateTurn1 = 31
23 StateTurn2 = 32
24 StateCubeValue = 33
25 StateCubePlayer = 34
26 StatePoints1 = 35
27 StatePoints2 = 36
28 StateTotalPoints = 37
29 StateCrawford = 38
30 StateJacoby = 39
31 StateMurphy = 40
32 StateBeavers = 41
33 StateVariant = 42
34 StateEntered1 = 43
35 StateEntered2 = 44
36 )
37
38 const CellCount = 45
39
40 type CrawfordType int
41
42 const (
43 CrawfordPending CrawfordType = iota
44 CrawfordActive
45 CrawfordExpired
46 )
47
48 type BeaversType int
49
50 const (
51 BeaversNone BeaversType = iota
52 BeaversOnly
53 BeaversAndRaccoons
54 )
55
56 type State struct {
57 Board []int
58
59 Roll1 int
60 Roll2 int
61 Roll3 int
62
63 Turn1 int
64 Turn2 int
65
66 CubeValue int
67 CubePlayer int
68
69 Points1 int
70 Points2 int
71 TotalPoints int
72
73 Crawford CrawfordType
74 Jacoby bool
75 Murphy bool
76 Beavers BeaversType
77
78 Variant int
79 Entered1 bool
80 Entered2 bool
81 }
82
83 func EncodeState(s *State) []int {
84 var v []int
85 v = append(v, s.Board[0:28]...)
86 v = append(v, s.Roll1, s.Roll2, s.Roll3, s.Turn1, s.Turn2, s.CubeValue, s.CubePlayer, s.Points1, s.Points2, s.TotalPoints)
87 var jacoby, murphy, entered1, entered2 int
88 if s.Jacoby {
89 jacoby = 1
90 }
91 if s.Murphy {
92 murphy = 1
93 }
94 if s.Entered1 {
95 entered1 = 1
96 }
97 if s.Entered2 {
98 entered2 = 1
99 }
100 return append(v, int(s.Crawford), jacoby, murphy, int(s.Beavers), int(s.Variant), entered1, entered2)
101 }
102
103 func DecodeState(state []int) (*State, error) {
104 if len(state) < CellCount {
105 return nil, fmt.Errorf("failed to parse state %d: expected at least %d cells, got %d", state, CellCount, len(state))
106 }
107 s := &State{
108 Board: state[0:28],
109 Roll1: state[StateRoll1],
110 Roll2: state[StateRoll2],
111 Roll3: state[StateRoll3],
112 Turn1: state[StateTurn1],
113 Turn2: state[StateTurn2],
114 CubeValue: state[StateCubeValue],
115 CubePlayer: state[StateCubePlayer],
116 Points1: state[StatePoints1],
117 Points2: state[StatePoints2],
118 TotalPoints: state[StateTotalPoints],
119 Crawford: CrawfordType(state[StateCrawford]),
120 Jacoby: state[StateJacoby] == 1,
121 Murphy: state[StateMurphy] == 1,
122 Beavers: BeaversType(state[StateBeavers]),
123 Variant: state[StateVariant],
124 Entered1: state[StateEntered1] == 1,
125 Entered2: state[StateEntered2] == 1,
126 }
127 switch {
128 case s.Roll1 < 0 || s.Roll1 > 6:
129 return nil, fmt.Errorf("failed to parse state %d: invalid dice roll 1: %d", state, s.Roll1)
130 case s.Roll2 < 0 || s.Roll2 > 6:
131 return nil, fmt.Errorf("failed to parse state %d: invalid dice roll 2: %d", state, s.Roll2)
132 case s.Roll3 < 0 || s.Roll3 > 6:
133 return nil, fmt.Errorf("failed to parse state %d: invalid dice roll 3: %d", state, s.Roll3)
134 case s.Crawford < CrawfordPending || s.Crawford > CrawfordExpired:
135 return nil, fmt.Errorf("failed to parse state %d: invalid crawford type: %d", state, s.Crawford)
136 case s.Beavers < BeaversNone || s.Beavers > BeaversAndRaccoons:
137 return nil, fmt.Errorf("failed to parse state %d: invalid beavers type: %d", state, s.Beavers)
138 default:
139 return s, nil
140 }
141 }
142
View as plain text