July 2026
Multiplayer chess on Flask and WebSockets
The objective of this project was to create a web-based chess platform for groups of friends to play people they know, without subscriptions or the connection problems associated with larger platforms. Players can select time controls and game variants before being paired with another player using the same settings. I first developed the platform for my A-level coursework and have since rebuilt it. Both the original project and the rebuild are on GitHub.
Analysis and requirements
To understand the needs of players in my age group, I circulated a survey and received 17 responses. I then compared the features requested by those users with the ten leading online chess platforms. The most valued features were personalised game settings and the ability to play friends. Learning resources, tournaments and mobile compatibility were less important to the survey group.
This analysis also helped define which features not to include. Game chat was not essential because groups of friends already communicate through WhatsApp, Discord or voice calls. Public forums require a large active user base and were not relevant to the intended use of the platform. I therefore prioritised a reliable chess game, user accounts, direct challenges and personalised time controls.
Chess game implementation
Key to providing a robust platform was ensuring that every move complied with the rules of chess. The movement of the six piece types is relatively straightforward; the difficulty comes from exceptions such as castling, en passant and promotion.
Castling is only legal when the king and the relevant rook have not moved, the squares between them are empty, and the king is not in check or passing through an attacked square. En passant requires the board to record when a pawn has moved two squares and to clear that state after the following move. Promotion changes the piece object while a move is being completed.
The main object is a Board containing a two-dimensional array of Square objects, which may themselves contain a piece. The piece classes inherit from a common parent and generate pseudo-legal moves according to their own movement rules. To produce legal moves, the program copies the board, plays each candidate move and rejects any move that leaves the player's king in check. FEN notation is used to load and save positions.
Server and web interface
The back end is powered by Flask, with Flask-SocketIO providing real-time, bidirectional communication between the server and each browser. This allows a move made by one player to update the opponent's board without refreshing the page.
When a signed-in client connects, it joins a Socket.IO room named after its user ID. A direct challenge can then be sent to that room. For automatic pairing, the player submits a time control and increment. The server either matches the request with a waiting player using the same settings or creates a new game and waits for a suitable opponent.
Flask-Login manages user sessions, with persistent sign-in enabled so that accidentally closing a tab does not end an active game.
Database and testing
The MySQL database is accessed through SQLAlchemy. A Player record stores a username, email address, password hash, rating and game results. Passwords are processed using Werkzeug's generate_password_hash, so the original password is not stored.
Friendship is represented by a self-referential association table because it is a many-to-many relationship between records in the same player table. The relationship loads only when required, preventing every player query from also retrieving the complete friend list.
I focused the automated tests on the rules engine rather than the web framework. Eighteen unit tests cover the square and board objects, including FEN loading, check detection, promotion, pseudo-legal and legal move generation, and en passant. The suite completes in 0.169 seconds.
Features added in the rebuild
The rebuild adds bughouse, a four-player variant played across two boards. A captured piece is transferred to the player's partner and can then be placed on the second board instead of making a normal move. This was listed as an optional feature in the original analysis and became the main addition to the second version.
The bughouse board inherits from the standard board and adds a pool of held pieces. The FEN representation is extended to include this pool, allowing the existing move-validation logic to be reused while adding the new drop move. The rebuild also includes friend lists, direct challenges, rematches and clock timeouts.
Evaluation and possible improvements
The main change I would make is to remove the use of deep copies during move validation. Copying the complete board for every pseudo-legal move is reliable, but it allocates a full position simply to test whether the king remains safe. A later bitboard chess engine uses make and unmake operations instead, changing only the required bits before reversing the move.
This performance limitation did not prevent the platform from meeting its original requirements because a human player takes much longer to select a move than the validation process requires. However, revisiting the same problem later showed how a different board representation can process hundreds of thousands of positions per second without repeatedly copying the board.