📄 jcboard.java
字号:
HasCastled[ 0 ] = target.HasCastled[ 0 ]; HasCastled[ 1 ] = target.HasCastled[ 1 ]; CurrentPlayer = target.CurrentPlayer; return true; } // public boolean Print // Display the board on standard output public boolean Print() { for( int line = 0; line < 8; line++ ) { System.out.println( "-----------------------------------------" ); System.out.println( "| | | | | | | | |" ); for( int col = 0; col < 8; col++ ) { long bits = SquareBits[ line * 8 + col ]; // Scan the bitboards to find a piece, if any int piece = 0; while ( ( piece < ALL_PIECES ) && ( ( bits & BitBoards[ piece ] ) == 0 ) ) piece++; // One exception: don't show the "phantom kings" which the program places // on the board to detect illegal attempts at castling over an attacked // square if ( ( piece == BLACK_KING ) && ( ( ExtraKings[ jcPlayer.SIDE_BLACK ] & SquareBits[ line * 8 + col ] ) != 0 ) ) piece = EMPTY_SQUARE; if ( ( piece == WHITE_KING ) && ( ( ExtraKings[ jcPlayer.SIDE_WHITE ] & SquareBits[ line * 8 + col ] ) != 0 ) ) piece = EMPTY_SQUARE; // Show the piece System.out.print( "| " + PieceStrings[ piece ] + " " ); } System.out.println( "|" ); System.out.println( "| | | | | | | | |" ); } System.out.println( "-----------------------------------------" ); if ( CurrentPlayer == jcPlayer.SIDE_BLACK ) System.out.println( "NEXT MOVE: BLACK "); else System.out.println( "NEXT MOVE: WHITE" ); return true; } // public int SwitchSides // Change the identity of the player to move public int SwitchSides() { if ( CurrentPlayer == jcPlayer.SIDE_WHITE ) SetCurrentPlayer( jcPlayer.SIDE_BLACK ); else SetCurrentPlayer( jcPlayer.SIDE_WHITE ); return CurrentPlayer; } // public int HashKey // Compute a 32-bit integer to represent the board, according to Zobrist[70] public int HashKey() { int hash = 0; // Look at all pieces, one at a time for( int currPiece = 0; currPiece < ALL_PIECES; currPiece++ ) { long tmp = BitBoards[ currPiece ]; // Search for all pieces on all squares. We could optimize here: not // looking for pawns on the back row (or the eight row), getting out // of the "currSqaure" loop once we found one king of one color, etc. // But for simplicity's sake, we'll keep things generic. for( int currSquare = 0; currSquare < ALL_SQUARES; currSquare++ ) { // Zobrist's method: generate a bunch of random bitfields, each // representing a certain "piece X is on square Y" predicate; XOR // the bitfields associated with predicates which are true. // Therefore, if we find a piece (in tmp) in a certain square, // we accumulate the related HashKeyComponent. if ( ( tmp & SquareBits[ currSquare ] ) != 0 ) hash ^= HashKeyComponents[ currPiece ][ currSquare ]; } } return hash; } // public int HashLock // Compute a second 32-bit hash key, using an entirely different set // piece/square components. // This is required to be able to detect hashing collisions without // storing an entire jcBoard in each slot of the jcTranspositionTable, // which would gobble up inordinate amounts of memory public int HashLock() { int hash = 0; for( int currPiece = 0; currPiece < ALL_PIECES; currPiece++ ) { long tmp = BitBoards[ currPiece ]; for( int currSquare = 0; currSquare < ALL_SQUARES; currSquare++ ) { if ( ( tmp & SquareBits[ currSquare ] ) != 0 ) hash ^= HashLockComponents[ currPiece ][ currSquare ]; } } return hash; } // public boolean ApplyMove // Change the jcBoard's internal representation to reflect the move // received as a parameter public boolean ApplyMove( jcMove theMove ) { // If the move includes a pawn promotion, an extra step will be required // at the end boolean isPromotion = ( theMove.MoveType >= jcMove.MOVE_PROMOTION_KNIGHT ); int moveWithoutPromotion = ( theMove.MoveType & jcMove.NO_PROMOTION_MASK ); int side = theMove.MovingPiece % 2; // For now, ignore pawn promotions switch( moveWithoutPromotion ) { case jcMove.MOVE_NORMAL: // The simple case RemovePiece( theMove.SourceSquare, theMove.MovingPiece ); AddPiece( theMove.DestinationSquare, theMove.MovingPiece ); break; case jcMove.MOVE_CAPTURE_ORDINARY: // Don't forget to remove the captured piece! RemovePiece( theMove.SourceSquare, theMove.MovingPiece ); RemovePiece( theMove.DestinationSquare, theMove.CapturedPiece ); AddPiece( theMove.DestinationSquare, theMove.MovingPiece ); break; case jcMove.MOVE_CAPTURE_EN_PASSANT: // Here, we can use our knowledge of the board to make a small // optimization, since the pawn to be captured is always // "behind" the moving pawn's destination square, we can compute its // position on the fly RemovePiece( theMove.SourceSquare, theMove.MovingPiece ); AddPiece( theMove.DestinationSquare, theMove.MovingPiece ); if ( ( theMove.MovingPiece % 2 ) == jcPlayer.SIDE_WHITE ) RemovePiece( theMove.DestinationSquare + 8, theMove.CapturedPiece ); else RemovePiece( theMove.DestinationSquare - 8, theMove.CapturedPiece ); break; case jcMove.MOVE_CASTLING_QUEENSIDE: // Again, we can compute the rook's source and destination squares // because of our knowledge of the board's structure RemovePiece( theMove.SourceSquare, theMove.MovingPiece ); AddPiece( theMove.DestinationSquare, theMove.MovingPiece ); int theRook = ROOK + ( theMove.MovingPiece % 2 ); RemovePiece( theMove.SourceSquare - 4, theRook ); AddPiece( theMove.SourceSquare - 1, theRook ); // We must now mark some squares as containing "phantom kings" so that // the castling can be cancelled by the next opponent's move, if he // can move to one of them if ( side == jcPlayer.SIDE_WHITE ) { SetExtraKings( side, EXTRAKINGS_WHITE_QUEENSIDE ); } else { SetExtraKings( side, EXTRAKINGS_BLACK_QUEENSIDE ); } HasCastled[ side ] = true; break; case jcMove.MOVE_CASTLING_KINGSIDE: // Again, we can compute the rook's source and destination squares // because of our knowledge of the board's structure RemovePiece( theMove.SourceSquare, theMove.MovingPiece ); AddPiece( theMove.DestinationSquare, theMove.MovingPiece ); theRook = ROOK + ( theMove.MovingPiece % 2 ); RemovePiece( theMove.SourceSquare + 3, theRook ); AddPiece( theMove.SourceSquare + 1, theRook ); // We must now mark some squares as containing "phantom kings" so that // the castling can be cancelled by the next opponent's move, if he // can move to one of them if ( side == jcPlayer.SIDE_WHITE ) { SetExtraKings( side, EXTRAKINGS_WHITE_KINGSIDE ); } else { SetExtraKings( side, EXTRAKINGS_BLACK_KINGSIDE ); } HasCastled[ side ] = true; break; case jcMove.MOVE_RESIGN: // FDL Later, ask the AI player who resigned to print the continuation break; case jcMove.MOVE_STALEMATE: System.out.println( "Stalemate - Game is a draw." ); break; } // And now, apply the promotion if ( isPromotion ) { int promotionType = ( theMove.MoveType & jcMove.PROMOTION_MASK ); int color = ( theMove.MovingPiece % 2 ); switch( promotionType ) { case jcMove.MOVE_PROMOTION_KNIGHT: RemovePiece( theMove.DestinationSquare, theMove.MovingPiece ); AddPiece( theMove.DestinationSquare, KNIGHT + color ); break; case jcMove.MOVE_PROMOTION_BISHOP: RemovePiece( theMove.DestinationSquare, theMove.MovingPiece ); AddPiece( theMove.DestinationSquare, BISHOP + color ); break; case jcMove.MOVE_PROMOTION_ROOK: RemovePiece( theMove.DestinationSquare, theMove.MovingPiece ); AddPiece( theMove.DestinationSquare, ROOK + color ); break; case jcMove.MOVE_PROMOTION_QUEEN: RemovePiece( theMove.DestinationSquare, theMove.MovingPiece ); AddPiece( theMove.DestinationSquare, QUEEN + color ); break; } } // If this was a 2-step pawn move, we now have a valid en passant // capture possibility. Otherwise, no. if ( ( theMove.MovingPiece == jcBoard.WHITE_PAWN ) && ( theMove.SourceSquare - theMove.DestinationSquare == 16 ) ) SetEnPassantPawn( theMove.DestinationSquare + 8 ); else if ( ( theMove.MovingPiece == jcBoard.BLACK_PAWN ) && ( theMove.DestinationSquare - theMove.SourceSquare == 16 ) ) SetEnPassantPawn( theMove.SourceSquare + 8 ); else ClearEnPassantPawn(); // And now, maintain castling status // If a king moves, castling becomes impossible for that side, for the // rest of the game switch( theMove.MovingPiece ) { case WHITE_KING: SetCastlingStatus( CASTLE_KINGSIDE + jcPlayer.SIDE_WHITE, false ); SetCastlingStatus( CASTLE_QUEENSIDE + jcPlayer.SIDE_WHITE, false ); break; case BLACK_KING: SetCastlingStatus( CASTLE_KINGSIDE + jcPlayer.SIDE_BLACK, false ); SetCastlingStatus( CASTLE_QUEENSIDE + jcPlayer.SIDE_BLACK, false ); break; default: break; } // Or, if ANYTHING moves from a corner, castling becomes impossible on // that side (either because it's the rook that is moving, or because // it has been captured by whatever moves, or because it is already gone) switch( theMove.SourceSquare ) { case 0: SetCastlingStatus( CASTLE_QUEENSIDE + jcPlayer.SIDE_BLACK, false ); break; case 7: SetCastlingStatus( CASTLE_KINGSIDE + jcPlayer.SIDE_BLACK, false ); break; case 56: SetCastlingStatus( CASTLE_QUEENSIDE + jcPlayer.SIDE_WHITE, false ); break; case 63: SetCastlingStatus( CASTLE_KINGSIDE + jcPlayer.SIDE_WHITE, false ); break; default: break; } // All that remains to do is switch sides SetCurrentPlayer( ( GetCurrentPlayer() + 1 ) % 2 ); return true; } // public boolean Load // Load a board from a file public boolean Load( String fileName ) throws Exception { // Clean the board first EmptyBoard(); // Open the file as a Java tokenizer FileReader fr = new FileReader( fileName ); StreamTokenizer tok = new StreamTokenizer( fr ); tok.eolIsSignificant( false ); tok.lowerCaseMode( false ); // Whose turn is it to play? tok.nextToken(); if ( tok.sval.equalsIgnoreCase( jcPlayer.PlayerStrings[ jcPlayer.SIDE_WHITE ] ) ) SetCurrentPlayer( jcPlayer.SIDE_WHITE ); else SetCurrentPlayer( jcPlayer.SIDE_BLACK ); // Read the positions of all the pieces
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -