package minechess.common.ai; import java.util.List; import minechess.common.EntityBaseChessPiece; import minechess.common.EntityBishop; import minechess.common.EntityKing; import minechess.common.EntityKnight; import minechess.common.EntityPawn; import minechess.common.EntityQueen; import minechess.common.EntityRook; import net.minecraft.nbt.NBTTagCompound; /** * MineChess * @author MineMaarten * www.minemaarten.com * @license Lesser GNU Public License v3 (http://www.gnu.org/licenses/lgpl.html) * * This class came from pate's ChessMate, found at https://github.com/pate/chessmate. Many thanks to him for allowing * the usage of his code by others. These classes are a bit modified to be able to have more AI's running at the same time. */ public class ChessPosition{ final static public int BLANK = 0; final static public int PAWN = 1; final static public int KNIGHT = 2; final static public int BISHOP = 3; final static public int ROOK = 4; final static public int QUEEN = 5; final static public int KING = 6; /** * An array of board squares. */ public int[] board = new int[80]; /** * Stores the index of pieces on the board. Exists for faster move generation. */ // public Vector pieces = new Vector(); boolean bWhiteKingMoved = false; boolean bBlackKingMoved = false; boolean bWhiteChecked = false; boolean bBlackChecked = false; int enPassantSquare = 0; private boolean isBlackTurn; /** * Applies the given move parameter to the board position saved in this instance of the class. */ public void makeMove(ChessMove move){ /* pieces.remove(move.from); if ( !pieces.contains( new Integer(move.to) ) ) pieces.add( new Integer(move.to) ); pieces.set( pieces.indexOf( new Integer(move.from)) , new Integer(move.to) ); */ board[move.to] = board[move.from]; board[move.from] = 0; if(move.to >= 70) { if(board[move.to] == PAWN) board[move.to] = QUEEN; } else if(move.to < 8) { if(board[move.to] == -PAWN) board[move.to] = -QUEEN; } else if(board[move.to] == KING && !bWhiteKingMoved) { bWhiteKingMoved = true; } else if(board[move.to] == -KING && !bBlackKingMoved) { bBlackKingMoved = true; }// else /* if ( enPassantSquare > 0 ) { if ( board[ move.to ] == PAWN && move.to-10 == enPassantSquare ) { board[move.to-10] = 0; enPassantSquare = 0; } else if ( board[ move.to ] == -PAWN && move.to+10 == enPassantSquare ) { board[move.to+10] = 0; enPassantSquare = 0; } }*/ } /** * Instantiates the board position by mirroring another board position. * Used extensively during alpha-beta search. */ public ChessPosition(ChessPosition p){ System.arraycopy(p.board, 0, board, 0, 80); //eval = p.eval; bWhiteKingMoved = p.bWhiteKingMoved; bBlackKingMoved = p.bBlackKingMoved; bWhiteChecked = p.bWhiteChecked; bBlackChecked = p.bBlackChecked; isBlackTurn = p.isBlackTurn; } /** * Constructs an empty chess board. */ public ChessPosition(){} public ChessPosition(EntityBaseChessPiece entityPiece){ List<EntityBaseChessPiece> pieces = entityPiece.getChessPieces(true); for(EntityBaseChessPiece piece : pieces) { int pieceValue = 0; if(piece instanceof EntityPawn) pieceValue = PAWN; else if(piece instanceof EntityBishop) pieceValue = BISHOP; else if(piece instanceof EntityKnight) pieceValue = KNIGHT; else if(piece instanceof EntityRook) pieceValue = ROOK; else if(piece instanceof EntityKing) { pieceValue = KING; if(!piece.firstMove) { if(piece.isBlack()) { bBlackKingMoved = true; } else { bWhiteKingMoved = true; } } } else if(piece instanceof EntityQueen) pieceValue = QUEEN; if(piece.targetX + piece.targetZ * 10 < board.length) board[piece.targetX + piece.targetZ * 10] = piece.isBlack() ? -pieceValue : pieceValue; isBlackTurn = piece.isBlackTurn; } for(int i = 0; i < 8; i++) { board[i * 10 + 8] = 7; board[i * 10 + 9] = 7; } } public void printBoard(){ for(int i = 0; i < 80; i++) { System.out.print("[" + board[i] + "] "); if(i % 10 == 9) System.out.println(); } } public void writeToNBT(NBTTagCompound tag){ for(int i = 0; i < board.length; i++) { tag.setInteger("tile" + i, board[i]); } tag.setBoolean("blackChecked", bBlackChecked); tag.setBoolean("blackKingMoved", bBlackKingMoved); tag.setBoolean("whiteChecked", bWhiteChecked); tag.setBoolean("whiteKingMoved", bWhiteKingMoved); tag.setByte("enPassantSquare", (byte)enPassantSquare); tag.setBoolean("isBlackTurn", isBlackTurn); } public void readFromNBT(NBTTagCompound tag){ for(int i = 0; i < board.length; i++) { board[i] = tag.getInteger("tile" + i); } bBlackChecked = tag.getBoolean("blackChecked"); bBlackKingMoved = tag.getBoolean("blackKingMoved"); bWhiteChecked = tag.getBoolean("whiteChecked"); bWhiteKingMoved = tag.getBoolean("whiteKingMoved"); enPassantSquare = tag.getByte("enPassantSquare"); isBlackTurn = tag.getBoolean("isBlackTurn"); } /** * Returns true if the pieces are at the same place as the comparison, and when the piece movement booleans are the same. * @param compare * @return */ public boolean isSame(ChessPosition compare){ for(int i = 0; i < board.length; i++) { if(board[i] != compare.board[i]) return false; } if(bBlackChecked != compare.bBlackChecked) return false; if(bBlackKingMoved != compare.bBlackKingMoved) return false; if(bWhiteChecked != compare.bWhiteChecked) return false; if(bWhiteKingMoved != compare.bWhiteKingMoved) return false; if(enPassantSquare != compare.enPassantSquare) return false; if(isBlackTurn != compare.isBlackTurn) return false; return true; } /** * Returns true when the given position has a difference in active pieces from this position (unreproducable moves, e.g. pawns moved) * @param compare * @return */ public boolean hasActiveDifference(ChessPosition compare){ //check for pawn change and captures int thisPieceCount = 0; int comparePieceCount = 0; for(int i = 0; i < board.length; i++) { if(board[i] == 1 && compare.board[i] != 1) return true; if(board[i] == -1 && compare.board[i] != -1) return true; if(board[i] != 0) thisPieceCount++; if(compare.board[i] != 0) comparePieceCount++; } if(thisPieceCount != comparePieceCount) return true; return false; } }