Spaces:
Sleeping
Sleeping
File size: 12,552 Bytes
4d66e9d |
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 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
import chess
import chess.svg
import pygame
import engine
from pygame import Vector2
import move_finder
from multiprocessing import Process,Queue
from final import get_board
move_width =200
move_height=0
width,height=512,512 #can be 768,768
dimensions = 8 #chess board is 64 squares
sq_size = int(height/dimensions)
max_fps=15
images ={}
#load images
#loading image sis very expensive so load only once per game
# board = chess.Board('rnbqkbnr/8/8/8/8/8/8/8')
# svg = chess.svg.board(board)
# make engine that recognize legal chess move or not
#hopefully 2 player game
# with open('b.svg', 'w', encoding="utf-8") as f:
# f.write(svg)
'''
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)) #cenetr peice nicely
# we can access an peice by calling image['wp] we added them in the dictionary
'''
draw squares on board
always top left square is white
'''
def draw_board(screen):
global colors #so that we can use them globally
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 # global scroll variable
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)
# Draw background
pygame.draw.rect(screen, pygame.Color('black'), move_log_rect)
moves = gs.moveLog
text_y = 5 - scroll_offset # apply scroll offset here
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 up
scroll_offset = max(0, scroll_offset - 20)
elif event.button == 5: # scroll down
scroll_offset += 20
'''
rensonsible for graphics in current game state
'''
def draw_game_state(screen,gs,valid_moves,sq_selected):
draw_board(screen) #draw squares on board
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'): #sq selected is a peice
# highlight selected square
# use surface
s = pygame.Surface((sq_size,sq_size))
s.set_alpha(100) # transparent
s.fill(pygame.Color('blue'))
screen.blit(s,(c*sq_size,r*sq_size))
# highlist moves from that square
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) # transparent
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))
#what the board does is redraw images when u move
#animation is simply slow the change such that u see every frame
def main():
pygame.init()
screen = pygame.display.set_mode((width+move_width,height+move_height))
clock = pygame.time.Clock() #clock
screen.fill(pygame.Color('white'))
gs = engine.GameState() #create a game state and craete variables
load_images() # load only once before whilw
running = True
sqselected = ()
player_clicks=[] #two squares of player clicks
valid_moves = gs.get_valid_moves()
game_over=False
player_one = True # white true , machine is playing false
player_two = False # similarly but for player two
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 #until the valid move we need not generate valid moves
# make ui changes
animate=False
while running:
human_Turn = (gs.whiteToMove and player_one) or (not gs.whiteToMove and player_two)
for e in pygame.event.get():
#mouse handler
if e.type == pygame.QUIT:
running=False
elif e.type == pygame.MOUSEBUTTONDOWN:
if not game_over and human_Turn:
location =pygame.mouse.get_pos() #location of mouse
col = int(location[0]//sq_size)
row = int(location[1]//sq_size)
if sqselected == (row,col) or col>=8: #user click same square then unmove
sqselected=()
player_clicks=[]
else:
sqselected = (row,col)
player_clicks.append(sqselected) # append for both first and second cicks
if len(player_clicks)==2: #after the second click
move = engine.Move(player_clicks[0],player_clicks[1],gs.board)
for i in range(len(valid_moves)):
if move==valid_moves[i]:#move is pretty cheap
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] #after move is doen reset squares
if gs.check_mate or gs.steale_mate:
running=False
#keyboard handlers
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
#reset the board
# best moves
if not game_over and not human_Turn and not move_undone:
if not ai_thinking:
ai_thinking = True # threads wont share data
returnQueue = Queue() # used to pass data between threads
move_find_process = Process(target=move_finder.find_best_move,args=(gs,valid_moves,returnQueue)) # passing function as parameter
move_find_process.start() #creates new thread without waiting this code tun
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) #add mouse hnadlers
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 # in [0, 1]
current = start.lerp(end, t) # linear interpolation
c, r = current.x, current.y
draw_board(screen)
draw_peices(screen, board)
# erase ending square
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)
# draw captured piece if any
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)
# draw moving piece at interpolated position
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))
def get_moves(image_path):
board,fen = get_board(image_path)
gs= engine.GameState(board)
moves = move_finder.get_best_n_moves(gs)
gs = engine.GameState(board)
gs.whiteToMove = not gs.whiteToMove
moves2 = move_finder.get_best_n_moves(gs)
colour = ('white_moves','black_moves') if not gs.whiteToMove else ('black_moves','white_moves')
return fen, {colour[0]:moves,colour[1]:moves2}
if __name__=='__main__':
#handle and update graphics and input
#whenever u import this module else where this wont run this fucntion
#main()
get_moves('./image.png')
|