Feb-06-2021, 09:22 PM
(Feb-06-2021, 04:44 PM)deanhystad Wrote: This should work. It uses list() to replace the code that built the moves_list.
def move_picker(game): board = game.board() num_moves = random.randint(5,50) for move in list(game.mainline_moves())[:num_moves]: board.push(move) sf.set_fen_position(board.fen()) print(game.headers["White"] + ' vs ' + game.headers["Black"]) print(game.headers["Event"]) display(board)Avoid using "global". It looks like the purpose of the global variable fen_position was to return my_board.fen to run_the_game() which did this "sf.set_fen_position(fen_position)". Does it make more sense to move this code from run_the_game() to move_picker()?
The problem with global variables is it isn't apparent where they are used. The only way to learn this information is search for the name, and since there can be local variables with the same name, this can be confusing. It is far better to return the needed information.
This is an example of returning the pieces required to do the bookkeeping. I like that each function has a well defined roll. Pick_game() randomly selects a game to play. It does not play the game. It does not cause the game to be played. It just does what the name implies. Play_game() plays the game. It doesn't pick the game. It doesn't display results. it doesn't update collect information that it doesn't use. Run_the_game() is the organizer and bookkeeper. It delegates selecting and playing the game.
import chess import chess.pgn from random import randint from stockfish import Stockfish sf = Stockfish("/Users/User/stockfish_20011801_x64.exe") def pick_game(pgn): """Play a randomly selected game""" game = chess.pgn.read_game(pgn) for _ in range(randint(2,550)): game = chess.pgn.read_game(pgn) return game def play_game(game): """Play randomly selected number of moves of game""" board = game.board() num_moves = randint(5,50) for move in list(game.mainline_moves())[:num_moves]: board.push(move) def run_the_game(game_file): with open(game_file) as pgn: game = pick_game(pgn) play_game(game) print(game.headers["White"] + ' vs ' + game.headers["Black"]) print(game.headers["Event"]) display(game.board()) sf.set_fen_position(game.board().fen()) position_evaluation = sf.get_evaluation() position_evaluation = position_evaluation["value"] print("Stockfish says... " + str(position_evaluation)) run_the_game("Capablanca.pgn")
Point well taken about global variables. I need to learn more about namespaces, scope, and passing variables between functions. I have been doing some reading on this today, so again thank you.
The code as you have it does not work fully. It is only returning the first move of any given game, so there is some issue here...
for move in list(game.mainline_moves())[:num_moves]: board.push(move)which I think has something to do with the mainline_moves method from the chess library. For some reason I do not understand, when I create a new list and append each move from the mainline moves output, and iterate through that list, then it works fine. But if I try to do like you're doing here and iterate through it directly and feed the output to 'board.push' then it does not function properly.
I have yet to understand that. I do see that '__ITER__' does not appear in the 'dir' for 'mainline_moves' however, but so then why does it work to iterate through it and create a new list? Who knows.
Thank you again