import java.util.*; public class Position { public Square square[][] = new Square[9][9]; //for convenience public Vector whitePieces = new Vector(), blackPieces = new Vector(), myPieces, enemyPieces; public Stack moveStack = new Stack(); //private Stack capturedPieces = new Stack(); private String turn = null; //"white"/"black" public boolean checkmate = false; public boolean stalemate = false; public Position() //default - initial position { int i,j; //create 64 new squares for (i = 1; i <= 8; i++) for (j = 1; j <= 8; j++) square[i][j] = new Square(i,j); //squares receive their pieces Piece wk = new Piece("white","king"), bk = new Piece("black","king"); wk.putOnSquare(square[5][1]); bk.putOnSquare(square[5][8]); Piece wqn = new Piece("white","queen"), bqn = new Piece("black","queen"); wqn.putOnSquare(square[4][1]); bqn.putOnSquare(square[4][8]); Piece wr1 = new Piece("white","rook"), br1 = new Piece("black","rook"); wr1.putOnSquare(square[1][1]); br1.putOnSquare(square[1][8]); Piece wr2 = new Piece("white","rook"), br2 = new Piece("black","rook"); wr2.putOnSquare(square[8][1]); br2.putOnSquare(square[8][8]); Piece wb1 = new Piece("white","bishop"), bb1 = new Piece("black","bishop"); wb1.putOnSquare(square[3][1]); bb1.putOnSquare(square[3][8]); Piece wb2 = new Piece("white","bishop"), bb2 = new Piece("black","bishop"); wb2.putOnSquare(square[6][1]); bb2.putOnSquare(square[6][8]); Piece wkt1 = new Piece("white","knight"), bkt1 = new Piece("black","knight"); wkt1.putOnSquare(square[2][1]); bkt1.putOnSquare(square[2][8]); Piece wkt2 = new Piece("white","knight"), bkt2 = new Piece("black","knight"); wkt2.putOnSquare(square[7][1]); bkt2.putOnSquare(square[7][8]); for (i = 1; i <= 8; i++) { Piece wpn = new Piece("white","pawn"), bpn = new Piece("black","pawn"); wpn.putOnSquare(square[i][2]); bpn.putOnSquare(square[i][7]); } //set the turn and build whitePieces,blackPieces vectors based on square[][] setTurn("white"); //default setPieces(square); } public Position(Field[][] f) { //create 64 new squares for (int i = 1; i <= 8; i++) for (int j = 1; j <= 8; j++) { //new square is created and receives its coordinates from f[i][j] square[i][j] = new Square(f[i][j]); //new square receives its piece if (f[i][j].piece == null) square[i][j].piece = null; else {Piece p = new Piece(f[i][j].piece); p.putOnSquare(square[i][j]);} } setTurn("white"); //default setPieces(square); } public Position(Field[][] f, String t) { //create 64 new squares for (int i = 1; i <= 8; i++) for (int j = 1; j <= 8; j++) { //new square is created and receives its coordinates from f[i][j] square[i][j] = new Square(f[i][j]); //new square receives its piece if (f[i][j].piece == null) square[i][j].piece = null; else {Piece p = new Piece(f[i][j].piece); p.putOnSquare(square[i][j]);} } setTurn(t); //default setPieces(square); } //2D array [9][9] - 64 squares, which, in turn, have links to the pieces public Position(Square[][] s) { for (int i = 1; i <= 8; i++) for (int j = 1; j <= 8; j++) square[i][j] = s[i][j]; setTurn("white"); //default setPieces(square); } public Position(Square[][] s, String t) { for (int i = 1; i <= 8; i++) for (int j = 1; j <= 8; j++) square[i][j] = s[i][j]; setTurn(t); setPieces(square); } public Position(Position pos) { for (int i = 1; i <= 8; i++) for (int j = 1; j <= 8; j++) { //new square is created and receives its coordinates from pos.square[i][j] square[i][j] = new Square(i,j); //new square receives its piece if (pos.square[i][j].piece == null) square[i][j].piece = null; else {Piece p = new Piece(pos.square[i][j].piece); p.putOnSquare(square[i][j]);} } //copy moveStack moveStack = (Stack) pos.moveStack.clone(); setTurn(pos.turn); //sets whitePieces,blackPieces vectors setPieces(square); } public Position(Position pos, Move m) { for (int i = 1; i <= 8; i++) for (int j = 1; j <= 8; j++) { //new square is created and receives its coordinates from pos.square[i][j] square[i][j] = new Square(i,j); //new square receives its piece if (pos.square[i][j].piece == null) square[i][j].piece = null; else {Piece p = new Piece(pos.square[i][j].piece); p.putOnSquare(square[i][j]);} } //copy moveStack moveStack = (Stack) pos.moveStack.clone(); setTurn(pos.turn); //sets whitePieces,blackPieces vectors setPieces(square); //now, make move; Move m refers to src,dest,victim from pos, so I must redirect them Move mv = new Move(m); mv.srcsqr = square[m.srccol][m.srcrow]; mv.destsqr = square[m.destcol][m.destrow]; if (m.victpiece != null) { mv.victpiece = square[m.victcol][m.victrow].piece; } makeMove(mv); } //fills vectors whitePieces,blackPieces with pieces that occupy given array of squares //and sorts in increasing order (king,queen,rook,bishop,knight,pawn) private void setPieces(Square[][] s) { for (int i = 1; i <= 8; i++) { for (int j = 1; j <= 8; j++) { Piece p = s[i][j].piece; if (p == null) continue; if (p.owner.equals("white")) whitePieces.addElement(p); else if (p.owner.equals("black")) blackPieces.addElement(p); else System.out.println("piece " + p.name + " has no owner!"); } } sort(whitePieces); sort(blackPieces); } //in the order king,quuen,rook,bishop,knight,pawn private void sort(Vector v) { for (int j = v.size() - 1; j >= 1; j--) { for (int i = 0; i <= j-1; i++) { Piece p1 = (Piece) v.elementAt(i), p2 = (Piece) v.elementAt(i+1); if (p1.compareName(p2) == -1) swap(v,i,i+1); } } } private void swap(Vector v, int i, int j) { Object o1 = v.elementAt(i), o2 = v.elementAt(j); v.setElementAt(o1,j); v.setElementAt(o2,i); } public Vector getWhitePieces() {return whitePieces;} public Vector getBlackPieces() {return blackPieces;} public Piece getMyKing() { Piece p = null; for (int i = 0; i < myPieces.size(); i++) { p = (Piece) myPieces.elementAt(i); if (p.name.equals("king")) return p; } return p; } public Piece getEnemyKing() { Piece p = null; for (int i = 0; i < enemyPieces.size(); i++) { p = (Piece) enemyPieces.elementAt(i); if (p.name.equals("king")) return p; } return p; } public void printPosition() { printWhitePieces(); printBlackPieces(); } public void printWhitePieces() { System.out.print("White: "); printPieceSet(whitePieces); } public void printBlackPieces() { System.out.print("Black: "); printPieceSet(blackPieces); } private void printPieceSet() { if (turn.equals("white")) printPieceSet(whitePieces); else printPieceSet(blackPieces); } public String toString() { String str = turn + "'s move; "; str = str + "White: "; boolean flag = false; int i = 0; for (i = 0; i < whitePieces.size(); i++) { Piece p = (Piece)whitePieces.elementAt(i); if (p.name.equals("pawn") && !flag) {str = str + "pp: ";flag = true;} str = str + p.abbreviation() + p.getSquare().toString(); if (i != whitePieces.size() - 1) str = str + ","; } str = str + " Black: "; flag = false; for (i = 0; i < blackPieces.size(); i++) { Piece p = (Piece)blackPieces.elementAt(i); if (p.name.equals("pawn") && !flag) {str = str + "pp: ";flag = true;} str = str + p.abbreviation() + p.getSquare().toString(); if (i != blackPieces.size() - 1) str = str + ","; } StringBuffer sb = new StringBuffer(str); if (sb.length() > 80) sb.insert(80,'\n'); str = sb.toString(); return str; } private void printPieceSet(Vector v) { boolean flag = false; sort(v); Enumeration e = v.elements(); while (e.hasMoreElements()) { Piece p = (Piece) e.nextElement(); if (p.name.equals("pawn") && flag == false) {System.out.print("pp: "); flag = true;} System.out.print(p.abbreviation()); System.out.print(p.getSquare().coords()); if (e.hasMoreElements()) System.out.print(","); } System.out.println(); } private void printMoves(Vector v) { //System.out.println("Possible moves in this position: "); int size = v.size(); for (int i = 0; i < size; i++) { if (i != 0 && i%10 == 0) System.out.println(); Move m = (Move) v.elementAt(i); System.out.print(m.toString() + "(" + m.positionalMerit() + ")"); if (i < size - 1) System.out.print(","); } System.out.println(); } public String getTurn() {return turn;} public void setTurn(String t) { turn = t; if (t.equals("white")) {myPieces = whitePieces; enemyPieces = blackPieces;} else {myPieces = blackPieces; enemyPieces = whitePieces;} } public void swapTurn() { if (turn.equals("white")) {turn = "black"; myPieces = blackPieces; enemyPieces = whitePieces;} else if (turn.equals("black")) {turn = "white"; myPieces = whitePieces; enemyPieces = blackPieces;} } //material of the player whose turn it is to move public int myMaterial() { int material = 0; Vector pieces; if (turn.equals("white")) pieces = whitePieces; else pieces = blackPieces; for (int i = 0; i < pieces.size(); i++) { Piece p = (Piece) pieces.elementAt(i); material += p.value(); } return material; } //material of the other player public int enemyMaterial() { int material = 0; Vector pieces; if (turn.equals("white")) pieces = blackPieces; else pieces = whitePieces; for (int i = 0; i < pieces.size(); i++) { Piece p = (Piece) pieces.elementAt(i); material += p.value(); } return material; } //advantage of the player whose turn it is to move; can be positive or negative //returns relative advantage (my material - enemy material)/(smaller of the two) //thus, if the turn changes, this will merely change the sign public double materialAdvantage() { double my = (double) myMaterial(), enemy = (double) enemyMaterial(), min; if (my < enemy) min = my; else min = enemy; //return (my - enemy) / min; return my-enemy; } //sets enpasse to false for all pawns in this Vector of pieces //meaning that they can't now be taken en passe private void removeEnPasse(Vector v) { for (int i = 0; i < v.size(); i++) { Piece p = (Piece) v.elementAt(i); if (p.name.equals("pawn")) p.enpasse = false; } } //checks if the information provided in m is self-consistent /*private boolean checkConsistency(Move m) { //Square srcsqr = m.srcsqr, destsqr = m.destsqr; Piece victpiece = m.victpiece; String transforms = m.transforms; String castle = m.castle; boolean enpasse = m.enpasse; if (m.srcsqr == m.destsqr) return false; if ((m.srcsqr == null) || (m.destsqr == null)) return false; if (m.srcpiece == null) return false; //empty square if ((m.destsqr.piece != null) && (m.srcpiece.owner.equals(dest.piece.owner))) return false; //can't capture piece of the same color return true; } */ /*public boolean checkValidity(Move m) { if ((m.srccol == m.destcol) && (m.srcrow == m.destrow)) return false; if (m.srcpiece == null) return false; //empty square if ((m.destfld.piece != null) && (m.srcpiece.getOwner() == m.destfld.piece.getOwner())) return false; //can't capture piece of the same color if (!m.srcpiece.getOwner().equals(user)) return false; //can't move with the enemy piece return true; } */ //makes an actual change in the position; different from Chess's makeMove() //assumes: m already has all the relevant data members set to their values public Move makeMove(Move m) { //if (!checkConsistency(m)) {return null;} //else {/*System.out.println("making move " + m.toString());*/} m.produceAuxiliaryVariables(this); //update status updateStatusOfPieces(m); //remove victim piece from the vector if (m.victpiece != null) { if (m.victpiece.owner.equals("white")) whitePieces.removeElement(m.victpiece); if (m.victpiece.owner.equals("black")) blackPieces.removeElement(m.victpiece); } //remove victim piece from the board if (m.victpiece != null) m.victsqr.setPiece(null); //if pawn reached the last row, replace it with the new piece if (m.transforms != 0) //pawn turns into queen/rook/bishop/knight { m.srcpiece.transform(m.transforms); } //piece remembers its new square, old and new squares are informed about the change m.srcpiece.putOnSquare(m.destsqr); //if it's a castle, the rook moves as well if (m.castle != 0) { if (m.castle == 1) m.prtnrpiece.putOnSquare(square[6][m.srcrow]); if (m.castle == 2) m.prtnrpiece.putOnSquare(square[4][m.srcrow]); } //remember the move Move mv = new Move(m); moveStack.push(mv); //System.out.println("...done"); //printPosition(); //System.out.println(); swapTurn(); return mv; } public Move goBack() { Piece tp; //temporary piece Move m = (Move) moveStack.pop(); //put the src piece to the original square tp = square[m.destcol][m.destrow].piece; //my piece that moved if (m.transforms != 0) {tp.transform("pawn");} //transform it back to the pawn if needed tp.enpasse = m.srcenpasse; //restore its enpasse status tp.cancastle = m.srccancastle; //restore its cancastle status tp.putOnSquare(square[m.srccol][m.srcrow]); //put it back on original square //and the partner piece, if necessary if (m.castle == 1) { tp = square[6][m.prtnrrow].piece; //the rook can be found on the "f" file tp.putOnSquare(square[8][m.prtnrrow]); //goes back to the "h" file } if (m.castle == 2) { tp = square[4][m.prtnrrow].piece; tp.putOnSquare(square[1][m.prtnrrow]); } //restore the victim piece if (m.victcol != 0 && m.victrow != 0) { Piece p = new Piece(m.victowner,m.victname); p.enpasse = m.victenpasse; //restore victim's enpasse status p.cancastle = m.victcancastle; //restore victim's cancastle status p.putOnSquare(square[m.victcol][m.victrow]); //put it where it was if (p.owner.equals("white")) whitePieces.addElement(p); //and add it to the vector of pieces if (p.owner.equals("black")) blackPieces.addElement(p); } //restore the beneficiary's enpasse status if (m.bencol != 0 && m.benrow != 0) { square[m.bencol][m.benrow].piece.enpasse = true; } //restore the turn that existed before the move swapTurn(); return m; } //assumes the move was already checked and found to be valid but not yet made //updates each piece's status, i.e. right to castle, to be taken en passe private void updateStatusOfPieces(Move m) { //if king or rook has moved, it loses right to castle if (m.srcpiece.name.equals("king") || m.srcpiece.name.equals("rook")) m.srcpiece.cancastle = false; //all remaining enemy pawns lose their enpasse status if (m.srcpiece.owner.equals("white")) //i am white removeEnPasse(blackPieces); else //i am black removeEnPasse(whitePieces); //my moving pawn can also acquire an enpasse status //(if it loses it, this will be taken care of during the enemy's move) if (m.srcpiece.name.equals("pawn")) { if (m.srccol == m.destcol) if ((m.srcrow - m.destrow == 2) || (m.srcrow - m.destrow == -2)) m.srcpiece.enpasse = true; } } public Move findBestMove() { Vector myMoves = findBestMoves(); return findBestMove(myMoves); } public Move findBestMove(Vector myMoves) { if (myMoves == null) return null; System.out.println("Choosing best move from "); printMoves(myMoves); double curEstimate = materialAdvantage(); System.out.println("current position's estimate = " + curEstimate); double maxEstimate = -1000; Move bestMove = (Move) myMoves.elementAt(0); for (int i = 0; i < myMoves.size(); i++) { Move m = (Move) myMoves.elementAt(i); //take one move m.produceAuxiliaryVariables(this); //match its variables with this position Position p = new Position(this,m); //make the new position double estimate = p.estimatePosition(2); //estimate for user since it's now user's turn estimate = -estimate; //estimate for computer if (estimate > maxEstimate) {maxEstimate = estimate;bestMove = m;} System.out.println("move " + m.toString() + ": estimate = " + estimate); } System.out.println("maxEstimate = " + maxEstimate); /////////////////////////////////// Move mv = bestMove; //Move mv = (Move) myMoves.elementAt(0); System.out.println("generated " + mv.toString()); System.out.println("...done"); return mv; } public Vector findBestMoves() { Vector myMoves = possibleMoves(); if (myMoves.size() == 0) return null; //estimate each move for (int i = 0; i < myMoves.size(); i++) { Move m = (Move) myMoves.elementAt(i); //take one move m.produceAuxiliaryVariables(this); //match its variables with this position Position p = new Position(this,m); //make the new position double estimate = p.estimatePosition(1); //estimate for user since it's now user's turn m.estimate = -estimate; //estimate for computer m.estimate += m.positionalMerit(); //add positional component of the move's estimate } //perform bubble sort on myMoves to sort by estimate for (int j = myMoves.size() - 1; j >= 1; j--) { for (int i = 0; i <= j-1; i++) { Move m1 = (Move) myMoves.elementAt(i), m2 = (Move) myMoves.elementAt(i+1); if (m1.estimate < m2.estimate) {myMoves.setElementAt(m1,i+1); myMoves.setElementAt(m2,i);} } } System.out.println("Possible moves: "); printMoves(myMoves); //now best moves are in the beginning of myMoves, discard all others if (myMoves.size() > 5) myMoves.setSize(5); //print the best moves String str = "best moves are: "; for (int k = 0; k < myMoves.size(); k++) { Move m = (Move) myMoves.elementAt(k); str = str + m.toString() + "(" + m.estimate + "), "; } System.out.println(str); return myMoves; } //from the point of view of the player whose turn it is to move public double estimatePosition(int depth) //depth- the number of half-moves { if (depth == 0) return materialAdvantage(); //default way to estimate when I have run out of depth Vector myMoves = possibleMoves(); //possible moves double maxEstimate = -1000; //best "child" position for myself for (int i = 0; i < myMoves.size(); i++) //for each of them { Move m = (Move) myMoves.elementAt(i); //take one move makeMove(m); double estimate = estimatePosition(depth-1); //my opponent's estimate estimate = -estimate; //my estimate if (estimate > maxEstimate) maxEstimate = estimate; //find minimal estimate goBack(); } //now, if the best I can do is to make +2 for my opponent, then it's -2 for me return (maxEstimate); } /*public Move findBestMove(int depth) { Vector myMoves = possibleMoves(); Move curChoice = (Move) myMove.elementAt(0); //default choice double curEstimate = estimate(); //estimate of current position if (depth == 0) return curChoice; for (int i = 0; i < myMoves.size(); i++) { Move m = (Move) myMoves.elementAt(i); Position p = new Position(this,m); //try this move Move best = p.findBestMove(depth-1); //get best response that will follow from this position if (best. } }*/ //returns a vector of moves that are possible in this position public Vector possibleMoves() { Vector myMoves = new Vector(); Vector myPieces = (turn.equals("white")) ? whitePieces : blackPieces; Piece ben = findPotentialBeneficiary(); //for each piece in myPieces for (int i = 0 ; i < myPieces.size(); i++) { Piece p = (Piece) myPieces.elementAt(i); Vector temp = p.possibleMoves(square); //possible moves for this piece for (int j = 0 ; j < temp.size(); j++) { //add each of them to myMoves Move m = (Move)temp.elementAt(j); if (ben != null) {m.bencol = ben.getSquare().col; m.benrow = ben.getSquare().row;} //set the Move's "beneficiary" fields //if (!myKingUnderCheck(m)) myMoves.addElement(m); if (m.buildMoveFromSrcAndDest(this) == true) myMoves.addElement(m); } } if (myMoves.size() == 0) { Square myKingSqr = getMyKing().getSquare(); if (isThreatened(myKingSqr)) checkmate = true; else stalemate = true; //System.out.println("Warning!!! No possible moves in position\n" + toString()); return new Vector(); } return myMoves; } //will this move put my king under check public boolean myKingUnderCheck(Move m) { Vector myPieces = (turn.equals("white")) ? whitePieces : blackPieces; Piece myKing = (Piece) myPieces.elementAt(0); Square myKingSqr = myKing.getSquare(); //1) king is the source piece if (m.srccol == myKingSqr.col && m.srcrow == myKingSqr.row) { if (isThreatened(square[m.destcol][m.destrow])) return true; if (m.castle != 0) { //if castle, check intermediary squares if (PositionAnalysis.noCheckDuringCastle(m,this) == false) return true; } return false; } //king doesn't move else { //do I expose it to check by moving a pinned piece? //that won't happen if the pinned piece captures the attacker Piece attacker = new Piece(); if (isPinned(myKingSqr,square[m.srccol][m.srcrow],attacker)) if (square[m.destcol][m.destrow] != attacker.getSquare()) return true; //is it under check now and my move fails to defend it? if (!isThreatened(myKingSqr)) return false; else //my king is under check, do I fail to defend it? { //System.out.println("findThreateningSquares(" + myKingSqr.toString() + ")"); Vector thrSqs = findThreateningSquares(myKingSqr); if (thrSqs.size() == 2) return true; //no defense from double check Square thrSq = (Square)thrSqs.elementAt(0); //it's a single check if (m.victcol == thrSq.col && m.victrow == thrSq.row) return false; //I capture the threatening piece if (isDefending(square[m.destcol][m.destrow],myKingSqr,thrSq)) return false; //I defended my king return true; } } } //am I under check right now? public boolean myKingUnderCheck() { Move m = (Move) moveStack.peek(); if (m.check) return true; else return false; } //is this square dangerous to my pieces? public boolean isThreatened(Square sq) { for (int i = 0; i < enemyPieces.size(); i++) { Piece p = (Piece) enemyPieces.elementAt(i); Square s = p.getSquare(); //if the enemy piece is on sq itself, it's NOT dangerous //('cause when my piece goes to sq, this enemy piece will be captured) if (s.col == sq.col && s.row == sq.row) continue; if (threatens(s,sq)) return true; } return false; } //is piece on sq1 threatening square sq2? public boolean threatens(Square sq1, Square sq2) { int relloc = Chessboard.relativeLocation(sq1,sq2); if (relloc == Chessboard.NOT_RELATED) return false; if (relloc == Chessboard.SAME_KNIGHT_MOVE && sq1.piece.name.equals("knight")) return true; if (pieceBetween(sq1,sq2,relloc)) return false; //no piece between them, so now threat would be real if ((relloc == Chessboard.SAME_VER || relloc == Chessboard.SAME_HOR) && (sq1.piece.name.equals("rook") || sq1.piece.name.equals("queen"))) return true; if (relloc == Chessboard.SAME_DIAG && (sq1.piece.name.equals("bishop") || sq1.piece.name.equals("queen"))) return true; if (sq1.piece.name.equals("pawn") && Chessboard.withinPawnAttackingRange(sq1,sq2,sq1.piece.owner)) return true; if (sq1.piece.name.equals("king") && Chessboard.withinKingRange(sq1,sq2)) return true; return false; } //will piece given by name when put on sq1 threaten square sq2? public boolean threatens(Square sq1, String name, Square sq2) { int relloc = Chessboard.relativeLocation(sq1,sq2); if (relloc == Chessboard.NOT_RELATED) return false; if (relloc == Chessboard.SAME_KNIGHT_MOVE && name.equals("knight")) return true; //strictly speaking, the very move that I am considering //(when piece "name" moves to sq1) might remove the pieceBetween condition //(i.e. the piece is ALREADY between sq1,sq2), but I neglect this //because if I am ALREADY threatening sq2 then I probably won't //postpone this threat if (pieceBetween(sq1,sq2,relloc)) return false; //no piece between them, so now threat would be real if ((relloc == Chessboard.SAME_VER || relloc == Chessboard.SAME_HOR) && (name.equals("rook") || name.equals("queen"))) return true; if (relloc == Chessboard.SAME_DIAG && (name.equals("bishop") || name.equals("queen"))) return true; //I assume it's the player whose turn it is will put his pawn on sq1 if (name.equals("pawn") && Chessboard.withinPawnAttackingRange(sq1,sq2,turn)) return true; if (name.equals("king") && Chessboard.withinKingRange(sq1,sq2)) return true; return false; } //is piece on sq2 pinned because it defends piece on sq1? //if yes, puts the attacking piece into whoPins public boolean isPinned(Square sq1,Square sq2, Piece whoPins) { int relloc = Chessboard.relativeLocation(sq1,sq2); if (relloc == Chessboard.NOT_RELATED || relloc == Chessboard.SAME_KNIGHT_MOVE) return false; if (pieceBetween(sq1,sq2,relloc)) return false; //can't be pinned 'cause there are pieces in between Square s1,s2; int i,j,incr; if (relloc == Chessboard.SAME_VER) //does anyone threaten s2 from this vertical? { incr = (sq1.row < sq2.row) ? 1 : -1; for (i = sq2.col, j = sq2.row + incr; j >= 1 && j <= 8; j += incr) { Piece p = square[i][j].piece; if (p == null) continue; if (p.owner.equals(sq1.piece.owner)) return false; //encountered my own piece, so there's no pin if (p.name.equals("rook") || p.name.equals("queen")) {whoPins.setSquare(p.getSquare()); return true;} else return false; //any other enemy piece is not dangerous } } if (relloc == Chessboard.SAME_HOR) { incr = (sq1.col < sq2.col) ? 1 : -1; for (i = sq2.col + incr, j = sq2.row; i >= 1 && i <= 8; i += incr) { Piece p = square[i][j].piece; if (p == null) continue; if (p.owner.equals(sq1.piece.owner)) return false; //encountered my own piece, so there's no pin if (p.name.equals("rook") || p.name.equals("queen")) {whoPins.setSquare(p.getSquare()); return true;} else return false; //any other enemy piece is not dangerous } } if (relloc == Chessboard.SAME_DIAG) { incr = (sq1.col < sq2.col) ? 1 : -1; int incr2 = (sq1.row < sq2.row) ? 1 : -1; for (i = sq2.col + incr, j = sq2.row + incr2; i>=1 && i<= 8 && j>=1 && j <= 8; i+=incr, j+=incr2) { Piece p = square[i][j].piece; if (p == null) continue; if (p.owner.equals(sq1.piece.owner)) return false; //encountered my own piece, so there's no pin if (p.name.equals("bishop") || p.name.equals("queen")) {whoPins.setSquare(p.getSquare()); return true;} else return false; //any other enemy piece is not dangerous } } return false; } //Vector of Squares whose pieces threaten Square sq public Vector findThreateningSquares(Square sq) { Vector vectSquares = new Vector(); for (int i = 0; i < enemyPieces.size(); i++) { Piece p = (Piece) enemyPieces.elementAt(i); Square s = p.getSquare(); int relloc = Chessboard.relativeLocation(sq,s); if (relloc == Chessboard.NOT_RELATED) continue; //s doesn't threaten sq - they are not connected by a piece move if (relloc == Chessboard.SAME_KNIGHT_MOVE && p.name.equals("knight")) {vectSquares.addElement(s); continue;} if (pieceBetween(sq,s,relloc)) continue; //s doesn't threaten sq - there is piece between them //no piece between them, so now threat would be real if ((relloc == Chessboard.SAME_VER || relloc == Chessboard.SAME_HOR) && (p.name.equals("rook") || p.name.equals("queen"))) {vectSquares.addElement(s);continue;} if (relloc == Chessboard.SAME_DIAG && (p.name.equals("bishop") || p.name.equals("queen"))) {vectSquares.addElement(s);continue;} if (p.name.equals("pawn") && Chessboard.withinPawnAttackingRange(s,sq,p.owner)) {vectSquares.addElement(s);continue;} if (p.name.equals("king") && Chessboard.withinKingRange(s,sq)) vectSquares.addElement(s); } return vectSquares; } //is defender defending target from attacker? //similar to isPinned(), with the difference that attacker is known //Also, isPinned() tells if "defender" piece is NESESSARY for defence //while isDefending() tells if it is SUFFICIENT for defence //The attack must be real, because I don't check it public boolean isDefending(Square defender, Square target, Square attacker) { ////no defence from enemy knight,pawn, or king if (attacker.piece.name.equals("knight")) return false; if (attacker.piece.name.equals("pawn")) return false; if (attacker.piece.name.equals("king")) return false; //no defence if attacker and target are adjacent if (Chessboard.squaresAdjacent(attacker,target)) return false; //is it a defence from queen,rook, or bishop? if (Chessboard.isBetween(defender,target,attacker)) return true; return false; } //is there a piece between sq1 and sq2, given their relative location? //assumes that sq1 and sq2 are on the same vertical,horizontal, or diagonal public boolean pieceBetween(Square sq1,Square sq2,int relloc) { int i,j; if (relloc == Chessboard.SAME_VER) { for (i = sq1.col, j = Math.min(sq1.row,sq2.row) + 1; j < Math.max(sq1.row,sq2.row); j++) if (square[i][j].piece != null) return true; } if (relloc == Chessboard.SAME_HOR) { for (j = sq1.row, i = Math.min(sq1.col,sq2.col) + 1; i < Math.max(sq1.col,sq2.col); i++) if (square[i][j].piece!= null) return true; } if (relloc == Chessboard.SAME_DIAG) { Square s1,s2; //s1 = "left" square, s2 = "right" square if (sq1.col < sq2.col) {s1=sq1; s2=sq2;} else {s1=sq2; s2=sq1;} i = s1.col; j = s1.row; int incr = (Chessboard.diagDetails(sq1,sq2) == Chessboard.DIAG_SLASH) ? 1 : -1; for (i = s1.col + 1, j = s1.row + incr; i < s2.col; i++,j+=incr) if (square[i][j].piece != null) return true; } return false; } //find an enemy pawn that has its enpasse flag set //it will be the beneficiary of my next move if I don't capture it private Piece findPotentialBeneficiary() { Vector enemyPieces = (turn.equals("white")) ? blackPieces : whitePieces; for (int i = 0; i < enemyPieces.size(); i++) { Piece p = (Piece)enemyPieces.elementAt(i); if (p.name.equals("pawn") && p.enpasse == true) return p; } return null; } }