This is a browser based multiplayer chess engine written in Node.
This project made into the top 5 projects in TinkerHub HireHack.
- Express hosts the server
- Using Sockets.io, real time communication between server and clients could be achieved through events.
- The server stores the details of each room in a MongoDB.
- If the player creates a room, a new document is created in DB and a new room is allocated to the player.
- Joining or creating a room will lead to the
getGameId
event, which sends thegameId
to the client. - After 2 players are in a room, the game countdown starts by emitting the
startCountDown
event. - If a player quit during the countdown, an
endCountDownDisconnect
event is emitted and the countdown stops. - After the countdown ends, if the room still has 2 players, the game will begin by emitting
startGame
event. - Each move made by the player is sent to the server using
makeMove
event. - The board state is read from the db and the move is validated. The board is sent to the listening clients through
updateBoard
event. - This goes on until the game is over through victory or draw.
- After the game is over, the game's details are removed from DB.
The chess logic run by the server is stored in /server/chess/. The client side does not support exports and require, so it is separately maintained in /static/chessBrowser.js.
FEN notation is used to store the board state in db. The only disadvantage is it can't store pawn promotion data, so it has to be separately maintained.
All the pieces extend the Base Class Piece
.
The Piece
Class
Member | Overriden | Usage |
---|---|---|
type | yes | The string representation |
player | no | The owner of this piece |
nextNormalMoves | yes | The directions for the next moves |
nextCaptureMoves | yes | The directions for the next capture moves(Pawn Only) |
multipleMoves | yes | Whether this piece can move multiple columns |
getSpecialMoves() | yes | Return the absoule positions of this piece's special moves |
getAllMoves() | no | Return the next moves based on the attributes |
getPlayer() | no | Get the owner of the provided piece |
Takes a board Object, the position(Integer), and additional args(dictionary) required for special Moves. This should be implemented by Pieces having special moves like Pawn(En Passant, Double First Move) and King(Castling).
Takes a board Object, the position(Integer), and additional args(dictionary) required for special Moves. This generates the next moves of a particular piece based on nextNormalMoves, nextCaptureMoves, getSpecialMoves(), and multipleMoves.
This Class is mainly used to represent the board state, to perform move generation, make moves and check game over.
The positions of the pieces is represented in an array of length 64. Empty columns are marked null.
- Get all pieces of the
player
from the board and store them by mapping to their position. - For each piece in pieces call
piece.getAllMoves()
, and store them tovalidMoves
by mapping to their position. - If checkForCheck is false, return
validMoves
- Else check if move is legal by making the move and checking if this player is in check.
- If not in check add to
legalMoves[position]
. - return
legalMoves
.
- Get the position of
player
's king. - Get all moves of the enemy by
this.getNextMoves(false, changePlayer(player))
.checkForCheck
is set tofalse
to avoid infinite recursion. - If any enemy piece can move to the king's location, the player is in check.
This function makes the actual changes to the array
property. It also changes the properties like enPassantSquare
, castleData
, etc according to the move
- A Player has won -> Enemy has no legal moves and is in check(checkVictory function)
- The game is drawn(checkDraw function)
- Stalemate: The enemy has no legal moves but isn't in check.(checkStalemate function)
- 50 move rule: Game is automatically drawn after 50 consecutive halfmoves.
Currently move is validated outside the chess core files.
Server Side -> socketEvents
Client Side -> chessClient
The Logic
- Generate NextMoves
- Check if this move in NextMoves.
-
The
makeMove
function will set theBoard.pawnPromotion
attribute if eligible for pawn promotion. The player won't be changed if eligible. -
The server will send a
startPawnPromotion
event to the room. The eligible player has to pick a piece for promotion. No other moves are allowed. The promotionData would be written to the db. -
On choosing a piece the client would send a
promotePawn
event to the server. Which would in turn send asuccessPawnPromotion
orerrorPawnPromotion
event back based on the promotionData stored by the db. -
On
successPawnPromotion
, the game will resume and the other player gets their turn.
All server side socket handling is located in socketEvents.js
All client side socket handling is located in index.html
Event | Emitter | Data | Functionality |
---|---|---|---|
roomCreate |
Client | null | Indicate to the server a new room has been created. |
roomJoin |
Client | null | Indicate to the server a new player has joined the room. |
getGameId |
Server | gameId | Emit the game Id to the client. |
startCountDown |
Server | null | Emit to the room to start the countdown. |
coutdownFinished |
Client | gameId | Emit to the server that coutdown has finished. |
endCountDownDisconnect |
Server | null | Emit to the room that countdown must be stopped due to a disconnecting player |
startGame |
Server | initialBoard | Emit to the room to start the game. |
playerColor |
Server | color | Emit the color of the client to the client. |
invalidRoomId |
Server | null | Emit that the room id is invalid to the client. |
makeMove |
Client | gameId, from, to | Emit the move made by the player to server. |
boardUpdated |
Server | fen | Emit the current board state to the room. |
invalidMove |
Server | null | Emit to indicate the proposed move is invalid. |
victory |
Server | player | Emit to the room, that player is the winner. |
draw |
Server | null | Emit to the room that the game has been drawn. |
startPawnPromotion |
Server | player | Emit to the room that player can promote a pawn. |
successPawnPromotion |
Server | null | Emit to the client that Pawn Promotion is successfull. |
errorPawnPromotion |
Server | null | Emit to the client that Pawn Promotion Failed. |
promotePawn |
Client | gameId, piece | Emit to the server that the client requests to promote the pawn to piece |
playerDisconnect |
Server | null | Emit to the room that a player has disconnected. |
endGameDisconnect |
Server | null | Emit to the room that the current game has ended due to a player being disconnected. |