Pure javascript chess board library

Discussion of anything and everything relating to chess playing software and machines.

Moderators: hgm, Dann Corbit, Harvey Williamson

User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Pure javascript chess board library

Post by maksimKorzh »

Hey what's up guys, Code Monkey King's here.
I'd like to share a project I'm currently working on -

a chess board widget that knows rules of chess

The idea has come to me when I've realized that famous chessboardjs library actually needs additional module to play only legal moves so I decided to try my skills and create all-in-one bundle for GUI and move validation. Now it's in the very early developmnet stage, but I can already share the milestone - a proof of concept implementation of the library - it allows to move pieces along chess board via 2 clicks and drag-n-drop (needs to be improved though)

Current features:
- full blown move generator ported to javascript from my Wukong chess engine (0x88 array based board)
- move validation
- pure javascript implementation of GUI (HTML table)

Project link:
https://github.com/maksimKorzh/chessboard

Learn more:
User avatar
hgm
Posts: 27701
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Pure javascript chess board library

Post by hgm »

Nice!

I did a similar project (the 'Interactive Diagram') aimed at doing arbitrary chess variants. So the rules for the piece movement are not hard-coded, but configurable. I also use a HTML table to represent the board. Initially I had problems with making this work well: the piece images put in the table cells tended to enlarge the height of the row they were in even when their size was so small that they should have fitted. This lead to very annoying expansion and contraction of the board ranks as you moved pieces, unless you made the pieces unaesthetically small.

I could finally solve that problem by using the piece images as background, rather than cell content. An additional advantage of that is that I could then use the cell content to display images of 'markers' used for highlighting move targets and such. Before I was using the background color visible in the transparent surroundings of the pieces to highlight. This is still possible, because even when you use a background image, the HTML background color is still visible through the transparent part of that image.

I made these Diagrams embeddable in this forum:
theme=MV firstRank=1 markerDir=http://www.chessvariants.com/membergrap ... lven-chess
Pawn::::a2-h2,,a7,h7
Lance::C::a1,h1,,a8,h8
Cannon::mRcpR:Canon:c1,f1,,c8,f8
King::::e1,,e8
This is an open-ended project. At some point I decided to equip it with a simple AI, (accessible through the 'Play it' link), so it could be used as sparring partner in web pages that explained the rules of a new chess variant. It remembers the game history, and allows you to step through it, while displaying the game in SAN below the diagram.

I am now working on making it possible to paste pre-existing games in the HTML paragraph that normally displays the game you are playing, so that it can be used as game viewer. The mechanics of the pasting is easy (through the HTML attributes contenteditable and onpaste). But unfortunately I must also write a SAN parser for that to work, which is quite a chore.
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Pure javascript chess board library

Post by maksimKorzh »

hgm wrote: Wed Dec 02, 2020 10:53 am Nice!

I did a similar project (the 'Interactive Diagram') aimed at doing arbitrary chess variants. So the rules for the piece movement are not hard-coded, but configurable. I also use a HTML table to represent the board. Initially I had problems with making this work well: the piece images put in the table cells tended to enlarge the height of the row they were in even when their size was so small that they should have fitted. This lead to very annoying expansion and contraction of the board ranks as you moved pieces, unless you made the pieces unaesthetically small.

I could finally solve that problem by using the piece images as background, rather than cell content. An additional advantage of that is that I could then use the cell content to display images of 'markers' used for highlighting move targets and such. Before I was using the background color visible in the transparent surroundings of the pieces to highlight. This is still possible, because even when you use a background image, the HTML background color is still visible through the transparent part of that image.

I made these Diagrams embeddable in this forum:
theme=MV firstRank=1 markerDir=http://www.chessvariants.com/membergrap ... lven-chess
Pawn::::a2-h2,,a7,h7
Lance::C::a1,h1,,a8,h8
Cannon::mRcpR:Canon:c1,f1,,c8,f8
King::::e1,,e8
This is an open-ended project. At some point I decided to equip it with a simple AI, (accessible through the 'Play it' link), so it could be used as sparring partner in web pages that explained the rules of a new chess variant. It remembers the game history, and allows you to step through it, while displaying the game in SAN below the diagram.

I am now working on making it possible to paste pre-existing games in the HTML paragraph that normally displays the game you are playing, so that it can be used as game viewer. The mechanics of the pasting is easy (through the HTML attributes contenteditable and onpaste). But unfortunately I must also write a SAN parser for that to work, which is quite a chore.
Wow! Never thought you'll like something that I'm doing, HGM))) This is such an honor for me to get a positive feedback from you!
I'm thinking about providing a simple alpha beta search to play against as well, but I'm having problems with negative indices in TT when hash key is negative. I know I can make it unsigned via Uint32Array([hash_key])[0] but when hash key gets incrementally updated it gets to negative values from time to time, also 32bit hashes seems to be not enough in terms of collisions - my savings with TT were miserable so I've dropped the idea to provide search best move feature for a while (also issues with async calls arising - I don't want search to block UI)

re: images resizing target cells
- I'm using idea that is implemented in Nano chess by OscarToledo:

Code: Select all

// draw piece
document.getElementById(square).innerHTML = '<img src="image.gif"></img>'
User avatar
hgm
Posts: 27701
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Pure javascript chess board library

Post by hgm »

The AI in the Interactive Diagram currently doesn't even have a hash table. That of course makes that it utterly sucks in the late end-game, in particular Pawn edings. (But it wasn't really its purpose to play those. I have a separate applet that plays by EGT.) The advantage is that I can more easily do extensions depending on the previous move. It accounts in half-plies, and for moves that 'touch' the squares of the previous two ply it charges only 0 or 1 half-ply (i.e. they are extended by a full or a half ply). Where 'touching' means it starts from, goes over, or goes to a square that was mutated. So logical follow ups, such as discovered attacks, pin punishment, recapture, plunder raids all get extended. There is no separate QS, but effectively the extension of recaptures by one full ply, and other new captures by half a ply, acts as a sufficient replacement.

I don't see why you should have a problem with a negative hash key, though. Surely you don't use the hash key itself as index? If you AND it with a mask shorter than 32 bits, the result should never be negative. Whether the signature is negative or not should not matter; you just store what was incrementally updated, and on probing you would compare with that too.

Using <img> in the table cells (which I think should not be accompanied by </img> in HTML) worked poorly for me. It seems HTML imagines some invisible margin at the botton of the image, which in size depends on the font size for the cell. (It considers the image characters, and aligns them such that there can be 'true decenders' for p and q.) So for moving the pieces around I assign their 'url("image.png")' to document.getElementById(square).style.backgroundImage . That solved all problems; even when images are larger than the cell it just clips them, without enlarging the square.
tomitank
Posts: 276
Joined: Sat Mar 04, 2017 12:24 pm
Location: Hungary

Re: Pure javascript chess board library

Post by tomitank »

maksimKorzh wrote: Wed Dec 02, 2020 2:43 pm I'm thinking about providing a simple alpha beta search to play against as well, but I'm having problems with negative indices in TT when hash key is negative. I know I can make it unsigned via Uint32Array([hash_key])[0] but when hash key gets incrementally updated it gets to negative values from time to time, also 32bit hashes seems to be not enough in terms of collisions - my savings with TT were miserable so I've dropped the idea to provide search best move feature for a while (also issues with async calls arising - I don't want search to block UI)
1. There will be nothing wrong with negative numbers.
2. You need to use webworker. It's don't block the UI.

I wrote my own engine and UI as well.
Here can you check:
iOS:
https://apps.apple.com/hu/app/sakk/id1150654415
Android:
https://play.google.com/store/apps/deta ... k.tanky.hu
Web:
http://mobil.tanky.hu/
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Pure javascript chess board library

Post by maksimKorzh »

tomitank wrote: Wed Dec 02, 2020 4:47 pm
maksimKorzh wrote: Wed Dec 02, 2020 2:43 pm I'm thinking about providing a simple alpha beta search to play against as well, but I'm having problems with negative indices in TT when hash key is negative. I know I can make it unsigned via Uint32Array([hash_key])[0] but when hash key gets incrementally updated it gets to negative values from time to time, also 32bit hashes seems to be not enough in terms of collisions - my savings with TT were miserable so I've dropped the idea to provide search best move feature for a while (also issues with async calls arising - I don't want search to block UI)
1. There will be nothing wrong with negative numbers.
2. You need to use webworker. It's don't block the UI.

I wrote my own engine and UI as well.
Here can you check:
iOS:
https://apps.apple.com/hu/app/sakk/id1150654415
Android:
https://play.google.com/store/apps/deta ... k.tanky.hu
Web:
http://mobil.tanky.hu/
Thanks) Your JS engine is very impressive - 15 ply depth in a matter of seconds in the browser - that's faster than my chess engine in C )))
tomitank
Posts: 276
Joined: Sat Mar 04, 2017 12:24 pm
Location: Hungary

Re: Pure javascript chess board library

Post by tomitank »

maksimKorzh wrote: Thu Dec 03, 2020 2:10 am
tomitank wrote: Wed Dec 02, 2020 4:47 pm
maksimKorzh wrote: Wed Dec 02, 2020 2:43 pm I'm thinking about providing a simple alpha beta search to play against as well, but I'm having problems with negative indices in TT when hash key is negative. I know I can make it unsigned via Uint32Array([hash_key])[0] but when hash key gets incrementally updated it gets to negative values from time to time, also 32bit hashes seems to be not enough in terms of collisions - my savings with TT were miserable so I've dropped the idea to provide search best move feature for a while (also issues with async calls arising - I don't want search to block UI)
1. There will be nothing wrong with negative numbers.
2. You need to use webworker. It's don't block the UI.

I wrote my own engine and UI as well.
Here can you check:
iOS:
https://apps.apple.com/hu/app/sakk/id1150654415
Android:
https://play.google.com/store/apps/deta ... k.tanky.hu
Web:
http://mobil.tanky.hu/
Thanks) Your JS engine is very impressive - 15 ply depth in a matter of seconds in the browser - that's faster than my chess engine in C )))
Tanks!
Currently the strongest JavaScript chess engine and to my knowledge, the only bitboard JavaScript engine.
User avatar
hgm
Posts: 27701
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Pure javascript chess board library

Post by hgm »

maksimKorzh wrote: Wed Dec 02, 2020 12:35 am - pure javascript implementation of GUI (HTML table)
What I like about your GUI is that you can drag the piece images. The Interactive Diagram lost that capability when I started displaying the pieces as background image. And even before that it did not work as well as in your case. Is this because you use the extra keyword 'draggable' in the <img> tags? Drag-drop moving in principle still works in the Interactive Diagram, in the sense that you can press the mouse button over a piece, and then release it on another square, and it will do the move. But there is no optical feedback suggesting you can do this; the mouse pointer remains unchanged when there is no foreground image in the cell.

The behavior is still not perfect, though: you would want the original image to disappear when you start dragging the piece. When dragging still worked I once tried to remove it from the cell, on the button press, but that did not work.

Do you have any ideas how this could be solved? I suppose there must be JavaScript calls to define a custom image for the mouse pointer. Then it should in principle be possible to remove the (background) piece image on press, and define the mouse pointer as the piece image.
tomitank
Posts: 276
Joined: Sat Mar 04, 2017 12:24 pm
Location: Hungary

Re: Pure javascript chess board library

Post by tomitank »

hgm wrote: Thu Dec 03, 2020 11:28 am
maksimKorzh wrote: Wed Dec 02, 2020 12:35 am - pure javascript implementation of GUI (HTML table)
What I like about your GUI is that you can drag the piece images. The Interactive Diagram lost that capability when I started displaying the pieces as background image. And even before that it did not work as well as in your case. Is this because you use the extra keyword 'draggable' in the <img> tags? Drag-drop moving in principle still works in the Interactive Diagram, in the sense that you can press the mouse button over a piece, and then release it on another square, and it will do the move. But there is no optical feedback suggesting you can do this; the mouse pointer remains unchanged when there is no foreground image in the cell.

The behavior is still not perfect, though: you would want the original image to disappear when you start dragging the piece. When dragging still worked I once tried to remove it from the cell, on the button press, but that did not work.

Do you have any ideas how this could be solved? I suppose there must be JavaScript calls to define a custom image for the mouse pointer. Then it should in principle be possible to remove the (background) piece image on press, and define the mouse pointer as the piece image.
Simplest and best way to use jquery with jquery-ui.
Another way you clone your image (and move this) and set visibility to hidden during you move the clone.
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Pure javascript chess board library

Post by maksimKorzh »

hgm wrote: Thu Dec 03, 2020 11:28 am
maksimKorzh wrote: Wed Dec 02, 2020 12:35 am - pure javascript implementation of GUI (HTML table)
What I like about your GUI is that you can drag the piece images. The Interactive Diagram lost that capability when I started displaying the pieces as background image. And even before that it did not work as well as in your case. Is this because you use the extra keyword 'draggable' in the <img> tags? Drag-drop moving in principle still works in the Interactive Diagram, in the sense that you can press the mouse button over a piece, and then release it on another square, and it will do the move. But there is no optical feedback suggesting you can do this; the mouse pointer remains unchanged when there is no foreground image in the cell.

The behavior is still not perfect, though: you would want the original image to disappear when you start dragging the piece. When dragging still worked I once tried to remove it from the cell, on the button press, but that did not work.

Do you have any ideas how this could be solved? I suppose there must be JavaScript calls to define a custom image for the mouse pointer. Then it should in principle be possible to remove the (background) piece image on press, and define the mouse pointer as the piece image.
re: keyword 'draggable':
- even though tutorials insist on that but it works without that as well, I guess in HTML5 its default for images

To keep your current implementation of pieces as background images the best thing is to use method proposed by tomitank - create a clone of image and stick it to the mouse pointer on 'ondragenter' event, but that's over complicated. You've mentioned the issue that piece images are resizing the board cells - my board allows to change its size on create and the way I handle it is as simple as to resize piece images basing on the cell size:

Code: Select all

// update board position (draw pieces)
  function update_board() {
    // loop over board rows
    for (var row = 0; row < 8; row++) {
      // loop over board columns
      for (var col = 0; col < 16; col++) {
        // int square
        var square = row * 16 + col;
        
        // make sure square is on board
        if ((square & 0x88) == 0)
          // draw pieces
          document.getElementById(square).innerHTML = '<img style="width: ' + 
                                                       (width ? width / 8: 400 / 8) + 
                                                      'px" draggable="true" id="' + 
                                                       board[square] + '" src ="Images/' + 
                                                      (board[square]) +'.gif">';
      }
    }
  }
and the entire drag-n-drop code is as trivial as this:

Code: Select all

// pick piece
  function drag_piece(event, square) {
    // init source square
    user_source = square;
    
    // "erase" piece on source square
    event.target.style.opacity = 0.0;
  }
  
  // drag piece
  function drag_over(event) {    
    // needed to allow drop
    event.preventDefault();    
  }
  
  // drop piece
  function drop_piece(square) {
    // init target square
    user_target = square;

    // move piece
    move_piece(square);
    
    // highlight square
    if (board[square])
      document.getElementById(square).style.backgroundColor = SELECT_COLOR;
  }
Did you try dynamic resizing of image width within style attribute to prevent cells from resizing?