A Julia library for computer chess. Visit the documentation for more details.
romstad / chess.jl Goto Github PK
View Code? Open in Web Editor NEWJulia chess programming library.
Home Page: https://romstad.github.io/Chess.jl/dev/
License: Other
Julia chess programming library.
Home Page: https://romstad.github.io/Chess.jl/dev/
License: Other
A Julia library for computer chess. Visit the documentation for more details.
Is it on purpose that the isdraw(g::Game)
doesn't look if it's a draw by threefold repetition, but only for material and fifty move rule?
Hi, thanks for making a very cool package!
I was trying to read my own Lichess games but I encountered an issue with the crazyhouse variant. The problem is that dropped pieces are stored as for example "N@g3" to indicate that a knight is dropped at g3. However, when I try to read this file I get:
nested task error: Chess.PGN.PGNException("Invalid character: @")
now, obviously, the "@" is the issue. Is there a recommended workaround for this? I'm not necessarily interested in reading the games with the crazyhouse variant, so I'd be happy to skip this game if that's possible. However, my goal is to read in the larger Lichess datasets, and in those files all variants are mixed.
full example:
Chess.PGN.gamefromstring("""
[Event "Hourly Crazyhouse Arena"]
[Site "https://lichess.org/urHSzup4"]
[Date "2021.04.06"]
[White "vandenman"]
[Black "damatte"]
[Result "0-1"]
[UTCDate "2021.04.06"]
[UTCTime "17:22:01"]
[WhiteElo "1869"]
[BlackElo "2181"]
[WhiteRatingDiff "-4"]
[BlackRatingDiff "+2"]
[Variant "Crazyhouse"]
[TimeControl "300+0"]
[ECO "B02"]
[Termination "Normal"]
1. e4 Nf6 2. e5 Nc6 3. exf6 exf6 4. d4 d5 5. Bb5 Bd6 6. Bxc6+ bxc6 7. N@h5 O-O 8. Nxg7 Kxg7 9. N@h5+ Kg8 10. P@g7 Re8+ 11. Qe2 B@g4 12. Qxe8+ Qxe8+ 13. Be3 Q@d1# 0-1
""")
ERROR: Chess.PGN.PGNException("Invalid character: @")
Stacktrace:
[1] readtoken(p::Chess.PGN.PGNReader)
@ Chess.PGN ~/.julia/packages/Chess/oXD5R/src/pgn.jl:351
[2] readgame(p::Chess.PGN.PGNReader; annotations::Bool)
@ Chess.PGN ~/.julia/packages/Chess/oXD5R/src/pgn.jl:444
[3] #gamefromstring#6
@ ~/.julia/packages/Chess/oXD5R/src/pgn.jl:557 [inlined]
[4] gamefromstring(s::String)
@ Chess.PGN ~/.julia/packages/Chess/oXD5R/src/pgn.jl:557
[5] top-level scope
@ REPL[29]:1
Apologies for coming from left field...
I'm trying to solve the N-queens problem using Chess.jl by doing a:
julia> b = fromfen("Q7/2Q5/8/8/8/8/8/8 w - - 0 1")
Board (Q7/2Q5/8/8/8/8/8/8 w - -):
Q - - - - - - -
- - Q - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
Then calling attacksfrom():
julia> pprint(b, highlight=attacksfrom(b, SQ_A8));
+---+---+---+---+---+---+---+---+
| Q | * | * | * | * | * | * | * |
+---+---+---+---+---+---+---+---+
| * | * | Q | | | | | |
+---+---+---+---+---+---+---+---+
| * | | * | | | | | |
+---+---+---+---+---+---+---+---+
| * | | | * | | | | |
+---+---+---+---+---+---+---+---+
| * | | | | * | | | |
+---+---+---+---+---+---+---+---+
| * | | | | | * | | |
+---+---+---+---+---+---+---+---+
| * | | | | | | * | |
+---+---+---+---+---+---+---+---+
| * | | | | | | | * |
+---+---+---+---+---+---+---+---+
Q7/2Q5/8/8/8/8/8/8 w - -
But the above doesn't have the attacksfrom() of the second (or... N) queen.
I'm looking at the code at squareset.jl and I'm not sure how to make queenattacks() etc. to return a set that takes into account all the queens.
Any assistance very much appreciated.
Thank you.
First, thanks for the package. It is awesome and I know writing open source code can be a little thankless. Second, I have a suspicion that I'm doing something wrong here, but is there a way to suppress the printing of the entire game when you return a game from a pgn?
I have functions that look like those below, and when I run the get_game function it prints the entire game. I am a Julia noob so I might be missing something painfully obvious, and if so apologies in advance.
function create_game_id(g)
# creates game IDs based on players, site and date played
white_player = Chess.whiteplayer(g)
black_player = Chess.blackplayer(g)
site = Chess.site(g)
date_played = Chess.dateplayed(g)
game_string = string(white_player, " - ", black_player, " | ", site, " ", date_played)
game_string
end
function get_game(pgn, game_id)
# searches the pgn file for game IDs
for g in gamesinfile(pgn, annotations = true)
if(create_game_id(g) == game_id)
return g
end
end
end
pgn = "C:\\Users\\<user>\\Desktop\\Chess\\Books\\PGN\\CaroKannMBM.pgn"
game_name = "Atkins, H. - Capablanca, J. | nothing 1922-01-01"
g = get_game(pgn, game_name)
The implementation of empty square is
const PIECE_TYPE_NONE = PieceType(7)
however, Board
has the field
bytype::MVector{6,SquareSet}
,
and the implementation of pieces is
function pieces(b::Board, t::PieceType)::SquareSet
@inbounds b.bytype[t.val]
end
so the following will result in an out of bounds read (possible crash?)
julia> pieces(startboard(), PIECE_TYPE_NONE)
SquareSet:
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
I am not sure how much it would cost to introduce a branch in that statement, but somenthing like the following should be a solution;
function pieces(b::Board, t::PieceType)::SquareSet
if t.val != 7
@inbounds b.bytype[t.val]
else
return -reduce(union, b.bytype)
end
end
If the practical cost is too high it might not be worth the fix.
For not getting this error when you are first trying Chess.jl
I think that in the documentation it should be:
b = startboard()
domove(b, "e4")
Could you please stage a new release for Chess.jl? The most recent PRs are mostly performance related, but there is one bug fix #28, which I think warrants a new release so it is easier to access through the package manager.
Thanks!
In the documentation it is said that "If you are using Chess.jl through a Pluto or Jupyter notebook, you'll see a graphical board, along with a link for opening the board in lichess." But I could not find a graphical board, nor a link in the Jupyter notebook
In order to implement chess variants with nonstandard pieces, would it be possible to extend PieceType
manually? I suspect that if I define const MYPIECE = PieceType(42)
, I will run into a whole lot of issues with the rest of the codebase?
When precompiling I got this notice.
┌ Formatting [59287772-0a20-5a39-b81b-1366585eb4c0]
│ ┌ Warning: DEPRECATION NOTICE
│ │
│ │ Formatting.jl has been unmaintained for a while, with some serious
│ │ correctness bugs compromising the original purpose of the package. As a result,
│ │ it has been deprecated - consider using an alternative, such as
│ │ `Format.jl` (https://github.com/JuliaString/Format.jl) or the `Printf` stdlib directly.
│ │
│ │ If you are not using Formatting.jl as a direct dependency, please consider
│ │ opening an issue on any packages you are using that do use it as a dependency.
│ │ From Julia 1.9 onwards, you can query `]why Formatting` to figure out which
│ │ package originally brings it in as a dependency.
│ └ @ Formatting C:\Users\dimer\.julia\packages\Formatting\3VxOt\src\Formatting.jl:12
└
Are there plans to allow reading of syzygy
or gaviota
TBs from this library? Imo, if that was added, this would be at feature parity with Python Chess.
Hi there, noticed that the pickbookmove()
function broke in my code after this commit:
529b11b
(I noticed this issue after updating the package)
My exact call is:
move = pickbookmove(board, "my-book.obk")
and the error I now get is
ERROR: LoadError: MethodError: no method matching pickbookmove(::Board, ::String) Closest candidates are: pickbookmove(::Board; bookfile, minscore, mingamecount) at /home/vscode/.julia/packages/Chess/86E71/src/book.jl:665
Did something change about how this function is called? I can't seem to find any working examples/documentation on if the way to use this function has changed.
Thanks!
The fen()
function returns incomplete FEN, missing fields 5 ("halfmove clock") and 6 ("fullmove number"). For example:
julia> b = fromfen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1")
Board (rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3):
r n b q k b n r
p p p p p p p p
- - - - - - - -
- - - - - - - -
- - - - P - - -
- - - - - - - -
P P P P - P P P
R N B Q K B N R
julia> fen(b)
"rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3"
The halfmove clock is easy to fix by using board.r50
, but fullmove number requires adjustments to Board
structure. I can provide a patch, but I'm not sure if the current behaviour is intentional (if it is, it would be nice to have it documented somewhere).
Hi,
I'm not a programmer, but I want to try the book making functions.
What exactly do I have to type for making a book from a pgn database?
If the folder location of the pgn is: C:\Users\Jonathan\Downloads\pgn\Magnus White.pgn
I tried to follow the manual but without succes. I must be doing sommeting wrong.
I have made a video capture of it to better explain what is going wrong:
When trying to call ismovecheck() during a tree search I stumbled across the error
LoadError: MethodError: no method matching bishoplike(::PieceColor)
�[0mClosest candidates are:
�[0m bishoplike(�[91m::Board�[39m) at /home/fabio/.julia/packages/Chess/86E71/src/board.jl:600
�[0m bishoplike(�[91m::Board�[39m, �[91m::PieceColor�[39m) at /home/fabio/.julia/packages/Chess/86E71/src/board.jl:625
MethodError: no method matching bishoplike(::PieceColor)
Closest candidates are:
bishoplike(::Board) at /home/fabio/.julia/packages/Chess/86E71/src/board.jl:600
bishoplike(::Board, ::PieceColor) at /home/fabio/.julia/packages/Chess/86E71/src/board.jl:625
The functions bishoplike() and rooklike() take indeed a board and a color as argument but only a color is passed.
# src/board.jl:1263
# En passant checks
if moveisep(b, m)
capsq = Square(file(t), rank(f))
newocc = occ - f + t - capsq
if !isempty(bishopattacks(newocc, ksq) ∩ bishoplike(us))
return true
end
if !isempty(rookattacks(newocc, ksq) ∩ rooklike(us))
return true
end
end
I just added the board to the functions args and now it seems to work fine
# En passant checks
if moveisep(b, m)
capsq = Square(file(t), rank(f))
newocc = occ - f + t - capsq
if !isempty(bishopattacks(newocc, ksq) ∩ bishoplike(b, us))
return true
end
if !isempty(rookattacks(newocc, ksq) ∩ rooklike(b, us))
return true
end
end
Is there a function that converts a string like "b5" to a Square
?
I'm experimenting with a little idea here, where I'd like to extract all the captures in a game. Something like "black pawn takes white bishop", or something like this.
Is there an easy way to use Chess.jl
to get this info from a game?
Below is an example of an illegal move generation edge case due to improperly set castle rights.
Consider the following PGN:
1. g3 c5 2. Bg2 e6 3. d3 d5 4. Bd2 Nf6 5. e3 Be7 6. Qe2 O-O 7. f3 Nc6 8. g4 g6 9. h4 Ne8 10. h5 e5 11. hxg6 fxg6 12. Qf2 Rf7 13. Nh3 d4 14. e4 Be6 15. Ng5 Rg7 16. Nxe6 Qd7 17. Nxg7 Kxg7 18. Qg3 Bf6 19. Qh3 Nd6 20. Qxh7+ Kf8 21. Qxd7 Nf7 22. Rh7 Be7 23. Bh6+ Kg8 24. Rxf7 Kxf7 25. g5 Rd8 26. Qxb7 Na5 27. Qa6 Nc4 28. dxc4 Rd7 29. Nd2 Bd6 30. Qc6 Be7 31. Qxd7 a5 32. Qa7 Ke6 33. Qxa5 Bd6 34. Qb6 Kd7 35. b3 Bc7 36. Qf6 Kc8 37. Qxg6 Kb7 38. Qg8 Bd6 39. Bf8 Bc7 40. Qg7 Ka6 41. Be7 Bb6 42. Qg6 Ka5 43. Bf6 Kb4 44. Bxe5 Ba5 45. Qf6 Kc3 46. g6 Bb4 47. g7 Kb2 48. g8=Q Kxa1 49. Qff7 Bc3 50. Qh8 Kb2 51. Qh1 Kc1 52. Ke2+ Kb2 53. Qb1+ Ka3 54. Qa7+ Kb4 55. Qa4# 1-0
after 48. ... Kxa1
, Chess.moves(b)
generates the illegal move a1c1
(a kingside castle). The reasons are
a1
rook and left their king thereThe game in question is https://lichess.org/x7ej96mq#96.
If you directly import the FEN from that game/position (6Q1/8/5Q2/2p1B3/1bPpP3/1P3P2/P1PN2B1/k3K3 w - - 0 49
), the illegal move is not generated, due to the castle property being properly set.
Hello, I am currently trying to use this library to solve a variant of chess. However, the ischeck
function doesn't seem to work in some positions where black is in check, even though I've used donullmove
. For some reason I have to change the board into an FEN and convert back after performing the null move for it to work properly:
julia> board = fromfen("1q2n2n/ppprkprr/1pp3pp/8/8/PPPP3P/BP2RQPB/R2BK2N w - - 0 1")
Board (1q2n2n/ppprkprr/1pp3pp/8/8/PPPP3P/BP2RQPB/R2BK2N w - -):
- q - - n - - n
p p p r k p r r
- p p - - - p p
- - - - - - - -
- - - - - - - -
P P P P - - - P
B P - - R Q P B
R - - B K - - N
julia> ischeck(board)
false
julia> ischeck(donullmove(board)) # should be true
false
julia> donullmove(board)
Board (1q2n2n/ppprkprr/1pp3pp/8/8/PPPP3P/BP2RQPB/R2BK2N b - -):
- q - - n - - n
p p p r k p r r
- p p - - - p p
- - - - - - - -
- - - - - - - -
P P P P - - - P
B P - - R Q P B
R - - B K - - N
# ^ This FEN is definitely a check, what's wrong??
julia> ischeck(fromfen(fen(donullmove(board)))) # why does this work?
true
How can I check if black is in check properly? The workaround works for me, but doesn't seem like the proper way to do this. The problem (without looking at the internal code) is probably that the checkers
bit-board isn't updated on a donullmove
(maybe a call to findcheckers
in that function would help?).
The function fromfen
seems to ignore the 5th component of the FEN string. Therefore, the following example does not work correctly:
fifty_move_board = fromfen("8/6k1/8/8/4R3/5r2/1K6/8 b - - 100 108") # position where 50 move rule has reached
isrule50draw(fifty_move_board)
Here, isrule50draw
returns false
. It should return true
.
First of all I really like and appreciate this library, but haven't gotten around to really dig into the internals.
I have the following issue: when I pick a move from a "normal" opening book, it returns a move as expected, but when the book was written with the compact flag it does not.
julia> bk = createbook("lichess_elite_2021-11.pgn"); writebooktofile(bk, "lichess_elite.obk"); writebooktofile(bk, "lichess_elite_compact.obk", true);
julia> @time pickbookmove(b, bookfile="lichess_elite.obk")
0.000294 seconds (86 allocations: 6.328 KiB)
Move(d2d4)
julia> @time pickbookmove(b, bookfile="lichess_elite_compact.obkc")
0.000321 seconds (84 allocations: 5.844 KiB)
So it does seem to do something but does not make the chosen move accessible.
This package has been incredibly useful for one of my Julia projects. However, I was wondering if you had a version of this in C++, or could point me towards a similar library for C++?
P.S. Thank you for your work on this! It's an incredibly simple interface!
Given position: r1bqkbnr/ppp2pp1/2np4/4p3/6P1/2N1P3/PPPP1PB1/R1BQK1NR b KQkq - 0 6
If black plays Rxh1, the correct fen should be r1bqkbn1/ppp2pp1/2np4/4p3/6P1/2N1P3/PPPP1PB1/R1BQK1Nr w Qq - 0 7, but Chess.jl will give r1bqkbn1/ppp2pp1/2np4/4p3/6P1/2N1P3/PPPP1PB1/R1BQK1Nr w Qkq - thereby listing kingside catling as a legal move for black.
Wouldn't be nice to print the board with the Unicode characters for the corresponding pieces (at least in environments that support Unicode, like Atom, and REPL if not in Windows)?:
x = rand(Bool) ? BLACK : WHITE
# it would be great if one of these would work:
the_other_color = -x
the_other_color = ~x
the_other_color = !x
the_other_color = inv(x)
I keep re-running the cell, sometimes I get a completed game, sometimes an error. It looks like moves
returned an invalid move.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.