1:- module( chess_db, [ 2 % io.(pgn + dbs) 3 pgn/2, % +PgnToF, ?PgnT 4 chess_db/1,chess_db/2,chess_db/3, % +PgnToF[, Db[, +Opts]] 5 chess_db_ids_pgn/2, % +GidS, +PgnF 6 % db.connections 7 chess_db_disconnect/0, % 8 chess_db_disconnect/1, % ?Db 9 chess_db_connect/1,chess_db_connect/2, % +Dbs[, +Opts] 10 chess_db_current/1, chess_db_current/2, % -CdbHs[,-Db] 11 % db.games 12 chess_db_game/1, % -GameID 13 chess_db_game_info/3, % ?Gid, -Key, -Val 14 chess_db_match/2, % +Patts, ?GameS 15 chess_db_opening/2, % +Moves, ?GameS 16 chess_db_opening_pgn/2, % +Moves, +PgnF 17 chess_db_position/3, % +PosOrMoves, -DbHandles, -Conts 18 % db.info 19 chess_db_list/1, % +Dir 20 chess_db_max_id/2, % +HandleST, -Max 21 % chess.dict 22 chess_dict_start_board/1 , % -Brd 23 chess_dict_inpo/2, % ?Brd, ?Inpo 24 chess_pgn_limos/2, % +PgnTerm, -Limos 25 chess_dict_move/3,chess_dict_move/4, % +Move, +DictI, [+Turn,] -DictO 26 chess_dict_piece/3, % +DictPiece, +Colour, +Piece 27 chess_annotate_freq/3, % +Pgn, +CheDbLoc, +Args 28 chess_fen_square/2, % ?Fen, ?Sqr 29 chess_dict_pos_algebraic/2, % ?Pos, ?Alg 30 % etc 31 chess_db_version/2 % -Vers, -Date 32 ] ). 33 34chess_db_alias( Alias, Path ) :- 35 user:file_search_path( Alias, Path ), 36 !. 37chess_db_alias( Alias, Path ) :- 38 assertz( user:file_search_path(Alias,Path) ). 39 40:- multifile(user:file_search_path/2). 41:- chess_db_alias(pgn, pack('chess_db/data/pgn')). 42:- chess_db_alias(chess_db, pack('chess_db/data/dbs')). 43 44% user:file_search_path( pgn, pack('chess_db/data/pgn') ). 45% user:file_search_path( pgn, pack('chess_db_data/pgn') ). 46% user:file_search_path( chess_db, pack('chess_db_data/dbs') ). 47 48:- use_module(library(lib)). 49 50:- lib(options). 51:- lib(os_lib). 52:- lib(db_facts). 53:- lib(prosqlite). 54:- lib(stoics_lib). 55:- lib(debug_call). 56 57:- dynamic(chess_db_handles/2). % +Dir, +HandlesTerm 58 59:- lib(source(chess_db),homonyms(true)). 60 61:- lib(pgn/2). 62:- lib(chess_db/2). 63:- lib(chess_db_list/1). 64:- lib(chess_db_max_id/2). 65:- lib(chess_db_game/1). 66:- lib(chess_db_ids_pgn/2). 67:- lib(chess_db_connect/1). 68:- lib(chess_db_current/2). 69:- lib(chess_db_game_info/3). 70:- lib(chess_db_match/2). 71:- lib(chess_db_opening/2). 72:- lib(chess_db_disconnect/1). 73:- lib(chess_db_opening_pgn/2). 74:- lib(chess_db_handles/4). 75:- lib(chess_db_messages/0). 76:- lib(chess_dict/0). 77:- lib(chess_fen_square/2). 78:- lib(chess_dict_move/4). 79:- lib(chess_pgn_limos/2). 80:- lib(chess_annotate_freq/3). 81:- lib(chess_dict_pos_algebraic/2). 82:- lib(chess_db_position/3). 83 84:- debuc(chess_db(true)). 85:- lib(end(chess_db)).
date(Y,M,D)
term.
?- chess_db_version( 1:0:0, date(2021,6,18) ). true.
*/
409chess_db_version( 1:0:0, date(2021,6,18) )
PGN and chess game databases.
This library produces chess games databases from PGN files and provides some
predicates for manipulating these databases.
Once connected to a number of chess_db databases, information about the games
can be interrogated. (See chess_db_opening/2 for an example.)
Ideally we want to hook this pack to either a web-based interface, or (b) have an engive interface to exploit GUI playing programs, for playing the games as we select them.
Currently selected games can be saved to a PGN file and be displayed with any PGN displaying program.
Installation:
There are three example pgns in
pack(chess_db/data/pgn)
and an example program inpack(chess_db/examples/short.pl)
.The best way to view the documentation is via the SWI-Prolog html documentation server:
Static docs version is available at: https://stoics.org.uk/~nicos/sware/chess_db/doc/html/chess_db.html
Home page: https://stoics.org.uk/~nicos/sware/chess_db
The source code for the pack is available at github: https://github.com/nicos-angelopoulos/chess_db
Dependencies
Packs:
Basics
The pack includes code to:
See below for details on each.
A number of chess databases can be connected at the same time. Operations are implicit to all open databases. Connecting is via chess_db_connect/2.
Example
Mini tutorial
The above example in detail.
Turn debugging of writing out the original games as they are added to the database.
Create a database in fresh directory short/. The DB will be populated with games from pgn file chess_db/data/4ncl_short.pgn
The database is closed after it is populated.
Connect to the new database. The connections are managed internally.
Interrogate all connected databases for games starting with the sequence [e4,e6] (French defence).
Turn general library debugging on.
Re-connecting is handled fine.
Create a new PGN file from the original scripts of the two French defence 2 games in their original script. Moves are matched to game_move/4 and are pulled from the game_orig/2 sub-database.
View the two games in a PGN interface program such as:
Find continuations for specific positions
Please note that this is more generic than chess_db_opening/2 as it also finds transpositions.
Debug terms
Listens to:
PGNs
Portable Game Notation is the standard for recording chess games. Each file, typically with a .pgn extension, may contain multiple games. In most cases a single PGN file will contain all the games a particular chess tournament.
For example the file
pack(chess_db('data/pgn/4NCL-2017.pgn')
records some of the games for the 2017, 4NCL league taking place in the UK.This pack implements a parser for PGNs (pgn/2) that converts the games in the .pgn file to a Prolog terms list, where each game is represented by a
pgn(Info,Moves,Res,Orig)
term (see pgn/2).The following two queries are equivalent
To disambiguate between multiple pieces that maybe able to be refered to by a game move, the pack implements a pinned piece logic. The non-interface predicate implementing this is: chess_dict_move_pin/3.
Disambiguation is needed in the following example. On a board with white rooks on b2 and b7 a move noded by Rb3, could refer to either of the rooks moving to this square. If both rooks are unconstrained the move should have be recordes as either R2b3 or R7b3. If the move is recorded as Rb3, it means that either of the two rooks is constrained by a pin: ie moving the rook would put the white king under attack. For instance, if the white king is at a1 and the black queen is on c3, then the rook on b2 is pinned and moving it to b3 whould be an illegal move. Thus, in this context Rb3 refers to moving the rook on b7 to b3.
Databases
By default, each chess_db database directory contains 4 SQLite DBs each holding a single table. In the following, a + sign prefixes a key field:
game_info(+Gid,+Key,Val)
info Key->Val pairs about each gamegame_move(+Gid,+Ply,Hmv,Move)
game_orig(+Gid,Orig)
; where Orig is the verbatim of the section in the PGN for that gamegame_posi(Posi,GPPairs)
, where GPPairs is a ; seperated Gid-Ply-Move pairs stored as text (eg '1-2-e4;2-4-e3'), Posi is a long integer stored as a stringgame_posi(Posi,Conts)
; where Posi is a unique position and Conts is the continuations string (Gid-Ply-Mov, eg: 1-3-d5).Positions are encoded as long integers.
A number of chess_dbs can be opened at the same time.
Databases are created and managed with packs
library(db_facts)
andlibrary(prosqlite)
.Dictionaries
The pack also implements boards as dictionaries along with predicates that effect transitions to the board due to moves.
Positions on the board get keys 1-64, and there are keys for: whether various castlings and any en passant are still valid, whose move it is, ply move and half moves since last take.
See:
Inpos
Integer representation of positions. These hold less information than a board dictionary as we want to make positions that look the same identical, irrespective of when was the last take or at which stage (ply counter) of the game the position arose.
To convert from a dictionary use: chess_dict_inpo/2.
Inpos are used as the first field of game_posi/2 database tables (see Databases section above).
Pack predicates
parsing of and saving to pgn files, and storing/retriving on/from chess_dbs
manage database connections
access db games and info
dictionaries
info interactions
documentation
Pack info
pack('chess_db/examples/short.pl')
]pack(prosqlite)
,pack(db_facts)
,pack(stoics_lib)
,pack(options)
*/