My first PY project | Chess Game

For the discussion of Perl, Python, Ruby, and PHP and other interpreted languages.

My first PY project | Chess Game

Post by Hell ClaN on Sun Sep 11, 2011 3:57 am
([msg=61497]see My first PY project | Chess Game[/msg])

Hello everybody ...
Since this is my first post, I'll introduce myself briefly. I'm Hell ClaN, Egypt, 17, started learning VB about a year ago as a hobby and made some simple app.s . Just started to git into hacking, programming, web designing, etc, couple of months ago. Kept reading on HTS since 3 months but I've just registered.
---------
I've recently finished my first program in PY. It's a chess game involving board grid and all the game rules. It just needs a GUI, so I decided to learn pyQt to do that. But till now the game is drawn in text with a label for each piece. The code is in python 3. I don't know what are the differences between 2 and 3, so maybe you should edit it if you have python 2. I tried to make my code clear as much as possible, but if you find something ambiguous, just tell and I'll explain. So, here is the code :
(Please be patient and read it all if possible)

*** Got to explain that the plot is a list of 64 characters representing a 8x8 board. Each list item hold whether an object "piece" or None.

Code: Select all

                                        ### ~~ My Chess v 1.0 - 2011 ~~ ###
###----------------------------------------------------------------------------------------------------------------------###


# Here goes our imports ...
from math import fabs
import sys
from time import sleep

# Here goes our vars ...
global plot
global turn_is_white
global white_pieces
global cap_white_pieces
global black_pieces
global cap_black_pieces

# Here goes our functions ...
def get_position(position_of_piece):   # Changes the Letter/Number co-ordinates to index in Plot
    alpha_list = ['a','b','c','d','e','f','g','h']
    position = ((int(position_of_piece[1]) - 1) * 8) + alpha_list.index(position_of_piece[0])
    del alpha_list
    return position

def get_alpha_num(plot_index):   # Changes index in Plot to Letter/Number co-ordinates
    a = plot_index % 8
    n = int(plot_index / 8)
    alpha_list = ['a','b','c','d','e','f','g','h']
    num_list = ['1','2','3','4','5','6','7','8']
    return alpha_list[a] + num_list[n]

def get_num(position_of_piece):   # Gets the index of the row (zero-based)
    position = get_position(position_of_piece)
    num = int((position - (position % 8)) / 8)
    return num

def get_alpha(position_of_piece):   # Gets the index of column (zero-based)
    position = get_position(position_of_piece)
    alpha = position % 8
    return alpha

def get_piece_type(position_of_piece):   # Gets the attribute "Type" from the piece object on plot in (position_of_piece)
    position = get_position(position_of_piece)
    return plot[position].type

def get_piece_color(position_of_piece):  # Gets the attribute "Color" from the piece object on plot in (position_of_piece)
    position = get_position(position_of_piece)
    return plot[position].color

def check_input(input_command):   # Checks that the input is understandable to the program. Return False if it's not
    x = input_command.split(' ')  # the input will be like this : (A3 move D4)
    if len(x) != 3:
        return False
    else:
        x0 = x[0]; x1 = x[1]; x2 = x[2]
        alpha_list = ['a','b','c','d','e','f','g','h']
        num_list = ['1','2','3','4','5','6','7','8']
        com_list = ['move','capture','castle']
        if alpha_list.count(x0[0].lower()) != 1 or num_list.count(x0[1]) != 1 :
            return False
        elif com_list.count(x1.lower()) != 1 :
            return False
        elif alpha_list.count(x2[0].lower()) != 1 or num_list.count(x2[1]) != 1 :
            return False
        else :
            return True

def is_line(point_1, point_2):   # Returns True if the two points are ends of a straight line
    if point_1 == point_2 :
        return False
    elif get_alpha(point_1) == get_alpha(point_2):
        return True
    elif get_num(point_1) == get_num(point_2):
        return True
    elif fabs((get_num(point_1) - get_num(point_2))) == fabs((get_alpha(point_1) - get_alpha(point_2))):
        return True
    else :
        return False

def get_line_prop(point_1, point_2):   # Gets a list of line properties
    prop = []
    # Property [0] : Get orientation of the line ...
    if get_alpha(point_1) == get_alpha(point_2) :
        prop.append('v')
    elif get_num(point_1) == get_num(point_2) :
        prop.append('h')
    else :
        prop.append('d')
    # Property [1] : Get direction of line ...
    ddd = ''
    if get_num(point_1) < get_num(point_2) :
        ddd = 'u'
    elif get_num(point_1) > get_num(point_2) :
        ddd = 'd'
    if get_alpha(point_1) < get_alpha(point_2) :
        ddd = ddd + 'r'
    elif get_alpha(point_1) > get_alpha(point_2) :
        ddd = ddd + 'l'
    prop.append(ddd)
    # Property [2] : Get length of the line ...
    if prop[0] == 'v' :
        prop.append(int(fabs(get_num(point_1) - get_num(point_2))))
    else :
        prop.append(int(fabs(get_alpha(point_1) - get_alpha(point_2))))
    return prop

def distance_is_clear(current_position, target_position):   # Returns True if the line between two points is clear
    x = 0                                                   # Note: the end points are excluded
    d = get_line_prop(current_position, target_position)[1] # i.e. if a piece is at target_position, but way is clear, ruturn True
    l = get_line_prop(current_position, target_position)[2]
    for i in range(1, int(l)):
        if d.count('r') == 1 :
            x = x + 1
        elif d.count('l') == 1 :
            x = x - 1
        if d.count('u') == 1 :
            x = x + 8
        elif d.count('d') == 1 :
            x = x - 8
        if plot[get_position(current_position) + x] != None :
            return False
    return True
           
def move_is_possible(current_position, target_position):   # Makes sure that the piece can make a move to location
    if plot[get_position(current_position)] == None :
        return False
    p = get_line_prop(current_position, target_position)
    d = distance_is_clear(current_position, target_position)
    l = is_line(current_position, target_position)
    pType = get_piece_type(current_position)
    if (get_piece_color(current_position) == 'white')!= turn_is_white :
        return False
    elif plot[get_position(target_position)] != None:
        return False
    else:
        if pType == 'pawn':
            if (turn_is_white == False and p[1] != 'd') or (turn_is_white == True and p[1] != 'u'):
                return False
            elif ((turn_is_white == False and get_num(current_position) == 6) or
                  (turn_is_white == True and get_num(current_position) == 1)) and p[2] > 2 :
                return False
            elif ((turn_is_white == False and get_num(current_position) != 6) or
                  (turn_is_white == True and get_num(current_position) != 1)) and p[2] != 1 :
                    return False
            elif d == False:
                return False
            elif l == False :
                return False
            else :
                return True
        elif pType == 'rook':
            if d == False :
                return False
            elif l == False :
                return False
            elif p[0] == 'd' :
                return False
            else :
                return True
        elif pType == 'bishop':
            if d == False :
                return False
            elif l == False :
                return False
            elif p[0] != 'd' :
                return False
            else :
                return True
        elif pType == 'queen' :
            if d == False :
                return False
            elif l == False :
                return False
            else :
                return True
        elif pType == 'king' :
            if d == False :
                return False
            elif l == False :
                return False
            elif p[2] != 1 :
                return False
            else :
                return True
        elif pType == 'knight' :
            if (fabs(get_num(current_position) - get_num(target_position)) == 2 and
                fabs(get_alpha(current_position) - get_alpha(target_position)) == 1) == False and (fabs(get_num(current_position) - get_num(target_position)) == 1 and
                fabs(get_alpha(current_position) - get_alpha(target_position)) == 2) == False :
                return False
            else :
                return True

def capture_is_possible(current_position, target_position):   # Makes sure a piece can capture another at location
    p = get_line_prop(current_position, target_position)
    d = distance_is_clear(current_position, target_position)
    pType = get_piece_type(current_position)
    l = is_line(current_position, target_position)
    if (get_piece_color(current_position) == 'white') != turn_is_white :
        return False
    elif plot[get_position(target_position)] == None:
        return False
    elif (get_piece_color(target_position) == 'white') == turn_is_white :
        return False
    else:
        if pType == 'pawn':
            if (turn_is_white == False and ['dr','dl'].count(p[1]) != 1) or (turn_is_white == True and ['ur','ul'].count(p[1]) != 1):
                return False
            elif l == False :
                return False
            elif p[2] != 1 :
                return False
            elif d == False:
                return False
            else :
                return True
        elif pType == 'rook':
            if d == False :
                return False
            elif l == False :
                return False
            elif p[0] == 'd' :
                return False
            else :
                return True
        elif pType == 'bishop':
            if d == False :
                return False
            elif l == False :
                return False
            elif p[0] != 'd' :
                return False
            else :
                return True
        elif pType == 'queen' :
            if d == False :
                return False
            elif l == False :
                return False
            else :
                return True
        elif pType == 'king' :
            if d == False :
                return False
            elif l == False :
                return False
            elif p[2] != 1 :
                return False
            else :
                return True
        elif pType == 'knight' :
            if (fabs(get_num(current_position) - get_num(target_position)) == 2 and
                fabs(get_alpha(current_position) - get_alpha(target_position)) == 1) == False and (fabs(get_num(current_position) - get_num(target_position)) == 1 and
                fabs(get_alpha(current_position) - get_alpha(target_position)) == 2) == False :
                return False
            else :
                return True

def move_capture(current_position, target_position):   # Makes the move/capture after program makes sure the move/capture is leagal
    if get_piece_type(current_position) == 'king' or get_piece_type(current_position) == 'rook' :
        plot[get_position(current_position)].has_moved = True
    if plot[get_position(target_position)] != None :
        if turn_is_white == True:
            cap_black_pieces.append(black_pieces.pop(black_pieces.index(plot[get_position(target_position)])))
        else :
            cap_white_pieces.append(white_pieces.pop(white_pieces.index(plot[get_position(target_position)])))
    plot[get_position(target_position)] = plot[get_position(current_position)]
    plot[get_position(current_position)] = None

def castle_is_possible(current_position, target_position):  # Checks if castling is possible
    if plot[get_position(current_position)] == None :
        return False
    elif get_piece_type(current_position) != 'king' :
        return False
    elif plot[get_position(current_position)].has_moved == True :
        return False
    elif (get_piece_color(current_position) == 'white') != turn_is_white :
        return False
    elif is_line(current_position, target_position) == False:
        return False
    elif get_line_prop(current_position, target_position)[0] != 'h':
        return False
    elif get_line_prop(current_position, target_position)[2] != 2 :
        return False
    else :
        if get_line_prop(current_position, target_position)[1] == 'r' :
            if turn_is_white == False :
                x = 'h8'
            else :
                x = 'h1'
        else :
            if turn_is_white == False :
                x = 'a8'
            else :
                x = 'a1'
        if distance_is_clear(current_position, x) == False:
            return False
        elif plot[get_position(x)] != 'rook' :
            return False
        elif plot[get_position(x)].has_moved == True :
            return False
        else :
            return True
       
def castle(current_position, target_position):   # Makes a castle move
    k = plot[get_position(current_position)]
    move_capture(current_position, target_position)
    if get_line_prop(current_position, target_position)[1] == 'r' :
        plot[plot.index(k) - 1] = plot[get_position(x)]
    else :
        plot[plot.index(k) + 1] = plot[get_position(x)]
    plot[get_position(x)] = None

def player_is_checked():   # Returns True if the player with the current turn is checked
    if turn_is_white == False:
        x = get_alpha_num(plot.index(b_king))
        for white_piece in white_pieces:
            if capture_is_possible(get_alpha_num(white_piece.location()), x) == True:
                return True
        return False
    else :
        x = get_alpha_num(plot.index(w_king))
        for black_piece in black_pieces:
            if capture_is_possible(get_alpha_num(black_piece.location()), x) == True:
                return True
        return False

def player_willbe_checked(current_position, target_position, command):   # Makes a mock test, whether after the move the king will be checked or not
    p = []
    p.extend(plot)   
    t = plot[get_position(target_position)]
    check = False
    if command == 'm' or command == 'c' :
        move_capture(current_position, target_position)
    elif command == 's' :
        castle(current_position, target_position)
    if player_is_checked() == True :
        check = True
    while len(plot) != 0 :
        plot.remove(plot[0])
    plot.extend(p)
    if t != None :
        if turn_is_white == True :
            black_pieces.append(cap_black_pieces.pop(cap_black_pieces.index(t)))
        else :
            white_pieces.append(cap_white_pieces.pop(cap_white_pieces.index(t)))
    return check

def player_is_stalemated():   # Checks if the player is stalemated
    if player_is_checked() == True :
        return False
    else :
        dirs = [8, 9, 1, -7, -8, -9, -1, 7]
        if turn_is_white == True :
            if white_pieces != [w_king] :
                return False
            else :
                for i in dirs :
                    if player_willbe_checked(w_king.location(), w_king.location() + i, 'm') != True :
                        return False
                return True
        else :
            if black_pieces != [b_king] :
                return False
            else :
                for i in dirs :
                    if player_willbe_checked(b_king.location(), b_king.location() + i, 'm') != True :
                        return False
                return True

def player_is_mated():   # Checks if the player is mated
    if player_is_checked != True :
        return False
    g = get_alpha_num
    # Check that king can't make any move ...
    # if he can, return False ...
    dirs = [8, 9, 1, -7, -8, -9, -1, 7]
    if turn_is_white == True :
        for i in dirs :
           if player_willbe_checked(w_king.location(), w_king.location() + i, 'm') != True :
                return False
    else :
        for i in dirs :
            if player_willbe_checked(b_king.location(), b_king.location() + i, 'm') != True :
                return False
    # Assign a variable to the piece ...
    # which is checking the king ...
    thret = []
    if turn_is_white == True :
        for bbb in black_pieces :
            turn_is_white = False
            if captuer_is_possible(g(bbb.location()), g(w_king.location())) == True :
                threat.append(bbb)
        turn_is_white == True
    else :
        for www in black_pieces :
            turn_is_white = True
            if captuer_is_possible(g(www.location()), g(b_king.location())) == True :
                threat.append(www)
        turn_is_white == False
    # Check that no piece can capture the one ...
    # that has checked the king ...
    if len(threat) == 1 :
        if turn_is_white == True :
            for w in white_pieces :
                if capture_is_possible(g(w.location()), g(threat[0].location())) == True :
                    if player_willbe_checked(g(w.location()), g(threat[0].location()), 'c') == False :
                        return False
        else :
            for b in black_pieces :
                if capture_is_possible(g(b.location()), g(threat[0].location())) == True :
                    if player_willbe_checked(g(b.location()), g(threat[0].location()), 'c') == False :
                        return False
    # Check that no piece can intercept ...
    # the way between the king and piece ...
    # that has checked the king ...
    if len(threat) == 1 :
        dist = []
        x = 0
        d = get_line_prop(current_position, target_position)[1]
        l = get_line_prop(current_position, target_position)[2]
        for i in range(1, int(l)):
            if d.count('r') == 1 :
                x = x + 1
            elif d.count('l') == 1 :
                x = x - 1
            if d.count('u') == 1 :
                x = x + 8
            elif d.count('d') == 1 :
                x = x - 8
            dist.append(g(plot[get_position(current_position) + x]))
        if turn_is_white == True :
            for ww in white_pieces :
                for loc in dist :
                    if move_is_possible(g(ww.location()), loc) == True :
                        if player_willbe_checked(g(ww.location()), loc, 'm') == False :
                            return False
        else :
            for bb in white_pieces :
                for loc in dist :
                    if move_is_possible(g(bb.location()), loc) == True :
                        if player_willbe_checked(g(bb.location()), loc, 'm') == False :
                            return False
    return True

def pl(location):  # A function to get the label of a piece on Plot to draw it on the board
    if plot[get_position(location)] == None :
        return '   '
    else :
        return plot[get_position(location)].label

# Here goes our classes ...
class piece():   # Main class of all pieces ...
    def __init__(self, c, t):
        self.color = c
        self.type = t
        self.label = c[0] + t[0:2]   # Label is conssisting of 3 letters, Color, and first two of the Type; i.e. wpa
        if t == 'king' or t == 'rook':
            self.has_moved = False
    def location(self):   # A method to return the location of piece in a Plot-Index format
        return plot.index(self)
   
# Start game ...
while True:
    # This is the programe loop. When break out of it, excec stops.
    # When loop, a new game is started and variables are initialized.

    print('New Game !!')
    turn_is_white = True
   
    b_king = piece('black','king') ; w_king = piece('white','king')
    b_queen1 = piece('black', 'queen') ; w_queen1 = piece('white', 'queen')
    b_bishop1 = piece('black', 'bishop') ; w_bishop1 = piece('white', 'bishop')
    b_bishop2 = piece('black', 'bishop') ; w_bishop2 = piece('white', 'bishop')
    b_knight1 = piece('black', 'knight') ; w_knight1 = piece('white', 'knight')
    b_knight2 = piece('black', 'knight') ; w_knight2 = piece('white', 'knight')
    b_rook1 = piece('black', 'rook') ; w_rook1 = piece('white', 'rook')
    b_rook2 = piece('black', 'rook') ; w_rook2 = piece('white', 'rook')
    b_pawn1 = piece('black', 'pawn') ; w_pawn1 = piece('white', 'pawn')
    b_pawn2 = piece('black', 'pawn') ; w_pawn2 = piece('white', 'pawn')
    b_pawn3 = piece('black', 'pawn') ; w_pawn3 = piece('white', 'pawn')
    b_pawn4 = piece('black', 'pawn') ; w_pawn4 = piece('white', 'pawn')
    b_pawn5 = piece('black', 'pawn') ; w_pawn5 = piece('white', 'pawn')
    b_pawn6 = piece('black', 'pawn') ; w_pawn6 = piece('white', 'pawn')
    b_pawn7 = piece('black', 'pawn') ; w_pawn7 = piece('white', 'pawn')
    b_pawn8 = piece('black', 'pawn') ; w_pawn8 = piece('white', 'pawn')
   
    plot = [w_rook1,w_knight1,w_bishop1,w_queen1,w_king,w_bishop2,w_knight2,w_rook2,
            w_pawn1,w_pawn2,w_pawn3,w_pawn4,w_pawn5,w_pawn6,w_pawn7,w_pawn8,
            None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
            None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
            b_pawn1,b_pawn2,b_pawn3,b_pawn4,b_pawn5,b_pawn6,b_pawn7,b_pawn8,
            b_rook1,b_knight1,b_bishop1,b_queen1,b_king,b_bishop2,b_knight2,b_rook2]

    white_pieces = [w_rook1,w_knight1,w_bishop1,w_queen1,w_king,w_bishop2,w_knight2,w_rook2,
            w_pawn1,w_pawn2,w_pawn3,w_pawn4,w_pawn5,w_pawn6,w_pawn7,w_pawn8]
   
    black_pieces = [b_pawn1,b_pawn2,b_pawn3,b_pawn4,b_pawn5,b_pawn6,b_pawn7,b_pawn8,
            b_rook1,b_knight1,b_bishop1,b_queen1,b_king,b_bishop2,b_knight2,b_rook2]
   
    cap_white_pieces = []; cap_black_pieces = []

   
    while True:
    # Game actions go here ...
       
        print (' ╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗')
        print ('8║'+pl('a8')+'║'+pl('b8')+'║'+pl('c8')+'║'+pl('d8')+'║'+pl('e8')+'║'+pl('f8')+'║'+pl('g8')+'║'+pl('h8')+'║')
        print (' ╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣')
        print ('7║'+pl('a7')+'║'+pl('b7')+'║'+pl('c7')+'║'+pl('d7')+'║'+pl('e7')+'║'+pl('f7')+'║'+pl('g7')+'║'+pl('h7')+'║')
        print (' ╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣')
        print ('6║'+pl('a6')+'║'+pl('b6')+'║'+pl('c6')+'║'+pl('d6')+'║'+pl('e6')+'║'+pl('f6')+'║'+pl('g6')+'║'+pl('h6')+'║')
        print (' ╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣')
        print ('5║'+pl('a5')+'║'+pl('b5')+'║'+pl('c5')+'║'+pl('d5')+'║'+pl('e5')+'║'+pl('f5')+'║'+pl('g5')+'║'+pl('h5')+'║')
        print (' ╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣')
        print ('4║'+pl('a4')+'║'+pl('b4')+'║'+pl('c4')+'║'+pl('d4')+'║'+pl('e4')+'║'+pl('f4')+'║'+pl('g4')+'║'+pl('h4')+'║')
        print (' ╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣')
        print ('3║'+pl('a3')+'║'+pl('b3')+'║'+pl('c3')+'║'+pl('d3')+'║'+pl('e3')+'║'+pl('f3')+'║'+pl('g3')+'║'+pl('h3')+'║')
        print (' ╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣')
        print ('2║'+pl('a2')+'║'+pl('b2')+'║'+pl('c2')+'║'+pl('d2')+'║'+pl('e2')+'║'+pl('f2')+'║'+pl('g2')+'║'+pl('h2')+'║')
        print (' ╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣')
        print ('1║'+pl('a1')+'║'+pl('b1')+'║'+pl('c1')+'║'+pl('d1')+'║'+pl('e1')+'║'+pl('f1')+'║'+pl('g1')+'║'+pl('h1')+'║')
        print (' ╚═══╩═══╩═══╩═══╩═══╩═══╩═══╩═══╝')
        print ('   A   B   C   D   E   F   G   H')

        _pass_ = False
        if player_is_stalemated() == True :
            print ("Stalemate !! It's a draw")
            x = input ('Play Again ??!')
            if x.lower() == 'y' :
                break
            else :
                sys.exit()
        elif player_is_mated() == True :
            if turn_is_white == True :
                print('Black Wins !!')
            else :
                print('White Wins !!')
            x = input ('Play Again ??!')
            if x.lower() == 'y' :
                break
            else :
                sys.exit()
        elif player_is_checked() == True :
            print('Check')
        if turn_is_white == True :
            print("White's Turn ...")
        else :
            print("Black's Turn ...")
        inp = input('>> ')
        if check_input(inp) == False :
            print('wrong input')
            _pass_ = True
            pass
        else :
            inp = inp.split(' ')
            l1 = inp[0]
            l2 = inp[2]
            if inp[1] == 'move' :
                if move_is_possible(l1, l2) == False :
                    print("move isn't possible")
                    _pass_ = True
                    pass
                elif player_willbe_checked(l1, l2, 'm') == True :
                    print("move isn't possible; king may be captured")
                    _pass_ = True
                    pass
                else :
                    move_capture(l1, l2)
            elif inp[1] == 'capture' :
                if capture_is_possible(l1, l2) == False :
                    print("capture isn't possible")
                    _pass_ = True
                    pass
                elif player_willbe_checked(l1, l2, 'c') == True :
                    print("capture isn't possible; king may be captured")
                    _pass_ = True
                    pass
                else :
                    move_capture(l1, l2)
            elif inp[1] == 'castle' :
                if castle_is_possible(l1, l2) == False :
                    print("castle isn't possible")
                    _pass_ = True
                    pass
                elif player_willbe_checked(l1, l2, 's') == True :
                    print("castle isn't possible; king may be captured")
                    _pass_ = True
                    pass
                else :
                    castle(l1, l2)
            if _pass_ == False :
                turn_is_white = not turn_is_white   # Changes the turn to the other player ...

_____________________________________

So, please test it and comment. Post me Bug-reports if found.
I'm willing to learn pyQt soon and post the new graphical-user-interface edition.
Thanks for all ...
Hell ClaN
New User
New User
 
Posts: 2
Joined: Sun Sep 11, 2011 4:06 am
Blog: View Blog (0)


Return to Interpreted Languages

Who is online

Users browsing this forum: No registered users and 0 guests