-
Notifications
You must be signed in to change notification settings - Fork 0
/
chess.py
155 lines (140 loc) · 5.35 KB
/
chess.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
from io import BufferedRandom, BufferedReader
from chessai import MinMaxPlayer, RandomPlayer, material_heuristic
from chesslogic import *
import random
import argparse
# Terminal interface
def text_to_coords(coords_str):
if len(coords_str) != 2:
raise ValueError(f"invalid coordinates {coords_str}")
letter_num = {}
for i, c in enumerate("abcdefgh"):
letter_num[c] = i
nums = "12345678"
letter, num = coords_str
if not letter in letter_num or not num in nums:
raise ValueError(f"invalid coordinates {coords_str}")
r, c = int(num) - 1, letter_num[letter]
return Coords(r, c)
def text_to_promotion(s):
return None if s is None else CHAR_PROMOTE[s]
# @return: Type of promotion piece chosen
# None to quit game
def ask_promote(board, file_moves):
print(board)
print("choose promotion piece (Q, R, B, N)")
while True:
try:
choice = file_moves.pop(0) if len(file_moves) > 0 else input()
if choice == "0":
return None
if choice not in list("QRBN"):
raise ValueError("invalid choice try again")
except ValueError as e:
print(e)
else:
return CHAR_PROMOTE[choice]
def end_game(game_status):
if game_status == BoardStatus.Check:
print("check")
if game_status == BoardStatus.Checkmate:
print("checkmate")
elif game_status == BoardStatus.Stalemate:
print("stalemate")
return (game_status == BoardStatus.Checkmate or
game_status == BoardStatus.Stalemate
)
if __name__=="__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--test", help="path to test file")
parser.add_argument("-ai", "--ai", help="play against AI: r - random"
"m - minmax"
)
parser.add_argument("-d", "--depth", default=1, help="depth for recursive"
"algorithms should be 1 or more (default 1)"
)
parser.add_argument("-c", "--color",
help="color of human player: b - black, w - white"
)
print(INTRO)
print("move: 'e2 e4' or 'a7 a8 Q' revert: 'r' exit: '0'")
print("help: 'python chess.py -h'")
args = parser.parse_args()
board = Board()
computer_turn = False if board.white_turn else True
ai_player = None
if args.ai:
if args.color == "b" or args.color == "black":
# TODO rewrite this to go according to current state
computer_turn = True if board.white_turn else False
if args.ai == "r" or args.ai == "random":
ai_player = RandomPlayer(board, False)
if args.ai == "m" or args.ai == "minmax":
# TODO here add choice of heuristic as well
ai_player = MinMaxPlayer(board, computer_turn, material_heuristic,
depth = int(args.depth))
moves_input = []
if args.test:
with open(args.test) as f:
for line in f:
print(line)
moves_input.append(line.strip())
# TODO refactor this
print(board)
while True:
if ai_player and ai_player.is_white == board.white_turn:
# TODO change so AI plays and returns status and move
move = ai_player.get_ai_move()
try:
origin, target, promotion = move
game_status = board.move_piece(origin, target, promotion)
print(board)
if end_game(game_status):
break
except Exception as e:
print(e)
continue
else:
print("enter move")
move_input = moves_input.pop(0) if len(moves_input) > 0 else input()
if move_input == 'r':
try:
board.revert_last_move()
# TODO differnetiate if black or white
if ai_player:
board.revert_last_move()
except Exception as e:
print(e)
finally:
print(board)
continue
if move_input == '0':
break
try:
start, end, promote_choice = None, None, None
move_split = move_input.split(" ")
if len(move_split) == 2:
start, end = move_split
elif len(move_split) == 3:
start, end, promote_choice = move_split
else:
# TODO return this for any invalid input
print("invalid move. try again.")
continue
origin = text_to_coords(start)
target = text_to_coords(end)
promotion = text_to_promotion(promote_choice)
game_status = board.move_piece(origin, target, promotion)
print(board)
if end_game(game_status):
break
except MissingPromotionChoice as e:
promotion = ask_promote(board, moves_input)
if promotion == None:
break
game_status = board.move_piece(origin, target, promotion)
print(board)
if end_game(game_status):
break
except ValueError as e:
print(e)