├── additions.py ├── assets └── images │ ├── black bishop.png │ ├── black king.png │ ├── black knight.png │ ├── black pawn.png │ ├── black queen.png │ ├── black rook.png │ ├── white bishop.png │ ├── white king.png │ ├── white knight.png │ ├── white pawn.png │ ├── white queen.png │ └── white rook.png ├── constants.py └── main.py /additions.py: -------------------------------------------------------------------------------- 1 | # two player chess in python with Pygame! 2 | # pawn double space checking 3 | # castling 4 | # en passant 5 | # pawn promotion 6 | 7 | import pygame 8 | from constants import * 9 | 10 | pygame.init() 11 | 12 | 13 | # draw main game board 14 | def draw_board(): 15 | for i in range(32): 16 | column = i % 4 17 | row = i // 4 18 | if row % 2 == 0: 19 | pygame.draw.rect(screen, 'light gray', [600 - (column * 200), row * 100, 100, 100]) 20 | else: 21 | pygame.draw.rect(screen, 'light gray', [700 - (column * 200), row * 100, 100, 100]) 22 | pygame.draw.rect(screen, 'gray', [0, 800, WIDTH, 100]) 23 | pygame.draw.rect(screen, 'gold', [0, 800, WIDTH, 100], 5) 24 | pygame.draw.rect(screen, 'gold', [800, 0, 200, HEIGHT], 5) 25 | status_text = ['White: Select a Piece to Move!', 'White: Select a Destination!', 26 | 'Black: Select a Piece to Move!', 'Black: Select a Destination!'] 27 | screen.blit(big_font.render(status_text[turn_step], True, 'black'), (20, 820)) 28 | for i in range(9): 29 | pygame.draw.line(screen, 'black', (0, 100 * i), (800, 100 * i), 2) 30 | pygame.draw.line(screen, 'black', (100 * i, 0), (100 * i, 800), 2) 31 | screen.blit(medium_font.render('FORFEIT', True, 'black'), (810, 830)) 32 | if white_promote or black_promote: 33 | pygame.draw.rect(screen, 'gray', [0, 800, WIDTH - 200, 100]) 34 | pygame.draw.rect(screen, 'gold', [0, 800, WIDTH - 200, 100], 5) 35 | screen.blit(big_font.render('Select Piece to Promote Pawn', True, 'black'), (20, 820)) 36 | 37 | 38 | # draw pieces onto board 39 | def draw_pieces(): 40 | for i in range(len(white_pieces)): 41 | index = piece_list.index(white_pieces[i]) 42 | if white_pieces[i] == 'pawn': 43 | screen.blit(white_pawn, (white_locations[i][0] * 100 + 22, white_locations[i][1] * 100 + 30)) 44 | else: 45 | screen.blit(white_images[index], (white_locations[i][0] * 100 + 10, white_locations[i][1] * 100 + 10)) 46 | if turn_step < 2: 47 | if selection == i: 48 | pygame.draw.rect(screen, 'red', [white_locations[i][0] * 100 + 1, white_locations[i][1] * 100 + 1, 49 | 100, 100], 2) 50 | 51 | for i in range(len(black_pieces)): 52 | index = piece_list.index(black_pieces[i]) 53 | if black_pieces[i] == 'pawn': 54 | screen.blit(black_pawn, (black_locations[i][0] * 100 + 22, black_locations[i][1] * 100 + 30)) 55 | else: 56 | screen.blit(black_images[index], (black_locations[i][0] * 100 + 10, black_locations[i][1] * 100 + 10)) 57 | if turn_step >= 2: 58 | if selection == i: 59 | pygame.draw.rect(screen, 'blue', [black_locations[i][0] * 100 + 1, black_locations[i][1] * 100 + 1, 60 | 100, 100], 2) 61 | 62 | 63 | # function to check all pieces valid options on board 64 | def check_options(pieces, locations, turn): 65 | global castling_moves 66 | moves_list = [] 67 | all_moves_list = [] 68 | castling_moves = [] 69 | for i in range((len(pieces))): 70 | location = locations[i] 71 | piece = pieces[i] 72 | if piece == 'pawn': 73 | moves_list = check_pawn(location, turn) 74 | elif piece == 'rook': 75 | moves_list = check_rook(location, turn) 76 | elif piece == 'knight': 77 | moves_list = check_knight(location, turn) 78 | elif piece == 'bishop': 79 | moves_list = check_bishop(location, turn) 80 | elif piece == 'queen': 81 | moves_list = check_queen(location, turn) 82 | elif piece == 'king': 83 | moves_list, castling_moves = check_king(location, turn) 84 | all_moves_list.append(moves_list) 85 | return all_moves_list 86 | 87 | 88 | # check king valid moves 89 | def check_king(position, color): 90 | moves_list = [] 91 | castle_moves = check_castling() 92 | if color == 'white': 93 | enemies_list = black_locations 94 | friends_list = white_locations 95 | else: 96 | friends_list = black_locations 97 | enemies_list = white_locations 98 | # 8 squares to check for kings, they can go one square any direction 99 | targets = [(1, 0), (1, 1), (1, -1), (-1, 0), (-1, 1), (-1, -1), (0, 1), (0, -1)] 100 | for i in range(8): 101 | target = (position[0] + targets[i][0], position[1] + targets[i][1]) 102 | if target not in friends_list and 0 <= target[0] <= 7 and 0 <= target[1] <= 7: 103 | moves_list.append(target) 104 | return moves_list, castle_moves 105 | 106 | 107 | # check queen valid moves 108 | def check_queen(position, color): 109 | moves_list = check_bishop(position, color) 110 | second_list = check_rook(position, color) 111 | for i in range(len(second_list)): 112 | moves_list.append(second_list[i]) 113 | return moves_list 114 | 115 | 116 | # check bishop moves 117 | def check_bishop(position, color): 118 | moves_list = [] 119 | if color == 'white': 120 | enemies_list = black_locations 121 | friends_list = white_locations 122 | else: 123 | friends_list = black_locations 124 | enemies_list = white_locations 125 | for i in range(4): # up-right, up-left, down-right, down-left 126 | path = True 127 | chain = 1 128 | if i == 0: 129 | x = 1 130 | y = -1 131 | elif i == 1: 132 | x = -1 133 | y = -1 134 | elif i == 2: 135 | x = 1 136 | y = 1 137 | else: 138 | x = -1 139 | y = 1 140 | while path: 141 | if (position[0] + (chain * x), position[1] + (chain * y)) not in friends_list and \ 142 | 0 <= position[0] + (chain * x) <= 7 and 0 <= position[1] + (chain * y) <= 7: 143 | moves_list.append((position[0] + (chain * x), position[1] + (chain * y))) 144 | if (position[0] + (chain * x), position[1] + (chain * y)) in enemies_list: 145 | path = False 146 | chain += 1 147 | else: 148 | path = False 149 | return moves_list 150 | 151 | 152 | # check rook moves 153 | def check_rook(position, color): 154 | moves_list = [] 155 | if color == 'white': 156 | enemies_list = black_locations 157 | friends_list = white_locations 158 | else: 159 | friends_list = black_locations 160 | enemies_list = white_locations 161 | for i in range(4): # down, up, right, left 162 | path = True 163 | chain = 1 164 | if i == 0: 165 | x = 0 166 | y = 1 167 | elif i == 1: 168 | x = 0 169 | y = -1 170 | elif i == 2: 171 | x = 1 172 | y = 0 173 | else: 174 | x = -1 175 | y = 0 176 | while path: 177 | if (position[0] + (chain * x), position[1] + (chain * y)) not in friends_list and \ 178 | 0 <= position[0] + (chain * x) <= 7 and 0 <= position[1] + (chain * y) <= 7: 179 | moves_list.append((position[0] + (chain * x), position[1] + (chain * y))) 180 | if (position[0] + (chain * x), position[1] + (chain * y)) in enemies_list: 181 | path = False 182 | chain += 1 183 | else: 184 | path = False 185 | return moves_list 186 | 187 | 188 | # check valid pawn moves 189 | def check_pawn(position, color): 190 | moves_list = [] 191 | if color == 'white': 192 | if (position[0], position[1] + 1) not in white_locations and \ 193 | (position[0], position[1] + 1) not in black_locations and position[1] < 7: 194 | moves_list.append((position[0], position[1] + 1)) 195 | # indent the check for two spaces ahead, so it is only checked if one space ahead is also open 196 | if (position[0], position[1] + 2) not in white_locations and \ 197 | (position[0], position[1] + 2) not in black_locations and position[1] == 1: 198 | moves_list.append((position[0], position[1] + 2)) 199 | if (position[0] + 1, position[1] + 1) in black_locations: 200 | moves_list.append((position[0] + 1, position[1] + 1)) 201 | if (position[0] - 1, position[1] + 1) in black_locations: 202 | moves_list.append((position[0] - 1, position[1] + 1)) 203 | # add en passant move checker 204 | if (position[0] + 1, position[1] + 1) == black_ep: 205 | moves_list.append((position[0] + 1, position[1] + 1)) 206 | if (position[0] - 1, position[1] + 1) == black_ep: 207 | moves_list.append((position[0] - 1, position[1] + 1)) 208 | else: 209 | if (position[0], position[1] - 1) not in white_locations and \ 210 | (position[0], position[1] - 1) not in black_locations and position[1] > 0: 211 | moves_list.append((position[0], position[1] - 1)) 212 | # indent the check for two spaces ahead, so it is only checked if one space ahead is also open 213 | if (position[0], position[1] - 2) not in white_locations and \ 214 | (position[0], position[1] - 2) not in black_locations and position[1] == 6: 215 | moves_list.append((position[0], position[1] - 2)) 216 | if (position[0] + 1, position[1] - 1) in white_locations: 217 | moves_list.append((position[0] + 1, position[1] - 1)) 218 | if (position[0] - 1, position[1] - 1) in white_locations: 219 | moves_list.append((position[0] - 1, position[1] - 1)) 220 | # add en passant move checker 221 | if (position[0] + 1, position[1] - 1) == white_ep: 222 | moves_list.append((position[0] + 1, position[1] - 1)) 223 | if (position[0] - 1, position[1] - 1) == white_ep: 224 | moves_list.append((position[0] - 1, position[1] - 1)) 225 | return moves_list 226 | 227 | 228 | # check valid knight moves 229 | def check_knight(position, color): 230 | moves_list = [] 231 | if color == 'white': 232 | enemies_list = black_locations 233 | friends_list = white_locations 234 | else: 235 | friends_list = black_locations 236 | enemies_list = white_locations 237 | # 8 squares to check for knights, they can go two squares in one direction and one in another 238 | targets = [(1, 2), (1, -2), (2, 1), (2, -1), (-1, 2), (-1, -2), (-2, 1), (-2, -1)] 239 | for i in range(8): 240 | target = (position[0] + targets[i][0], position[1] + targets[i][1]) 241 | if target not in friends_list and 0 <= target[0] <= 7 and 0 <= target[1] <= 7: 242 | moves_list.append(target) 243 | return moves_list 244 | 245 | 246 | # check for valid moves for just selected piece 247 | def check_valid_moves(): 248 | if turn_step < 2: 249 | options_list = white_options 250 | else: 251 | options_list = black_options 252 | valid_options = options_list[selection] 253 | return valid_options 254 | 255 | 256 | # draw valid moves on screen 257 | def draw_valid(moves): 258 | if turn_step < 2: 259 | color = 'red' 260 | else: 261 | color = 'blue' 262 | for i in range(len(moves)): 263 | pygame.draw.circle(screen, color, (moves[i][0] * 100 + 50, moves[i][1] * 100 + 50), 5) 264 | 265 | 266 | # draw captured pieces on side of screen 267 | def draw_captured(): 268 | for i in range(len(captured_pieces_white)): 269 | captured_piece = captured_pieces_white[i] 270 | index = piece_list.index(captured_piece) 271 | screen.blit(small_black_images[index], (825, 5 + 50 * i)) 272 | for i in range(len(captured_pieces_black)): 273 | captured_piece = captured_pieces_black[i] 274 | index = piece_list.index(captured_piece) 275 | screen.blit(small_white_images[index], (925, 5 + 50 * i)) 276 | 277 | 278 | # draw a flashing square around king if in check 279 | def draw_check(): 280 | global check 281 | check = False 282 | if turn_step < 2: 283 | if 'king' in white_pieces: 284 | king_index = white_pieces.index('king') 285 | king_location = white_locations[king_index] 286 | for i in range(len(black_options)): 287 | if king_location in black_options[i]: 288 | check = True 289 | if counter < 15: 290 | pygame.draw.rect(screen, 'dark red', [white_locations[king_index][0] * 100 + 1, 291 | white_locations[king_index][1] * 100 + 1, 100, 100], 5) 292 | else: 293 | if 'king' in black_pieces: 294 | king_index = black_pieces.index('king') 295 | king_location = black_locations[king_index] 296 | for i in range(len(white_options)): 297 | if king_location in white_options[i]: 298 | check = True 299 | if counter < 15: 300 | pygame.draw.rect(screen, 'dark blue', [black_locations[king_index][0] * 100 + 1, 301 | black_locations[king_index][1] * 100 + 1, 100, 100], 5) 302 | 303 | 304 | def draw_game_over(): 305 | pygame.draw.rect(screen, 'black', [200, 200, 400, 70]) 306 | screen.blit(font.render(f'{winner} won the game!', True, 'white'), (210, 210)) 307 | screen.blit(font.render(f'Press ENTER to Restart!', True, 'white'), (210, 240)) 308 | 309 | 310 | # check en passant because people on the internet won't stop bugging me for it 311 | def check_ep(old_coords, new_coords): 312 | if turn_step <= 1: 313 | index = white_locations.index(old_coords) 314 | ep_coords = (new_coords[0], new_coords[1] - 1) 315 | piece = white_pieces[index] 316 | else: 317 | index = black_locations.index(old_coords) 318 | ep_coords = (new_coords[0], new_coords[1] + 1) 319 | piece = black_pieces[index] 320 | if piece == 'pawn' and abs(old_coords[1] - new_coords[1]) > 1: 321 | # if piece was pawn and moved two spaces, return EP coords as defined above 322 | pass 323 | else: 324 | ep_coords = (100, 100) 325 | return ep_coords 326 | 327 | 328 | # add castling 329 | def check_castling(): 330 | # king must not currently be in check, neither the rook nor king has moved previously, nothing between 331 | # and the king does not pass through or finish on an attacked piece 332 | castle_moves = [] # store each valid castle move as [((king_coords), (castle_coords))] 333 | rook_indexes = [] 334 | rook_locations = [] 335 | king_index = 0 336 | king_pos = (0, 0) 337 | if turn_step > 1: 338 | for i in range(len(white_pieces)): 339 | if white_pieces[i] == 'rook': 340 | rook_indexes.append(white_moved[i]) 341 | rook_locations.append(white_locations[i]) 342 | if white_pieces[i] == 'king': 343 | king_index = i 344 | king_pos = white_locations[i] 345 | if not white_moved[king_index] and False in rook_indexes and not check: 346 | for i in range(len(rook_indexes)): 347 | castle = True 348 | if rook_locations[i][0] > king_pos[0]: 349 | empty_squares = [(king_pos[0] + 1, king_pos[1]), (king_pos[0] + 2, king_pos[1]), 350 | (king_pos[0] + 3, king_pos[1])] 351 | else: 352 | empty_squares = [(king_pos[0] - 1, king_pos[1]), (king_pos[0] - 2, king_pos[1])] 353 | for j in range(len(empty_squares)): 354 | if empty_squares[j] in white_locations or empty_squares[j] in black_locations or \ 355 | empty_squares[j] in black_options or rook_indexes[i]: 356 | castle = False 357 | if castle: 358 | castle_moves.append((empty_squares[1], empty_squares[0])) 359 | else: 360 | for i in range(len(black_pieces)): 361 | if black_pieces[i] == 'rook': 362 | rook_indexes.append(black_moved[i]) 363 | rook_locations.append(black_locations[i]) 364 | if black_pieces[i] == 'king': 365 | king_index = i 366 | king_pos = black_locations[i] 367 | if not black_moved[king_index] and False in rook_indexes and not check: 368 | for i in range(len(rook_indexes)): 369 | castle = True 370 | if rook_locations[i][0] > king_pos[0]: 371 | empty_squares = [(king_pos[0] + 1, king_pos[1]), (king_pos[0] + 2, king_pos[1]), 372 | (king_pos[0] + 3, king_pos[1])] 373 | else: 374 | empty_squares = [(king_pos[0] - 1, king_pos[1]), (king_pos[0] - 2, king_pos[1])] 375 | for j in range(len(empty_squares)): 376 | if empty_squares[j] in white_locations or empty_squares[j] in black_locations or \ 377 | empty_squares[j] in white_options or rook_indexes[i]: 378 | castle = False 379 | if castle: 380 | castle_moves.append((empty_squares[1], empty_squares[0])) 381 | return castle_moves 382 | 383 | 384 | def draw_castling(moves): 385 | if turn_step < 2: 386 | color = 'red' 387 | else: 388 | color = 'blue' 389 | for i in range(len(moves)): 390 | pygame.draw.circle(screen, color, (moves[i][0][0] * 100 + 50, moves[i][0][1] * 100 + 70), 8) 391 | screen.blit(font.render('king', True, 'black'), (moves[i][0][0] * 100 + 30, moves[i][0][1] * 100 + 70)) 392 | pygame.draw.circle(screen, color, (moves[i][1][0] * 100 + 50, moves[i][1][1] * 100 + 70), 8) 393 | screen.blit(font.render('rook', True, 'black'), 394 | (moves[i][1][0] * 100 + 30, moves[i][1][1] * 100 + 70)) 395 | pygame.draw.line(screen, color, (moves[i][0][0] * 100 + 50, moves[i][0][1] * 100 + 70), 396 | (moves[i][1][0] * 100 + 50, moves[i][1][1] * 100 + 70), 2) 397 | 398 | 399 | # add pawn promotion 400 | def check_promotion(): 401 | pawn_indexes = [] 402 | white_promotion = False 403 | black_promotion = False 404 | promote_index = 100 405 | for i in range(len(white_pieces)): 406 | if white_pieces[i] == 'pawn': 407 | pawn_indexes.append(i) 408 | for i in range(len(pawn_indexes)): 409 | if white_locations[pawn_indexes[i]][1] == 7: 410 | white_promotion = True 411 | promote_index = pawn_indexes[i] 412 | pawn_indexes = [] 413 | for i in range(len(black_pieces)): 414 | if black_pieces[i] == 'pawn': 415 | pawn_indexes.append(i) 416 | for i in range(len(pawn_indexes)): 417 | if black_locations[pawn_indexes[i]][1] == 0: 418 | black_promotion = True 419 | promote_index = pawn_indexes[i] 420 | return white_promotion, black_promotion, promote_index 421 | 422 | 423 | def draw_promotion(): 424 | pygame.draw.rect(screen, 'dark gray', [800, 0, 200, 420]) 425 | if white_promote: 426 | color = 'white' 427 | for i in range(len(white_promotions)): 428 | piece = white_promotions[i] 429 | index = piece_list.index(piece) 430 | screen.blit(white_images[index], (860, 5 + 100 * i)) 431 | elif black_promote: 432 | color = 'black' 433 | for i in range(len(black_promotions)): 434 | piece = black_promotions[i] 435 | index = piece_list.index(piece) 436 | screen.blit(black_images[index], (860, 5 + 100 * i)) 437 | pygame.draw.rect(screen, color, [800, 0, 200, 420], 8) 438 | 439 | 440 | def check_promo_select(): 441 | mouse_pos = pygame.mouse.get_pos() 442 | left_click = pygame.mouse.get_pressed()[0] 443 | x_pos = mouse_pos[0] // 100 444 | y_pos = mouse_pos[1] // 100 445 | if white_promote and left_click and x_pos > 7 and y_pos < 4: 446 | white_pieces[promo_index] = white_promotions[y_pos] 447 | elif black_promote and left_click and x_pos > 7 and y_pos < 4: 448 | black_pieces[promo_index] = black_promotions[y_pos] 449 | 450 | 451 | # main game loop 452 | black_options = check_options(black_pieces, black_locations, 'black') 453 | white_options = check_options(white_pieces, white_locations, 'white') 454 | run = True 455 | while run: 456 | timer.tick(fps) 457 | if counter < 30: 458 | counter += 1 459 | else: 460 | counter = 0 461 | screen.fill('dark gray') 462 | draw_board() 463 | draw_pieces() 464 | draw_captured() 465 | draw_check() 466 | if not game_over: 467 | white_promote, black_promote, promo_index = check_promotion() 468 | if white_promote or black_promote: 469 | draw_promotion() 470 | check_promo_select() 471 | if selection != 100: 472 | valid_moves = check_valid_moves() 473 | draw_valid(valid_moves) 474 | if selected_piece == 'king': 475 | draw_castling(castling_moves) 476 | # event handling 477 | for event in pygame.event.get(): 478 | if event.type == pygame.QUIT: 479 | run = False 480 | if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1 and not game_over: 481 | x_coord = event.pos[0] // 100 482 | y_coord = event.pos[1] // 100 483 | click_coords = (x_coord, y_coord) 484 | if turn_step <= 1: 485 | if click_coords == (8, 8) or click_coords == (9, 8): 486 | winner = 'black' 487 | if click_coords in white_locations: 488 | selection = white_locations.index(click_coords) 489 | # check what piece is selected, so you can only draw castling moves if king is selected 490 | selected_piece = white_pieces[selection] 491 | if turn_step == 0: 492 | turn_step = 1 493 | if click_coords in valid_moves and selection != 100: 494 | white_ep = check_ep(white_locations[selection], click_coords) 495 | white_locations[selection] = click_coords 496 | white_moved[selection] = True 497 | if click_coords in black_locations: 498 | black_piece = black_locations.index(click_coords) 499 | captured_pieces_white.append(black_pieces[black_piece]) 500 | if black_pieces[black_piece] == 'king': 501 | winner = 'white' 502 | black_pieces.pop(black_piece) 503 | black_locations.pop(black_piece) 504 | black_moved.pop(black_piece) 505 | # adding check if en passant pawn was captured 506 | if click_coords == black_ep: 507 | black_piece = black_locations.index((black_ep[0], black_ep[1] - 1)) 508 | captured_pieces_white.append(black_pieces[black_piece]) 509 | black_pieces.pop(black_piece) 510 | black_locations.pop(black_piece) 511 | black_moved.pop(black_piece) 512 | black_options = check_options(black_pieces, black_locations, 'black') 513 | white_options = check_options(white_pieces, white_locations, 'white') 514 | turn_step = 2 515 | selection = 100 516 | valid_moves = [] 517 | # add option to castle 518 | elif selection != 100 and selected_piece == 'king': 519 | for q in range(len(castling_moves)): 520 | if click_coords == castling_moves[q][0]: 521 | white_locations[selection] = click_coords 522 | white_moved[selection] = True 523 | if click_coords == (1, 0): 524 | rook_coords = (0, 0) 525 | else: 526 | rook_coords = (7, 0) 527 | rook_index = white_locations.index(rook_coords) 528 | white_locations[rook_index] = castling_moves[q][1] 529 | black_options = check_options(black_pieces, black_locations, 'black') 530 | white_options = check_options(white_pieces, white_locations, 'white') 531 | turn_step = 2 532 | selection = 100 533 | valid_moves = [] 534 | if turn_step > 1: 535 | if click_coords == (8, 8) or click_coords == (9, 8): 536 | winner = 'white' 537 | if click_coords in black_locations: 538 | selection = black_locations.index(click_coords) 539 | # check what piece is selected, so you can only draw castling moves if king is selected 540 | selected_piece = black_pieces[selection] 541 | if turn_step == 2: 542 | turn_step = 3 543 | if click_coords in valid_moves and selection != 100: 544 | black_ep = check_ep(black_locations[selection], click_coords) 545 | black_locations[selection] = click_coords 546 | black_moved[selection] = True 547 | if click_coords in white_locations: 548 | white_piece = white_locations.index(click_coords) 549 | captured_pieces_black.append(white_pieces[white_piece]) 550 | if white_pieces[white_piece] == 'king': 551 | winner = 'black' 552 | white_pieces.pop(white_piece) 553 | white_locations.pop(white_piece) 554 | white_moved.pop(white_piece) 555 | if click_coords == white_ep: 556 | white_piece = white_locations.index((white_ep[0], white_ep[1] + 1)) 557 | captured_pieces_black.append(white_pieces[white_piece]) 558 | white_pieces.pop(white_piece) 559 | white_locations.pop(white_piece) 560 | white_moved.pop(white_piece) 561 | black_options = check_options(black_pieces, black_locations, 'black') 562 | white_options = check_options(white_pieces, white_locations, 'white') 563 | turn_step = 0 564 | selection = 100 565 | valid_moves = [] 566 | # add option to castle 567 | elif selection != 100 and selected_piece == 'king': 568 | for q in range(len(castling_moves)): 569 | if click_coords == castling_moves[q][0]: 570 | black_locations[selection] = click_coords 571 | black_moved[selection] = True 572 | if click_coords == (1, 7): 573 | rook_coords = (0, 7) 574 | else: 575 | rook_coords = (7, 7) 576 | rook_index = black_locations.index(rook_coords) 577 | black_locations[rook_index] = castling_moves[q][1] 578 | black_options = check_options(black_pieces, black_locations, 'black') 579 | white_options = check_options(white_pieces, white_locations, 'white') 580 | turn_step = 0 581 | selection = 100 582 | valid_moves = [] 583 | if event.type == pygame.KEYDOWN and game_over: 584 | if event.key == pygame.K_RETURN: 585 | game_over = False 586 | winner = '' 587 | white_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook', 588 | 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn'] 589 | white_locations = [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0), 590 | (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)] 591 | white_moved = [False, False, False, False, False, False, False, False, 592 | False, False, False, False, False, False, False, False] 593 | black_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook', 594 | 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn'] 595 | black_locations = [(0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7), 596 | (0, 6), (1, 6), (2, 6), (3, 6), (4, 6), (5, 6), (6, 6), (7, 6)] 597 | black_moved = [False, False, False, False, False, False, False, False, 598 | False, False, False, False, False, False, False, False] 599 | captured_pieces_white = [] 600 | captured_pieces_black = [] 601 | turn_step = 0 602 | selection = 100 603 | valid_moves = [] 604 | black_options = check_options(black_pieces, black_locations, 'black') 605 | white_options = check_options(white_pieces, white_locations, 'white') 606 | 607 | if winner != '': 608 | game_over = True 609 | draw_game_over() 610 | 611 | pygame.display.flip() 612 | pygame.quit() 613 | -------------------------------------------------------------------------------- /assets/images/black bishop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/black bishop.png -------------------------------------------------------------------------------- /assets/images/black king.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/black king.png -------------------------------------------------------------------------------- /assets/images/black knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/black knight.png -------------------------------------------------------------------------------- /assets/images/black pawn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/black pawn.png -------------------------------------------------------------------------------- /assets/images/black queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/black queen.png -------------------------------------------------------------------------------- /assets/images/black rook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/black rook.png -------------------------------------------------------------------------------- /assets/images/white bishop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/white bishop.png -------------------------------------------------------------------------------- /assets/images/white king.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/white king.png -------------------------------------------------------------------------------- /assets/images/white knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/white knight.png -------------------------------------------------------------------------------- /assets/images/white pawn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/white pawn.png -------------------------------------------------------------------------------- /assets/images/white queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/white queen.png -------------------------------------------------------------------------------- /assets/images/white rook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plemaster01/pygameChess/87ad5d2cc4ea5c4874d489ea6de4d4350506450c/assets/images/white rook.png -------------------------------------------------------------------------------- /constants.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | pygame.init() 3 | 4 | WIDTH = 1000 5 | HEIGHT = 900 6 | screen = pygame.display.set_mode([WIDTH, HEIGHT]) 7 | pygame.display.set_caption('Two-Player Pygame Chess!') 8 | font = pygame.font.Font('freesansbold.ttf', 20) 9 | medium_font = pygame.font.Font('freesansbold.ttf', 40) 10 | big_font = pygame.font.Font('freesansbold.ttf', 50) 11 | timer = pygame.time.Clock() 12 | fps = 60 13 | # game variables and images 14 | white_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook', 15 | 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn'] 16 | white_locations = [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0), 17 | (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)] 18 | black_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook', 19 | 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn'] 20 | black_locations = [(0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7), 21 | (0, 6), (1, 6), (2, 6), (3, 6), (4, 6), (5, 6), (6, 6), (7, 6)] 22 | captured_pieces_white = [] 23 | captured_pieces_black = [] 24 | # 0 - whites turn no selection: 1-whites turn piece selected: 2- black turn no selection, 3 - black turn piece selected 25 | turn_step = 0 26 | selection = 100 27 | valid_moves = [] 28 | # load in game piece images (queen, king, rook, bishop, knight, pawn) x 2 29 | black_queen = pygame.image.load('assets/images/black queen.png') 30 | black_queen = pygame.transform.scale(black_queen, (80, 80)) 31 | black_queen_small = pygame.transform.scale(black_queen, (45, 45)) 32 | black_king = pygame.image.load('assets/images/black king.png') 33 | black_king = pygame.transform.scale(black_king, (80, 80)) 34 | black_king_small = pygame.transform.scale(black_king, (45, 45)) 35 | black_rook = pygame.image.load('assets/images/black rook.png') 36 | black_rook = pygame.transform.scale(black_rook, (80, 80)) 37 | black_rook_small = pygame.transform.scale(black_rook, (45, 45)) 38 | black_bishop = pygame.image.load('assets/images/black bishop.png') 39 | black_bishop = pygame.transform.scale(black_bishop, (80, 80)) 40 | black_bishop_small = pygame.transform.scale(black_bishop, (45, 45)) 41 | black_knight = pygame.image.load('assets/images/black knight.png') 42 | black_knight = pygame.transform.scale(black_knight, (80, 80)) 43 | black_knight_small = pygame.transform.scale(black_knight, (45, 45)) 44 | black_pawn = pygame.image.load('assets/images/black pawn.png') 45 | black_pawn = pygame.transform.scale(black_pawn, (65, 65)) 46 | black_pawn_small = pygame.transform.scale(black_pawn, (45, 45)) 47 | white_queen = pygame.image.load('assets/images/white queen.png') 48 | white_queen = pygame.transform.scale(white_queen, (80, 80)) 49 | white_queen_small = pygame.transform.scale(white_queen, (45, 45)) 50 | white_king = pygame.image.load('assets/images/white king.png') 51 | white_king = pygame.transform.scale(white_king, (80, 80)) 52 | white_king_small = pygame.transform.scale(white_king, (45, 45)) 53 | white_rook = pygame.image.load('assets/images/white rook.png') 54 | white_rook = pygame.transform.scale(white_rook, (80, 80)) 55 | white_rook_small = pygame.transform.scale(white_rook, (45, 45)) 56 | white_bishop = pygame.image.load('assets/images/white bishop.png') 57 | white_bishop = pygame.transform.scale(white_bishop, (80, 80)) 58 | white_bishop_small = pygame.transform.scale(white_bishop, (45, 45)) 59 | white_knight = pygame.image.load('assets/images/white knight.png') 60 | white_knight = pygame.transform.scale(white_knight, (80, 80)) 61 | white_knight_small = pygame.transform.scale(white_knight, (45, 45)) 62 | white_pawn = pygame.image.load('assets/images/white pawn.png') 63 | white_pawn = pygame.transform.scale(white_pawn, (65, 65)) 64 | white_pawn_small = pygame.transform.scale(white_pawn, (45, 45)) 65 | white_images = [white_pawn, white_queen, white_king, white_knight, white_rook, white_bishop] 66 | white_promotions = ['bishop', 'knight', 'rook', 'queen'] 67 | white_moved = [False, False, False, False, False, False, False, False, 68 | False, False, False, False, False, False, False, False] 69 | small_white_images = [white_pawn_small, white_queen_small, white_king_small, white_knight_small, 70 | white_rook_small, white_bishop_small] 71 | black_images = [black_pawn, black_queen, black_king, black_knight, black_rook, black_bishop] 72 | small_black_images = [black_pawn_small, black_queen_small, black_king_small, black_knight_small, 73 | black_rook_small, black_bishop_small] 74 | black_promotions = ['bishop', 'knight', 'rook', 'queen'] 75 | black_moved = [False, False, False, False, False, False, False, False, 76 | False, False, False, False, False, False, False, False] 77 | piece_list = ['pawn', 'queen', 'king', 'knight', 'rook', 'bishop'] 78 | # check variables/ flashing counter 79 | counter = 0 80 | winner = '' 81 | game_over = False 82 | white_ep = (100, 100) 83 | black_ep = (100, 100) 84 | white_promote = False 85 | black_promote = False 86 | promo_index = 100 87 | check = False 88 | castling_moves = [] -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # two player chess in python with Pygame! 2 | # part one, set up variables images and game loop 3 | 4 | import pygame 5 | 6 | pygame.init() 7 | WIDTH = 1000 8 | HEIGHT = 900 9 | screen = pygame.display.set_mode([WIDTH, HEIGHT]) 10 | pygame.display.set_caption('Two-Player Pygame Chess!') 11 | font = pygame.font.Font('freesansbold.ttf', 20) 12 | medium_font = pygame.font.Font('freesansbold.ttf', 40) 13 | big_font = pygame.font.Font('freesansbold.ttf', 50) 14 | timer = pygame.time.Clock() 15 | fps = 60 16 | # game variables and images 17 | white_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook', 18 | 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn'] 19 | white_locations = [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0), 20 | (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)] 21 | black_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook', 22 | 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn'] 23 | black_locations = [(0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7), 24 | (0, 6), (1, 6), (2, 6), (3, 6), (4, 6), (5, 6), (6, 6), (7, 6)] 25 | captured_pieces_white = [] 26 | captured_pieces_black = [] 27 | # 0 - whites turn no selection: 1-whites turn piece selected: 2- black turn no selection, 3 - black turn piece selected 28 | turn_step = 0 29 | selection = 100 30 | valid_moves = [] 31 | # load in game piece images (queen, king, rook, bishop, knight, pawn) x 2 32 | black_queen = pygame.image.load('assets/images/black queen.png') 33 | black_queen = pygame.transform.scale(black_queen, (80, 80)) 34 | black_queen_small = pygame.transform.scale(black_queen, (45, 45)) 35 | black_king = pygame.image.load('assets/images/black king.png') 36 | black_king = pygame.transform.scale(black_king, (80, 80)) 37 | black_king_small = pygame.transform.scale(black_king, (45, 45)) 38 | black_rook = pygame.image.load('assets/images/black rook.png') 39 | black_rook = pygame.transform.scale(black_rook, (80, 80)) 40 | black_rook_small = pygame.transform.scale(black_rook, (45, 45)) 41 | black_bishop = pygame.image.load('assets/images/black bishop.png') 42 | black_bishop = pygame.transform.scale(black_bishop, (80, 80)) 43 | black_bishop_small = pygame.transform.scale(black_bishop, (45, 45)) 44 | black_knight = pygame.image.load('assets/images/black knight.png') 45 | black_knight = pygame.transform.scale(black_knight, (80, 80)) 46 | black_knight_small = pygame.transform.scale(black_knight, (45, 45)) 47 | black_pawn = pygame.image.load('assets/images/black pawn.png') 48 | black_pawn = pygame.transform.scale(black_pawn, (65, 65)) 49 | black_pawn_small = pygame.transform.scale(black_pawn, (45, 45)) 50 | white_queen = pygame.image.load('assets/images/white queen.png') 51 | white_queen = pygame.transform.scale(white_queen, (80, 80)) 52 | white_queen_small = pygame.transform.scale(white_queen, (45, 45)) 53 | white_king = pygame.image.load('assets/images/white king.png') 54 | white_king = pygame.transform.scale(white_king, (80, 80)) 55 | white_king_small = pygame.transform.scale(white_king, (45, 45)) 56 | white_rook = pygame.image.load('assets/images/white rook.png') 57 | white_rook = pygame.transform.scale(white_rook, (80, 80)) 58 | white_rook_small = pygame.transform.scale(white_rook, (45, 45)) 59 | white_bishop = pygame.image.load('assets/images/white bishop.png') 60 | white_bishop = pygame.transform.scale(white_bishop, (80, 80)) 61 | white_bishop_small = pygame.transform.scale(white_bishop, (45, 45)) 62 | white_knight = pygame.image.load('assets/images/white knight.png') 63 | white_knight = pygame.transform.scale(white_knight, (80, 80)) 64 | white_knight_small = pygame.transform.scale(white_knight, (45, 45)) 65 | white_pawn = pygame.image.load('assets/images/white pawn.png') 66 | white_pawn = pygame.transform.scale(white_pawn, (65, 65)) 67 | white_pawn_small = pygame.transform.scale(white_pawn, (45, 45)) 68 | white_images = [white_pawn, white_queen, white_king, white_knight, white_rook, white_bishop] 69 | small_white_images = [white_pawn_small, white_queen_small, white_king_small, white_knight_small, 70 | white_rook_small, white_bishop_small] 71 | black_images = [black_pawn, black_queen, black_king, black_knight, black_rook, black_bishop] 72 | small_black_images = [black_pawn_small, black_queen_small, black_king_small, black_knight_small, 73 | black_rook_small, black_bishop_small] 74 | piece_list = ['pawn', 'queen', 'king', 'knight', 'rook', 'bishop'] 75 | # check variables/ flashing counter 76 | counter = 0 77 | winner = '' 78 | game_over = False 79 | 80 | 81 | # draw main game board 82 | def draw_board(): 83 | for i in range(32): 84 | column = i % 4 85 | row = i // 4 86 | if row % 2 == 0: 87 | pygame.draw.rect(screen, 'light gray', [600 - (column * 200), row * 100, 100, 100]) 88 | else: 89 | pygame.draw.rect(screen, 'light gray', [700 - (column * 200), row * 100, 100, 100]) 90 | pygame.draw.rect(screen, 'gray', [0, 800, WIDTH, 100]) 91 | pygame.draw.rect(screen, 'gold', [0, 800, WIDTH, 100], 5) 92 | pygame.draw.rect(screen, 'gold', [800, 0, 200, HEIGHT], 5) 93 | status_text = ['White: Select a Piece to Move!', 'White: Select a Destination!', 94 | 'Black: Select a Piece to Move!', 'Black: Select a Destination!'] 95 | screen.blit(big_font.render(status_text[turn_step], True, 'black'), (20, 820)) 96 | for i in range(9): 97 | pygame.draw.line(screen, 'black', (0, 100 * i), (800, 100 * i), 2) 98 | pygame.draw.line(screen, 'black', (100 * i, 0), (100 * i, 800), 2) 99 | screen.blit(medium_font.render('FORFEIT', True, 'black'), (810, 830)) 100 | 101 | 102 | # draw pieces onto board 103 | def draw_pieces(): 104 | for i in range(len(white_pieces)): 105 | index = piece_list.index(white_pieces[i]) 106 | if white_pieces[i] == 'pawn': 107 | screen.blit(white_pawn, (white_locations[i][0] * 100 + 22, white_locations[i][1] * 100 + 30)) 108 | else: 109 | screen.blit(white_images[index], (white_locations[i][0] * 100 + 10, white_locations[i][1] * 100 + 10)) 110 | if turn_step < 2: 111 | if selection == i: 112 | pygame.draw.rect(screen, 'red', [white_locations[i][0] * 100 + 1, white_locations[i][1] * 100 + 1, 113 | 100, 100], 2) 114 | 115 | for i in range(len(black_pieces)): 116 | index = piece_list.index(black_pieces[i]) 117 | if black_pieces[i] == 'pawn': 118 | screen.blit(black_pawn, (black_locations[i][0] * 100 + 22, black_locations[i][1] * 100 + 30)) 119 | else: 120 | screen.blit(black_images[index], (black_locations[i][0] * 100 + 10, black_locations[i][1] * 100 + 10)) 121 | if turn_step >= 2: 122 | if selection == i: 123 | pygame.draw.rect(screen, 'blue', [black_locations[i][0] * 100 + 1, black_locations[i][1] * 100 + 1, 124 | 100, 100], 2) 125 | 126 | 127 | # function to check all pieces valid options on board 128 | def check_options(pieces, locations, turn): 129 | moves_list = [] 130 | all_moves_list = [] 131 | for i in range((len(pieces))): 132 | location = locations[i] 133 | piece = pieces[i] 134 | if piece == 'pawn': 135 | moves_list = check_pawn(location, turn) 136 | elif piece == 'rook': 137 | moves_list = check_rook(location, turn) 138 | elif piece == 'knight': 139 | moves_list = check_knight(location, turn) 140 | elif piece == 'bishop': 141 | moves_list = check_bishop(location, turn) 142 | elif piece == 'queen': 143 | moves_list = check_queen(location, turn) 144 | elif piece == 'king': 145 | moves_list = check_king(location, turn) 146 | all_moves_list.append(moves_list) 147 | return all_moves_list 148 | 149 | 150 | # check king valid moves 151 | def check_king(position, color): 152 | moves_list = [] 153 | if color == 'white': 154 | enemies_list = black_locations 155 | friends_list = white_locations 156 | else: 157 | friends_list = black_locations 158 | enemies_list = white_locations 159 | # 8 squares to check for kings, they can go one square any direction 160 | targets = [(1, 0), (1, 1), (1, -1), (-1, 0), (-1, 1), (-1, -1), (0, 1), (0, -1)] 161 | for i in range(8): 162 | target = (position[0] + targets[i][0], position[1] + targets[i][1]) 163 | if target not in friends_list and 0 <= target[0] <= 7 and 0 <= target[1] <= 7: 164 | moves_list.append(target) 165 | return moves_list 166 | 167 | 168 | # check queen valid moves 169 | def check_queen(position, color): 170 | moves_list = check_bishop(position, color) 171 | second_list = check_rook(position, color) 172 | for i in range(len(second_list)): 173 | moves_list.append(second_list[i]) 174 | return moves_list 175 | 176 | 177 | # check bishop moves 178 | def check_bishop(position, color): 179 | moves_list = [] 180 | if color == 'white': 181 | enemies_list = black_locations 182 | friends_list = white_locations 183 | else: 184 | friends_list = black_locations 185 | enemies_list = white_locations 186 | for i in range(4): # up-right, up-left, down-right, down-left 187 | path = True 188 | chain = 1 189 | if i == 0: 190 | x = 1 191 | y = -1 192 | elif i == 1: 193 | x = -1 194 | y = -1 195 | elif i == 2: 196 | x = 1 197 | y = 1 198 | else: 199 | x = -1 200 | y = 1 201 | while path: 202 | if (position[0] + (chain * x), position[1] + (chain * y)) not in friends_list and \ 203 | 0 <= position[0] + (chain * x) <= 7 and 0 <= position[1] + (chain * y) <= 7: 204 | moves_list.append((position[0] + (chain * x), position[1] + (chain * y))) 205 | if (position[0] + (chain * x), position[1] + (chain * y)) in enemies_list: 206 | path = False 207 | chain += 1 208 | else: 209 | path = False 210 | return moves_list 211 | 212 | 213 | # check rook moves 214 | def check_rook(position, color): 215 | moves_list = [] 216 | if color == 'white': 217 | enemies_list = black_locations 218 | friends_list = white_locations 219 | else: 220 | friends_list = black_locations 221 | enemies_list = white_locations 222 | for i in range(4): # down, up, right, left 223 | path = True 224 | chain = 1 225 | if i == 0: 226 | x = 0 227 | y = 1 228 | elif i == 1: 229 | x = 0 230 | y = -1 231 | elif i == 2: 232 | x = 1 233 | y = 0 234 | else: 235 | x = -1 236 | y = 0 237 | while path: 238 | if (position[0] + (chain * x), position[1] + (chain * y)) not in friends_list and \ 239 | 0 <= position[0] + (chain * x) <= 7 and 0 <= position[1] + (chain * y) <= 7: 240 | moves_list.append((position[0] + (chain * x), position[1] + (chain * y))) 241 | if (position[0] + (chain * x), position[1] + (chain * y)) in enemies_list: 242 | path = False 243 | chain += 1 244 | else: 245 | path = False 246 | return moves_list 247 | 248 | 249 | # check valid pawn moves 250 | def check_pawn(position, color): 251 | moves_list = [] 252 | if color == 'white': 253 | if (position[0], position[1] + 1) not in white_locations and \ 254 | (position[0], position[1] + 1) not in black_locations and position[1] < 7: 255 | moves_list.append((position[0], position[1] + 1)) 256 | if (position[0], position[1] + 2) not in white_locations and \ 257 | (position[0], position[1] + 2) not in black_locations and position[1] == 1: 258 | moves_list.append((position[0], position[1] + 2)) 259 | if (position[0] + 1, position[1] + 1) in black_locations: 260 | moves_list.append((position[0] + 1, position[1] + 1)) 261 | if (position[0] - 1, position[1] + 1) in black_locations: 262 | moves_list.append((position[0] - 1, position[1] + 1)) 263 | else: 264 | if (position[0], position[1] - 1) not in white_locations and \ 265 | (position[0], position[1] - 1) not in black_locations and position[1] > 0: 266 | moves_list.append((position[0], position[1] - 1)) 267 | if (position[0], position[1] - 2) not in white_locations and \ 268 | (position[0], position[1] - 2) not in black_locations and position[1] == 6: 269 | moves_list.append((position[0], position[1] - 2)) 270 | if (position[0] + 1, position[1] - 1) in white_locations: 271 | moves_list.append((position[0] + 1, position[1] - 1)) 272 | if (position[0] - 1, position[1] - 1) in white_locations: 273 | moves_list.append((position[0] - 1, position[1] - 1)) 274 | return moves_list 275 | 276 | 277 | # check valid knight moves 278 | def check_knight(position, color): 279 | moves_list = [] 280 | if color == 'white': 281 | enemies_list = black_locations 282 | friends_list = white_locations 283 | else: 284 | friends_list = black_locations 285 | enemies_list = white_locations 286 | # 8 squares to check for knights, they can go two squares in one direction and one in another 287 | targets = [(1, 2), (1, -2), (2, 1), (2, -1), (-1, 2), (-1, -2), (-2, 1), (-2, -1)] 288 | for i in range(8): 289 | target = (position[0] + targets[i][0], position[1] + targets[i][1]) 290 | if target not in friends_list and 0 <= target[0] <= 7 and 0 <= target[1] <= 7: 291 | moves_list.append(target) 292 | return moves_list 293 | 294 | 295 | # check for valid moves for just selected piece 296 | def check_valid_moves(): 297 | if turn_step < 2: 298 | options_list = white_options 299 | else: 300 | options_list = black_options 301 | valid_options = options_list[selection] 302 | return valid_options 303 | 304 | 305 | # draw valid moves on screen 306 | def draw_valid(moves): 307 | if turn_step < 2: 308 | color = 'red' 309 | else: 310 | color = 'blue' 311 | for i in range(len(moves)): 312 | pygame.draw.circle(screen, color, (moves[i][0] * 100 + 50, moves[i][1] * 100 + 50), 5) 313 | 314 | 315 | # draw captured pieces on side of screen 316 | def draw_captured(): 317 | for i in range(len(captured_pieces_white)): 318 | captured_piece = captured_pieces_white[i] 319 | index = piece_list.index(captured_piece) 320 | screen.blit(small_black_images[index], (825, 5 + 50 * i)) 321 | for i in range(len(captured_pieces_black)): 322 | captured_piece = captured_pieces_black[i] 323 | index = piece_list.index(captured_piece) 324 | screen.blit(small_white_images[index], (925, 5 + 50 * i)) 325 | 326 | 327 | # draw a flashing square around king if in check 328 | def draw_check(): 329 | if turn_step < 2: 330 | if 'king' in white_pieces: 331 | king_index = white_pieces.index('king') 332 | king_location = white_locations[king_index] 333 | for i in range(len(black_options)): 334 | if king_location in black_options[i]: 335 | if counter < 15: 336 | pygame.draw.rect(screen, 'dark red', [white_locations[king_index][0] * 100 + 1, 337 | white_locations[king_index][1] * 100 + 1, 100, 100], 5) 338 | else: 339 | if 'king' in black_pieces: 340 | king_index = black_pieces.index('king') 341 | king_location = black_locations[king_index] 342 | for i in range(len(white_options)): 343 | if king_location in white_options[i]: 344 | if counter < 15: 345 | pygame.draw.rect(screen, 'dark blue', [black_locations[king_index][0] * 100 + 1, 346 | black_locations[king_index][1] * 100 + 1, 100, 100], 5) 347 | 348 | 349 | def draw_game_over(): 350 | pygame.draw.rect(screen, 'black', [200, 200, 400, 70]) 351 | screen.blit(font.render(f'{winner} won the game!', True, 'white'), (210, 210)) 352 | screen.blit(font.render(f'Press ENTER to Restart!', True, 'white'), (210, 240)) 353 | 354 | 355 | # main game loop 356 | black_options = check_options(black_pieces, black_locations, 'black') 357 | white_options = check_options(white_pieces, white_locations, 'white') 358 | run = True 359 | while run: 360 | timer.tick(fps) 361 | if counter < 30: 362 | counter += 1 363 | else: 364 | counter = 0 365 | screen.fill('dark gray') 366 | draw_board() 367 | draw_pieces() 368 | draw_captured() 369 | draw_check() 370 | if selection != 100: 371 | valid_moves = check_valid_moves() 372 | draw_valid(valid_moves) 373 | # event handling 374 | for event in pygame.event.get(): 375 | if event.type == pygame.QUIT: 376 | run = False 377 | if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1 and not game_over: 378 | x_coord = event.pos[0] // 100 379 | y_coord = event.pos[1] // 100 380 | click_coords = (x_coord, y_coord) 381 | if turn_step <= 1: 382 | if click_coords == (8, 8) or click_coords == (9, 8): 383 | winner = 'black' 384 | if click_coords in white_locations: 385 | selection = white_locations.index(click_coords) 386 | if turn_step == 0: 387 | turn_step = 1 388 | if click_coords in valid_moves and selection != 100: 389 | white_locations[selection] = click_coords 390 | if click_coords in black_locations: 391 | black_piece = black_locations.index(click_coords) 392 | captured_pieces_white.append(black_pieces[black_piece]) 393 | if black_pieces[black_piece] == 'king': 394 | winner = 'white' 395 | black_pieces.pop(black_piece) 396 | black_locations.pop(black_piece) 397 | black_options = check_options(black_pieces, black_locations, 'black') 398 | white_options = check_options(white_pieces, white_locations, 'white') 399 | turn_step = 2 400 | selection = 100 401 | valid_moves = [] 402 | if turn_step > 1: 403 | if click_coords == (8, 8) or click_coords == (9, 8): 404 | winner = 'white' 405 | if click_coords in black_locations: 406 | selection = black_locations.index(click_coords) 407 | if turn_step == 2: 408 | turn_step = 3 409 | if click_coords in valid_moves and selection != 100: 410 | black_locations[selection] = click_coords 411 | if click_coords in white_locations: 412 | white_piece = white_locations.index(click_coords) 413 | captured_pieces_black.append(white_pieces[white_piece]) 414 | if white_pieces[white_piece] == 'king': 415 | winner = 'black' 416 | white_pieces.pop(white_piece) 417 | white_locations.pop(white_piece) 418 | black_options = check_options(black_pieces, black_locations, 'black') 419 | white_options = check_options(white_pieces, white_locations, 'white') 420 | turn_step = 0 421 | selection = 100 422 | valid_moves = [] 423 | if event.type == pygame.KEYDOWN and game_over: 424 | if event.key == pygame.K_RETURN: 425 | game_over = False 426 | winner = '' 427 | white_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook', 428 | 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn'] 429 | white_locations = [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0), 430 | (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)] 431 | black_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook', 432 | 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn'] 433 | black_locations = [(0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7), 434 | (0, 6), (1, 6), (2, 6), (3, 6), (4, 6), (5, 6), (6, 6), (7, 6)] 435 | captured_pieces_white = [] 436 | captured_pieces_black = [] 437 | turn_step = 0 438 | selection = 100 439 | valid_moves = [] 440 | black_options = check_options(black_pieces, black_locations, 'black') 441 | white_options = check_options(white_pieces, white_locations, 'white') 442 | 443 | if winner != '': 444 | game_over = True 445 | draw_game_over() 446 | 447 | pygame.display.flip() 448 | pygame.quit() 449 | --------------------------------------------------------------------------------