Eine abhängigkeitsfreie chess engine Bibliothek, die so konzipiert ist, dass sie überall ausgeführt werden kann.
Geschrieben in Rust??
Vor allem dieses Video von Tom7 ist meine Inspiration für dieses Projekt. Er ist absolut brillant und ich flehe Sie an, sich seine Inhalte anzusehen.
Ich liebe Schach sehr . Es ist definitiv eines meiner Lieblingsspiele überhaupt. Allerdings war ich immer enttäuscht, wenn ich versuchte, Programme zu schreiben, die Schach digital spielen (insbesondere in einer kompilierten Sprache). Obwohl es mehrere erstaunliche Engines gibt, ist es nahezu unmöglich, eine ordentliche Bibliothek für schachbezogene Programmierung zu finden, die auf allem läuft.
Chess-Engine ist eine Lösung für mein Problem. Wenn Sie eine chess engine wünschen, die auf eingebetteten Geräten, dem Terminal, dem Desktop (mit einer GUI) und dem Web läuft, ist dies wahrscheinlich die beste Wahl.
Diese spezielle KI (zusammen mit den meisten anderen Schach-KIs) arbeitet mit dem Minimax-Algorithmus und Alpha-Beta-Pruning zur Optimierung.
Packen wir das jetzt aus.
Der Minimax-Algorithmus durchläuft im Wesentlichen alle möglichen Züge rekursiv und wertet alle Spielbretter aus, nachdem die Züge gespielt wurden. Wenn das Spielbrett günstiger ist, wird es dazu ermutigen , den übergeordneten Zug zu spielen, wenn das Spielbrett jedoch weniger günstig ist, wird es sich dagegen entscheiden, einen bestimmten Zug zu spielen.
Wenn die KI außerdem versucht, über das aktuelle Spielfeld hinauszusehen, geht sie davon aus, dass der Mensch immer mit den besten Zügen reagiert. Dadurch macht der Computer fast nie Fehler. Dadurch kann der Computer fast immer objektiv bessere Züge spielen als der Spieler.
Da es keinerlei Abhängigkeiten gibt, ist die Einbettung in den Webbrowser mit WASM äußerst einfach. Versuchen Sie es selbst zu spielen!
Durchschnittliche KI-Einstellung
Die Board
Struktur verfügt über einige verschiedene Methoden, mit denen Benutzer Züge aus einer bestimmten Position generieren können, darunter get_best_next_move
, get_worst_next_move
und get_legal_moves
. Diese sind besonders praktisch, um Schach-KIs zu schreiben, gegen die man spielen möchte.
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" )
}
}
Um etwas Abwechslung oder ein fortgeschritteneres Spiel hinzuzufügen, sollten Sie darüber nachdenken, eine KI zu schreiben, die bekannte Eröffnungen spielt, die bessere Stellungen aufbauen, bevor Sie die Methode get_best_next_move
verwenden!
Darüber hinaus können Benutzer neben dem Standardobjekt auch ihre eigenen benutzerdefinierten Board
-Objekte erstellen. Dies geschieht mithilfe der BoardBuilder
Struktur. Die BoardBuilder
Struktur unterstützt das Aktivieren und Deaktivieren der Rochade, das Platzieren von Figurenreihen und -spalten sowie das Platzieren einzelner Figuren.
Beachten Sie bei der Verwendung eines BoardBuilder
, dass die Rochade standardmäßig deaktiviert ist!
Spielen Sie die Horde-Schachvariante
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." ) ;
}
}
}
Ich bin ein Studienanfänger und arbeite hauptsächlich in den ca. 30-minütigen Pausen zwischen den Vorlesungen an Nebenprojekten wie diesen. Wenn Ihnen meine Projekte gefallen, denken Sie darüber nach, mich zu unterstützen, indem Sie mir einen Kaffee spendieren!