Created
October 12, 2018 22:38
-
-
Save MikeTheWatchGuy/51627f68dd4f3fd52a5dba9904c24a4b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import PySimpleGUI as sg | |
import os | |
import chess | |
import chess.pgn | |
import copy | |
import time | |
button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer') | |
CHESS_PATH = '.' # path to the chess pieces | |
BLANK = 0 # piece names | |
PAWNB = 1 | |
KNIGHTB = 2 | |
BISHOPB = 3 | |
ROOKB = 4 | |
KINGB = 5 | |
QUEENB = 6 | |
PAWNW = 7 | |
KNIGHTW = 8 | |
BISHOPW = 9 | |
ROOKW = 10 | |
KINGW = 11 | |
QUEENW = 12 | |
initial_board = [[ROOKB, KNIGHTB, BISHOPB, KINGB, QUEENB, BISHOPB, KNIGHTB, ROOKB ], | |
[PAWNB,]*8, | |
[BLANK,]*8, | |
[BLANK,]*8, | |
[BLANK,]*8, | |
[BLANK,]*8, | |
[PAWNW,]*8, | |
[ROOKW, KNIGHTW, BISHOPW, KINGW, QUEENW, BISHOPW, KNIGHTW, ROOKW]] | |
blank = os.path.join(CHESS_PATH, 'blank.png') | |
bishopB = os.path.join(CHESS_PATH, 'nbishopb.png') | |
bishopW = os.path.join(CHESS_PATH, 'nbishopw.png') | |
pawnB = os.path.join(CHESS_PATH, 'npawnb.png') | |
pawnW = os.path.join(CHESS_PATH, 'npawnw.png') | |
knightB = os.path.join(CHESS_PATH, 'nknightb.png') | |
knightW = os.path.join(CHESS_PATH, 'nknightw.png') | |
rookB = os.path.join(CHESS_PATH, 'nrookb.png') | |
rookW = os.path.join(CHESS_PATH, 'nrookw.png') | |
queenB = os.path.join(CHESS_PATH, 'nqueenb.png') | |
queenW = os.path.join(CHESS_PATH, 'nqueenw.png') | |
kingB = os.path.join(CHESS_PATH, 'nkingb.png') | |
kingW = os.path.join(CHESS_PATH, 'nkingw.png') | |
images = {BISHOPB: bishopB, BISHOPW: bishopW, PAWNB: pawnB, PAWNW: pawnW, KNIGHTB: knightB, KNIGHTW: knightW, | |
ROOKB: rookB, ROOKW: rookW, KINGB: kingB, KINGW: kingW, QUEENB: queenB, QUEENW: queenW, BLANK: blank} | |
def open_pgn_file(filename): | |
pgn = open(filename) | |
first_game = chess.pgn.read_game(pgn) | |
moves = [move for move in first_game.main_line()] | |
return moves | |
def render_square(image, key, location): | |
if (location[0] + location[1]) % 2: | |
color = '#B58863' | |
else: | |
color = '#F0D9B5' | |
return sg.RButton('', image_filename=image, size=(1, 1), button_color=('white', color), pad=(0, 0), key=key) | |
def redraw_board(window, board): | |
for i in range(8): | |
for j in range(8): | |
color = '#B58863' if (i+j) % 2 else '#F0D9B5' | |
piece_image = images[board[i][j]] | |
elem = window.FindElement(key=(i,j)) | |
elem.Update(button_color = ('white', color), | |
image_filename=piece_image,) | |
def PlayGame(): | |
menu_def = [['&File', ['&Open PGN File', 'E&xit' ]], | |
['&Help', '&About...'],] | |
# sg.SetOptions(margins=(0,0)) | |
sg.ChangeLookAndFeel('GreenTan') | |
# create initial board setup | |
board = copy.deepcopy(initial_board) | |
# the main board display layout | |
board_layout = [[sg.T(' ')] + [sg.T('{}'.format(a), pad=((23,27),0), font='Any 13') for a in 'abcdefgh']] | |
# loop though board and create buttons with images | |
for i in range(8): | |
row = [sg.T(str(8-i)+' ', font='Any 13')] | |
for j in range(8): | |
piece_image = images[board[i][j]] | |
row.append(render_square(piece_image, key=(i,j), location=(i,j))) | |
row.append(sg.T(str(8-i)+' ', font='Any 13')) | |
board_layout.append(row) | |
# add the labels across bottom of board | |
board_layout.append([sg.T(' ')] + [sg.T('{}'.format(a), pad=((23,27),0), font='Any 13') for a in 'abcdefgh']) | |
# setup the controls on the right side of screen | |
openings = ('Any', 'Defense', 'Attack', 'Trap', 'Gambit','Counter', 'Sicillian', 'English','French', 'Queen\'s openings', 'King\'s Openings','Indian Openings') | |
board_controls = [[sg.RButton('New Game', key='Open PGN File'), sg.RButton('Draw')], | |
[sg.RButton('Resign Game'), sg.RButton('Set FEN')], | |
[sg.RButton('Player Odds'),sg.RButton('Training') ], | |
[sg.Drop(openings),sg.Text('Opening/Style')], | |
[sg.CBox('Play a White', key='_white_')], | |
[sg.Text('Move List')], | |
[sg.Multiline([], do_not_clear=True, autoscroll=True, size=(15,10),key='_movelist_')],] | |
# layouts for the tabs | |
controls_layout = [[sg.Text('Performance Parameters', font='_ 20')], | |
[sg.T('Put stuff like AI engine tuning parms on this tab')]] | |
statistics_layout = [[sg.Text('Statistics', font=('_ 20'))], | |
[sg.T('Game statistics go here?')]] | |
board_tab = [[sg.Column(board_layout)]] | |
# the main window layout | |
layout = [[sg.Menu(menu_def, tearoff=False)], | |
[sg.TabGroup([[sg.Tab('Board',board_tab), | |
sg.Tab('Controls', controls_layout), | |
sg.Tab('Statistics', statistics_layout)]], title_color='red'), | |
sg.Column(board_controls)], | |
[sg.Text('Click anywhere on board for next move', font='_ 14')]] | |
window = sg.Window('Chess', default_button_element_size=(12,1), auto_size_buttons=False, icon='kingb.ico').Layout(layout) | |
# ---===--- Loop taking in user input --- # | |
i = 0 | |
moves = None | |
while True: | |
button, value = window.Read() | |
if button in (None, 'Exit'): | |
break | |
if button == 'Open PGN File': | |
filename = sg.PopupGetFile('', no_window=True) | |
if filename is not None: | |
moves = open_pgn_file(filename) | |
i = 0 | |
board = copy.deepcopy(initial_board) | |
window.FindElement('_movelist_').Update(value='') | |
if button == 'About...': | |
sg.Popup('Powerd by Engine Kibitz Chess Engine') | |
if type(button) is tuple and moves is not None and i < len(moves): | |
move = moves[i] # get the current move | |
window.FindElement('_movelist_').Update(value='{} {}\n'.format(i+1, str(move)), append=True) | |
move_from = move.from_square # parse the move-from and move-to squares | |
move_to = move.to_square | |
row, col = move_from // 8, move_from % 8 | |
piece = board[row][col] # get the move-from piece | |
button = window.FindElement(key=(row,col)) | |
for x in range(3): | |
button.Update(button_color = ('white' , 'red' if x % 2 else 'white')) | |
window.Refresh() | |
time.sleep(.05) | |
board[row][col] = BLANK # place blank where piece was | |
row, col = move_to // 8, move_to % 8 # compute move-to square | |
board[row][col] = piece # place piece in the move-to square | |
redraw_board(window, board) | |
i += 1 | |
PlayGame() |
Why is castling not working? Here's a sequence of moves that shows long castling not working:
e2e4
d7d5
e4d5
d8d5
b1c3
d5e6
d1e2
c7c6
d2d3
e6e2
f1e2
b8d7
c1d2
g7g6
e1c1
Although the king moves from e1 to c1, the rook doesn't move from a1 to d1.
Here's a sequence of moves that shows short castling not working:
e2e4
d7d5
e4d5
d8d5
g1f3
e7e5
f1e2
e5e4
e1g1
Again, the king moves from e1 to g1, but the rook doesn't move from h1 to f1.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Requires Python 3
To get the entire program and graphic images, install using:
pip install pysimplegui-chess
if you're on Linux that means:
pip3 install pysimplegui-chess
The pip install will put the code in your site packages, so be prepared to go hunting for it.
Or, you can go to the GitHub and download the folder named 'Chess'. You will need to do a pip install of python-chess if you download the folder.