MrEDog

Checkers 2.0

Nov 11th, 2020
528
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.08 KB | None | 0 0
  1. """
  2.    This program is a nice game of checkers.
  3. """
  4.  
  5. import pygame as py
  6. import settings as s
  7.  
  8. py.init()
  9.  
  10. # create the screen and set the caption
  11. screen = py.display.set_mode((s.WIDTH, s.HEIGHT))
  12. py.display.set_caption("Checkers")
  13.  
  14. # groups of sprites so the program can update and display the sprites more easily
  15. squares = py.sprite.Group()
  16. checkers = py.sprite.Group()
  17.  
  18. # Sets up the board logic.
  19. board = []
  20.  
  21. for x in range(int(s.SQUARE_SIZE//2), s.WIDTH, int(s.SQUARE_SIZE)):
  22.     col = []
  23.     for y in range(int(s.SQUARE_SIZE//2), s.HEIGHT, int(s.SQUARE_SIZE)):
  24.         col.append((x, y))
  25.        
  26.     board.append(col)
  27.  
  28.  
  29. class Checker(py.sprite.Sprite):
  30.     def __init__(self, coords, color):
  31.         super(Checker, self).__init__()
  32.        
  33.         self.surf = py.Surface((s.CIRCLE_SIZE,s.CIRCLE_SIZE))
  34.         self.surf.fill(s.BLACK)
  35.         self.surf.set_colorkey(s.BLACK)
  36.        
  37.         py.draw.circle(self.surf, color, [s.CIRCLE_SIZE//2,s.CIRCLE_SIZE//2], s.CIRCLE_SIZE//2)
  38.        
  39.         self.set_pos(coords)
  40.        
  41.         self.isCrown = False
  42.         self.coords = coords
  43.         self.color = color
  44.        
  45.     def set_pos(self, coords):
  46.         self.rect = self.surf.get_rect(center=(board[coords[0]][coords[1]]))
  47.    
  48.     # When selected, this function is called and the checker is anchored on the mouse
  49.     def update(self, mouse):
  50.         self.rect = self.surf.get_rect(center=mouse)
  51.        
  52.     def set_crown(self):
  53.         self.isCrown = True        
  54.         py.draw.circle(self.surf, s.NEAR_BLACK, [s.CIRCLE_SIZE//2, s.CIRCLE_SIZE//2], s.CROWN_SIZE)
  55.        
  56. class Square(py.sprite.Sprite):
  57.     def __init__(self, location, color):
  58.         super(Square, self).__init__()
  59.         self.surf = py.Surface((s.SQUARE_SIZE, s.SQUARE_SIZE))
  60.         self.surf.fill(color)
  61.         self.rect = self.surf.get_rect(topleft=location)
  62.  
  63. # Point used to determine what checker the user clicks.
  64. class Point(py.sprite.Sprite):
  65.     def __init__(self, location):
  66.         super(Point, self).__init__()
  67.         x = location[0]
  68.         y = location[1]
  69.         self.rect = py.Rect(x, y, 1, 1)
  70.  
  71. # Check to see if a specific coordinate has a checker in it.
  72. def has_checker(coords):
  73.     collision = py.sprite.spritecollide(Point(board[coords[0]][coords[1]]), checkers, False)
  74.     return collision
  75.  
  76. # Check if the coordinate is a valid move (if it is in range and it doesnt have a checker in it)
  77. # for the given checker.
  78. def is_valid_move(coords, checker):
  79.     if not coords[0] in range(8) or not coords[1] in range(8):
  80.         return False
  81.    
  82.     square_has_checker = has_checker(coords)
  83.    
  84.     if checker in square_has_checker:
  85.         square_has_checker.remove(checker)
  86.    
  87.     if square_has_checker:
  88.         return False
  89.    
  90.     return True
  91.  
  92. # Check to see if the given checker can jump from the given coordinates in the
  93. # given direction with the distance given by the move variable.
  94. def calculate_jump(checker, start_coords, move, direction):
  95.     jumped_coords = []
  96.        
  97.     forwards = (start_coords[0]+(move[0]*direction), start_coords[1]+(move[1]*direction))
  98.     backwards = (start_coords[0]+(move[0]*-direction), start_coords[1]+(move[1]*-direction))
  99.  
  100.     if is_valid_move(forwards, checker):
  101.         checker_to_jump = has_checker([start_coords[0]+(move[0]//2*direction), start_coords[1]+(move[1]//2*direction)])
  102.         if checker_to_jump and checker_to_jump[0].color != checker.color:
  103.             jumped_coords.append((start_coords[0]+(move[0]//2*direction), start_coords[1]+(move[1]//2*direction)))
  104.            
  105.             return jumped_coords, forwards
  106.        
  107.     if checker.isCrown:
  108.         if is_valid_move(backwards, checker):
  109.             checker_to_jump = has_checker([start_coords[0]+(move[0]//2*direction), start_coords[1]+(move[1]//2*-direction)])
  110.             if checker_to_jump and checker_to_jump[0].color != checker.color:
  111.                 jumped_coords.append((start_coords[0]+(move[0]//2*direction), start_coords[1]+(move[1]//2*-direction)))
  112.                
  113.                 return jumped_coords, backwards
  114.        
  115.     return None, None
  116.        
  117. # Function to get all the possible positions the given checker can
  118. # move to.
  119. def get_valid_positions(checker):
  120.     valid_positions = []
  121.     valid_capture_positions = []
  122.     coords_jumped = []
  123.    
  124.     normal_moves = [[1, -1], [-1, -1]]
  125.     capture_moves = [[2, -2], [-2, -2]]
  126.    
  127.     if checker.color == s.WHITE:
  128.         direction = 1
  129.     else:
  130.         direction = -1
  131.    
  132.     # Get all possible normal moves
  133.     for move in normal_moves:
  134.         forwards = (checker.coords[0]+(move[0]*direction), checker.coords[1]+(move[1]*direction))
  135.         backwards = (checker.coords[0]+(move[0]*-direction), checker.coords[1]+(move[1]*-direction))
  136.        
  137.         if is_valid_move(forwards, checker):
  138.             valid_positions.append(forwards)
  139.         if checker.isCrown:
  140.             if is_valid_move(backwards, checker):
  141.                 valid_positions.append(backwards)
  142.                
  143.     # Get all possible jump moves    
  144.     for move in capture_moves:
  145.         jumped_coords, new_coords = calculate_jump(checker, checker.coords, move, direction)
  146.        
  147.         if new_coords:
  148.             # Check to see if a double jump is possible
  149.             valid_capture_positions.append(new_coords)
  150.             coords_jumped.append(jumped_coords)
  151.            
  152.             for move in capture_moves:
  153.                 second_jumped_coords, second_coords = calculate_jump(checker, new_coords, move, direction)
  154.                
  155.                 if second_coords:
  156.                     valid_capture_positions.append(second_coords)
  157.                     coords_jumped.append([jumped_coords + second_jumped_coords])        
  158.    
  159.     # If the settings require that the player to jump, then the normal moves are
  160.     # not returned.
  161.     if valid_capture_positions and s.REQUIRE_JUMP:
  162.         return [[], valid_capture_positions, coords_jumped]
  163.     else:
  164.         return [valid_positions, valid_capture_positions, coords_jumped]
  165.  
  166. def text_objects(text, font):
  167.     textSurface = font.render(text, True, s.WHITE)
  168.     return textSurface, textSurface.get_rect()
  169.  
  170. def turn_display(turn):
  171.     font = py.font.SysFont(None, 25)
  172.     text = font.render(turn, True, s.NEAR_BLACK)
  173.     return text
  174.  
  175.    
  176. def set_up():
  177.     for i in range(s.BOARD_SIZE):    
  178.         for j in range(s.BOARD_SIZE):
  179.             # location of where the new squares need to be
  180.             location = [i*s.SQUARE_SIZE, j*s.SQUARE_SIZE]
  181.            
  182.             # Calculate the color of the squares
  183.             if (i+j) % 2 == 0:
  184.                 color = s.BROWN
  185.                
  186.                 # If the current row is in the range of the number of rows
  187.                 # given in the settings, it will add a checker with the correct color
  188.                 if j > s.BOARD_SIZE-(s.ROWS_OF_CHECKERS+1):
  189.                     new_checker = Checker((i, j), s.WHITE)
  190.                     checkers.add(new_checker)
  191.                 elif j < s.ROWS_OF_CHECKERS:
  192.                     new_checker = Checker((i, j), s.DARK_GRAY)
  193.                     checkers.add(new_checker)
  194.             else:
  195.                 color = s.BEIGE
  196.                
  197.             new_square = Square(location, color)
  198.             squares.add(new_square)
  199.            
  200. # Testing purposes only.
  201. def test_set_up():
  202.     for i in range(s.BOARD_SIZE):    
  203.         for j in range(s.BOARD_SIZE):
  204.             # location of where the new squares need to be
  205.             location = [i*s.SQUARE_SIZE, j*s.SQUARE_SIZE]
  206.            
  207.             # Calculate the color of the squares
  208.             if (i+j) % 2 == 0:
  209.                 color = s.BROWN
  210.             else:
  211.                 color = s.BEIGE
  212.                
  213.             new_square = Square(location, color)
  214.             squares.add(new_square)
  215.            
  216.     new_checker_1 = Checker((4, 6), s.DARK_GRAY)
  217.     checkers.add(new_checker_1)
  218.    
  219.     new_checker_2 = Checker((3, 1), s.WHITE)
  220.     checkers.add(new_checker_2)
  221.    
  222. # Render all the squares, checkers, and text to the screen.
  223. def render(turn):
  224.     screen.fill(s.REDWOOD)
  225.    
  226.     # Display all the squares first
  227.     for entity in squares:
  228.         screen.blit(entity.surf, entity.rect)
  229.    
  230.     # Then display all the checkers so they are on top of them.
  231.     for entity in checkers:
  232.         screen.blit(entity.surf, entity.rect)
  233.        
  234.     # Display what turn it is.
  235.     if turn == s.WHITE:            
  236.         turn_text = turn_display("Turn: White")
  237.     else:
  238.         turn_text = turn_display("Turn: Gray")
  239.     screen.blit(turn_text,(15,s.WIDTH+17))
  240.        
  241.     py.display.update()
  242.      
  243. def main():
  244.     #set_up()
  245.     test_set_up()
  246.    
  247.     selected_checker = None
  248.     turn = s.WHITE
  249.    
  250.     while True:
  251.         mouse = py.mouse.get_pos()
  252.         snapped_mouse = (int(mouse[0] // s.SQUARE_SIZE), int(mouse[1] // s.SQUARE_SIZE))
  253.        
  254.         for event in py.event.get():
  255.             if event.type == py.QUIT:
  256.                 py.quit()
  257.                 return
  258.             elif event.type == py.MOUSEBUTTONDOWN:
  259.                 # Select a checker, if it exists
  260.                 if not selected_checker:
  261.                     clicked_checker = py.sprite.spritecollideany(Point(mouse), checkers)
  262.                    
  263.                     if clicked_checker and clicked_checker.color == turn:
  264.                         selected_checker = clicked_checker
  265.             elif event.type == py.MOUSEBUTTONUP:
  266.                 # If a checker is currently selected, check if the move the player attempted to make is
  267.                 # valid, if so then move the checker to the new position and kill any
  268.                 # checkers it jumped over if neccesary
  269.                 if selected_checker:                            
  270.                     valid_positions = get_valid_positions(selected_checker)
  271.                            
  272.                     if snapped_mouse in valid_positions[0] or snapped_mouse in valid_positions[1]:
  273.                         if snapped_mouse in valid_positions[1]:
  274.                             index = valid_positions[1].index(snapped_mouse)
  275.                            
  276.                             for i in range(len(valid_positions[2][index])):
  277.                                 for checker in checkers:
  278.                                     if checker.coords == valid_positions[2][index][i] or checker.coords in valid_positions[2][index][i]:
  279.                                         checker.kill()
  280.                                    
  281.                         selected_checker.set_pos(snapped_mouse)
  282.                        
  283.                         # Change the turn
  284.                         if turn == s.WHITE:
  285.                             turn = s.DARK_GRAY
  286.                         else:
  287.                             turn = s.WHITE
  288.                    
  289.                         selected_checker.coords = snapped_mouse      
  290.                     else:
  291.                         # If the position is not valid, move the checker back to the original position
  292.                         # and don't change the turn
  293.                         selected_checker.rect = selected_checker.surf.get_rect(center=(board[selected_checker.coords[0]][selected_checker.coords[1]]))
  294.                    
  295.                     # Check to see if the checker is in a position to be crowned, if it is in a position
  296.                     # to be crowned and the setting for crowning is enabled, then crown the checker.
  297.                     if ((selected_checker.color == s.WHITE and selected_checker.coords[1] == 0) \
  298.                         or (selected_checker.color == s.DARK_GRAY and selected_checker.coords[1] == 7)) \
  299.                             and s.CAN_CROWN:
  300.                         selected_checker.set_crown()
  301.                    
  302.                     # Let go of the checker
  303.                     selected_checker = None
  304.                    
  305.         # If there is a selected checker, move it to the position of the mouse.
  306.         if selected_checker:
  307.             selected_checker.update(mouse)
  308.                
  309.         render(turn)
  310.         s.CLOCK.tick(s.FPS)
  311.        
  312. if __name__ == "__main__":
  313.     main()
Advertisement
Add Comment
Please, Sign In to add comment