-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgamePlay.py
executable file
·216 lines (189 loc) · 6.47 KB
/
gamePlay.py
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
import sys
import time
import getopt
from copy import deepcopy
def opponent(x):
""" Given a string representing a color (must be either "B" or "W"),
return the opposing color """
if x == "b" or x == "B":
return "W"
elif x == "w" or x == "W":
return "B"
else:
return "."
def validMove(board, color, pos):
""" Given a 2D array representing a board, a string
representing a color, and a tuple representing a
position, return true if the position is a valid
move for the color """
if board[pos[0]][pos[1]] != '.':
return False
for i in range(-1, 2):
for j in range(-1, 2):
if i != 0 or j != 0:
if canFlip(board, color, pos, (i,j)):
return True
return False
def valid(board, color, move):
""" Given a 2D array representing a board, a string
representing a color, and either a tuple representing a
position or the string "pass", return true if the move
is a valid for the color """
if move == "pass":
for i in range(0,8):
for j in range(0,8):
if validMove(board, color, (i,j)):
return False
return True
else:
return validMove(board, color, move)
def validPos(x,y):
""" Return true of the (x,y) position is within the board """
return x >= 0 and x < 8 and y >= 0 and y < 8
def doFlip(board, color, pos, direction):
""" Given a 2D array representing a board, a color, a position
to move to, and a tuple representing a direction ( (-1,0)
for up, (-1,1) for up and to the right, (0,1) for to the right,
and so on), flip all the pieces in the direction until a
piece of the same color is found """
currX = pos[0] + direction[0]
currY = pos[1] + direction[1]
while board[currX][currY] == opponent(color):
board[currX][currY] = color
(currX, currY) = (currX + direction[0], currY + direction[1])
def doMove(board, color, pos):
""" Given a 2D array representing a board, a color, and a position,
implement the move on the board. Note that the move is assumed
to be valid """
if pos != "pass":
if validMove(board, color, pos):
board[pos[0]][pos[1]] = color
for i in range(-1, 2):
for j in range(-1, 2):
if i != 0 or j != 0:
if canFlip(board, color, pos, (i,j)):
doFlip(board, color, pos, (i,j))
def canFlip(board, color, pos, direction):
""" Given a 2D array representing a board, a color, a position
to move to, and a tuple representing a direction ( (-1,0)
for up, (-1,1) for up and to the right, (0,1) for to the right,
and so on), determine if there is a sequence of opponent pieces,
followed by a color piece, that would allow a flip in this direction
from this position, if a color piece is placed at pos """
currX = pos[0] + direction[0]
currY = pos[1] + direction[1]
if not validPos(currX,currY):
return False
if board[currX][currY] != opponent(color):
return False
while True:
(currX, currY) = (currX + direction[0], currY + direction[1])
if not validPos(currX, currY):
return False
if board[currX][currY] == color:
return True
if board[currX][currY] == '.':
return False
def newBoard():
""" Create a new board: 2D array of strings:
'B' for black, 'W' for white, and '.' for empty """
result = []
for i in range(3):
result = result + [["."]*8]
result = result + [["."] * 3 + ["W","B"] + ["."] * 3]
result = result + [["."] * 3 + ["B","W"] + ["."] * 3]
for i in range(3):
result = result + [["."]*8]
return result
def printBoard(board):
""" Print a board, with letters and numbers as guides """
print " " + "".join(map(chr, range(ord('A'), ord('H') + 1)))
for (x,y) in zip(range(1,9), board):
print str(x) + "".join(y)
print("Black = %d, White = %d") % score(board)
# For fun, here is a one-line board printer, without the
# row and column labels
# print "\n".join(["".join(x) for x in board])
def gameOver(board):
""" return true if the game is over, that is, no valid moves """
return valid(board, "B", 'pass') and valid(board, "W", 'pass')
def score(board):
""" returns the current score for the board as a tuple
containing # of black pieces, # of white pieces """
black = white = 0
for row in board:
for square in row:
if (square == "B"):
black = black + 1
elif (square == "W"):
white = white + 1
return (black, white)
def playGame(p1, p2, verbose = False, t = 128):
""" Takes as input two functions p1 and p2 (each of which
calculates a next move given a board and player color),
and returns either a tuple containing the score for black,
score for white, and final board (for a normal game ending)
or a tuple containing the final score for black, final score
for white, and the invalid move (for a game that ends with
and invalid move """
board = newBoard()
(currColor, nextColor) = ("B", "W")
p1time = t
p2time = t
p1realTime = t*2
p2realTime = t*2
while not gameOver(board):
tmpBoard = deepcopy(board)
t1 = time.time()
nextMove = p1(tmpBoard, currColor, p1time)
t2 = time.time()
p1time = p1time - (t2 - t1)
p1realTime = p1realTime - (t2 - t1)
if (p1realTime < 0):
if currColor == "B":
return (0,64, board, "Timeout")
else:
return (64, 0, board, "Timeout")
if valid(board, currColor, nextMove):
doMove(board, currColor, nextMove)
else:
if currColor == "B":
return (0,64, board, "Bad Move: %s" %str(nextMove))
else:
return (64, 0, board, "Bad Move: %s" %str(nextMove))
(p1, p2) = (p2, p1)
(p1time, p2time) = (p2time, p1time)
(currColor, nextColor) = (nextColor, currColor)
if verbose:
printBoard(board)
print "Clock remaining: %s=%f, %s=%f" %(currColor, p1time, nextColor, p2time)
return score(board) + (board,)
if __name__ == "__main__":
try:
optlist,args=getopt.getopt(sys.argv[1:],'vt:r')
except getopt.error:
print "Usage: python %s {-r} {-v} {-t time} payer1 player2" % (sys.argv[0])
exit()
verbose = False
clockTime = 320.0
for (op,opVal) in optlist:
if (op == "-v"):
verbose = True
if (op == "-t"):
clockTime = float(opVal)
exec("from " + args[0] + " import nextMove")
p1 = nextMove
exec("from " + args[1] + " import nextMove")
p2 = nextMove
res = playGame(p1, p2, verbose, clockTime)
printBoard(res[2])
if ((res[0] > res[1]) and reversed != "R") or ((res[0] < res[1]) and reversed == "R"):
print "%s Wins %s Loses (%d to %d)" %(args[0], args[1], res[0], res[1]),
elif ((res[0] < res[1]) and reversed != "R") or ((res[0] > res[1]) and reversed == "R"):
print "%s Wins %s Loses (%d to %d)" %(args[1], args[0], res[1], res[0]),
else:
print "TIE %s, %s, (%d to %d)" % (args[1], args[0], res[1], res[0])
if (len(res) == 4):
print res[3]
else:
print ""