| 6.170 |
Laboratory in Software Engineering
Spring 2002
Final Project: Antichess
|
Handout F3
Contents:
Introduction
Your final project is to design, document, build, and test a program that plays
antichess. You will work in teams of three or four. Each team member should
be responsible for a significant part of the design, documentation, code and
testing. All members of a team will get the same grade, except in unusual
circumstances. If your group is experiencing internal problems, see your
TA immediately.
Antichess Overview
Antichess is a variant of chess in which the goal is to lose all of
your pieces (except your king) or force your opponent to checkmate
you. This section describes the rules of the game.
The Chessboard
Antichess is played between two opponents by moving pieces on a
square board. The board is composed of 64 equal squares. The eight
vertical lines of squares are called columns. The eight
horizontal lines of squares are called rows. The squares are
colored black and white alternately. (Actually, we prefer black and
blue.) The lines of squares of the same color, touching corner to
corner, are called diagonals. The chessboard is placed
between the players in such a way that the near corner to the right of
each player is white(blue). The columns are labeled a to
h from left to right. The rows are numbered 1 to 8 from
bottom to top.
The Pieces
At the beginning of the game, one player ("white") has 16 white
pieces, and the other ("black") has 16 black pieces. The white player
pieces are: one King (e1), one Queen (d1), two bishops (c1 and f1),
two knights (b1 and g1), two rooks (a1 and h1), and eight pawns (row
2). The black player pieces are: one King (e8), one Queen (d8), two
bishops (c8 and f8), two knights (b8 and g8), two rooks (a8 and h8),
and eight pawns (row 7). The initial position of the pieces on the
chessboard is shown to the right.
The Moves
A move is defined by the following rules:
- "White" (in our case, green) moves first. The players
alternate in making one move at a time until the game is completed.
- A move is the transfer by a player of one of his pieces from one
square to another square, which is either vacant or occupied by an
opponent's piece.
- No piece except the knight may cross a square occupied by another piece.
That is, only the knight may jump over other pieces.
- A piece played to a square occupied by an opponent's piece
captures that piece as part of the same move. The captured
piece is immediately removed from the board.
- A player is forced to capture an opponent's piece whenever
possible. If a player can take several of the opponent's pieces, he/she is
free to choose which piece to take.
Various pieces move in different ways:
- (For simplicity, some special moves in chess have been changed as
follows in our version of antichess (if you do not understand the
terms used below, ignore them):
- Castling is not allowed.
- En passant capture is not allowed.
- When a pawn moves to the last row on the opposing side, it turns
into a queen. (In normal chess, such a pawn can be turned into any
piece of the player's choice.)
- The King
- The king moves to any adjoining square. (See below left)
- The Queen
- The queen moves to any square on the column, row, or the two
diagonals on which it stands (except as limited by rule 3). (See
below
right)
- The Rook
- The rook moves to any square (except as limited by rule 3) on the
column or row on which it stands. (See below left)
- The Bishop
- The bishop moves to any square (except as limited by rule 3) on
the two diagonals on which it stands. (See below right)
- The Knight
- The knight's move is composed of two different steps; first, it
makes one step of one single square along its row or column, then,
still moving away from the square of departure, one step of one square
on a diagonal. It does not matter if the square of the step is
occupied; no capture takes place on this first step. (See below left)
- The Pawn
- The pawn is the only piece whose moving regulations are different
from its capturing regulations. A pawn may only advance forward. It
may move one vacant square along the same column. In addition, for
its first move it may also move two vacant squares along the same
column. When capturing, it advances one square along either of the
diagonals on which it stands. (See below right) On reaching the last
row, a pawn must immediately be exchanged, as part of the same move,
for a queen of the same color as the pawn. This exchange is called a
promotion and its effect is immediate and permanent.
Handling Check Situations
The king is in check when the square it occupies is
attackable by one or more of the opponent's pieces; in this case, the
latter is/are said to be checking the king. A player may not
make a move which leaves his king on a square attackable by any of his
opponent's pieces; e.g., the player cannot move the king into check.
Check must be parried by the move immediately following. If any check
cannot be parried, the king is said to be checkmated or
mated.
It is the foremost obligation of each player to move the king out
of a check. This overrides the rule to take the opponent's piece (rule
5). For example, in the figure below to the left, it is purple's turn and
purple must move its king out of check even though it can take green's
bishop on c6 with its rook.
If it is possible for a player to remove the king from check as
well take a piece of the opponent, then the player must do so. For
example, suppose the purple player's king is under check from green's
rook. Further, suppose purple has two choices to move away from check
--- remove the check with or without taking a green piece. In that
case, purple must take green's piece and remove the check. In the
figure below to the right, purple's king must take the green bishop
with the king in the next move (it cannot simply move the king away
from check without taking the bishop).
In short, each move of player A must observe the following:
- If A's king is under check, A must move the king out of check.
- A cannot move in a way that causes the king to come into check.
- If A can take one of B's pieces, then it must (unless disallowed
by the previous rule).
- If A's king is under check and A can move in such a way that the
king is out of check by either taking B's piece or in some other
manner, A must take B's piece.
End of the Game
We shall play antichess with time restrictions, as is often the
case in chess games. Each player is allocated a fixed amount of time T
to make all the moves, e.g., 5 minutes. There is a clock for each
player that is set to T minutes at the start of the game. If it is
player A's turn to move, A's clock will count down until the move is
made. While it is B's turn to move, A's clock is suspended, and B's
clock runs down. If a player's clock runs down to zero while the game
is in progress, the player loses. This ensures that the game is over
in less than 2*T minutes, because by then at least one of the clocks
would have run down to zero.
Player A wins the game against player B if:
- all pieces of A except for the king are taken, or
- player A forces player B to checkmate player A, or
- player B's timer runs to 0.
The game is drawn when the king of the player who has the move is
not in check, and this player cannot make any legal move. The player's
king is then said to be stalemated. This immediately ends
the game in a draw, i.e., neither player wins or loses the game.
Grading and Schedule
| Stage |
Due date
|
% of project grade |
Graded on |
| Preliminary design |
Thu. 4/18 |
10% |
Have you identified the issues? |
| Weekly meetings with TA |
Mon. 4/08-Fri. 5/10 |
5% |
Did all of the team members participate constructively? |
| Preliminary Release |
Tue. 4/30 |
25% |
Is it a good design? Is the required functionality present? |
| Design Amendment |
Mon. 5/13 |
NA |
Handed out May 1.
|
| Final Report |
Mon. 5/13 |
25% |
Quality of entire documentation including design amendment and critique.
|
| Implementation & test |
Mon. 5/13 |
35% |
Does it work? Have you demonstrated that it works? |
As you can see, 60% of your grade depends on design and documentation. Please realize
that the most important aspect of any large software endeavor is
design. A good, well documented design will make the rest of a group's
work faster, easier and more enjoyable.
Each stage of this assignment should be handed in electronically and/or as
hardcopy to your TA or to the course secretary (NE43-209) by 4:30 PM on its
due date. All of the source and compiled code should be put online on
May 13, in your team project directory.
The final report is due by 4:30 pm on May 13, 2002 in the Course
Secretary's office (NE43-209). Because of end of term constraints,
late reports will not be accepted.
Preliminary Design
The preliminary design must be submitted in hardcopy outside of the course
secretary's office (NE43-209) by 4:30pm on the due date.
You should express your preliminary design in under 15 pages. Your
document will be a subset of that described in the Documenting a Software System handout. It
will include a revised specification, a design (including a problem object
model), and an implementation overview (including a code object model or
models and a module dependency diagram). You do not need to include
information about your validation strategy.
The revised specification, design, and implementation overview must
discuss, among other issues:
-
The GUI, applet and any other user interfaces which you will support.
How user input will be accepted and how the game state will be displayed
to the user.
- How the computer players will interact with the game.
- How the game will validate if a move is legal.
- How timers will function.
The preliminary design should also include a project plan, which
lists milestones for the team and allocation of tasks to each team member.
A milestone is what you expect to be done by some date, such as a tested
module or a working feature -- an achievement that is objective, easy to
evaluate, and significant. There must be at least two milestones in the
project between the preliminary design and the final deadline. The division
of labor should be equitable.
(It is most useful to combine the milestones and the task allocation into a
single table with task, who, and when columns, rather than making the
milestones and task allocation into to separate documents which cannot be
easily related.)
The preliminary design will be graded for clarity of expression and for
whether you have thought rigorously about the problem, identified the major
issues and challenges, and proposed a design that makes sense.
Weekly Meetings with TA
Each team will meet with its TA once a week for half an hour. The official
time for these meetings is during the regular 10am - 11am class time. To receive
full participation credit:
-
All team members must be present at all meetings.
-
All team members must answer questions and participate in the discussion
at each meeting.
-
A clear progress document that is useful for productive discussions must
be handed in each week at the meeting. At the first meeting a draft of the Preliminary
Design will serve as the progress document.
Although the progress document must be clear, it is short and
informal. This document will form the basis
of discussion during the meeting, and the TA will keep it on file as a record
of progress made. The team should bring multiple copies to the meeting,
one for each team member and one for the TA. This progress document should
include the following information:
-
A description of all the new issues that have been discovered during the
previous week. This includes both a list of newly discovered bugs, and
a list of unresolved design issues.
-
A description of all the issues that have been solved over the past week.
This includes a list of bugs that were fixed, and how they were fixed,
and a list of design issues that were resolved, and how they were resolved.
-
A list of all the issues from previous weeks that are still unresolved.
-
A plan for the next week, with specific actions and goals for each team member.
-
An assessment of success at meeting the previous week's plan.
-
The document may also contain any other material that you feel describes
your progress, such as object model or MDD fragments showing changes to
the design.
Preliminary Release
The preliminary release has two components: a final design writeup and a
demonstration of basic functionality.
Final Design
The final design document is an improved and completed version of the
preliminary design document. (For instance, it should include a section on
your validation/testing strategy.) You should express your final design in
under 20 pages. In the project plan section, explain any milestones that
you missed and give reasons why you were unable to reach them.
Since the final design is due as part of the preliminary release milestone, you should
have found all major mistakes in your design. Therefore
the final design will be graded on whether it is a good design,
in addition to clarity of expression.
Required Functionality
At the preliminary release deadline, we will ask you to demonstrate some specific
functionality.
In order to demo what you had done at the preliminary release
deadline, even if the demo is slightly later and you have made
modifications in the meanwhile, you must to retain a copy of your code
as it existed before the deadline. You can create a snapshot of your
source and/or compiled code by using a jar
file. Then, you can run the demo by placing the jarfile in your
classpath, or by making the jar itself executable.
Your group must demonstrate the following features:
- Applet and Application
Your antichess game should be playable both as an applet and as an
application. For convenience, we
will refer to the program as an application, although it should be runnable
in both forms.
- Human Computer Game The application should provide functionality for
a human computer game. It must display to the user the board, the timers and
whose turn it is. The user should be able to type in moves (mouse control is optional.
- File Save and Retrieve The program should allow the user to save the current
game into a text file as defined by the Game File Format. The current game should continue after the game is saved. The program should also allow the user to load a saved game.
Your GUI should be easy to use and understand.
Amendment
Shortly after submitting the preliminary release, you will receive an amendment
to the program specification. In large programming projects, the requirements
often change during development. Your design should be flexible
enough to adapt easily to possible changes in the specification.
Implementation and Critique
It should be possible for you to describe your implementation and critique
your design in under 20 pages (except for the Specifications in Item 2,
which may take another 5-10 pages and should be placed in an appendix).
Conciseness is important.
Put your code online in your team project directory. You do not need
to turn in a printout of your code.
The final report includes a section on Design Changes.
Detail what changes you have made to the design that was submitted on
Apr 30. Be precise. It is vitally important that your TA have versions
of the descriptive parts of the Revised Specification, Implementation
Overview, and Validation Strategy that accurately describe your
submitted code and what you actually did for testing or validation. If
the description is not accurate, the submission will not be graded
accurately.
For demonstrations (as described immediately below), you must also
make a jar file of your implementation named
/mit/6.170/groups/seMMN/final.jar. This file must be
runnable and must include all of your code in both source and compiled
form.
Demonstrate your working program for your TA. All team members must
be present to give a brief presentation and answer questions pertaining
to their responsibilities in the development process. The presentation
and demonstration should not last for more than 15 minutes. Expect another
half hour of questions and discussion.
Competition
When you submit your implementation and critique on May 13, indicate
on the first page if you want it to be considered for one or more of the
following prizes.
-
Best design: Awarded for the project with the best abstraction, modularity,
extensibility, simplicity, etc. The quality of the final report is also
considered.
- Best AI Player: there will be a single elimination, tournament to determine
which AI player reigns. Only teams with complete, working antichess implementations
will be permitted to enter. This competition will have no bearing on grading.
Judging will be done initially by the TAs and final judgments will
be made by the lecturers. Winners
will be announced at the last class on May 15.
What We Give You
We are providing you with images for various chess pieces. They are available
in the directory /mit/6.170/www/psets/final/antichess/src/images. The README file in that
directory has more information about the images provided.
In addition we provide you with a specification for machine players. It can be
found in Appendix 2.
Hints
General
-
Design
A careful design will save you a lot of time in the long run. It's well
known that a small mistake made early in a project can become a big problem
if it's not caught until much later. The preliminary design is a major part
of the project (more so than its proportion of the grade might
indicate). Do it very carefully, trying to anticipate problems that may
arise. Then the rest of your project will be more straightforward and more
fun.
-
Prototype
One of the largest challenges for this kind of design problem is figuring
out where the "gotchas" are. If you are having difficulty imagining how
to structure one part of the design it sometimes helps to build a small
prototype. Plan to throw away your prototypes. Once you've figured out
how to do design something correctly, it rarely makes sense to try to retrofit
a hacked up, broken version.
-
Validate early and often
Validation shouldn't be an afterthought! You may choose a design because
its implementation will be easier to test. Make sure you validate your
code as you implement.
-
Document early and often
Incomplete documentation is better than no documentation at all. If
a potential problem or subtlety occurs to you, but you don't have time
(or are unable) to formulate it properly, then just add a few sentences
in your document describing the issue. Later, if you have time, you can
go back and fix it.
-
Don't overdocument
Don't include any redundant material. For example, there's no need
to explain the difference between black-box and glass-box testing. Just
indicate which of your test cases fall in each category. Similarly, being
rigorous is not the same as belaboring the obvious. You can assume that
your TA knows what a set or a stack is. There's no need to explain something
from scratch when you can use standard terms and notions.
-
Have fun being on a team
Enjoy being part of a team. Run new ideas past your partners, and discuss
problems with them. Read and discuss each others code. A good way to find
a bug is to ask someone else to look at your code. Start early!
-
Communicate effectively
Each meeting you hold with your team members (or your TA) should have
- an agenda. Don't get together unless you know the reason. This will
help you avoid wasting time.
- a designated leader to facilitate the meeting. The leader ensures that
the meeting stays on track, encourages all group members to participate,
and helps to resolve problems.
- a secretary who takes notes and distributes them to the remainder of
the group afterward. These notes highlight the important decisions
made, issues resolved (and not resolved), etc. They ensure that all
decisions are agreed upon by everyone and that everyone is aware of the
issues raised at the meeting.
The roles should rotate among the group members; in 6.170, no one
individual should perform any of the roles disproportionately often.
-
Prioritize
We had fun putting together this project. Our goal was to provide you
with a project that is both very challenging and offers many opportunities
for you to be creative. We encourage you to experiment. Make your implementation
of Antichess as beautiful to watch, and as fun to play as possible. That
said, make sure you get the basic functionality working before you
add new features, expert level AI players, or an elaborate GUI.
The best way to approach extensions to the project is to make your initial
design flexible and extensible.
System Administration and Computer Tools
Group Work
To make intra-group collaboration easier, each team
has an AFS locker to store project work and a mailing list for
posting messages within the group. Each group has a name in the
format "seMMN", where MM is the team's original
recitation section number, and N is the team number within
that section. This name serves both as an identifier for your team's
mailing list (seMMN at MIT) and as a name for the
allocated project space (/mit/6.170/groups/seMMN/).
We have also setup web access to your project space, using your MIT
certificates. The URL for your group is of the form https://web.mit.edu/6.170/groups/seMMN/
(note the s in the https protocol).
Revision Control
We strongly recommend that you use a revision control package such as CVS to help you coordinate your work, prevent
loss of code, and permit backing up to previous versions.
Make: System Model
Another tool you may find useful is make.
This tool allows you to write a makefile that is a model of
your system: which files contain code, what work needs to be done to
compile the system, what work needs to be done to run your tests, what
work needs to be done to clean up the directory, etc. Once you have
written the makefile, you can do any of these tasks by typing a single
command.
On Athena, type info make.
Java Archive (JAR) files
You will need to create jar files as a way of collecting all
parts of your application for delivery to your TA. jar files
are useful because they can store all of the source code, compiled
code, and associated data files (such as images or sounds) into one
centralized archive, which can then be easily distributed.
To learn more about jar files, review the
jar tool
manual from Sun.
As a quick reference, here are a few sample uses of the jar command:
To create antichess.jar from classes in packages anti and chess:
jar cvf antichess.jar antichess
To list the contents of the jar file, use:
jar tf antichess.jar
To create a runnable antichess.jar
jar cvfm antichess.jar JarMainManifest antichess
In the example above, the file JarMainManifest should contain
a single line which names the entry point:
Main-Class: antichess.Antichess
To run the application using the jar file, use:
java -jar antichess.jar
Using a Makefile, as described the section above, can simplify and
automate the creation of jar files.
Appendix 1: Detailed Requirements
Antichess Web Applet
Your antichess game should be playable both as an applet and as an
application. For convenience, we
will refer to the program as an application, although it should be runnable
in both forms.
Your program should be runnable via either of the following commands:
java antichess.Antichess
appletviewer antichess.html
The basic mode of your game will be to have a human play against a
machine player. Your application should use the Java
Swing to provide a graphical user interface for this form of play, as
described in Section 4.2.
In addition, we will provide a referee which will allow your machine player
to play against machine players from other
groups. In order to be able to do this, you must provide a MachinePlayer
class which conforms to the specification in Appendix B.
The referee will use the information about what has changed on the board, plus its knowledge of the current state, to display
the status of the game. It will check each response for legality, it will keep track of the time left for each player, and it will
display the status of the game. We will provide our own referee that does these things. We will use this referee in the
tournament. You will not implement the referee in this problem set; only the antichess player. Of course, in a
human-computer game, your program has to provide functionalities very similar to the referee (e.g. checking for illegal
moves, displaying status, etc.).
Your program will not be graded on the absolute level of the skill exhibited by your machine player. You should employ
heuristics in your program to make it play reasonably well, but do not get bogged down in this process. However, your
machine player should not simply play randomly.
Human-Computer Game
The web interface for a human-computer game should display at least the
following information:
- The board.
- Player names and the colors they are playing (black or white)
- Whose turn it is.
- How much time is on each player's clock.
This information need not be updated on the fly,
but at the end of each move and whenever the user explicitly
asks for the most up-to-date information.
- Any other status information that you feel is relevant.
Once the game has started, the following functionality must be available:
- When it is the user's turn, the user should be allowed to make a move, by manually typing in the coordinates of the move (e.g. a1-b2. See Section 4.4). Support for mouse-based moves is optional. Your program
should be able to handle erroneous input by the user (e.g. an incorrectly typed move, or an illegal move) by displaying a
reasonable error message, and allowing the user to retry.
- After the user has entered his or her move, your program should validate the move, and update the screen to show its new state. After the user's move is displayed, the machine player is allowed to decide on its
move. The result of the machine player's move is then displayed to the screen, and the process repeats.
- In the case of a computer player, your program should be able to display the last move that that player made. For example, this may be a text message (such as black moved a1-b1) or a graphical animation that shows
the pieces moving. Only redrawing the board after the move is not sufficient, because it is sometime difficult to see what
changed.
- Your application should also allow the user to start a new game. This includes letting the user decide which color he or she wishes to play.
- The program should allow the user to save the current game into a text file as defined by the Game File Format (see Section 4.3). The current game should continue after the game is saved.
- The program should also allow the user to load a saved game. This would allow the user to choose a game that has been saved and let them load it and play from where the game was left off. The user should be able
to play either side once it is loaded.
- Your program should allow the user to set the time left for either side. This will allow the user to increase or decrease the time left for either the human or the computer player in the middle of a game.
- The user should also be able to end the current game.
Computer-Computer Games
This section describes the standard features that your program must support
in order to work with our referee. Your program is required to conform to
these specifications (even if you do not intend to enter the
tournament), and the specifications may not be changed.
We define a standard string format for a chess move. The string should be 5
characters long. The first two characters represent the square where the
piece began, the third character is a dash (-), and the next two characters
represent the square where the piece moved to:
::= -
::= a | b | c | d | e | f | g | h
::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
[Figure 4]
You must implement a MachinePlayer class in package antichess that has the methods
given in Appendix B. Your MachinePlayer may have additional methods,
but it must have at least the ones described in Appendix B.
Your machine player is allowed to use multiple threads and be thinking while
the opponent is thinking and making his move. However, you are not allowed
to use the resources of a computer other than the one running the machine
player.
The specifications for MachinePlayer allow you to specify a level for the
machine player. That is, you may want to have one
version of the machine player that plays (potentially) faster but not as
well as another version. This feature is entirely
optional; the only requirement is that your level 0 machine player play
somewhat decently.
Game File Format
The game file format contains all of the current game state. On consecutive lines in contains: next player, white time, black time, and 8 lines for game state with upper-case letters for white, lower-case for black and dashes (-) for empty. The following is a formal discription of the file format:
::= newline newline
::= black -- white
::= newline
::=
::= newline
::= - |
::= P | p | K | k | N | n | R | r | Q | q | B | b
The fields in the file are:
- < next-turn-color > indicates which color moves next after the board is loaded.
- < timeleft > is two integers indicating the number of milliseconds left on each player's clock
(white player first).
- < board > describes the content of each of the squares on the board. The first < sq > in the first < row > corresponds to square A8 on the display, and the last < sq > in the last < row > corresponds to square H1. Each square is either a blank (denoted by a hyphen) or a <piece >. A <piece > is either denoted by
lower case letters for black pieces or upper case letters as white pieces (P = white pawn, p = black pawn, K/k= white/black
king, Q/q = white/black queen, R/r = white/black rook, B/b = white/black bishop, N/n = white/black knight).
As an example here is a load file for the initial board configuration. Time left for each player is 5 minutes (300000 milliseconds). In conventional layout,
the white pieces are in the bottom two rows and black pieces in the top two.
white
300000
300000
rnbqkbnr
pppppppp
--------
--------
--------
--------
PPPPPPPP
RNBQKBNR
[Figure 5]
Appendix 2: Specifications for MachinePlayer
The following specification is available in the directory /mit/6.170/www/psets/final/antichess/src.
package antichess;
public class MachinePlayer {
public MachinePlayer(boolean iswhite, int level) {
// effects: Creates a new MachinePlayer with the normal starting
// board (as described in Figure 5). If iswhite is
// true, the player plays as white, else as black. Level
// is an optional, arbitrary integer which can be used to
// affect the algorithm the machine player uses. The
// tournament referee will always request a level 0
// MachinePlayer.
}
public MachinePlayer(boolean iswhite, int level, String bd) {
// requires: bd is a string representing a valid board, as
// described in Figure 5.
// effects: Creates a new MachinePlayer in the same way described
// by the constructor MachinePlayer(boolean, int), except
// that the initial board configuration is set to be the one
// described by bd.
}
public String getName(){
// effects: Returns a string name for the machine player (this is
// needed for the tournament.
}
public String makeMove(String opponentMove,
int timeLeft,
int opponentTimeLeft) {
// requires: opponentMove is either a string representing a valid
// move by the opponent on the board stored in this (see
// Figure 4), or the empty string. timeLeft and
// opponentTimeLeft are both > 0
// modifies: this
// effects: Returns a valid next move for this player in a string
// of the appropriate format, given the opponent's move,
// the time left for this player, and the time left for the
// opponent. Both times are in milliseconds. If
// opponentMove is the empty string, then the board for this
// player should be considered up to date (as would be the
// case if this player is asked to make the first move of the
// game).
//
// NOTE: This procedure may run greater than timeLeft, but
// this would mean losing the game.
}
}