1 package tabula
2
3 import (
4 "fmt"
5 "testing"
6 )
7
8 func TestMoveBackgammon(t *testing.T) {
9 b := NewBoard(VariantBackgammon)
10 b[SpaceRoll1] = 1
11 b[SpaceRoll2] = 2
12 got, expected := b[24], int8(2)
13 if got != expected {
14 t.Errorf("unexpected space %d value: expected %d: got %d", 24, expected, got)
15 }
16 got, expected = b[22], 0
17 if got != expected {
18 t.Errorf("unexpected space %d value: expected %d: got %d", 22, expected, got)
19 }
20 bc := b.Move(24, 23, 1)
21 got, expected = b[24], int8(2)
22 if got != expected {
23 t.Errorf("unexpected space %d value: expected %d: got %d", 24, expected, got)
24 }
25 got, expected = bc[23], int8(1)
26 if got != expected {
27 t.Errorf("unexpected space %d value: expected %d: got %d", 23, expected, got)
28 }
29 got, expected = bc[24], 1
30 if got != expected {
31 t.Errorf("unexpected space %d value: expected %d: got %d", 24, expected, got)
32 }
33 got, expected = bc[22], 0
34 if got != expected {
35 t.Errorf("unexpected space %d value: expected %d: got %d", 22, expected, got)
36 }
37 }
38
39 func TestMoveTabula(t *testing.T) {
40 {
41 b := NewBoard(VariantTabula)
42 b[SpaceRoll1] = 1
43 b[SpaceRoll2] = 2
44
45 bc := b.Move(SpaceHomePlayer, 23, 1)
46 got, expected := bc[SpaceHomePlayer], int8(14)
47 if got != expected {
48 t.Errorf("unexpected space %d value: expected %d: got %d", SpaceHomePlayer, expected, got)
49 }
50 got, expected = bc[23], int8(1)
51 if got != expected {
52 t.Errorf("unexpected space %d value: expected %d: got %d", 23, expected, got)
53 }
54 bc = bc.Move(SpaceHomePlayer, 22, 1)
55 got, expected = bc[SpaceHomePlayer], int8(13)
56 if got != expected {
57 t.Errorf("unexpected space %d value: expected %d: got %d", SpaceHomePlayer, expected, got)
58 }
59 got, expected = bc[22], int8(1)
60 if got != expected {
61 t.Errorf("unexpected space %d value: expected %d: got %d", 22, expected, got)
62 }
63 }
64
65 {
66 b := Board{0, 1, 2, 3, 4, 4, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 1, 0, 2}
67 b[SpaceRoll1] = 1
68 b[SpaceRoll2] = 2
69
70 bc := b.UseRoll(1, 2, 1).Move(1, 2, 1)
71 got, expected := bc[1], int8(0)
72 if got != expected {
73 t.Errorf("unexpected space %d value: expected %d: got %d", 1, expected, got)
74 }
75 got, expected = bc[2], int8(3)
76 if got != expected {
77 t.Errorf("unexpected space %d value: expected %d: got %d", 2, expected, got)
78 }
79
80 if !bc.HaveRoll(5, 7, 1) {
81 t.Errorf("unexpected have roll value: expected %v: got %v", false, true)
82 }
83
84 if bc.HaveRoll(12, 13, 1) {
85 t.Errorf("unexpected have roll value: expected %v: got %v", false, true)
86 }
87
88 if !bc.HaveRoll(12, 14, 1) {
89 t.Errorf("unexpected have roll value: expected %v: got %v", true, true)
90 }
91 }
92
93 {
94 b := Board{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 0, 2}
95 b[SpaceRoll1] = 1
96 b[SpaceRoll2] = 2
97
98 if b.HaveRoll(12, 13, 1) {
99 t.Errorf("unexpected have roll value: expected %v: got %v", false, true)
100 }
101
102 bc := b.UseRoll(0, 1, 1).Move(0, 1, 1)
103 got, expected := bc[0], int8(0)
104 if got != expected {
105 t.Errorf("unexpected space %d value: expected %d: got %d", 0, expected, got)
106 }
107 got, expected = bc[1], int8(1)
108 if got != expected {
109 t.Errorf("unexpected space %d value: expected %d: got %d", 1, expected, got)
110 }
111
112 if bc.HaveRoll(12, 13, 1) {
113 t.Errorf("unexpected have roll value: expected %v: got %v", false, false)
114 }
115
116 if !bc.HaveRoll(12, 14, 1) {
117 t.Errorf("unexpected have roll value: expected %v: got %v", true, false)
118 }
119 }
120
121 {
122 b := Board{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 0, 1, 0, 2}
123 b[SpaceRoll1] = 1
124 b[SpaceRoll2] = 2
125
126 if !b.HaveRoll(12, 14, 1) {
127 t.Errorf("unexpected have roll value: expected %v: got %v", true, false)
128 }
129
130 if b.MayBearOff(1) {
131 t.Errorf("unexpected bear off value: expected %v: got %v", false, true)
132 }
133
134 b = b.Move(12, 14, 1).UseRoll(12, 14, 1)
135 got, expected := b[12], int8(0)
136 if got != expected {
137 t.Errorf("unexpected space %d value: expected %d: got %d", 12, expected, got)
138 }
139 got, expected = b[14], int8(1)
140 if got != expected {
141 t.Errorf("unexpected space %d value: expected %d: got %d", 14, expected, got)
142 }
143
144 if !b.MayBearOff(1) {
145 t.Errorf("unexpected bear off value: expected %v: got %v", true, false)
146 }
147
148 if !b.HaveRoll(14, 15, 1) {
149 t.Errorf("unexpected have roll value: expected %v: got %v", true, false)
150 }
151
152 if b.HaveRoll(14, 16, 1) {
153 t.Errorf("unexpected have roll value: expected %v: got %v", false, true)
154 }
155 }
156
157 {
158 b := Board{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -15, 0, 0, 0, 0, 0, 0, 1, 0, 2}
159 b[SpaceRoll1] = 1
160 b[SpaceRoll2] = 2
161
162 if !b.HaveRoll(12, 14, 1) {
163 t.Errorf("unexpected have roll value: expected %v: got %v", true, false)
164 }
165
166 if b.MayBearOff(1) {
167 t.Errorf("unexpected bear off value: expected %v: got %v", false, true)
168 }
169
170 if b.HaveRoll(24, 0, 1) {
171 t.Errorf("unexpected have roll value: expected %v: got %v", false, true)
172 }
173
174 b = b.UseRoll(12, 14, 1).Move(12, 14, 1)
175 got, expected := b[12], int8(0)
176 if got != expected {
177 t.Errorf("unexpected space %d value: expected %d: got %d", 12, expected, got)
178 }
179 got, expected = b[14], int8(1)
180 if got != expected {
181 t.Errorf("unexpected space %d value: expected %d: got %d", 14, expected, got)
182 }
183
184 if !b.MayBearOff(1) {
185 t.Errorf("unexpected bear off value: expected %v: got %v", true, false)
186 }
187
188 if !b.HaveRoll(24, 0, 1) {
189 t.Errorf("unexpected have roll value: expected %v: got %v", true, false)
190 }
191 }
192 }
193
194 func TestPastBackgammon(t *testing.T) {
195 b := NewBoard(VariantBackgammon)
196 got, expected := b.Past(), false
197 if got != expected {
198 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
199 }
200
201 b = Board{0, 1, 3, -1, 0, -1, 0, -2, 0, 0, -1, 0, -3, 3, 0, 0, 0, -2, 0, -5, 4, 0, 2, 2, 0, 0, 0, 0, 5, 5, 5, 5, 1, 1, 0}
202 got, expected = b.Past(), false
203 if got != expected {
204 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
205 }
206
207 b = Board{0, -1, 1, -2, -1, 2, 4, 0, 0, 0, 0, 0, -1, 2, -1, 0, 0, -1, 3, -3, 0, 3, -1, -3, -1, 0, 0, 0, 4, 3, 0, 0, 1, 1, 0}
208 got, expected = b.Past(), false
209 if got != expected {
210 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
211 }
212
213 b = Board{7, 2, 2, 4, 0, -2, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, -4, 0, -2, -1, -1, -1, 0, 0, 0, 6, 2, 0, 0, 1, 1, 0}
214 got, expected = b.Past(), true
215 if got != expected {
216 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
217 }
218 }
219
220 func TestPastAcey(t *testing.T) {
221 b := NewBoard(VariantAceyDeucey)
222 got, expected := b.Past(), false
223 if got != expected {
224 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
225 }
226
227 b = Board{0, 1, 3, -1, 0, -1, 0, -2, 0, 0, -1, 0, -3, 3, 0, 0, 0, -2, 0, -5, 4, 0, 2, 2, 0, 0, 0, 0, 5, 5, 5, 5, 1, 1, 1}
228 got, expected = b.Past(), false
229 if got != expected {
230 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
231 }
232
233 b = Board{0, -1, 1, -2, -1, 2, 4, 0, 0, 0, 0, 0, -1, 2, -1, 0, 0, -1, 3, -3, 0, 3, -1, -3, -1, 0, 0, 0, 4, 3, 0, 0, 1, 1, 1}
234 got, expected = b.Past(), false
235 if got != expected {
236 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
237 }
238
239 b = Board{7, 2, 2, 4, 0, -2, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, -4, 0, -2, -1, -1, -1, 0, 0, 0, 6, 2, 0, 0, 0, 1, 1}
240 got, expected = b.Past(), false
241 if got != expected {
242 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
243 }
244
245 b = Board{7, 2, 2, 4, 0, -2, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, -4, 0, -2, -1, -1, -1, 0, 0, 0, 6, 2, 0, 0, 1, 1, 1}
246 got, expected = b.Past(), true
247 if got != expected {
248 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
249 }
250 }
251
252 func TestPastTabula(t *testing.T) {
253 b := NewBoard(VariantTabula)
254 got, expected := b.Past(), false
255 if got != expected {
256 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
257 }
258
259 b = Board{0, 1, 3, -1, 0, -1, 0, -2, 0, 0, -1, 0, -3, 3, 0, 0, 0, -2, 0, -5, 4, 0, 2, 2, 0, 0, 0, 0, 5, 5, 5, 5, 1, 1, 2}
260 got, expected = b.Past(), false
261 if got != expected {
262 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
263 }
264
265 b = Board{0, -1, 1, -2, -1, 2, 4, 0, 0, 0, 0, 0, -1, 2, -1, 0, 0, -1, 3, -3, 0, 3, -1, -3, -1, 0, 0, 0, 4, 3, 0, 0, 1, 1, 2}
266 got, expected = b.Past(), false
267 if got != expected {
268 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
269 }
270
271 b = Board{7, 2, 2, 4, 0, -2, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, -4, 0, -2, -1, -1, -1, 0, 0, 0, 6, 2, 0, 0, 1, 1, 2}
272 got, expected = b.Past(), false
273 if got != expected {
274 t.Errorf("unexpected past value: expected %v: got %v", expected, got)
275 }
276 }
277
278 func TestBlots(t *testing.T) {
279 b := NewBoard(VariantBackgammon)
280 got, expected := b.Blots(1), 0
281 if got != expected {
282 t.Errorf("unexpected blots value: expected %v: got %v", expected, got)
283 }
284 got, expected = b.Blots(2), 0
285 if got != expected {
286 t.Errorf("unexpected blots value: expected %v: got %v", expected, got)
287 }
288
289 b = b.Move(24, 23, 1)
290
291 got, expected = b.Blots(1), 19
292 if got != expected {
293 t.Errorf("unexpected blots value: expected %v: got %v", expected, got)
294 }
295 got, expected = b.Blots(2), 0
296 if got != expected {
297 t.Errorf("unexpected blots value: expected %v: got %v", expected, got)
298 }
299
300 b = b.Move(1, 2, 2)
301
302 got, expected = b.Blots(1), 19
303 if got != expected {
304 t.Errorf("unexpected blots value: expected %v: got %v", expected, got)
305 }
306 got, expected = b.Blots(2), 19
307 if got != expected {
308 t.Errorf("unexpected blots value: expected %v: got %v", expected, got)
309 }
310 }
311
312 func TestHitScore(t *testing.T) {
313 b := Board{0, 0, -2, -2, -2, 4, 0, -1, 0, 0, -2, 4, 0, -2, -1, 0, -2, 4, 0, 2, 0, 0, 0, 0, -1, 0, 1, 0, 4, 1, 0, 0, 1, 1, 1}
314 available, _ := b.Available(1)
315 analysis := make([]*Analysis, 0, AnalysisBufferSize)
316 b.Analyze(available, &analysis)
317
318 var reached bool
319 minHitScore := 200
320 for _, a := range analysis {
321 if a.hitScore >= minHitScore {
322 reached = true
323 break
324 }
325 }
326 if !reached {
327 t.Errorf("unexpected hit score for analysis: expected hit score of at least %d", minHitScore)
328 }
329 }
330
331 func TestAnalyze(t *testing.T) {
332 b := NewBoard(VariantBackgammon)
333 b = b.Move(24, 23, 1)
334 b = b.Move(1, 2, 2)
335 b[SpaceRoll1], b[SpaceRoll2] = 1, 2
336
337 available, _ := b.Available(1)
338 analysis := make([]*Analysis, 0, AnalysisBufferSize)
339 b.Analyze(available, &analysis)
340 var blots int
341 for _, r := range analysis {
342 blots += r.Blots
343 }
344 if blots <= 0 {
345 t.Errorf("expected >0 blots in results, got %d", blots)
346 }
347
348 type testCase struct {
349 roll1, roll2, roll3, roll4 int8
350 }
351 cases := []*testCase{
352 {1, 1, 1, 1},
353 {2, 2, 2, 2},
354 {3, 3, 3, 3},
355 {4, 4, 4, 4},
356 {5, 5, 5, 5},
357 {6, 6, 6, 6},
358 {1, 2, 0, 0},
359 {2, 3, 0, 0},
360 {3, 4, 0, 0},
361 {4, 5, 0, 0},
362 {5, 6, 0, 0},
363 }
364 for _, c := range cases {
365 t.Run(fmt.Sprintf("%d-%d", c.roll1, c.roll2), func(t *testing.T) {
366 board := NewBoard(VariantBackgammon)
367 board[SpaceRoll1] = c.roll1
368 board[SpaceRoll2] = c.roll2
369 board[SpaceRoll3] = c.roll3
370 board[SpaceRoll4] = c.roll4
371 available, _ := board.Available(1)
372
373 board.Analyze(available, &analysis)
374 })
375 }
376 }
377
378 func BenchmarkAvailable(b *testing.B) {
379 type testCase struct {
380 roll1, roll2, roll3, roll4 int8
381 }
382 cases := []*testCase{
383 {1, 1, 1, 1},
384 {2, 2, 2, 2},
385 {3, 3, 3, 3},
386 {4, 4, 4, 4},
387 {5, 5, 5, 5},
388 {6, 6, 6, 6},
389 {1, 2, 0, 0},
390 {2, 3, 0, 0},
391 {3, 4, 0, 0},
392 {4, 5, 0, 0},
393 {5, 6, 0, 0},
394 }
395 for _, c := range cases {
396 b.Run(fmt.Sprintf("%d-%d", c.roll1, c.roll2), func(b *testing.B) {
397 board := NewBoard(VariantBackgammon)
398 board[SpaceRoll1] = c.roll1
399 board[SpaceRoll2] = c.roll2
400 board[SpaceRoll3] = c.roll3
401 board[SpaceRoll4] = c.roll4
402
403 var available [][4][2]int8
404 b.ResetTimer()
405 for i := 0; i < b.N; i++ {
406 available, _ = board.Available(1)
407 }
408
409 _ = available
410 })
411 }
412 }
413
414 func BenchmarkAnalyze(b *testing.B) {
415 type testCase struct {
416 roll1, roll2, roll3, roll4 int8
417 }
418 cases := []*testCase{
419 {1, 1, 1, 1},
420 {2, 2, 2, 2},
421 {3, 3, 3, 3},
422 {4, 4, 4, 4},
423 {5, 5, 5, 5},
424 {6, 6, 6, 6},
425 {1, 2, 0, 0},
426 {2, 3, 0, 0},
427 {3, 4, 0, 0},
428 {4, 5, 0, 0},
429 {5, 6, 0, 0},
430 }
431 for _, c := range cases {
432 b.Run(fmt.Sprintf("%d-%d", c.roll1, c.roll2), func(b *testing.B) {
433 board := NewBoard(VariantBackgammon)
434 board[SpaceRoll1] = c.roll1
435 board[SpaceRoll2] = c.roll2
436 board[SpaceRoll3] = c.roll3
437 board[SpaceRoll4] = c.roll4
438 available, _ := board.Available(1)
439 analysis := make([]*Analysis, 0, AnalysisBufferSize)
440
441 b.ResetTimer()
442 for i := 0; i < b.N; i++ {
443 board.Analyze(available, &analysis)
444 }
445
446 _ = analysis
447 })
448 }
449 }
450
451 func BenchmarkChooseDoubles(b *testing.B) {
452 board := Board{0, -2, -2, -3, -1, -2, -3, 0, -2, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 2, 2, 5, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 1, 1}
453 analysis := make([]*Analysis, 0, AnalysisBufferSize)
454
455 var doubles int
456 b.ResetTimer()
457 for i := 0; i < b.N; i++ {
458 doubles = board.ChooseDoubles(&analysis)
459 }
460 _ = doubles
461 }
462
463 func BenchmarkMayBearOff(b *testing.B) {
464 board := NewBoard(VariantBackgammon)
465
466 var allowed bool
467 b.ResetTimer()
468 for i := 0; i < b.N; i++ {
469 allowed = board.MayBearOff(1)
470 }
471
472 _ = allowed
473 }
474
View as plain text