main.py
from Player import Player
import tkinter as tk
import pygame
import pygame_menu
import time
import colors
import Connect4 as cFour
import Minimax as mx
def text_format(option, textSize, textColor):
"""
Creates a text object to show in the main menu
"""
newFont = pygame.font.Font(pygame_menu.font.FONT_FRANCHISE, textSize)
newText = newFont.render(option, 0, textColor)
return newText
def load_screen():
"""
This initializes the window for pygame to use
"""
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Connect4")
return screen
def get_player_details(screen):
"""
Creates a tkinter object(button) that gets players names
"""
root = tk.Tk()
root.title("Player Names!")
tk.Label(root, text="Player One", fg="blue").grid(row=0)
tk.Label(root, text="Player Two", fg="red").grid(row=1)
p1 = tk.Entry(root, font=(None, 15))
p2 = tk.Entry(root, font=(None, 15))
p1.grid(row=0, column=1)
p2.grid(row=1, column=1)
tk.Button(root, text='Play!', command= lambda: play_game(p1.get(),p2.get(), root, screen)).grid(row=10, column=1, sticky=tk.W)
tk.mainloop()
def get_player_ai_details(screen):
"""
Creating the panel to allow the user to select a color and go against the AI
"""
options = ["Player 1", "Player 2"]
root = tk.Tk()
root.title("Player 1(Blue) or 2(Red)?")
colorChoice= tk.StringVar(root)
colorChoice.set(options[0])
tk.OptionMenu(root, colorChoice, *options).grid(row=3)
p1 = tk.Entry(root, font=(None, 15))
p1.grid(row=3, column=1)
tk.Button(root, text="Play Computer!", command=lambda: play_computer(colorChoice.get(), p1.get(), root, screen)).grid(row=10, column=1)
tk.mainloop()
def play_computer(colorChoice, playerName, root, screen):
"""
Connect4 play function (human v computer)
"""
root.destroy()
if colorChoice == "Player 1":
mx.Minimax(Player(playerName), Player("Ed"), screen).play_computer()
else:
mx.Minimax(Player("Ed"), Player(playerName), screen).play_computer()
def play_game(p1Name, p2Name, root, screen):
"""
Connect4 play function (human v human)
"""
root.destroy()
game = cFour.Connect4(Player(p1Name.strip()), Player(p2Name.strip()), screen).play()
if __name__ == "__main__":
pygame.init()
screen = load_screen()
features = [
("Player Vs Player", colors.yellow),
("Player Vs AI", colors.red),
("Quit", colors.gray)
]
iterator = 0
menu = True
while menu:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
#This if block makes it where the user doesnt have to click arrow key up/down if they have exhausted the possible options, it will loop you throughout options
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
iterator += 1
if iterator == len(features):
iterator = 0
if event.key == pygame.K_UP:
iterator -= 1
if iterator < 0:
iterator = len(features) - 1
if event.key == pygame.K_RETURN:
if selected == "Player Vs Player":
get_player_details(screen)
if selected == "Player Vs AI":
get_player_ai_details(screen)
if selected == "Quit":
pygame.quit()
quit()
selected = features[iterator][0]
screen.fill(colors.blue)
screen_rect = screen.get_rect()
for i in range(0, len(features)):
counter = -50 + (i * 90) # Equation that sets distance between each choice in main menu
if i == iterator:
text = text_format(features[i][0], 80, features[i][1])
else:
text = text_format(features[i][0], 80, colors.black)
player_rect = text.get_rect(center=screen_rect.center)
player_rect[1] = player_rect[1] + counter
screen.blit(text, player_rect)
pygame.display.update()
Connect4.py
import pygame
import colors
import tkinter as tk
import pygame_menu
# import pandas as pd
import random
class Connect4:
"""
Class used to represent connect4 game
"""
def __init__(self, player1, player2, screen):
# Use 1 version of the screen instead of trying to create a new one
self.screen = screen
# Circle Radius and Width
self.WIDTH = 0
self.CIRCLERADIUS = 25
# Game-Time Variables
self.player1 = player1
self.player2 = player2
self.moveNumber = 0
self.gameOver = False
self.COLUMNS = 7
self.ROWS = 6
self.EMPTY = 99
self.board = [[self.EMPTY for x in range(self.COLUMNS)] for y in range(self.ROWS)]
# The distance between where the window starts and the game board is placed
self.DISTANCE = 90
# Space between each circle
self.DISTANCEGAP = 70
# Setting rectangle default
self.LEFT = 50
self.TOP = 70
self.HEIGHT = 470
self.RECWIDTH = 500
#Creating new tkinterobject
self.root = tk.Tk()
self.scoreboard = {self.player1.name: 0, self.player2.name: 0, "ties": 0}
# Storing locations of available moves given a user clicks the window -- Tuple of locations
self.POSITIONS = [
(
self.DISTANCE + (self.DISTANCEGAP*column) - self.CIRCLERADIUS,
self.DISTANCE + (self.DISTANCEGAP*column) + self.CIRCLERADIUS
)
for column in range(0, self.COLUMNS)
]
def who_won(self, board, piece):
"""
Determines the state of the game and finds if there is a winner
"""
# Horizontal
for col in range(0, self.COLUMNS - 3):
for row in range(0, self.ROWS):
if board[row][col] == piece and board[row][col + 1] == piece and board[row][col + 2] == piece and board[row][col + 3] == piece:
return True
# Vertical
for col in range(0, self.COLUMNS):
for row in range(0, self.ROWS - 3):
if board[row][col] == piece and board[row + 1][col] == piece and board[row + 2][col] == piece and board[row + 3][col] == piece:
return True
# Up-Left/Down-Right
for col in range(3, self.COLUMNS):
for row in range(3, self.ROWS):
if board[row][col] == piece and board[row - 1][col - 1] == piece and board[row - 2][col - 2] == piece and board[row - 3][col - 3] == piece:
return True
# Up-Right/Down-Left
for col in range(0, self.COLUMNS - 3):
for row in range(3, self.ROWS):
if board[row][col] == piece and board[row - 1][col + 1] == piece and board[row - 2][col + 2] == piece and board[row - 3][col + 3] == piece:
return True
# A winning move is not found
return False
def is_legal_move(self, position, board):
"""
Validates if a move is available/legal
"""
if board[0][position] == self.EMPTY:
return True
return False
def display_board(self):
"""
Displaying the game board to the user
"""
# Function: rect(surface, color, rectangle object, optional width) -- First one forms the outline of the board
pygame.draw.rect(self.screen, colors.salmon, (self.LEFT, self.TOP, self.RECWIDTH, self.HEIGHT), 13)
# This forms inner-most rectangle that users play on
pygame.draw.rect(self.screen, colors.burlywood, (self.LEFT, self.TOP, self.RECWIDTH, self.HEIGHT))
for column in range(0, self.COLUMNS):
colEq = self.DISTANCE + (self.DISTANCEGAP * column)
for row in range(0, self.ROWS):
# 125 is used here to make a the board placed in the center of the board and helps finding a value for self.TOP easier
rowEq = 125 + (self.DISTANCEGAP * row)
if self.board[row][column] == self.EMPTY:
color = colors.white
elif self.board[row][column] == 0:
color = colors.realBlue
elif self.board[row][column] == 1:
color = colors.red
pygame.draw.circle(self.screen, color, (colEq, rowEq), self.CIRCLERADIUS, self.WIDTH)
pygame.display.flip()
def play(self):
"""
This is the game-loop
"""
while not self.gameOver:
self.display_board()
if self.moveNumber % 2 == 0:
userText, userRect = self.display_player_name(self.player1.name, colors.realBlue)
elif self.moveNumber % 2 == 1:
userText, userRect = self.display_player_name(self.player2.name, colors.red)
self.screen.blit(userText, userRect)
for event in pygame.event.get():
self.screen.fill(colors.aquamarine) # Set up background color
if event.type == pygame.QUIT:
self.gameOver = True
elif event.type == pygame.MOUSEBUTTONDOWN:
x, y = pygame.mouse.get_pos()
position = self.get_column_position(x)
if self.moveNumber % 2 == 0 and position != self.EMPTY:
if self.is_legal_move(position, self.board):
self.drop_piece_animation(position)
if self.who_won(self.board, 0):
self.gameOver = True
self.scoreboard[self.player1.name] = self.scoreboard.get(self.player1.name) + 1
userText, userRect = self.display_player_name(self.player1.name + " " + "Wins!!!", colors.dark_gray)
elif self.check_if_tie(self.board):
self.gameOver = True
self.scoreboard["ties"] = self.scoreboard.get("ties") + 1
userText, userRect = self.display_player_name("It is a TIE!!!", colors.dark_gray)
elif self.moveNumber % 2 == 1 and position != self.EMPTY:
if self.is_legal_move(position, self.board):
self.drop_piece_animation(position)
if self.who_won(self.board, 1):
self.gameOver = True
self.scoreboard[self.player2.name] = self.scoreboard.get(self.player2.name) + 1
userText, userRect = self.display_player_name(self.player2.name + " " + "Wins!!!", colors.dark_gray)
elif self.check_if_tie(self.board):
self.gameOver = True
self.scoreboard["ties"] = self.scoreboard.get("ties") + 1
userText, userRect = self.display_player_name("It is a TIE!!!", colors.dark_gray)
self.display_board()
self.screen.blit(userText, userRect)
pygame.display.flip()
self.display_scoreboard(False)
def display_scoreboard(self, isAi):
"""
This enables the tkinter object so I can display the user options after : Victory/Loss/Tie
"""
self.root.geometry('460x150+300+0')
self.reset()
self.root.title("Choices")
# This creates the feedback information screen that the user sees after a game
tk.Label(self.root, text="Close window to go to main menu", font=(None, 15, 'underline'), anchor='w', justify='left').grid(row=0, column=1, sticky="NSEW")
tk.Label(self.root, text=self.player1.name + ": " + str(self.scoreboard.get(self.player1.name)), font=(None, 15), anchor='w', justify='left').grid(row=1, column=1, sticky = "NSEW")
tk.Label(self.root, text=self.player2.name + ": " + str(self.scoreboard.get(self.player2.name)), font=(None, 15), anchor='w', justify='left').grid(row=2, column=1, sticky="NSEW")
tk.Label(self.root, text="Ties: " + str(self.scoreboard.get("ties")), font=(None, 15), anchor='w', justify='left').grid(row=3, column=1, sticky="NSEW")
# if isAi == True:
# # tk.Button(self.root, text='Rematch!', command=self.playAi, font=(None, 12), fg="blue").grid(row=4, column=1, sticky=tk.W)
# else:
tk.Button(self.root, text='Rematch!', command=self.play, font=(None, 12), fg="blue").grid(row=4, column=1, sticky=tk.W)
# tk.Button(self.root, text='Rematch with Swap!', command= lambda: self.swapPlayers(isAi), font=(None, 12), fg="red").grid(row=4, column=2, sticky=tk.W)
tk.Entry(self.root)
self.root.mainloop()
def check_if_tie(self, board):
"""
A possible game state : Checking for a tie
"""
totalPieces = 0
for col in range(0, self.COLUMNS):
for row in range(0, self.ROWS):
if board[row][col] == 0 or board[row][col] == 1:
totalPieces += 1
if totalPieces == 42:
return True
else:
return False
def display_player_name(self, name, color):
"""
A feature to help users know who's turn it is that gets displayed
"""
font = pygame.font.Font(pygame_menu.font.FONT_FRANCHISE, 60)
text = font.render(name, True, color)
textRect = text.get_rect()
textRect.center = (len(name) * 30, 20)
return text, textRect
def drop_piece_animation(self, position):
"""
Inserting a piece at a given position with the animation of a piece drop
"""
tmpRow = 5
while self.board[tmpRow][position] == 1 or self.board[tmpRow][position] == 0:
tmpRow -= 1
for i in range(0, tmpRow + 1):
self.board[i][position] = self.moveNumber % 2
self.display_board()
pygame.time.delay(200)
pygame.display.flip()
self.board[i][position] = self.EMPTY
self.board[tmpRow][position] = self.moveNumber % 2
self.moveNumber += 1
def get_column_position(self, position):
"""
Takes a X coordinate value dependent on a click and determines what column user clicked
"""
index = 0
for i in self.POSITIONS:
if position + self.CIRCLERADIUS/2 >= i[0] and position - self.CIRCLERADIUS/2 <= i[1]:
return index
index += 1
return self.EMPTY
def reset(self):
"""
Restoring the game in its original state
"""
self.moveNumber = 0
self.board = [[self.EMPTY for x in range(self.COLUMNS)] for y in range(self.ROWS)]
self.gameOver = False
def play_computer(self):
"""
This is the game-loop used for AI play
"""
# If/else block to distinguish the human/Ai because the ai cant mouse click events
if self.player1.name == "Ed": # Ed Watkins (Staten Island)
humanPlayer = 1
computerPlayer = 0
humanName = self.player2.name
computerName = self.player1.name
elif self.player2.name == "Ed":
humanPlayer = 0
computerPlayer = 1
humanName = self.player1.name
computerName = self.player2.name
while not self.gameOver:
self.display_board()
if self.moveNumber % 2 == 0:
userText, userRect = self.display_player_name(self.player1.name, colors.blue)
elif self.moveNumber % 2 == 1:
userText, userRect = self.display_player_name(self.player2.name, colors.red)
self.screen.blit(userText, userRect)
for event in pygame.event.get():
self.screen.fill(colors.aquamarine) # Set up background color
if event.type == pygame.QUIT:
self.gameOver = True
elif event.type == pygame.MOUSEBUTTONDOWN:
x, y = pygame.mouse.get_pos()
position = self.get_column_position(x)
if self.moveNumber % 2 == humanPlayer and position != self.EMPTY:
if self.is_legal_move(position, self.board):
self.drop_piece_animation(position)
if self.who_won(self.board, humanPlayer):
self.gameOver = True
self.scoreboard[humanName] = self.scoreboard.get(humanName) + 1
userText, userRect = self.display_player_name(humanName + " " + "Wins!!!", colors.dark_gray)
elif self.check_if_tie(self.board):
self.gameOver = True
self.scoreboard["ties"] = self.scoreboard.get("ties") + 1
userText, userRect = self.display_player_name("It is a TIE!!!", colors.dark_gray)
if self.moveNumber % 2 == computerPlayer and self.gameOver == False:
move = self.generate_move(self.board, 4, computerPlayer, humanPlayer, True, self.moveNumber)
self.drop_piece_animation(move)
if self.who_won(self.board, computerPlayer):
self.gameOver = True
self.scoreboard[computerName] = self.scoreboard.get(computerName) + 1
userText, userRect = self.display_player_name(computerName + " " + "Wins!!!", colors.dark_gray)
elif self.check_if_tie(self.board):
self.gameOver = True
self.scoreboard["ties"] = self.scoreboard.get("ties") + 1
userText, userRect = self.display_player_name("It is a TIE!!!", colors.dark_gray)
self.display_board()
self.screen.blit(userText, userRect)
pygame.display.flip()
Minimax.py
from Connect4 import Connect4
import random
from copy import copy, deepcopy
import pygame
class Minimax(Connect4):
def __init__(self, player1, player2, screen):
super().__init__(player1, player2, screen)
def is_game_over(self, board):
if self.who_won(board, 1) or self.who_won(board, 0):
return True
return False
def generate_move(self, board, depth, computerPlayer, humanPlayer, maximizingPlayer, moveNumber):
if depth == 0 or self.is_game_over(board) or self.check_if_tie(board):
if self.is_game_over(board):
if self.who_won(board, computerPlayer):
return 1000000
elif self.who_won(board, humanPlayer):
return -1000000
elif self.check_if_tie(board):
return 0
else:
return self.get_game_score(board, computerPlayer, humanPlayer)
if maximizingPlayer:
maxValue = -1000000
for move in range(0, self.COLUMNS):
tmpBoard = self.copyBoard(board)
if self.is_legal_move(move, tmpBoard):
self.drop_piece_computer(move, tmpBoard, moveNumber)
result = self.generate_move(tmpBoard, depth - 1, computerPlayer, humanPlayer, False, moveNumber + 1)
if result >= maxValue:
maxValue = result
bestMove = move
return bestMove
else:
minValue = 1000000
for move in range(0,self.COLUMNS):
tmpBoard = self.copyBoard(board)
if self.is_legal_move(move, tmpBoard):
self.drop_piece_computer(move, tmpBoard, moveNumber)
result = self.generate_move(tmpBoard, depth - 1, humanPlayer, humanPlayer, True, moveNumber + 1)
if result <= minValue:
minValue = result
thismove = move
return thismove
def copyBoard(self, board):
tmpList = [[self.EMPTY for x in range(self.COLUMNS)] for y in range(self.ROWS)]
for row in range(0, self.ROWS):
for col in range(0, self.COLUMNS):
tmpList[row][col] = board[row][col]
return tmpList
def drop_piece_computer(self, position, board, moveNumber):
"""
Inserting a piece at a given position with the animation of a piece drop
"""
tmpRow = 5
while board[tmpRow][position] == 1 or board[tmpRow][position] == 0:
tmpRow -= 1
board[tmpRow][position] = moveNumber % 2
# moveNumber += 1
def get_game_score(self, board, computerPlayer, humanPlayer):
totalScore = 0
totalScore += self.get_hori_score(board, computerPlayer, humanPlayer)
# totalScore += self.get_vert_score(board, computerPlayer, humanPlayer)
# totalScore += self.get_upright_score(board, computerPlayer, humanPlayer)
# totalScore += self.get_upleft_score(board, computerPlayer, humanPlayer)
return totalScore
def get_hori_score(self, board, computerPlayer, humanPlayer):
score = 0
# List to collect all the groupings of 4(Horizontally) out of the current game state
groupingFourList = []
for col in range(0, self.COLUMNS - 3):
for row in range(0, self.ROWS):
groupingFourList.append(board[row][col])
groupingFourList.append(board[row][col + 1])
groupingFourList.append(board[row][col + 2])
groupingFourList.append(board[row][col + 3])
computerPieces = self.count_player_pieces(groupingFourList, 1)
humanPieces = self.count_player_pieces(groupingFourList, 0)
emptyPieces = self.count_player_pieces(groupingFourList, self.EMPTY)
score += self.score_metric(computerPieces, humanPieces, emptyPieces)
groupingFourList = []
return score
def get_upright_score(self, board, computerPlayer, humanPlayer):
score = 0
# List to collect all the groupings of 4(Horizontally) out of the current game state
groupingFourList = []
for col in range(0, self.COLUMNS - 3):
for row in range(3, self.ROWS):
groupingFourList.append(board[row][col])
groupingFourList.append(board[row - 1][col + 1])
groupingFourList.append(board[row - 2][col + 2])
groupingFourList.append(board[row - 3][col + 3])
computerPieces = self.count_player_pieces(groupingFourList, 1)
humanPieces = self.count_player_pieces(groupingFourList, 0)
emptyPieces = self.count_player_pieces(groupingFourList, self.EMPTY)
score += self.score_metric(computerPieces, humanPieces, emptyPieces)
groupingFourList = []
return score
def get_upleft_score(self, board, computerPlayer, humanPlayer):
score = 0
# List to collect all the groupings of 4(Horizontally) out of the current game state
groupingFourList = []
for col in range(3, self.COLUMNS):
for row in range(3, self.ROWS):
groupingFourList.append(board[row][col])
groupingFourList.append(board[row - 1][col - 1])
groupingFourList.append(board[row - 2][col - 2])
groupingFourList.append(board[row - 3][col - 3])
computerPieces = self.count_player_pieces(groupingFourList, 1)
humanPieces = self.count_player_pieces(groupingFourList, humanPlayer)
emptyPieces = self.count_player_pieces(groupingFourList, self.EMPTY)
score += self.score_metric(computerPieces, humanPieces, emptyPieces)
groupingFourList = []
return score
def get_vert_score(self, board, computerPlayer, humanPlayer):
score = 0
# List to collect all the groupings of 4(Horizontally) out of the current game state
groupingFourList = []
for col in range(0, self.COLUMNS):
for row in range(0, self.ROWS -3):
groupingFourList.append(board[row][col])
groupingFourList.append(board[row + 1][col])
groupingFourList.append(board[row + 2][col])
groupingFourList.append(board[row + 3][col])
computerPieces = self.count_player_pieces(groupingFourList, computerPlayer)
humanPieces = self.count_player_pieces(groupingFourList, humanPlayer)
emptyPieces = self.count_player_pieces(groupingFourList, self.EMPTY)
score += self.score_metric(computerPieces, humanPieces, emptyPieces)
groupingFourList = []
return score
def count_player_pieces(self, groupingFourList, playerPiece):
totalPieces = 0
for piece in groupingFourList:
if piece == playerPiece:
totalPieces += 1
return totalPieces
def score_metric(self, computerPieces, humanPieces, emptyPieces):
score = 0
# Making bot prioritize playing defense than offense
# Thats why the score is lower when regarding the enemy: AI chooses highest scoring move
if (computerPieces == 4):
score += 100
elif (computerPieces == 3 and emptyPieces == 1):
score += 20
elif (computerPieces == 2 and emptyPieces == 2):
score += 10
if (humanPieces == 3 and emptyPieces == 1):
score -= 100
return score
colors.py
"""
Valid colors to use got it from this link : https://python-forum.io/Thread-PyGame-PyGame-Colors
"""
realBlue = (0,0,255)
white = (255,255,255)
green = (0,255,0)
black = (0,0,0)
orange = (255,100,10)
blue_green = (0,255,170)
marroon = (115,0,0)
lime = (180,255,100)
pink = (255,100,180)
purple = (240,0,255)
magenta = (255,0,230)
brown = (100,40,0)
forest_green = (0,50,0)
navy_blue = (0,0,100)
rust = (210,150,75)
dandilion_yellow = (255,200,0)
highlighter = (255,255,100)
sky_blue = (0,255,255)
light_gray = (200,200,200)
dark_gray = (50,50,50)
tan = (230,220,170)
coffee_brown = (200,190,140)
moon_glow = (235, 245, 255)
burlywood = (255, 211, 155)
salmon = (139, 76, 57)
aquamarine = (127, 255, 212)
#Colors used for menu
blue = (135, 206, 250)
yellow = (255, 255, 0)
red = (255,0,0)
gray = (128, 128, 128)
Player.py
class Player():
def __init__(self, name):
self.name = name
The solution is solved but stackoverflow wont allow me to remove the question. The reason I would like the question removed because the answer provided isnt the solution so it would just throw other people off.
Ok the solution is as follows:
In this section of code this is going through a portion of the search space and evaluating the game states based on the best moves for each player. Through this algorithm the AI knows the best moves for each player and can make a "good" move.
if maximizingPlayer:
maxValue = -1000000
for move in range(0, self.COLUMNS):
tmpBoard = self.copyBoard(board)
if self.is_legal_move(move, tmpBoard):
self.drop_piece_computer(move, tmpBoard, moveNumber)
result = self.generate_move(tmpBoard, depth - 1, computerPlayer, humanPlayer, False, moveNumber + 1)
if result >= maxValue:
maxValue = result
bestMove = move
return bestMove
else:
minValue = 1000000
for move in range(0,self.COLUMNS):
tmpBoard = self.copyBoard(board)
if self.is_legal_move(move, tmpBoard):
self.drop_piece_computer(move, tmpBoard, moveNumber)
result = self.generate_move(tmpBoard, depth - 1, humanPlayer, humanPlayer, True, moveNumber + 1)
if result <= minValue:
minValue = result
thismove = move
return thismove
However, if you look closely when I recursively call the function back to the AI in the !maximizing player function I have:
result = self.generate_move(tmpBoard, depth - 1, humanPlayer, humanPlayer, True, moveNumber + 1)
In words when a simulated human player was playing on a generic board to generate the ai move it was assuming that there were 2 human players, and thats why the halt would happen because you cannot have a game with 2 of the same player.
so changing:
result = self.generate_move(tmpBoard, depth - 1, humanPlayer, humanPlayer, True, moveNumber + 1)
to this:
result = self.generate_move(tmpBoard, depth - 1, computerPlayer, humanPlayer, True, moveNumber + 1)
Putting False instead of True in the if maximizingPlayer block and True instead of False in the else clause for the second to last argument to the recursive calls to generate_move seems to fix the game.
i.e. Change False on line 33 of Minimax.py to True and change the True on line 44 to False.
I'm trying to use pyinstaller to turn a project into an executable. Pyinstaller creates the directories with sucess, but when I try to run the executable, It gives the following Error.
./main
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "main.py", line 51, in <module>
font = pygame.font.Font("freesansbold.ttf", 30)
File "pygame/pkgdata.py", line 50, in getResource
File "setuptools-40.8.0-py3.6.egg/pkg_resources/__init__.py", line 1134, in resource_exists
File "setuptools-40.8.0-py3.6.egg/pkg_resources/__init__.py", line 1404, in has_resource
File "setuptools-40.8.0-py3.6.egg/pkg_resources/__init__.py", line 1457, in _has
NotImplementedError: Can't perform this operation for unregistered loader type
[8482] Failed to execute script main
This is the main code:
import pygame
from pygame.locals import *
from board import Board
from button import Button
# Initialization and screen surface loading
pygame.init()
screen = pygame.display.set_mode()
screenSize = pygame.display.get_surface().get_size()
width = screenSize[0]
height = screenSize[1]
pygame.display.set_caption("Sudokey: Sudoku's Solver")
# Image and music loading
bgMenu = pygame.image.load("background/sudokey2Menu.png")
bgMenu = pygame.transform.scale(bgMenu, (width, height - 30))
bgStart = pygame.image.load("background/sudokeyCustom.png")
bgStart = pygame.transform.scale(bgStart, (width - 40, height - 55))
pygame.mixer.pre_init()
pygame.mixer.init()
pygame.mixer.music.load("musica/lullabyGhostInYourPiano.mp3")
pygame.mixer.music.play(-1)
click = pygame.mixer.Sound("sons/click.ogg")
# Default screen and game state
running = 1
menu = 1
start = 0
credit = 0
# Mouse logic to detect click
currentSquare = (9, 9)
clickedCell = None
# Creating board using class "Board"
tabuleiro = Board()
# Creating menu buttons using class "Button"
buttonStart = Button(400, 186, 530, 90)
buttonTutorial = Button(400, 325, 530, 90)
buttonOptions = Button(400, 464, 530, 90)
buttonCredits = Button(400, 603, 530, 90)
# Creating start buttons using class "Button"
buttonSolve = Button(898, 40, 380, 80)
buttonReset = Button(898, 159, 380, 80)
buttonGoBack = Button(898, 279, 380, 80)
buttonOptionsStart = Button(898, 398, 380, 80)
# Font loading
font = pygame.font.Font("freesansbold.ttf", 30)
# Visually updates the board
def drawGrid(board):
for i in range(9):
for j in range(9):
if (board[i][j]):
text = font.render(str(board[i][j]), True, (0, 0, 0))
textRect = text.get_rect()
textRect.center = (j * 90 + 45, i * 80 + 45)
screen.blit(text, textRect)
# Plays music based on input
def jukebox(number):
if number == 0:
pygame.mixer.music.stop()
elif number == 1:
pygame.mixer.music.load("musica/lullabyGhostInYourPiano.mp3")
pygame.mixer.music.play(-1)
elif number == 2:
pygame.mixer.music.load("musica/adventureGhostInYourPiano.mp3")
pygame.mixer.music.play(-1)
elif number == 3:
pygame.mixer.music.load("musica/liebestrau.mp3")
pygame.mixer.music.play(-1)
elif number == 4:
pygame.mixer.music.load("musica/Kiss_the_Sky.mp3")
pygame.mixer.music.play(-1)
elif number == 5:
pygame.mixer.music.load("musica/Lullaby.mp3")
pygame.mixer.music.play(-1)
elif number == 6:
pygame.mixer.music.load("musica/Gentle_Breeze.mp3")
pygame.mixer.music.play(-1)
elif number == 7:
pygame.mixer.music.load("musica/Eternal_Hope.mp3")
pygame.mixer.music.play(-1)
elif number == 8:
pygame.mixer.music.load("musica/Pressure.mp3")
pygame.mixer.music.play(-1)
elif number == 9:
pygame.mixer.music.load("musica/01 To the Moon - Main Theme.mp3")
pygame.mixer.music.play(-1)
while running:
while menu:
pygame.display.flip()
screen.blit(bgMenu, (0, 0))
for event in pygame.event.get():
if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
running = 0
menu = 0
elif event.type == pygame.KEYDOWN and event.key == pygame.K_s:
start = 1
menu = 0
if event.type == pygame.MOUSEBUTTONUP:
x, y = pygame.mouse.get_pos()
if buttonStart.isOn(x, y):
#click.play()
#click.stop()
print(x, y)
menu = 0
start = 1
elif buttonTutorial.isOn(x, y):
print(x, y)
print('tutorial')
menu = 0
start = 1
elif buttonOptions.isOn(x, y):
print(x, y)
print('Options')
menu = 0
start = 1
elif buttonCredits.isOn(x, y):
print(x, y)
print('Credits')
menu = 0
start = 1
if (event.type == pygame.KEYDOWN):
if (pygame.K_0 <= event.key <= pygame.K_9):
number = int(event.unicode)
jukebox(number)
while start:
pygame.display.flip()
screen.blit(bgStart, (0, 0))
drawGrid(tabuleiro.tabuleiro)
for event in pygame.event.get():
if event.type == pygame.QUIT:
print('stopping')
running = 0
start = 0
elif event.type == pygame.KEYDOWN and (event.key == pygame.K_m or event.key == pygame.K_ESCAPE):
start = 0
menu = 1
if (event.type == pygame.MOUSEBUTTONUP):
coords = pygame.mouse.get_pos()
col = coords[1] // 80
line = coords[0] // 90
clickedCell = (line, col)
if (event.type == pygame.KEYDOWN):
if (clickedCell != None):
if (pygame.K_0 <= event.key <= pygame.K_9):
line = clickedCell[1]
col = clickedCell[0]
number = int(event.unicode)
if 0 <= line <= 8 and 0 <= col <= 8:
tabuleiro.setCell(line, col, number)
clickedCell = None
if (event.type == pygame.KEYDOWN):
if event.key == pygame.K_s:
tabuleiro.findFirst()
tabuleiro.solve()
elif event.key == pygame.K_r:
tabuleiro.reset()
if event.type == pygame.MOUSEBUTTONUP:
x, y = pygame.mouse.get_pos()
print(x, y)
if buttonSolve.isOn(x, y):
print('solving')
tabuleiro.solve()
elif buttonReset.isOn(x, y):
tabuleiro.reset()
tabuleiro.show()
elif buttonGoBack.isOn(x, y):
start = 0
menu = 1
elif buttonOptionsStart.isOn(x, y):
start = 0
menu = 1
pygame.quit()
Thanks in advance. I tried to search for the error on the internet, but didn't had any luck. I'll be grateful if someone can help :)
I have created this game which gives you a time limit to kill as many as the targets as you can. Below is the part of the code which pauses and unpauses the game. The problem I am having is that when I pause the game the timer which sets the time limit is still counting. How do I get this to stop?
paused = False
def button(msg, msg_two, x, y, w, h, i, a, fontsize, action=None):
global paused
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if (x < mouse[0] < (x+450)) and (y < mouse[1]<(y+100)):
pygame.draw.rect(gameDisplay, a, [x, y, w, h])
largeText = pygame.font.Font('freesansbold.ttf',fontsize)
TextSurf, TextRect = text_objects(msg, largeText, green)
TextRect.center = ((x+(w/2)),(y+(h/2)))
gameDisplay.blit(TextSurf, TextRect)
if click[0] == 1 and action != None:
if action == "play":
gameloop()
elif action == "quit":
game_quit()
elif action == "pause":
paused = True
pause()
elif action == "unpause":
unpause()
else:
pygame.draw.rect(gameDisplay, i, [x, y, w, h])
largeText = pygame.font.Font('freesansbold.ttf',fontsize)
TextSurf, TextRect = text_objects(msg_two, largeText, green)
TextRect.center = ((x+(w/2)),(y+(h/2)))
gameDisplay.blit(TextSurf, TextRect)
def game_quit():
pygame.quit()
quit()
def unpause():
global paused
paused = False
def pause():
pygame.mouse.set_visible(1)
button_x = (display_width/4)-150
button_y = display_height/1.5
button_width = 450
button_height = 100
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
largeText = pygame.font.Font('freesansbold.ttf',72)
TextSurf, TextRect = text_objects('paused', largeText, red)
TextRect.center = ((display_width/2),(display_height/3))
gameDisplay.blit(TextSurf, TextRect)
mouse = pygame.mouse.get_pos()
button("let's go", "carry on", button_x, button_y, button_width, button_height, blue, light_blue, 70, "unpause")
button("Bye then :(", "Leaving?", button_x+600, button_y, button_width, button_height, red, light_red, 70, "quit")
pygame.display.update()
clock.tick(15)
def gameloop():
gameExit = False
start = time.time()
elapsed = 0
while not gameExit and elapsed < 30:
button("Stop", "Stop", 1550, 0, 50, 50, red, light_red, 15, "pause")
elapsed = time.time() - start - (enemy_kills/2)
gameloop()
def game_intro():
pygame.mouse.set_visible(1)
button_x = (display_width/4)-150
button_y = display_height/1.5
button_width = 450
button_height = 100
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
largeText = pygame.font.Font('freesansbold.ttf',72)
TextSurf, TextRect = text_objects('Shoot Hitler and not trump', largeText, red)
TextRect.center = ((display_width/2),(display_height/3))
gameDisplay.blit(TextSurf, TextRect)
mouse = pygame.mouse.get_pos()
button("let's go", "wanna play?", button_x, button_y, button_width, button_height, blue, light_blue, 70, "play")
button("Bye then :(", "wanna quit?", button_x+600, button_y, button_width, button_height, red, light_red, 70, "quit")
pygame.display.update()
clock.tick(15)
game_intro()
I apologize if I have missed out important parts of the code. Inform me if I have
There are other strange things in this program that makes it hard to understand it enough to give you a proper answer.
For example, the fact that you call back gameloop() at the end of the gameloop function - it creates a recursive call that should no t be recursive at all.
Anyway, what happens is that you should move most of these functions inside a class - so that some of the state variables like paused can be an attribute of that class. Instances of the class are meant to be game plays.
In that case, your "start" variable would be made an attribute as well, so that it could be modified from within the unpause method.
You then could count the amount of paused time, and add that amount to the "start" tick count .
Or you can just make start a global variable and go on with your current pattern. Since I am not re-organizng all of your code just to answer the question, keeping the things more or less as they are would require you to do:
def gameloop():
global start
...
def pause():
global pause_start
pause_start = time.time()
...
def unpause():
global start, pause_start
pause_duration = time.time() - pause_start
start += pause_duration
...