Dylan Leigh
Student Number: 3017239
Note: this file is raw HTML with no style information. It may be easier to view this in a thin window so the text does not stretch across the entire screen.
Design a system to allow a game to be run as a TCP/IP client/server system, with the server playing against the user who is operating the client. All game rules decisions must be made server side and steps should be taken to prevent the client cheating.
The first step was the design of the game rules. I created my own game, the rules are outlined in the readme.txt file, which also describes how to build the client and server. The name "NumLock" was chosen as the main strategy is to block the other player from getting high numbers.
The second was design of the protocol. It was decided that the protocol should be text-based so it was human-readable, portable and easily extensible. The details of the protocol can be found in the Protocol section below.
The implementation was done using Java to ensure portability. Java 1.5 (the most recent major version) was used.
The server was implemented first. Because it would not be taking any direct user input it was designed as a console program. Basic testing was performed on the server by connecting to the server using telnet and typing in responses (remember that the protocol was text).
The client was then implemented using a Java Swing GUI. There are three UI "panes" - one for connecting to the server, one for viewing high scores and selecting game difficulty and another for playing the actual game. These were chosen to fit in well with the protocol.
As mentioned above, some basic testing was done on the server using telnet. After the client was finished extensive testing was done on both by playing the game.
The client and server were also tested by attempting to connect using a different program or service (e.g. connecting to a web server using the NumLock client, or accessing the NumLock server using a web browser). If the other end does not appear to be using the NumLock protocol the server/client terminates the connection.
All communications are in ASCII text. Generally messages are terminated by a newline, although some messages span multiple lines (such as when sending high scores). These multiline messages have a unique ending line.
Server and client wait for the other side to transmit a complete message, and it responds with another complete message (thus communication is half-duplex at all times). An exception is at the end of the game, when the server sends two messages, however, there is a special flag in the first message to warn the client in this case. This considerably simplifies the implementation.
On any unexpected input the server/client should terminate the connection.
The basic process is as follows:
The details of the various messages follow:
Sent from server to client
"NumLock server- protocol version x.y" where x is the
major version number and y is the minor version number. This
version is 1.0. If a client encounters an unexpected version number
it should warn the user.
Sent from client to server
Multiline (2 lines)
The first line is "NumLock client- protocol version
x.y" where x and y are the major and minor
version numbers. The server typically should accept all connections
regardless of version.
The second line is "Player Name: xxx" where
xxx is the player name, which may include whitespace (i.e.
everything on the line after the semicolon and space is used as the
player name).
Sent from server to client
Multiline (variable)
The first line should read "High Scores follow:".
After this there is a number of sections for each difficulty level.
Each section begins with a blank line, followed by a line with the description of the difficulty level (in 1.0 these are "Easy", "Normal" and "Hard"). Afterwards there are a set of lines that contain the actual scores - each line consisting of the score itself, a tab character, and the player name (which may include whitespace - the player name is the remainder of the line as in the Client Hello message).
The final line should read "End High Scores. Transmit game
parameters"
For Example:
High Scores follow:
Easy
101 David
38 Dylan
30 bob
23 Emil
2 Synapse
Medium
109 Dylan
109 David
97 David
20 fghghj
10 fghghj
Hard
48 Synapse
24 Synapse
15 dylan
6 Synapse
3 Synapse
End High Scores. Transmit game parameters
Sent from client to server
"Newgame difficulty: x" where x is the
difficulty level - 0 is easy, 1 is normal, 2 is hard. In later
versions other options could be given such as who starts first or
the dimensions of the game board. Also, more difficulty levels could
be included.
Sent from server to client
Multiline (variable)
The first line should read "Initial Game State
follows:". Afterward there is a grid of numbers with each
column seperated by whitespace and each row seperated by a newline.
In version 1.0 this is limited to a 10 by 10 grid with a space
before each number.
The final line (or 2 lines) depend on whether the player or server move first. This is decided randomly by the server in version 1.0.
If the
player moves first the server also chooses which row the player can
move in, at random. The server sends the final line
"Player move row x" where x is the row
(between 0 and 9 as the grid is 10 by 10 in version 1.0).
If the server moves first the message is sent over two lines. The
first is "CPU move x,y" where x is the
column (x position) and y is the row (y position) of the
server's move (both limited to 0-9 in version 1.0). The second line
is ""Scores: Player x, CPU y" where
x is the player score and y is the server score.
Example 1: Player moves first
Initial Game State follows:
2 3 6 5 1 7 8 8 9 4
2 1 7 5 2 2 6 1 1 2
8 8 5 2 6 6 7 7 8 2
5 3 2 4 1 6 2 1 9 7
3 3 9 9 3 2 3 3 3 9
6 8 5 6 1 8 1 5 8 5
8 8 5 3 1 6 1 2 1 2
4 5 3 3 3 5 2 9 5 2
3 6 9 8 4 4 2 3 3 2
9 6 2 9 6 7 2 6 8 4
Player move row 0
Example 2: Server moves first
Initial Game State follows:
8 1 2 2 2 9 3 8 7 4
7 9 1 7 6 1 6 1 3 6
2 8 2 5 8 9 5 1 2 1
5 9 2 2 7 2 2 6 1 2
1 7 8 6 6 8 7 6 1 9
2 9 3 4 6 8 3 5 9 7
2 1 9 9 9 4 8 3 3 5
2 1 7 3 1 9 1 2 1 4
8 8 9 8 6 4 9 4 4 9
3 1 8 8 9 7 4 3 5 7
CPU move 0,0
Scores: Player 0, CPU 8
Sent from client to server
"Move x,y" where x is the column and
y is the row of the move the player has made. If the row
does not match with the previous server move the server should send
a message such as "Illegal Row Jumping" and close the connection.
Sent from server to client
Multiline (variable)
The first line should read ""Scores: Player x, CPU
y" where x is the player score and y
is the server score. Note that this is the same as one of the
possible final lines of the Game State message.
If the game is not over yet, the server sends it's move in the
form "CPU Move x,y" where x is the column
and y is the row of the server's move.
If the game is over (with or without the server move!) the server
sends a line reading "Endgame" or "Endgame -
HighScore" if the player achieved a high score.
Finally, the server sends a score line (""Scores: Player
x, CPU y" where x is the player score
and y is the server score) and this is the end of the
message.
The game itself has been popular with several other students and I am considering wrtiing a multithreaded server to allow serveral people to connect, or expanding the system so that people can play against each other.
Thanks to Mike (quex.org) for thinking up the name of the
game.
David Marshall and Steven Buck assisted me with testing
the client.
Copyright © Dylan Leigh 2004-2005.