position.java

来自「J2ME编写的完整国际象棋程序」· Java 代码 · 共 1,200 行 · 第 1/3 页

JAVA
1,200
字号
	}

	public void addPiece(int sq, int pc) {
		addPiece(sq, pc, false);
	}

	public void delPiece(int sq, int pc) {
		addPiece(sq, pc, true);
	}

	/* A - Take out Captured Piece (Different in En-Passant, see A-EP)
	 * B - Remove Source
	 * C - Add into Destination (Different in Promotion, see C-P)
	 * D - for Castling only
	 */
	public void movePiece() {
		int sqSrc = SRC(mvList[moveNum]);
		int sqDst = DST(mvList[moveNum]);
		int pcCaptured = squares[sqDst];
		if (pcCaptured > 0) {
			delPiece(sqDst, pcCaptured); // A
		}
		int pc = squares[sqSrc];
		// __ASSERT((pcCaptured & SIDE_TAG(sdPlayer)) == 0);
		// __ASSERT((pc & SIDE_TAG(sdPlayer)) != 0);
		delPiece(sqSrc, pc); // B
		addPiece(sqDst, pc); // C
		pcList[moveNum] = pcCaptured;
		specialMoveList[moveNum] = false;
		castlingBitsList[moveNum] = castlingBits();
		sqEnPassantList[moveNum] = 0;
		// CASTLING -> Set Castling Bits for Rook's Capture
		if (PIECE_TYPE(pcCaptured) == PIECE_ROOK) {
			int castling = (1 - sdPlayer) << 1;
			if (sqDst == CASTLING_ROOK_SRC[castling]) {
				castlingBitsList[moveNum] &= ~(1 << castling);
			} else if (sqDst == CASTLING_ROOK_SRC[castling + 1]) {
				castlingBitsList[moveNum] &= ~(1 << (castling + 1));
			}
		}
		if (PIECE_TYPE(pc) == PIECE_KING) {
			// CASTLING -> Move both King and Rook
			if (!KING_SPAN(sqSrc, sqDst)) {
				int castling = CASTLING_TYPE(sdPlayer, sqSrc, sqDst);
				delPiece(CASTLING_ROOK_SRC[castling], pc - PIECE_KING + PIECE_ROOK); // D
				addPiece(CASTLING_ROOK_DST[castling], pc - PIECE_KING + PIECE_ROOK); // D
				specialMoveList[moveNum] = true;
			}
			// CASTLING -> Set Castling Bits for King's Move
			castlingBitsList[moveNum] &= ~(3 << (sdPlayer << 1));
		} else if (PIECE_TYPE(pc) == PIECE_PAWN) {
			if (PAWN_PROMOTION(sqDst, sdPlayer)) {
				// PROMOTION -> Add a Queen instead of a Pawn
				delPiece(sqDst, pc); // C-P
				addPiece(sqDst, pc - PIECE_PAWN + PIECE_QUEEN); // C-P
				specialMoveList[moveNum] = true;
			} else if (sqDst == enPassantSquare()) {
				// EN-PASSANT -> Reset the Captured Piece for En-Passant Move
				int sqCaptured = sqDst - FORWARD_DELTA(sdPlayer);
				pcCaptured = squares[sqCaptured];
				// __ASSERT(sqSrc == sqCaptured + 1 || sqSrc == sqCaptured - 1);
				// __ASSERT(pcCaptured == OPP_SIDE_TAG(sdPlayer) + PIECE_PAWN);
				delPiece(sqCaptured, pcCaptured); // A-EP
				pcList[moveNum] = pcCaptured;
				specialMoveList[moveNum] = true;
			} else {
				// EN-PASSANT -> Set En-Passant Square for Pawn's Double-Move
				int delta = FORWARD_DELTA(sdPlayer);
				if (sqDst == sqSrc + (delta << 1)) {
					sqEnPassantList[moveNum] = sqSrc + delta;
				}
			}
		} else if (PIECE_TYPE(pc) == PIECE_ROOK) {
			// CASTLING -> Set Castling Bits for Rook's Move
			int castling = sdPlayer << 1;
			if (sqSrc == CASTLING_ROOK_SRC[castling]) {
				castlingBitsList[moveNum] &= ~(1 << castling);
			} else if (sqSrc == CASTLING_ROOK_SRC[castling + 1]) {
				castlingBitsList[moveNum] &= ~(1 << (castling + 1));
			}
		}
	}

	/* A - Return Captured Piece (Different in En-Passant, see A-EP)
	 * B - Add into Source (Different in Promotion, see B-P)
	 * C - Remove Destination
	 * D - for Castling only
	 */
	public void undoMovePiece() {
		int sqSrc = SRC(mvList[moveNum]);
		int sqDst = DST(mvList[moveNum]);
		int pc = squares[sqDst];
		// __ASSERT((pcList[moveNum] & SIDE_TAG(sdPlayer)) == 0);
		// __ASSERT((pc & SIDE_TAG(sdPlayer)) != 0);
		delPiece(sqDst, pc); // C
		addPiece(sqSrc, pc); // B
		if (pcList[moveNum] > 0) {
			addPiece(sqDst, pcList[moveNum]); // A
		}
		if (specialMoveList[moveNum]) {
			if (PIECE_TYPE(pc) == PIECE_KING) {
				// CASTLING -> Move both King and Rook
				int castling = CASTLING_TYPE(sdPlayer, sqSrc, sqDst);
				// __ASSERT((castlingBits() & (1 << castling)) != 0);
				// __ASSERT(squares[CASTLING_ROOK_DST[castling]] == SIDE_TAG(sdPlayer) + PIECE_ROOK);
				// __ASSERT(squares[CASTLING_ROOK_SRC[castling]] == 0);
				delPiece(CASTLING_ROOK_DST[castling], pc - PIECE_KING + PIECE_ROOK); // D
				addPiece(CASTLING_ROOK_SRC[castling], pc - PIECE_KING + PIECE_ROOK); // D
			} else if (PAWN_PROMOTION(sqDst, sdPlayer)) {
				// PROMOTION -> Add a Pawn instead of a Queen
				// __ASSERT(pc == SIDE_TAG(sdPlayer) + PIECE_QUEEN);
				delPiece(sqSrc, pc); // B-P
				addPiece(sqSrc, pc - PIECE_QUEEN + PIECE_PAWN); // B-P
			} else {
				// __ASSERT(sqDst == enPassantSquare());
				// EN-PASSANT -> Adjust the Captured Pawn
				// __ASSERT(pcList[moveNum] == OPP_SIDE_TAG(sdPlayer) + PIECE_PAWN);
				delPiece(sqDst, pcList[moveNum]); // A-EP
				addPiece(sqDst - FORWARD_DELTA(sdPlayer), pcList[moveNum]); // A-EP
			}
		}
	}

	public void changeSide() {
		sdPlayer = 1 - sdPlayer;
		zobristKey ^= PreGen_zobristKeyPlayer;
		zobristLock ^= PreGen_zobristLockPlayer;
	}

	public boolean makeMove(int mv) {
		keyList[moveNum] = zobristKey;
		mvList[moveNum] = mv;
		movePiece();
		if (checked()) {
			undoMovePiece();
			return false;
		}
		changeSide();
		chkList[moveNum] = checked();
		moveNum ++;
		distance ++;
		return true;
	}

	public void undoMakeMove() {
		moveNum --;
		distance --;
		changeSide();
		undoMovePiece();
	}

	public void nullMove() {
		keyList[moveNum] = zobristKey;
		changeSide();
		mvList[moveNum] = pcList[moveNum] = sqEnPassantList[moveNum] = 0;
		chkList[moveNum] = specialMoveList[moveNum] = false;
		castlingBitsList[moveNum] = castlingBits();
		moveNum ++;
		distance ++;
	}

	public void undoNullMove() {
		moveNum --;
		distance --;
		changeSide();
	}

	public int fenPiece(char c) {
		switch (c) {
		case 'K':
			return PIECE_KING;
		case 'Q':
			return PIECE_QUEEN;
		case 'R':
			return PIECE_ROOK;
		case 'B':
			return PIECE_BISHOP;
		case 'N':
			return PIECE_KNIGHT;
		case 'P':
			return PIECE_PAWN;
		default:
			return -1;
		}
	}

	public void fromFen(String fen) {
		clearBoard();
		int y = RANK_TOP;
		int x = FILE_LEFT;
		int index = 0;
		if (index == fen.length()) {
			setIrrev(0, 0);
			return;
		}
		char c = fen.charAt(index);
		while (c != ' ') {
			if (c == '/') {
				x = FILE_LEFT;
				y ++;
				if (y > RANK_BOTTOM) {
					break;
				}
			} else if (c >= '1' && c <= '9') {
				for (int k = 0; k < (c - '0'); k ++) {
					if (x >= FILE_RIGHT) {
						break;
					}
					x ++;
				}
			} else if (c >= 'A' && c <= 'Z') {
				if (x <= FILE_RIGHT) {
					if (c != 'P' || (y != RANK_TOP && y != RANK_BOTTOM)) {
						int pt = fenPiece(c);
						if (pt >= 0) {
							addPiece(COORD_XY(x, y), pt + 8);
						}
					}
					x ++;
				}
			} else if (c >= 'a' && c <= 'z') {
				if (x <= FILE_RIGHT) {
					if (c != 'p' || (y != RANK_TOP && y != RANK_BOTTOM)) {
						int pt = fenPiece((char) (c + 'A' - 'a'));
						if (pt >= 0) {
							addPiece(COORD_XY(x, y), pt + 16);
						}
					}
					x ++;
				}
			}
			index ++;
			if (index == fen.length()) {
				setIrrev(0, 0);
				return;
			}
			c = fen.charAt(index);
		}
		index ++;
		if (index == fen.length()) {
			setIrrev(0, 0);
			return;
		}
		if (sdPlayer == (fen.charAt(index) == 'b' ? 0 : 1)) {
			changeSide();
		}
		index ++; // Skip a ' '
		if (index == fen.length()) {
			setIrrev(0, 0);
			return;
		}
		int castlingBits = 0;
		index ++;
		if (index == fen.length()) {
			setIrrev(0, 0);
			return;
		}
		c = fen.charAt(index);
		while (c != ' ') {
			switch (c) {
			case 'K':
				if (squares[0x78] == 8 && squares[0x7b] == 10) {
					castlingBits += 1;
				}
				break;
			case 'Q':
				if (squares[0x78] == 8 && squares[0x74] == 10) {
					castlingBits += 2;
				}
				break;
			case 'k':
				if (squares[0x08] == 16 && squares[0x0b] == 18) {
					castlingBits += 4;
				}
				break;
			case 'q':
				if (squares[0x08] == 16 && squares[0x04] == 18) {
					castlingBits += 8;
				}
				break;
			}
			index ++;
			if (index == fen.length()) {
				setIrrev(castlingBits, 0);
				return;
			}
			c = fen.charAt(index);
		}
		int sqEnPassant = PARSE_COORD(fen, index + 1);
		if (sqEnPassant > 0 && PAWN_EN_PASSANT(sqEnPassant, sdPlayer) &&
				squares[sqEnPassant - FORWARD_DELTA(sdPlayer)] > 0) {
			setIrrev(castlingBits, sqEnPassant);
		} else {
			setIrrev(castlingBits, 0);
		}
	}

	public static final String FEN_PIECE = "        KQRBNP  kqrbnp  ";
	public static final String CASTLING_CHAR = "KQkq";

	public String toFen() {
		StringBuffer fen = new StringBuffer();
		for (int y = RANK_TOP; y <= RANK_BOTTOM; y ++) {
			int k = 0;
			for (int x = FILE_LEFT; x <= FILE_RIGHT; x ++) {
				int pc = squares[COORD_XY(x, y)];
				if (pc > 0) {
					if (k > 0) {
						fen.append((char) ('0' + k));
						k = 0;
					}
					fen.append(FEN_PIECE.charAt(pc));
				} else {
					k ++;
				}
			}
		    if (k > 0) {
				fen.append((char) ('0' + k));
		    }
		    fen.append('/');
		}
		fen.setCharAt(fen.length() - 1, ' ');
		fen.append(sdPlayer == 0 ? 'w' : 'b');
		fen.append(' ');
		int castlingBits = castlingBits();
		if (castlingBits == 0) {
			fen.append('-');
		} else {
			for (int castling = 0; castling < 4; castling ++) {
				if ((castlingBits & (1 << castling)) != 0) {
					fen.append(CASTLING_CHAR.charAt(castling));
				}
			}
		}
		fen.append(' ');
		fen.append(enPassantSquare() > 0 ? SQUARE_STR(enPassantSquare()) : "-");
		return fen.toString();
	}

	public int generateAllMoves(int[] mvs) {
		return generateMoves(mvs, null);
	}

	public int generateMoves(int[] mvs, int[] vls) {
		int moves = 0;
		int pcSelfSide = SIDE_TAG(sdPlayer);
		int pcOppSide = OPP_SIDE_TAG(sdPlayer);
		// CASTLING -> Begin Generating Castling Moves
		if (vls == null) {
			for (int i = 0; i < 2; i ++) {
				int castling = (sdPlayer << 1) + i;
				if (canCastling(castling)) {
					mvs[moves] = MOVE(CASTLING_KING_SRC[castling], CASTLING_KING_DST[castling]);
					moves ++;
				}
			}
		}
		// CASTLING -> End Generating Castling Moves
		for (int sqSrc = 0; sqSrc < 128; sqSrc ++) {
			int pcSrc = squares[sqSrc];
			if ((pcSrc & pcSelfSide) == 0) {
				continue;
			}
			switch (pcSrc - pcSelfSide) {
			case PIECE_KING:
				for (int i = 0; i < 8; i ++) {
					int sqDst = sqSrc + KING_DELTA[i];
					if (!IN_BOARD(sqDst)) {
						continue;
					}
					int pcDst = squares[sqDst];
					if (vls == null) {
						if ((pcDst & pcSelfSide) == 0) {
							mvs[moves] = MOVE(sqSrc, sqDst);
							moves ++;
						}
					} else if ((pcDst & pcOppSide) != 0) {
						mvs[moves] = MOVE(sqSrc, sqDst);
						vls[moves] = MVV_LVA(pcDst, 99);
						moves ++;
					}
				}
				break;
			case PIECE_QUEEN:
				for (int i = 0; i < 8; i ++) {
					int delta = KING_DELTA[i];
					int sqDst = sqSrc + delta;
					while (IN_BOARD(sqDst)) {
						int pcDst = squares[sqDst];
						if (pcDst == 0) {
							if (vls == null) {
								mvs[moves] = MOVE(sqSrc, sqDst);
								moves ++;
							}
						} else {
							if ((pcDst & pcOppSide) != 0) {
								mvs[moves] = MOVE(sqSrc, sqDst);
								if (vls != null) {
									vls[moves] = MVV_LVA(pcDst, 9);
								}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?