Advertisement
Stegnewe

Game.py

Apr 24th, 2017
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.22 KB | None | 0 0
  1. import sys
  2. from Sprites import * #Pygame is imported here
  3.  
  4. '''
  5. This first section initiates pygame and sets up the chess board
  6. '''
  7. pygame.init() #I
  8.  
  9. debugging = 0 #A special mode that has tools for me to debug the GUI
  10. spriteOffset = 10 #Offset so the sprite is centered in the box, the sprite is 60x60 and the box is 80x80
  11. boxWidth = 80 #Width of a box on the chess board
  12. turn = 0 #Keeps track of whose turn it is
  13. selectedPiece = None #Keeps track of which piece is selected
  14. repeat = 1 #Checks if the loop should continue
  15.  
  16. #Set board size and board image
  17. boardSize = width, height = 640, 640
  18. bg = pygame.image.load("otherSprites/board.png")
  19. bgrect = bg.get_rect()
  20.  
  21. #Create the window with the size above
  22. screen = pygame.display.set_mode(boardSize)
  23.  
  24. #Make sprite groups for black and white pieces and highlight boxes
  25. bpieces = pygame.sprite.Group()
  26. wpieces = pygame.sprite.Group()
  27. highlights = pygame.sprite.Group()
  28. dbHighlights = pygame.sprite.Group()
  29.  
  30. #Add the rooks into the board
  31. for i in [0, 7]:
  32.     bpieces.add(bRook(i*boxWidth + spriteOffset, 0*boxWidth + spriteOffset))
  33.     wpieces.add(wRook(i*boxWidth + spriteOffset, 7*boxWidth + spriteOffset))
  34.  
  35. #Add the knights into the board
  36. for i in [1, 6]:
  37.     bpieces.add(bKnight(i*boxWidth + spriteOffset, 0*boxWidth + spriteOffset))
  38.     wpieces.add(wKnight(i*boxWidth + spriteOffset, 7*boxWidth + spriteOffset))
  39.  
  40. #Add the bishops into the board
  41. for i in [2, 5]:
  42.     bpieces.add(bBishop(i*boxWidth + spriteOffset, 0*boxWidth + spriteOffset))
  43.     wpieces.add(wBishop(i*boxWidth + spriteOffset, 7*boxWidth + spriteOffset))
  44.  
  45. #Add the kings and queens into the board
  46. bpieces.add(bKing(3*boxWidth + spriteOffset, 0*boxWidth + spriteOffset))
  47. wpieces.add(wKing(3*boxWidth + spriteOffset, 7*boxWidth + spriteOffset))
  48. bpieces.add(bQueen(4*boxWidth + spriteOffset, 0*boxWidth + spriteOffset))
  49. wpieces.add(wQueen(4*boxWidth + spriteOffset, 7*boxWidth + spriteOffset))
  50.  
  51. #Add the pawns into the board
  52. for i in range(8):
  53.     bpieces.add(bPawn(i*boxWidth + spriteOffset, 1*boxWidth + spriteOffset))
  54.     wpieces.add(wPawn(i*boxWidth + spriteOffset, 6*boxWidth + spriteOffset))
  55.  
  56. '''
  57. This next section defines some functions that will be used in the game
  58. '''
  59.  
  60. #Get the sprite at a certain coordinate, can specify a sprite group
  61. def getAt(x, y, group = None):
  62.     if group:
  63.         for s in group.sprites():
  64.             if s.rect.x == x and s.rect.y == y:
  65.                 return s
  66.         return None
  67.     allSprites = pygame.sprite.Group()
  68.     allSprites.add(wpieces.sprites())
  69.     allSprites.add(bpieces.sprites())
  70.     for s in allSprites.sprites():
  71.         if s.rect.x == x and s.rect.y == y:
  72.             allSprites.empty()
  73.             return s
  74.     return None
  75.  
  76. #Highlights squares at certain coordinates
  77. def highlightSquare(pos):
  78.     if debugging: print("Hightlighting", pos)
  79.     h = highlight(pos[0], pos[1])
  80.     highlights.add(h)
  81.  
  82. #Return True if the coordinates are on the board
  83. def onBoard(x, y):
  84.     if x > 0 and y > 0 and x < 8*boxWidth and y < 8*boxWidth:
  85.         return True
  86.     return False
  87.  
  88. #Return a list of possible moves for a bishop
  89. def getMovesBishop(s):
  90.     moves = [] #Possible moves will be added here
  91.  
  92.     #Remember current x and y of the piece
  93.     xCurr = s.rect.x
  94.     yCurr = s.rect.y
  95.  
  96.     color = s.groups()[0].sprites() #Get color of currect piece
  97.  
  98.     #Checking diagonally in all directions
  99.     for sign in [(-1, -1), (-1, 1), (1, -1), (1, 1)]:
  100.         x = xCurr + sign[0]*boxWidth
  101.         y = yCurr + sign[1]*boxWidth
  102.         while onBoard(x, y):
  103.             hit = getAt(x, y)
  104.             if hit and hit in color: break #If the hit object is the same color you cannot move there
  105.             moves.append((x, y))
  106.             if hit: break #If the hit object is the opposite color you can capture it
  107.             x += sign[0]*boxWidth
  108.             y += sign[1]*boxWidth
  109.  
  110.     return moves
  111.  
  112. #Return a list of possible moves for a plack pawn
  113. def getMovesbPawn(s):
  114.     moves = []
  115.  
  116.     currX = s.rect.x
  117.     currY = s.rect.y
  118.  
  119.     color = s.groups()[0].sprites()
  120.  
  121.     x = currX
  122.     y = currY + boxWidth
  123.     hit1 = getAt(x, y)
  124.     if onBoard(x, y) and not hit1:
  125.         moves.append((x, y))
  126.  
  127.     #Can move 2 spaces on first move
  128.     y += boxWidth
  129.     hit2 = getAt(x, y)
  130.     if not s.moved and not hit1 and not hit2:
  131.         moves.append((x, y))
  132.  
  133.     #Check diagonals for captures
  134.     diags = [(s.rect.x + boxWidth, s.rect.y + boxWidth), (s.rect.x - boxWidth, s.rect.y + boxWidth)]
  135.     for m in diags:
  136.         hit = getAt(m[0], m[1])
  137.         if onBoard(m[0], m[1]) and hit and hit not in color:
  138.             moves.append(m)
  139.     return moves
  140.  
  141. #Return a list of moves for a white pawn
  142. def getMoveswPawn(s):
  143.     moves = []
  144.  
  145.     currX = s.rect.x
  146.     currY = s.rect.y
  147.  
  148.     color = s.groups()[0].sprites()
  149.  
  150.     x = currX
  151.     y = currY - boxWidth
  152.     hit1 = getAt(x, y)
  153.     if onBoard(x, y) and not hit1:
  154.         moves.append((x, y))
  155.  
  156.     #Can move 2 spaces on first move
  157.     y -= boxWidth
  158.     hit2 = getAt(x, y)
  159.     if not s.moved and not hit1 and not hit2:
  160.         moves.append((x, y))
  161.  
  162.     #Check diagonals for captures
  163.     diags = [(s.rect.x + boxWidth, s.rect.y - boxWidth), (s.rect.x - boxWidth, s.rect.y - boxWidth)]
  164.     for m in diags:
  165.         hit = getAt(m[0], m[1])
  166.         if onBoard(m[0], m[1]) and hit and hit not in color:
  167.             moves.append(m)
  168.     return moves
  169.  
  170. #Return a list of moves for a rook
  171. def getMovesRook(s):
  172.     moves = [] #Possible moves will be added here
  173.  
  174.     #Remember current x and y of the piece
  175.     xCurr = s.rect.x
  176.     yCurr = s.rect.y
  177.  
  178.     color = s.groups()[0].sprites() #Get color of currect piece
  179.  
  180.     #Checking row and column of peice
  181.     for sign in [(-1, 0), (0, -1), (1, 0), (0, 1)]:
  182.         x = xCurr + sign[0]*boxWidth
  183.         y = yCurr + sign[1]*boxWidth
  184.         while onBoard(x, y):
  185.             hit = getAt(x, y)
  186.             if hit and hit in color: break #If the hit object is the same color you cannot move there
  187.             moves.append((x, y))
  188.             if hit: break #If the hit object is the opposite color you can capture it
  189.             x += sign[0]*boxWidth
  190.             y += sign[1]*boxWidth
  191.  
  192.     return moves
  193.  
  194. #Return a list of moves for a queen
  195. def getMovesQueen(s):
  196.     moves = []
  197.  
  198.     #A queen's moves is a combination of a rook's and bishop's
  199.     for m in getMovesRook(s):
  200.         moves.append(m)
  201.  
  202.     for m in getMovesBishop(s):
  203.         moves.append(m)
  204.  
  205.     return moves
  206.  
  207. #Return a list of moves for a knight
  208. def getMovesKnight(s):
  209.     moves = [] #Possible moves will be added here
  210.  
  211.     #Remember current x and y of the piece
  212.     xCurr = s.rect.x
  213.     yCurr = s.rect.y
  214.  
  215.     color = s.groups()[0].sprites() #Get color of currect piece
  216.  
  217.     #Checking in L shapes all around, like a knight does
  218.     for sign in [(2, 1), (1, 2), (-2, 1), (1, -2), (2, -1), (-1, 2), (-1, -2), (-2, -1)]:
  219.         x = xCurr + sign[0]*boxWidth
  220.         y = yCurr + sign[1]*boxWidth
  221.         if onBoard(x, y):
  222.             hit = getAt(x, y)
  223.             if hit and hit in color: continue #If the hit object is the same color you cannot move there
  224.             moves.append((x, y))
  225.            
  226.     return moves
  227.  
  228. #Return a list of moves for the black king
  229. #Note: While this function allows the king to move into check, it will later be checked and will alert the players if the move puts the king in check
  230. def getMovesKing(s):
  231.     moves = []
  232.  
  233.     xCurr = s.rect.x
  234.     yCurr = s.rect.y
  235.  
  236.     color = s.groups()[0].sprites()
  237.  
  238.     for sign in [(1, 0), (0, 1), (-1, 0), (0, -1), (1, 1), (-1, -1), (1, -1), (-1, 1)]:
  239.         x = xCurr + sign[0]*boxWidth
  240.         y = yCurr + sign[1]*boxWidth
  241.         if onBoard(x, y):
  242.             hit = getAt(x, y)
  243.             if hit and hit in color: continue
  244.             moves.append((x, y))
  245.  
  246.     return moves
  247.  
  248. def getMoves(s):
  249.     if isinstance(s, (bBishop, wBishop)):
  250.         #if debugging: print("Getting Bishop Moves")
  251.         return getMovesBishop(s)
  252.     if isinstance(s, bPawn):
  253.         #if debugging: print("Getting bPawn Moves")
  254.         return getMovesbPawn(s)
  255.     if isinstance(s, wPawn):
  256.         #if debugging: print("Getting wPawn Moves")
  257.         return getMoveswPawn(s)
  258.     if isinstance(s, (bRook, wRook)):
  259.         #if debugging: print("Getting Rook Moves")
  260.         return getMovesRook(s)
  261.     if isinstance(s, (bQueen, wQueen)):
  262.         #if debugging: print("Getting Queen Moves")
  263.         return getMovesQueen(s)
  264.     if isinstance(s, (bKnight, wKnight)):
  265.         #if debugging: print("Getting Knight Moves")
  266.         return getMovesKnight(s)
  267.     if isinstance(s, (bKing, wKing)):
  268.         #if debugging: print("Getting King Moves")
  269.         return getMovesKing(s)
  270.  
  271. def move(s, x, y, reverse = False):
  272.     #The current group of pieces
  273.     g = s.groups()[0]
  274.  
  275.     #Get the color which isn't currently its turn
  276.     if g == bpieces:
  277.         otherg = wpieces
  278.     else:
  279.         otherg = bpieces
  280.     hit = getAt(x, y, otherg)
  281.  
  282.     #if a piece is moved onto, kill it (remove it from being displayed)
  283.     if hit:
  284.         hit.kill()
  285.  
  286.     #Save the old coords of the piece being moved in case the move is going to be reversed
  287.     xOld = s.rect.x
  288.     yOld = s.rect.y
  289.     s.rect.x = x
  290.     s.rect.y = y
  291.  
  292.     #See if the move puts the player in check
  293.     if g == bpieces:
  294.         isCheck = checkOnBlack()
  295.     else:
  296.         isCheck = checkOnWhite()
  297.  
  298.     #If the player is in check, reverse the move because they cannot end the move in check
  299.     if isCheck or reverse: #Or the move is marked to be reversed
  300.         s.rect.x = xOld
  301.         s.rect.y = yOld
  302.         if hit: otherg.add(hit) #add the previously "killed" piece back
  303.         if isCheck:
  304.             if not reverse: print("Check")
  305.             return 0
  306.         return 1
  307.     else:
  308.         s.moved = 1
  309.         return 1
  310.  
  311. #Return True if black is in check
  312. #Note: This is only called after black moves because it is fine for black to start the move in check, just not end the move
  313. def checkOnBlack():
  314.     for s in wpieces.sprites():
  315.         for m in getMoves(s):
  316.             hit = getAt(m[0], m[1], bpieces)
  317.             if isinstance(hit, bKing):
  318.                 if debugging: print("Check on Black")
  319.                 return True
  320.     return False
  321.  
  322. #Return True if white is in check
  323. def checkOnWhite():
  324.     for s in bpieces.sprites():
  325.         for m in getMoves(s):
  326.             hit = getAt(m[0], m[1], wpieces)
  327.             if isinstance(hit, wKing):
  328.                 if debugging: print("Check on White")
  329.                 return True
  330.     return False
  331.  
  332. #Returns true if checkmate
  333. def isCheckmate(color):
  334.     for s in color.sprites():
  335.         for m in getMoves(s):
  336.             if move(s, m[0], m[1], True):
  337.                 if debugging: print("Not checkmate")
  338.                 return False
  339.     print("Checkmate")
  340.     return True
  341.  
  342.  
  343. '''
  344. This next section runs the game
  345. '''
  346. while 1:
  347.    
  348.  
  349.     for event in pygame.event.get():
  350.         #Terminate the program on close
  351.         if event.type == pygame.QUIT: sys.exit()
  352.  
  353.         #If I am debugging I want to see which box is getting clicked on
  354.         if debugging:
  355.             if event.type == pygame.MOUSEBUTTONDOWN:
  356.                 print("MOUSEBUTTONDOWN")
  357.                 pos = pygame.mouse.get_pos()
  358.                 x = (pos[0] // boxWidth) * boxWidth
  359.                 y = (pos[1] // boxWidth) * boxWidth
  360.                 dbHighlights.add(dbhighlight(x, y))
  361.  
  362.                 #Output the coordinate position of the mouse in terms of boxes on the chess board
  363.                 print("Mouse at (", x//boxWidth, ",", y//boxWidth, ")")
  364.  
  365.                 #Display the type of piece clicked on
  366.                 hit = getAt(x + spriteOffset, y + spriteOffset)
  367.                 print(hit)
  368.  
  369.             if event.type == pygame.MOUSEBUTTONUP:
  370.                 print("MOUSEBUTTONUP")
  371.                 dbHighlights.empty()
  372.  
  373.  
  374.         if repeat:
  375.             #When the mouse is clicked down
  376.             if event.type == pygame.MOUSEBUTTONDOWN:
  377.                 #Get which color is player
  378.                 if turn%2 == 0:
  379.                     player = wpieces
  380.                     otherPlayer = bpieces
  381.                 else:
  382.                     player = bpieces
  383.                     otherPlayer = wpieces
  384.  
  385.                 #Get the mouse position
  386.                 pos = pygame.mouse.get_pos()
  387.                 x = (pos[0] // boxWidth) * boxWidth
  388.                 y = (pos[1] // boxWidth) * boxWidth
  389.                
  390.                 #Look only if whoever's turn it is has selected a piece
  391.                 #ex: if it is white's turn, only allow white pieces to be selectable
  392.                
  393.                 hit = getAt(x + spriteOffset, y + spriteOffset, player)
  394.                 selectedPiece = hit
  395.  
  396.                 #if a piece of the appropriate color was selected show it's possible moves
  397.                 if hit:
  398.                     highlights.add(highlightCurr(x + spriteOffset, y + spriteOffset))
  399.                     moves = getMoves(hit)
  400.                     if moves:
  401.                         for m in moves:
  402.                             highlightSquare(m)
  403.  
  404.             #Look where the mouse was un-clicked and see if that is a valid move
  405.             if event.type == pygame.MOUSEBUTTONUP and selectedPiece:
  406.                 pos = pygame.mouse.get_pos()
  407.                 x = (pos[0] // boxWidth) * boxWidth
  408.                 y = (pos[1] // boxWidth) * boxWidth
  409.                 hit = getAt(x + spriteOffset, y + spriteOffset, highlights)
  410.                 if isinstance(hit, highlight):
  411.                     turn += move(selectedPiece, x + spriteOffset, y + spriteOffset)
  412.                 highlights.empty()
  413.                 #Check for checkmate
  414.                 if isCheckmate(otherPlayer):
  415.                     otherPlayer.add(checkmate())
  416.                     repeat = 0
  417.  
  418.     screen.blit(bg, bgrect) #Redraw the background (the board)
  419.     bpieces.draw(screen)
  420.     wpieces.draw(screen)
  421.     highlights.draw(screen)
  422.  
  423.     if debugging: dbHighlights.draw(screen)
  424.     pygame.display.update() #Update the whole screen
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement