| import chess
|
| import chess.svg
|
| import pygame
|
| import engine
|
| from pygame import Vector2
|
| import move_finder
|
| from multiprocessing import Process,Queue
|
|
|
| move_width =200
|
| move_height=0
|
| width,height=512,512
|
| dimensions = 8
|
| sq_size = int(height/dimensions)
|
| max_fps=15
|
| images ={}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| '''
|
| load images in global dictionary .
|
| called exactly on the main
|
| '''
|
| def load_images():
|
| peices=['bQ','bK','bB','bN','bR','wQ','wK','wB','wN','wR','bp','wp']
|
| for peice in peices:
|
| images[peice] = pygame.transform.scale(pygame.image.load("./images/"+peice+".png"),(sq_size,sq_size))
|
|
|
|
|
|
|
| '''
|
| draw squares on board
|
| always top left square is white
|
| '''
|
| def draw_board(screen):
|
| global colors
|
| colors = [pygame.Color('white'),pygame.Color(194, 194, 194)]
|
| for r in range(dimensions):
|
| for c in range(dimensions):
|
| parity = (r+c) & 1
|
| color = colors[parity]
|
| pygame.draw.rect(screen,color,pygame.Rect(c*sq_size,r*sq_size,sq_size,sq_size))
|
|
|
|
|
| '''
|
| draw peices using current game state (board)
|
| '''
|
| def draw_peices(screen,board):
|
| for r in range(dimensions):
|
| for c in range(dimensions):
|
| peice = board[r][c]
|
| if peice !='--':
|
| screen.blit(images[peice],pygame.Rect(c*sq_size,r*sq_size,sq_size,sq_size))
|
|
|
| import pygame
|
|
|
| scroll_offset = 0
|
|
|
| def draw_move_log(screen, gs, width, move_width, height):
|
| global scroll_offset
|
| font = pygame.font.SysFont('Arial', 16, False, False)
|
| move_log_rect = pygame.Rect(width, 0, move_width, height)
|
|
|
|
|
| pygame.draw.rect(screen, pygame.Color('black'), move_log_rect)
|
|
|
| moves = gs.moveLog
|
| text_y = 5 - scroll_offset
|
|
|
| for j, i in enumerate(moves):
|
| text = f"{j+1}. {str(i)}"
|
| text_object = font.render(text, True, pygame.Color('white'))
|
| text_location = move_log_rect.move(5, text_y)
|
| screen.blit(text_object, text_location)
|
| text_y += text_object.get_height() + 5
|
|
|
|
|
| def handle_scroll(event):
|
| """Handles mouse wheel scrolling"""
|
| global scroll_offset
|
| if event.type == pygame.MOUSEBUTTONDOWN:
|
| if event.button == 4:
|
| scroll_offset = max(0, scroll_offset - 20)
|
| elif event.button == 5:
|
| scroll_offset += 20
|
|
|
|
|
| '''
|
| rensonsible for graphics in current game state
|
| '''
|
| def draw_game_state(screen,gs,valid_moves,sq_selected):
|
| draw_board(screen)
|
| high_light_squares(screen,gs,valid_moves,sq_selected)
|
| draw_peices(screen,gs.board)
|
| draw_move_log(screen,gs,512,200,512)
|
| '''
|
| hgihlight the square selected and moves for peices selected
|
| '''
|
|
|
| def high_light_squares(screen,gs,valid_moves,sqselected):
|
| if sqselected != ():
|
| r,c = sqselected
|
| if gs.board[r][c][0] == ('w' if gs.whiteToMove else 'b'):
|
|
|
|
|
| s = pygame.Surface((sq_size,sq_size))
|
|
|
| s.set_alpha(100)
|
| s.fill(pygame.Color('blue'))
|
| screen.blit(s,(c*sq_size,r*sq_size))
|
|
|
| s.fill(pygame.Color('red'))
|
|
|
| for move in valid_moves:
|
| if move.start_row == r and move.start_col==c:
|
| pygame.draw.circle(screen,pygame.Color(0,255,0),( int(sq_size*(move.end_col + 0.5)),int(sq_size*(move.end_row + 0.5))),7.5)
|
| if gs.board[move.end_row][move.end_col][0]== ('b' if gs.whiteToMove else 'w'):
|
| screen.blit(s,(sq_size*move.end_col,sq_size*move.end_row))
|
| if len(gs.moveLog)>=1:
|
| prev_move= gs.moveLog[-1]
|
| s.set_alpha(100)
|
| s.fill(pygame.Color('dark green'))
|
| r,c = prev_move.end_row,prev_move.end_col
|
| screen.blit(s,(c*sq_size,r*sq_size))
|
|
|
|
|
|
|
|
|
|
|
|
|
| def main():
|
| pygame.init()
|
| screen = pygame.display.set_mode((width+move_width,height+move_height))
|
| clock = pygame.time.Clock()
|
| screen.fill(pygame.Color('white'))
|
| gs = engine.GameState()
|
| load_images()
|
| running = True
|
| sqselected = ()
|
| player_clicks=[]
|
| valid_moves = gs.get_valid_moves()
|
| game_over=False
|
| player_one = True
|
| player_two = False
|
| ai_thinking = False
|
| move_finder_procee = None
|
| move_undone = False
|
| if len(valid_moves)<=5:
|
| for move in valid_moves:
|
| print(move.peice_captured ,move.peice_moved, move.id)
|
| move_made = False
|
|
|
| animate=False
|
| while running:
|
| human_Turn = (gs.whiteToMove and player_one) or (not gs.whiteToMove and player_two)
|
| for e in pygame.event.get():
|
|
|
| if e.type == pygame.QUIT:
|
| running=False
|
| elif e.type == pygame.MOUSEBUTTONDOWN:
|
| if not game_over and human_Turn:
|
| location =pygame.mouse.get_pos()
|
| col = int(location[0]//sq_size)
|
| row = int(location[1]//sq_size)
|
| if sqselected == (row,col) or col>=8:
|
| sqselected=()
|
| player_clicks=[]
|
| else:
|
| sqselected = (row,col)
|
| player_clicks.append(sqselected)
|
| if len(player_clicks)==2:
|
| move = engine.Move(player_clicks[0],player_clicks[1],gs.board)
|
| for i in range(len(valid_moves)):
|
| if move==valid_moves[i]:
|
| print("move taken",move.get_chess_notation(),"peice_moved:",gs.board[move.start_row][move.start_col])
|
| gs.make_move(valid_moves[i])
|
| move_made=True
|
| animate=True
|
| sqselected=()
|
| player_clicks=[]
|
| if not move_made:
|
| print("invalid_move",move.get_chess_notation(),move.peice_captured,move.peice_moved)
|
| player_clicks=[sqselected]
|
| if gs.check_mate or gs.steale_mate:
|
| running=False
|
|
|
|
|
| elif e.type == pygame.KEYDOWN:
|
| if e.key == pygame.K_z:
|
| gs.undo_move()
|
| move_made=True
|
| game_over=False
|
| if ai_thinking:
|
| move_find_process.terminate()
|
| ai_thinking=False
|
| move_undone=True
|
|
|
| elif e.key == pygame.K_r:
|
| gs = engine.GameState()
|
| valid_moves=gs.get_valid_moves()
|
| sqselected=()
|
| player_clicks=[]
|
| move_made=False
|
| animate=True
|
| game_over=False
|
| if ai_thinking:
|
| move_find_process.terminate()
|
| ai_thinking=False
|
| move_undone=True
|
|
|
|
|
| if not game_over and not human_Turn and not move_undone:
|
| if not ai_thinking:
|
| ai_thinking = True
|
| returnQueue = Queue()
|
| move_find_process = Process(target=move_finder.find_best_move,args=(gs,valid_moves,returnQueue))
|
|
|
| move_find_process.start()
|
| if not move_find_process.is_alive():
|
| print('done thinking')
|
| move = returnQueue.get()
|
| if move is None:
|
| move = move_finder.random_move(valid_moves)
|
| gs.make_move(move)
|
| move_made = True
|
| animate = True
|
| ai_thinking = False
|
| if move_made:
|
| valid_moves = gs.get_valid_moves()
|
| if animate:
|
| animateMove(gs.moveLog[-1],screen,gs.board,clock)
|
| animate=False
|
| print('valid_moves:',len(valid_moves))
|
| if len(valid_moves)<=5:
|
| for move in valid_moves:
|
| print(move.peice_captured ,move.peice_moved, move.move_id)
|
|
|
| move_made=False
|
| move_undone = False
|
|
|
| draw_game_state(screen,gs,valid_moves,sqselected)
|
| if gs.check_mate:
|
| game_over=True
|
| if gs.whiteToMove:
|
| draw_end_game_text(screen,'black wins by checkmate')
|
| else:
|
| draw_end_game_text(screen,"white wins by checkmate")
|
| elif gs.steale_mate:
|
| game_over=True
|
| draw_end_game_text(screen,'stealmate no moves for king and no check')
|
| clock.tick(max_fps)
|
| pygame.display.flip()
|
| from pygame.math import Vector2
|
|
|
| def animateMove(move, screen, board, clock):
|
| start = Vector2(move.start_col, move.start_row)
|
| end = Vector2(move.end_col, move.end_row)
|
| distance = end.distance_to(start)
|
| frames_per_sq = 10
|
| frame_count = int(distance * frames_per_sq)
|
|
|
| for frame in range(frame_count + 1):
|
| t = frame / frame_count
|
| current = start.lerp(end, t)
|
| c, r = current.x, current.y
|
|
|
| draw_board(screen)
|
| draw_peices(screen, board)
|
|
|
|
|
| colour = colors[(move.end_row + move.end_col) & 1]
|
| end_sq = pygame.Rect(move.end_col * sq_size, move.end_row * sq_size, sq_size, sq_size)
|
| pygame.draw.rect(screen, colour, end_sq)
|
|
|
|
|
| if move.peice_captured != '--':
|
| if move.is_empassant_move:
|
| screen.blit(images[move.peice_captured], end_sq)
|
| else:
|
| screen.blit(images[move.peice_captured], end_sq)
|
|
|
|
|
| screen.blit(images[move.peice_moved],
|
| pygame.Rect(c * sq_size, r * sq_size, sq_size, sq_size))
|
|
|
| pygame.display.flip()
|
| clock.tick(120)
|
|
|
| def draw_end_game_text(screen,text):
|
| font = pygame.font.SysFont('Helvitca',32,True,False)
|
| text_object = font.render(text,0,pygame.Color('Gray'))
|
| text_location = pygame.Rect(0,0,width,height).move(width/2,height/2)
|
| screen.blit(text_object,text_location)
|
| text_object = font.render(text,0,pygame.Color('Black'))
|
| screen.blit(text_object,text_location.move(2,2))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| if __name__=='__main__':
|
|
|
|
|
| main()
|
|
|
|
|
|
|
|
|
|
|
|
|