My first full stack data science project (Part 4)…

Bhavya Rajdev
8 min readFeb 20, 2022

--

Link to previous article: Here
Link to next article: Here

In the previous article we build the website model. In this article we will discuss the design of website and how to encode all the chess rules, decode move notation strings, encode move clicks to notation and more.

First thing is to design the skeleton. Two main components as you can see on the webpage are chess board and the right part where all the data is displayed. Requirement here is that chess board must remain square, right side can shrink and expand but at some point right div should nicely wrap down. I couldn’t do it with pure CSS and took the help of JS as you can see in ‘skeleton.js’ file.

Next I designed right div. Four parts of right div. 1st div in right part has user data and rating data buttons. On changing them, second and fourth div in the main-right div will change accordingly. Next adding the required components in the second div like changing time class, username input box, changing color, ok buttons, rating range length and rating range. Also taking care that on changing range length the range will change in select tag and both select tags representing time classes are nicely duplicated. All of these are done in ‘main-right.js’ file.

Now designing the chess board. Adding alternating colors to squares, adding flip board functionality taking care of coordinates displayed on each row and column’s end. I am using flex item’s ordering and flex direction for this. All of these are done in ‘main-left.js’ file.

Time to do chess stuff. First thing is to code piece movement rules. Forget about whether our king will be in check if we move that piece, firstly just coding piece movement rules. You can simultaneously check the source code for below discussion on ‘show_legal_moves.js’ file. For all pieces we want to separate piece’s movement squares and attacking squares in 2 different arrays. Each array will be storing ‘position’ of squares (unique number representing each square. id=’b7' -> pos = (‘b’-’a’)*8+7 = 15)

King: a king can move only one square adjacent or diagonally. King can have at most 8 legal moves in a position. (up, right-up, right, right-down, down, left-down, left and left-up). Checking for all 8 cases. Castling is special kind of move king can make where king can move 2 squares from starting position provided that king won’t be in check for all three positions(32,40,48 for example), it’s king’s first move and rook’s first move and no piece are in between them. Storing the right to castle for both kings both sides in an array. Given king’s position in terms of i and j(id=’e6' -> i=’e’-’a’=4, j=‘6’-’1'=5) it returns king’s moving squares and attacking squares.

Pawn: a white pawn can move 1 square up the board(white’s perspective) and 2 squares up in a special case where pawn is in it’s starting position. Pawn’s attacking rules are different from it’s movement. It can attack it’s top left square and top-right square. Same rules are applied for black pawn just replace up with down in above description. Pawn can make special move which is called en-passant where if the white pawn is on 5th ‘rank’ and pawn’s next or previous ‘file’s pawns are on initial squares and moves 2 squares down, white pawn can capture that black pawn. Similar rule for black’s pawns as well.

Bishop: a bishop can move diagonally in any direction any number of squares as long as there’s no piece obstructing it’s path.

Rook: Similar to bishop it can move adjacently in any direction any number of squares as long as no piece is in it’s path

knight: a knight can move in L shape and jumping other pieces. knight will have at most 8 legal moves in any position

Queen: Think of queen as combination of both rook and a bishop. It can move to any square if a rook or bishop could move to.

Now we also need to check whether our king will be in check if we move particular piece from current position to new position. For that we first move that piece to new position, next get all the legal moves of the opponent and if one of the legal move is king’s current position, we can’t move that piece to new position, finally safely put that piece back to it’s current position and return true or false. dontMove parameter tells whether initially we want to move piece to it’s new position or not. This parameter is only required in case of checking for castling.

Now we want to wrap all the above written functions into one function which on given the position, it get all the possible move, then applies the kingInCheck filter to filter those moves which on playing will put it’s king in check. finally return the filtered ‘arr’ and ‘attacking’ arrays. This is what is going to be used in other files.

show_legal_moves function’s work is nothing but just to add styling around all the moving and attacking squares of piece.

25% of the chess stuff is done. ONLY part remaining is to play the move change global variables storing the current position. Source code is in the ‘moves_handling.js’ file.

User request to play the move will be given either in form of string like ‘e4’ or ‘Nxf3’ like that. Or playing a move on chess board(user will select a piece on board and click on another available square on board). Our code should be able to convert the move string into move and move into move string. Also going back a move functionality should work.

Firstly let’s start with move played on the chess board. If no piece is selected to play the move and we can select that piece to be played then we select that piece, show the available moves and captures on the board, store the html element of selected piece in a global variable and if some piece is already selected to play and user selected position position is amongst the move user can play, we play the move using changePos() function. ‘position’ array of 32 length is storing position of all the pieces on the board as shown in ‘declarations.js’ file. stackMovesPlayed array is storing stack of all moves played in form of [fromElem, toElem, piece_that_was_captured, index_of_that_piece _in_position_array]. castling and en-passant are special moves and are given special care. getMovesString() and checkOrMate() functions are used to convert move played on board to a move string. Let’s discuss all the functions used here one by one. Forget about first line in the function, it will come later in the next article.

changePos(): it changes the background image of squares on board and does changes in position array like piece position change or captured position to -1. Why are we storing again in ‘savePrev’ variable because remember this function was also called in kingInCheck() function and changeBack() will need it later.

checkPlayCastling(): This function will check if the castling is played(not checking if it’s possible, this is already done) and if it’s played, this will just change position of rook to it’s destination and not touching the king. King movement will be done by changePos() function. Also modifying the first moves of king and rook, as it’s required to check if user has right to castle or not.

checkPlayEnPassant(): Similar to above function this will check if en passant is played and if it’s played change position of opponent’s pawn and that square’s image. Again user’s colored pawn will be moved by changePos().

Now we want to convert our move played into string. Played move is already stored in the stackMovesPlayed. First we get the name of piece which is moved like ‘k’(black king), ‘p’(white pawn) etc. Check if the same piece which is on another square which can come to same square then add the rank or file name in notation as well. If some piece was captured then add ‘X’ in notation and finally add the id of destination square.

checkOrMate(): is a function to add ‘+’ or ‘#’ means check or mate in the moves notation. This is called after the positions are changed. Firstly check if the king is in check or not and if it’s in check, check for checkmate means check if user’s all pieces don’t have any legal moves. If it’s true then add ‘#’ sign in the notation.

Finally make changes in the moves box as we already have function to convert move into the move notation string.

Now the second type of request user can give to play a move is via string. If we can convert move string into move click then other things are already done in moveClicked() function.
Looks like we just need to reverse the procedure of getMovesString(). The goal is to get the starting position and destination position of move. Destination position we can get easily by extracting 2 ending positions in the notation string and drop those positions. Pawn move and pawn captures should be taken care differently. For knight and rook we want to check which knight and rook is coming to that position. We also want to check for castling. As we have starting and destination positions we can call moveClicked() which will take care of everything remained.

Now finally we want our current board to be able to go back moves. changeBack() is the function that will have two jobs. One is to change back a played move and another is when it’s called from kingInCheck() function where the move is not played by user. That will be decided by colorChanged parameter. If the color is changed means if the move is played, then set the previous move ‘savePrev’ as last value in stack of moves played. Why we want to do that ? because ‘savePrev’ variable is handled by changePos() function which is not just called when really move is played but also from kingInCheck() its called which will reset the ‘savePrev’. We’ll discuss all the functions used in changeBack function one by one.

checkPlayBackCastling(): check if the castling was played and if it was played change the position of rook back. Not to touch the king. This is similar to checkPlayCastling().

Again there’s a chance of ‘savePrev’ to reset. So set it back to last value of stackMovesPlayed.
changeBackMovesBox(): Nothing but just doing the work of popping some required characters from the moves box and reset it to ‘Moves’ if it was first move.
changeBackEnPassant(): Similar to change back castling, this will check if en passant was played and if it was played change the position of opponent’s pawn. User’s pawn position will be changed by change back helper function

changeBackHelper(): Every required information is stored in ‘savePrev’. Extract info from it and change positions in the ‘positions’ array and make changes in images displayed on board.

This part is finally over. In the next article we’ll discuss Django stuff to connect the work we did in the 2nd, 3rd and 4th article together. Link to next article: Here

--

--