This repository was archived by the owner on Feb 9, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_connect4.py
More file actions
167 lines (141 loc) · 6.31 KB
/
test_connect4.py
File metadata and controls
167 lines (141 loc) · 6.31 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
"""
To run tests:
pytest-3 connect4
"""
from collections import namedtuple
import textwrap
import numpy as np
from .Connect4Game import Connect4Game
# Tuple of (Board, Player, Game) to simplify testing.
BPGTuple = namedtuple('BPGTuple', 'board player game')
def init_board_from_moves(moves, height=None, width=None):
"""Returns a BPGTuple based on series of specified moved."""
game = Connect4Game(height=height, width=width)
board, player = game.getInitBoard(), 1
for move in moves:
board, player = game.getNextState(board, player, move)
return BPGTuple(board, player, game)
def init_board_from_array(board, player):
"""Returns a BPGTuple based on series of specified moved."""
game = Connect4Game(height=len(board), width=len(board[0]))
return BPGTuple(board, player, game)
def test_simple_moves():
board, player, game = init_board_from_moves([4, 5, 4, 3, 0, 6])
expected = textwrap.dedent("""\
[[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 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.]
[ 1. 0. 0. -1. 1. -1. -1.]]""")
assert expected == game.stringRepresentation(board)
def test_overfull_column():
for height in range(1, 10):
# Fill to max height is ok
init_board_from_moves([4] * height, height=height)
# Check overfilling causes an error.
try:
init_board_from_moves([4] * (height + 1), height=height)
assert False, "Expected error when overfilling column"
except ValueError:
pass # Expected.
def test_get_valid_moves():
"""Tests vector of valid moved is correct."""
move_valid_pairs = [
([], [True] * 7),
([0, 1, 2, 3, 4, 5, 6], [True] * 7),
([0, 1, 2, 3, 4, 5, 6] * 5, [True] * 7),
([0, 1, 2, 3, 4, 5, 6] * 6, [False] * 7),
([0, 1, 2] * 3 + [3, 4, 5, 6] * 6, [True] * 3 + [False] * 4),
]
for moves, expected_valid in move_valid_pairs:
board, player, game = init_board_from_moves(moves)
assert (np.array(expected_valid) == game.getValidMoves(board, player)).all()
def test_symmetries():
"""Tests symetric board are produced."""
board, player, game = init_board_from_moves([0, 0, 1, 0, 6])
pi = [0.1, 0.2, 0.3]
(board1, pi1), (board2, pi2) = game.getSymmetries(board, pi)
assert [0.1, 0.2, 0.3] == pi1 and [0.3, 0.2, 0.1] == pi2
expected_board1 = textwrap.dedent("""\
[[ 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. 0.]
[-1. 0. 0. 0. 0. 0. 0.]
[ 1. 1. 0. 0. 0. 0. 1.]]""")
assert expected_board1 == game.stringRepresentation(board1)
expected_board2 = textwrap.dedent("""\
[[ 0. 0. 0. 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. 0. -1.]
[ 1. 0. 0. 0. 0. 1. 1.]]""")
assert expected_board2 == game.stringRepresentation(board2)
def test_game_ended():
"""Tests game end detection logic based on fixed boards."""
array_end_state_pairs = [
(np.array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 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),
(np.array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]]), 1, 1),
(np.array([[0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]]), -1, -1),
(np.array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 1, 0]]), -1, -1),
(np.array([[0, 0, 0, -1],
[0, 0, -1, 0],
[0, -1, 0, 0],
[-1, 0, 0, 0]]), 1, -1),
(np.array([[0, 0, 0, 0, 1],
[0, 0, 0, 1, 0],
[0, 0, 1, 0, 0],
[0, 1, 0, 0, 0]]), -1, -1),
(np.array([[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0]]), -1, -1),
(np.array([[ 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, -1, 0, 0, 0],
[ 0, 0, 0, -1, 0, 0, 1],
[ 0, 0, 0, 1, 1, -1, -1],
[ 0, 0, 0, -1, 1, 1, 1],
[ 0, -1, 0, -1, 1, -1, 1]]), -1, 0),
(np.array([[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., -1., 0., 0., 0.],
[ 1., 0., 1., -1., 0., 0., 0.],
[-1., -1., 1., 1., 0., 0., 0.],
[ 1., 1., 1., -1., 0., 0., 0.],
[ 1., -1., 1., -1., 0., -1., 0.]]), -1, -1),
(np.array([[ 0., 0., 0., 1., 0., 0., 0.,],
[ 0., 0., 0., 1., 0., 0., 0.,],
[ 0., 0., 0., -1., 0., 0., 0.,],
[ 0., 0., 1., 1., -1., 0., -1.,],
[ 0., 0., -1., 1., 1., 1., 1.,],
[-1., 0., -1., 1., -1., -1., -1.,],]), 1, 1),
]
for np_pieces, player, expected_end_state in array_end_state_pairs:
board, player, game = init_board_from_array(np_pieces, player)
end_state = game.getGameEnded(board, player)
assert expected_end_state == end_state, ("expected=%s, actual=%s, board=\n%s" % (expected_end_state, end_state, board))
def test_immutable_move():
"""Test original board is not mutated whtn getNextState() called."""
board, player, game = init_board_from_moves([1, 2, 3, 3, 4])
original_board_string = game.stringRepresentation(board)
new_np_pieces, new_player = game.getNextState(board, 3, -1)
assert original_board_string == game.stringRepresentation(board)
assert original_board_string != game.stringRepresentation(new_np_pieces)