fix bear_off bug; addtional tests and additional fixes

This commit is contained in:
Christoffer Müller Madsen 2018-05-12 15:18:52 +02:00
parent c3f5e909d6
commit 9f1bd56c0a
2 changed files with 385 additions and 315 deletions

View File

@ -73,29 +73,49 @@ int no_block_at_to_idx(int to_state, int player) {
else return 1; else return 1;
} }
int can_bear_off(int board[], int player, int from_idx) {
int can_bear_off(int board[], int player, int from_idx, int to_idx) {
int* checker_idxs = idxs_with_checkers_of_player(board, player); int* checker_idxs = idxs_with_checkers_of_player(board, player);
if (player == 1) { int moving_backmost_checker = 1;
for (int i = 1; i <= checker_idxs[0]; i++) { int bearing_directly_off = 0;
if ( !((checker_idxs[i] >= from_idx) && int all_checkers_in_last_quadrant = 1;
(checker_idxs[i] >= 19)) ) {
free(checker_idxs); /* Check if bearing directly off */
return 0; if (player == 1 && to_idx == 25) bearing_directly_off = 1;
else if (player == -1 && to_idx == 0) bearing_directly_off = 1;
for (int i = 1; i <= checker_idxs[0]; i++) {
if (player == 1 ) {
/* Check if all checkers are in last quardrant */
if (checker_idxs[i] < 19) {
all_checkers_in_last_quadrant = 0;
break;
} }
}
} else { /* Check if moving backmost checker */
for (int i = 1; i <= checker_idxs[0]; i++) { if (checker_idxs[i] < from_idx) {
if ( !((checker_idxs[i] <= from_idx) && moving_backmost_checker = 0;
(checker_idxs[i] <= 6)) ) { if (!bearing_directly_off) break;
free(checker_idxs); }
return 0; } else {
if (checker_idxs[i] > 6) {
all_checkers_in_last_quadrant = 0;
break;
}
if (checker_idxs[i] > from_idx) {
moving_backmost_checker = 0;
if (!bearing_directly_off) break;
} }
} }
} }
free(checker_idxs); free(checker_idxs);
return 1;
if (all_checkers_in_last_quadrant &&
(bearing_directly_off || moving_backmost_checker)) return 1;
else return 0;
} }
@ -124,7 +144,7 @@ int is_move_valid(int board[], int player, int face_value, int move[]) {
&& bear_in_if_checker_on_bar(board, player, from_idx) && bear_in_if_checker_on_bar(board, player, from_idx)
&& checkers_at_from_idx(from_state, player) && checkers_at_from_idx(from_state, player)
&& no_block_at_to_idx(to_state, player) && no_block_at_to_idx(to_state, player)
&& (!bearing_off || can_bear_off(board, player, from_idx)) && (!bearing_off || can_bear_off(board, player, from_idx, to_idx))
; ;
} }

648
test.py
View File

@ -141,6 +141,56 @@ class TestIsMoveValid(unittest.TestCase):
# TODO: More tests for bearing off are needed # TODO: More tests for bearing off are needed
def test_bear_off_non_backmost(self):
board = ( 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1,
0 )
self.assertEqual(Board.is_move_valid(board, 1, 2, (23, 25)), True)
self.assertEqual(Board.is_move_valid(board, 1, 1, (24, 25)), True)
self.assertEqual(Board.is_move_valid(board, 1, 2, (24, 26)), False)
def test_bear_off_quadrant_limits_white(self):
board = ( 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1,
0 )
self.assertEqual(Board.is_move_valid(board, 1, 2, (23, 25)), False)
self.assertEqual(Board.is_move_valid(board, 1, 1, (24, 25)), False)
def test_bear_off_quadrant_limits_black(self):
board = ( 0,
-1, -1, -1, -1, -1, -1,
-1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0 )
self.assertEqual(Board.is_move_valid(board, -1, 2, (2, 0)), False)
self.assertEqual(Board.is_move_valid(board, -1, 1, (1, 0)), False)
def test_bear_off_quadrant_limits_white_2(self):
board = ( 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 1,
0 )
self.assertEqual(Board.is_move_valid(board, 1, 1, (24, 25)), True)
def test_bear_off_quadrant_limits_black_2(self):
board = ( 0,
-1, 0, 0, 0, 0, -1,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0 )
self.assertEqual(Board.is_move_valid(board, -1, 1, (1, 0)), True)
class TestNumOfChecker(unittest.TestCase): class TestNumOfChecker(unittest.TestCase):
def test_simple_1(self): def test_simple_1(self):
board = ( 0, board = ( 0,
@ -552,372 +602,372 @@ class TestLegalMoves(unittest.TestCase):
self.assertEqual(Board.calculate_legal_states(board, -1, (4,3)), expected_board_set) self.assertEqual(Board.calculate_legal_states(board, -1, (4,3)), expected_board_set)
# class TestBoardFlip(unittest.TestCase): class TestBoardFlip(unittest.TestCase):
# def test_flip_board(self): def test_flip_board(self):
# board = (0, board = (0,
# -14, -1, 0, 0, 0, 0, -14, -1, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1,
# 0) 0)
# expected_board = ( 0, expected_board = ( 0,
# -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 1, 14, 0, 0, 0, 0, 1, 14,
# 0 ) 0 )
# self.assertEqual(Board.flip(board), expected_board) self.assertEqual(Board.flip(board), expected_board)
# def test_flip_board_bar(self): def test_flip_board_bar(self):
# board = (2, board = (2,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# -7) -7)
# expected_board = (7, expected_board = (7,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# -2) -2)
# self.assertEqual(Board.flip(board), expected_board) self.assertEqual(Board.flip(board), expected_board)
# def test_flip_board_extensive(self): def test_flip_board_extensive(self):
# board = (4, board = (4,
# -5, -1, 0, 4, 3, 0, -5, -1, 0, 4, 3, 0,
# 0, -1, 0, -5, 0, 0, 0, -1, 0, -5, 0, 0,
# 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
# 0, 0, 0, -1, 0, 1, 0, 0, 0, -1, 0, 1,
# -2) -2)
# expected_board = (2, expected_board = (2,
# -1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0,
# 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -3, 0,
# 0, 0, 5, 0, 1, 0, 0, 0, 5, 0, 1, 0,
# 0, -3, -4, 0, 1, 5, 0, -3, -4, 0, 1, 5,
# -4) -4)
# self.assertEqual(Board.flip(board), expected_board) self.assertEqual(Board.flip(board), expected_board)
# def test_inverse(self): def test_inverse(self):
# board = (4, board = (4,
# -5, -1, 0, 4, 3, 0, -5, -1, 0, 4, 3, 0,
# 0, -1, 0, -5, 0, 0, 0, -1, 0, -5, 0, 0,
# 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
# 0, 0, 0, -1, 0, 1, 0, 0, 0, -1, 0, 1,
# -2) -2)
# self.assertEqual(Board.flip(Board.flip(board)), board) self.assertEqual(Board.flip(Board.flip(board)), board)
# def test_tesauro_initial(self): def test_tesauro_initial(self):
# board = Board.initial_state board = Board.initial_state
# expected = (1,1,0,0, expected = (1,1,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,0, 1,1,1,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0.0, 0.0,
# 0, 0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,0, 1,1,1,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,0,0, 1,1,0,0,
# 0.0, 0.0,
# 0, 0,
# 1, 1,
# 0 0
# ) )
# import numpy as np import numpy as np
# self.assertTrue((Board.board_features_tesauro(board, 1) == self.assertTrue((Board.board_features_tesauro(board, 1) ==
# np.array(expected).reshape(1, 198)).all()) np.array(expected).reshape(1, 198)).all())
# def test_tesauro_bars(self): def test_tesauro_bars(self):
# board = list(Board.initial_state) board = list(Board.initial_state)
# board[1] = 0 board[1] = 0
# board[0] = 2 board[0] = 2
# board[24] = 0 board[24] = 0
# board[25] = -2 board[25] = -2
# board = tuple(board) board = tuple(board)
# expected = (0,0,0,0, expected = (0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,0, 1,1,1,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1.0, 1.0,
# 0, 0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,0, 1,1,1,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1.0, 1.0,
# 0, 0,
# 1, 1,
# 0 0
# ) )
# import numpy as np import numpy as np
# self.assertTrue((Board.board_features_tesauro(board, 1) == self.assertTrue((Board.board_features_tesauro(board, 1) ==
# np.array(expected).reshape(1, 198)).all()) np.array(expected).reshape(1, 198)).all())
# def test_tesauro_home(self): def test_tesauro_home(self):
# board = list(Board.initial_state) board = list(Board.initial_state)
# board[1] = 0 board[1] = 0
# board[24] = 0 board[24] = 0
# board = tuple(board) board = tuple(board)
# expected = (0,0,0,0, expected = (0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,0, 1,1,1,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0.0, 0.0,
# 2, 2,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,0, 1,1,1,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0.0, 0.0,
# 2, 2,
# 1, 1,
# 0 0
# ) )
# import numpy as np import numpy as np
# self.assertTrue((Board.board_features_tesauro(board, 1) == self.assertTrue((Board.board_features_tesauro(board, 1) ==
# np.array(expected).reshape(1, 198)).all()) np.array(expected).reshape(1, 198)).all())
# def test_tesauro_black_player(self): def test_tesauro_black_player(self):
# board = Board.initial_state board = Board.initial_state
# expected = (1,1,0,0, expected = (1,1,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,0, 1,1,1,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0.0, 0.0,
# 0, 0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,0, 1,1,1,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,1,1, 1,1,1,1,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 0,0,0,0, 0,0,0,0,
# 1,1,0,0, 1,1,0,0,
# 0.0, 0.0,
# 0, 0,
# 0, 0,
# 1 1
# ) )
# import numpy as np import numpy as np
# self.assertTrue((Board.board_features_tesauro(board, -1) == self.assertTrue((Board.board_features_tesauro(board, -1) ==
# np.array(expected).reshape(1, 198)).all()) np.array(expected).reshape(1, 198)).all())
if __name__ == '__main__': if __name__ == '__main__':