GithubHelp home page GithubHelp logo

niklasf / python-chess Goto Github PK

View Code? Open in Web Editor NEW
2.3K 71.0 507.0 12.29 MB

A chess library for Python, with move generation and validation, PGN parsing and writing, Polyglot opening book reading, Gaviota tablebase probing, Syzygy tablebase probing, and UCI/XBoard engine communication

Home Page: https://python-chess.readthedocs.io/en/latest/

License: GNU General Public License v3.0

Python 100.00%
chess fen epd pgn polyglot syzygy gaviota uci xboard

python-chess's Introduction

python-chess: a chess library for Python

Test status

PyPI package

Docs

Chat on Gitter

Introduction

python-chess is a chess library for Python, with move generation, move validation, and support for common formats. This is the Scholar's mate in python-chess:

>>> import chess

>>> board = chess.Board()

>>> board.legal_moves  # doctest: +ELLIPSIS
<LegalMoveGenerator at ... (Nh3, Nf3, Nc3, Na3, h3, g3, f3, e3, d3, c3, ...)>
>>> chess.Move.from_uci("a8a1") in board.legal_moves
False

>>> board.push_san("e4")
Move.from_uci('e2e4')
>>> board.push_san("e5")
Move.from_uci('e7e5')
>>> board.push_san("Qh5")
Move.from_uci('d1h5')
>>> board.push_san("Nc6")
Move.from_uci('b8c6')
>>> board.push_san("Bc4")
Move.from_uci('f1c4')
>>> board.push_san("Nf6")
Move.from_uci('g8f6')
>>> board.push_san("Qxf7")
Move.from_uci('h5f7')

>>> board.is_checkmate()
True

>>> board
Board('r1bqkb1r/pppp1Qpp/2n2n2/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 4')

Installing

Requires Python 3.8+. Download and install the latest release:

pip install chess

Features

  • Includes mypy typings.
  • IPython/Jupyter Notebook integration. SVG rendering docs.

    >>> board  # doctest: +SKIP

    r1bqkb1r/pppp1Qpp/2n2n2/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR

  • Chess variants: Standard, Chess960, Suicide, Giveaway, Atomic, King of the Hill, Racing Kings, Horde, Three-check, Crazyhouse. Variant docs.
  • Make and unmake moves.

    >>> Nf3 = chess.Move.from_uci("g1f3")
    >>> board.push(Nf3)  # Make the move
    
    >>> board.pop()  # Unmake the last move
    Move.from_uci('g1f3')
  • Show a simple ASCII board.

    >>> board = chess.Board("r1bqkb1r/pppp1Qpp/2n2n2/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 4")
    >>> print(board)
    r . b q k b . r
    p p p p . Q p p
    . . n . . n . .
    . . . . p . . .
    . . B . P . . .
    . . . . . . . .
    P P P P . P P P
    R N B . K . N R
  • Detects checkmates, stalemates and draws by insufficient material.

    >>> board.is_stalemate()
    False
    >>> board.is_insufficient_material()
    False
    >>> board.outcome()
    Outcome(termination=<Termination.CHECKMATE: 1>, winner=True)
  • Detects repetitions. Has a half-move clock.

    >>> board.can_claim_threefold_repetition()
    False
    >>> board.halfmove_clock
    0
    >>> board.can_claim_fifty_moves()
    False
    >>> board.can_claim_draw()
    False

    With the new rules from July 2014, a game ends as a draw (even without a claim) once a fivefold repetition occurs or if there are 75 moves without a pawn push or capture. Other ways of ending a game take precedence.

    >>> board.is_fivefold_repetition()
    False
    >>> board.is_seventyfive_moves()
    False
  • Detects checks and attacks.

    >>> board.is_check()
    True
    >>> board.is_attacked_by(chess.WHITE, chess.E8)
    True
    
    >>> attackers = board.attackers(chess.WHITE, chess.F3)
    >>> attackers
    SquareSet(0x0000_0000_0000_4040)
    >>> chess.G2 in attackers
    True
    >>> print(attackers)
    . . . . . . . .
    . . . . . . . .
    . . . . . . . .
    . . . . . . . .
    . . . . . . . .
    . . . . . . . .
    . . . . . . 1 .
    . . . . . . 1 .
  • Parses and creates SAN representation of moves.

    >>> board = chess.Board()
    >>> board.san(chess.Move(chess.E2, chess.E4))
    'e4'
    >>> board.parse_san('Nf3')
    Move.from_uci('g1f3')
    >>> board.variation_san([chess.Move.from_uci(m) for m in ["e2e4", "e7e5", "g1f3"]])
    '1. e4 e5 2. Nf3'
  • Parses and creates FENs, extended FENs and Shredder FENs.

    >>> board.fen()
    'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
    >>> board.shredder_fen()
    'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w HAha - 0 1'
    >>> board = chess.Board("8/8/8/2k5/4K3/8/8/8 w - - 4 45")
    >>> board.piece_at(chess.C5)
    Piece.from_symbol('k')
  • Parses and creates EPDs.

    >>> board = chess.Board()
    >>> board.epd(bm=board.parse_uci("d2d4"))
    'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - bm d4;'
    
    >>> ops = board.set_epd("1k1r4/pp1b1R2/3q2pp/4p3/2B5/4Q3/PPP2B2/2K5 b - - bm Qd1+; id \"BK.01\";")
    >>> ops == {'bm': [chess.Move.from_uci('d6d1')], 'id': 'BK.01'}
    True
  • Detects absolute pins and their directions.
  • Reads Polyglot opening books. Docs.

    >>> import chess.polyglot
    
    >>> book = chess.polyglot.open_reader("data/polyglot/performance.bin")
    
    >>> board = chess.Board()
    >>> main_entry = book.find(board)
    >>> main_entry.move
    Move.from_uci('e2e4')
    >>> main_entry.weight
    1
    
    >>> book.close()
  • Reads and writes PGNs. Supports headers, comments, NAGs and a tree of variations. Docs.

    >>> import chess.pgn
    
    >>> with open("data/pgn/molinari-bordais-1979.pgn") as pgn:
    ...     first_game = chess.pgn.read_game(pgn)
    
    >>> first_game.headers["White"]
    'Molinari'
    >>> first_game.headers["Black"]
    'Bordais'
    
    >>> first_game.mainline()  # doctest: +ELLIPSIS
    <Mainline at ... (1. e4 c5 2. c4 Nc6 3. Ne2 Nf6 4. Nbc3 Nb4 5. g3 Nd3#)>
    
    >>> first_game.headers["Result"]
    '0-1'
  • Probe Gaviota endgame tablebases (DTM, WDL). Docs.
  • Probe Syzygy endgame tablebases (DTZ, WDL). Docs.

    >>> import chess.syzygy
    
    >>> tablebase = chess.syzygy.open_tablebase("data/syzygy/regular")
    
    >>> # Black to move is losing in 53 half moves (distance to zero) in this
    >>> # KNBvK endgame.
    >>> board = chess.Board("8/2K5/4B3/3N4/8/8/4k3/8 b - - 0 1")
    >>> tablebase.probe_dtz(board)
    -53
    
    >>> tablebase.close()
  • Communicate with UCI/XBoard engines. Based on asyncio. Docs.

    >>> import chess.engine
    
    >>> engine = chess.engine.SimpleEngine.popen_uci("stockfish")
    
    >>> board = chess.Board("1k1r4/pp1b1R2/3q2pp/4p3/2B5/4Q3/PPP2B2/2K5 b - - 0 1")
    >>> limit = chess.engine.Limit(time=2.0)
    >>> engine.play(board, limit)  # doctest: +ELLIPSIS
    <PlayResult at ... (move=d6d1, ponder=c1d1, info={...}, draw_offered=False, resigned=False)>
    
    >>> engine.quit()

Selected projects

If you like, share interesting things you are using python-chess for, for example:

image

https://syzygy-tables.info/

A website to probe Syzygy endgame tablebases

image

https://maiachess.com/

A human-like neural network chess engine

image

clente/chess

Oppinionated wrapper to use python-chess from the R programming language

image

https://crazyara.org/

Deep learning for Crazyhouse

image

http://johncheetham.com

A GUI to play against UCI chess engines

image

https://pettingzoo.farama.org

A multi-agent reinforcement learning environment

image

cli-chess

A highly customizable way to play chess in your terminal

Prior art

Thanks to the Stockfish authors and thanks to Sam Tannous for publishing his approach to avoid rotated bitboards with direct lookup (PDF) alongside his GPL2+ engine Shatranj. Some move generation ideas are taken from these sources.

Thanks to Ronald de Man for his Syzygy endgame tablebases. The probing code in python-chess is very directly ported from his C probing code.

Thanks to Kristian Glass for transferring the namespace chess on PyPI.

License

python-chess is licensed under the GPL 3 (or any later version at your option). Check out LICENSE.txt for the full text.

python-chess's People

Contributors

ainnuganti avatar alvanieto avatar amdw avatar bobotig avatar cash avatar ddugovic avatar donlarry avatar gbtami avatar hugovk avatar ianfab avatar jnavila avatar johndoknjas avatar jsonn avatar kraktus avatar laniakea64 avatar markzh avatar mauricesvp avatar mk-chan avatar niklasf avatar pedantichacker avatar rgerkin avatar rheber avatar salmanjnr avatar self-perfection avatar tanmay2004 avatar tesseracta avatar themactep avatar thomas-daniels avatar trevorbayless avatar vdbergh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-chess's Issues

MultiPV scores

When using MultiPV score for engine, can't get scores of those lines, but only variations themselves.

Incomplete SAN

There are a couple of things that are not working good with pos.make_move_from_san method. In PGN format castling is denoted as O-O and O-O-O, but here at least Kg1 and Kc1 works for white, and Kg8 and Kc8 works for black.

The bigger problem are pawn promotions, for example, load this FEN:
8/8/8/3R1P2/8/2k2K2/3p4/r7 b - - 0 82

One of the legal moves is d1=Q+, none of the combinations that I tried worked for pos.make_move_from_san method. I know that longer notation works "d1d2q" (I listed the legal moves with get_legal_moves), but SAN is a standard in pgn files.

Documentation error

Hi

I just spotted an error in the documentation files in the Core section.

The line "chess.H7 = 62" should read "chess.G8 = 62"

Bitboard caching during pgn parsing

I have the following issue:

  • I parse a pgn and get a resulting game
  • each game node has self.board_cached = None initially
  • suppose now I jump to move no. 80 and try to get that board (this can e.g. happen in my chess GUI, if the user decides to immediately to jump to that position. Then I need the san (for redrawing) which triggers the board as well as the board itself (for e.g. sending the fen position to the engine, or for checking validity of user inputed moves etc.)
  • A call goes to node.board which triggers calls to recursively traverse up to the root node, compute board(), and back down in the tree. This is SLOW, especially IF the game is large. This game (http://www.chessgames.com/perl/nph-chesspgn?text=1&gid=1497429) with 271 moves is a nice example. It gets even worse if this game would be annotated with lots of variations.
  • After that everything is fine, since all board_caches are "initialized". I can now get boards quickly; even if some nodes change: As long as not all parent nodes are changed, the board can quickly be rebuild by one of the parents, and I can quickly get e.g. the new san.

Current Solution:

  • I currently load a game, and then afterwards traverse through the nodes and trigger calls to node.board() to initialize the whole tree. During that I present a "load screen" to the user. But this is actually quite slow on older systems, and makes the user wait to "just" load up a pgn, which is a bad user experience.

Question:

  • Is it possible to somehow build up the board cache directly during pgn parsing in order to speed up the process? Unfortunately I have no clue about the bitboard representation, and if that would even bring a performance improvement...

thx

Spelling of 'Repetition?'

Hi Niklasf,

I don't know if it matters, or if you can spell the class both ways in future, but I think repitition is spelled repetition. A pull-request in picochess was broken because the requestor spelled repitition the correct way. I don't know what the right answer is, since the correct way was a typo since it's not the name of the method. Just an FYI. Anyway, thanks for python-chess.

Jimmy

Promotions in pgn without equal sign

I used your library for pgn parsing and got exceptions then try to parse some pgns with promotion moves like:

e8Q
e8Q+
e8Q#

I think it's because it's doesn't have equal sign and there moves throws no exception:

e8=Q
e8=Q+
e8=Q#

set_fen does not yet check for chess position legality

I tried set_fen with only one king on the board and it passed validation. Looking at the code, this is not yet done. It would be useful to check if a fen is valid.

Use case: Setup position on a board and using python chess to verify that the position is valid.

Question on PGN parsing

I would like to read some PGN file with one or more games, make some changes, or traverse the game tree, and save back to a new PGN file. Is this possible with the library in its current state? It is not clear from the API how to use the PgnFile class which is why I'm asking.

uci stop() issue

Engine would not stop() in such scenario:
engine.go(async_callback=True) with finite depth or time.
engine.stop() hanging forever...

Info breaks if engine sends 2 spaces

https://github.com/mAarnos/Hakkapeliitta

producing two spaces after lower/upperbound. see:
depth 10 seldepth 9 score cp 22 upperbound time 17 nodes 48299 nps 2683000 tbhits 0 pv d7d5 e4e5 depth 10 seldepth 9 score cp 14 time 22 nodes 72368 nps 3146000 tbhits 0 pv d7d5 e4e5 d5d4 e2e1 c6c5 f2f4 d8d5 h2h4 d5e4 g1e2 depth 10 seldepth 9 score cp 14 time 28 nodes 101261 nps 3491000 tbhits 0 pv d7d5 e4e5 d5d4 e2e1 c6c5 f2f4 d8d5 h2h4 d5e4 g1e2 depth 11 seldepth 10 score cp 30 lowerbound time 36 nodes 140401 nps 3794000 tbhits 0 pv d7d5 e4e5

That breaks your lib.
Im dont know, if two spaces allowed, so i post this issue on both systems ;-)

Im using a "if not token: continue" to solve it right now.

Mirrored piece moves when move is pushed to the board

When a Move is created for a piece, for example, the white pawn on a2, the data in the Move appears to be correct. However, when the Move is pushed to the board the mirrored piece is moved instead (black pawn on a7 is moved instead).

if not spaceClicked == None:
                sx, sy = spaceClicked
                index = getIndex(sx, sy)
                print index
                move = []
                moves_str = []
                moves_index = []
                hspaces_old = highlight_spaces
                highlight_spaces = []

                index = getIndex(sx,sy)
                pc = spaces[index]

                highlight = False
                for sqr in range(64):
                    if chess.Move(index, sqr) in boardData.legal_moves:
                        move.append(chess.Move(index, sqr))
                if index in hspaces_old:
                    new_move = chess.Move(space_in_focus, index) # Have found this to be correct. The data given matches the chosen move
                    boardData.push(new_move) # Focus of issue
                for m in move:
                    moves_str.append(m.uci()[2:])
                    for mstr in moves_str:
                        #moves_index.append(chess.SQUARE_NAMES.index(mstr))
                        highlight_spaces.append(chess.SQUARE_NAMES.index(mstr))
                    space_in_focus = index

a show stopper bug on handling castling

It seems the move string for castling has changed from '0-0' to 'e1h1' if white castles king side. This is inconsistent with stockfish, which recognize either '0-0' or 'e1g1'.

This is actually a serious bug -- I've just upgraded from 0.7.0, suddenly the engines spits out wrong cp scores after castling. At this stage, I'd say 0.9.0 is in very bad state... Please fix asap.

Support commercial chess engines

This is nothing that intrests me in particular, but just to keep track of it: registration and copyprotection commands may be implemented in the UCI module.

error when using board.pieces()

board = chess.Board()
bishops = board.pieces(chess.BISHOP, chess.WHITE)

throws error

Traceback (most recent call last):
File "/Users/benajaminpusey/PycharmProjects/Test/Chess_Project/chess_project.py", line 98, in
bishops = board.pieces(chess.BISHOP, chess.WHITE)
File "build/bdist.macosx-10.9-intel/egg/chess/init.py", line 897, in pieces

AttributeError: 'Board' object has no attribute 'piece_mask'

Error - See Edited Try Except Print

File "./Main.py", line 76, in
Computer_vs_Computer() #uncomment for computer vs. computer testing
File "./Main.py", line 63, in Computer_vs_Computer
Minimax_Move('w')
File "./Main.py", line 47, in Minimax_Move
move = Minimax.Minimax( board, color )
File "/home/john/Desktop/Chess/Minimax.py", line 92, in Minimax
if Loss( board ):
File "/home/john/Desktop/Chess/Minimax.py", line 51, in Loss
elif board.can_claim_threefold_repitition():
File "/home/john/Desktop/Chess/chess/init.py", line 1641, in can_claim_threefold_repitition
self.push(move)
File "/home/john/Desktop/Chess/chess/init.py", line 1708, in push
self.remove_piece_at(move.to_square + 8)
File "/home/john/Desktop/Chess/chess/init.py", line 935, in remove_piece_at
piece_type = self.pieces[square]
IndexError: list index out of range

def remove_piece_at(self, square):
"""Removes a piece from the given square if present."""
try:
piece_type = self.pieces[square]
except: print(square, len(self.pieces))

    if piece_type == NONE:
        return

68 64
Traceback (most recent call last):
File "./Main.py", line 76, in
Computer_vs_Computer() #uncomment for computer vs. computer testing
File "./Main.py", line 63, in Computer_vs_Computer
Minimax_Move('w')
File "./Main.py", line 47, in Minimax_Move
move = Minimax.Minimax( board, color )
File "/home/john/Desktop/Chess/Minimax.py", line 92, in Minimax
if Loss( board ):
File "/home/john/Desktop/Chess/Minimax.py", line 51, in Loss
elif board.can_claim_threefold_repitition():
File "/home/john/Desktop/Chess/chess/init.py", line 1643, in can_claim_threefold_repitition
self.push(move)
File "/home/john/Desktop/Chess/chess/init.py", line 1710, in push
self.remove_piece_at(move.to_square + 8)

difference between "board.copy()" and "copy.deepcopy(board)"?

Hello,

I thinked, they behave same. But if i use "copy()" in thinking(game). i get back the old problem with ghost boards (and the calc. is wrong). Using a deepcopy of board, working - like before. Changed it back.

basically a uci_engine.position(game.copy()) or (copy.deepcopy(game)) - one working the other not.

Threefold repetition detection and fifty-move rule

First I would like to thank you for this great lib ! We are using it in picochess :-)
Would it be possible to implement threefold repetition detection and fifty-move rule ? (juste like the is_stalemate() or is_game_over() methods)

En Passant Capture Not in board.legal_moves although it is.

!/usr/bin/python3

import chess

b = chess.Bitboard('rnk2bnr/8/b4p2/p1p2Pp1/P1P5/7p/3N3P/R1BK1B1R w - g6 0 27')
print(list(b.legal_moves))
print(chess.Move.from_uci('f5g6') in b.legal_moves)
print(chess.Move.from_uci('d2b1') in b.legal_moves)

"has_*side_castling_rights" behaves strange (in my eyes)

Hello.
Maybe i understand this 2 functions wrong.
But for me they should tell me future possibilities to castle.

If i use the NON-chess960 mode, i get wrong answers.
Seems the function only checks for the rook&king spaces in correct direction (that only helps me on chess960 mode).

Here is some code:
fen_game = '1r2k3/8/8/8/8/8/8/R3KR2 w KQkq - 0 1'
board = chess.Board(fen_game, False)
print(board.has_queenside_castling_rights(chess.WHITE))
print(board.has_queenside_castling_rights(chess.BLACK))
print(board.has_kingside_castling_rights(chess.WHITE))
print(board.has_kingside_castling_rights(chess.BLACK))
print('')
board = chess.Board(fen_game, True)
print(board.has_queenside_castling_rights(chess.WHITE))
print(board.has_queenside_castling_rights(chess.BLACK))
print(board.has_kingside_castling_rights(chess.WHITE))
print(board.has_kingside_castling_rights(chess.BLACK))

The first part should display: T,F,F,F but i get T,T,T,F - for example, as black i can never play 0-0-0 nor as white 0-0.
Similar problems with a wK on d1 for example.

Typo's in docu & uci.py

In the uci docu & uci.py [inside docu] at function:
chess.uci.spur_spawn_engine

the name "spawn" written wrong.

EPD parsing PV tag

The EPD spec allows the 'PV' tag (principal variation) to contain a list of moves, which could be executed in order. the Board.set_epd() function fails to do this because it assums there is only one move, and also assumes that the move is to be played in the current position.

Chess Query Language

Hi,

This looks a nice project to play around with the pgn databases. Did you consider to implement the Chess Query Language (www.rbnn.com/cql/)?
You already have some of the building blocks to do it.
This will allow to make nice searches in the databases.

Missing move number on pgn with black to move

Hello,
on picochess we just had this problem. I prepared a small script for proof.
game1 print is wrong. Can you check please?

Here the code:

import chess
import chess.pgn

b_move = chess.Move(chess.E6, chess.D6)
w_move = chess.Move(chess.E3, chess.D4)

# wrong display when black to move - "1." missing
game1 = chess.pgn.Game()
game1.setup('8/8/4k3/8/4P3/4K3/8/8 b - - 0 1')
node = game1
node = node.add_main_variation(b_move)
node = node.add_main_variation(w_move)
print(game1)

# proof, with white to move, no problem
game2 = chess.pgn.Game()
game2.setup('8/8/4k3/8/4P3/4K3/8/8 w - - 0 1')
node = game2
node = node.add_main_variation(w_move)
node = node.add_main_variation(b_move)
print(game2)

Tablebase probing

Hi,

I have a question concerning the probing of syzygy tablebases. The method probe_dtz sometimes takes more than 10 times longer depending on which side is to move. E.g. with the code below I get approximately 0.05s for white to move and 1.5s for black to move. Am I missing something or is this kind of strange?

import chess, chess.syzygy
import time

with chess.syzygy.Tablebases("data/syzygy") as tb:
    start = time.time()
    for i in range(100):
        tb.probe_dtz(chess.Board("8/8/3rk3/8/8/2Q1K3/8/8 w - - 0 1"))
    end = time.time()

    start2 = time.time()  
    for i in range(100):           
        tb.probe_dtz(chess.Board("8/8/3rk3/8/8/2Q1K3/8/8 b - - 0 1"))
    end2 = time.time()

print(end - start, end2 - start2)

Feature Request: Setting Castling Rights

It would be nice to have the following high-level functions:

def set_kingside_castling_rights(color, bool_val)
def set_queenside_castling_rights(color, bool_val)

Also
clean_castling_rights()
is not really clear to me. Does it reset the castling rights of the current board? If not, how do I have to reset? Like this: board.castling_rights = board.clean_castling_rights() ?!

Background: I have a "Enter Position" functionality in my chess GUI. So far I just copied & pasted the low-level bitmask manipulation from the python-chess lib-source code, but it seems to have changed from 0.8 to 12.5, and I am really lost in how they are encoded. Hence, having these high-level calls would be highly appreciated...

Cannot replay legal moves

Hi,

Nice library you got there, I really like its ease of use. Unfortunately I'm having trouble with the push_san() function. Here is a sample of code :

from __future__ import print_function
import chess

board = chess.Bitboard("k7/pp6/8/8/8/8/8/3R3K w - - 0 1")

for move in board.legal_moves:
    pprint(move)
    try:
        board.push_san(str(move))
        board.fen()
        board.pop()
    except:
        print('Bad move')

For each legal move, it says "Bad move".

build error

$ python setup.py build           
Traceback (most recent call last):
  File "setup.py", line 29, in <module>
    (opt, ) = distutils.sysconfig.get_config_vars("OPT")
AttributeError: 'module' object has no attribute 'sysconfig'

I can reproduce this in both python-chess 0.0.5 and r352acb5e80a1

python 2.7.5
Slackware Linux 14.1, clean 64 bit, no multilib

Result header not read from game moves

If there is a result at the end of the game moves, this code is supposed to pick it up:

Set result header if not present, yet.

if "Result" not in game.headers:
game.headers["Result"] = token
However, Result is always set to '*' by default in the headers, so this is never run. Could this please be updated to check for none and for an unknown result?

Thanks.

ImportError: /usr/lib/libboost_python.so.1.54.0: undefined symbol: PyClass_Type

Hello, I just finished installing python-chess on Archlinux distro, using easy_install. When I tried to run it (python 3.3), I got this error:

In [1]: import chess
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-31dd7659fda0> in <module>()
----> 1 import chess

/home/ed/.local/lib/python3.3/site-packages/python_chess-0.0.5-py3.3-linux-x86_64.egg/chess/__init__.py in <module>()
     28 
     29 # Import from libchess.
---> 30 from libchess import START_FEN
     31 from libchess import opposite_color
     32 from libchess import Square

ImportError: /usr/lib/libboost_python.so.1.54.0: undefined symbol: PyClass_Type

PGN initialization problem

I noticed the following error with this code. If board is a starting position, the setup function will try to delete the item SetUp from the headers dictionary. However, that item does not exist.

# create a PGN game
pgn = chess.pgn.Game()
pgn.setup(board=board)

Parameter order for "go" in uci

Something I snuck into my pull request was a change to the order in which "searchmoves" is appended to the command string in the uci. I found that searchmoves was clobbering other parameters like depth and movetime when appended first, as in the current code. In other words:

go searchmoves [moves] depth 20 movetime 5000

was ignoring the depth and movetime values completely. I changed it to:

go depth 20 movetime 5000 searchmoves [moves]

then it worked fine. I changed the order of the commands in 00ee993, which is currently causing an AssertionError due to a syntax check (uci.py, line 607) not allowing that order of commands. However, I think that is the correct order, due to the inability to get the engine I am using (stockfish) to work as intended using the existing code.

PGN export

Is it possible to export a game into PGN? Thanks

Feature request: docstrings for public members of Position class

Typical workflow of a starter:

  • download the source code
  • build from source
  • install
  • proceed to studying the API

That's pretty much what I did, then I fired IPython for the last step. But when I do

import chess
pos = chess.Position()
pos.PRETTY_MUCH_ANYTHING??

I see this:

Docstring:  <no docstring>

Next thing I did was to try reading the source code and realized it's C++. I understand this was done for performance reasons, yet for someone who doesn't know any C++ past 'hello world' this is a total show stopper :(

error in pgn docu

Hi,
in the docu there is an error:
Thats wrong:
exporter = chess.pgn.StringExporter()
pgn_string = game.accept(exporter, headers=True, variations=True, comments=True)

Thats right:
exporter = chess.pgn.StringExporter(headers=True, variations=True, comments=True)
pgn_string = game.accept(exporter)

Can y say something, why y now have this visitor stuff? Its different (with new api), but i dont see an advantage for the user. I see its cleaner in coding, something else?

Peformance

Hi, I have been examining your chess library and I think it is quite good. I have not found any good, readable x88 chess validation libraries implemented for python. However, due to the way the classes are setup, the x88 speed gain is completely overshadowed by attribute access and object creation.

Testing the making of 10 moves (Move.from_uci not from SAN) took over 3 seconds on my somewhat slow netbook (AMD C60). Tying this in a gui interface causes notable lag on adding a move and validating a game of 30 moves would be an hourglass operation.

I see that you have heavily used custom objects with "private" attribute access. While this may lead to better OO design, in Python this comes at a performance cost. I made a simple test case http://pastebin.com/0x0xpVLv of atribute access vs. property access. At 100,000 iterations, the difference of adding 1 to an attribute via property vs attribute was .361 and .063 seconds respectively (a 5x speedup). Profiling the position.py code, in 10 moves the inner functions were being called around 20,00 times.

The same will hold true for object creation where the profiler shows the code in init's a significant amount of time.

I forked and rewrote the classes using implied privacy and held the underlaying data structure as the x88 number in Square and Move so it would not have to be calculated. I switched the x88 pieces list from holding Piece objects to 1 length pieces strings. I used copy.deepcopy to copy the Position to avoid parsing and recreating the fen string. I only created the squares one time in and held them as a class variable as I consider them immutable.

All this produced about a 10 times speed up with only trivial changes to the x88 code! By using 'Class._attr' style to access variables instead @prop function calls to Class.private variables we stay away from function overhead that is expensive. Nothing is truly private in python anyways so I do not find much benefit in burying things with the '.*' syntax.

Of course the rule is always never to pre-optimize, but chess may an exception due to the exponential blowup of moves. In any case, I think it is a good library which is why I am taking the time to explain this. If the move generation is fast enough it should be possible to write a simple eval function for alpha-beta search.

You can see the fork at https://github.com/nate1001/python-chess.

Regards,
Nate.

Error in uci.py

in function "position" there is a "chess." missing

if standard_chess_status & chess.STATUS_BAD_CASTLING_RIGHTS and not chess960_status &
STATUS_BAD_CASTLING_RIGHTS:

must be chess.STATUS_BAD_CASTLING_RIGHTS

CentOS 6 and Python 2.6

python-chess does not work on python 2.6 because of the Counter class. So it also does not work on CentOS.

Using this backport

http://code.activestate.com/recipes/576611-counter-class/

everything seems to work (admittedly I did only limited testing).

It seems a shame that such a useful package as python-chess would not work out of the box on the still widely used CentOS 6 (10 years of support).

Would you consider using the backported Counter class?

Gaviota - 3 request issue

(1)
Following the docu of gaviota, i get this error when i try:

>>> with chess.gaviota.open_tablebases("data/gaviota") as tablebases:
...     tablebases.probe_dtm(chess.Board("8/8/8/8/8/8/8/K2kr3 w - - 0 1"))
...
-10

but i get:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: __exit__

(2)
also below this fen is not valid (in docu & file):
"4k3/8/B7/8/8/8/4K3 w - 0 1"

(3)
libgtb:
Could you please provide an example with using the shared lib?
(=what to enter in python after "make install"). Thanks

Cant Convert PGN to string (could be user error...)

Hey,

I've been trying to create a PGN from a game played (engine vs engine) through python-chess.

However, whenever I convert the pgn to a string, I get a stack trace back.

game.pgn = str(pgn)
File "/home/jordan/Projects/virtual_environments/moregames/lib/python3.4/site-packages/chess/pgn.py", line 283, in __str__
self.export(exporter)
File "/home/jordan/Projects/virtual_environments/moregames/lib/python3.4/site-packages/chess/pgn.py", line 366, in export
super(Game, self).export(exporter, comments=comments, variations=variations)
File "/home/jordan/Projects/virtual_environments/moregames/lib/python3.4/site-packages/chess/pgn.py", line 230, in export
exporter.put_move(_board, main_variation.move)
File "/home/jordan/Projects/virtual_environments/moregames/lib/python3.4/site-packages/chess/pgn.py", line 450, in put_move
self.write_token(board.san(move) + " ")
File "/home/jordan/Projects/virtual_environments/moregames/lib/python3.4/site-packages/chess/__init__.py", line 2275, in san
others &= ~BB_SQUARES[move.from_square]
UnboundLocalError: local variable 'others' referenced before assignment

This occurs here in my code:
# update the PGN
pgn.add_main_variation(move)

# write the new PGN to the database, now
exporter = chess.pgn.StringExporter()
# pgn.export(exporter, headers=True, variations=True, comments=True)
game.pgn = str(pgn)

I can add moves, just not get the PGN string back.

As you can see above, I also tried the PGN exporter, but that failed with the same exception.

PV problem

Hello,
im not sure, if its a python-chess problem, or a picochess one.

I played the following game. On move 19, stockfish wanted to play Nd6-e4, but i played Nf6-e4
At this time: program in pondering mode. Then the program crushed with error message.
Could that be a problem with both N can go to e4?

GAME:

  1. d4 d5 2. Bf4 c5 3. c3 Nc6 4. Nf3 Nf6 5. e3 Bg4 6. Be2 e6 7. O-O cxd4 8. cxd4
    Bd6 9. Bxd6 Qxd6 10. Nc3 O-O 11. h3 Bxf3 12. Bxf3 Rfc8 13. Rc1 h6 14. Re1 Ne7
  2. Qb3 Qd7 16. Be2 Nf5 17. Bb5 Qd8 18. Bd3 Nd6 19. Nb5 Nfe4 20. Nxd6 Nxd6 21.
    Qa3 1-0

ErrorLog:
2015-07-20 07:27:41.531 DEBUG picochess - main: User move [c3b5]
2015-07-20 07:27:41.589 INFO dgtdisplay - run: Search already stopped
2015-07-20 07:27:41.661 INFO dgtdisplay - run: Search ponder started
2015-07-20 07:27:41.691 ERROR uci - _info: exception parsing pv
Traceback (most recent call last):
File "./libs/chess/uci.py", line 724, in _info
pv.append(board.push_uci(token))
File "./libs/chess/init.py", line 2361, in push_uci
move = self.parse_uci(uci)
File "./libs/chess/init.py", line 2348, in parse_uci
raise ValueError("illegal uci: {0}".format(repr(uci)))
ValueError: illegal uci: 'd6e4'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.