def legal_moves(history, player_is_white):
    """"Generates a list of legal moves. Missing castling, en-passant."""
    board = ai.to_array(history)[-1]
    moves = list(ai.legal_moves(board, player_is_white))
    assert type(moves[0][0]) == array
    moves = [ai.from_array(move) for move, _score in moves]
    return moves
def performance_test():
    ai.transpositionTable = dict()
    ai.total_moves = 0
    _board = boards['difficultPosition']
    test_start_time = now()
    for depth in range(1, 6):
        start_time = now()
        best_move, _ = ai.search(_board, depth, ai.evaluate(_board), True, -99999, 99999)
        print('{}\t\t\t{}\t\t{:.3f}\t{}'.format(ai.total_moves, depth, now() - start_time, len(ai.transpositionTable)))
        # print('\n'.join(' '.join(piece for piece in row) for row in best_move.__reversed__()) + '\n')
    print('{} moves made per second'.format(int(ai.total_moves / (now() - test_start_time))))
def print_state(_turn, board, run_time, white_time_remaining,
                black_time_remaining, white, black, repeat):
    ai.recalculate_position_values(ai.to_array(board))
    print(
        f'----- {white.__name__} vs {black.__name__} match {repeat} move {_turn} -----'
    )
    print('\n'.join(' '.join(piece for piece in row)
                    for row in board.__reversed__()) + '\n')
    print('{} took: {:.3f} seconds'.format('white' if _turn % 2 else 'black',
                                           run_time))
    print('white time: {:.3f}'.format(white_time_remaining))
    print('black time: {:.3f}'.format(black_time_remaining))
    print('score: {:.1f}'.format(ai.evaluate(ai.to_array(board))))
def main(given_history, _, __):
    history = ai.to_array(given_history)
    player_is_white = len(history) % 2 == 1
    current_board = history[-1]
    best_score = -10**10
    for move, diff in ai.legal_moves(current_board, player_is_white):
        score = ai.evaluate(move)
        if not player_is_white:
            score = -score
        if score > best_score:
            best_score = score
            best_move = move
    print(f'search depth: 1')
    print(f'expected score: {best_score}')
    return ai.from_array(best_move)
To allow my chess engine to play a single game against my Dad I created this hacky new front end for my chess program.
Every time he made a move I edited the below board to match the new board state and then re-ran this file
to get the next move of my engine. The below board is the point at which my dad (lowercase, black) resigned."""

import time
import David_AI_v9

currentBoard = '''
r . . . . . r .
. k . . . . . .
p . . b . . . .
. b . . . . . p
P . . . P . . .
. R . P N . . .
. P . . . P P P
R . . . . . K .'''

playerIsWhite = True

history = [
    list([[piece for piece in line]
          for line in currentBoard.replace(' ', '').split()].__reversed__())
]
history = history * ((not playerIsWhite) + 1)
startTime = time.perf_counter()
chosen_move = David_AI_v9.main(history, 10, 10)
print('computation took', time.perf_counter() - startTime, 'seconds')
print('\n'.join(' '.join(piece for piece in row)
                for row in chosen_move.__reversed__()) + '\n')
def main(history, _, __):
    possible_moves = list(
        ai.legal_moves(ai.to_array(history[-1]),
                       len(history) % 2))
    move = random.choice(possible_moves)[0]
    return ai.from_array(move)
. . . R . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . p
. . . . . . . P
P . P . . P P .
. . . . . R K .'''
}

for key in boards:
    board = boards[key].replace(' ', '').split().__reversed__()
    board = array('u', ''.join(row + '_' * 8 for row in board))
    assert len(board) == 128
    boards[key] = board
    # print(len(list(ai.moves(position, True))))
assert abs(ai.evaluate(boards['initialPosition'])) < 0.000001
assert len(list(ai.moves(boards['initialPosition'], True))) == 20
assert len(list(ai.moves(boards['difficultPosition'], True))) == 42
assert len(list(ai.moves(boards['pawnTakePosition1'], True))) == 2
assert len(list(ai.moves(boards['pawnTakePosition1'], False))) == 3
assert len(list(ai.moves(boards['pawnTakePosition2'], True))) == 3
assert len(list(ai.moves(boards['pawnTakePosition2'], False))) == 2
assert len(list(ai.moves(boards['castlingPosition'], True))) == 16
assert len(list(ai.moves(boards['castlingPosition'], False))) == 16
assert not ai.is_check(boards['kingSavePosition'], True)
assert not ai.is_check(boards['kingSavePosition'], False)
assert not ai.is_check(boards['kingThreat'], True)
assert ai.is_check(boards['kingThreat'], False)
assert ai.position_value['N'][3 + 4 * 16] == ai.position_value['N'][4 + 3 * 16]
assert ai.position_value['N'][3 + 4 * 16] == -ai.position_value['n'][3 + 4 * 16]
assert ai.position_value['P'][16] < ai.position_value['P'][5 * 16]
def match(white, black, repeat):
    """This plays a single match between the white and black players and records the result."""
    print(
        f'\nMatch {repeat} between {white.__name__} on white and {black.__name__} on black'
    )
    # -------- turns and time -------
    black_moves = white_moves = 0
    black_time_taken = white_time_taken = 0

    history = [[[piece for piece in line]
                for line in initialBoard.replace(' ', '').split()]]
    history[0].reverse()

    to_record = {
        'score': 0.5,
        'cause': 'Draw due to reaching {} turns'.format(turnsToPlayFor)
    }
    for turn in range(1, 1 + turnsToPlayFor):
        player_is_white = turn % 2
        start_time = time.process_time()
        white_time = initialTime + white_moves * (
            timePerMove + (repeat - 1) * extraRepeatTime) - white_time_taken
        black_time = initialTime + black_moves * (
            timePerMove + (repeat - 1) * extraRepeatTime) - black_time_taken
        try:
            chosen_move = (white if player_is_white else black).main(
                copy.deepcopy(history), white_time, black_time)
        except shared.ThreeFoldRepetition:
            to_record = {
                'score':
                0.5,
                'cause':
                '{} called a draw with the threefold repetition rule'.format(
                    'White' if player_is_white else 'Black')
            }
            break
        except shared.FiftyMoveException:
            to_record = {
                'score':
                0.5,
                'cause':
                '{} called a draw with the 50 move rule'.format(
                    'White' if player_is_white else 'Black')
            }
            break
        run_time = time.process_time() - start_time
        assert isinstance(chosen_move, list)
        assert len(chosen_move) == 8
        for row in chosen_move:
            assert isinstance(row, list)
            assert len(row) == 8
            for char in row:
                assert isinstance(char, str)
                assert len(char) == 1
                assert char in 'KQRBNP.pnbrqk'
        if player_is_white:
            white_time_taken += run_time
            white_time = initialTime + white_moves * (
                timePerMove +
                (repeat - 1) * extraRepeatTime) - white_time_taken
            white_moves += 1
        else:
            black_time_taken += run_time
            black_time = initialTime + black_moves * (
                timePerMove +
                (repeat - 1) * extraRepeatTime) - black_time_taken
            black_moves += 1
        print_state(turn, chosen_move, run_time, white_time, black_time, white,
                    black, repeat)
        if chosen_move not in legal_moves(history, player_is_white):
            if player_is_white:
                to_record = {
                    'score': 0,
                    'cause': 'Black won because white made an illegal move'
                }
            else:
                to_record = {
                    'score': 1,
                    'cause': 'White won because black made an illegal move'
                }
            break
        # is_check can fail if it is is handed an illegal move
        # so these print statements are after the legal move check
        if ai.is_check(ai.to_array(chosen_move), True):
            print('white is in check')
        if ai.is_check(ai.to_array(chosen_move), False):
            print('black is in check')
        print()
        if ai.is_checkmate(ai.to_array(chosen_move), True):
            to_record = {'score': 0, 'cause': 'Black won by checkmate'}
            break
        if ai.is_checkmate(ai.to_array(chosen_move), False):
            to_record = {'score': 1, 'cause': 'White won by checkmate'}
            break
        if ai.is_stalemate(ai.to_array(chosen_move)):
            to_record = {'score': 0.5, 'cause': 'Draw due to stalemate'}
            break
        if white_time < 0:
            to_record = {
                'score': 0,
                'cause': 'Black won due to white running out of time'
            }
            break
        if black_time < 0:
            to_record = {
                'score': 1,
                'cause': 'White won due to black running out of time'
            }
            break
        # once the move has been shown valid add it to the history
        history.append(chosen_move)
    to_record['white_time_taken'] = white_time_taken
    to_record['black_time_taken'] = black_time_taken
    to_record['white_moves'] = white_moves
    to_record['black_moves'] = black_moves
    print(to_record['cause'])
    open(make_file_name(white, black, repeat),
         'w').write(current_versions + str(to_record))