简体   繁体   中英

add variations/nodes to games in python-chess

I'm trying to build a chess engine by using the "python-chess"-package

My problem is that I want to add variations to games, so I used the method:

add_variation(move: chess.Move, *, comment: str = '', starting_comment: str = '', nags: Iterable[int] = []) → chess.pgn.ChildNode

If I have a game that has the moves.

1. e4 e5 2. Nf3 Nf6

Then I can do it for the first move :

pgn = io.StringIO("1. e4 e5 2. Nf3 Nf6 *")
game = chess.pgn.read_game(pgn)
board = game.board()
for move in game.mainline_moves():
    board.push(move)

node0 = game.add_variation(chess.Move.from_uci("d2d4"))
node = node0.add_variation(chess.Move.from_uci("d7d5"))
node = node.add_variation(chess.Move.from_uci("g1f3"))
node2 = game.add_variation(chess.Move.from_uci("a2a4"))

print(game)

And it will show

1. e4 ( 1. d4 d5 2. Nf3 ) ( 1. a4 ) 1... e5 2. Nf3 Nf6 *

Then I have two nodes for the first move. (one that starts with the move "d4" and one that starts with the move "a4")

My problem is that I can't find a way to do it for any other moves. So eg what's the way to do it, if I want to add nodes to the move 2. Nf3 ?

I think the solution to the problem is the method

chess.pgn.GameNode.next()

It returns the next node for the next move. However, it doesn't seem to be a direct way to get the node for a specific move, so you have to recursively apply the method to step through the moves forward to get to the specific node/move.

I made a short demonstration of the solution. It's a bit clunky and I suspect there are more elegant ways to do it by using the package. But I'm not an experienced programmer and the docs for the package is a bit lacking.

import chess
import chess.pgn
import io


def UCIString2Moves(str_moves):
    return [chess.Move.from_uci(move) for move in str_moves.split()]


# mainline
game = chess.pgn.read_game(
    io.StringIO("1.f4 d5 2.Nf3 g6 3.e3 Bg7 4.Be2 Nf6 5.0-0 0-0 6.d3 c5 *"))
board = game.board()
for move in game.mainline_moves():
    board.push(move)

# 1:st line, 1:st move in mainline
str_line1 = "a2a4 d7d5 g1f3 g7g6"
game.add_line(UCIString2Moves(str_line1))

# 2:nd line, 1:st move in mainline
str_line2 = "h2h5 d7d6 g1f3 g8f6"
game.add_line(UCIString2Moves(str_line2))

# 3:rd line, 2:nd move in mainline
move2_main = game.next()  # get the node for 2:nd move
str_line3 = "a7a6 g1f3 g8f6"
move2_main.add_line(UCIString2Moves(str_line3))

# 1:st variation, 3:rd move in mainline
move3_main = move2_main.next()  # get the node for 3:rd move
move3_main.add_variation(chess.Move.from_uci("c1c3"))
chess.pgn.GameNode.next()

print(game)

The notation for the moves and the variations/lines (no specific opening, just random moves):

1. f4 ( 1. a4 d5 2. Nf3 g6 ) ( 1. h5 d6 2. Nf3 Nf6 ) 
1... d5 ( 1... a6 2. Nf3 Nf6 ) 
2. Nf3 ( 2. Bc3 ) 2... g6 3. e3 Bg7 4. Be2 Nf6 5. O-O O-O 6. d3 c5 *

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM