Una biblioteca chess engine sin dependencias creada para ejecutarse en cualquier lugar.
¿Escrito en Rust?
Sobre todo, este vídeo de Tom7 es mi inspiración para este proyecto. Es absolutamente brillante y te imploro que mires su contenido.
Amo mucho el ajedrez. Definitivamente es uno de mis juegos favoritos. Sin embargo, siempre me ha decepcionado intentar escribir programas que jueguen ajedrez digitalmente (particularmente en un lenguaje compilado). Aunque existen varios motores sorprendentes, es casi imposible encontrar una biblioteca ordenada para programación relacionada con el ajedrez que se ejecute en todo.
El motor de ajedrez es una solución a mi problema. Si desea un chess engine que se ejecute en dispositivos integrados, la terminal, el escritorio (con una interfaz gráfica de usuario) y la web, esta es probablemente su mejor opción.
Esta IA en particular (junto con la mayoría de las otras IA de ajedrez) funciona utilizando el algoritmo Minimax, junto con la poda Alfa-Beta para optimización.
Ahora, analicemos eso.
Básicamente, el algoritmo Minimax recorre en iteración todos los movimientos posibles de forma recursiva y evalúa todos los tableros después de realizar los movimientos. Si el tablero es más favorable, alentará a realizar su movimiento principal, pero si un tablero es menos favorable, optará por no realizar un movimiento determinado.
Además, cuando la IA intenta ver más allá del tablero actual, asumirá que el humano siempre responde con los mejores movimientos. Como resultado, la computadora casi nunca comete errores. Esto permite que la computadora casi siempre realice movimientos objetivamente mejores que el jugador.
Debido a que no tiene dependencias, es extremadamente sencillo incrustarlo en el navegador web usando wasm. ¡Intenta jugarlo tú mismo!
Configuración promedio de IA
La estructura Board
tiene algunos métodos diferentes que permiten a los usuarios generar movimientos desde una posición determinada, incluidos get_best_next_move
, get_worst_next_move
y get_legal_moves
. Estos son particularmente útiles para escribir IA de ajedrez contra las cuales jugar.
fn main ( ) {
let board = Board :: default ( ) ;
// Get the best move with 4 moves of lookahead
let best_move = board . get_best_next_move ( 4 ) ;
// Get the worst move with 3 moves of lookahead
let worst_move = board . get_worst_next_move ( 3 ) ;
// Get all of the possible legal moves for the given player
let legal_moves = board . get_legal_moves ( ) ;
// Print the board
println ! ( "{}" , board ) ;
print ! ( "CPU chose to " ) ;
match best_move {
Move :: Piece ( from , to ) => println ! ( "move {} to {}" , from, to ) ,
Move :: KingSideCastle => println ! ( "castle kingside" ) ,
Move :: QueenSideCastle => println ! ( "castle queenside" ) ,
Move :: Resign => println ! ( "resign" )
}
}
Para agregar alguna variación o un juego más avanzado, considere escribir una IA que juegue aperturas conocidas que construyan mejores posiciones antes de usar el método get_best_next_move
.
Además, los usuarios pueden crear sus propios objetos Board
personalizados además del predeterminado. Esto se hace utilizando la estructura BoardBuilder
. La estructura BoardBuilder
admite habilitar y deshabilitar el enroque, colocar filas y columnas de piezas y colocar piezas individuales.
¡Tenga en cuenta que cuando utilice un BoardBuilder
el enroque está desactivado de forma predeterminada!
Juega la variante de ajedrez de la Horda
fn main ( ) {
// `BoardBuilder::new()` returns an empty board
// with castling disabled.
// Creating a board builder from another board
// structure will preserve
// all settings from the board (such as castling
// and the last en-passant move).
// This BoardBuilder constructs the "Horde" chess variant!
let board = BoardBuilder :: from ( Board :: default ( ) )
. row ( Piece :: Pawn ( WHITE , A1 ) )
. row ( Piece :: Pawn ( WHITE , A2 ) )
. row ( Piece :: Pawn ( WHITE , A3 ) )
. row ( Piece :: Pawn ( WHITE , A4 ) )
. piece ( Piece :: Pawn ( WHITE , F5 ) )
. piece ( Piece :: Pawn ( WHITE , G5 ) )
. piece ( Piece :: Pawn ( WHITE , B5 ) )
. piece ( Piece :: Pawn ( WHITE , C5 ) )
. build ( ) ;
// The CPU can also play variants!
let cpu_move = board . get_best_next_move ( 3 ) ;
match board . play_move ( cpu_move ) {
GameResult :: Continuing ( next_board ) => {
println ! ( "{}" , next_board ) ;
}
GameResult :: Victory ( winner ) => {
// You can use the ! operator on a player's
// color to invert.
println ! ( "{} loses. {} is victorious." ,
!winner, winner
) ;
}
GameResult :: IllegalMove ( x ) => {
eprintln ! ( "{} is an illegal move." , x ) ;
}
GameResult :: Stalemate => {
println ! ( "Drawn game." ) ;
}
}
}
Soy un estudiante de primer año en la universidad y trabajo principalmente en proyectos paralelos como estos en los descansos de ~ 30 minutos entre clases. Si disfrutas de mis proyectos, ¡considera apoyarme invitándome un café!