//public int col, row; range from 1 to 8 //private Piece piece; reference to piece that stands on this square , null if square empty // //constructor - public Square(Color c, int w, int h, int col, int row) //(first 3 parameters - fot the GoodButton constructor) //only this GoodButtoon's constructor is used so far //user must take care to give correct col, row // //presents to the user methods: //public String coords() returns its coordinates as "a1","h8", etc. //public void setPiece(Piece p) puts the given piece on this square, drawing its image //public void Piece getPiece() returns the piece, null if none //public void clearPiece() sets piece to null regardess of current content // //Methods setPiece() and clearPiece() are should only be accessed by Piece //class. DO NOT attempt to call them directly! import java.awt.*; import java.awt.event.*; import java.util.*; public class Square //extends GoodButton { public int col, row; public Piece piece = null; //range from 1 to 8 public Square(int col, int row) { this.col = col; this.row = row; } //receives coordinates in one string like "a1", etc. String must have the right format public Square(String nm) { int col = (int) (nm.charAt(0) - 'a' + 1); int row = (int) (nm.charAt(1) - '1' + 1); this.col = col; this.row = row; } //receives coordinates from Field public Square(Field fld) { col = fld.col; row = fld.row; } //receives coordinates from Square public Square(Square sq) { col = sq.col; row = sq.row; } //put the specified piece on this square public void setPiece(Piece p) {piece = p;} public void clearPiece() {piece = null;} public Piece getPiece() {return piece;} public String coords() {return "" + (char)('a' + col - 1) + row;} public int getCol() {return col;} public int getRow() {return row;} public boolean empty() {if (piece == null) return true; else return false;} //determines which color i ought to have based on my coordinates private String properColor(int col, int row) { if ((col==1) || (col==3) || (col==5) || (col==7)) //a,c,e,g file if ((row==1) || (row==3) || (row==5) || (row==7)) return "black"; else return "white"; else //b,d,f,h file if ((row==1) || (row==3) || (row==5) || (row==7)) return "white"; else return "black"; } //these functions receive a [9][9] array of references to Squares //and return a Vector of Moves accessible to the given piece public Vector kingMoves(Square [][] s) { Vector v = new Vector(); addIfCan(v,s,col+1,row); addIfCan(v,s,col+1,row-1); addIfCan(v,s,col+1,row+1); addIfCan(v,s,col,row-1); addIfCan(v,s,col,row+1); addIfCan(v,s,col-1,row); addIfCan(v,s,col-1,row-1); addIfCan(v,s,col-1,row+1); if ((col==5) && (row==1 || row==8) && (!empty()) && (piece.getName().equals("king")) && (piece.cancastle==true)) //king can castle { if (!s[8][row].empty() && s[8][row].piece.getName().equals("rook") && s[8][row].piece.cancastle==true) { if (s[6][row].empty() && s[7][row].empty()) addIfCan(v,s,col+2,row); //short castle } if (!s[1][row].empty() && s[1][row].piece.getName().equals("rook") && s[1][row].piece.cancastle==true) { if (s[4][row].empty() && s[3][row].empty() && s[2][row].empty()) addIfCan(v,s,col-2,row); //long castle } } return v; } public Vector queenMoves(Square[][] s) { Vector v = new Vector(); int i; Vector temp1 = rookMoves(s); for (i = 0; i < temp1.size(); i++) v.addElement(temp1.elementAt(i)); Vector temp2 = bishopMoves(s); for (i = 0; i < temp2.size(); i++) v.addElement(temp2.elementAt(i)); return v; } //possible rook moves; we break the cycle if any piece is encountered //(rook has no "roentgenn" properties) public Vector rookMoves(Square[][] s) { Vector v = new Vector(); int i; for (i = row + 1; i <= 8; i++) {addIfCan(v,s,col,i); if (!s[col][i].empty()) break;} //column for (i = row - 1; i >= 1; i--) {addIfCan(v,s,col,i); if (!s[col][i].empty()) break;} //column for (i = col + 1; i <= 8; i++) {addIfCan(v,s,i,row); if (!s[i][row].empty()) break;} //row for (i = col - 1; i >= 1; i--) {addIfCan(v,s,i,row); if (!s[i][row].empty()) break;} //row return v; } public Vector bishopMoves(Square[][] s) { Vector v = new Vector(); int i,j; for (i = col + 1, j = row + 1; i <= 8 && j <= 8; i++,j++) {addIfCan(v,s,i,j); if (!s[i][j].empty()) break;} //upper right for (i = col - 1, j = row - 1; i >= 1 && j >= 1; i--,j--) {addIfCan(v,s,i,j); if (!s[i][j].empty()) break;}//lower left for (i = col + 1, j = row - 1; i <= 8 && j >= 1; i++,j--) {addIfCan(v,s,i,j); if (!s[i][j].empty()) break;}//lower right for (i = col - 1, j = row + 1; i >= 1 && j <= 8; i--,j++) {addIfCan(v,s,i,j); if (!s[i][j].empty()) break;}//upper left return v; } public Vector knightMoves(Square[][] s) { Vector v = new Vector(); addIfCan(v,s,col+1,row+2); addIfCan(v,s,col+2,row+1); addIfCan(v,s,col+2,row-1); addIfCan(v,s,col+1,row-2); addIfCan(v,s,col-1,row-2); addIfCan(v,s,col-2,row-1); addIfCan(v,s,col-2,row+1); addIfCan(v,s,col-1,row+2); return v; } public Vector pawnMoves(Square[][] s) { Vector v = new Vector(); if (piece == null) return v; if (piece.getOwner().equals("white")) { //moves to 8th rank //advance if (onBoard(col,row+1)) if (s[col][row+1].empty()) addIfCan(v,s,col,row+1); if ((row == 2) && s[col][3].empty() && s[col][4].empty()) addIfCan(v,s,col,4); //take enemy piece if (onBoard(col-1,row+1)) if (!s[col-1][row+1].empty()) addIfCan(v,s,col-1,row+1); if (onBoard(col+1,row+1)) if (!s[col+1][row+1].empty()) addIfCan(v,s,col+1,row+1); //en passe addEnPasseIfCan(v,s,col-1,row+1,col-1,row); addEnPasseIfCan(v,s,col+1,row+1,col+1,row); } if (piece.getOwner().equals("black")) { //moves to 1st rank //advance if (onBoard(col,row-1)) if (s[col][row-1].empty()) addIfCan(v,s,col,row-1); if ((row == 7) && s[col][6].empty() && s[col][5].empty()) addIfCan(v,s,col,5); //take enemy piece if (onBoard(col-1,row-1)) if (!s[col-1][row-1].empty()) addIfCan(v,s,col-1,row-1); if (onBoard(col+1,row-1)) if (!s[col+1][row-1].empty()) addIfCan(v,s,col+1,row-1); //en passe addEnPasseIfCan(v,s,col-1,row-1,col-1,row); addEnPasseIfCan(v,s,col+1,row-1,col+1,row); } return v; } //add s[i][j] to v if i<=1<=8, j<=1<=8 (but Square can't add itself) //only for use by kingMoves(), queenMoves(), etc. //for all moves except enpasse private void addIfCan(Vector v, Square[][] s, int i, int j) { if (!onBoard(i,j)) return; //outside the board if ((i == col) && (j == row)) return; //can't add myself Piece p1 = this.piece, p2 = s[i][j].piece; if (p1 == null) return; //no piece to move if (p2 != null) if (p1.getOwner().equals(p2.getOwner())) return; //occupied by a piece of same color //add the element Move m = new Move(); m.srccol = col; m.srcrow = row; m.srcsqr = this; m.srcpiece = piece; m.destcol = i; m.destrow = j; m.destsqr = s[i][j]; m.victpiece = s[i][j].piece; if (m.victpiece != null) {m.victsqr = s[i][j]; m.victcol=i; m.victrow=j;} m.enpasse = false; //by defenition m.transforms = 0; m.castle = 0; m.srcname = new String(piece.name); m.srcowner = new String(piece.owner); m.srcenpasse = piece.enpasse; m.srccancastle = piece.cancastle; if (m.victpiece != null) { m.victname = new String(m.victpiece.name); m.victowner = new String(m.victpiece.owner); m.victenpasse = m.victpiece.enpasse; m.victcancastle = m.victpiece.cancastle; } //check for castles if (p1.name.equals("king") && i==col+2 && j==row) {m.castle = 1; m.prtnrpiece=s[8][j].piece; m.prtnrsqr = s[8][j]; m.prtnrcol = 8; m.prtnrrow = j;} if (p1.name.equals("king") && i==col-2 && j==row) {m.castle = 2; m.prtnrpiece=s[1][j].piece; m.prtnrsqr = s[1][j]; m.prtnrcol = 1; m.prtnrrow = j;} //check for transformations if (p1.name.equals("pawn") && (s[i][j].getRow() == 8 || s[i][j].getRow() == 1)) //pawn reached last rank { m.transforms = 1; Move m1 = new Move(m), m2 = new Move(m), m3 = new Move(m); m1.transforms = 2; m2.transforms = 3; m3.transforms = 4; v.addElement(m1); v.addElement(m2); v.addElement(m3); } v.addElement(m); } //makes sense only for pawns //adds an en passe move to the Vector of moves; similar to addIfCan() //takes 2 extra params k,l for the coordinates of the enemy pawn //(because they're different from coordinates of the dest square) private void addEnPasseIfCan(Vector v, Square[][] s, int i, int j, int k, int l) { if (!onBoard(i,j)) return; //outside the board if (!onBoard(k,l)) return; //outside the board if ((i == col) && (j == row)) return; //can't remain still if ((k == col) && (l == row)) return; //can't capture myself Piece p1 = this.piece, p2 = s[k][l].getPiece(); //p1 - this pawn, p2 - victim pawn if ((p1 == null) || (p2 == null)) return; //no moving pawn or no victim pawn if (p1.owner.equals(p2.owner)) return; //occupied by a piece of same color if (!p1.name.equals("pawn") || !p2.name.equals("pawn")) return; //one or the other is not a pawn if (p2.enpasse == false) return; //the enemy pawn cannot be taken en passe if (!s[i][j].empty()) return; //a precaucion; actually, it MUST be empty if the enemy pawn was able to advance 2 squares //make the move Move m = new Move(); m.srccol = col; m.srcrow = row; m.srcsqr = this; m.srcpiece = piece; m.destcol = i; m.destrow = j; m.destsqr = s[i][j]; m.victcol = k; m.victrow = l; m.victsqr = s[k][l]; m.victpiece = s[k][l].piece; m.enpasse = true; m.srcname = new String("pawn"); m.srcowner = new String(piece.owner); m.srcenpasse = false; //pawn can't be taken enpasse: it itself captures en passe m.srccancastle = false; //false for a pawn m.victname = new String("pawn"); m.victowner = new String(m.victpiece.owner); m.victenpasse = true; //it could be taken (and was taken) enpasse m.victcancastle = false;//false for a pawn v.addElement(m); } private boolean onBoard(int i, int j) { if ((i < 1) || (i > 8) || (j < 1) || (j > 8)) return false; else return true; } public String toString() { return coords(); } }