Git Product home page Git Product logo

kokopu's People

Contributors

dependabot[bot] avatar mbutsykin avatar vladmandic avatar yo35 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

Watchers

 avatar  avatar  avatar  avatar  avatar

kokopu's Issues

How does one access the moves/variations/comments/etc. of a Game object?

I couldn't find anything in the documentation that allows one to access the content of a game object, such as the moves, the variations, the comments, etc. Only the names of the players and other things like that.

I need to be able to load PGNs, look at them/add comments and variations to them/etc, and then export the modified PGNs after.

How would I do that?

Invalid disambiguation symbol

var kokopu = require('./index');

var p = new kokopu.Position('2r1b2k/p5p1/1p1qp2p/3nNp2/3P3Q/P2R3P/1P3PP1/1Br1R1K1 w - - 0 25');
console.log(p.ascii());
// +---+---+---+---+---+---+---+---+
// |   |   | r |   | b |   |   | k |
// +---+---+---+---+---+---+---+---+
// | p |   |   |   |   |   | p |   |
// +---+---+---+---+---+---+---+---+
// |   | p |   | q | p |   |   | p |
// +---+---+---+---+---+---+---+---+
// |   |   |   | n | N | p |   |   |
// +---+---+---+---+---+---+---+---+
// |   |   |   | P |   |   |   | Q |
// +---+---+---+---+---+---+---+---+
// | P |   |   | R |   |   |   | P |
// +---+---+---+---+---+---+---+---+
// |   | P |   |   |   | P | P |   |
// +---+---+---+---+---+---+---+---+
// |   | B | r |   | R |   | K |   |
// +---+---+---+---+---+---+---+---+
// w - -

var md = p.notation('Rdd1');
console.log(p.notation(md)); // Returns Rd1 instead of Rdd1.

Multi-part comments in PGN

When parsing a PGN with text comments split into several {...} parts such as:

1. e4 e6 {comment-A-part-1} (1... c6) {comment-A-part-2} 2. d4 d5 {comment-B-part-1} {comment-B-part-2} 3. e5 *

... the last part erases the previous ones during parsing.

Expected behavior: merge the parts related to the same move, so that the output game is equivalent to what would be obtained with:

1. e4 e6 {comment-A-part-1 comment-A-part-2} (1... c6) 2. d4 d5 {comment-B-part-1 comment-B-part-2} 3. e5 *

En-passant flag inconsistency

There is an inconsistent behavior regarding the en-passant flag between the checks performed in Position.isLegal(..) and the update strategy applied in Position.play(..):

  • In Position.isLegal(..), en-passant set for a column implies that the position is compatible with a 2-square pawn move just before (i.e. for instance, if en-passant is set to e, and if Black is to play, it implies that e2 and e3 are empty, and that there is a white pawn in e4).
  • In Position.play(..), en-passant is set after a 2-square pawn move ONLY if the opponent has a pawn in position to achieve en-passant (i.e., in the previous example, only if there is a black pawn in d4 or f4).

This leads to unexpected behaviors, i.e. for instance:

var p1 = new kokopu.Position();
p1.play('e4');
var p2 = new kokopu.Position('rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1');
console.log(kokopu.Position.isEqual(p1, p2));
// return false

Possible features

Loving your creation!
Is there any chances you are planing on adding promote & remove variation / node?

Illegal castling move at chess960

Considering the following position at chess960, and assuming that both the white king and white rook occupy their initial squares, kokopu consider O-O-O as a valid move, although it's not (because the white king would be in check).

chess960_diagram

Game - find by FEN

Can we have find by "FEN" method for game? similar to findById?

Mb even something more generic - have some method in game / variation that returns all existing nodes (including child variations of nodes) as a JS array so native functions like map/filter/find etc. are availiable? I'm not sure about memory usage of this mb it's better to stay with existing data structure like bidirectional list, so instead of it - implement own filter/map/find(predicate) methods?

Inconsistent handling of PGN with no metadata

version: kokopu 4.10.0

If given a PGN with no metadata (moves only), kokopu will parse it correctly but returns inconsistent games attributes. For instance, given the input:

   1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 Bg4 5. Be2 e6 6. O-O Be7 7. h3 Bh5 8. c4 Nb6

kokopu.pgnRead() will create a db object with a gameCount=1, but the iterator from db.games() sees no games; e.g.,

for (let game of db.games()){...} 

will not enter the loop body. The debug screenshot will hopefully make that clear.

image

What is the relation between Game and Position and Variation?

Hi, it might be just me but I'm having trouble understanding the relation between Game, Position and Variation.

I would consider a Game to be the 'total state' of a game, with e.g. the initial Position, the played moves, all resulting Positions and the current Position. However I can only find the initialPosition there...

What is the proper way to set up a Game, set a board, then play some moves and then get hold of all the previous Positions (and current Position) through the Game object?

And what is a Variation meant for? Do we need to use it or is it just an internal thing?

Thanks!

Effective castling

Currently, the castling flags of a Position (see Position.castling()) are used to determine whether a position is legal or not: for instance, if the flag K (aka. "white king-side castling") is set, there must a white king on e1 and a white rook on h1 for the position to be considered as legal, see Position.isLegal()).

This causes issues when processing FEN strings issued by unreliable sources: typically, a position could be judged as illegal by Kokopu just because of a castling flag incorrectly set in the input FEN.

This issue is similar to #31, concerning castling flags instead of en-passant flags. (although less critical, there is no issue with the castling flags in relation of Position.fen() and Position.isEqual()...)

Chess variations

Is it possible to extend the classes to create new chess variants other than ones in the library? For example, Chess.com's solo chess.

Trying to retrieve the FEN for each move in a game

This returns FENs for moves in a game:

    const fens = game.nodes().map(n=>n.position().fen())

The problem is this:

Game moves: 1. d4 d5

FENs returned:

rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq - 0 1
rnbqkb1r/pppppppp/5n2/8/3P4/8/PPP1PPPP/RNBQKBNR w KQkq - 0 1

The second FEN should end in "0 2" (since it is the second ply). I also notice that the en passant indicator is always 0, which shouldn't be the case if, say, 1...Nf6 was black's response.

Is there any way to get an accurate FEN for a move in a game?

pgn tags

currently library supports parsing of standard PGN Seven Tag Roster:

  • Event, Site, Date, Round, White, Black, Result

and adds couple of more of non-standard tags:

  • Annotator, BlackTitle, WhiteTitle

per PGN specs a tag pair section can be anything as long as its in format of [ <key> "<value>" ]

why are there 3 very specific non-standard tags and there is no support for other tags as they are used by many chess sites?

for example, i'm writing a game annotator and would like to add a termination reason as its commonly found.

Previous node for first node of child variations

Maybe it's better to return "parent's" previous node for children variations?

const game = new kokopu.Game();

const e4 = game.mainVariation().play('e4');
const e5 = e4.play('e5')

const e6 = e5.addVariation().play('e6')

e6.previous(); // for now - it's undefined but maybe return e4?

It would be convenient if Game had properties instead of functions

I can't decompose Game properties wrapped in functions such as playerName, playerElo, etc. For example, I would like to do the following assignments (if properties were data members instead of functions):

const {w, b} = db.players

for (let p of {w, b}) {
  const {elo, playerName, playerColor, playerTitle, playerElo} = p
  // do something with the properties
}

Tags not read when spanning more than one line

kokopu version=1.2.4

Example PGN.

    const kokopu = require('kokopu')
    const pgn =
      '[ePGN "0.1;DGT LiveChess/2.2.4"]\n' +
      '[Event "Altibox Norway Chess 2019"]\n' +
      '[Site "Stavanger, Norway"]\n' +
      '[Date "2019.06.04"]\n' +
      '[Round "1.1"]\n' +
      '[White "Carlsen, Magnus"]\n' +
      '[Black "Anand, Viswanathan"]\n' +
      '[Result "*"]\n' +
      '[WhiteClock "01:05:58"]\n' +
      '[BlackClock "01:13:09"]\n' +
      '[ReferenceTime "B/2019-06-04T18:41:31.315+02:00"]\n' +
      '[WhiteElo "2875"]\n' +
      '[BlackElo "2767"]\n' +
      '\n' +
      '1. d4 {[%clk 01:59:57]} {[%emt 00:00:02]} Nf6 {[%clk 01:59:53]} {[%emt\n' +
      '00:00:07]} 2. c4 {[%clk 01:59:53]} {[%emt 00:00:04]} e6 {[%clk 01:59:48]}\n' +
      '{[%emt 00:00:06]} 3. Nf3 {[%clk 01:59:47]} {[%emt 00:00:05]} d5 {[%clk\n' +
      '01:59:42]} {[%emt 00:00:06]} 4. Nc3 {[%clk 01:59:42]} {[%emt 00:00:05]} dxc4\n' +
      '{[%clk 01:59:36]} {[%emt 00:00:07]} 5. e4 {[%clk 01:58:51]} {[%emt 00:00:51]}\n' +
      'Bb4 {[%clk 01:59:27]} {[%emt 00:00:08]} 6. Bg5 {[%clk 01:58:16]} {[%emt\n' +
      '00:00:35]} c5 {[%clk 01:59:12]} {[%emt 00:00:15]} 7. Bxc4 {[%clk 01:56:58]}\n' +
      '{[%emt 00:01:18]} cxd4 {[%clk 01:58:57]} {[%emt 00:00:15]} 8. Nxd4 {[%clk\n' +
      '01:56:50]} {[%emt 00:00:08]} Bxc3+ {[%clk 01:58:49]} {[%emt 00:00:07]} 9. bxc3\n' +
      '{[%clk 01:56:44]} {[%emt 00:00:06]} Qa5 {[%clk 01:58:43]} {[%emt 00:00:06]} 10.\n' +
      'Nb5 {[%clk 01:56:00]} {[%emt 00:00:44]} Nxe4 {[%clk 01:57:25]} {[%emt\n' +
      '00:01:17]} 11. Qd4 {[%clk 01:55:46]} {[%emt 00:00:14]} O-O {[%clk 01:57:00]}\n' +
      '{[%emt 00:00:26]} 12. Qxe4 {[%clk 01:55:41]} {[%emt 00:00:05]} a6 {[%clk\n' +
      '01:56:52]} {[%emt 00:00:07]} 13. O-O {[%clk 01:53:21]} {[%emt 00:02:20]} axb5\n' +
      '{[%clk 01:54:17]} {[%emt 00:02:35]} 14. Bd3 {[%clk 01:51:59]} {[%emt 00:01:22]}\n' +
      'f5 {[%clk 01:53:49]} {[%emt 00:00:28]} 15. Qe2 {[%clk 01:51:48]} {[%emt\n' +
      '00:00:11]} Nc6 {[%clk 01:51:11]} {[%emt 00:02:38]} 16. Bd2 {[%clk 01:51:23]}\n' +
      '{[%emt 00:00:25]} Qc7 {[%clk 01:49:15]} {[%emt 00:01:57]} 17. Bxb5 {[%clk\n' +
      '01:50:42]} {[%emt 00:00:41]} f4 {[%clk 01:46:28]} {[%emt 00:02:47]} 18. f3\n' +
      '{[%clk 01:40:39]} {[%emt 00:10:04]} e5 {[%clk 01:43:38]} {[%emt 00:02:49]} 19.\n' +
      'Rfe1 {[%clk 01:38:34]} {[%emt 00:02:05]} Bd7 {[%clk 01:36:05]} {[%emt\n' +
      '00:07:33]} 20. a4 {[%clk 01:30:35]} {[%emt 00:07:59]} Kh8 {[%clk 01:30:13]}\n' +
      '{[%emt 00:05:51]} 21. Rad1 {[%clk 01:28:20]} {[%emt 00:02:16]} Rae8 {[%clk\n' +
      '01:19:41]} {[%emt 00:10:32]} 22. Bc1 {[%clk 01:25:52]} {[%emt 00:02:29]} e4\n' +
      '{[%clk 01:13:50]} {[%emt 00:05:50]} 23. fxe4 {[%clk 01:20:58]} {[%emt\n' +
      '00:04:54]} Ne5 {[%clk 01:13:25]} {[%emt 00:00:25]} 24. Bxd7 {[%clk 01:19:53]}\n' +
      '{[%emt 00:01:05]} Nxd7 {[%clk 01:13:10]} {[%emt 00:00:15]} 25. Rf1 {[%clk\n' +
      '01:05:58]} {[%emt 00:13:55]} *'

    const game = kokopu.pgnRead(pgn).game(0)
    const variation = game.mainVariation()
    for (let node = variation.first(); node; node = node.next()) {
      console.log(node.tag('clk'))
    }

Output

01:59:57
01:59:53
01:59:53
01:59:48
01:59:47
undefined
01:59:42
01:59:36
01:58:51
01:59:27
01:58:16
01:59:12
01:56:58
01:58:57
undefined
01:58:49
01:56:44
01:58:43
01:56:00
01:57:25
01:55:46
01:57:00
01:55:41
undefined
01:53:21
01:54:17
01:51:59
01:53:49
01:51:48
01:51:11
01:51:23
01:49:15
undefined
01:46:28
01:40:39
01:43:38
01:38:34
01:36:05
01:30:35
01:30:13
01:28:20
undefined
01:25:52
01:13:50
01:20:58
01:13:25
01:19:53
01:13:10
undefined

Improve robustness to linebreaks issues

Some users report issue with linebreaks (see yo35/rpb-chessboard#155).

Indeed, in most cases, linebreaks should not be taken into account at all by the parser. The only case in which it is necessary to look at line breaks is to parse some ill-formed headers such as:

[HeaderName "Header value with unescaped \ (backslash) or " (double-quote)"]

The right way to encode this header is:
[HeaderName "Header value with properly escaped \\ (backslash) or \" (double-quote)"]
... but some softwares do it the wrong way.

See http://www.saremba.de/chessgml/standards/pgn/pgn-complete.htm#c7 for more details about escaping special characters in PGN.

Variations don't interpret comments before first move.

Often in PGN you'll find comments before the first move to describe the game. And in variations on a move, you'll see a comment before the first move of the variation that describes the whole variation, and not the move specifically.

For example:

{Let's look at some openings} 1. e4 e5 {A classic move} ({Here's the Sicilian instead} 1... c5 {This move attacks d4, taking control of the center})

Both "Let's look at some openings" and "Here's the Sicilian instead" get dropped by pgnRead()

How to get fen in PGN parsing ?

I am trying to parse pgn and get the fen, but don't see any mention in (parsed.game(0)

const { pgnRead } = require('kokopu');
const parsed = pgnRead(multerText);
console.log(parsed.game(0));

How to get starting fen from this tag ?
[FEN "4r1k1/1q3ppp/p7/8/Q3r3/8/P4PPP/R3R1K1 w - - 0 1"]

Wrong behavior of `Database#game(..)` with invalid indexes

var pgn = ' ... '; // let's assume this is a valid PGN string with 2 games.
var database = kokopu.pgnRead(pgn);
var gameIndex = 3; // invalid index since database contains only 2 games, at indexes 0 and 1 respectively
database.game(gameIndex); // WRONG BEHAVIOR -> returns the first game, instead of throwing an exception

Errors with pgn from lichess

I am trying to export this study from lichess and import inside my app
https://lichess.org/study/8dnqBWj0
but get an error:

Unknown chess game variant (From Position).

then I am trying to avoid this error with

multerText = multerText.replace(/"From Position"/g, 'regular');

but then get an error

Missing or invalid PGN game header value

Effective en-passant

Currently, the en-passant flag of a Position (see Position.enPassant()) corresponds to the column on which a 2-square pawn move has just happen, if any.

Among other things, this flag is used:

  1. to decide whether a position is legal or not (e.g. if the flag is set to file d and Black is to play, then there must be a white pawn in d4 and two empty squares in d3 and d2 for the position to be considered as legal, see Position.isLegal()),
  2. to generate the FEN corresponding a chess position (see Position.fen()),
  3. to compare two positions (see Position.isEqual()).

As discussed in #27 (at the end), this leads to unexpected behaviors in some cases:

const p = new Position();
p.play('e4');
console.log(p.fen())
// rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1 (current behavior)
// rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1 (what would be expected,
// and also what is obtained with lichess, scid...)
const p1 = new Position();
p1.play('e4');
p1.play('e5');
p1.play('d4');
const p2 = new Position();
p2.play('d4');
p2.play('e5');
p2.play('e4');
console.log(Position.isEqual(p1, p2));
// -> false (current behavior), although the positions are the same in terms of
// board state and possible moves.

Moreover, the fact that the en-passant flag is used to decide whether a position is legal or not may cause some issues when processing FEN strings issued by unreliable sources (e.g. a position could be judged as illegal by Kokopu just because of a en-passant flag incorrectly set in the input FEN).

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.