hgm wrote: ↑Thu Jan 24, 2019 3:46 pm
I am currently developing a server for playing (human) games over the internet, based on the Jocly user interface. The latter is a JavaScript library for implementing a chess board in 2d or 3d (based on WebGL) display, and enforcing the game rules on it. It already supports a multitude of games, not only chess variants, but also Draughts, Amazons, Annexation, Spline, Scrum, Yohoho, ...
But everything in Jocly is trictly local; it runs in your web browser, and you can do local games with it, but it does not connect to any remote opponent, neither peer-to-peer nor to a server. So that is the functionality I aim to add.
To allow communication between remote users I opted for a Game Server that is embedded in a standard HTTP server, as a CGI 'script'. (In fact it is the executable of a compiled C program.) In such a design the Game Server does not run as a persistent process, handling one command after another. Instead a new process is started for every user (HTTP) request, to handle only that request, and deliver a response to it. The persistent state of the Game Server is completely implemented in the file system of the server machine. The CGI script gives the users read and (highly-restricted) write access to this state.
I try to keep the server side of this design as simple and general as possible. ('Minimalist' would be a good description.) As Jocly is already a very powerful piece of software running in the clients, it makes sense to delegate as many tasks as possible to that. So the Game Server doesn't have to worry about legality testing of game moves, or nicely formatting its output. To it, games are just a list of moves, and moves are blackboxes that it passes along. And data requested by the user are just provided as a number of lines, each a comma-separated list. Clients can convert this info (or the part of it they want to show) into HTML that would display nicely.
Overview of server tasks
The state of the Game Server is basically just the collection of games, where each game has its own state. The latter must be modifiable by the players of that game: they must add moves to it. Of course only the player that is on move must be allowed to add a move, so it must be possible to recognize and verify the identity of the users. For this a (not publicly accessible) password file is needed, storing identities as a (public) user / (secret) password combination. To not unnecessarily burden the server operator, the Game Server must also maintain that password file.
I opted for storing each game in a separate file, recognizable by a unique number. (Like game327.txt.) Each move is stored as a separate line, so submitting a move would just append the move text as a new line to it. The first two lines are reserved for the player names and the game type (e.g. 'brazilian-draughts').
Because users will frequently want to fetch a list of games, and it would be very cumbersome to open all game files to get the player names, the Game Server will also maintain a game-list file (gamelist.txt). In a fixed-size format this contains for each game the name of the white and black player, the game type, the player clocks, and a game-state indicator. The latter is a single character that indiates who is to move (w or b), whether a draw offer is pending (capital W or B), or whether the game is finished (+, = or -). The player names and game type are immutable once the game is created, but the state and clocks must of course be updated on every move. This requires random write access to the file (hence the fixed size of its elements).
List of user requests
* add a user / password combination to the password file
* read the user names in the password file
* read the game list (possibly filtered by a player name or game type)
* read a game file (possibly suppressing the moves he is already aware of)
* put a 'game request' (a game with as yet unknown opponent) in the game list
* satisfy a game request to initiate a game
* possibly delete a game request that no one wants to satisfy
* add a move to a game
* resign a game
* offer a draw in a game
* abort a game (?)
A server could also allow chatting between users. This would add extra state, and extra requests to read or modify that state. I haven't thought much about that yet.