CSSE7231 – Semester 2, 2024 Assignment 4 (Version 1.2)
Specification changes since version 1.0 are shown in red and are summarised at the end of the document. Changes from v1.1 to v1.2 are shown in blue.
Introduction 1
The goal of this assignment is to further develop your C programming skills, and to demonstrate your under- 2 standing of networking and multithreaded programming. You are to create a server program (uqchessserver) 3 that supports multiple simultaneously connected clients playing chess against another client or against a chess 4 engine (Stockfish). The server will maintain pipe connections to and from a single chess engine process and 5 mediate client requests for the engine’s services. You should also create a client program (uqchessclient) that 6 can send requests to the server and show responses. 3407 7Communication between the clients and uqchessserver is over TCP using a text based protocol defined 8 later in this specification. 9 CSSE7231 students are expected to also implement some additional server functionality. 10 The assignment will also test your ability to code to a particular programming style guide and to use a 11 revision control system appropriately. 12 It is not necessary that you know how to play chess to undertake this assignment, though knowledge of 13 how pieces can move on a chess board may be useful in testing (i.e. knowing which moves are valid). See 14 https://en.wikipedia.org/wiki/Chess#Rules to learn more about the rules of chess if you are interested. 3407 15
Student Conduct 16
This section is unchanged from assignments one and three – but you should remind yourself of the referencing requirements. Remember that you can’t copy code from websites and if you learn about how to use a library 17 function from a resource other than course-provided material then you must reference it.
This is an individual assignment. You should feel free to discuss general aspects of C programming and 18 the assignment specification with fellow students, including on the discussion forum. In general, questions like 19 “How should the program behave if ⟨this happens⟩?” would be safe, if they are seeking clarification on the 20 specification. 21
You must not actively help (or seek help from) other students or other people with the actual design, structure 22 and/or coding of your assignment solution. It is cheating to look at another person’s assignment code 23 and it is cheating to allow your code to be seen or shared in printed or electronic form by others. 24 All submitted code will be subject to automated checks for plagiarism and collusion. If we detect plagiarism or 25 collusion, formal misconduct actions will be initiated against you, and those you cheated with. That’s right, if 26 you share your code with a friend, even inadvertently, then both of you are in trouble. Do not post your 27 code to a public place such as the course discussion forum or a public code repository. (Code in private posts 28 to the discussion forum is permitted.) You must assume that some students in the course may have very long 29 extensions so do not post your code to any public repository until at least three months after the result release 30 date for the course (or check with the course coordinator if you wish to post it sooner). Do not allow others to 31 access your computer – you must keep your code secure. Never leave your work unattended. 32
You must follow the following code usage and referencing rules for all code committed to your SVN 33
repository (not just the version that you submit):
Code Origin
Usage/Referencing
Code written by, modified by, debugged by, explained by, obtained from, or based on the output of, an artificial intelligence tool or other code generation tool that you alone personally have interacted with, without the assis- tance of another person. This includes code you wrote yourself but then modified or debugged because of your interaction with such a tool. It also includes code you wrote where you learned about the concepts or library functions etc. because of your interaction with such a tool. It also includes where comments are written by such a tool – comments are part of your code.
Code copied from sources not mentioned above
Code, in any programming language:
copied from any website or forum (including Stack-
Overflow and CSDN);
copied from any public or private repositories;
copied from textbooks, publications, videos, apps;
copied from code provided by teaching staff only
in a previous offering of this course (e.g. previous
assignment one solution);
written by or partially written by someone else or
written with the assistance of someone else (other
than a teaching staff member);
written by an AI tool that you did not personally
and solely interact with;
written by you and available to other students; or
from any other source besides those mentioned in
earlier table rows above.
May be used freely without reference. (You must be able to point to the source if queried about it – so you may find it easier to reference the code.)
Permitted
May be used freely without reference. (This assumes that no reference was required for the original use.)
Conditions apply, references required
May be used provided you understand the code AND the source of the code is referenced in a comment adjacent to that code (in the required format – see the style guide). If such code is used without appropriate referencing then this will be considered misconduct.
Conditions apply, references & documentation req’d
May be used provided you understand the code AND the source of the code or learning is referenced in a com- ment adjacent to that code (in the required format – see the style guide) AND an ASCII text file (named toolHistory.txt) is included in your repository and with your submission that describes in detail how the tool was used. (All of your interactions with the tool must be captured.) The file must be committed to the reposi- tory at the same time as any code derived from such a tool. If such code is used without appropriate referencing and without inclusion of the toolHistory.txt file then this will be considered misconduct. See the detailed AI tool use documentation requirements on Blackboard – this tells you what must be in the toolHistory.txt file.
Code provided to you in writing this semester by CSSE7231 teaching staff (e.g., code hosted on Blackboard, found in /local/courses/csse2310/resources on moss, posted on the discussion forum by teaching staff, provided in Ed Lessons, or shown in class).
Code provided by teaching staff this semester
Permitted
Code you have personally written this semester for CSSE7231 (e.g. code written for A1 reused in A3) – pro- vided you have not shared or published it.
Code you wrote this semester for this course
Code you have personally written in a previous enrolment in this course or in another UQ course or for other reasons and where that code has not been shared with any other person or published in any way.
Unpublished code you wrote earlier
Code examples found in man pages on moss. (This does not apply to code from man pages found on other systems or websites unless that code is also in the moss man page.)
Code from man pages on moss
Code and learning from AI tools
May not be used. If the source of the code is referenced adjacent to the code then this will be considered code without academic merit (not misconduct) and will be re- moved from your assignment prior to marking (which may cause compilation to fail and zero marks to be awarded). Copied code without adjacent referencing will be consid- ered misconduct and action will be taken.
This prohibition includes code written in other program- ming languages that has been converted to C.
Examples, websites, discussions, videos, code (in any pro- gramming language), etc. that you have learned from or that you have taken inspiration from or based any part of your code on but have not copied or just converted from another programming language. This includes learning about the existence of and behaviour of library functions and system calls that are not covered in class.
Code that you have learned from
May be used provided you do not directly copy code AND you understand the code AND the source of the code or inspiration or learning is referenced in a comment adjacent to that code (in the required format – see the style guide). If such code is used without appropriate referencing then this will be considered misconduct.
You must not share this assignment specification with any person (other than course staff), organ- 35 isation, website, etc. Uploading or otherwise providing the assignment specification or part of it to a third 36 party including online tutorial and contract cheating websites is considered misconduct. The university is aware 37 of many of these sites and many cooperate with us in misconduct investigations. You are permitted to post 38 small extracts of this document to the course Ed Discussion forum for the purposes of seeking or providing 39 clarification on this specification. 40
In short – Don’t risk it! If you’re having trouble, seek help early from a member of the teaching staff. 41 Don’t be tempted to copy another student’s code or to use an online cheating service. Don’t help another 42 CSSE2310/7231 student with their code no matter how desperate they may be and no matter how close your 43 relationship. You should read and understand the statements on student misconduct in the course profile and 44 on the school website: https://eecs.uq.edu.au/current-students/guidelines-and-policies-students/ 45 student-conduct. 46
Specification - uqchessclient 47
The uqchessclient program provides a command line interface that allows you to interact with the server 48 (uqchessserver) as a client – connecting for a session, playing one or more games in that session and then 49 exiting. Because your client will need to listen for incoming messages on both stdin and the network connection, 50 it will require two threads. Alternatively, you can implement your client using multiplexed IO as demonstrated 51 in class.3407 52
Command Line Arguments 53
Your uqchessclient program is to accept command line arguments as follows: 54 ./uqchessclient portno [--col white|black] [--play machine|person] 55
The square brackets ([]) indicate optional arguments. The pipe symbol (|) indicates a choice. Italics 56 indicate a placeholder for a user-supplied arguments. The portno argument must always be the first argument. 57 Option arguments can be in any order after the portno argument. 58
Some examples of how the program might be run include the following1: 59 ./uqchessclient 1234 60
./uqchessclient 3456 --play machine 61
./uqchessclient mysql --col black 62
./uqchessclient 8978 --col white --play person 63 The meaning of the arguments is as follows:3407 64
portno – this mandatory argument specifies which localhost port the server is listening on – either 65 numerical or the name of a service. 66
--play – if specified, this option is followed by either the string machine or person and indicates that, 67 by default, the user wishes to play against the computer (i.e. the chess engine) or a “human” player 68 respectively. If this argument is not specified, then the default is to play against the computer. 3407 69
--col – if specified, this option argument is followed by either the string white or black and indicates 70 the colour (white or black) that the user wishes to be. If this argument is not specified, then the default 71 is play white against a computer opponent and either colour against the first available human opponent. 72 Note that white always plays first in chess.3407 73
Prior to doing anything else, your program must check the command line arguments for validity. If the 74 program receives an invalid command line then it must print the (single line) message: 75
Usage: uqchessclient portno [--col white|black] [--play machine|person] 76 to standard error (with a following newline), and exit with an exit status of 2. 77
Invalid command lines include (but may not be limited to) any of the following: 78 • No arguments are present (i.e. there is no portno argument) 79
• An option argument is present but is not followed by a valid option value 80 1This is not an exhaustive list and does not show all possible combinations of arguments. The examples also assume that a
• Any of the option arguments is listed more than once. 81 • An unexpected argument is present.3407 82 • Any argument is the empty string. 83
Checking whether the portno is a valid port or service name is not part of the usage checking (other than 84 checking that the value is not empty). The validity of the port or service name is checked after command line 85 validity as described next. 86
Client Port Checking 87
If uqchessclient is unable to create a socket and connect to the server on the specified port (or service name) 88 of host localhost, it shall print the following message (terminated by a newline) to stderr and exit with exit 89 status 7: 90
uqchessclient: unable to make connection to port "N" 91 where N should be replaced by the argument given on the command line. (This may be a non-numerical string.) 92
The double quotes must be present.3407 93 Client Runtime Behaviour 94
Assuming that the checks above are passed and your uqchessclient can successfully connect to the server, 95 then your uqchessclient must print and flush the following message to stdout (terminated by a newline): 96
Welcome to UQChessClient - written by s4876492 97
Once this message is printed, the client will act as if a newgame command has been entered by the user as 98 described below (i.e. send a “start” message to the server with appropriate argument(s)) and must then read 99 lines of input from the user (via stdin) and respond to them as described below (e.g. usually by sending a 100 message to the server), and will simultaneously read lines received from the server (via the connected socket) 101 and respond to them as described below. Often the messages from the server will be responses to requests 102 sent by the client but this is not always the case. Communication is asynchronous – either party can send a 103 message at any time – so your client must be implemented to support this. You can do this by using two threads 104 (one reading from stdin and one reading from the connected network socket) or by using multiplexed IO as 105 demonstrated in class.3407 106
Note that uqchessclient does not have to understand chess or know the current position of pieces, etc. 107 The server will keep track of the game state. The client must however keep track of whether a game is currently 108 in progress or not and whose turn it currently is (the user or the opponent) and what colour the user is playing. 109 3407 110
Client – Handling Standard Input 111
The user can enter the following commands on stdin. Commands are to be terminated by a single newline. 112 No leading or trailing spaces are to be accepted. If an invalid command is entered, then uqchessclient must 113 print the following message to stderr (terminated by a newline):3407 114
Try again - command invalid 115
Valid commands are listed below. In most cases, these will result in a message being sent to the server. 116 See the Communication Protocol section on page 6 for details for how those messages are formatted and which 117 arguments are mandatory and which are optional. 118
newgame 119 This command indicates that the user wishes to start a new game and will result in a “start” message 120 being sent to the server (with appropriate argument(s)). This command is valid even if a current game is 121 in progress (no matter whose turn it is). If playing against a computer, uqchessclient must send either 122 “black” or “white” as the desired colour with the “start” message, not “either”. (The default colour 123 when playing the computer is “white” when no colour is specified on the command line.) 124
print 125 This command this indicates that the user wishes to have the current state of the board printed out. If a 126 game is in progress or has finished then the command will result in a “board” message being sent to the 127
server. (The client does not keep track of the board state – it must ask the server for this.) If the first 128
game has not been started yet then an error message must be printed (see below)2.3407
129
hint 130 This command indicates that the user wishes to receive a hint from the server’s chess engine about the 131 best move to make next. If a game is in progress and it is the user’s turn then the command will result 132 in the “hint best” message being sent to the server. Otherwise, an error message must be printed (see 133 below). 134
possible 135 This command indicates that the user wishes to know all possible moves that they could make given the 136 current game state. If a game is in progress and it is the user’s turn then the command will result in the 137 “hint all” message being sent to the server. Otherwise, an error message must be printed (see below). 138
move movestring 139 This command indicates that the user wishes to make the indicated move. The command “move” must be 140 followed by a single space and then by 4 or 5 alphanumeric characters before the newline (the movestring ) 141 to be considered valid. This associated movestring argument is a chess move expressed in standard chess 142 long algebraic notation as used by the Universal Chess Interface (UCI), e.g. e2e4 indicates that the piece on 143 square e2 should be moved to square e43. See https://en.wikipedia.org/wiki/Algebraic_notation_ 144 (chess) for details on chess notations. If the command is invalid then a message must be printed as 145 described above. If the command is valid and a game is in progress and it is the user’s turn then this will 146 result in a “move” message being sent to the server. Otherwise, an error message must be printed (see 147 below). (Note that a valid command may not contain a valid chess move. The server will report this if 148 needed – it is not the client’s job to know which moves are valid on the game board or not.)3407 149
resign 150 This command indicates that the user wishes to resign from the current game. If a game is in progress 151 then this will result in a “resign” message being sent to the server. Otherwise, an error message must be 152 printed (see below). A user can resign at any time in the game, not just when it is their turn.3407 153
quit 154 This command indicates that the user wishes to exit the program. The uqchessclient program should 155 exit immediately, without sending anything to the server. The same behaviour is expected if the stdin 156 of uqchessclient is closed even if the user has entered part of a command (e.g. stdin will be closed if 157 a terminal user presses Ctrl-D at the start of a line or Ctrl-D Ctrl-D part way through a line). Partially 158 entered lines are to be ignored. Your client must exit with status 0. 159
If a valid command above is entered (i.e. the line matches the syntax outlined above) but no action can be 160 taken because a game is not in progress or hasn’t started yet, then uqchessclient must print a message to 161 stderr (with a terminating newline): 162
Invalid command - game is not in progress 163
The client should consider a game to be in progress from the time it receives an “ok” a “started” response 164 in reply to a “start” message through until the time it receives a “gameover” message. 165 If a game is in progress, but a valid command can’t be acted on because it is not the user’s turn, then 166 uqchessclient must print a message to stderr (with a terminating newline):3407 167
Command is not valid - not your turn 168 No messages are to be sent to the server in either of these cases. The user can enter another command if 169
desired. 170 Client – Handling Messages from Server 171
The client may receive messages from the server at any time. These messages will have the form outlined in 172 the Communication Protocol section below. 173 The client must just print all lines of text received from the server to the client’s stdout, with the exception 174 of the startboard and endboard lines that surround the depiction of the game board. (The lines between these 175 keywords will be output – including any blank lines.) All messages must be flushed to stdout upon receipt4. 176
2The only situation in which this error should happen is if the client wishes to play a human and no human opponent has yet been assigned.
3A movestring may be 5 characters for a pawn promotion move, e.g. g7g8q indicates a pawn moving to the final rank and being promoted to a queen.
4uqchessclient can not assume that stdout is line buffered.
There is no need for the client to check that messages comply with the protocol – they can just be output as 177 described.3407 178 The client must also use the content of the messages (e.g. “gameover” messages and others) to keep track 179 of the game state, specifically, whether a game is currently in progress, and if so, whether it is the client’s turn 180 to play or not. Specifically, a game will be in progress from when the client receives a “started” message from 181 the server until it receives a “gameover” message. The player whose turn it is will change every time an “ok” 182 or “moved” message is received from the server. 183 Note that a well implemented client should almost never receive some error responses from the server – it 184 should never send an invalid command and it should never send commands that assume a game is in progress 185 if it is not. It may receive an error message if the chess engine fails or if a move is invalid. Rarely, a game-not- 186 in-progess error will be received in the event that a game-ending race condition occurs5. error messages from 187 the server should just be printed to the client’s stdout like other messages from the server. 188
Other Client Requirements 189 If your client detects that the connection to the server has been closed then it should print the following message 190
to stderr (terminated by a newline): 191 uqchessclient: server connection closed 192
and exit with status 18. 193 There is no requirement that uqchessclient free all memory before exiting. 3407 194 Your client must not exit due to SIGPIPE. 195
Communication Protocol 196
This section describes the incoming and outgoing messages that will be supported by uqchessserver. All 197 messages are to be terminated with a single newline (\n) and no leading or trailing spaces are permitted. Each 198 message is a command word that may be followed by arguments as described below. If a message accepts 199 arguments then arguments must be separated using a single space character. In the messages below, square 200 brackets ([]) indicate optional arguments, and italics indicate placeholders for specified values.3407 201
See the Specification - uqchessserver section below for precise details of how the server should behave. 202 Messages to server 203
The following incoming messages must be supported by uqchessserver. 204
• start against colour 205 – A “start” message indicates to the server that the client is starting a new game. The argument 206 against must be either “computer” or “human” (without the quotes) and indicates to the server 207 which type of opponent the client will play against. The argument colour must be one of “either”, 208 “black” or “white” (without the quotes) and indicates the colour of pieces that the client will use. 209 The “either” option will only matter if the client is playing against a human. If this option is specified 210 with a “computer” opponent, then the client will be playing white pieces. See the Specification - 211 uqchessserver section for details of how the server assigns colours to human players if “either” is 212 specified.3407 213
– The server’s response to this message will be a “started” message – see below. This may take some 214 time to come back if the client is requesting to play a human and no other player has connected to 215 the server. This “started” response will specify which colour that this client will be playing (which 216 will match the colour specified by this client if black or white was specified). 217
– If a game is in progress for this client when this message is sent, then the server must treat this 218 as a resignation and send a “gameover” response as described below, before sending the “started” 219 message.3407 220
– If the client is playing the “computer” and has chosen to be black, then the server (playing white) 221 will also send a “moved” message to indicate the computer’s first move in the game. 222
5A race condition can occur if the client believes that a game is in progress and sends a message on this basis, but the server has just received a resignation from their human opponent so finishes the game, but receives the client’s message before sending out the gameover message to the client – followed by an error 3 message in response to the client’s message because the game is no longer in progress.
• board 223 – This message asks the server to return the current game board or the game board of a game that 224 has just finished (anytime before a “start” request is made). If a game is in progress or has just 225 finished, the server will respond with a multi-line response starting with startboard and finishing 226 with endboard - see below. If the first game has not started yet, the server will respond with an 227 error response. 228
• hint best|all 229
– Either “best” or “all” (without the quotes) must be given as an argument to the “hint” command.3407 230
– With the “best” argument, this message asks the server to return a hint to the client about the next 231
move that the client can make. If a game is in progress and it is this client’s turn then the server 232 will respond with a moves response (see below), otherwise the server will respond with an error 233 response. 234
– With the “all” argument, this message asks the server to return a list of all the possible moves a 235 client can make. If a game is in progress and it is this client’s turn then the server will respond with 236 a moves response (see below), otherwise the server will respond with an error response. 237
• move move-to-make 238
– This message indicates the move that the client wishes to make. The required argument move-to-make 239 must be a 4 or 5 character alphanumeric string that indicates the move in long chess algebraic no- 240 tation (e.g. e2e46). The server will respond with either an “ok” or “error” response depending on 241 whether the move is valid in the current game state or not. 3407 A “move” command will be considered 242 valid (i.e. will not result in an “error command” response from the server) if the move-to-make 243 argument consists of 4 or 5 letters and or numbers (alphanumeric characters). The server should not 244 check that the letters/numbers form a valid move – this is left to the chess engine. 245
– If the move was accepted (“ok” response received) then the message might also be followed by a 246 “check” or “gameover” response from the server if the move resulted in check or checkmate or 247 stalemate. (See the Specification - uqchessserver section for details.) 248
– If the client is playing the “computer” (and the client’s move did not finish the game) then the server 249 will also send a moved message to indicate the move that the “computer” is making. 250
• resign 251 – This message indicates that the client is resigning from the current game. The server will respond 252 with either a gameover or error response – see below. 253
Messages from server to client 254 The following messages may be sent by uqchessserver.3407 255
• started colour 256
– The server will send this response to a “start” message, when the game can be started. 257
– The argument colour confirms the colour that the client will be playing. (This will match the colour 258
• ok
the user requested, but is present for those situations where the user requested either colour against 259 a human opponent.) 260
261 – The server will send this response to a “move” message if the move is a valid move on the game 262 board. 263
• error reason 264 – The server will send this response to the client when it can not accept or process a message sent by 265 the client or some other error has happened. The required argument (reason ) will be a single word 266 and must be one of:3407 267 – engine 268 Chess engine failure. If the chess engine fails (terminates for some reason) then the message 269 “error engine” must be sent to all clients before the server exits. See the Specification - 270 uqchessserver section for more details. 271
6Castling can be represented by showing the movement of the king, e.g. e1g1. Pawn promotion can be indicated by appending a letter indicating which piece the pawn is promoted to, e.g. h7h8q.
– command 272 Invalid command – the server does not understand this command (which could include invalid 273 formatting, e.g. unknown command, additional characters, etc.). A properly implemented client 274 will never send invalid commands but a server must handle them gracefully if received. 275
– game 276 Game not in progress – this command can not be accepted because no game is currently in 277 progress.3407 278
– turn 279 Not your turn – this command can not be accepted because it is not currently the client’s turn 280 to play (but a game currently is in progress). 281
– move 282 Invalid move – the attempted move is not valid for this game 283
startboard 284 lines of text 285 endboard 286
– This multiline message returns the current state of the game board. The lines between the startboard 287 line and the endboard line will contain an ASCII art representation of the board. These lines may 288 contain spaces and blank lines.3407 289
moves move-details [...] 290
– This message will be sent in response to a valid “hint” message and will contain one or more moves 291 (each 4 or 5 character alphanumeric strings), space separated, each in chess long algebraic notation 292 (e.g. e2e4). Only one move will be sent in response to a “hint best” message. One or more moves 293 will be sent in response to a “hint all” message.3407 294
• moved move-made 295 – This message will tell the client the move made by their opponent (human or computer). The 296 move-made argument will be a 4 or 5 character alphanumeric string in chess long algebraic notation 297 (e.g. e7e5).3407 If playing a human, the move-made string sent back to a client will be exactly the string 298 provided by their opponent. 299
• check 300 – This message will be sent by the server when it detects that the most recent move has resulted in a 301 king being in a “check” position. This message will be sent in response to a move message from the 302 client to the server in place of after an ok message if the client’s move has resulted in the opponent’s 303 king being in check (but not checkmate). It will immediately follow a moved message from the server 304 to the client if the opponent’s move has resulted in the client’s king being in check.3407 305
• gameover how [winner ] 306 – This message tells the client that the current game is now over. The required argument how is one 307 of “checkmate” or “stalemate” or “resignation” (without the quotes). If the how argument is 308 “checkmate” or “resignation” then the winner argument must also be supplied and will be either 309 “white” or “black” (without the quotes) – indicating which colour won the game. This message will 310 be sent in place of after an “ok” message if the client’s move has resulted in checkmate or stalemate. 311 This message may arrive to a client at any time if their human opponent resigns (the “computer” 312 never resigns). If two clients are playing (i.e. two humans) then the same message is sent to both 313 clients. 314
Specification - uqchessserver 315
uqchessserver is a networked, multithreaded server that manages chess games for connected clients. It will 316 start and communicate with a single chess engine process (Stockfish) and use that engine to support all of the 317 games that are in progress. Games can be between one client and another client or between a client and the 318 “computer” (i.e. the chess engine).3407 319
All communication between clients and the server is via a ASCII text line-based protocol over TCP. See the 320
Communication Protocol section on 6 for details.3407
Command Line Arguments 322
Your uqchessserver program is to accept command line arguments as follows: 323 ./uqchessserver [--max num] [--port portnum] 324
The square brackets ([]) indicate optional arguments. Italics indicate a placeholder for a user-supplied 325 argument. None, either or both of the options can be specified (at most once each). Option arguments can be 326 in either order if both are specified. 327
Some examples of how the program might be run include the following7: 328 ./uqchessserver 329
./uqchessserver --port 2310 330
./uqchessserver --max 5 331
./uqchessserver --port 1234 --max 10 332 The meaning of the arguments is as follows:3407 333
--max – if specified, this option argument is followed by a non-negative integer less than or equal to 800 334 specifying the maximum number of simultaneous client connections to be permitted. If this is zero or this 335 argument pair is absent, then there is no limit to how many clients may connect (other than operating 336 system limits which we will not test). 337
--port – if specified, this option argument is followed by a string which specifies which localhost port 338 the server is to listen on. This can be either numerical or the name of a service. If this is zero or this 339 argument pair is absent, then uqchessserver is to use an ephemeral port.3407 340
Important: Even if you do not implement the connection limiting functionality, your program must cor- 341 rectly handle command lines which include this argument and value (after which it can ignore any provided 342 values – you will simply not receive any marks for that feature). 343
Prior to doing anything else, your program must check the command line arguments for validity. If the 344 program receives an invalid command line then it must print the (single line) message:3407 345
./uqchessserver [--max num] [--port portnum] 346
to standard error (with a following newline), and exit with an exit status of 15. 347
Invalid command lines include (but may not be limited to) any of the following: 348
The --max option argument is given but it is not followed by a non-negative integer less than or equal to 349 800. A leading + sign is permitted (optional). Numbers with leading zeroes will not be tested – i.e. may 350 be accepted or rejected. 351
Any of the option arguments is listed more than once. 352
The --port option argument is given but it is not followed by a non-empty string argument 353
An unexpected argument is present.3407 354
Any argument is the empty string. 355
Checking whether the portnum argument is a valid port or service name is not part of the usage checking 356 (other than checking that the value is not empty). The validity of this value is checked after command line 357 validity as described below. 358
Port Checking 359 If uqchessserver is unable to listen on the given port (or service name) of localhost, it shall output the 360
following message (terminated by a newline) to stderr and exit with status 6: 361
uqchessserver: unable to listen on port "N" 362
where N should be replaced by the argument given on the command line. (This may be a non-numerical string.) 363 The double quotes must be present. Being “unable to listen on a given port” includes the cases where the socket 364 can’t be created, the port string is invalid, the socket can’t be bound to the address, and the socket can’t be 365 listened on. Note that we will not test the situation where uqchessserver is unable to listen on an ephemeral 366
port.3407
Starting the Chess Engine 368
If the checks above succeed, then uqchessserver is to start the chess engine (Stockfish). A single chess engine 369 is used by uqchessserver no matter how many clients are being serviced. Stockfish (which is run using the 370 stockfish executable on moss) is a Universal Chess Interface (UCI) compliant chess engine8 which means that 371 it listens for text commands on its stdin and provides text responses on its stdout. Details of UCI can be 372 found at https://backscattering.de/chess/uci/, however, the necessary information for this assignment 373 can be found in this specification in the UCI – Universal Chess Interface section below.3407 374
To start the chess engine, your uqchessserver program must: 375
create two pipes – one will be for uqchessserver to write to the Stockfish process’s stdin and one will 376 be for the server to read from the Stockfish process’s stdout; 377
fork to create a child process;3407 378
redirect/close file descriptors as appropriate; 379
in the child process, run the program stockfish – which is to be found in the user’s path (no command 380 line arguments are to be provided); 381
send the “isready” message to stockfish and wait for the “readyok” response (another line will be sent 382 before this also – this can be ignored); and 383
after the “readyok” response has been received, send the “uci” message to stockfish and wait for the 384 “uciok” response (other lines will be sent before this also – these can be ignored). 385
Note that stockfish’s stderr should just be inherited from that of uqchessserver. 386
If uqchessserver is unable to start the Stockfish process, e.g. SIGPIPE or EPIPE or other error is detected 387 when writing to stockfish or EOF is detected when reading from stockfish then uqchessserver must print 388 the following message to stderr (with a terminating newline):3407 389
uqchessserver: unable to start communication with chess engine 390
and exit with status 12. No client connections are ever to be accepted. 391 Your server can assume that the chess engine is well behaved, i.e., that if you are expecting a response in 392 accordance with the UCI protocol then that response will be forthcoming, i.e. reads from stockfish looking 393 for that response won’t block forever.3407 394 If, after starting the chess engine (the first readyok and uciok responses are received) your uqchessserver 395 ever detects that the Stockfish process has exited (e.g. by detecting an error when writing to stockfish, or 396 detecting EOF when reading the pipe from stockfish), then the server must reap the child process, send 397 an error message to all connected clients (if any) (see the Communication Protocol) section), and print the 398 following message to stderr (with a terminating newline): 399
uqchessserver: chess engine terminated 400
and then exit with exit status 20. 401 This is the only circumstance under which the server is expected to exit after it has completed the start-up 402 checks (on the command line arguments and whether it can listen and whether it can start the chess engine). 403 It is not necessary for the server to free all memory when it exits (under this or any circumstance). 404
Runtime Behaviour 405
Once the port is opened for listening and the chess engine started, uqchessserver shall print to stderr the 406 port number that it is listening on (not the service name) followed by a single newline character and then flush 407 the output. In the case of ephemeral ports, the actual port number obtained shall be printed, not 408 zero.3407 409
Upon receiving an incoming client connection on the port, uqchessserver shall spawn a new thread to 410 handle that client (see below for client thread handling).3407 411 If the --max argument is specified on the command line (along with a value argument) and connection 412 limiting behaviour is implemented, then uqchessserver must keep track of how many active client connections 413 exist, and must not let that number exceed the num parameter. See below for more details on how this limit is 414 to be implemented.3407 415 The uqchessserver program should not terminate under normal circumstances (unless the chess engine 416 terminates – see above), nor should it block or otherwise attempt to handle SIGINT. 417 Note that your uqchessserver must be able to deal with any clients, not just the client programs specified 418 for the assignment. Testing with netcat is highly recommended.3407 419
8Stockfish has some additional functionality beyond that required in UCI. We take advantage of that in this assignment, e.g. the presence of the “d” command.
© 2024 The University of Queensland 10 Version 1.2
Client handling threads 420
A single client handler thread is spawned for each incoming connection. This client thread must then wait for a 421 message from the client, and act on it – which in many cases will involve sending a message to the chess engine, 422 awaiting a response and then sending a response to the client. The exact format of client requests is described 423 in the Communication Protocol section on page 6. 424
Due to the simultaneous nature of multiple client connections, your uqchessserver will need to ensure 425 mutual exclusion around accesses to any shared data structure(s) and resources (e.g. the chess engine) so as to 426 ensure that data/messages do not get corrupted.3407 427
Once a client disconnects or there is a communication error on the socket (e.g. a read() or equivalent 428 from the client returns EOF, or a write() or equivalent fails) then the client handler thread is to close the 429 connection, clean up as appropriate (e.g. send a “gameover” message to a human opponent – a disconnection 430 is to be treated as a resignation) and terminate. Other client threads and the uqchessserver program itself 431 must continue uninterrupted. uqchessserver must not exit in response to a SIGPIPE.3407 432
Managing Chess Games 433
Your client thread must handle messages from the client as described in the Communication Protocol section. 434 Additional information on server behaviour in response to each message type is provided below. Note that each 435 client message will result in the specified behaviour, usually resulting in a response to the client. Once the 436 specified behaviour is undertaken (and a response sent to the client if appropriate), then the client thread must 437 await the next message from the client. Note that if messages must be sent to the chess engine, they will need 438 to be preceded by other messages that specify the game state - see the UCI – Universal Chess Interface section 439 below (page 14). 440
start against colour 441 When the server receives a “start” message from a client, it must do the following: 442
– Conclude any game in progress as if a resignation message had been received. 443
– If the client wishes to play against a computer opponent, start the game and send back an appropriate 444 “started” response. If the computer is playing white, then the server must also generate a move 445 (see below) and send back a “moved” response. 446
– If the client wishes to play against a human opponent, then check to see if another client is awaiting 447 a human opponent and their colour choices are compatible (i.e. white with black or a specified colour 448 preference with no colour preference or both have no colour preference). If neither has a colour 449 preference then the first client waiting will be assigned the white pieces (i.e. the client that sent the 450 “start” message last will be assigned black). If multiple clients are waiting with a particular colour 451 preference then the one which was the first to connect to the server must be chosen. Appropriate 452 “started” messages must be sent to both clients9. If there is no colour-compatible human opponent 453 waiting to play, then this will be noted (so that if a colour-compatible client does connect then a 454 game can be started – by the other client’s thread). The client thread does not send a response to 455 the client in this case, but will wait for further messages from the client. 456
board 457 When the server receives a “board” message from the client, it must do the following: 458
– If this client has never started a game (no “start” request has been received) or a “start” request 459 to play a human has been received and no colour compatible opponent is available, then the client 460 must send a game-not-in-progress “error” response. 461
– If a game is in progress (even if no moves have been made yet) then the server must issue a “d” 462 UCI request to the engine and return the current game board to the client between startboard and 463 endboard messages (see details of the “d” message in the UCI – Universal Chess Interface section). 464
– If a game is not in progress but one has been played (i.e. it is over) and no new “start” request has 465 been received, then the server must must issue a “d” UCI request to the engine and return the last 466 state of the game board (i.e. as it was when the last game finished) to the client between startboard 467 and endboard messages.3407 468
hint [best|all] 469 When the server receives a “hint” message from the client, it must do the following: 470 – If a game is not in progress or it is not the client’s turn then issue an appropriate “error” response. 471
9Note that this one client thread will be sending messages to two different connected clients.
© 2024 The University of Queensland 11 Version 1.2
– If it is a “hint best” message, then the client thread must issue the UCI command “go movetime 472 500 depth 15” to the chess engine and await a “bestmove” line in the response. (This request 473 will limit the move search to 500 milliseconds or a depth of 15 moves, whichever happens sooner.). 474 The client thread must then send a moves response to the client with the move extracted from the 475 “bestmove” response from the chess engine. Other lines of text emitted by the chess engine (info 476 lines) are to be ignored. 3407 477
– If it is a “hint all” message, then the client thread must issue the UCI command “go perft 1” to 478 the chess engine and collect the moves in the response (over multiple lines). The client thread must 479 then send a “moves” response to the client with the moves extracted from the response. Other lines 480 of text emitted by the chess engine (“info” lines, blank lines and the count of “Nodes searched”) are 481 to be ignored. 3407 482
• move move-to-make 483 When the server receives a “move” message from the client, it must do the following: 484
– If a game is not in progress or it is not the client’s turn then issue an appropriate “error” response. 485
– If it is the client’s turn, then the client thread must issue a “position” UCI command with the 486 current board state (see below) and this specified move. Following this it must issue a “d” command 487 to get the board state to determine the outcome of the move. 488
– If the board state has not changed (the “Fen” line in the response is the same as before the 489 attempted move) then the move is not valid and the client thread must send the appropriate 490 “error” response to the client.3407 491
– If the board state has changed (the move was accepted) then an “ok” response must be sent to 492 the client. If the opponent is human then the “moved” message must be sent to the client of the 493 opponent. 494
– If the move was accepted, the client thread must also send the “go perft 1” command to 495 the chess engine (to determine the number of valid moves for the opponent – from the “Nodes 496 searched” line in the response) and use the output of this and the output of the “d” command 497 to determine the consequences of the move as outlined next. 498
– If the move was accepted and the “Checkers” line in the “d” response is not empty then the 499 player is in check or checkmate. If there are zero possible moves for the opponent then this is 500 checkmate and the game is over. The client thread must send a “gameover” message to the 501 client (and the opponent’s client if the opponent is human). If there are possible moves then the 502 move has resulted in a check position and the client thread must send a “check” message to the 503 client (and the opponent’s client if the opponent is human). 3407 504
– If the move was accepted and the “Checkers” line in the “d” response was empty and there 505 are no valid moves for the opponent then this is a stalemate (the game is over, but no player 506 wins). The client thread must send an appropriate “gameover” message to the client (and the 507 opponent’s client if the opponent is human). 508
– If the opponent is the “computer” and the game was not finished by the provided move, then the 509 server must do the following: 510
– Generate a move that the computer will make in response. It does this is the same way that 511 hints are generated (see above), by sending the UCI command “go movetime 500 depth 15” 512 to the chess engine and waiting for the “bestmove” line (the last line) in the response. The best 513 move is then sent to the client with a “moved” message. 514
– Check whether the computer’s move resulted in check, checkmate or stalemate – using the same 515 approach described above. If so, this will result in the server sending a “check” or “gameover” 516 message to the client following the “moved” message. 3407 517
• resign
When the server receives a “resign” message from the client, it must do the following: 519
– If a game is not in progress then issue an appropriate “error” response.3407 520
– If a game is in progress, then this indicates that this client has resigned (i.e. lost the game). The 521 client thread must send an appropriate “gameover” message back to the client. If the opponent is 522 human, then an appropriate “gameover” message must be sent the opponent’s client also. 523
Game State
For each game, uqchessserver must maintain some game state:
whether the game is in progress or finished; 526
who is playing white (i.e. which client, or the computer); 527
who is playing black (i.e. which client, or the computer – noting that at least one of the colours must be 528 played by a client); and3407 529
the current or last game board state – maintained as a FEN string (provided by the chess engine – see 530 below). This string includes information about whose turn it is to play next. 531
Note that recording which client is playing which colour does not involve recording which thread is managing 532 that client – more likely it will involve recording the file descriptor or FILE* handle(s) associated with the client 533 so that messages can be sent to the client.3407 534
Note that the state of completed games must be maintained until the client(s) who played the game has/have 535 started another game or disconnected from the server. This is so that an appropriate response can be given to 536 a “board” message, i.e. what the board looked like at the end of the game. 537
Client connection limiting (CSSE7231 students only) 538
If the --max num feature is implemented and a non-zero command line argument is provided, then 539 uqchessserver must not permit more than that number of simultaneous client connections to the server. If a 540 client beyond that limit attempts to connect, uqchessserver shall block, indefinitely if required, until another 541 client leaves and this new client’s connection request can be accept()ed. Clients in this waiting state are not to 542 be counted in statistics reporting – they are only counted once they have properly connected. Existing clients 543 must continue to be served. 3407 544
Statistics reporting (CSSE7231 students only) 545 Upon receiving SIGHUP, uqchessserver is to output (and flush) to stderr statistics reflecting the program’s 546
operation to-date, specifically 547
• Total number of clients connected (at this instant) 548 • The total number of clients that have connected and disconnected since program start 549 • Number of games in progress (at this instant) 550 • The total number of games that have been started and completed up to now3407 551
The required statistics format is illustrated below. Each of the four lines is terminated by a single newline. 552 You can assume that all numbers will fit in a 32-bit unsigned integer, i.e. you do not have to consider numbers 553 larger than 4,294,967,295.3407 554
Example 1: uqchessserver SIGHUP stderr output sample
1 Number of connected clients: 4
2 Number of completed clients: 20
3 Games in progress: 3
4 Games completed: 35
Note that to accurately gather these statistics and avoid race conditions, you will need some sort of mutual 555 exclusion protecting the variables holding these statistics.3407 556 Global variables are NOT to be used to implement signal handling (or for any other purposes in this 557 assignment). See the Hints section below for how you can implement signal handling. 558
Other Requirements 559
Other than the listening port number, SIGHUP-initiated statistics output, and error messages, uqchessserver 560 is not to emit any output to stdout or stderr. 561 Your server must not leak memory. Your server is never expected to exit after startup (unless the chess 562 engine terminates for some reason) so your program never has to free all memory but it’s memory consumption 563 should not grow significantly over time. It is expected that the memory consumption of your program will be the 564 same after a client disconnects as it was just before the client connected (assuming no other clients connected 565 and remained connected in that time).3407 566 Your server must not busy wait. If a thread has nothing to do then it must be blocking, e.g. in accept() 567 or a
We will not test for unexpected system call or library failures in an otherwise correctly-implemented program 569 (e.g. if fork(), malloc(), pipe(), pthread_create(), etc. fails due to insufficient available resources). Your 570 program can behave however it likes in these cases, including crashing. 571
UCI – Universal Chess Interface 572
Full details about how Stockfish implements the Universal Chess Interface (UCI) can be found at 573 https://github.com/official-stockfish/Stockfish/wiki/UCI-&-Commands. Descriptions of the commands 574 you need to send to Stockfish, and the expected responses, are found below. In the examples below, green text 575 indicates commands sent to Stockfish via its stdin. Black text indicates response text from Stockfish via its 576 stdout. Commands and responses are terminated by a single newline.3407 577
• isready 578 This command must be sent prior to any other communication with the chess engine to check whether the 579 engine is ready or not. No other commands should be sent until the engine responds with a “readyok” 580
Example 2: Example interaction with Stockfish showing the isready command and response
1 Stockfish dev-20240917-60351b9d by the Stockfish developers (see AUTHORS file)
2 isready
3 readyok
• uci 581 This command tells the engine to use UCI (Universal Chess Interface). The engine will return a number of 582 id and option lines identifying the engine and which options it supports, concluded by a uciok message. 583 None of the commands below should be sent until after this uciok response is received. 584
Example 3: Example interaction with Stockfish showing the uci command and response
1 uci
2 id name Stockfish dev-20240917-60351b9d
3 id author the Stockfish developers (see AUTHORS file)
4
5 option name Debug Log File type string default <empty>
6 option name NumaPolicy type string default auto
7 option name Threads type spin default 1 min
8 option name Hash type spin default 16 min 1
9 option name Clear Hash type button
1 max 1024
max 33554432
10 option name Ponder type check default false
11 option name MultiPV type spin default 1 min
12 option name Skill Level type spin default 20 min 0 max 20
13 option name Move Overhead type spin default 10 min 0 max 5000
14 option name nodestime type spin default 0 min 0 max 10000
15 option name UCI_Chess960 type check default false
16 option name UCI_LimitStrength type check default false
17 option name UCI_Elo type spin default 1320 min 1320 max 3190
18 option name UCI_ShowWDL type check default false
19 option name SyzygyPath type string default <empty>
20 option name SyzygyProbeDepth type spin default 1 min 1 max 100
21 option name Syzygy50MoveRule type check default true
22 option name SyzygyProbeLimit type spin default 7 min 0 max 7
23 option name EvalFile type string default nn-1111cefa1111.nnue
24 option name EvalFileSmall type string default nn-37f18f62d772.nnue
25
• ucinewgame 585 This command tells the engine that the interactions that follow are associated with a different game. You 586 can think of this as a context switch – the engine will now be doing calculations for a different game – not 587 necessarily from the starting position. This command must always be followed by an isready command 58
uciok
and no further commands should be sent until a readyok response is received. (The engine will not send a 589 response to the ucinewgame command.) A ucinewgame command and subsequent isready command must 590 only be sent just before it is necessary to send some other UCI command – usually a position command 591 (followed by a go or d command). A ucinewgame command (and subsequent isready command) can be 592 sent prior to every position command if desired – even if the subsequent position command is for the 593 same game. Alternatively, you can just send them when a context (i.e. game) switch is necessary. 594
Example 4: Example interaction with Stockfish showing the ucinewgame command
1 ucinewgame
2 isready
3 readyok
• position startpos 595 position startpos moves movestring 596 position fen fenstring 597 position fen fenstring moves movestring 598 The position command specifies a given game state and optionally a move to make in that game state. 599 The game state can be startpos which indicates a chess board at the start of the game when no moves 600 have been made (white to play first). Alternatively, the game state can be specified as fen fenstring 601 which specifies the game state using a string in Forsyth Edwards Notation (FEN) – with fenstring made 602 up of six space-separated fields. If a move is specified (with the moves keyword), the following movestring 603 is a 4 or 5 character string in long algebraic notation, e.g. e2e4. The engine will not send a response to 604 the position command. Note that the second of six fields in the FEN string (either the letter ‘w’ or ‘b’) 605 indicates the colour of the next player to move. A position command must be immediately followed by 606 a go or depth command – i.e. don’t send a position command if you don’t have something else to ask 607 the server. 608
Example 5: Examples of the position command
1 position startpos
2 position startpos moves e2e4
3 position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
4 position fen rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1 moves e7e5
• go perft 1 609 go movetime time depth depth 610 The go command specifies that the engine should evaluate the current position (as set with the position 611 command) to calculate a move or possible moves. The first variant, “go perft 1” will list all of the possible 612 moves that can be made from the current position and how many different moves are possible (listed against 613 the heading “Nodes searched:”). The second variant (“go movetime time depth depth ”) searches for 614 the best possible move from the current position. The time value is the maximum search time (in 615 milliseconds). The depth value is the maximum depth of the search (how many moves to look ahead). 616 The line of interest in the output is the “bestmove” line. The “ponder” element (if present) is the move 617 that the engine thinks is most likely in response – this value is ignored.3407 A go command must always be 618 preceded by a position command (possibly with an intervening d command between the position and 619 go commands). 620
Example 6: Examples of the go command. The 20 possible moves are listed on lines 7 to 26. The best move to make is listed on line 50 51.
1 position startpos
2 go perft 1
3 info string Available processors: 0-11
4 info string Using 1 thread
info string NNUE evaluation using nn-1111cefa1111.nnue (133MiB, (22528, 3072, 15, 32,
1))
info string NNUE evaluation using nn-37f18f62d772.nnue (6MiB, (22528, 128, 15, 32, 1))
a2a3: 1
b2b3: 1
c2c3: 1
d2d3: 1
e2e3: 1
f2f3: 1
g2g3: 1
h2h3: 1
a2a4: 1
10 11 12 13 14 15
16 b2b4: 1
17 c2c4: 1
18 d2d4: 1
19 e2e4: 1
20 f2f4: 1
21 g2g4: 1
22 h2h4: 1
23 b1a3: 1
24 b1c3: 1
25 g1f3: 1
26 g1h3: 1
27
28 Nodes searched: 20 29
30 position startpos
31 go movetime 500 depth 15
32 info string Available processors: 0-11
33 info string Using 1 thread
34 info string NNUE evaluation using nn-1111cefa1111.nnue (133MiB, (22528, 3072, 15, 32, 1))
35 info string NNUE evaluation using nn-37f18f62d772.nnue (6MiB, (22528, 128, 15, 32, 1))
36 info depth 1 seldepth 3 multipv 1 score cp 33 nodes 23 nps 23000 hashfull 0 tbhits 0
time 1 pv e2e4
37 info depth 2 seldepth 8 multipv 1 score cp 33 nodes 62 nps 62000 hashfull 0 tbhits 0
time 1 pv e2e4 e7e5 g1f3 d7d5 e4d5 e5e4
38 info depth 3 seldepth 10 multipv 1 score cp 33 nodes 95 nps 47500 hashfull 0 tbhits 0
time 2 pv e2e4 e7e5 g1f3 d7d5 e4d5 e5e4 f3e5 d8d5
39 info depth 4 seldepth 12 multipv 1 score cp 33 nodes 138 nps 69000 hashfull 0 tbhits 0
time 2 pv e2e4 e7e5 g1f3 d7d5 e4d5 e5e4 f3e5 d8d5 e5c4 f8e7
40 info depth 5 seldepth 13 multipv 1 score cp 33 nodes 182 nps 91000 hashfull 0 tbhits 0
time 2 pv e2e4 e7e5 g1f3 d7d5 e4d5 e5e4 f3e5 d8d5 e5c4 f8e7 b1c3 d5c6
41 info
42 info
43 info
44 info
45 info
46 info
depth 6 seldepth 13 multipv 1 score cp 33 nodes 236 nps 118000 hashfull 0 tbhits 0
time 2 pv e2e4 e7e5 g1f3 d7d5 e4d5 e5e4 f3e5 d8d5 e5c4 f8e7 b1c3 d5c6
depth 7 seldepth 13 multipv 1 score cp 33 nodes 292 nps 146000 hashfull 0 tbhits 0
time 2 pv e2e4 e7e5 g1f3 d7d5 e4d5 e5e4 f3e5 d8d5 e5c4 f8e7 b1c3 d5c6
depth 8 seldepth 13 multipv 1 score cp 33 nodes 374 nps 187000 hashfull 0 tbhits 0
time 2 pv e2e4 e7e5 g1f3 d7d5 e4d5 e5e4 f3e5 d8d5 e5c4 f8e7 b1c3 d5c6
depth 9 seldepth 13 multipv 1 score cp 33 nodes 608 nps 304000 hashfull 0 tbhits 0
time 2 pv e2e4 e7e5 g1f3 d7d5 e4d5 e5e4 f3e5 d8d5 e5c4 f8e7 b1c3 d5c6
depth 10 seldepth 17 multipv 1 score cp 32 nodes 2040 nps 408000 hashfull 0 tbhits
0 time 5 pv e2e4 e7e5 g1f3 g8f6 d2d4 d7d5 e4d5 e5d4 f1b5 c7c6 d5c6 b7c6 b5e2
depth 11 seldepth 17 multipv 1 score cp 31 nodes 2846 nps 569200 hashfull 0 tbhits
0 time 5 pv e2e4 e7e5 g1f3 g8f6 d2d4 f6e4 f3e5 d7d5 f1d3 f8d6 e1g1 e8g8 b1c3 e4c3
b2c3 d8h4
47 info depth 12 seldepth 17 multipv 1 score cp 30 nodes 3896 nps 556571 hashfull 0 tbhits
0 time 7 pv e2e4 e7e5 g1f3 b8c6 f1b5 g8f6 d2d4 f6e4 e1g1
48 info depth 13 seldepth 21 multipv 1 score cp 35 nodes 12002 nps 631684 hashfull 4
tbhits 0 time 19 pv e2e4 e7e5 g1f3 g8f6 d2d4 f6e4 f3e5 d7d5 d1f3 c8e6 f1d3 f8d6
d3e4 d5e4 f3e4
info depth 14 seldepth 18 multipv 1 score cp 33 nodes 15415 nps 670217 hashfull 5
tbhits 0 time 23 pv e2e4 e7e5 g1f3 g8f6 d2d4 f6e4 f3e5 d7d5 f1d3 b8c6 e1g1 f8d6
f2f4 e8g8 b1c3
info depth 15 seldepth 21 multipv 1 score cp 35 nodes 28782 nps 702000 hashfull 9
tbhits 0 time 41 pv e2e4 e7e5 g1f3 b8c6 d2d4 e5d4 f3d4 g8f6 d4c6 b7c6 f1d3 d7d5
e4e5 f6d7 e1g1 d7c5
bestmove e2e4 ponder e7e5
50
51
•d 621 The d command asks the engine to display details of the current game position and state. This includes an 622 ASCII art representation of the game board (white pieces are shown with upper case letters, black pieces 623 are shown with lower case letters10). The ASCII art lines, including the blank line immediately before the 624 art and the blank line immediately after the art, are the lines to be sent back to clients when requested 625 (with “startboard” and “endboard” delimiters). The FEN string (in the line with the “Fen:” prefix) 626 will be line saved as part of the game state – this contains full details about the game. The “Checkers:” 627 line lists the positions of all the pieces that have the current player’s king in check.3407 A d command must 628
always be immediately preceded by a position command.
Example 7: Examples of the d command. Lines 3 to 22 (inclusive) or lines 28 to 47 (inclusive) would be
those sent back in response to a “board” message.
1 position startpos 2d
3
4 +---+---+---+---+---+---+---+---+
5 |r|n|b|q|k|b|n|r|8
6 +---+---+---+---+---+---+---+---+
7 |p|p|p|p|p|p|p|p|7
8 +---+---+---+---+---+---+---+---+
9 |||||||||6
629
10 +---+---+---+---+---+---+---+---+
11 |||||||||5
12 +---+---+---+---+---+---+---+---+
13 |||||||||4
14 +---+---+---+---+---+---+---+---+
15 |||||||||3
16 +---+---+---+---+---+---+---+---+
17 |P|P|P|P|P|P|P|P|2
18 +---+---+---+---+---+---+---+---+
19 |R|N|B|Q|K|B|N|R|1
20 +---+---+---+---+---+---+---+---+
21 abcdefgh
22
23 Fen: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
24 Key: 8F8F01D4562F59FB
25 Checkers:
26 position fen 8/k7/8/2QK4/8/8/8/8 b - - 4 20
27 d
|||Q|K|||||5 +---+---+---+---+---+---+---+---+ |||||||||4 +---+---+---+---+---+---+---+---+ |||||||||3
+---+---+---+---+---+---+---+---+ |||||||||2 +---+---+---+---+---+---+---+---+ |||||||||1 +---+---+---+---+---+---+---+---+
abcdefgh
41 42 43 44 45 46 47
48 Fen: 8/k7/8/2QK4/8/8/8/8 b - - 4 20
49 Key: B7AE661E3C37B0A7
50 Checkers: c5
Provided Libraries 630 libcsse2310a4 631
A split_by_char() function is available to break a string up into multiple parts, e.g. based on spaces. Several 632 functions that operate on Stockfish’s output are also available to simplify the parsing of this output. The 633 functions available in this library are:3407 634
char** split_by_char(char* str, char split, unsigned int maxFields); StockfishGameState* read_stockfish_d_output(FILE* stream);
void free_stockfish_game_state(StockfishGameState* state); ChessMoves* read_stockfish_go_perft_1_output(FILE* stream); ChessMoves* read_stockfish_bestmove_output(FILE* stream);
void free_chess_moves(ChessMoves* moves);
char next_player_from_fen_string(const char* fen);
These functions and the associated types are declared in /local/courses/csse2310/include/csse2310a4.h 635 on moss and their behaviour and required compiler flags are described in man pages on moss.3407 636
Testing 637 You are responsible for ensuring that your program operates according to the specification. You are encouraged 638
to test your program on a variety of scenarios. A variety of programs will be provided to help you in testing: 639
Two demonstration programs (called demo-uqchessserver and demo-uqchessclient) that implement 640 the correct behaviour will be made available on moss. You can test your client with the demo server 641 and vice-versa. You can also use demo-uqchessserver and demo-uqchessclient to check the expected 642 behaviour of the programs if some part of this specification is unclear.3407 643
Remember that you can use netcat (nc) to do testing also – you can use netcat as a client to communicate 644 with your server, or as a server that your client can communicate with. This will allow you to simulate 645 and capture requests and responses between the server and client.3407 646
A test script will be provided on moss that will test your programs against a subset of the functionality 647 requirements – approximately 50% of the available functionality marks. The script will be made available 648 about 7 to 10 days before the assignment deadline and can be used to give you some confidence that you’re 649 on the right track. The “public tests” in this test script will not test all functionality and you should be 650 sure to conduct your own tests based on this specification. The “public tests” will be used in marking, 651
along with a set of “private tests” that you will not see.3407
• The Gradescope submission site will also be made available about 7 to 10 days prior to the assignment 653 deadline. Gradescope will run the test suite immediately after you submit. When this is complete11 you 654 will be able to see the results of the “public tests”. You should check these test results to make sure 655 your program is working as expected. Behaviour differences between moss and Gradescope may be due to 656 memory initialisation assumptions in your code, so you should allow enough time to check (and possibly 657 fix) any issues after submission.3407 658
Style 659
Your program must follow version 3 of the CSSE2310/CSSE7231 C programming style guide available on the 660 course Blackboard site. Your submission must also comply with the Documentation required for the use of AI 661 tools if applicable. 3407 662
Hints 663
The multithreaded network server example from the lectures can form the basis of uqchessserver. 664
Review the lectures and sample code related to network clients, threads and synchronisation (semaphores), 665 and multi-threaded network servers. This assignment builds on all of these concepts. You should also 666 review the content on pipes, redirection and forking if this is not fresh in your memory. 667
Use the provided library functions (see above).3407 668
Remember to fflush() output that you printf() or fprintf() or otherwise output via FILE* streams. 669 Output to network sockets is not newline buffered. (Flushing is not necessary when using write() to 670 output directly to a file descriptor.)3407 671
You will need to use appropriate mutual exclusion (e.g. implemented with semaphores) in your server 672 to avoid race conditions when accessing common data structures and shared resources (e.g. the chess 673 engine). 674
(Read this in conjunction with the next hint.) Your server will probably need to maintain several types 675 of data structures. For example, each client thread might have an associated Client struct that records 676 details of how to communicate with the client, details of the game in progress (which might be a pointer 677 to a Game struct possibly shared between two clients, which points back to the client(s) involved so that 678 one client thread can send messages to another client). The server will also have to maintain some array 679 or list data structures, e.g. a list of all clients and a list of clients who are awaiting a human opponent 680 with a compatible colour choice. 681
The implementation of the server and associated data structures is much simpler when clients can only 682 play the computer and not other clients (humans) – all the game information is specific to one client 683 and not shared between multiple clients and a client thread will only ever communicate with one client. 684 You also don’t have to manage queues of clients waiting for a colour-compatible opponent. It is possible 685 to obtain 60% of the marks for the server with an implementation that only allows clients to play the 686 computer. 687
Consider a dedicated signal handling thread for SIGHUP. pthread_sigmask() can be used to mask signal 688 delivery to threads, and sigwait() can be used in a thread to block until a signal is received. You will 689 need to do some research and experimentation to get this working. Be sure to properly reference any code 690 samples or inspiration you use. 691
The isalnum() function can be used to check if a character is alphanumeric (i.e. is either a letter or a 692 number). 693
Possible Approach 694
Try implementing uqchessclient first. (The programs are independent so this is not a requirement, but 695 when you test it with demo-uqchessserver it may give you a better understanding of how uqchessserver 696 works.) 697
For uqchessserver, start with the multithreaded network server example from the lectures, gradually 698 adding functionality for supported message types and operations. 3407 699
Forbidden functions 700 You must not use any of the following C statements/directives/etc. If you do so, you will get zero (0) marks 701
for the assignment. 702
• goto 703 • #pragma3407 704 • gcc attributes (other than the possible use of __attribute__((unused)) as described in the style guide) 705
You must not use any of the following C functions. If you do so, you will get zero (0) marks for any test 706 case that calls the function. 707
longjmp() and equivalent functions 708
system() 709
mkfifo() or mkfifoat() 710
pthread_cancel() 711
signal(2), sigpending(2), sigqueue(3), sigtimedwait(2) 712
sleep(), usleep(), nanosleep() or any other function that involves a sleep, alarm or timeout. 713
Functions described in the man page as non standard, e.g. strcasestr(). Standard functions will 714 conform to a POSIX standard – often listed in the “CONFORMING TO” section of a man page. Note 715 that getopt_long() and getopt_long_only() are an exception to this – these functions are permitted 716 if desired. 717
The use of comments to control the behaviour of clang-format and/or clang-tidy (e.g., to disable style 718 checking) will result in zero marks for automatically marked style. 719