Latest version of Chess test prog for anyone who might be interested. It does not do en-passon or castling.

Best Regards

Chris

#!/opt/local/bin/pypy -u -tt
#!/opt/local/bin/pypy -u -tt -m cProfile
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Chris Hinsley, GPL V3 License

import sys, os, time
from operator import itemgetter
from array import array

MAX_PLY = 10
MAX_TIME_PER_MOVE = 10
PIECE_VALUE_FACTOR = 3

KING_VALUE, QUEEN_VALUE, ROOK_VALUE = 1000000, 9 * PIECE_VALUE_FACTOR, 5 * PIECE_VALUE_FACTOR BISHOP_VALUE, KNIGHT_VALUE, PAWN_VALUE = 3 * PIECE_VALUE_FACTOR, 3 * PIECE_VALUE_FACTOR, 1 * PIECE_VALUE_FACTOR

EMPTY, WHITE, BLACK = 0, 1, -1
NO_CAPTURE, MAY_CAPTURE, MUST_CAPTURE = 0, 1, 2

piece_type = {' ' : EMPTY, 'K' : BLACK, 'Q' : BLACK, 'R' : BLACK, 'B' : BLACK, 'N' : BLACK, 'P' : BLACK, \ 'k' : WHITE, 'q' : WHITE, 'r' : WHITE, 'b' : WHITE, 'n' : WHITE, 'p' : WHITE}

def display_board(board):
        print
        print '  a   b   c   d   e   f   g   h'
        print '+---+---+---+---+---+---+---+---+'
        for row in range(8):
                for col in range(8):
                        print '| %c' % board[row * 8 + col],
                print '|', 8 - row
                print '+---+---+---+---+---+---+---+---+'
        print

def piece_moves(board, index, vectors):
        piece = board[index]
        type = piece_type[piece]
        promote = 'QRBN' if type == BLACK else 'qrbn'
        cy, cx = divmod(index, 8)
        for dx, dy, length, flag in vectors:
                x, y = cx, cy
                if length == 0:
                        if piece == 'P':
                                length = 2 if (y == 1) else 1
                        else:
                                length = 2 if (y == 6) else 1
                while length > 0:
                        x += dx; y += dy; length -= 1
                        if (x < 0) or (x >=8) or (y < 0) or (y >= 8):
                                break
                        newindex = y * 8 + x
                        newpiece = board[newindex]
                        newtype = piece_type[newpiece]
                        if newtype == type:
                                break
                        if (flag == NO_CAPTURE) and (newtype != EMPTY):
                                break
                        if (flag == MUST_CAPTURE) and (newtype == EMPTY):
                                break
                        board[index] = ' '
                        if (y == 0 or y == 7) and piece in 'Pp':
                                for promote_piece in promote:
                                        board[newindex] = promote_piece
                                        yield board
                        else:
                                board[newindex] = piece
                                yield board
                        board[index], board[newindex] = piece, newpiece
                        if (flag == MAY_CAPTURE) and (newtype != EMPTY):
                                break

def piece_scans(board, index, vectors):
        cy, cx = divmod(index, 8)
        for dx, dy, length in vectors:
                x, y = cx, cy
                while length > 0:
                        x += dx; y += dy; length -= 1
                        if (0 <= x < 8) and (0 <= y < 8):
                                piece = board[y * 8 + x]
                                if piece != ' ':
                                        yield piece
                                        break

black_pawn_vectors = [(-1, 1, 1), (1, 1, 1)]
white_pawn_vectors = [(-1, -1, 1), (1, -1, 1)]
bishop_vectors = [(x, y, 7) for x, y in [(-1, -1), (1, 1), (-1, 1), (1, -1)]]
rook_vectors = [(x, y, 7) for x, y in [(0, -1), (-1, 0), (0, 1), (1, 0)]]
knight_vectors = [(x, y, 1) for x, y in [(-2, 1), (2, -1), (2, 1), (-2, -1), (-1, -2), (-1, 2), (1, -2), (1, 2)]]
queen_vectors = bishop_vectors + rook_vectors
king_vectors = [(x, y, 1) for x, y, _ in queen_vectors]

black_pawn_moves = [(0, 1, 0, NO_CAPTURE), (-1, 1, 1, MUST_CAPTURE), (1, 1, 1, MUST_CAPTURE)] white_pawn_moves = [(x, -1, length, flag) for x, _, length, flag in black_pawn_moves]
rook_moves = [(x, y, length, MAY_CAPTURE) for x, y, length in rook_vectors]
bishop_moves = [(x, y, length, MAY_CAPTURE) for x, y, length in bishop_vectors]
knight_moves = [(x, y, length, MAY_CAPTURE) for x, y, length in knight_vectors]
queen_moves = bishop_moves + rook_moves
king_moves = [(x, y, 1, flag) for x, y, _, flag in queen_moves]

moves = {'P' : black_pawn_moves, 'p' : white_pawn_moves, 'R' : rook_moves, 'r' : rook_moves, \ 'B' : bishop_moves, 'b' : bishop_moves, 'N' : knight_moves, 'n' : knight_moves, \
                'Q' : queen_moves, 'q' : queen_moves, 'K' : king_moves, 'k' : 
king_moves}

white_scans = [('QB', bishop_vectors), ('QR', rook_vectors), ('N', knight_vectors), ('K', king_vectors), ('P', white_pawn_vectors)] black_scans = [('qb', bishop_vectors), ('qr', rook_vectors), ('n', knight_vectors), ('k', king_vectors), ('p', black_pawn_vectors)]

def in_check(board, colour):
        if colour == BLACK:
                king_piece, scans = 'K', black_scans
        else:
                king_piece, scans = 'k', white_scans
        king_index = array.index(board, king_piece)
        for test_pieces, vectors in scans:
                pieces = [piece for piece in piece_scans(board, king_index, 
vectors)]
                for piece in test_pieces:
                        if piece in pieces:
                                return True
        return False

def all_moves(board, colour):
        for index, piece in enumerate(board):
                if piece_type[piece] == colour:
                        for new_board in piece_moves(board, index, 
moves[piece]):
                                if not in_check(new_board, colour):
                                        yield new_board

piece_values = {'K' : (KING_VALUE, 0), 'k' : (0, KING_VALUE), 'Q' : (QUEEN_VALUE, 0), 'q' : (0, QUEEN_VALUE), \ 'R' : (ROOK_VALUE, 0), 'r' : (0, ROOK_VALUE), 'B' : (BISHOP_VALUE, 0), 'b' : (0, BISHOP_VALUE), \ 'N' : (KNIGHT_VALUE, 0), 'n' : (0, KNIGHT_VALUE), 'P' : (PAWN_VALUE, 0), 'p' : (0, PAWN_VALUE)}

generic_position_values =  [0, 0, 0, 0, 0, 0, 0, 0, \
                                                        0, 1, 1, 1, 1, 1, 1, 0, 
\
                                                        0, 1, 2, 2, 2, 2, 1, 0, 
\
                                                        0, 1, 2, 3, 3, 2, 1, 0, 
\
                                                        0, 1, 2, 3, 3, 2, 1, 0, 
\
                                                        0, 1, 2, 2, 2, 2, 1, 0, 
\
                                                        0, 1, 1, 1, 1, 1, 1, 0, 
\
                                                        0, 0, 0, 0, 0, 0, 0, 0]

white_king_position_values =   [0, 0, 0, 0, 0, 0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                3, 3, 3, 3, 3, 
3, 3, 3]

black_king_position_values =   [3, 3, 3, 3, 3, 3, 3, 3, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0, \
                                                                0, 0, 0, 0, 0, 
0, 0, 0]

piece_positions = {'K' : black_king_position_values, 'k' : white_king_position_values, \
                                        'P' : generic_position_values, 'p' : 
generic_position_values, \
                                        'N' : generic_position_values, 'n' : 
generic_position_values, \
                                        'B' : generic_position_values, 'b' : 
generic_position_values, \
                                        'R' : generic_position_values, 'r' : 
generic_position_values, \
                                        'Q' : generic_position_values, 'q' : 
generic_position_values}

def evaluate(board):
        black_score, white_score = 0, 0
        for index, piece in enumerate(board):
                type = piece_type[piece]
                if type != EMPTY:
                        position_value = piece_positions[piece][index]
                        if type == BLACK:
                                black_score += position_value
                        else:
                                white_score += position_value
                        black_value, white_value = piece_values[piece]
                        black_score += black_value
                        white_score += white_value
        return white_score - black_score

start_time = time.time()

def next_move(board, colour, alpha, beta, ply):
        global start_time
        if ply <= 0:
                return evaluate(board) * colour
        for new_board in all_moves(board[:], colour):
                alpha = max(alpha, -next_move(new_board, -colour, -beta, 
-alpha, ply - 1))
                if alpha >= beta:
                        break
                if (time.time() - start_time) > MAX_TIME_PER_MOVE:
                        break
        return alpha

def best_move(board, colour):
        global start_time
all_boards = [(evaluate(new_board) * colour, new_board[:]) for new_board in all_moves(board, colour)]
        all_boards = sorted(all_boards, key = itemgetter(0), reverse = True)
        best_board, best_ply_board, start_time = board, board, time.time()
        for ply in range(1, MAX_PLY):
                print '\nPly =', ply
                alpha, beta = -KING_VALUE * 10, KING_VALUE * 10
                for new_board in all_boards:
                        score = -next_move(new_board[1], -colour, -beta, 
-alpha, ply - 1)
                        if (time.time() - start_time) > MAX_TIME_PER_MOVE:
                                return best_board
                        if score > alpha:
                                alpha, best_ply_board = score, new_board[1]
                                print '\b*',
                        else:
                                print '\b.',
                best_board = best_ply_board
        return best_board

def main():
board = array('c', 'RNBQKBNRPPPPPPPP pppppppprnbqkbnr')
        colour = WHITE
        os.system(['clear','cls'][os.name=='nt'])
        display_board(board)
        while True:
                print 'White to move:' if colour == WHITE else 'Black to move:'
                board = best_move(board, colour)
                colour = -colour
                os.system(['clear','cls'][os.name=='nt'])
                display_board(board)
                #raw_input()

if __name__ == '__main__':
        main()

--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to