214 lines
7.8 KiB
Python
214 lines
7.8 KiB
Python
import sys
|
|
|
|
import pygame
|
|
|
|
from utilities.constants import WIDTH, HEIGHT, SQUARE_SIZE, WHITE, GREEN
|
|
from utilities.gameManager import GameManager
|
|
from minimax.minimaxAlgo import MiniMax
|
|
|
|
FPS = 60
|
|
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
|
|
pygame.display.set_caption("Draughts")
|
|
|
|
|
|
def getRowColFromMouse(pos):
|
|
x, y = pos
|
|
row = y // SQUARE_SIZE
|
|
col = x // SQUARE_SIZE
|
|
return row, col
|
|
|
|
|
|
def drawText(text, font, color, surface, x, y):
|
|
textobj = font.render(text, 1, color)
|
|
textrect = textobj.get_rect()
|
|
textrect.topleft = (x, y)
|
|
surface.blit(textobj, textrect)
|
|
|
|
|
|
def drawMultiLineText(surface, text, pos, font, color=pygame.Color('black')):
|
|
words = [word.split(' ') for word in text.splitlines()] # 2D array where each row is a list of words.
|
|
space = font.size(' ')[0] # The width of a space.
|
|
max_width, max_height = surface.get_size()
|
|
x, y = pos
|
|
word_height = None
|
|
for line in words:
|
|
for word in line:
|
|
word_surface = font.render(word, 0, color)
|
|
word_width, word_height = word_surface.get_size()
|
|
if x + word_width >= max_width:
|
|
x = pos[0] # Reset the x.
|
|
y += word_height # Start on new row.
|
|
surface.blit(word_surface, (x, y))
|
|
x += word_width + space
|
|
x = pos[0] # Reset the x.
|
|
y += word_height # Start on new row.
|
|
|
|
|
|
def main():
|
|
pygame.init()
|
|
screen = pygame.display.set_mode((WIDTH, HEIGHT))
|
|
menuClock = pygame.time.Clock()
|
|
click = False
|
|
width = screen.get_width()
|
|
font = pygame.font.SysFont(None, 25)
|
|
difficulty = 0
|
|
|
|
while True:
|
|
# menu
|
|
screen.fill((128, 128, 128))
|
|
drawText('Main Menu', font, (255, 255, 255), screen, width / 2, 20)
|
|
|
|
mx, my = pygame.mouse.get_pos()
|
|
|
|
easy = pygame.Rect(width / 2 - 50, 100, 200, 50)
|
|
pygame.draw.rect(screen, (0, 255, 0), easy)
|
|
drawText("easy", font, (255, 255, 255), screen, width / 2, 100)
|
|
medium = pygame.Rect(width / 2 - 50, 200, 200, 50)
|
|
pygame.draw.rect(screen, (255, 125, 0), medium)
|
|
drawText("medium", font, (255, 255, 255), screen, width / 2, 200)
|
|
hard = pygame.Rect(width / 2 - 50, 300, 200, 50)
|
|
pygame.draw.rect(screen, (255, 0, 0), hard)
|
|
drawText("hard", font, (255, 255, 255), screen, width / 2, 300)
|
|
rules = pygame.Rect(width / 2 - 50, 400, 200, 50)
|
|
pygame.draw.rect(screen, (0, 0, 255), rules)
|
|
drawText("rules", font, (255, 255, 255), screen, width / 2, 400)
|
|
quitGame = pygame.Rect(width / 2 - 50, 500, 200, 50)
|
|
pygame.draw.rect(screen, (0, 0, 0), quitGame)
|
|
drawText("quit", font, (255, 255, 255), screen, width / 2, 500)
|
|
|
|
if easy.collidepoint((mx, my)):
|
|
if click:
|
|
difficulty = 1
|
|
break
|
|
if medium.collidepoint((mx, my)):
|
|
if click:
|
|
difficulty = 3
|
|
break
|
|
if hard.collidepoint((mx, my)):
|
|
if click:
|
|
difficulty = 5
|
|
break
|
|
if rules.collidepoint((mx, my)):
|
|
if click:
|
|
rulesGUI()
|
|
break
|
|
if quitGame.collidepoint((mx, my)):
|
|
if click:
|
|
pygame.quit()
|
|
sys.exit()
|
|
click = False
|
|
for event in pygame.event.get():
|
|
if event.type == pygame.QUIT:
|
|
pygame.quit()
|
|
sys.exit()
|
|
if event.type == pygame.MOUSEBUTTONDOWN:
|
|
if event.button == 1:
|
|
click = True
|
|
|
|
pygame.display.update()
|
|
menuClock.tick(60)
|
|
if difficulty != 0:
|
|
game(difficulty)
|
|
|
|
|
|
def rulesGUI():
|
|
screen = pygame.display.set_mode((WIDTH, HEIGHT))
|
|
menuClock = pygame.time.Clock()
|
|
click = False
|
|
width = screen.get_width()
|
|
titleFont = pygame.font.SysFont(None, 48)
|
|
font = pygame.font.SysFont(None, 21)
|
|
while True:
|
|
screen.fill((128, 128, 128))
|
|
drawText("Rules", titleFont, (255, 255, 255), screen, width / 2, 20)
|
|
|
|
mx, my = pygame.mouse.get_pos()
|
|
drawMultiLineText(screen, """Both the player and AI start with 12 pieces on the dark squares of the three rows closest to that
|
|
player's side. The row closest to each player is called the kings row or crownhead. The player moves first.
|
|
Then turns alternate.
|
|
\n
|
|
Move rules
|
|
\n
|
|
There are two different ways to move in utilities:
|
|
\n
|
|
Simple move: A simple move consists of moving a piece one square diagonally to an adjacent unoccupied dark square.
|
|
Uncrowned pieces can move diagonally forward only; kings can move in any diagonal direction. Jump: A jump consists of
|
|
moving a piece that is diagonally adjacent an opponent's piece, to an empty square immediately beyond it in the same
|
|
direction (thus "jumping over" the opponent's piece front and back ). Pieces can jump diagonally forward only; kings
|
|
can jump in any diagonal direction. A jumped piece is considered "captured" and removed from the game. Any piece,
|
|
king or piece, can jump a king.
|
|
\n
|
|
Forced capture, is always mandatory: if a player has the option to jump, he/she must take it, even if doing so
|
|
results in disadvantage for the jumping player. For example, a piecedated single jump might set up the player such
|
|
that the opponent has a multi-jump in reply.
|
|
\n
|
|
Multiple jumps are possible, if after one jump, another piece is immediately eligible to be jumped by the moved
|
|
piece—even if that jump is in a different diagonal direction. If more than one multi-jump is available, the player
|
|
can choose which piece to jump with, and which sequence of jumps to make. The sequence chosen is not required to be
|
|
the one that maximizes the number of jumps in the turn; however, a player must make all available jumps in the
|
|
sequence chosen. Kings If a piece moves into the kings row on the opponent's side of the board, it is crowned as a
|
|
king and gains the ability to move both forward and backward. If a piece moves into the kings row or if it jumps into
|
|
the kings row, the current move terminates; the piece is crowned as a king but cannot jump back out as in a
|
|
multi-jump until the next move.""", (50, 50), font)
|
|
back = pygame.Rect(width / 2 - 50, 700, 200, 50)
|
|
pygame.draw.rect(screen, (0, 0, 0), back)
|
|
drawText("back", font, (255, 255, 255), screen, width / 2, 700)
|
|
|
|
if back.collidepoint((mx, my)):
|
|
if click:
|
|
main()
|
|
break
|
|
|
|
for event in pygame.event.get():
|
|
if event.type == pygame.QUIT:
|
|
pygame.quit()
|
|
sys.exit()
|
|
if event.type == pygame.MOUSEBUTTONDOWN:
|
|
if event.button == 1:
|
|
click = True
|
|
|
|
pygame.display.update()
|
|
menuClock.tick(60)
|
|
|
|
|
|
def game(difficulty):
|
|
run = True
|
|
clock = pygame.time.Clock()
|
|
gameManager = GameManager(WIN, GREEN)
|
|
|
|
while run:
|
|
clock.tick(FPS)
|
|
|
|
if gameManager.turn == WHITE:
|
|
mm = MiniMax()
|
|
value, newBoard = mm.AI(gameManager.getBoard(), difficulty, WHITE, gameManager)
|
|
gameManager.aiMove(newBoard)
|
|
# time.sleep(0.15)
|
|
|
|
if gameManager.turn == GREEN:
|
|
mm = MiniMax()
|
|
value, newBoard = mm.AI(gameManager.getBoard(), difficulty, GREEN, gameManager)
|
|
gameManager.aiMove(newBoard)
|
|
# time.sleep(0.15)
|
|
|
|
if gameManager.winner() != None:
|
|
print(gameManager.winner())
|
|
run = False
|
|
|
|
for event in pygame.event.get():
|
|
if event.type == pygame.QUIT:
|
|
run = False
|
|
if event.type == pygame.MOUSEBUTTONDOWN:
|
|
pos = pygame.mouse.get_pos()
|
|
row, col = getRowColFromMouse(pos)
|
|
# if gameManager.turn == GREEN:
|
|
gameManager.select(row, col)
|
|
|
|
gameManager.update()
|
|
pygame.display.update()
|
|
|
|
# pygame.quit()
|
|
|
|
|
|
main()
|