CS Summer Camp, June, 2007
Problem Solving and Programming in Java
Foundational Computer Science Concepts
Fred Annexstein, Raj Bhatnagar, John Franco
Computer Science, University of Cincinnati

Project:

Write Java client classes which support playing checkers with another client remotely through a monitor (aka a server). Features your Java classes should have and the protocol it should implement are stated after the following description of the game of checkers. The description uses jpg and gif files that should be downloaded (shift-left click) and used to display game status.

The Game of Checkers:

The game of checkers is a two player game which is played by Player 1 and Player 2 on a checkboard that looks like this:

with pieces that look like this:

Player 1            Player 2
   
Normal King
   
Normal King

All pieces can only occupy dark squares and only one piece may occupy any one square. Pieces may be moved from one square to another by a player according to the following rules:

Player 1 can only move a Player 1 piece. Player 2 can only move a Player 2 piece. A Player 1 piece can be moved only when it is Player 1's turn. A Player 2 piece can be moved only when it is Player 2's turn.

Initially, 12 Normal Player 1 pieces are placed on dark squares at the bottom of the checkerboard, 12 Normal Player 2 pieces are placed in dark squares at the top of the checkerboard, and it is Player 1's turn. Except in the case of a piece being jumped, players alternate turns and may move one piece on their turn. In case a piece is jumped, the player whose piece was jumped forfeits his/her turn (that is, the jumping player gets another move). If a Player 1 piece reaches a dark square at the top of the checkerboard, it is replaced by a Player 1 King piece. If a Player 2 piece reaches a dark square at the bottom of the checkerboard it is replaced by a Player 2 King piece.

If some move results in no Player 2 pieces remaining on the checkerboard, then Player 1 is declared the winner. If some move results in no Player 1 pieces remaining on the checkerboard, then Player 2 is declared the winner. If some move results in one Player 1 King piece and one Player 2 King piece remaining on the checkerboard then a draw is declared (no one wins).

If a subsequent game is played, the player who lost the previous game takes the first turn, or if the previous game was a draw, the player who took the first turn in the previous game takes the first turn in the subsequent game.

Features and Operation of the Client:

The client should be able to

  1. register with the server, which means the client is available for play
  2. deregister, which means removal from the server player data base
  3. ask the server for a list of registered players
  4. select one of the registered players to have a game with (the selector is the challenger and becomes Player 2)
  5. display the current state of the checkerboard visually using the jpg and gif files above (NOTE: you must use the above files with no modifications)
  6. allow movement of pieces by mouse dragging
  7. show the movement of pieces as they are being moved
  8. display messages from the server
  9. show which player's turn it currently is
  10. change a piece from Normal to King when indicated by the server

Rules:

  1. deregistering is not allowed when a client is playing a game
  2. a player will be able to move only if the server believes it is that player's turn
  3. a piece is considered by the server as moving as long as it is being dragged
  4. a moving piece becomes fixed two seconds after the mouse button is released
  5. when moving, if the mouse button is released and re-pressed within two seconds of being released, the piece remains a moving piece

Protocols: The server is listening on port 8180 of helios.ececs.uc.edu. Both the server and client may initiate commands. The commands and who initiates them are as follows:

Client initiated:

"register" - register with the server
A client registers with the server by sending a String consisting of the string "register" followed by a handle of the client's choosing (there are no blanks in the handle). This is shown schematically as

    "register " + <handle of the registrant, no blanks> + "\n"
The server records the client's handle, machine, and port. The server sends a response to the client using the client's machine and port which are by now stored in the server's database. The response text is either
    <handle> + " registered on machine " + <client ip address> + " at " + <port> + "\n"
if the handle is not already in use, or
    <handle> + " is in use\n"
if the handle is unavailable. If the handle is unavailable, the client will not be registered until another "register" is sent with a valid handle.

"unregister" - remove the client from the list of registered clients
To remove a handle from the list of registered clients, the following string is sent to the server:

    "unregister\n"
The server determines the machine and port from this message and checks its database to make sure there is a match. If there is a match, the machine and port are removed from the database and the server responds to the client with
    <handle> + " unregistered from machine " + <client ip addresss> + " at " + <port> + "\n"
If the database does not contain a pair matching the machine and port of the incoming message, or the client is currently playing a game, the following is sent back to the client:
    "fail\n"
If the user is currently playing a game unregistering is not allowed. If a client wishes to unregister while playing a game, it must send a resign message (see below). Doing so will cause the client to lose the game.

"getclients" - request an update of the list of registered clients
A client requests the current list of registered clients by sending the String

    "getclients\n"
to the server. There is no need to send port or host information since the server saves that information when the client is registered. The server responds with multiple copies of the string
    <handle> + " " + <availability status> + "|"
and the sequence ends with "\n". The availablility status can either be "Yes" or "No". For example, "franco Yes|alterr No|cokane No\n" would indicate that there are three registered clients and client franco is available for play but clients alterr and cokane are not (probably because they are playing each other). It is expected that client software will use readLine() to read the entire message in one fell swoop and use StringTokenizers to break the line into sections delimited by '|' and to break each section into handle etc.

"getboard" - Retreive the current status of the gameboard according to the server
The server maintains a record of the current positions and types of all pieces. To request the current status of the board, the client sends:

 
    "getboard\n" 
The server will respond with multiple copies of the string
    <horizontal coord> + " " + <vertical coord> + " " + <piece type> + "|" 
followed by:
 
   "\n" 
The piece type may be either Normal or King. Each piece is surrounded by a tight fitting square and the horizontal and vertical coordinates of a piece are the number of pixels horizontally and vertically, respectively, from the origin to the upper left corner of the square surrounding the piece. The origin is the upper left corner of the gameboard. It is the client's responsibility to translate the coordinate values to a square on the 8x8 gameboard. The server locates a piece on a gameboard square by looking at the center of the piece's surrounding square.

"movestart" - start the movement of a piece
To move a piece on the board, the client sends:

    "movestart " + <horizontal coord> + " " + <vertical coord> + "\n"
where the coordinates are the position of the mouse cursor, in pixels from the origin, when the movement starts. The server responds with either:
    "ok\n"
if the user is allowed to move the piece or
    "fail\n"
if it is not the user's turn, or if there is no piece belonging to the mover at those coordinates. To determine whether there is a piece under the mouse coordinates, the server looks to see if the coordinates are within the boundaries of a square tightly surrounding a mover's piece.

"movepos" - send movement information to the server
Movement of a piece is sent as the following:

 
    "movepos " + <horizontal coord> + " " + <vertical coord> + "\n" 
The server does not respond to a movepos message. But if the client's opponent drags a piece with his/her mouse on his/her turn, movepos messages are sent through the server to the opponent's client as oppmovepos messages (see below). No movepos messages are sent through the server if it is not the mover's turn or if the mover has not initiated a move with movestart where the server has responded "ok\n".

"moveend" - end the movement of a piece
To place the piece being moved, the client sends:

    "moveend " + <horizontal coord> + " " + <vertical coord> + "\n"
The server responds with either
    "ok\n"
or
    "fail\n"
if the center of the piece being moved lands or does not land on a legal square, respectively, according to the rules for playing checkers above.

NOTE: A move to a white square, or to the original square is not a legal move and such a move can be used as a way to abort a move without giving up a turn.

"invite" - send an invitation to play to another client
A player selects a partner by sending the following message to the server:

    "invite " + <selected player's handle> + "\n"
The server determines whether the invitee is registered and free. If it is, the server responds to the invitor with:
    "invitation " + <handle of invitee> + " accepted\n"
or
    "invitation " + <handle of invitee> + " declined\n"
if, respectively, the invitee accepts the invitation or the invitee is not registered. If the invitee is unavailable, the server responds with:
    "<handle of invitee> unavailable\n"

"resign" - stop and forfeit the game
The game may be stopped using the message:

    "resign\n"
In this case, the winner is declared to be the client's opponent and the client's opponent immediately becomes available. If the client has resigned in order to unregister, the client must issue a separate unregister message as well, after the resign message.

Server initiated:

"invite" - Respond to an invitation request
The server will send the message

    "invite " + <handle of invitor> + "\n"
to inform an invitee that invitor has challenged them to a game. The client responds to this using either
    "invitation " + <handle of invitor> + " accepted\n"
or
    "invitation " + <handle of invitor> + " declined\n"
depending on whether the invitee accepts or declines the challenge.

Once a player accepts an invitation, he or she may start the game with mouse drag movements (the server will be listening).

"oppmovestart" - The coordinates of a piece the opponent is beginning to move
Sent just the first time an opponent moves a piece. Use this information to locate and delete the image associated with the moving piece. The server will send the following message:

 
    "oppmovestart " + <horizontal coord> + " " + <vertical coord> + "\n"

"oppmovepos" - The coordinates of a piece the opponent is moving
Each time the opponent sends a "movepos" command during a movement, the server will send the following message:

    "oppmovepos " + <horizontal coord> + " " + <vertical coord> + "\n"

"oppmove" - The opponent has moved a piece, coordinates before and after
When the opponent places a piece after movement, the server will send

    "oppmove " + <init horizontal coord> + " " + <init vertical coord> + " " + <final horizontal coord> + " " + <final vertical coord> + "\n"
where init coordinates are the pixel coordinates of the piece (upper left corner of surrounding rectangle wrt gameboard origin) before the piece was moved and final coordinates represent the position of the piece after the move. Only one piece may be moved on a turn. However, at most one piece may be removed on a turn (see below).

"yourturn" - Indicates that it is the clients turn to move a piece
After a client has finished a move, the server determines whose turn is next and sends the following message to the client that the server recognizes is the next valid mover of a piece:

    "yourturn " +
    <horizontal coord> + " " + <vertical coord> + " " + <piece type> + <onwer> + "|" 
    ...
    <horizontal coord> + " " + <vertical coord> + " " + <piece type> + <onwer> + "|" +
    "\n"
A client may see more than one yourturn in a row if jumps are made. The server is the official decider of legal jumps. In case of a jump, a piece is removed from the gameboard (see below). The same information that the response to a "getboard" command contains is sent in the "yourturn" command to allow the client to synchronize with the server, particularly when subsequent games are played and pieces are not centered in their boxes.

"gameend" - Indicates that the game has ended
When the game has finished, either due to a draw or a client winning, or a client resigning, both playing clients will receive the following message:

    "gameend " + <outcome> + "\n"
where the outcome is Won, Lost, or Draw. At this point, both clients will become available according to the server and may unregister if they wish.

"remove" - A piece has been removed from the gameboard
The server decides what pieces are removed from the gameboard due to a jump. When a piece is removed the server sends the following message to both playing clients:

    "remove " + <horizontal coord> + " " + <vertical coord> + "\n"
where the coordinates are relative pixel locations of surrounding box origins with respect to the gameboard origin.

"king" - A Normal piece has changed to a King piece
The server decides when a piece type changes from Normal to King. When this happens, the following message is sent to both clients:

    "king " + <horizontal coord> + " " + <vertical coord> + "\n"
where the coordinates are relative pixel locations of surrounding box origins with respect to the gameboard origin.

10 85 10 - Check client connection
Every second, the server checks whether a client is still alive by doing the following:

    Socket socket = new Socket(ipaddress, port);
    (socket.getOutputStream()).write((new Byte((byte)10)).byteValue());
    (socket.getOutputStream()).write((new Byte((byte)85)).byteValue());
    (socket.getOutputStream()).write((new Byte((byte)10)).byteValue());
If the connection fails, the client is taken off the list of registered clients.