001    package core;
002    
003    import java.util.*;
004    
005    import rules.GameState;
006    import rules.NoneSquare;
007    
008    /**
009     * A Piece represents a state of the board. Individual pieces are subclasses of
010     * Piece, overriding various methods to determine their name and how they move.
011     * 
012     * Pieces are immutable.
013     * 
014     * One special case is Empty, for non-piece squares.
015     * 
016     * @specfield state : int //Useful for castling/en passant
017     * @specfield color : Color //Who the owner is
018     * @specfield name : String //Name of this piece type
019     * @derivedfield moves(GameState) : Set<Move> //Possible moves from a position
020     */
021    public abstract class Piece
022    {
023        /* The color of this piece */
024        protected Color color;
025    
026        /* This isn't actually the last move; it is
027         * 0    before a piece moves
028         * (the last move)  if the piece was just a pawn pushed by 2 squares
029         * 1    otherwise
030         * So castling can only be done if both have lastMove 0;
031         * en passant if the opposing pawn's lastMove is the current move.
032         * and it is in the right spot
033         */
034        private int lastMove;
035    
036            // AF:
037            // state = lastMove
038            // color = color
039            // name = getName() (short) or pieceString() (long)
040            //
041            // RI:
042            // color != null
043            // color == NONE for Empty and != NONE otherwise
044    
045            /**
046             * @returns a single-character name of this piece
047             */
048            protected abstract String getName();
049    
050            /**
051             * @returns a human readable string for the piece.
052             */
053            abstract public String pieceString();
054    
055            private void checkRep()
056            {
057                    assert (color != null);
058                    if (this instanceof NoneSquare)
059                    {
060                            assert (color == Color.NONE);
061                    } else
062                    {
063                            assert (color != Color.NONE);
064                    }
065            }
066    
067            /**
068             * @returns valid moves for this piece.
069             * @requires g, here != null
070             */
071            public abstract Collection<Move> moveCandidates(GameState g, Position here);
072    
073    
074            /**
075             * Constructs a new piece.
076             * 
077             * @param color
078             *            of the piece
079             * @param lastMove
080             *            of the piece (0 means it hasn't moved)
081             * @requires color not null, last move valid
082             */
083            public Piece(Color color, int lastMove)
084            {
085                    this.color = color;
086                    this.lastMove = lastMove;
087                    checkRep();
088            }
089    
090            /**
091             * @returns the last time this piece moved
092             */
093            public int getLastMove()
094            {
095                    return lastMove;
096            }
097    
098            /**
099             * @returns the color of this piece
100             */
101            public Color getColor()
102            {
103                    return color;
104            }
105    
106            /**
107             * @returns the short 1-character name of this piece, in lower case for
108             *          black and upper case for white.
109             */
110            public String toString()
111            {
112                    if (getColor() == Color.WHITE)
113                            return getName().toUpperCase();
114                    else
115                            return getName().toLowerCase();
116            }
117    
118        /**
119         * Apply the modifications to a move map for a move onto this
120         * square completes.
121         *
122         * Used to implement powerups; others can safely do nothing.
123         */
124        public void postMove(GameState gs, Map<Position, Piece> move,
125                             Position here) {
126        }
127        
128        /**
129         *  This should be unique for different pieces or different
130         *  colors.
131         */
132        abstract public int hashCode();
133    }