1
+ import numpy as np
2
+
3
+ class Board :
4
+ WHITE = - 1
5
+ BLACK = 1
6
+ EMPTY = 0
7
+
8
+ def __init__ (self ) -> None :
9
+ '''Initiliaze the Othello game board with a 8x8 numpy matrix'''
10
+ self .board = np .array ([0 ]* 8 , dtype = np .int8 ) # initiliasing 1D array with the first row of 8 zeroes
11
+ self .board = self .board [np .newaxis , : ] # expanding 1D array to 2D array
12
+ for _ in range (3 ): # increasing rows till 8
13
+ self .board = np .concatenate ((self .board , self .board ), axis = 0 )
14
+
15
+ # initiliasing the centre squares
16
+ self .board [3 , 3 ] = self .board [4 ,4 ] = Board .WHITE
17
+ self .board [3 , 4 ] = self .board [4 ,3 ] = Board .BLACK
18
+
19
+ self .black_disc_count = 2
20
+ self .white_disc_count = 2
21
+
22
+ def all_legal_moves (self , PLAYER : int ) -> set :
23
+ '''Return all legal moves for the player'''
24
+ OPPONENT = Board .WHITE if PLAYER == Board .BLACK else Board .BLACK
25
+
26
+ all_legal_moves = set ()
27
+ for row in range (8 ):
28
+ for col in range (8 ):
29
+ if self .board [row , col ] == PLAYER :
30
+ all_legal_moves .update (self .legal_moves (row , col ))
31
+
32
+ return all_legal_moves
33
+
34
+ def legal_moves (self , row : int , col : int ) -> list :
35
+ '''Return all legal moves for the cell at the given position'''
36
+ PLAYER = self .board [row , col ]
37
+ OPPONENT = Board .WHITE if PLAYER == Board .BLACK else Board .BLACK
38
+ legal_moves = list ()
39
+
40
+ # check for legal moves along the row of the cell
41
+ if col >= 2 :
42
+ i = col - 1
43
+ while i >= 0 and self .board [row , i ] == OPPONENT :
44
+ i -= 1
45
+ if (i != col - 1 and i >= 0 ) and self .board [row , i ] == Board .EMPTY :
46
+ legal_moves .append ((row , i ))
47
+
48
+ if col <= 5 :
49
+ i = col + 1
50
+ while i < 8 and self .board [row , i ] == OPPONENT :
51
+ i += 1
52
+ if (i != col + 1 and i < 8 ) and self .board [row , i ] == Board .EMPTY :
53
+ legal_moves .append ((row , i ))
54
+
55
+ # check for legal moves along the column of the cell
56
+ if row >= 2 :
57
+ i = row - 1
58
+ while i >= 0 and self .board [i , col ] == OPPONENT :
59
+ i -= 1
60
+ if (i != row - 1 and i >= 0 ) and self .board [i , col ] == Board .EMPTY :
61
+ legal_moves .append ((i , col ))
62
+
63
+ if row <= 5 :
64
+ i = row + 1
65
+ while i < 8 and self .board [i , col ] == OPPONENT :
66
+ i += 1
67
+ if (i != row + 1 and i < 8 ) and self .board [i ,col ] == Board .EMPTY :
68
+ legal_moves .append ((i , col ))
69
+
70
+ # check for legal moves along diagonals on which the cell lies
71
+ if row >= 2 and col >= 2 : # diagonal from the cell towards top left
72
+ r = row - 1
73
+ c = col - 1
74
+ while (r >= 0 and c >= 0 ) and self .board [r , c ] == OPPONENT :
75
+ r -= 1
76
+ c -= 1
77
+ if (r != row - 1 and c != col - 1 ) and (r >= 0 and c >= 0 ) and self .board [r , c ] == Board .EMPTY :
78
+ legal_moves .append ((r , c ))
79
+
80
+ if row >= 2 and col <= 5 : # diagonal from the cell towards top right
81
+ r = row - 1
82
+ c = col + 1
83
+ while (r >= 0 and c < 8 ) and self .board [r , c ] == OPPONENT :
84
+ r -= 1
85
+ c += 1
86
+ if (r != row - 1 and c != col + 1 ) and (r >= 0 and c < 8 ) and self .board [r , c ] == Board .EMPTY :
87
+ legal_moves .append ((r , c ))
88
+
89
+ if row <= 5 and col <= 5 : # diagonal from the cell towards bottom right
90
+ r = row + 1
91
+ c = col + 1
92
+ while (r < 8 and c < 8 ) and self .board [r , c ] == OPPONENT :
93
+ r += 1
94
+ c += 1
95
+ if (r != row + 1 and c != col + 1 ) and (r < 8 and c < 8 ) and self .board [r , c ] == Board .EMPTY :
96
+ legal_moves .append ((r , c ))
97
+
98
+ if row <= 5 and col >= 2 : # diagonal from the cell towards bottom left
99
+ r = row + 1
100
+ c = col - 1
101
+ while (r < 8 and c >= 0 ) and self .board [r , c ] == OPPONENT :
102
+ r += 1
103
+ c -= 1
104
+ if (r != row + 1 and c != col - 1 ) and (r < 8 and c >= 0 ) and self .board [r , c ] == Board .EMPTY :
105
+ legal_moves .append ((r , c ))
106
+
107
+
108
+ return legal_moves
109
+
110
+ def set_discs (self , row : int , col : int , PLAYER : int ) -> None :
111
+ '''Set the discs on the board as per the move made on the given cell'''
112
+ self .board [row , col ] = PLAYER
113
+ OPPONENT = Board .WHITE if PLAYER == Board .BLACK else Board .BLACK
114
+
115
+ # outflanking pieces on the right
116
+ c = col + 1
117
+ while c < 8 and self .board [row , c ] == OPPONENT :
118
+ c += 1
119
+ if (c != col + 1 and c < 8 ) and self .board [row , c ] == PLAYER : # outflanking is legal
120
+ self .board [row , col :c ] = PLAYER
121
+
122
+ # outflanking pieces on the left
123
+ c = col - 1
124
+ while c >= 0 and self .board [row , c ] == OPPONENT :
125
+ c -= 1
126
+ if (c != col - 1 and c >= 0 ) and self .board [row , c ] == PLAYER : # outflanking is ilegal
127
+ self .board [row , c :col ] = PLAYER
128
+
129
+ # outflanking pieces below
130
+ r = row + 1
131
+ while r < 8 and self .board [r , col ] == OPPONENT :
132
+ r += 1
133
+ if (r != row + 1 and r < 8 ) and self .board [r , col ] == PLAYER : # outflanking is legal
134
+ self .board [row :r , col ] = PLAYER
135
+
136
+ # outflanking pieces above
137
+ r = row - 1
138
+ while r >= 0 and self .board [r , col ] == OPPONENT :
139
+ r -= 1
140
+ if (r != row - 1 and r >= 0 ) and self .board [r , col ] == PLAYER : # outflanking is legal
141
+ self .board [r :row , col ] = PLAYER
142
+
143
+ # outflanking pieces in the diagonal from the cell towards top left
144
+ r = row - 1
145
+ c = col - 1
146
+ while (r >= 0 and c >= 0 ) and self .board [r , c ] == OPPONENT :
147
+ r -= 1
148
+ c -= 1
149
+ if (r != row - 1 and c != col - 1 ) and (r >= 0 and c >= 0 ) and self .board [r , c ] == PLAYER : # outflanking is legal
150
+ r = row - 1
151
+ c = col - 1
152
+ while self .board [r , c ] == OPPONENT :
153
+ self .board [r , c ] = PLAYER
154
+ r -= 1
155
+ c -= 1
156
+
157
+ # outflanking pieces in the diagonal from the cell towards top right
158
+ r = row - 1
159
+ c = col + 1
160
+ while (r >= 0 and c < 8 ) and self .board [r , c ] == OPPONENT :
161
+ r -= 1
162
+ c += 1
163
+ if (r != row - 1 and c != col + 1 ) and (r >= 0 and c < 8 ) and self .board [r , c ] == PLAYER : # outflanking is legal
164
+ r = row - 1
165
+ c = col + 1
166
+ while self .board [r , c ] == OPPONENT :
167
+ self .board [r , c ] = PLAYER
168
+ r -= 1
169
+ c += 1
170
+
171
+ # outflanking pieces in the diagonal from the cell towards bottom right
172
+ r = row + 1
173
+ c = col + 1
174
+ while (r < 8 and c < 8 ) and self .board [r , c ] == OPPONENT :
175
+ r += 1
176
+ c += 1
177
+ if ( r != row + 1 and c != col + 1 ) and (r < 8 and c < 8 ) and self .board [r , c ] == PLAYER : # outflanking is legal
178
+ r = row + 1
179
+ c = col + 1
180
+ while self .board [r , c ] == OPPONENT :
181
+ self .board [r , c ] = PLAYER
182
+ r += 1
183
+ c += 1
184
+
185
+ # outflanking pieces in the diagonal from the cell towards bottom left
186
+ r = row + 1
187
+ c = col - 1
188
+ while (r < 8 and c >= 0 ) and self .board [r , c ] == OPPONENT :
189
+ r += 1
190
+ c -= 1
191
+ if (r != row + 1 and c != col - 1 ) and (r < 8 and c >= 0 ) and self .board [r , c ] == PLAYER : # outflanking is legal
192
+ r = row + 1
193
+ c = col - 1
194
+ while self .board [r , c ] == OPPONENT :
195
+ self .board [r , c ] = PLAYER
196
+ r += 1
197
+ c -= 1
198
+
199
+ # update disc counters
200
+ self .black_disc_count = self .board [self .board > 0 ].sum ()
201
+ self .white_disc_count = - self .board [self .board < 0 ].sum ()
202
+
203
+ def print_board (self ) -> None :
204
+ print (self .board )
205
+
206
+ def reset_board (self ) -> None :
207
+ self .board .fill (Board .EMPTY )
208
+
209
+ # initiliasing the centre squares
210
+ self .board [3 , 3 ] = self .board [4 ,4 ] = Board .WHITE
211
+ self .board [3 , 4 ] = self .board [4 ,3 ] = Board .BLACK
212
+
213
+ self .black_disc_count = self .white_disc_count = 2
0 commit comments