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))