Add assignment

This commit is contained in:
Job Noorman
2022-10-27 12:29:19 +02:00
commit 9f05ab03c1
49 changed files with 4339 additions and 0 deletions

945
Tests/BoardTests.cpp Normal file
View File

@@ -0,0 +1,945 @@
#include "catch2/catch.hpp"
#include "TestUtils.hpp"
#include "Board.hpp"
#include "Square.hpp"
#include "Fen.hpp"
#include <vector>
#include <set>
#include <algorithm>
#include <map>
TEST_CASE("A default-constructed board is empty", "[Board][Fundamental]") {
auto board = Board();
for (auto i = 0; i < 64; ++i) {
auto optSquare = Square::fromIndex(i);
REQUIRE(optSquare.has_value());
auto square = optSquare.value();
auto optPiece = board.piece(square);
REQUIRE_FALSE(optPiece.has_value());
}
}
TEST_CASE("Pieces can be set on a board", "[Board][Fundamental]") {
auto board = Board();
auto optSquare = Square::fromIndex(41);
REQUIRE(optSquare.has_value());
auto square = optSquare.value();
auto piece = Piece(PieceColor::White, PieceType::Rook);
board.setPiece(square, piece);
auto optSetPiece = board.piece(square);
REQUIRE(optSetPiece.has_value());
auto setPiece = optSetPiece.value();
REQUIRE(setPiece == piece);
SECTION("Setting a piece on an occupied square overrides") {
auto newPiece = Piece(PieceColor::Black, PieceType::King);
board.setPiece(square, newPiece);
auto optNewSetPiece = board.piece(square);
REQUIRE(optNewSetPiece.has_value());
auto newSetPiece = optNewSetPiece.value();
REQUIRE(newSetPiece == newPiece);
}
}
TEST_CASE("The turn can be set on a board", "[Board][Fundamental]") {
auto color = GENERATE(PieceColor::Black, PieceColor::White);
auto board = Board();
board.setTurn(color);
REQUIRE(board.turn() == color);
}
static void testPseudoLegalMoves(
const char* fen,
const std::string& fromName,
const std::vector<std::string>& expectedTargets)
{
auto optBoard = Fen::createBoard(fen);
REQUIRE(optBoard.has_value());
auto from = Square::Optional();
if (!fromName.empty()) {
from = Square::fromName(fromName);
REQUIRE(from.has_value());
}
auto board = optBoard.value();
using MoveSet = std::set<Move>;
auto expectedMoves = MoveSet();
for (auto targetName : expectedTargets) {
if (targetName.length() == 2) {
// targetName is a square
auto optTarget = Square::fromName(targetName);
REQUIRE(optTarget.has_value());
REQUIRE(from.has_value());
auto target = optTarget.value();
auto move = Move(from.value(), target);
expectedMoves.insert(move);
} else {
// targetName is a move
auto optMove = Move::fromUci(targetName);
REQUIRE(optMove.has_value());
expectedMoves.insert(optMove.value());
}
}
auto generatedMovesVec = Board::MoveVec();
if (from.has_value()) {
board.pseudoLegalMovesFrom(from.value(), generatedMovesVec);
} else {
board.pseudoLegalMoves(generatedMovesVec);
}
auto generatedMoves = MoveSet(generatedMovesVec.begin(),
generatedMovesVec.end());
auto unexpectedMoves = MoveSet();
auto notGeneratedMoves = MoveSet();
std::set_difference(
generatedMoves.begin(), generatedMoves.end(),
expectedMoves.begin(), expectedMoves.end(),
std::inserter(unexpectedMoves, unexpectedMoves.begin())
);
std::set_difference(
expectedMoves.begin(), expectedMoves.end(),
generatedMoves.begin(), generatedMoves.end(),
std::inserter(notGeneratedMoves, notGeneratedMoves.begin())
);
CAPTURE(fen, from, unexpectedMoves, notGeneratedMoves);
REQUIRE(generatedMoves == expectedMoves);
}
#define TEST_CASE_PSEUDO_MOVES(name, tag) \
TEST_CASE(name, "[Board][MoveGen]" tag)
TEST_CASE_PSEUDO_MOVES("Pseudo-legal knight moves, empty board", "[Knight]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/3N4/8/8/8_w_-_-_0_1
"8/8/8/8/3N4/8/8/8 w - - 0 1",
"d4",
{
"c6", "e6",
"f5", "f3",
"c2", "e2",
"b3", "b5"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal knight moves, side of board", "[Knight]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/8/8/n7/8_b_-_-_0_1
"8/8/8/8/8/8/n7/8 b - - 0 1",
"a2",
{
"b4",
"c3", "c1"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal knight moves, captures", "[Knight]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/2p1P3/8/2PN4/2Pp4/8/8_w_-_-_0_1
"8/8/2p1P3/8/2PN4/2Pp4/8/8 w - - 0 1",
"d4",
{
"c6",
"f5", "f3",
"c2", "e2",
"b3", "b5"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal king moves, empty board", "[King]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/3K4/8/8/8_w_-_-_0_1
"8/8/8/8/3K4/8/8/8 w - - 0 1",
"d4",
{
"c5", "d5", "e5",
"c4", "e4",
"c3", "d3", "e3",
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal king moves, side of board", "[King]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/8/8/8/K7_w_-_-_0_1
"8/8/8/8/8/8/8/K7 w - - 0 1",
"a1",
{
"a2", "b2",
"b1"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal king moves, captures", "[King]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/2PK4/3p4/8/8_w_-_-_0_1
"8/8/8/8/2PK4/3p4/8/8 w - - 0 1",
"d4",
{
"c5", "d5", "e5",
"e4",
"c3", "d3", "e3",
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal bishop moves, empty board", "[Bishop]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/3B4/8/8/8_w_-_-_0_1
"8/8/8/8/3B4/8/8/8 w - - 0 1",
"d4",
{
"c5", "b6", "a7",
"e5", "f6", "g7", "h8",
"c3", "b2", "a1",
"e3", "f2", "g1"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal bishop moves, captures", "[Bishop]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/1p3P2/8/3B4/8/8/8_w_-_-_0_1
"8/8/1p3P2/8/3B4/8/8/8 w - - 0 1",
"d4",
{
"c5", "b6",
"e5",
"c3", "b2", "a1",
"e3", "f2", "g1"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal rook moves, empty board", "[Rook]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/3R4/8/8/8_w_-_-_0_1
"8/8/8/8/3R4/8/8/8 w - - 0 1",
"d4",
{
"d5", "d6", "d7", "d8",
"d3", "d2", "d1",
"c4", "b4", "a4",
"e4", "f4", "g4", "h4"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal rook moves, captures", "[Rook]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/3p4/8/3R1P2/8/8/8_w_-_-_0_1
"8/8/3p4/8/3R1P2/8/8/8 w - - 0 1",
"d4",
{
"d5", "d6",
"d3", "d2", "d1",
"c4", "b4", "a4",
"e4"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal queen moves, empty board", "[Queen]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/3Q4/8/8/8_w_-_-_0_1
"8/8/8/8/3Q4/8/8/8 w - - 0 1",
"d4",
{
"c5", "b6", "a7",
"e5", "f6", "g7", "h8",
"c3", "b2", "a1",
"e3", "f2", "g1",
"d5", "d6", "d7", "d8",
"d3", "d2", "d1",
"c4", "b4", "a4",
"e4", "f4", "g4", "h4"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal queen moves, captures", "[Queen]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/1p3P2/8/1P1Q4/8/3p4/8_w_-_-_0_1
"8/8/1p3P2/8/1P1Q4/8/3p4/8 w - - 0 1",
"d4",
{
"c5", "b6",
"e5",
"c3", "b2", "a1",
"e3", "f2", "g1",
"d5", "d6", "d7", "d8",
"d3", "d2",
"c4",
"e4", "f4", "g4", "h4"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, step, empty board", "[Pawn]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/3P4/8/8/8_w_-_-_0_1
"8/8/8/8/3P4/8/8/8 w - - 0 1",
"d4",
{
"d5"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, step, opponent blocked", "[Pawn]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/3p4/3P4/8/8/8_w_-_-_0_1
"8/8/8/3p4/3P4/8/8/8 w - - 0 1",
"d4",
{}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, step, self blocked", "[Pawn]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/3p4/3b4/8/8/8_b_-_-_0_1
"8/8/8/3p4/3b4/8/8/8 b - - 0 1",
"d5",
{}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, capture left", "[Pawn]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/2ppP3/3P4/8/8/8_w_-_-_0_1
"8/8/8/2ppP3/3P4/8/8/8 w - - 0 1",
"d4",
{
"c5"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, capture both", "[Pawn]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/3p4/2PRQ3/8/8/8_b_-_-_0_1
"8/8/8/3p4/2PRQ3/8/8/8 b - - 0 1",
"d5",
{
"c4", "e4"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, base step, empty board", "[Pawn]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/3p4/8/8/8/8/8/8_b_-_-_0_1
"8/3p4/8/8/8/8/8/8 b - - 0 1",
"d7",
{
"d6", "d5"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, base step, blocked 1", "[Pawn]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/3p4/3P4/8/8/8/8/8_b_-_-_0_1
"8/3p4/3P4/8/8/8/8/8 b - - 0 1",
"d7",
{}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, base step, blocked 2", "[Pawn]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/7p/8/7P/8_w_-_-_0_1
"8/8/8/8/7p/8/7P/8 w - - 0 1",
"h2",
{
"h3"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, en passant, black left", "[Pawn][EnPassant]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/3Pp3/8/8/8_b_-_d3_0_1
"8/8/8/8/3Pp3/8/8/8 b - d3 0 1",
"e4",
{
"e3", "d3"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, en passant, black right", "[Pawn][EnPassant]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/2pP4/2P5/8/8_b_-_d3_0_1
"8/8/8/8/2pP4/2P5/8/8 b - d3 0 1",
"c4",
{
"d3"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, en passant, white left", "[Pawn][EnPassant]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/2n5/pP6/8/8/8/8_w_-_a6_0_1
"8/8/2n5/pP6/8/8/8/8 w - a6 0 1",
"b5",
{
"a6", "b6", "c6"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, en passant, white right", "[Pawn][EnPassant]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/n7/Pp6/8/8/8/8_w_-_b6_0_1
"8/8/n7/Pp6/8/8/8/8 w - b6 0 1",
"a5",
{
"b6"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, en passant, black both", "[Pawn][EnPassant]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/5pPp/7P/8/8_b_-_g3_0_1
"8/8/8/8/5pPp/7P/8/8 b - g3 0 1",
"",
{
"f4f3", "f4g3",
"h4g3"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, en passant, white both", "[Pawn][EnPassant]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/2r2n2/2PpP3/8/8/8/8_w_-_d6_0_1
"8/8/2r2n2/2PpP3/8/8/8/8 w - d6 0 1",
"",
{
"c5d6",
"e5d6", "e5e6", "e5f6"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, en passant, wrong square", "[Pawn][EnPassant]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/3p1P2/8/8/8_b_-_f3_0_1
"8/8/8/8/3p1P2/8/8/8 b - f3 0 1",
"d4",
{
"d3"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, visual en passant, no square", "[Pawn]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/1pPp4/8/8/8/8_w_-_-_0_1
"8/8/8/1pPp4/8/8/8/8 w - - 0 1",
"c5",
{
"c6"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, white promotions", "[Pawn][Promotion]") {
testPseudoLegalMoves(
// https://lichess.org/editor/5r2/4P3/8/8/8/8/8/8_w_-_-_0_1
"5r2/4P3/8/8/8/8/8/8 w - - 0 1",
"e7",
{
"e7e8q", "e7e8r", "e7e8b", "e7e8n",
"e7f8q", "e7f8r", "e7f8b", "e7f8n"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal pawn moves, black promotions", "[Pawn][Promotion]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/8/8/1p6/2Q5_b_-_-_0_1
"8/8/8/8/8/8/1p6/2Q5 b - - 0 1",
"b2",
{
"b2b1q", "b2b1r", "b2b1b", "b2b1n",
"b2c1q", "b2c1r", "b2c1b", "b2c1n"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, white kingside", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/8/8/3PPP2/3QK2R_w_K_-_0_1
"8/8/8/8/8/8/3PPP2/3QK2R w K - 0 1",
"e1",
{
"f1", "g1"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, white queenside", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/8/8/3PPP2/R3KB2_w_Q_-_0_1
"8/8/8/8/8/8/3PPP2/R3KB2 w Q - 0 1",
"e1",
{
"d1", "c1"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, black kingside", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/3qk2r/3ppp2/8/8/8/8/8/8_b_k_-_0_1
"3qk2r/3ppp2/8/8/8/8/8/8 b k - 0 1",
"e8",
{
"f8", "g8"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, black queenside", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/r3kb2/3ppp2/8/8/8/8/8/8_b_q_-_0_1
"r3kb2/3ppp2/8/8/8/8/8/8 b q - 0 1",
"e8",
{
"d8", "c8"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, kingside blocked", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/8/8/3PPP2/3QK1NR_w_K_-_0_1
"8/8/8/8/8/8/3PPP2/3QK1NR w K - 0 1",
"e1",
{
"f1"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, queenside blocked", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/rn2kb2/3ppp2/8/8/8/8/8/8_b_q_-_0_1
"rn2kb2/3ppp2/8/8/8/8/8/8 b q - 0 1",
"e8",
{
"d8"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, kingside attacked", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/3qk2r/3ppp2/5N2/8/8/8/8/8_b_k_-_0_1
"3qk2r/3ppp2/5N2/8/8/8/8/8 b k - 0 1",
"e8",
{
"f8"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, queenside attacked", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/8/5n2/3PPP2/R3KB2_w_Q_-_0_1
"8/8/8/8/8/5n2/3PPP2/R3KB2 w Q - 0 1",
"e1",
{
"d1"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, queenside rook attacked", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/r3kb2/3ppp2/8/8/8/5B2/8/8_b_q_-_0_1
"r3kb2/3ppp2/8/8/8/5B2/8/8 b q - 0 1",
"e8",
{
"d8", "c8"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, kingside rook attacked", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/2q5/8/8/8/3PPP2/3QK2R_w_K_-_0_1
"8/8/2q5/8/8/8/3PPP2/3QK2R w K - 0 1",
"e1",
{
"f1", "g1"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, queenside b-square attacked", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/r3kb2/3ppp2/8/8/8/8/8/1R6_b_q_-_0_1
"r3kb2/3ppp2/8/8/8/8/8/1R6 b q - 0 1",
"e8",
{
"d8", "c8"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal castling moves, no rights", "[Castling]") {
testPseudoLegalMoves(
// https://lichess.org/editor/r3k2r/8/8/8/8/8/3PPP2/R3K2R_w_Kkq_-_0_1
"r3k2r/8/8/8/8/8/3PPP2/R3K2R w Kkq - 0 1",
"e1",
{
"f1", "g1",
"d1"
}
);
}
static void testMakeMove(const char* fen, const Move& move) {
auto board = Fen::createBoard(fen);
REQUIRE(board.has_value());
auto piece = board->piece(move.from());
REQUIRE(piece.has_value());
auto turn = board->turn();
board->makeMove(move);
REQUIRE(board->turn() == !turn);
REQUIRE_FALSE(board->piece(move.from()).has_value());
auto toPiece = board->piece(move.to());
REQUIRE(toPiece.has_value());
REQUIRE(piece == toPiece.value());
}
static void testMakeMove(const char* fen, const Move& move,
const std::map<Square, Piece>& expectedBoard) {
CAPTURE(fen, move);
auto board = Fen::createBoard(fen);
REQUIRE(board.has_value());
auto turn = board->turn();
board->makeMove(move);
REQUIRE(board->turn() == !turn);
for (auto [square, expectedPiece] : expectedBoard) {
auto piece = board->piece(square);
INFO("Expected piece not on board");
CAPTURE(square, piece, expectedPiece);
REQUIRE(piece.has_value());
REQUIRE(piece.value() == expectedPiece);
}
for (auto i = 0; i < 64; ++i) {
auto square = Square::fromIndex(i);
REQUIRE(square.has_value());
auto piece = board->piece(square.value());
CAPTURE(square.value(), piece);
auto expectedPieceIt = expectedBoard.find(square.value());
if (piece.has_value()) {
INFO("Unexpected piece on board");
REQUIRE(expectedPieceIt != expectedBoard.end());
CAPTURE(expectedPieceIt->second);
REQUIRE(piece.value() == expectedPieceIt->second);
}
}
}
static void testMakeMove(const char* fen, const Move& move, CastlingRights cr) {
auto board = Fen::createBoard(fen);
REQUIRE(board.has_value());
auto turn = board->turn();
board->makeMove(move);
REQUIRE(board->turn() == !turn);
REQUIRE(board->castlingRights() == cr);
}
static void testMakeMove(const char* fen, const Move& move,
const Square::Optional& epSquare) {
auto board = Fen::createBoard(fen);
REQUIRE(board.has_value());
auto turn = board->turn();
board->makeMove(move);
REQUIRE(board->turn() == !turn);
REQUIRE(board->enPassantSquare() == epSquare);
}
#define TEST_CASE_MAKE_MOVE(name, tag) \
TEST_CASE(name, "[Board][MoveMaking]" tag)
TEST_CASE_MAKE_MOVE("Move making moves a piece on the board", "") {
// https://lichess.org/editor/8/8/8/8/8/8/8/2Q5_w_-_-_0_1
testMakeMove(
"8/8/8/8/8/8/8/2Q5 w - - 0 1",
Move(Square::C1, Square::F4)
);
}
TEST_CASE_MAKE_MOVE("Move making supports captures", "") {
// https://lichess.org/editor/8/8/8/2n5/8/3P4/8/8_b_-_-_0_1
testMakeMove(
"8/8/8/2n5/8/3P4/8/8 b - - 0 1",
Move(Square::C5, Square::D3)
);
}
TEST_CASE_MAKE_MOVE("Move making, white promotion", "[Promotion]") {
// https://lichess.org/editor/8/4P3/8/8/8/8/8/8_w_-_-_0_1
testMakeMove(
"8/4P3/8/8/8/8/8/8 w - - 0 1",
Move(Square::E7, Square::E8, PieceType::Queen),
{
{Square::E8, Piece(PieceColor::White, PieceType::Queen)}
}
);
}
TEST_CASE_MAKE_MOVE("Move making, black promotion", "[Promotion]") {
// https://lichess.org/editor/8/8/8/8/8/8/p7/8_b_-_-_0_1
testMakeMove(
"8/8/8/8/8/8/p7/8 b - - 0 1",
Move(Square::A2, Square::A1, PieceType::Knight),
{
{Square::A1, Piece(PieceColor::Black, PieceType::Knight)}
}
);
}
TEST_CASE_MAKE_MOVE("Move making, castling white kingside", "[Castling]") {
// https://lichess.org/editor/8/8/8/8/8/8/8/4K2R_w_K_-_0_1
testMakeMove(
"8/8/8/8/8/8/8/4K2R w K - 0 1",
Move(Square::E1, Square::G1),
{
{Square::G1, Piece(PieceColor::White, PieceType::King)},
{Square::F1, Piece(PieceColor::White, PieceType::Rook)}
}
);
}
TEST_CASE_MAKE_MOVE("Move making, castling white queenside", "[Castling]") {
// https://lichess.org/editor/8/8/8/8/8/8/8/R3K3_w_Q_-_0_1
testMakeMove(
"8/8/8/8/8/8/8/R3K3 w Q - 0 1",
Move(Square::E1, Square::C1),
{
{Square::C1, Piece(PieceColor::White, PieceType::King)},
{Square::D1, Piece(PieceColor::White, PieceType::Rook)}
}
);
}
TEST_CASE_MAKE_MOVE("Move making, castling black kingside", "[Castling]") {
// https://lichess.org/editor/4k2r/8/8/8/8/8/8/8_b_k_-_0_1
testMakeMove(
"4k2r/8/8/8/8/8/8/8 b k - 0 1",
Move(Square::E8, Square::G8),
{
{Square::G8, Piece(PieceColor::Black, PieceType::King)},
{Square::F8, Piece(PieceColor::Black, PieceType::Rook)}
}
);
}
TEST_CASE_MAKE_MOVE("Move making, castling black queenside", "[Castling]") {
// https://lichess.org/editor/r3k3/8/8/8/8/8/8/8_b_q_-_0_1
testMakeMove(
"r3k3/8/8/8/8/8/8/8 b q - 0 1",
Move(Square::E8, Square::C8),
{
{Square::C8, Piece(PieceColor::Black, PieceType::King)},
{Square::D8, Piece(PieceColor::Black, PieceType::Rook)}
}
);
}
TEST_CASE_MAKE_MOVE("Move making, castling rights king move", "[Castling]") {
// https://lichess.org/editor/r3k2r/8/8/8/8/8/8/R3K2R_w_KQkq_-_0_1
testMakeMove(
"r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1",
Move(Square::E1, Square::D1),
CastlingRights::Black
);
}
TEST_CASE_MAKE_MOVE("Move making, castling rights rook move", "[Castling]") {
// https://lichess.org/editor/r3k2r/8/8/8/8/8/8/R3K2R_b_KQkq_-_0_1
testMakeMove(
"r3k2r/8/8/8/8/8/8/R3K2R b KQkq - 0 1",
Move(Square::H8, Square::G8),
CastlingRights::White | CastlingRights::BlackQueenside
);
}
TEST_CASE_MAKE_MOVE("Move making, castling rights rook capture", "[Castling]") {
// https://lichess.org/editor/r3k2r/8/8/8/8/8/8/R3K2R_w_KQkq_-_0_1
testMakeMove(
"r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1",
Move(Square::A1, Square::A8),
CastlingRights::WhiteKingside | CastlingRights::BlackKingside
);
}
TEST_CASE_MAKE_MOVE("Move making, castling rights king back to base", "[Castling]") {
// https://lichess.org/editor/r3k2r/8/8/8/8/8/8/R2K3R_w_kq_-_0_1
testMakeMove(
"r3k2r/8/8/8/8/8/8/R2K3R w kq - 0 1",
Move(Square::D1, Square::E1),
CastlingRights::Black
);
}
TEST_CASE_MAKE_MOVE("Move making, en passant, black left", "[EnPassant]") {
// https://lichess.org/editor/8/8/8/8/5Pp1/8/8/8_b_-_f3_0_1
testMakeMove(
"8/8/8/8/5Pp1/8/8/8 b - f3 0 1",
Move(Square::G4, Square::F3),
{
{Square::F3, Piece(PieceColor::Black, PieceType::Pawn)}
}
);
}
TEST_CASE_MAKE_MOVE("Move making, en passant, black right", "[EnPassant]") {
// https://lichess.org/editor/8/8/8/3P4/1PpPP3/2P5/8/8_b_-_d3_0_1
testMakeMove(
"8/8/8/3P4/1PpPP3/2P5/8/8 b - d3 0 1",
Move(Square::C4, Square::D3),
{
{Square::D3, Piece(PieceColor::Black, PieceType::Pawn)},
{Square::B4, Piece(PieceColor::White, PieceType::Pawn)},
{Square::C3, Piece(PieceColor::White, PieceType::Pawn)},
{Square::D5, Piece(PieceColor::White, PieceType::Pawn)},
{Square::E4, Piece(PieceColor::White, PieceType::Pawn)},
}
);
}
TEST_CASE_MAKE_MOVE("Move making, en passant, white left", "[EnPassant]") {
// https://lichess.org/editor/8/8/8/3pPp2/8/8/8/8_w_-_d6_0_1
testMakeMove(
"8/8/8/3pPp2/8/8/8/8 w - d6 0 1",
Move(Square::E5, Square::D6),
{
{Square::D6, Piece(PieceColor::White, PieceType::Pawn)},
{Square::F5, Piece(PieceColor::Black, PieceType::Pawn)}
}
);
}
TEST_CASE_MAKE_MOVE("Move making, en passant, white right", "[EnPassant]") {
// https://lichess.org/editor/8/8/8/1Pp5/8/8/8/8_w_-_c6_0_1
testMakeMove(
"8/8/8/1Pp5/8/8/8/8 w - c6 0 1",
Move(Square::B5, Square::C6),
{
{Square::C6, Piece(PieceColor::White, PieceType::Pawn)}
}
);
}
TEST_CASE_MAKE_MOVE("Move making, en passant square, white double step update", "[EnPassant]") {
// https://lichess.org/editor/8/8/8/8/3p4/8/4P3/8_w_-_-_0_1
testMakeMove(
"8/8/8/8/3p4/8/4P3/8 w - - 0 1",
Move(Square::E2, Square::E4),
Square::E3
);
}
TEST_CASE_MAKE_MOVE("Move making, en passant square, black double step update", "[EnPassant]") {
// https://lichess.org/editor/8/p7/8/1P6/8/8/8/8_b_-_-_0_1
testMakeMove(
"8/p7/8/1P6/8/8/8/8 b - - 0 1",
Move(Square::A7, Square::A5),
Square::A6
);
}
TEST_CASE_MAKE_MOVE("Move making, en passant square, remove after capture", "[EnPassant]") {
// https://lichess.org/editor/8/8/8/8/Pp6/8/8/8_b_-_a3_0_1
testMakeMove(
"8/8/8/8/Pp6/8/8/8 b - a3 0 1",
Move(Square::B4, Square::A3),
std::nullopt
);
}
TEST_CASE_MAKE_MOVE("Move making, en passant square, remove after move", "[EnPassant]") {
// https://lichess.org/editor/8/8/8/4pP2/8/8/1N6/8_w_-_e6_0_1
testMakeMove(
"8/8/8/4pP2/8/8/1N6/8 w - e6 0 1",
Move(Square::B2, Square::C4),
std::nullopt
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal moves, multiple pieces, white", "") {
testPseudoLegalMoves(
// https://lichess.org/editor/8/8/8/8/8/8/2P5/NB6_w_-_-_0_1
"8/8/8/8/8/8/2P5/NB6 w - - 0 1",
"",
{
"a1b3",
"b1a2",
"c2c3", "c2c4"
}
);
}
TEST_CASE_PSEUDO_MOVES("Pseudo-legal moves, multiple pieces, black", "") {
testPseudoLegalMoves(
// https://lichess.org/editor/7n/7b/6p1/8/8/8/8/8_b_-_-_0_1
"7n/7b/6p1/8/8/8/8/8 b - - 0 1",
"",
{
"h8f7",
"h7g8",
"g6g5"
}
);
}

16
Tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,16 @@
add_subdirectory(Catch2/)
add_executable(tests
Main.cpp
SquareTests.cpp
MoveTests.cpp
PieceTests.cpp
BoardTests.cpp
FenTests.cpp
EngineTests.cpp
)
target_link_libraries(tests cplchess_lib Catch2::Catch2)
include(Catch2/contrib/Catch.cmake)
catch_discover_tests(tests)

1
Tests/Catch2 Submodule

Submodule Tests/Catch2 added at c4e3767e26

48
Tests/EngineTests.cpp Normal file
View File

@@ -0,0 +1,48 @@
#include "catch2/catch.hpp"
#include "TestUtils.hpp"
#include "EngineFactory.hpp"
#include "Engine.hpp"
#include "Fen.hpp"
#include "Board.hpp"
static std::unique_ptr<Engine> createEngine() {
return EngineFactory::createEngine();
}
static void testGameEnd(const char* fen, bool isMate) {
auto engine = createEngine();
REQUIRE(engine != nullptr);
auto board = Fen::createBoard(fen);
REQUIRE(board.has_value());
auto pv = engine->pv(board.value());
REQUIRE(pv.isMate() == isMate);
REQUIRE(pv.score() == 0);
REQUIRE(pv.length() == 0);
}
TEST_CASE("Engine detects checkmate", "[Engine][Checkmate]") {
auto fen = GENERATE(
// https://lichess.org/editor/4R2k/6pp/8/8/8/8/8/K7_b_-_-_0_1
"4R2k/6pp/8/8/8/8/8/K7 b - - 0 1",
// https://lichess.org/editor/7k/8/8/8/1bb5/8/r7/3BK3_w_-_-_0_1
"7k/8/8/8/1bb5/8/r7/3BK3 w - - 0 1"
);
testGameEnd(fen, true);
}
TEST_CASE("Engine detects stalemate", "[Engine][Stalemate]") {
auto fen = GENERATE(
// https://lichess.org/editor/k7/p7/P7/8/8/8/8/KR6_b_-_-_0_1
"k7/p7/P7/8/8/8/8/KR6 b - - 0 1",
// https://lichess.org/editor/k7/8/8/6n1/r7/4K3/2q5/8_w_-_-_0_1
"k7/8/8/6n1/r7/4K3/2q5/8 w - - 0 1"
);
testGameEnd(fen, false);
}

117
Tests/FenTests.cpp Normal file
View File

@@ -0,0 +1,117 @@
#include "catch2/catch.hpp"
#include "TestUtils.hpp"
#include "Fen.hpp"
#include <map>
TEST_CASE("Legal placements are correctly parsed", "[Fen]") {
// https://lichess.org/editor/k7/2B5/7p/1q3P2/8/3N4/8/5r2_w_-_-_0_1
auto fen = "k7/2B5/7p/1q3P2/8/3N4/8/5r2 w - - 0 1";
auto optBoard = Fen::createBoard(fen);
REQUIRE(optBoard.has_value());
auto board = optBoard.value();
auto expectedPlacement = std::map<Square, Piece>{
{Square::F1, Piece(PieceColor::Black, PieceType::Rook)},
{Square::D3, Piece(PieceColor::White, PieceType::Knight)},
{Square::B5, Piece(PieceColor::Black, PieceType::Queen)},
{Square::F5, Piece(PieceColor::White, PieceType::Pawn)},
{Square::H6, Piece(PieceColor::Black, PieceType::Pawn)},
{Square::C7, Piece(PieceColor::White, PieceType::Bishop)},
{Square::A8, Piece(PieceColor::Black, PieceType::King)}
};
for (auto index = 0; index < 64; ++index) {
auto optSquare = Square::fromIndex(index);
REQUIRE(optSquare.has_value());
auto square = optSquare.value();
INFO("Checking square " << square);
auto expectedPieceIt = expectedPlacement.find(square);
auto optActualPiece = board.piece(square);
if (expectedPieceIt == expectedPlacement.end()) {
INFO("Expecting empty")
REQUIRE_FALSE(optActualPiece.has_value());
} else {
auto expectedPiece = expectedPieceIt->second;
INFO("Expecting " << expectedPiece);
REQUIRE(optActualPiece.has_value());
auto actualPiece = optActualPiece.value();
REQUIRE(actualPiece == expectedPiece);
}
}
}
TEST_CASE("Legal turns are correctly parsed", "[Fen]") {
auto [fen, turn] = GENERATE(table<const char*, PieceColor>({
// https://lichess.org/editor/8/8/8/8/8/8/8/8_w_-_-_0_1
{"8/8/8/8/8/8/8/8 w - - 0 1", PieceColor::White},
// https://lichess.org/editor/8/8/8/8/8/8/8/8_b_-_-_0_1
{"8/8/8/8/8/8/8/8 b - - 0 1", PieceColor::Black}
}));
auto optBoard = Fen::createBoard(fen);
REQUIRE(optBoard.has_value());
auto board = optBoard.value();
REQUIRE(board.turn() == turn);
}
TEST_CASE("Castling rights are correctly parsed", "[Fen]") {
auto [fen, cr] = GENERATE(table<const char*, CastlingRights>({
// https://lichess.org/editor/rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR_w_KQkq_-_0_1
{
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
CastlingRights::All
},
// https://lichess.org/editor/8/8/8/8/8/8/8/8_b_-_-_0_1
{
"8/8/8/8/8/8/8/8 b - - 0 1",
CastlingRights::None
},
// https://lichess.org/editor/rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR_w_Qk_-_0_1
{
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w Qk - 0 1",
CastlingRights::WhiteQueenside | CastlingRights::BlackKingside
}
}));
CAPTURE(fen, cr);
auto optBoard = Fen::createBoard(fen);
REQUIRE(optBoard.has_value());
auto board = optBoard.value();
REQUIRE(board.castlingRights() == cr);
}
TEST_CASE("En passant square is correctly parsed", "[Fen][EnPassant]") {
auto [fen, ep] = GENERATE(table<const char*, Square::Optional>({
// https://lichess.org/editor/rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR_w_KQkq_-_0_1
{
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
std::nullopt
},
// https://lichess.org/editor/rnbqkbnr/ppppp1pp/8/8/2PPPp2/8/PP3PPP/RNBQKBNR_b_KQkq_e3_0_3
{
"rnbqkbnr/ppppp1pp/8/8/2PPPp2/8/PP3PPP/RNBQKBNR b KQkq e3 0 3",
Square::E3
}
}));
CAPTURE(fen, ep);
auto optBoard = Fen::createBoard(fen);
REQUIRE(optBoard.has_value());
auto board = optBoard.value();
REQUIRE(board.enPassantSquare() == ep);
}

2
Tests/Main.cpp Normal file
View File

@@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include "catch2/catch.hpp"

111
Tests/MoveTests.cpp Normal file
View File

@@ -0,0 +1,111 @@
#include "catch2/catch.hpp"
#include "TestUtils.hpp"
#include "Move.hpp"
#include <sstream>
TEST_CASE("Moves store the squares they are constructed with", "[Move][Fundamental]") {
auto from = Square::E2;
auto to = Square::G6;
auto move = Move(from, to);
REQUIRE(move.from() == from);
REQUIRE(move.to() == to);
REQUIRE_FALSE(move.promotion().has_value());
}
TEST_CASE("Moves store the promotion they are constructed with", "[Move][Promotion]") {
auto from = Square::A7;
auto to = Square::A8;
auto promotion = PieceType::Knight;
auto move = Move(from, to, promotion);
REQUIRE(move.from() == from);
REQUIRE(move.to() == to);
REQUIRE(move.promotion().has_value());
REQUIRE(move.promotion().value() == promotion);
}
TEST_CASE("Moves support equality checks", "[Move][Fundamental]") {
auto move1 = Move(Square::D4, Square::H7);
auto move2 = Move(Square::D4, Square::G3);
auto move3 = Move(Square::A3, Square::H7);
auto move1Copy = move1;
REQUIRE(move1 == move1Copy);
REQUIRE_FALSE(move1 == move2);
REQUIRE_FALSE(move1 == move3);
}
TEST_CASE("Moves with promotions support equality checks", "[Move][Promotion]") {
auto move1 = Move(Square::B2, Square::B1, PieceType::Queen);
auto move2 = Move(Square::B2, Square::B1);
auto move3 = Move(Square::C2, Square::C1, PieceType::Queen);
auto move1Copy = move1;
REQUIRE(move1 == move1Copy);
REQUIRE_FALSE(move1 == move2);
REQUIRE_FALSE(move1 == move3);
}
TEST_CASE("Moves stream their UCI correctly", "[Move][Fundamental]") {
auto [from, to, uci] = GENERATE(table<Square, Square, const char*>({
{Square::A1, Square::D7, "a1d7"},
{Square::C8, Square::F2, "c8f2"},
{Square::H6, Square::B1, "h6b1"}
}));
auto move = Move(from, to);
auto stream = std::stringstream();
stream << move;
REQUIRE(stream.str() == uci);
}
TEST_CASE("Moves with promotions stream their UCI correctly", "[Move][Promotion]") {
auto [from, to, promotion, uci] = GENERATE(table<Square, Square, PieceType, const char*>({
{Square::H7, Square::H8, PieceType::Knight, "h7h8n"},
{Square::C2, Square::C1, PieceType::Rook, "c2c1r"},
{Square::E7, Square::E8, PieceType::Queen, "e7e8q"}
}));
auto move = Move(from, to, promotion);
auto stream = std::stringstream();
stream << move;
REQUIRE(stream.str() == uci);
}
TEST_CASE("Moves can be created from valid UCI notation", "[Move][Fundamental]") {
auto [uci, from, to] = GENERATE(table<const char*, Square, Square>({
{"a1d7", Square::A1, Square::D7},
{"c8f2", Square::C8, Square::F2},
{"h6b1", Square::H6, Square::B1}
}));
auto move = Move::fromUci(uci);
auto expectedMove = Move(from, to);
CAPTURE(uci, expectedMove, move);
REQUIRE(move.has_value());
REQUIRE(move.value() == expectedMove);
}
TEST_CASE("Moves can be created from valid UCI notation with promotion", "[Move][Promotion]") {
auto [uci, from, to, promotion] = GENERATE(table<const char*, Square, Square, PieceType>({
{"a7a8n", Square::A7, Square::A8, PieceType::Knight},
{"c2c1b", Square::C2, Square::C1, PieceType::Bishop},
{"h7h8r", Square::H7, Square::H8, PieceType::Rook}
}));
auto move = Move::fromUci(uci);
auto expectedMove = Move(from, to, promotion);
CAPTURE(uci, expectedMove, move);
REQUIRE(move.has_value());
REQUIRE(move.value() == expectedMove);
}
TEST_CASE("Moves are not created from invalid UCI notation", "[Move][Fundamental]") {
auto uci = GENERATE("a1d7x", "a1d", "a1d7123", "a1", "", "a9d1", "a1c0");
auto move = Move::fromUci(uci);
CAPTURE(uci, move);
REQUIRE_FALSE(move.has_value());
}

74
Tests/PieceTests.cpp Normal file
View File

@@ -0,0 +1,74 @@
#include "catch2/catch.hpp"
#include "Piece.hpp"
#include <sstream>
#include <cctype>
TEST_CASE("Pieces store color and type correctly", "[Piece][Fundamental]") {
auto color = PieceColor::Black;
auto type = PieceType::Queen;
auto piece = Piece(color, type);
REQUIRE(piece.color() == color);
REQUIRE(piece.type() == type);
}
TEST_CASE("Pieces can be created from valid symbols", "[Piece][Fundamental]") {
auto [blackSymbol, pieceType] = GENERATE(table<char, PieceType>({
{'p', PieceType::Pawn},
{'n', PieceType::Knight},
{'b', PieceType::Bishop},
{'r', PieceType::Rook},
{'q', PieceType::Queen},
{'k', PieceType::King}
}));
auto optBlackPiece = Piece::fromSymbol(blackSymbol);
REQUIRE(optBlackPiece.has_value());
auto createdBlackPiece = optBlackPiece.value();
REQUIRE(createdBlackPiece == Piece(PieceColor::Black, pieceType));
auto whiteSymbol = static_cast<char>(std::toupper(blackSymbol));
auto optWhitePiece = Piece::fromSymbol(whiteSymbol);
REQUIRE(optWhitePiece.has_value());
auto createdWhitePiece = optWhitePiece.value();
REQUIRE(createdWhitePiece == Piece(PieceColor::White, pieceType));
}
TEST_CASE("Pieces are not created from invalid symbols", "[Piece][Fundamental]") {
auto symbol = GENERATE('x', 'Z');
auto optPiece = Piece::fromSymbol(symbol);
REQUIRE_FALSE(optPiece.has_value());
}
TEST_CASE("Pieces stream their symbol correctly", "[Piece][Fundamental]") {
auto [blackSymbol, pieceType] = GENERATE(table<char, PieceType>({
{'p', PieceType::Pawn},
{'n', PieceType::Knight},
{'b', PieceType::Bishop},
{'r', PieceType::Rook},
{'q', PieceType::Queen},
{'k', PieceType::King}
}));
auto blackStream = std::stringstream();
auto blackPiece = Piece(PieceColor::Black, pieceType);
blackStream << blackPiece;
auto blackSymbolStr = std::string(1, blackSymbol);
REQUIRE(blackStream.str() == blackSymbolStr);
auto whiteStream = std::stringstream();
auto whitePiece = Piece(PieceColor::White, pieceType);
whiteStream << whitePiece;
auto whiteSymbol = static_cast<char>(std::toupper(blackSymbol));
auto whiteSymbolStr = std::string(1, whiteSymbol);
REQUIRE(whiteStream.str() == whiteSymbolStr);
}
TEST_CASE("PieceColor can be inverted correctly", "[Piece][Fundamental]") {
REQUIRE((!PieceColor::White) == PieceColor::Black);
REQUIRE((!PieceColor::Black) == PieceColor::White);
}

View File

@@ -0,0 +1,20 @@
1nIpz,4r3/pppkn3/8/3p2R1/3P4/8/PPP2P1b/R3K3 w Q - 1 21,e1c1 h2f4 c1b1 f4g5,816,95,90,588,crushing endgame fork short,https://lichess.org/hNgUKDs9#41
Mu4H8,2r1k2r/1p3ppp/p1nqp3/3N4/6P1/3Q3P/PPP2P2/R3R1K1 b k - 0 18,e8g8 d5f6 g7f6 d3d6,1242,76,93,2547,crushing discoveredAttack middlegame short,https://lichess.org/4TidVneQ/black#36
tXqKo,r1b1k2r/1pB2ppp/p7/n2q4/8/3B1N2/P5PP/RN1Q1K2 b kq - 0 19,e8g8 d3h7 g8h7 d1d5,1119,83,94,746,crushing discoveredAttack kingsideAttack opening short,https://lichess.org/7uOa49aA/black#38
w24YE,r3k1r1/pbp1qp2/1pn2bp1/1N2p3/4Q3/PP2P1P1/RBPP2B1/4K2R b Kq - 0 20,e8c8 b5a7 c6a7 e4b7,1418,76,96,4838,crushing middlegame queensideAttack short,https://lichess.org/Xg4JUKxt/black#40
3FThf,2kr1r2/pp3ppp/2n2nq1/4p3/8/2PP1Q2/PP2NPPP/RN2K2R w KQ - 2 16,e1g1 d8d3 f3d3 g6d3,1468,76,85,526,crushing middlegame short trappedPiece,https://lichess.org/IsNuAAN9#31
jJ2Y6,r3kb1r/ppp2ppp/1nb5/6q1/3Q4/2P2P2/PP1NN1PP/R1B1K2R w KQkq - 1 12,e1g1 f8c5 d2b3 c5d4,1251,79,92,1234,crushing opening pin short,https://lichess.org/jXD6blSd#23
RgLWD,r4r1k/1pp1q1pp/p2b1pn1/8/P2P4/1PQ1PN2/1B3PPP/R3K2R w KQ - 3 17,d4d5 d6b4 e1g1 b4c3,1061,76,91,782,crushing middlegame pin short,https://lichess.org/5BMsYBNs#33
Oy4HD,4r1k1/1ppnqpb1/p5pp/3p4/1n1P2PP/PPQ2P2/1B1NN3/R3K2R w KQ - 1 20,e1c1 b4a2 c1b1 a2c3,1022,75,95,2356,crushing fork middlegame short,https://lichess.org/rLlXAUHf#39
mYVLz,r3k2r/pp1q1pp1/2n4p/3Nb3/2P1pN2/P7/R4PPP/3Q1RK1 b kq - 0 16,e8g8 d5f6 g7f6 d1d7,1228,75,96,4950,crushing discoveredAttack middlegame short,https://lichess.org/4Td7Ylh7/black#32
Xru4M,r1b1k2r/ppp2ppp/8/2bq4/8/3B4/PPPQ1PPP/R1B2RK1 b kq - 1 11,e8g8 d3h7 g8h7 d2d5,832,80,98,741,crushing discoveredAttack kingsideAttack middlegame short,https://lichess.org/SUQJEod2/black#22
O3mf8,r1bqk2r/pp3pp1/2nb3p/2pQ4/3P4/2P2N2/PP3PPP/RNB1K2R w KQkq - 0 11,e1g1 d6h2 f3h2 d8d5,992,77,98,503,crushing discoveredAttack kingsideAttack opening short,https://lichess.org/25COtgWc#21
YZphi,1rb2rk1/p4p1p/4p1p1/q1ppb3/6PP/1PN5/P1PQBB2/R3K2R w KQ - 0 17,e1c1 e5c3 d2c3 a5c3,1455,76,73,794,crushing master middlegame short,https://lichess.org/YUCwTutk#33
Xp0Fu,rnbqk2r/pp1p1ppp/2p1p3/3n4/1b1P4/1P1BPN2/P1P2PPP/RNBQK2R w KQkq - 1 6,b1d2 d5c3 e1g1 c3d1,1291,74,98,1101,crushing opening short trappedPiece,https://lichess.org/ZLMwfhTb#11
gSuce,r3k2r/ppp2p1p/2q3p1/3N1b2/4P2P/2bQ4/P1P2PP1/1R1K1B1R b kq - 0 15,e8c8 d5e7 c8b8 e7c6,978,93,97,502,crushing fork middlegame pin short,https://lichess.org/s986T8cn/black#30
ojyVA,r4rk1/1pp2ppp/p7/8/3nq3/P3N1Q1/BPP2PP1/R3KR2 w Q - 5 19,e1c1 d4e2 c1b1 e2g3,1467,75,99,1838,crushing fork middlegame short,https://lichess.org/9QGJ7rZV#37
JRXLt,2q1r1k1/5pbp/r4np1/8/1B2P1b1/Pp3PN1/1P1Q3P/R2NK2R w KQ - 0 19,f3g4 f6e4 e1g1 e4d2,1400,75,93,653,crushing master middlegame short,https://lichess.org/uOcxibZc#37
Mqwig,r3k3/pp1q4/3p3Q/2p1p3/2Pn4/2NP2P1/PP1K2BP/8 b q - 0 22,e8c8 g2h3 d7h3 h6h3,1459,74,95,7529,crushing endgame pin short,https://lichess.org/eMX64gmi/black#44
or8tr,r1bq3r/pp2kppp/3bpn2/1B6/3Q4/2N5/PPP2PPP/R1B1K2R w KQ - 3 10,e1g1 d6h2 g1h2 d8d4,1251,75,97,2368,crushing discoveredAttack kingsideAttack opening short,https://lichess.org/aTyyc4D6#19
ufB48,r3k2r/pp2pp2/n4b1p/1Npq2p1/8/3B1P2/2P2P1P/1R1Q1RK1 b kq - 0 16,e8g8 d3h7 g8h7 d1d5,1044,76,100,578,crushing discoveredAttack master middlegame short,https://lichess.org/4O7cI2vX/black#32
PPhgy,2r1k2r/pp1b1ppp/4p2n/3pP3/1b1q1P2/2NB4/PP1Q2PP/R1B2R1K b k - 5 13,e8g8 d3h7 g8h7 d2d4,1120,79,89,831,crushing discoveredAttack kingsideAttack middlegame short,https://lichess.org/NDtiGLde/black#26
1 1nIpz 4r3/pppkn3/8/3p2R1/3P4/8/PPP2P1b/R3K3 w Q - 1 21 e1c1 h2f4 c1b1 f4g5 816 95 90 588 crushing endgame fork short https://lichess.org/hNgUKDs9#41
2 Mu4H8 2r1k2r/1p3ppp/p1nqp3/3N4/6P1/3Q3P/PPP2P2/R3R1K1 b k - 0 18 e8g8 d5f6 g7f6 d3d6 1242 76 93 2547 crushing discoveredAttack middlegame short https://lichess.org/4TidVneQ/black#36
3 tXqKo r1b1k2r/1pB2ppp/p7/n2q4/8/3B1N2/P5PP/RN1Q1K2 b kq - 0 19 e8g8 d3h7 g8h7 d1d5 1119 83 94 746 crushing discoveredAttack kingsideAttack opening short https://lichess.org/7uOa49aA/black#38
4 w24YE r3k1r1/pbp1qp2/1pn2bp1/1N2p3/4Q3/PP2P1P1/RBPP2B1/4K2R b Kq - 0 20 e8c8 b5a7 c6a7 e4b7 1418 76 96 4838 crushing middlegame queensideAttack short https://lichess.org/Xg4JUKxt/black#40
5 3FThf 2kr1r2/pp3ppp/2n2nq1/4p3/8/2PP1Q2/PP2NPPP/RN2K2R w KQ - 2 16 e1g1 d8d3 f3d3 g6d3 1468 76 85 526 crushing middlegame short trappedPiece https://lichess.org/IsNuAAN9#31
6 jJ2Y6 r3kb1r/ppp2ppp/1nb5/6q1/3Q4/2P2P2/PP1NN1PP/R1B1K2R w KQkq - 1 12 e1g1 f8c5 d2b3 c5d4 1251 79 92 1234 crushing opening pin short https://lichess.org/jXD6blSd#23
7 RgLWD r4r1k/1pp1q1pp/p2b1pn1/8/P2P4/1PQ1PN2/1B3PPP/R3K2R w KQ - 3 17 d4d5 d6b4 e1g1 b4c3 1061 76 91 782 crushing middlegame pin short https://lichess.org/5BMsYBNs#33
8 Oy4HD 4r1k1/1ppnqpb1/p5pp/3p4/1n1P2PP/PPQ2P2/1B1NN3/R3K2R w KQ - 1 20 e1c1 b4a2 c1b1 a2c3 1022 75 95 2356 crushing fork middlegame short https://lichess.org/rLlXAUHf#39
9 mYVLz r3k2r/pp1q1pp1/2n4p/3Nb3/2P1pN2/P7/R4PPP/3Q1RK1 b kq - 0 16 e8g8 d5f6 g7f6 d1d7 1228 75 96 4950 crushing discoveredAttack middlegame short https://lichess.org/4Td7Ylh7/black#32
10 Xru4M r1b1k2r/ppp2ppp/8/2bq4/8/3B4/PPPQ1PPP/R1B2RK1 b kq - 1 11 e8g8 d3h7 g8h7 d2d5 832 80 98 741 crushing discoveredAttack kingsideAttack middlegame short https://lichess.org/SUQJEod2/black#22
11 O3mf8 r1bqk2r/pp3pp1/2nb3p/2pQ4/3P4/2P2N2/PP3PPP/RNB1K2R w KQkq - 0 11 e1g1 d6h2 f3h2 d8d5 992 77 98 503 crushing discoveredAttack kingsideAttack opening short https://lichess.org/25COtgWc#21
12 YZphi 1rb2rk1/p4p1p/4p1p1/q1ppb3/6PP/1PN5/P1PQBB2/R3K2R w KQ - 0 17 e1c1 e5c3 d2c3 a5c3 1455 76 73 794 crushing master middlegame short https://lichess.org/YUCwTutk#33
13 Xp0Fu rnbqk2r/pp1p1ppp/2p1p3/3n4/1b1P4/1P1BPN2/P1P2PPP/RNBQK2R w KQkq - 1 6 b1d2 d5c3 e1g1 c3d1 1291 74 98 1101 crushing opening short trappedPiece https://lichess.org/ZLMwfhTb#11
14 gSuce r3k2r/ppp2p1p/2q3p1/3N1b2/4P2P/2bQ4/P1P2PP1/1R1K1B1R b kq - 0 15 e8c8 d5e7 c8b8 e7c6 978 93 97 502 crushing fork middlegame pin short https://lichess.org/s986T8cn/black#30
15 ojyVA r4rk1/1pp2ppp/p7/8/3nq3/P3N1Q1/BPP2PP1/R3KR2 w Q - 5 19 e1c1 d4e2 c1b1 e2g3 1467 75 99 1838 crushing fork middlegame short https://lichess.org/9QGJ7rZV#37
16 JRXLt 2q1r1k1/5pbp/r4np1/8/1B2P1b1/Pp3PN1/1P1Q3P/R2NK2R w KQ - 0 19 f3g4 f6e4 e1g1 e4d2 1400 75 93 653 crushing master middlegame short https://lichess.org/uOcxibZc#37
17 Mqwig r3k3/pp1q4/3p3Q/2p1p3/2Pn4/2NP2P1/PP1K2BP/8 b q - 0 22 e8c8 g2h3 d7h3 h6h3 1459 74 95 7529 crushing endgame pin short https://lichess.org/eMX64gmi/black#44
18 or8tr r1bq3r/pp2kppp/3bpn2/1B6/3Q4/2N5/PPP2PPP/R1B1K2R w KQ - 3 10 e1g1 d6h2 g1h2 d8d4 1251 75 97 2368 crushing discoveredAttack kingsideAttack opening short https://lichess.org/aTyyc4D6#19
19 ufB48 r3k2r/pp2pp2/n4b1p/1Npq2p1/8/3B1P2/2P2P1P/1R1Q1RK1 b kq - 0 16 e8g8 d3h7 g8h7 d1d5 1044 76 100 578 crushing discoveredAttack master middlegame short https://lichess.org/4O7cI2vX/black#32
20 PPhgy 2r1k2r/pp1b1ppp/4p2n/3pP3/1b1q1P2/2NB4/PP1Q2PP/R1B2R1K b k - 5 13 e8g8 d3h7 g8h7 d2d4 1120 79 89 831 crushing discoveredAttack kingsideAttack middlegame short https://lichess.org/NDtiGLde/black#26

View File

@@ -0,0 +1,20 @@
LjCmb,1k1r3r/pp4Rp/1n2Bp2/2pPq3/1Q2N3/P6P/1P6/K2R4 w - c6 0 29,d5c6 d8d1 a1a2 e5e6,1177,76,94,1259,crushing hangingPiece middlegame short,https://lichess.org/Yk2zG0UY#57
04bSF,8/8/4kp2/2pPp1p1/1p4P1/1P1PK3/r1P1RP2/8 b - - 0 40,e6d5 c2c4 b4c3 e2a2,1055,78,94,722,crushing discoveredAttack endgame rookEndgame short,https://lichess.org/Ecn7TQaC/black#80
AF9UO,2kr2nr/ppp3pp/2bb1p2/5q2/3Pp3/1BP3P1/PP3P1P/RNBQR1K1 b - d3 0 13,e4d3 b3e6 f5e6 e1e6,976,78,99,1079,crushing fork opening short,https://lichess.org/fVTwPwnn/black#26
DeL19,2b2rk1/p4ppp/2p1p3/2qpP3/5B1P/3B1PPK/1r6/R2Q3R w - d6 0 24,e5d6 e6e5 g3g4 e5f4,1338,76,93,539,crushing discoveredAttack middlegame short,https://lichess.org/xu3NKiH3#47
m2n9Q,2r5/B2q2bp/2Np4/1Q1Ppkp1/2P2pP1/5P2/P6P/6K1 b - g3 0 33,f4g3 c6d4 e5d4 b5d7,1426,75,97,7352,crushing discoveredAttack endgame short,https://lichess.org/mYaK9ddh/black#66
r2rqH,1B6/7p/2p1k1p1/1pKpnpP1/8/8/PPP2P2/8 w - f6 0 33,g5f6 e5d7 c5c6 d7b8,1329,77,91,528,crushing endgame fork short,https://lichess.org/3jItgkvn#65
t18DC,8/7p/3k2p1/8/1p1p2P1/1P1P1K2/r1P2R2/8 b - - 2 44,d6d5 c2c4 d4c3 f2a2,1060,83,83,516,crushing discoveredAttack endgame rookEndgame short,https://lichess.org/RIDIKGiy/black#88
Gc8wi,4rk2/1p5p/2p1q1pP/1p1pPp2/rP1P2P1/P1R1QPK1/8/4R3 w - f6 0 34,e5f6 e6d6 e3e5 e8e5,1417,74,95,6861,crushing endgame short,https://lichess.org/YiVM7jB1#67
RCtAF,r1bq1rk1/1p3pp1/p1np4/2p1pPPp/P1B1P1n1/3P4/1PP3P1/RNBQ1RK1 w - h6 0 12,g5h6 d8h4 d1g4 h4g4,1372,76,91,547,crushing middlegame short,https://lichess.org/rXkJ3qWC#23
yLkJ8,2r2rk1/3q1ppp/3b4/2pP3b/3QP3/2N5/PP3PPP/R1B2RK1 w - c6 0 17,d5c6 d6h2 g1h2 d7d4,1278,74,90,1312,crushing discoveredAttack kingsideAttack middlegame short,https://lichess.org/zu4W2Xjc#33
hQiNO,8/2r2p1R/pk2p3/4P3/1P1K1P2/1P6/8/8 w - - 5 45,d4e4 f7f5 e5f6 c7h7,1226,75,98,3368,crushing discoveredAttack endgame rookEndgame short,https://lichess.org/kiGIgx3X#89
XcSfQ,8/R4pr1/2p3k1/1p4Pp/3P1P1P/P4K2/1P6/8 w - - 1 34,f3e4 f7f5 g5f6 g7a7,1435,74,95,7150,crushing discoveredAttack endgame rookEndgame short,https://lichess.org/H2FyMIZK#67
mqUlP,r3r1k1/bb1q1pp1/p6p/2p5/1PPp4/P2BnP2/3QNBPP/R3R2K b - c3 0 22,d4c3 d3h7 g8h7 d2d7,1389,75,97,7843,crushing discoveredAttack middlegame short,https://lichess.org/2GkHylJl/black#44
BlgSP,3r1k2/p2r1p1R/1pn1p1p1/2p3P1/2P1KP2/P1RPP3/5N2/8 w - - 1 34,f2g4 f7f5 g5f6 d7h7,1414,75,97,8105,crushing discoveredAttack endgame fork master short,https://lichess.org/SVDzwDrX#67
8Wf37,2r3k1/8/1B1Qp1r1/8/4PPp1/P5Pp/1P5P/2q2RK1 b - f3 0 28,g4f3 f1c1 c8c1 g1f2,1131,77,93,2318,crushing endgame short,https://lichess.org/MgBKmMyw/black#56
x1ST3,8/5p1r/r1pkp1p1/p5P1/P2PKP2/1RR4P/8/8 w - - 6 44,b3b7 f7f5 g5f6 h7b7,1206,75,88,120,crushing discoveredAttack endgame rookEndgame short,https://lichess.org/VKjN7j2C#87
8zW22,1R6/1P6/5p2/5k2/5Pp1/1r4P1/6K1/8 b - f3 0 67,g4f3 g2f2 b3b2 f2f3,1125,77,93,2162,crushing defensiveMove endgame rookEndgame short,https://lichess.org/IGmSHmFL/black#134
GNTiD,r1bq1rk1/2p4p/1p1p2p1/p2Pp1N1/P1P1p3/6P1/1P3P1P/R2Q1RK1 w - e6 0 17,d5e6 d8g5 d1d5 g5d5,1172,77,93,560,crushing hangingPiece middlegame short,https://lichess.org/Dvdu67gt#33
DyB55,8/kpr2p1R/p3p1p1/2b1P1P1/4pP2/1PP2K2/3B4/8 w - - 0 34,f3e4 f7f5 e5f6 c7h7,988,76,95,633,crushing discoveredAttack endgame short,https://lichess.org/E6h2U3g9#67
a3jh8,4r1k1/p2n2b1/1p1Br1pp/2p1Pp2/P3R3/5N1P/1PP2PP1/4R1K1 w - f6 0 28,e5f6 e6e4 e1e4 e8e4,1156,77,95,3041,crushing middlegame short,https://lichess.org/PMYUPzpW#55
1 LjCmb 1k1r3r/pp4Rp/1n2Bp2/2pPq3/1Q2N3/P6P/1P6/K2R4 w - c6 0 29 d5c6 d8d1 a1a2 e5e6 1177 76 94 1259 crushing hangingPiece middlegame short https://lichess.org/Yk2zG0UY#57
2 04bSF 8/8/4kp2/2pPp1p1/1p4P1/1P1PK3/r1P1RP2/8 b - - 0 40 e6d5 c2c4 b4c3 e2a2 1055 78 94 722 crushing discoveredAttack endgame rookEndgame short https://lichess.org/Ecn7TQaC/black#80
3 AF9UO 2kr2nr/ppp3pp/2bb1p2/5q2/3Pp3/1BP3P1/PP3P1P/RNBQR1K1 b - d3 0 13 e4d3 b3e6 f5e6 e1e6 976 78 99 1079 crushing fork opening short https://lichess.org/fVTwPwnn/black#26
4 DeL19 2b2rk1/p4ppp/2p1p3/2qpP3/5B1P/3B1PPK/1r6/R2Q3R w - d6 0 24 e5d6 e6e5 g3g4 e5f4 1338 76 93 539 crushing discoveredAttack middlegame short https://lichess.org/xu3NKiH3#47
5 m2n9Q 2r5/B2q2bp/2Np4/1Q1Ppkp1/2P2pP1/5P2/P6P/6K1 b - g3 0 33 f4g3 c6d4 e5d4 b5d7 1426 75 97 7352 crushing discoveredAttack endgame short https://lichess.org/mYaK9ddh/black#66
6 r2rqH 1B6/7p/2p1k1p1/1pKpnpP1/8/8/PPP2P2/8 w - f6 0 33 g5f6 e5d7 c5c6 d7b8 1329 77 91 528 crushing endgame fork short https://lichess.org/3jItgkvn#65
7 t18DC 8/7p/3k2p1/8/1p1p2P1/1P1P1K2/r1P2R2/8 b - - 2 44 d6d5 c2c4 d4c3 f2a2 1060 83 83 516 crushing discoveredAttack endgame rookEndgame short https://lichess.org/RIDIKGiy/black#88
8 Gc8wi 4rk2/1p5p/2p1q1pP/1p1pPp2/rP1P2P1/P1R1QPK1/8/4R3 w - f6 0 34 e5f6 e6d6 e3e5 e8e5 1417 74 95 6861 crushing endgame short https://lichess.org/YiVM7jB1#67
9 RCtAF r1bq1rk1/1p3pp1/p1np4/2p1pPPp/P1B1P1n1/3P4/1PP3P1/RNBQ1RK1 w - h6 0 12 g5h6 d8h4 d1g4 h4g4 1372 76 91 547 crushing middlegame short https://lichess.org/rXkJ3qWC#23
10 yLkJ8 2r2rk1/3q1ppp/3b4/2pP3b/3QP3/2N5/PP3PPP/R1B2RK1 w - c6 0 17 d5c6 d6h2 g1h2 d7d4 1278 74 90 1312 crushing discoveredAttack kingsideAttack middlegame short https://lichess.org/zu4W2Xjc#33
11 hQiNO 8/2r2p1R/pk2p3/4P3/1P1K1P2/1P6/8/8 w - - 5 45 d4e4 f7f5 e5f6 c7h7 1226 75 98 3368 crushing discoveredAttack endgame rookEndgame short https://lichess.org/kiGIgx3X#89
12 XcSfQ 8/R4pr1/2p3k1/1p4Pp/3P1P1P/P4K2/1P6/8 w - - 1 34 f3e4 f7f5 g5f6 g7a7 1435 74 95 7150 crushing discoveredAttack endgame rookEndgame short https://lichess.org/H2FyMIZK#67
13 mqUlP r3r1k1/bb1q1pp1/p6p/2p5/1PPp4/P2BnP2/3QNBPP/R3R2K b - c3 0 22 d4c3 d3h7 g8h7 d2d7 1389 75 97 7843 crushing discoveredAttack middlegame short https://lichess.org/2GkHylJl/black#44
14 BlgSP 3r1k2/p2r1p1R/1pn1p1p1/2p3P1/2P1KP2/P1RPP3/5N2/8 w - - 1 34 f2g4 f7f5 g5f6 d7h7 1414 75 97 8105 crushing discoveredAttack endgame fork master short https://lichess.org/SVDzwDrX#67
15 8Wf37 2r3k1/8/1B1Qp1r1/8/4PPp1/P5Pp/1P5P/2q2RK1 b - f3 0 28 g4f3 f1c1 c8c1 g1f2 1131 77 93 2318 crushing endgame short https://lichess.org/MgBKmMyw/black#56
16 x1ST3 8/5p1r/r1pkp1p1/p5P1/P2PKP2/1RR4P/8/8 w - - 6 44 b3b7 f7f5 g5f6 h7b7 1206 75 88 120 crushing discoveredAttack endgame rookEndgame short https://lichess.org/VKjN7j2C#87
17 8zW22 1R6/1P6/5p2/5k2/5Pp1/1r4P1/6K1/8 b - f3 0 67 g4f3 g2f2 b3b2 f2f3 1125 77 93 2162 crushing defensiveMove endgame rookEndgame short https://lichess.org/IGmSHmFL/black#134
18 GNTiD r1bq1rk1/2p4p/1p1p2p1/p2Pp1N1/P1P1p3/6P1/1P3P1P/R2Q1RK1 w - e6 0 17 d5e6 d8g5 d1d5 g5d5 1172 77 93 560 crushing hangingPiece middlegame short https://lichess.org/Dvdu67gt#33
19 DyB55 8/kpr2p1R/p3p1p1/2b1P1P1/4pP2/1PP2K2/3B4/8 w - - 0 34 f3e4 f7f5 e5f6 c7h7 988 76 95 633 crushing discoveredAttack endgame short https://lichess.org/E6h2U3g9#67
20 a3jh8 4r1k1/p2n2b1/1p1Br1pp/2p1Pp2/P3R3/5N1P/1PP2PP1/4R1K1 w - f6 0 28 e5f6 e6e4 e1e4 e8e4 1156 77 95 3041 crushing middlegame short https://lichess.org/PMYUPzpW#55

View File

@@ -0,0 +1,18 @@
gjB0I,r1r3k1/p3nppp/5q2/3pp3/3nQ1P1/P1P2N1P/P2PPPB1/R1B1KR2 w Q - 0 15,e4e5 d4f3 g2f3 f6e5,1441,77,96,7017,crushing intermezzo middlegame short,https://lichess.org/NNlhThCX#29
DjF9F,7k/1q4p1/PP2r2p/8/2Pp4/3p3P/4QPK1/RR6 w - - 0 37,e2f3 e6g6 g2h2 b7f3,1026,79,96,936,crushing deflection endgame pin short,https://lichess.org/ZRdpTIc7#73
sdK1f,7R/N3p3/4k1b1/6p1/5bP1/1P3P1P/PKP2n2/8 w - - 5 32,h3h4 f4e5 b2b1 e5h8,1350,75,94,4319,crushing endgame fork short,https://lichess.org/jRPMtIwq#63
c4Q2K,6k1/2pp4/1p1b2p1/p2n1rNp/7P/1P1Q3K/P4P2/5R2 w - - 2 40,g5e4 d5f4 h3h2 f4d3,964,75,100,633,crushing discoveredAttack endgame fork short,https://lichess.org/Wr2XI4kL#79
JMggH,r1b1k1nr/pp2bBpp/1np5/8/3P4/3q1N2/PP1N1KPP/R1BQ3R b kq - 0 13,e8f7 f3e5 f7f8 e5d3,1062,76,98,531,crushing fork opening short,https://lichess.org/cV3k9SJS/black#26
UkI37,8/7p/1b4k1/pB6/P2p1BP1/4nK2/8/8 b - - 3 48,e3c2 b5d3,1186,76,94,1406,crushing endgame oneMove,https://lichess.org/6Zy6lEOJ/black#96
u2uUc,4r3/pp3qk1/2p2n2/3pQP1p/8/2NB4/PPP2bPP/2K2R2 w - - 2 24,e5f4 f2e3 f4e3 e8e3,1382,74,97,6750,crushing fork middlegame short,https://lichess.org/SA2OAz7V#47
95aih,r1b1r1k1/pp3ppp/3p4/4n3/3p2B1/1P6/P1P2PPP/RN2R1K1 w - - 0 17,g4c8 e5f3 g2f3 e8e1,1180,78,94,4398,crushing discoveredAttack kingsideAttack middlegame short,https://lichess.org/OFPiuoKw#33
TGtYY,2r2rk1/ppqb1pp1/7p/4p3/4Qn2/1P1B4/PBPP1PPP/2KR3R w - - 6 19,b2e5 f4d3 e4d3 c7e5,1257,75,94,975,crushing middlegame pin queensideAttack short,https://lichess.org/VKOdc5WH#37
UFDsq,2R5/p2rr1pk/1p2b2p/8/5R1P/4B1P1/P4P2/6K1 w - - 11 30,a2a4 d7d1 g1h2 e6c8,1021,75,98,882,crushing discoveredAttack endgame short,https://lichess.org/6WDvsr9F#59
EhBCM,6k1/4bp2/p3b1p1/1pp1P3/5P1p/1P2BK1P/P1B3P1/8 w - - 0 28,f3e4 e6f5 e4d5 f5c2,1106,75,99,1353,bishopEndgame crushing endgame master short skewer,https://lichess.org/kSGgZyH6#55
1udMI,7k/1pp3p1/3p4/p7/6P1/2P1Pr1P/1P2K3/7R b - - 1 29,f3g3 e2f2 g3g4 h3g4,1165,76,90,743,crushing discoveredAttack endgame rookEndgame short trappedPiece,https://lichess.org/BwjVuezV/black#58
TpwxP,2kr4/R1pq1ppp/8/8/8/2PPr3/P1P3P1/R2QK3 w - - 0 23,e1d2 e3d3 c2d3 d7d3,1300,75,96,3003,crushing endgame sacrifice short,https://lichess.org/wRRxYzZB#45
v4SMo,3r2k1/5p1p/p3p1p1/2P1P1P1/5P2/P7/4p2P/2R3K1 w - - 0 31,g1f2 d8d1 f2e2 d1c1,1231,74,99,2872,crushing endgame rookEndgame short,https://lichess.org/80LcrMO8#61
pv5iO,2kr1bnr/pp1n1p1p/2pp1q2/6p1/4Pp2/1PNP3P/1PP3PN/R1BQ1RK1 w - - 0 12,a1a7 f6d4 g1h1 d4a7,1164,75,98,835,crushing fork middlegame short,https://lichess.org/JeND0wKx#23
IFFS9,3q2k1/3brppp/8/p1pp2N1/3P4/N7/4QPPP/1R4K1 w - - 0 25,e2e7 d8e7 b1b8 d7e8,994,75,98,970,crushing defensiveMove endgame hangingPiece short,https://lichess.org/L4E4AcIg#49
2x4l0,5r1k/3b1pp1/p2qp2p/3p4/P1n5/2NBP1P1/1r1P1P1P/R1Q2RK1 b - - 5 24,b2d2 d3c4 d5c4 c3e4,1448,74,93,1998,crushing middlegame short,https://lichess.org/3YGuCQvX/black#48
E9fXH,2kr4/3n1p2/2p2qp1/1p6/6P1/1Bb1P1Br/2P1QP2/1R1R2K1 w - - 2 23,d1d6 h3g3 f2g3 f6d6,1484,74,98,7693,crushing middlegame short,https://lichess.org/OhNQYiqs#45
1 gjB0I r1r3k1/p3nppp/5q2/3pp3/3nQ1P1/P1P2N1P/P2PPPB1/R1B1KR2 w Q - 0 15 e4e5 d4f3 g2f3 f6e5 1441 77 96 7017 crushing intermezzo middlegame short https://lichess.org/NNlhThCX#29
2 DjF9F 7k/1q4p1/PP2r2p/8/2Pp4/3p3P/4QPK1/RR6 w - - 0 37 e2f3 e6g6 g2h2 b7f3 1026 79 96 936 crushing deflection endgame pin short https://lichess.org/ZRdpTIc7#73
3 sdK1f 7R/N3p3/4k1b1/6p1/5bP1/1P3P1P/PKP2n2/8 w - - 5 32 h3h4 f4e5 b2b1 e5h8 1350 75 94 4319 crushing endgame fork short https://lichess.org/jRPMtIwq#63
4 c4Q2K 6k1/2pp4/1p1b2p1/p2n1rNp/7P/1P1Q3K/P4P2/5R2 w - - 2 40 g5e4 d5f4 h3h2 f4d3 964 75 100 633 crushing discoveredAttack endgame fork short https://lichess.org/Wr2XI4kL#79
5 JMggH r1b1k1nr/pp2bBpp/1np5/8/3P4/3q1N2/PP1N1KPP/R1BQ3R b kq - 0 13 e8f7 f3e5 f7f8 e5d3 1062 76 98 531 crushing fork opening short https://lichess.org/cV3k9SJS/black#26
6 UkI37 8/7p/1b4k1/pB6/P2p1BP1/4nK2/8/8 b - - 3 48 e3c2 b5d3 1186 76 94 1406 crushing endgame oneMove https://lichess.org/6Zy6lEOJ/black#96
7 u2uUc 4r3/pp3qk1/2p2n2/3pQP1p/8/2NB4/PPP2bPP/2K2R2 w - - 2 24 e5f4 f2e3 f4e3 e8e3 1382 74 97 6750 crushing fork middlegame short https://lichess.org/SA2OAz7V#47
8 95aih r1b1r1k1/pp3ppp/3p4/4n3/3p2B1/1P6/P1P2PPP/RN2R1K1 w - - 0 17 g4c8 e5f3 g2f3 e8e1 1180 78 94 4398 crushing discoveredAttack kingsideAttack middlegame short https://lichess.org/OFPiuoKw#33
9 TGtYY 2r2rk1/ppqb1pp1/7p/4p3/4Qn2/1P1B4/PBPP1PPP/2KR3R w - - 6 19 b2e5 f4d3 e4d3 c7e5 1257 75 94 975 crushing middlegame pin queensideAttack short https://lichess.org/VKOdc5WH#37
10 UFDsq 2R5/p2rr1pk/1p2b2p/8/5R1P/4B1P1/P4P2/6K1 w - - 11 30 a2a4 d7d1 g1h2 e6c8 1021 75 98 882 crushing discoveredAttack endgame short https://lichess.org/6WDvsr9F#59
11 EhBCM 6k1/4bp2/p3b1p1/1pp1P3/5P1p/1P2BK1P/P1B3P1/8 w - - 0 28 f3e4 e6f5 e4d5 f5c2 1106 75 99 1353 bishopEndgame crushing endgame master short skewer https://lichess.org/kSGgZyH6#55
12 1udMI 7k/1pp3p1/3p4/p7/6P1/2P1Pr1P/1P2K3/7R b - - 1 29 f3g3 e2f2 g3g4 h3g4 1165 76 90 743 crushing discoveredAttack endgame rookEndgame short trappedPiece https://lichess.org/BwjVuezV/black#58
13 TpwxP 2kr4/R1pq1ppp/8/8/8/2PPr3/P1P3P1/R2QK3 w - - 0 23 e1d2 e3d3 c2d3 d7d3 1300 75 96 3003 crushing endgame sacrifice short https://lichess.org/wRRxYzZB#45
14 v4SMo 3r2k1/5p1p/p3p1p1/2P1P1P1/5P2/P7/4p2P/2R3K1 w - - 0 31 g1f2 d8d1 f2e2 d1c1 1231 74 99 2872 crushing endgame rookEndgame short https://lichess.org/80LcrMO8#61
15 pv5iO 2kr1bnr/pp1n1p1p/2pp1q2/6p1/4Pp2/1PNP3P/1PP3PN/R1BQ1RK1 w - - 0 12 a1a7 f6d4 g1h1 d4a7 1164 75 98 835 crushing fork middlegame short https://lichess.org/JeND0wKx#23
16 IFFS9 3q2k1/3brppp/8/p1pp2N1/3P4/N7/4QPPP/1R4K1 w - - 0 25 e2e7 d8e7 b1b8 d7e8 994 75 98 970 crushing defensiveMove endgame hangingPiece short https://lichess.org/L4E4AcIg#49
17 2x4l0 5r1k/3b1pp1/p2qp2p/3p4/P1n5/2NBP1P1/1r1P1P1P/R1Q2RK1 b - - 5 24 b2d2 d3c4 d5c4 c3e4 1448 74 93 1998 crushing middlegame short https://lichess.org/3YGuCQvX/black#48
18 E9fXH 2kr4/3n1p2/2p2qp1/1p6/6P1/1Bb1P1Br/2P1QP2/1R1R2K1 w - - 2 23 d1d6 h3g3 f2g3 f6d6 1484 74 98 7693 crushing middlegame short https://lichess.org/OhNQYiqs#45

View File

@@ -0,0 +1,20 @@
WW5uk,r3kb1r/2p1ppp1/p1b2n1p/3qN3/3P4/4P3/PP3PPP/RNBQK2R w KQkq - 4 11,e1g1 d5g2,760,100,91,649,kingsideAttack mate mateIn1 oneMove opening,https://lichess.org/oBiCLIGA#21
zjfWz,rnbqk2r/ppp1bppp/8/3p2P1/5PP1/3Q4/PPPP4/RNB1K1NR b KQkq - 0 10,e8g8 d3h7,1210,79,90,285,kingsideAttack mate mateIn1 oneMove opening,https://lichess.org/4kj3hdb1/black#20
swBXg,r1b1k1nr/1p3ppp/p2bp3/4q3/8/2NBB3/PPP2PPP/R2QK2R w KQkq - 2 12,e1g1 e5h2,836,85,71,126,kingsideAttack mate mateIn1 oneMove opening,https://lichess.org/lhIYvgoM#23
E1wln,Qn2kbnr/p1q1ppp1/2p5/5bp1/4p3/2N5/PPPPBPPP/R1B1K2R w KQk - 3 10,e1g1 c7h2,1350,77,75,146,kingsideAttack mate mateIn1 oneMove opening,https://lichess.org/mB3slcX0#19
hIf6g,rn2k2r/2qbpp1p/2Np2p1/pB1P4/1p1Q4/7P/PPP2PP1/2KR3R b kq - 0 15,e8g8 c6e7,1020,163,82,11,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/IlQIKE1K/black#30
PKlaU,r1bk3N/1p1pqBpQ/p1p5/2b1p3/3n4/8/PPP2nPP/RNB1K2R w KQ - 0 12,e1g1 d4e2,1427,131,86,61,mate mateIn1 middlegame oneMove,https://lichess.org/KStAa02H#23
HgNow,r3k2r/pppn1p2/4pq1p/8/3P1Q2/P1P1P1B1/5P1P/R3K1R1 b Qkq - 2 18,e8c8 f4c7,931,76,100,195,mate mateIn1 middlegame oneMove queensideAttack,https://lichess.org/kzE6a9h5/black#36
6b7Wt,r3kbnr/ppp4p/2p1bqp1/4Q3/3PPB2/8/PPP2PPP/RN2K2R b KQkq - 2 9,e8c8 e5c7,915,75,99,526,mate mateIn1 oneMove opening queensideAttack,https://lichess.org/rjh2BgbH/black#18
nAfqs,r3k2r/2pq2p1/1b3p2/p6p/P1pP4/2P1PQP1/6P1/R3NRK1 b kq - 0 26,e8c8 f3a8,849,94,87,421,mate mateIn1 middlegame oneMove,https://lichess.org/65g7kSa0/black#52
0sw4O,r3k2r/ppB2ppp/2n1pq2/6b1/4Q1P1/2PB4/PP5P/3K3R b kq - 4 19,e8g8 e4h7,1074,80,71,71,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/g1if65nb/black#38
6kzIH,r1b1k2r/ppp2ppp/2n1pq2/8/3PQn2/P1PB1N2/1BP2PPP/R4RK1 b kq - 8 11,e8g8 e4h7,1154,93,68,44,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/NaDYEX6v/black#22
42Bal,2r1k2r/ppq2ppp/1n2b3/4p3/2P5/P3P1P1/1KQN1PP1/3R1B1R b k - 0 19,e8g8 c2h7,835,83,85,44,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/A2xv3ghS/black#38
AWZQ7,r2qk2r/2p1bppp/p3p3/n7/Pp1P4/3QPPP1/1PB2P2/RN3RK1 b kq - 0 15,e8g8 d3h7,602,96,60,48,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/m6RqcUwC/black#30
P2snV,r3k2r/1p3ppp/2p1bq2/p2n2N1/PbB1Q2P/8/1P3PP1/R1B2K1R b kq - 0 16,e8g8 e4h7,1260,158,82,10,kingsideAttack master mate mateIn1 middlegame oneMove,https://lichess.org/6s9dBTUL/black#32
DLdAn,r3k2r/p2q1p1p/b3pp2/1Nb5/P1Bp4/5Q2/1PP2PPP/R4RK1 b kq - 3 16,e8c8 f3a8,1287,76,94,3968,mate mateIn1 middlegame oneMove,https://lichess.org/l2DeuPYc/black#32
p3Q6M,r3k2r/1b4R1/p1n1p2p/1p1q1p2/3P1Q1P/P2B1N2/1PP5/2K5 b kq - 3 21,e8c8 f4c7,1193,76,90,517,mate mateIn1 middlegame oneMove,https://lichess.org/heIdcTW0/black#42
RsYIC,rnb1k2r/pp3ppp/4p3/q2p2N1/1b1P4/2N1P3/PPQ2PPP/2R1KB1R b Kkq - 0 10,e8g8 c2h7,847,103,89,164,kingsideAttack mate mateIn1 oneMove opening,https://lichess.org/YgEdGJ9v/black#20
aozJ2,3bk2r/p3npp1/2q4p/4Q3/4P3/1P6/PBP2PPP/5RK1 b k - 2 19,e8g8 e5g7,846,91,70,103,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/LNWojJtd/black#38
6PekE,r2qk2r/ppp2ppp/2n5/3p1Q2/3P3b/3B4/P2B2PP/R4K2 b kq - 0 16,e8g8 f5h7,754,82,97,188,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/Ncwq1lnM/black#32
nfUZQ,r2qk2r/pp1n1ppp/8/3Pn3/4Qp2/2N2Bb1/PPP3P1/R1B2K1R b kq - 4 14,e8g8 e4h7,1232,92,69,45,kingsideAttack mate mateIn1 oneMove opening,https://lichess.org/04AZISKa/black#28
1 WW5uk r3kb1r/2p1ppp1/p1b2n1p/3qN3/3P4/4P3/PP3PPP/RNBQK2R w KQkq - 4 11 e1g1 d5g2 760 100 91 649 kingsideAttack mate mateIn1 oneMove opening https://lichess.org/oBiCLIGA#21
2 zjfWz rnbqk2r/ppp1bppp/8/3p2P1/5PP1/3Q4/PPPP4/RNB1K1NR b KQkq - 0 10 e8g8 d3h7 1210 79 90 285 kingsideAttack mate mateIn1 oneMove opening https://lichess.org/4kj3hdb1/black#20
3 swBXg r1b1k1nr/1p3ppp/p2bp3/4q3/8/2NBB3/PPP2PPP/R2QK2R w KQkq - 2 12 e1g1 e5h2 836 85 71 126 kingsideAttack mate mateIn1 oneMove opening https://lichess.org/lhIYvgoM#23
4 E1wln Qn2kbnr/p1q1ppp1/2p5/5bp1/4p3/2N5/PPPPBPPP/R1B1K2R w KQk - 3 10 e1g1 c7h2 1350 77 75 146 kingsideAttack mate mateIn1 oneMove opening https://lichess.org/mB3slcX0#19
5 hIf6g rn2k2r/2qbpp1p/2Np2p1/pB1P4/1p1Q4/7P/PPP2PP1/2KR3R b kq - 0 15 e8g8 c6e7 1020 163 82 11 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/IlQIKE1K/black#30
6 PKlaU r1bk3N/1p1pqBpQ/p1p5/2b1p3/3n4/8/PPP2nPP/RNB1K2R w KQ - 0 12 e1g1 d4e2 1427 131 86 61 mate mateIn1 middlegame oneMove https://lichess.org/KStAa02H#23
7 HgNow r3k2r/pppn1p2/4pq1p/8/3P1Q2/P1P1P1B1/5P1P/R3K1R1 b Qkq - 2 18 e8c8 f4c7 931 76 100 195 mate mateIn1 middlegame oneMove queensideAttack https://lichess.org/kzE6a9h5/black#36
8 6b7Wt r3kbnr/ppp4p/2p1bqp1/4Q3/3PPB2/8/PPP2PPP/RN2K2R b KQkq - 2 9 e8c8 e5c7 915 75 99 526 mate mateIn1 oneMove opening queensideAttack https://lichess.org/rjh2BgbH/black#18
9 nAfqs r3k2r/2pq2p1/1b3p2/p6p/P1pP4/2P1PQP1/6P1/R3NRK1 b kq - 0 26 e8c8 f3a8 849 94 87 421 mate mateIn1 middlegame oneMove https://lichess.org/65g7kSa0/black#52
10 0sw4O r3k2r/ppB2ppp/2n1pq2/6b1/4Q1P1/2PB4/PP5P/3K3R b kq - 4 19 e8g8 e4h7 1074 80 71 71 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/g1if65nb/black#38
11 6kzIH r1b1k2r/ppp2ppp/2n1pq2/8/3PQn2/P1PB1N2/1BP2PPP/R4RK1 b kq - 8 11 e8g8 e4h7 1154 93 68 44 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/NaDYEX6v/black#22
12 42Bal 2r1k2r/ppq2ppp/1n2b3/4p3/2P5/P3P1P1/1KQN1PP1/3R1B1R b k - 0 19 e8g8 c2h7 835 83 85 44 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/A2xv3ghS/black#38
13 AWZQ7 r2qk2r/2p1bppp/p3p3/n7/Pp1P4/3QPPP1/1PB2P2/RN3RK1 b kq - 0 15 e8g8 d3h7 602 96 60 48 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/m6RqcUwC/black#30
14 P2snV r3k2r/1p3ppp/2p1bq2/p2n2N1/PbB1Q2P/8/1P3PP1/R1B2K1R b kq - 0 16 e8g8 e4h7 1260 158 82 10 kingsideAttack master mate mateIn1 middlegame oneMove https://lichess.org/6s9dBTUL/black#32
15 DLdAn r3k2r/p2q1p1p/b3pp2/1Nb5/P1Bp4/5Q2/1PP2PPP/R4RK1 b kq - 3 16 e8c8 f3a8 1287 76 94 3968 mate mateIn1 middlegame oneMove https://lichess.org/l2DeuPYc/black#32
16 p3Q6M r3k2r/1b4R1/p1n1p2p/1p1q1p2/3P1Q1P/P2B1N2/1PP5/2K5 b kq - 3 21 e8c8 f4c7 1193 76 90 517 mate mateIn1 middlegame oneMove https://lichess.org/heIdcTW0/black#42
17 RsYIC rnb1k2r/pp3ppp/4p3/q2p2N1/1b1P4/2N1P3/PPQ2PPP/2R1KB1R b Kkq - 0 10 e8g8 c2h7 847 103 89 164 kingsideAttack mate mateIn1 oneMove opening https://lichess.org/YgEdGJ9v/black#20
18 aozJ2 3bk2r/p3npp1/2q4p/4Q3/4P3/1P6/PBP2PPP/5RK1 b k - 2 19 e8g8 e5g7 846 91 70 103 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/LNWojJtd/black#38
19 6PekE r2qk2r/ppp2ppp/2n5/3p1Q2/3P3b/3B4/P2B2PP/R4K2 b kq - 0 16 e8g8 f5h7 754 82 97 188 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/Ncwq1lnM/black#32
20 nfUZQ r2qk2r/pp1n1ppp/8/3Pn3/4Qp2/2N2Bb1/PPP3P1/R1B2K1R b kq - 4 14 e8g8 e4h7 1232 92 69 45 kingsideAttack mate mateIn1 oneMove opening https://lichess.org/04AZISKa/black#28

View File

@@ -0,0 +1,20 @@
HDgzc,2r2r1q/5p1k/p3p2B/1p2P1Q1/4B3/P7/2p3P1/5R1K b - - 0 31,f7f5 e5f6,1990,81,65,148,discoveredAttack enPassant mate mateIn1 middlegame oneMove,https://lichess.org/ol00Tz8q/black#62
1j5dV,7k/3rN2p/7P/p1pp3n/5pP1/5R2/PPP5/2K5 b - g3 0 38,f4g3 f3f8,890,86,67,64,endgame mate mateIn1 oneMove,https://lichess.org/zjlGPoxK/black#76
QKy7Z,r2q1r2/1p1b1p1R/pnn1p1k1/3pP1P1/3P1P2/P2Q2P1/1P6/R1B2KN1 b - - 1 20,f7f5 e5f6,1840,77,94,5888,discoveredAttack enPassant mate mateIn1 middlegame oneMove,https://lichess.org/gowIv2fI/black#40
4588b,r1b4k/1pq2p1p/2pp1N2/p1nPr3/2P1pP2/P3P2P/1PQ1B1P1/2KR3R b - f3 0 19,e4f3 c2h7,1051,76,82,237,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/6u9WW5eB/black#38
1ymyA,4brk1/ppq5/4p1pQ/4PpRp/2P4r/3BR3/P1P3PP/7K w - f6 0 32,e5f6 c7h2,973,76,100,270,kingsideAttack master masterVsMaster mate mateIn1 middlegame oneMove,https://lichess.org/QVy1wixN#63
SsgM3,r4rk1/1bq3pp/p3p3/1pb1PpN1/6n1/2NB4/PPP1Q1PP/R4R1K w - f6 0 18,e5f6 c7h2,986,75,100,597,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/j8MpBLcv#35
YnOUq,1k1r1b1r/1pq1n3/1n2p3/1P1pPp2/3P2B1/2P5/R4PPB/1N1Q1RK1 w - f6 0 22,e5f6 c7h2,1169,205,83,8,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/uSZx2YbU#43
94PYq,7k/pb4pp/5p2/8/2PqpP2/1P5P/P3Q1PK/8 b - f3 0 26,e4f3 e2e8,600,95,69,68,backRankMate endgame mate mateIn1 oneMove,https://lichess.org/B1rpV4bq/black#52
iKfCM,2b1r1k1/p4p1p/B2N1b2/6pP/3P1K2/2P2P2/P5r1/RN5R w - g6 0 25,h5g6 f6g5,1434,76,85,278,mate mateIn1 middlegame oneMove,https://lichess.org/hLbfMhxx#49
Fyn9D,2r2rk1/2b3p1/4p2p/pp2Pp2/2pPQ1Pq/P1P1P3/1P1B4/R4RK1 w - f6 0 21,e5f6 h4h2,1324,75,98,3566,mate mateIn1 middlegame oneMove,https://lichess.org/RqPUtwYt#41
GAWcc,r4rk1/p1q3p1/bpp1p2p/4Pp2/1bpPB1nB/2N1P3/PP2Q1PP/R4RK1 w - f6 0 16,e5f6 c7h2,1098,80,92,453,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/T2TeS6dB#31
GAhR6,r3r1k1/p7/2p4p/1p2Ppp1/6R1/1P6/PP3PPP/4R1K1 w - f6 0 22,e5f6 e8e1,1010,167,67,10,backRankMate endgame hangingPiece mate mateIn1 oneMove rookEndgame,https://lichess.org/QSZy78Od#43
aA1q8,r7/8/p1R5/1p1P1kp1/1PnP1pP1/5K2/2P1N3/8 b - g3 0 40,f4g3 e2g3,970,78,98,633,endgame mate mateIn1 oneMove,https://lichess.org/dTA4VEdI/black#80
4fBpP,1q6/pp6/4r1pk/2p1PpRn/3p2Q1/1P1P4/1PP3P1/4R2K w - f6 0 35,e5f6 e6e1,761,80,99,539,endgame hangingPiece mate mateIn1 oneMove,https://lichess.org/UA8Kpwh5#69
CX1BO,8/p2n1p2/1p3b1p/3P1bk1/3pPN2/1P3KPP/PB4B1/8 b - e3 0 31,d4e3 h3h4,1177,74,97,3570,endgame mate mateIn1 oneMove,https://lichess.org/oyn66GTz/black#62
ZQj16,r3kb1r/ppqn2p1/2p1p3/3pPpp1/N2P4/3QN3/PPP2PPP/R4RK1 w kq f6 0 14,e5f6 c7h2,1225,77,73,405,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/NaUlTKhY#27
TfjSn,r2qk2r/ppp2pb1/3pn2p/6pn/2N1PpP1/2PB3P/PP3Q2/R1B2RK1 b kq g3 0 15,f4g3 f2f7,1033,86,88,455,attackingF2F7 mate mateIn1 oneMove opening,https://lichess.org/puM6gguU/black#30
0Px2t,8/1b6/p4Q2/1p2Pppk/1P5p/3B3P/P1PN2PK/4q3 w - - 2 36,g2g4 h4g3,1851,78,71,230,enPassant endgame mate mateIn1 oneMove,https://lichess.org/qyXVm3Xe#71
FSGUl,5r1k/8/3p3p/5RpP/5KP1/3Q1P2/8/4q3 w - g6 0 56,h5g6 e1e5,1541,93,84,217579,endgame mate mateIn1 oneMove pin,https://lichess.org/wFoaCTu7#111
akDOj,r1b2rk1/p1q3pp/2p1p3/4Pp2/4Q1n1/2NB4/PPP3PP/R4RK1 w - f6 0 17,e5f6 c7h2,1244,77,41,211,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/rC5UCaJ0#33
1 HDgzc 2r2r1q/5p1k/p3p2B/1p2P1Q1/4B3/P7/2p3P1/5R1K b - - 0 31 f7f5 e5f6 1990 81 65 148 discoveredAttack enPassant mate mateIn1 middlegame oneMove https://lichess.org/ol00Tz8q/black#62
2 1j5dV 7k/3rN2p/7P/p1pp3n/5pP1/5R2/PPP5/2K5 b - g3 0 38 f4g3 f3f8 890 86 67 64 endgame mate mateIn1 oneMove https://lichess.org/zjlGPoxK/black#76
3 QKy7Z r2q1r2/1p1b1p1R/pnn1p1k1/3pP1P1/3P1P2/P2Q2P1/1P6/R1B2KN1 b - - 1 20 f7f5 e5f6 1840 77 94 5888 discoveredAttack enPassant mate mateIn1 middlegame oneMove https://lichess.org/gowIv2fI/black#40
4 4588b r1b4k/1pq2p1p/2pp1N2/p1nPr3/2P1pP2/P3P2P/1PQ1B1P1/2KR3R b - f3 0 19 e4f3 c2h7 1051 76 82 237 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/6u9WW5eB/black#38
5 1ymyA 4brk1/ppq5/4p1pQ/4PpRp/2P4r/3BR3/P1P3PP/7K w - f6 0 32 e5f6 c7h2 973 76 100 270 kingsideAttack master masterVsMaster mate mateIn1 middlegame oneMove https://lichess.org/QVy1wixN#63
6 SsgM3 r4rk1/1bq3pp/p3p3/1pb1PpN1/6n1/2NB4/PPP1Q1PP/R4R1K w - f6 0 18 e5f6 c7h2 986 75 100 597 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/j8MpBLcv#35
7 YnOUq 1k1r1b1r/1pq1n3/1n2p3/1P1pPp2/3P2B1/2P5/R4PPB/1N1Q1RK1 w - f6 0 22 e5f6 c7h2 1169 205 83 8 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/uSZx2YbU#43
8 94PYq 7k/pb4pp/5p2/8/2PqpP2/1P5P/P3Q1PK/8 b - f3 0 26 e4f3 e2e8 600 95 69 68 backRankMate endgame mate mateIn1 oneMove https://lichess.org/B1rpV4bq/black#52
9 iKfCM 2b1r1k1/p4p1p/B2N1b2/6pP/3P1K2/2P2P2/P5r1/RN5R w - g6 0 25 h5g6 f6g5 1434 76 85 278 mate mateIn1 middlegame oneMove https://lichess.org/hLbfMhxx#49
10 Fyn9D 2r2rk1/2b3p1/4p2p/pp2Pp2/2pPQ1Pq/P1P1P3/1P1B4/R4RK1 w - f6 0 21 e5f6 h4h2 1324 75 98 3566 mate mateIn1 middlegame oneMove https://lichess.org/RqPUtwYt#41
11 GAWcc r4rk1/p1q3p1/bpp1p2p/4Pp2/1bpPB1nB/2N1P3/PP2Q1PP/R4RK1 w - f6 0 16 e5f6 c7h2 1098 80 92 453 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/T2TeS6dB#31
12 GAhR6 r3r1k1/p7/2p4p/1p2Ppp1/6R1/1P6/PP3PPP/4R1K1 w - f6 0 22 e5f6 e8e1 1010 167 67 10 backRankMate endgame hangingPiece mate mateIn1 oneMove rookEndgame https://lichess.org/QSZy78Od#43
13 aA1q8 r7/8/p1R5/1p1P1kp1/1PnP1pP1/5K2/2P1N3/8 b - g3 0 40 f4g3 e2g3 970 78 98 633 endgame mate mateIn1 oneMove https://lichess.org/dTA4VEdI/black#80
14 4fBpP 1q6/pp6/4r1pk/2p1PpRn/3p2Q1/1P1P4/1PP3P1/4R2K w - f6 0 35 e5f6 e6e1 761 80 99 539 endgame hangingPiece mate mateIn1 oneMove https://lichess.org/UA8Kpwh5#69
15 CX1BO 8/p2n1p2/1p3b1p/3P1bk1/3pPN2/1P3KPP/PB4B1/8 b - e3 0 31 d4e3 h3h4 1177 74 97 3570 endgame mate mateIn1 oneMove https://lichess.org/oyn66GTz/black#62
16 ZQj16 r3kb1r/ppqn2p1/2p1p3/3pPpp1/N2P4/3QN3/PPP2PPP/R4RK1 w kq f6 0 14 e5f6 c7h2 1225 77 73 405 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/NaUlTKhY#27
17 TfjSn r2qk2r/ppp2pb1/3pn2p/6pn/2N1PpP1/2PB3P/PP3Q2/R1B2RK1 b kq g3 0 15 f4g3 f2f7 1033 86 88 455 attackingF2F7 mate mateIn1 oneMove opening https://lichess.org/puM6gguU/black#30
18 0Px2t 8/1b6/p4Q2/1p2Pppk/1P5p/3B3P/P1PN2PK/4q3 w - - 2 36 g2g4 h4g3 1851 78 71 230 enPassant endgame mate mateIn1 oneMove https://lichess.org/qyXVm3Xe#71
19 FSGUl 5r1k/8/3p3p/5RpP/5KP1/3Q1P2/8/4q3 w - g6 0 56 h5g6 e1e5 1541 93 84 217579 endgame mate mateIn1 oneMove pin https://lichess.org/wFoaCTu7#111
20 akDOj r1b2rk1/p1q3pp/2p1p3/4Pp2/4Q1n1/2NB4/PPP3PP/R4RK1 w - f6 0 17 e5f6 c7h2 1244 77 41 211 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/rC5UCaJ0#33

View File

@@ -0,0 +1,20 @@
jrJls,2bQ1k1r/1p3p2/p4b1p/4pNp1/2q5/8/PPP2PPP/1K1RR3 b - - 3 23,f6d8 d1d8,779,82,97,239,mate mateIn1 middlegame oneMove,https://lichess.org/gQa01loO/black#46
rZoKr,5rk1/ppp5/2n4p/3b2p1/6R1/P1B1P2P/1Pq5/R4QK1 w - - 2 29,f1d1 c2f2,1467,79,81,132,mate mateIn1 middlegame oneMove,https://lichess.org/haKJxadR#57
0urF2,2kr4/ppp2ppp/2n5/8/1P1PrP2/q4bP1/P3N2P/1R1Q1RBK w - - 1 18,f1f3 a3f3,922,80,96,245,hangingPiece kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/Ea0aHiBh#35
2HNcF,r3rk2/5ppQ/b1ppnq1p/p7/P1P5/2N5/1PB2PP1/R3R1K1 b - - 5 23,e6g5 h7h8,1031,76,92,123,mate mateIn1 middlegame oneMove,https://lichess.org/TQl97w12/black#46
qFJW4,r5k1/ppp1nrpp/1b2Q3/8/6n1/B1N5/P5PP/R4RqK w - - 4 21,f1g1 g4f2,935,77,98,647,mate mateIn1 middlegame oneMove smotheredMate,https://lichess.org/4IhbR7Z4#41
07FBh,r7/1Rrk1p1P/1R2bQn1/3pP3/3P1p2/p1P3PK/5q2/3B4 w - - 0 46,b6e6 f2g3,1378,75,80,255,master masterVsMaster mate mateIn1 middlegame oneMove,https://lichess.org/N6cvrT1h#91
BOh5N,r1b1k2r/ppp2pp1/2p5/2b1q1Bp/4P1n1/2PP4/PP2BPPP/RN1Q1RK1 w kq - 1 10,d3d4 e5h2,1110,79,87,307,kingsideAttack mate mateIn1 oneMove opening,https://lichess.org/hBADdo6I#19
8K7dF,5Nr1/1p5k/3p1Q2/p2Pn3/4q3/1P6/P5RP/7K b - - 3 38,g8f8 f6g7,1374,78,85,113,endgame master mate mateIn1 oneMove,https://lichess.org/dVBFepDr/black#76
pfcY2,1rq4r/pk3ppp/Q1p5/8/R7/5P2/PPP4P/2KR4 b - - 14 24,b7a8 a6a7,969,76,100,457,endgame mate mateIn1 oneMove queensideAttack,https://lichess.org/iq1SsukA/black#48
1bg7G,r4rk1/2q4p/2p5/P1bp1pp1/4pNn1/2B1P2P/P1P2PP1/R2Q1RK1 w - - 0 18,f4d5 c7h2,1313,77,85,102,mate mateIn1 middlegame oneMove,https://lichess.org/6jomSlbK#35
Rsm4I,3r1Q1k/6p1/7p/1p2q3/8/1P1B1R2/2P3PP/7K b - - 0 33,d8f8 f3f8,600,90,68,137,endgame mate mateIn1 oneMove,https://lichess.org/cBl2WADX/black#66
lq6Om,5Q1k/1b2q1pp/p3B3/1pp1P3/8/2N5/PP4PP/5R1K b - - 0 28,e7f8 f1f8,629,104,84,148,backRankMate endgame mate mateIn1 oneMove,https://lichess.org/Hcocq7AO/black#56
WOhqq,8/1b4k1/p1q2rp1/8/2PQ4/1P1p3P/1P3RP1/7K w - - 2 41,f2f6 c6g2,1000,79,81,84,endgame mate mateIn1 oneMove,https://lichess.org/s4VKQPNb#81
1ZxkV,r1bqkb1r/p1p2ppp/2p5/3pN3/4n3/5Q2/PPPP1PPP/RNB1K2R b KQkq - 1 7,f8d6 f3f7,1102,79,100,66,attackingF2F7 mate mateIn1 oneMove opening,https://lichess.org/8mudJHJO/black#14
ozS9D,6k1/ppp2pp1/1nn2q1p/3p4/5B2/1PPB1P2/P1P3PP/4Q1K1 b - - 0 21,f6f4 e1e8,653,89,60,146,endgame master mate mateIn1 oneMove,https://lichess.org/r5n4dpAN/black#42
8xWfh,r4rk1/2p3pp/p2p4/1p1P1b2/5Q2/P1P1P2P/BP4q1/2KR3R w - - 0 19,h1g1 g2c2,1323,149,55,14,mate mateIn1 middlegame oneMove,https://lichess.org/nMPORUnV#37
GLtpk,r6r/p1p1kpQ1/3p2p1/2p5/4PP2/5Pq1/PPP1R3/R1B3K1 w - - 2 22,e2g2 g3e1,1195,75,94,1852,mate mateIn1 middlegame oneMove,https://lichess.org/fGjY3KEU#43
kOz0U,8/Q4kp1/2qB1p2/pp2p2p/n3P2P/5P2/2P3PK/8 b - - 5 36,f7e6 a7e7,805,75,100,281,endgame master mate mateIn1 oneMove,https://lichess.org/jS8203Ng/black#72
BEUkI,r1bq1r1k/pp3pR1/1b1p3p/2p2P2/2BBP2n/2N5/PPPQ2PP/R5K1 b - - 0 15,c5d4 d2h6,1080,84,63,46,kingsideAttack mate mateIn1 middlegame oneMove,https://lichess.org/qUYVfwWj/black#30
EAnMf,3R4/5r1k/6p1/4B3/3P1PK1/4r3/8/8 b - - 1 42,e3e1 d8h8,959,118,33,20,endgame master mate mateIn1 oneMove,https://lichess.org/7KoQ0ISo/black#84
1 jrJls 2bQ1k1r/1p3p2/p4b1p/4pNp1/2q5/8/PPP2PPP/1K1RR3 b - - 3 23 f6d8 d1d8 779 82 97 239 mate mateIn1 middlegame oneMove https://lichess.org/gQa01loO/black#46
2 rZoKr 5rk1/ppp5/2n4p/3b2p1/6R1/P1B1P2P/1Pq5/R4QK1 w - - 2 29 f1d1 c2f2 1467 79 81 132 mate mateIn1 middlegame oneMove https://lichess.org/haKJxadR#57
3 0urF2 2kr4/ppp2ppp/2n5/8/1P1PrP2/q4bP1/P3N2P/1R1Q1RBK w - - 1 18 f1f3 a3f3 922 80 96 245 hangingPiece kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/Ea0aHiBh#35
4 2HNcF r3rk2/5ppQ/b1ppnq1p/p7/P1P5/2N5/1PB2PP1/R3R1K1 b - - 5 23 e6g5 h7h8 1031 76 92 123 mate mateIn1 middlegame oneMove https://lichess.org/TQl97w12/black#46
5 qFJW4 r5k1/ppp1nrpp/1b2Q3/8/6n1/B1N5/P5PP/R4RqK w - - 4 21 f1g1 g4f2 935 77 98 647 mate mateIn1 middlegame oneMove smotheredMate https://lichess.org/4IhbR7Z4#41
6 07FBh r7/1Rrk1p1P/1R2bQn1/3pP3/3P1p2/p1P3PK/5q2/3B4 w - - 0 46 b6e6 f2g3 1378 75 80 255 master masterVsMaster mate mateIn1 middlegame oneMove https://lichess.org/N6cvrT1h#91
7 BOh5N r1b1k2r/ppp2pp1/2p5/2b1q1Bp/4P1n1/2PP4/PP2BPPP/RN1Q1RK1 w kq - 1 10 d3d4 e5h2 1110 79 87 307 kingsideAttack mate mateIn1 oneMove opening https://lichess.org/hBADdo6I#19
8 8K7dF 5Nr1/1p5k/3p1Q2/p2Pn3/4q3/1P6/P5RP/7K b - - 3 38 g8f8 f6g7 1374 78 85 113 endgame master mate mateIn1 oneMove https://lichess.org/dVBFepDr/black#76
9 pfcY2 1rq4r/pk3ppp/Q1p5/8/R7/5P2/PPP4P/2KR4 b - - 14 24 b7a8 a6a7 969 76 100 457 endgame mate mateIn1 oneMove queensideAttack https://lichess.org/iq1SsukA/black#48
10 1bg7G r4rk1/2q4p/2p5/P1bp1pp1/4pNn1/2B1P2P/P1P2PP1/R2Q1RK1 w - - 0 18 f4d5 c7h2 1313 77 85 102 mate mateIn1 middlegame oneMove https://lichess.org/6jomSlbK#35
11 Rsm4I 3r1Q1k/6p1/7p/1p2q3/8/1P1B1R2/2P3PP/7K b - - 0 33 d8f8 f3f8 600 90 68 137 endgame mate mateIn1 oneMove https://lichess.org/cBl2WADX/black#66
12 lq6Om 5Q1k/1b2q1pp/p3B3/1pp1P3/8/2N5/PP4PP/5R1K b - - 0 28 e7f8 f1f8 629 104 84 148 backRankMate endgame mate mateIn1 oneMove https://lichess.org/Hcocq7AO/black#56
13 WOhqq 8/1b4k1/p1q2rp1/8/2PQ4/1P1p3P/1P3RP1/7K w - - 2 41 f2f6 c6g2 1000 79 81 84 endgame mate mateIn1 oneMove https://lichess.org/s4VKQPNb#81
14 1ZxkV r1bqkb1r/p1p2ppp/2p5/3pN3/4n3/5Q2/PPPP1PPP/RNB1K2R b KQkq - 1 7 f8d6 f3f7 1102 79 100 66 attackingF2F7 mate mateIn1 oneMove opening https://lichess.org/8mudJHJO/black#14
15 ozS9D 6k1/ppp2pp1/1nn2q1p/3p4/5B2/1PPB1P2/P1P3PP/4Q1K1 b - - 0 21 f6f4 e1e8 653 89 60 146 endgame master mate mateIn1 oneMove https://lichess.org/r5n4dpAN/black#42
16 8xWfh r4rk1/2p3pp/p2p4/1p1P1b2/5Q2/P1P1P2P/BP4q1/2KR3R w - - 0 19 h1g1 g2c2 1323 149 55 14 mate mateIn1 middlegame oneMove https://lichess.org/nMPORUnV#37
17 GLtpk r6r/p1p1kpQ1/3p2p1/2p5/4PP2/5Pq1/PPP1R3/R1B3K1 w - - 2 22 e2g2 g3e1 1195 75 94 1852 mate mateIn1 middlegame oneMove https://lichess.org/fGjY3KEU#43
18 kOz0U 8/Q4kp1/2qB1p2/pp2p2p/n3P2P/5P2/2P3PK/8 b - - 5 36 f7e6 a7e7 805 75 100 281 endgame master mate mateIn1 oneMove https://lichess.org/jS8203Ng/black#72
19 BEUkI r1bq1r1k/pp3pR1/1b1p3p/2p2P2/2BBP2n/2N5/PPPQ2PP/R5K1 b - - 0 15 c5d4 d2h6 1080 84 63 46 kingsideAttack mate mateIn1 middlegame oneMove https://lichess.org/qUYVfwWj/black#30
20 EAnMf 3R4/5r1k/6p1/4B3/3P1PK1/4r3/8/8 b - - 1 42 e3e1 d8h8 959 118 33 20 endgame master mate mateIn1 oneMove https://lichess.org/7KoQ0ISo/black#84

View File

@@ -0,0 +1,20 @@
C3LDZ,N2k1bnr/pp3ppp/8/5b2/1n1p1B2/8/PP2PPPP/R3KBNR w KQ - 3 10,e1c1 b4a2 c1d2 f8b4,946,76,98,512,mate mateIn2 opening queensideAttack short,https://lichess.org/TEvwwNPR#19
9LFa6,N4b1r/p1p1kp2/4pp1p/1B6/4b3/8/PP3P1P/RNB1K2R w KQ - 0 17,e1g1 h8g8 c1g5 g8g5,1184,81,88,300,mate mateIn2 middlegame short,https://lichess.org/F32R0fa0#33
1pIrM,r3k1r1/p1p1qp2/1p2b1p1/n6p/4Q3/2PB4/2P2PPP/3RR1K1 b q - 3 21,e8c8 e4a8 c8d7 d3b5,1862,77,86,105,doubleCheck mate mateIn2 middlegame queensideAttack short,https://lichess.org/pSb6NXeF/black#42
zr2fX,r2qk2r/ppp2ppp/3p4/2b1p2n/2BnPP2/2NP3P/PPP3P1/R1BQK2R w KQkq - 3 10,e1g1 d4f3 g1h1 h5g3,1815,75,95,5210,doubleCheck kingsideAttack mate mateIn2 opening short,https://lichess.org/kjhbiYdz#19
YpQqh,r1b1k2r/ppb2ppp/2p1p3/5Nq1/3PQ3/2P4P/PPB2PP1/3RR1K1 b kq - 6 20,e8g8 f5e7 g8h8 e4h7,1226,74,97,2181,discoveredAttack kingsideAttack mate mateIn2 middlegame short,https://lichess.org/oqBsdf2S/black#40
DvrCz,r3k3/p1p3p1/1pP3p1/2b5/Q2NP3/4K3/PP3Pq1/R7 b q - 0 24,e8c8 a4a6 c8b8 a6b7,1169,77,93,1757,endgame mate mateIn2 queensideAttack short,https://lichess.org/Foi1kNan/black#48
XtR9Q,r3k2r/pp1n1p2/2p1p2p/5bp1/3P4/4P1B1/P2KBPPP/2R1R3 b kq - 3 17,e8c8 c1c6 b7c6 e2a6,1189,117,70,776,bodenMate mate mateIn2 middlegame queensideAttack sacrifice short,https://lichess.org/ALOKPySz/black#34
ELwWj,r3k3/pp1nqpb1/2p3p1/8/5BP1/5Q2/PPP1B3/2K4R b q - 2 21,e8c8 f3c6 b7c6 e2a6,1180,158,38,144,bodenMate master mate mateIn2 middlegame queensideAttack sacrifice short,https://lichess.org/MkCYHnmC/black#42
c1OJQ,Qn2k2r/p4pp1/1q1bp1p1/8/3P4/3BP3/P2B1PPP/R3K2R w KQk - 2 18,e1c1 d6a3 c1c2 b6b2,1170,76,88,402,mate mateIn2 middlegame queensideAttack short,https://lichess.org/ze00fCw3#35
0NplY,3r1q1r/pkp2p1p/2p2p2/7R/3bN3/1P2NQ2/P1PP2P1/R3K3 w Q - 1 19,e1c1 f8a3 c1b1 a3b2,1095,75,91,481,mate mateIn2 middlegame queensideAttack short,https://lichess.org/iqeYu7au#37
zaghF,r3k1r1/pp1nbp1p/2p1pn2/8/P2q4/2NB1QBP/1PP2PP1/R3R1K1 b q - 1 17,e8c8 f3c6 b7c6 d3a6,1180,114,72,618,bodenMate mate mateIn2 middlegame queensideAttack sacrifice short,https://lichess.org/2QzZrb7U/black#34
micYX,r3k2r/pp1n1pp1/2p2np1/q3p3/3P4/b1P1BQNP/PP3PP1/R3KB1R w KQkq - 1 13,e1c1 a5c3 c1b1 c3b2,1554,80,74,42,mate mateIn2 middlegame pin queensideAttack short,https://lichess.org/6fCoAKep#25
LjS86,r1bqk2r/p3bppp/2p1n3/1p2pQ2/4N3/2PB4/P1PP1PPP/R1B2RK1 b kq - 4 12,e8g8 e4f6 g8h8 f5h7,1122,79,72,358,kingsideAttack mate mateIn2 opening short,https://lichess.org/O55hxxVw/black#24
0uCn9,r5kr/pp2p1b1/1q1p4/2pPnbP1/4N3/5P2/PPPBQ2P/R3KBNR w KQ - 5 16,e1c1 e5d3 c1b1 b6b2,1522,76,92,1510,mate mateIn2 middlegame queensideAttack short,https://lichess.org/fpIzh0mk#31
MLdUA,r3k2r/1p3p1p/p2p1B1b/4pP2/1PP5/q7/2K2PPP/3Q1B1R b kq - 3 21,e8g8 d1g4 h6g7 g4g7,1365,81,40,68,kingsideAttack mate mateIn2 middlegame short,https://lichess.org/eBsszmz6/black#42
AhG2i,rn2k2r/2q2pp1/p3p1p1/2Np2N1/1P1P1n2/P7/2PQ1PPP/R3K2R w KQkq - 2 18,e1g1 f4e2 g1h1 c7h2,1345,76,85,185,discoveredAttack kingsideAttack mate mateIn2 middlegame short,https://lichess.org/eNauwPCr#35
vnoDi,r3k3/p3q1p1/2p2n2/2P2p2/1P3Br1/5Q2/P4PPP/RN4K1 b q - 1 21,e8c8 f3c6 e7c7 c6c7,1222,79,92,1655,mate mateIn2 middlegame queensideAttack short,https://lichess.org/nq7O55Iv/black#42
KCfTj,r1b1k2r/pppp1Npp/2n5/4p3/2B4q/5Q2/PPPP1b1P/RNB4K b kq - 0 10,e8g8 f7h6 g8h8 f3f8,1092,78,98,2011,deflection discoveredAttack doubleCheck kingsideAttack mate mateIn2 middlegame short,https://lichess.org/5aGYiZI2/black#20
W6DEV,r3kb1r/2p2p2/p1P1p3/4P1p1/Pp1q4/8/1P1NQ1PP/R3K2R b KQkq - 1 20,e8c8 e2a6 c8b8 a6b7,1100,80,95,536,mate mateIn2 middlegame queensideAttack short,https://lichess.org/GEq3AYMj/black#40
lo4i9,r3k2r/pp1nqppp/2p1pn2/5b2/1bB2B2/3P1QPP/PPP1NP2/2KR3R b kq - 4 13,e8c8 f3c6 b7c6 c4a6,1061,95,85,1074,bodenMate mate mateIn2 middlegame queensideAttack sacrifice short,https://lichess.org/LmkZcypC/black#26
1 C3LDZ N2k1bnr/pp3ppp/8/5b2/1n1p1B2/8/PP2PPPP/R3KBNR w KQ - 3 10 e1c1 b4a2 c1d2 f8b4 946 76 98 512 mate mateIn2 opening queensideAttack short https://lichess.org/TEvwwNPR#19
2 9LFa6 N4b1r/p1p1kp2/4pp1p/1B6/4b3/8/PP3P1P/RNB1K2R w KQ - 0 17 e1g1 h8g8 c1g5 g8g5 1184 81 88 300 mate mateIn2 middlegame short https://lichess.org/F32R0fa0#33
3 1pIrM r3k1r1/p1p1qp2/1p2b1p1/n6p/4Q3/2PB4/2P2PPP/3RR1K1 b q - 3 21 e8c8 e4a8 c8d7 d3b5 1862 77 86 105 doubleCheck mate mateIn2 middlegame queensideAttack short https://lichess.org/pSb6NXeF/black#42
4 zr2fX r2qk2r/ppp2ppp/3p4/2b1p2n/2BnPP2/2NP3P/PPP3P1/R1BQK2R w KQkq - 3 10 e1g1 d4f3 g1h1 h5g3 1815 75 95 5210 doubleCheck kingsideAttack mate mateIn2 opening short https://lichess.org/kjhbiYdz#19
5 YpQqh r1b1k2r/ppb2ppp/2p1p3/5Nq1/3PQ3/2P4P/PPB2PP1/3RR1K1 b kq - 6 20 e8g8 f5e7 g8h8 e4h7 1226 74 97 2181 discoveredAttack kingsideAttack mate mateIn2 middlegame short https://lichess.org/oqBsdf2S/black#40
6 DvrCz r3k3/p1p3p1/1pP3p1/2b5/Q2NP3/4K3/PP3Pq1/R7 b q - 0 24 e8c8 a4a6 c8b8 a6b7 1169 77 93 1757 endgame mate mateIn2 queensideAttack short https://lichess.org/Foi1kNan/black#48
7 XtR9Q r3k2r/pp1n1p2/2p1p2p/5bp1/3P4/4P1B1/P2KBPPP/2R1R3 b kq - 3 17 e8c8 c1c6 b7c6 e2a6 1189 117 70 776 bodenMate mate mateIn2 middlegame queensideAttack sacrifice short https://lichess.org/ALOKPySz/black#34
8 ELwWj r3k3/pp1nqpb1/2p3p1/8/5BP1/5Q2/PPP1B3/2K4R b q - 2 21 e8c8 f3c6 b7c6 e2a6 1180 158 38 144 bodenMate master mate mateIn2 middlegame queensideAttack sacrifice short https://lichess.org/MkCYHnmC/black#42
9 c1OJQ Qn2k2r/p4pp1/1q1bp1p1/8/3P4/3BP3/P2B1PPP/R3K2R w KQk - 2 18 e1c1 d6a3 c1c2 b6b2 1170 76 88 402 mate mateIn2 middlegame queensideAttack short https://lichess.org/ze00fCw3#35
10 0NplY 3r1q1r/pkp2p1p/2p2p2/7R/3bN3/1P2NQ2/P1PP2P1/R3K3 w Q - 1 19 e1c1 f8a3 c1b1 a3b2 1095 75 91 481 mate mateIn2 middlegame queensideAttack short https://lichess.org/iqeYu7au#37
11 zaghF r3k1r1/pp1nbp1p/2p1pn2/8/P2q4/2NB1QBP/1PP2PP1/R3R1K1 b q - 1 17 e8c8 f3c6 b7c6 d3a6 1180 114 72 618 bodenMate mate mateIn2 middlegame queensideAttack sacrifice short https://lichess.org/2QzZrb7U/black#34
12 micYX r3k2r/pp1n1pp1/2p2np1/q3p3/3P4/b1P1BQNP/PP3PP1/R3KB1R w KQkq - 1 13 e1c1 a5c3 c1b1 c3b2 1554 80 74 42 mate mateIn2 middlegame pin queensideAttack short https://lichess.org/6fCoAKep#25
13 LjS86 r1bqk2r/p3bppp/2p1n3/1p2pQ2/4N3/2PB4/P1PP1PPP/R1B2RK1 b kq - 4 12 e8g8 e4f6 g8h8 f5h7 1122 79 72 358 kingsideAttack mate mateIn2 opening short https://lichess.org/O55hxxVw/black#24
14 0uCn9 r5kr/pp2p1b1/1q1p4/2pPnbP1/4N3/5P2/PPPBQ2P/R3KBNR w KQ - 5 16 e1c1 e5d3 c1b1 b6b2 1522 76 92 1510 mate mateIn2 middlegame queensideAttack short https://lichess.org/fpIzh0mk#31
15 MLdUA r3k2r/1p3p1p/p2p1B1b/4pP2/1PP5/q7/2K2PPP/3Q1B1R b kq - 3 21 e8g8 d1g4 h6g7 g4g7 1365 81 40 68 kingsideAttack mate mateIn2 middlegame short https://lichess.org/eBsszmz6/black#42
16 AhG2i rn2k2r/2q2pp1/p3p1p1/2Np2N1/1P1P1n2/P7/2PQ1PPP/R3K2R w KQkq - 2 18 e1g1 f4e2 g1h1 c7h2 1345 76 85 185 discoveredAttack kingsideAttack mate mateIn2 middlegame short https://lichess.org/eNauwPCr#35
17 vnoDi r3k3/p3q1p1/2p2n2/2P2p2/1P3Br1/5Q2/P4PPP/RN4K1 b q - 1 21 e8c8 f3c6 e7c7 c6c7 1222 79 92 1655 mate mateIn2 middlegame queensideAttack short https://lichess.org/nq7O55Iv/black#42
18 KCfTj r1b1k2r/pppp1Npp/2n5/4p3/2B4q/5Q2/PPPP1b1P/RNB4K b kq - 0 10 e8g8 f7h6 g8h8 f3f8 1092 78 98 2011 deflection discoveredAttack doubleCheck kingsideAttack mate mateIn2 middlegame short https://lichess.org/5aGYiZI2/black#20
19 W6DEV r3kb1r/2p2p2/p1P1p3/4P1p1/Pp1q4/8/1P1NQ1PP/R3K2R b KQkq - 1 20 e8c8 e2a6 c8b8 a6b7 1100 80 95 536 mate mateIn2 middlegame queensideAttack short https://lichess.org/GEq3AYMj/black#40
20 lo4i9 r3k2r/pp1nqppp/2p1pn2/5b2/1bB2B2/3P1QPP/PPP1NP2/2KR3R b kq - 4 13 e8c8 f3c6 b7c6 c4a6 1061 95 85 1074 bodenMate mate mateIn2 middlegame queensideAttack sacrifice short https://lichess.org/LmkZcypC/black#26

View File

@@ -0,0 +1,20 @@
4ealO,7R/1r6/4npp1/3p2k1/4p1PN/4P1K1/5P2/8 b - - 1 41,e6g7 f2f4 e4f3 h4f3,1570,74,93,541,endgame mate mateIn2 short,https://lichess.org/Ake1xrvX/black#82
0jFaq,3r3R/p1r1kpp1/2pb4/6P1/3p1P2/1PnP4/PB4B1/K3R3 b - - 8 31,e7d7 g2h3 f7f5 g5f6,1473,75,95,8904,discoveredAttack enPassant mate mateIn2 middlegame short,https://lichess.org/PTxvhx4O/black#62
IzNuV,rnbq1bkr/pppp2pp/8/4P3/8/1Q6/PPP2nPP/RNB1K1NR b KQ - 3 7,d7d5 e5d6 c8e6 b3e6,2101,76,90,597,discoveredAttack enPassant kingsideAttack mate mateIn2 opening short,https://lichess.org/jeruntSh/black#14
pnp1m,6k1/2p2p2/7p/p4Pp1/PpP4K/1N1P3P/1PB1b1r1/R7 w - g6 0 36,f5g6 f7g6 d3d4 g6g5,1332,74,98,5203,endgame mate mateIn2 short,https://lichess.org/RqiEClbR#71
C8vzb,7r/6R1/5P1p/3p3k/b1pP3p/4K3/r4PPP/7R b - - 1 31,h8b8 g2g4 h4g3 h2g3,1734,75,93,284,discoveredAttack endgame mate mateIn2 short,https://lichess.org/dc3gg8Ux/black#62
m3UQp,r1bq1bkr/pppp2pp/2n5/4P3/6n1/1QN2N2/PP3PPP/R1B1K2R b KQ - 2 9,d7d5 e5d6 c8e6 b3e6,2256,77,99,139,discoveredAttack enPassant kingsideAttack mate mateIn2 opening short,https://lichess.org/VE0cPfvX/black#18
jkW7a,r1bq1bkr/pppp2pp/2n5/4P1N1/2Q5/8/Pp3PPP/RNB1K2R b KQ - 1 10,d7d5 e5d6 c8e6 c4e6,2008,85,100,60,discoveredAttack enPassant kingsideAttack mate mateIn2 opening short,https://lichess.org/R6aKczaF/black#20
VkFyK,3Q4/1k6/1n1b2p1/1B1p1pP1/P2Pp1K1/4q3/4N3/2R5 w - f6 0 46,g5f6 e3f3 g4g5 f3h5,2129,116,74,30,mate mateIn2 middlegame short,https://lichess.org/gcWm81m8#91
7dd9h,6k1/1bQ2p2/p3p1p1/6Pp/2P3K1/1P2PnP1/P6r/R4R2 w - h6 0 30,g5h6 f7f5 g4f4 g6g5,1817,75,96,4785,endgame mate mateIn2 short,https://lichess.org/URt1dC1A#59
GJfk2,5nk1/R4pp1/4p2p/2BpP2P/3P2P1/1r3K2/8/2R5 w - - 4 44,f3f4 g7g5 h5g6 f8g6,1637,74,86,400,endgame mate mateIn2 short,https://lichess.org/Rs0Ce6wy#87
By846,6k1/5rpp/2pB2b1/2P5/4pP2/2P4P/3r2P1/2R1R1K1 b - f3 0 28,e4f3 e1e8 f7f8 e8f8,687,107,78,374,endgame mate mateIn2 short,https://lichess.org/oVDK3Vtd/black#56
aCX4c,7k/1R2B1b1/p5pp/5p2/4p1P1/P2bP2P/5PB1/2r3K1 w - - 1 31,g1h2 g7e5 f2f4 e4f3,1611,74,95,6485,discoveredAttack enPassant endgame mate mateIn2 short,https://lichess.org/dVTQ6KQK#61
Ksv3B,6k1/7p/R5p1/5p2/4p3/1RP1B1PP/2P2PK1/3r1r2 w - - 0 35,f2f4 e4f3 g2h2 f1h1,1923,76,92,558,enPassant endgame mate mateIn2 short,https://lichess.org/wi3kg3x1#69
3DJKJ,8/4ppk1/3p2p1/1pnP3p/4PK1P/r4PP1/PR6/5B2 w - - 9 43,f1b5 e7e5 d5e6 c5e6,1962,74,96,4418,endgame mate mateIn2 short,https://lichess.org/RR03JsOK#85
n4CSG,1r2r1k1/p3qpbp/1pp3p1/3pP3/5BPn/2N3Q1/PPP2P1P/3RR1K1 w - d6 0 21,e5d6 e7e1 d1e1 e8e1,742,95,47,49,kingsideAttack mate mateIn2 middlegame short,https://lichess.org/B4cIJuuo#41
12YGT,r2qkbnr/1p2p3/2p2p2/2Pp1bp1/p2P3p/PN2BN1P/RP1KPPP1/3Q1B1R w kq - 0 15,b3c1 d8a5 b2b4 a4b3,1583,76,88,1028,discoveredAttack enPassant mate mateIn2 middlegame short,https://lichess.org/ggbXxMB9#29
BOPKK,1r5r/p1p2pk1/4p2p/1BNnP3/6R1/P7/1P4PP/7K b - - 2 23,g7h7 b5d3 f7f5 e5f6,1723,94,85,37,discoveredAttack enPassant endgame mate mateIn2 short,https://lichess.org/9He2SHa7/black#46
wU03v,5nk1/p4pp1/4p2p/4Pq1P/1p3P2/6PK/P1R3Q1/8 w - - 4 32,h3h4 g7g5 h5g6 f8g6,1602,75,95,386,endgame mate mateIn2 short,https://lichess.org/adh9umHR#63
gLCiH,3r2k1/p2r1ppp/2p5/1pP5/8/1R2P3/P4PPP/1R4K1 w - b6 0 24,c5b6 d7d1 b1d1 d8d1,829,114,90,117,backRankMate endgame mate mateIn2 rookEndgame short,https://lichess.org/EPK4b73V#47
5UCLk,8/8/p3RB2/kp3p1p/1Pp2K1P/2P5/6r1/8 b - b3 0 59,c4b3 f6d8 a5a4 e6a6,1610,75,85,304,deflection endgame mate mateIn2 short,https://lichess.org/Z6jDY4v4/black#118
1 4ealO 7R/1r6/4npp1/3p2k1/4p1PN/4P1K1/5P2/8 b - - 1 41 e6g7 f2f4 e4f3 h4f3 1570 74 93 541 endgame mate mateIn2 short https://lichess.org/Ake1xrvX/black#82
2 0jFaq 3r3R/p1r1kpp1/2pb4/6P1/3p1P2/1PnP4/PB4B1/K3R3 b - - 8 31 e7d7 g2h3 f7f5 g5f6 1473 75 95 8904 discoveredAttack enPassant mate mateIn2 middlegame short https://lichess.org/PTxvhx4O/black#62
3 IzNuV rnbq1bkr/pppp2pp/8/4P3/8/1Q6/PPP2nPP/RNB1K1NR b KQ - 3 7 d7d5 e5d6 c8e6 b3e6 2101 76 90 597 discoveredAttack enPassant kingsideAttack mate mateIn2 opening short https://lichess.org/jeruntSh/black#14
4 pnp1m 6k1/2p2p2/7p/p4Pp1/PpP4K/1N1P3P/1PB1b1r1/R7 w - g6 0 36 f5g6 f7g6 d3d4 g6g5 1332 74 98 5203 endgame mate mateIn2 short https://lichess.org/RqiEClbR#71
5 C8vzb 7r/6R1/5P1p/3p3k/b1pP3p/4K3/r4PPP/7R b - - 1 31 h8b8 g2g4 h4g3 h2g3 1734 75 93 284 discoveredAttack endgame mate mateIn2 short https://lichess.org/dc3gg8Ux/black#62
6 m3UQp r1bq1bkr/pppp2pp/2n5/4P3/6n1/1QN2N2/PP3PPP/R1B1K2R b KQ - 2 9 d7d5 e5d6 c8e6 b3e6 2256 77 99 139 discoveredAttack enPassant kingsideAttack mate mateIn2 opening short https://lichess.org/VE0cPfvX/black#18
7 jkW7a r1bq1bkr/pppp2pp/2n5/4P1N1/2Q5/8/Pp3PPP/RNB1K2R b KQ - 1 10 d7d5 e5d6 c8e6 c4e6 2008 85 100 60 discoveredAttack enPassant kingsideAttack mate mateIn2 opening short https://lichess.org/R6aKczaF/black#20
8 VkFyK 3Q4/1k6/1n1b2p1/1B1p1pP1/P2Pp1K1/4q3/4N3/2R5 w - f6 0 46 g5f6 e3f3 g4g5 f3h5 2129 116 74 30 mate mateIn2 middlegame short https://lichess.org/gcWm81m8#91
9 7dd9h 6k1/1bQ2p2/p3p1p1/6Pp/2P3K1/1P2PnP1/P6r/R4R2 w - h6 0 30 g5h6 f7f5 g4f4 g6g5 1817 75 96 4785 endgame mate mateIn2 short https://lichess.org/URt1dC1A#59
10 GJfk2 5nk1/R4pp1/4p2p/2BpP2P/3P2P1/1r3K2/8/2R5 w - - 4 44 f3f4 g7g5 h5g6 f8g6 1637 74 86 400 endgame mate mateIn2 short https://lichess.org/Rs0Ce6wy#87
11 By846 6k1/5rpp/2pB2b1/2P5/4pP2/2P4P/3r2P1/2R1R1K1 b - f3 0 28 e4f3 e1e8 f7f8 e8f8 687 107 78 374 endgame mate mateIn2 short https://lichess.org/oVDK3Vtd/black#56
12 aCX4c 7k/1R2B1b1/p5pp/5p2/4p1P1/P2bP2P/5PB1/2r3K1 w - - 1 31 g1h2 g7e5 f2f4 e4f3 1611 74 95 6485 discoveredAttack enPassant endgame mate mateIn2 short https://lichess.org/dVTQ6KQK#61
13 Ksv3B 6k1/7p/R5p1/5p2/4p3/1RP1B1PP/2P2PK1/3r1r2 w - - 0 35 f2f4 e4f3 g2h2 f1h1 1923 76 92 558 enPassant endgame mate mateIn2 short https://lichess.org/wi3kg3x1#69
14 3DJKJ 8/4ppk1/3p2p1/1pnP3p/4PK1P/r4PP1/PR6/5B2 w - - 9 43 f1b5 e7e5 d5e6 c5e6 1962 74 96 4418 endgame mate mateIn2 short https://lichess.org/RR03JsOK#85
15 n4CSG 1r2r1k1/p3qpbp/1pp3p1/3pP3/5BPn/2N3Q1/PPP2P1P/3RR1K1 w - d6 0 21 e5d6 e7e1 d1e1 e8e1 742 95 47 49 kingsideAttack mate mateIn2 middlegame short https://lichess.org/B4cIJuuo#41
16 12YGT r2qkbnr/1p2p3/2p2p2/2Pp1bp1/p2P3p/PN2BN1P/RP1KPPP1/3Q1B1R w kq - 0 15 b3c1 d8a5 b2b4 a4b3 1583 76 88 1028 discoveredAttack enPassant mate mateIn2 middlegame short https://lichess.org/ggbXxMB9#29
17 BOPKK 1r5r/p1p2pk1/4p2p/1BNnP3/6R1/P7/1P4PP/7K b - - 2 23 g7h7 b5d3 f7f5 e5f6 1723 94 85 37 discoveredAttack enPassant endgame mate mateIn2 short https://lichess.org/9He2SHa7/black#46
18 wU03v 5nk1/p4pp1/4p2p/4Pq1P/1p3P2/6PK/P1R3Q1/8 w - - 4 32 h3h4 g7g5 h5g6 f8g6 1602 75 95 386 endgame mate mateIn2 short https://lichess.org/adh9umHR#63
19 gLCiH 3r2k1/p2r1ppp/2p5/1pP5/8/1R2P3/P4PPP/1R4K1 w - b6 0 24 c5b6 d7d1 b1d1 d8d1 829 114 90 117 backRankMate endgame mate mateIn2 rookEndgame short https://lichess.org/EPK4b73V#47
20 5UCLk 8/8/p3RB2/kp3p1p/1Pp2K1P/2P5/6r1/8 b - b3 0 59 c4b3 f6d8 a5a4 e6a6 1610 75 85 304 deflection endgame mate mateIn2 short https://lichess.org/Z6jDY4v4/black#118

View File

@@ -0,0 +1,20 @@
uj7Uv,6k1/r4p2/6p1/4B3/p4P2/5r1p/K1R5/8 b - - 5 43,a7b7 c2c8 g8h7 c8h8,840,100,67,43,endgame mate mateIn2 short,https://lichess.org/Z3FRw1Fn/black#86
GWKLu,3r2qr/pp2Q3/2p2P1p/7k/6R1/1P6/1PP3PP/R1B4K w - - 5 23,g4g8 d8d1 e7e1 d1e1,1038,85,96,471,backRankMate endgame mate mateIn2 short,https://lichess.org/1kIpfnCX#45
ay0e7,1rr3k1/Q4pp1/4p2p/8/1PqPp3/P3P3/5PPP/R4RK1 w - - 3 27,f1c1 c4c1 a1c1 c8c1,630,95,69,168,backRankMate endgame mate mateIn2 short,https://lichess.org/x83fY9GE#53
f2HsU,8/2q1kp2/4p3/p7/4Q3/7P/P1Pr1PP1/1R4K1 w - - 0 32,b1b7 d2d1 e4e1 d1e1,941,78,76,128,endgame mate mateIn2 short,https://lichess.org/NxooUJUL#63
gEBEu,r3r2k/ppp3pp/3b4/5p2/1PQ1n2q/PnN1PB2/1B3PPP/R3K2R w KQ - 4 18,c4b3 h4f2 e1d1 f2d2,1124,80,94,862,attackingF2F7 mate mateIn2 middlegame short,https://lichess.org/prTiL04V#35
Lk2iz,r5k1/p1p2p1Q/2pq1Bp1/3p1b2/5R2/1P1Pr3/P1P3PP/R5K1 b - - 0 21,g8h7 f4h4 h7g8 h4h8,741,91,88,90,master mate mateIn2 middlegame short,https://lichess.org/i2Wi7l4e/black#42
t4DNf,2r3k1/5ppp/8/8/4pP2/4P2P/2Q3P1/1R3K2 b - - 0 43,c8c2 b1b8 c2c8 b8c8,655,107,82,33,backRankMate endgame mate mateIn2 rookEndgame short,https://lichess.org/r5W2eFui/black#86
xrekH,8/p1P5/8/PP6/8/5rkp/8/6K1 w - - 2 59,c7c8q h3h2 g1h1 f3f1,990,93,96,295,advancedPawn endgame mate mateIn2 queenRookEndgame short,https://lichess.org/dQGDwh3G#117
fBhqm,8/3R2kp/p5p1/8/5KP1/2p5/P1P4r/8 b - - 2 39,g7h6 g4g5 h6h5 d7h7,988,75,100,750,deflection endgame mate mateIn2 rookEndgame short,https://lichess.org/rfc0Wh0t/black#78
tn9U3,8/4Q3/p2pN3/2pP4/2p1k3/8/1PPK1q2/8 w - - 1 36,d2c3 f2e1 c3c4 e1b4,1917,75,96,2210,endgame mate mateIn2 short,https://lichess.org/js3slxFD#71
doGMx,5rk1/pp1R1pp1/4p3/8/6QP/3bB1N1/Pqr2PP1/3K3R w - - 0 22,d7d3 b2b1 e3c1 b1c1,1243,76,90,222,mate mateIn2 middlegame short,https://lichess.org/jYHnS2gv#43
TVLHT,r1bqr1k1/p1pnbp2/1p2pn1Q/6N1/3P4/2NB4/PPP3PP/R4RK1 b - - 2 13,e7f8 d3h7 f6h7 h6h7,1274,76,94,1181,kingsideAttack mate mateIn2 middlegame short,https://lichess.org/3luk8Lyr/black#26
EfOGc,8/5pk1/7q/3Pr3/8/3Q3P/4KRP1/8 w - - 1 45,e2f1 h6c1 d3d1 c1d1,992,76,95,561,endgame mate mateIn2 short,https://lichess.org/oWIOQKUU#89
I7xRS,8/pp1r4/2p5/5b1p/5N2/5kP1/P4P1P/Q5K1 w - - 1 34,a1e5 d7d1 e5e1 d1e1,600,84,83,169,endgame mate mateIn2 short,https://lichess.org/D6tGkCvf#67
CnqaD,r1bqk2r/1p6/p1n1pp1p/3p2p1/1QpPNB1P/P3P3/1PP1BPP1/R3K2R b KQkq - 0 14,g5f4 e2h5 e8d7 b4d6,1799,75,95,4247,mate mateIn2 middlegame short,https://lichess.org/gVyTK6U8/black#28
yuqa6,4k2r/p2nppb1/6pp/1p1NP3/1P5N/K5P1/P1b2rBP/3R3R b k - 3 25,d7e5 d5c7 e8f8 d1d8,1098,78,77,313,backRankMate mate mateIn2 middlegame short,https://lichess.org/HCiRNU2E/black#50
koa5w,r5k1/pbp1qpp1/1p2p1n1/3r2NQ/3P3P/5P2/PP4P1/R2R2K1 b - - 0 20,g6f4 h5h7 g8f8 h7h8,944,76,100,195,kingsideAttack mate mateIn2 middlegame short,https://lichess.org/TXpDhxAx/black#40
6HZF3,2rq3r/5k2/p3p3/1pn2Np1/4P3/P1Q2P2/6b1/1KBR2N1 b - - 0 29,d8d1 c3g7 f7e8 g7e7,1524,74,98,7690,mate mateIn2 middlegame short,https://lichess.org/f4k6roov/black#58
85ZUB,6k1/2p2pp1/p6p/3pPp2/P7/r3P3/5PPP/3R2K1 w - - 2 27,d1d5 a3a1 d5d1 a1d1,681,104,76,365,backRankMate endgame mate mateIn2 rookEndgame short,https://lichess.org/pBZZo8XP#53
YHYZd,8/pp1R4/6pk/8/6PP/5K2/PP1prP2/4r3 b - - 0 36,d2d1q g4g5 h6h5 d7h7,1239,77,90,369,endgame mate mateIn2 queenRookEndgame short,https://lichess.org/E8UBGJ5F/black#72
1 uj7Uv 6k1/r4p2/6p1/4B3/p4P2/5r1p/K1R5/8 b - - 5 43 a7b7 c2c8 g8h7 c8h8 840 100 67 43 endgame mate mateIn2 short https://lichess.org/Z3FRw1Fn/black#86
2 GWKLu 3r2qr/pp2Q3/2p2P1p/7k/6R1/1P6/1PP3PP/R1B4K w - - 5 23 g4g8 d8d1 e7e1 d1e1 1038 85 96 471 backRankMate endgame mate mateIn2 short https://lichess.org/1kIpfnCX#45
3 ay0e7 1rr3k1/Q4pp1/4p2p/8/1PqPp3/P3P3/5PPP/R4RK1 w - - 3 27 f1c1 c4c1 a1c1 c8c1 630 95 69 168 backRankMate endgame mate mateIn2 short https://lichess.org/x83fY9GE#53
4 f2HsU 8/2q1kp2/4p3/p7/4Q3/7P/P1Pr1PP1/1R4K1 w - - 0 32 b1b7 d2d1 e4e1 d1e1 941 78 76 128 endgame mate mateIn2 short https://lichess.org/NxooUJUL#63
5 gEBEu r3r2k/ppp3pp/3b4/5p2/1PQ1n2q/PnN1PB2/1B3PPP/R3K2R w KQ - 4 18 c4b3 h4f2 e1d1 f2d2 1124 80 94 862 attackingF2F7 mate mateIn2 middlegame short https://lichess.org/prTiL04V#35
6 Lk2iz r5k1/p1p2p1Q/2pq1Bp1/3p1b2/5R2/1P1Pr3/P1P3PP/R5K1 b - - 0 21 g8h7 f4h4 h7g8 h4h8 741 91 88 90 master mate mateIn2 middlegame short https://lichess.org/i2Wi7l4e/black#42
7 t4DNf 2r3k1/5ppp/8/8/4pP2/4P2P/2Q3P1/1R3K2 b - - 0 43 c8c2 b1b8 c2c8 b8c8 655 107 82 33 backRankMate endgame mate mateIn2 rookEndgame short https://lichess.org/r5W2eFui/black#86
8 xrekH 8/p1P5/8/PP6/8/5rkp/8/6K1 w - - 2 59 c7c8q h3h2 g1h1 f3f1 990 93 96 295 advancedPawn endgame mate mateIn2 queenRookEndgame short https://lichess.org/dQGDwh3G#117
9 fBhqm 8/3R2kp/p5p1/8/5KP1/2p5/P1P4r/8 b - - 2 39 g7h6 g4g5 h6h5 d7h7 988 75 100 750 deflection endgame mate mateIn2 rookEndgame short https://lichess.org/rfc0Wh0t/black#78
10 tn9U3 8/4Q3/p2pN3/2pP4/2p1k3/8/1PPK1q2/8 w - - 1 36 d2c3 f2e1 c3c4 e1b4 1917 75 96 2210 endgame mate mateIn2 short https://lichess.org/js3slxFD#71
11 doGMx 5rk1/pp1R1pp1/4p3/8/6QP/3bB1N1/Pqr2PP1/3K3R w - - 0 22 d7d3 b2b1 e3c1 b1c1 1243 76 90 222 mate mateIn2 middlegame short https://lichess.org/jYHnS2gv#43
12 TVLHT r1bqr1k1/p1pnbp2/1p2pn1Q/6N1/3P4/2NB4/PPP3PP/R4RK1 b - - 2 13 e7f8 d3h7 f6h7 h6h7 1274 76 94 1181 kingsideAttack mate mateIn2 middlegame short https://lichess.org/3luk8Lyr/black#26
13 EfOGc 8/5pk1/7q/3Pr3/8/3Q3P/4KRP1/8 w - - 1 45 e2f1 h6c1 d3d1 c1d1 992 76 95 561 endgame mate mateIn2 short https://lichess.org/oWIOQKUU#89
14 I7xRS 8/pp1r4/2p5/5b1p/5N2/5kP1/P4P1P/Q5K1 w - - 1 34 a1e5 d7d1 e5e1 d1e1 600 84 83 169 endgame mate mateIn2 short https://lichess.org/D6tGkCvf#67
15 CnqaD r1bqk2r/1p6/p1n1pp1p/3p2p1/1QpPNB1P/P3P3/1PP1BPP1/R3K2R b KQkq - 0 14 g5f4 e2h5 e8d7 b4d6 1799 75 95 4247 mate mateIn2 middlegame short https://lichess.org/gVyTK6U8/black#28
16 yuqa6 4k2r/p2nppb1/6pp/1p1NP3/1P5N/K5P1/P1b2rBP/3R3R b k - 3 25 d7e5 d5c7 e8f8 d1d8 1098 78 77 313 backRankMate mate mateIn2 middlegame short https://lichess.org/HCiRNU2E/black#50
17 koa5w r5k1/pbp1qpp1/1p2p1n1/3r2NQ/3P3P/5P2/PP4P1/R2R2K1 b - - 0 20 g6f4 h5h7 g8f8 h7h8 944 76 100 195 kingsideAttack mate mateIn2 middlegame short https://lichess.org/TXpDhxAx/black#40
18 6HZF3 2rq3r/5k2/p3p3/1pn2Np1/4P3/P1Q2P2/6b1/1KBR2N1 b - - 0 29 d8d1 c3g7 f7e8 g7e7 1524 74 98 7690 mate mateIn2 middlegame short https://lichess.org/f4k6roov/black#58
19 85ZUB 6k1/2p2pp1/p6p/3pPp2/P7/r3P3/5PPP/3R2K1 w - - 2 27 d1d5 a3a1 d5d1 a1d1 681 104 76 365 backRankMate endgame mate mateIn2 rookEndgame short https://lichess.org/pBZZo8XP#53
20 YHYZd 8/pp1R4/6pk/8/6PP/5K2/PP1prP2/4r3 b - - 0 36 d2d1q g4g5 h6h5 d7h7 1239 77 90 369 endgame mate mateIn2 queenRookEndgame short https://lichess.org/E8UBGJ5F/black#72

80
Tests/SquareTests.cpp Normal file
View File

@@ -0,0 +1,80 @@
#include "catch2/catch.hpp"
#include "TestUtils.hpp"
#include "Square.hpp"
#include <sstream>
TEST_CASE("Squares can be created from valid coordinates", "[Square][Fundamental]") {
auto [file, rank] = GENERATE(table<Square::Coordinate, Square::Coordinate>({
{4, 2}, {0, 0}, {7, 7}, {1, 7}
}));
auto optSquare = Square::fromCoordinates(file, rank);
REQUIRE(optSquare.has_value());
auto square = optSquare.value();
REQUIRE(square.file() == file);
REQUIRE(square.rank() == rank);
REQUIRE(square.index() == rank * 8 + file);
}
TEST_CASE("Squares are not created from invalid coordinates", "[Square][Fundamental]") {
auto [file, rank] = GENERATE(table<Square::Coordinate, Square::Coordinate>({
{4, 8}, {8, 3}, {12, 45}
}));
auto optSquare = Square::fromCoordinates(file, rank);
REQUIRE_FALSE(optSquare.has_value());
}
TEST_CASE("Squares can be created from valid indices", "[Square][Fundamental]") {
auto index = GENERATE(as<Square::Index>{}, 0, 63, 12, 41);
auto optSquare = Square::fromIndex(index);
REQUIRE(optSquare.has_value());
auto square = optSquare.value();
REQUIRE(square.file() == index % 8);
REQUIRE(square.rank() == index / 8);
REQUIRE(square.index() == index);
}
TEST_CASE("Squares are not created from invalid indices", "[Square][Fundamental]") {
auto index = GENERATE(as<Square::Index>{}, 64, 1024);
auto optSquare = Square::fromIndex(index);
REQUIRE_FALSE(optSquare.has_value());
}
TEST_CASE("Squares can be created from valid names", "[Square][Fundamental]") {
auto [square, name] = GENERATE(table<Square, const char*>({
{Square::A1, "a1"}, {Square::H8, "h8"}, {Square::D5, "d5"}
}));
auto optCreatedSquare = Square::fromName(name);
CAPTURE(square, name, optCreatedSquare);
REQUIRE(optCreatedSquare.has_value());
auto createdSquare = optCreatedSquare.value();
REQUIRE(createdSquare == square);
}
TEST_CASE("Squares are not created from invalid names", "[Square][Fundamental]") {
auto name = GENERATE("", "a", "a12", "1a", "xyz");
auto optSquare = Square::fromName(name);
CAPTURE(name, optSquare);
REQUIRE_FALSE(optSquare.has_value());
}
TEST_CASE("Squares stream their name correctly", "[Square][Fundamental]") {
auto [square, name] = GENERATE(table<Square, const char*>({
{Square::A1, "a1"}, {Square::H8, "h8"}, {Square::E4, "e4"}
}));
auto stream = std::stringstream();
stream << square;
REQUIRE(stream.str() == name);
}

26
Tests/TestUtils.hpp Normal file
View File

@@ -0,0 +1,26 @@
#ifndef CHESS_ENGINE_TESTS_TESTUTILS_HPP
#define CHESS_ENGINE_TESTS_TESTUTILS_HPP
#include <optional>
#include <memory>
#include <ostream>
template<typename T>
inline std::ostream& operator<<(std::ostream& os, const std::optional<T>& opt) {
if (opt.has_value()) {
return os << opt.value();
} else {
return os << "nullopt";
}
}
template<typename T>
inline std::ostream& operator<<(std::ostream& os, const std::unique_ptr<T>& ptr) {
if (ptr == nullptr) {
return os << "nullptr";
} else {
return os << ptr.get();
}
}
#endif

151
Tests/puzzledb.py Executable file
View File

@@ -0,0 +1,151 @@
#!/usr/bin/env python3
import csv
from pathlib import Path
import argparse
import sys
import chess
class Puzzle:
def __init__(self, puzzle_id, fen, moves, rating, rd, popularity,
num_plays, tags, game_url):
self.puzzle_id = puzzle_id
self.fen = fen
self.moves = moves
self.rating = rating
self.rd = rd
self.popularity = popularity
self.num_plays = num_plays
self.tags = tags
self.game_url = game_url
@staticmethod
def from_csv(row):
puzzle_id, fen, moves, rating, rd, popularity, \
num_plays, tags, game_url = row[:9]
moves = [chess.Move.from_uci(m) for m in moves.split()]
return Puzzle(puzzle_id, fen, moves, int(rating), int(rd),
int(popularity), int(num_plays), tags.split(), game_url)
def to_csv(self):
moves = ' '.join(m.uci() for m in self.moves)
tags = ' '.join(self.tags)
return (
self.puzzle_id, self.fen, moves, self.rating, self.rd,
self.popularity, self.num_plays, tags, self.game_url
)
def has_tags(self, tags):
return all(tag in self.tags for tag in tags)
def has_not_tags(self, tags):
return not any(tag in self.tags for tag in tags)
def _has_move(self, predicate):
board = chess.Board(self.fen)
for move in self.moves:
if predicate(board, move):
return True
board.push(move)
return False
def has_castling(self):
return self._has_move(chess.Board.is_castling)
def has_en_passant(self):
return self._has_move(chess.Board.is_en_passant)
def num_plies(self):
return len(self.moves) - 1
class PuzzleDb:
def __init__(self, puzzles):
self._puzzles = puzzles
@staticmethod
def from_csv(file):
def generate_puzzles():
csv_reader = csv.reader(file)
for row in csv_reader:
puzzle = Puzzle.from_csv(row)
yield puzzle
return PuzzleDb(generate_puzzles())
def to_csv(self, file):
csv_writer = csv.writer(file)
for puzzle in self._puzzles:
csv_writer.writerow(puzzle.to_csv())
def filter(self, predicate):
return PuzzleDb(filter(predicate, self))
def collect(self):
return list(self)
def sorted(self, key=None):
return PuzzleDb(sorted(self._puzzles, key=key))
def __iter__(self):
yield from self._puzzles
def main():
parser = argparse.ArgumentParser()
parser.add_argument('puzzle_db', type=Path)
parser.add_argument('--tag', action='append', dest='tags')
parser.add_argument('--not-tag', action='append', dest='not_tags')
parser.add_argument('--castling', choices=['yes', 'no', 'only'],
default='yes')
parser.add_argument('--en-passant', choices=['yes', 'no', 'only'],
default='yes')
parser.add_argument('--min-plies', type=int, default=0)
parser.add_argument('--max-plies', type=int, default=1000)
parser.add_argument('--min-rating', type=int, default=0)
parser.add_argument('--max-rating', type=int, default=4000)
parser.add_argument('--min-num-plays', type=int, default=0)
args = parser.parse_args()
with args.puzzle_db.open(newline='') as f:
puzzles = PuzzleDb.from_csv(f)
if args.tags is not None:
puzzles = puzzles.filter(lambda p: p.has_tags(args.tags))
if args.not_tags is not None:
puzzles = puzzles.filter(lambda p: p.has_not_tags(args.not_tags))
if args.castling == 'no':
puzzles = puzzles.filter(lambda p: not p.has_castling())
elif args.castling == 'only':
puzzles = puzzles.filter(lambda p: p.has_castling())
if args.en_passant == 'no':
puzzles = puzzles.filter(lambda p: not p.has_en_passant())
elif args.en_passant == 'only':
puzzles = puzzles.filter(lambda p: p.has_en_passant())
puzzles = puzzles.filter(
lambda p: args.min_plies <= p.num_plies() <= args.max_plies
)
puzzles = puzzles.filter(
lambda p: args.min_rating <= p.rating <= args.max_rating
)
puzzles = puzzles.filter(lambda p: args.min_num_plays <= p.num_plays)
puzzles.to_csv(sys.stdout)
if __name__ == '__main__':
main()

89
Tests/puzzlerating.py Executable file
View File

@@ -0,0 +1,89 @@
#!/usr/bin/env python3
from puzzledb import PuzzleDb
from puzzlerunner import run_puzzle
import argparse
from pathlib import Path
from random import Random
import glicko2
def select_puzzles(player, puzzle_db, num_puzzles, played_puzzles, random):
rd = player.rd
candidates = []
while len(candidates) < num_puzzles:
candidates = puzzle_db \
.filter(lambda p: p.rating >= player.rating - 2 * rd) \
.filter(lambda p: p.rating <= player.rating + 2 * rd) \
.filter(lambda p: p not in played_puzzles) \
.collect()
rd += 50
return sorted(random.sample(candidates, num_puzzles),
key=lambda p: p.rating)
def play_round(player, puzzle_db, num_puzzles, engine,
timeout, played_puzzles, random):
puzzles = select_puzzles(player, puzzle_db, num_puzzles,
played_puzzles, random)
played_puzzles.update(puzzles)
outcomes = []
for puzzle in puzzles:
print(f'Running puzzle {puzzle.puzzle_id} '
f'with rating {puzzle.rating}... ',
end='', flush=True)
result = run_puzzle(puzzle, engine, timeout)
success = result.is_success()
outcomes.append(success)
if success:
print('OK')
else:
print('FAIL')
ratings = [p.rating for p in puzzles]
rds = [p.rd for p in puzzles]
player.update_player(ratings, rds, outcomes)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--engine', type=Path, required=True)
parser.add_argument('--timeout', type=float, default=60)
parser.add_argument('--min-plays', type=int, default=500)
parser.add_argument('--min-popularity', type=int, default=50)
parser.add_argument('--rounds', type=int, default=20)
parser.add_argument('--puzzles-per-round', type=int, default=5)
parser.add_argument('--random-seed', type=int, default=0)
parser.add_argument('--puzzle-db', type=Path, required=True)
args = parser.parse_args()
with args.puzzle_db.open(newline='') as f:
puzzle_db = PuzzleDb.from_csv(f) \
.filter(lambda p: p.num_plays >= args.min_plays) \
.filter(lambda p: p.popularity >= args.min_popularity) \
.sorted(key=lambda p: p.rating)
player = glicko2.Player()
played_puzzles = set()
random = Random(args.random_seed)
for current_round in range(1, args.rounds + 1):
print(f'=== Round {current_round}/{args.rounds}, '
f'current rating: {round(player.rating)} '
f'(rd: {round(player.rd)}) ===')
play_round(player, puzzle_db, args.puzzles_per_round,
args.engine, args.timeout, played_puzzles, random)
print(f'Final rating: {round(player.rating)} (rd: {round(player.rd)})')
if __name__ == '__main__':
main()

260
Tests/puzzlerunner.py Executable file
View File

@@ -0,0 +1,260 @@
#!/usr/bin/env python3
from puzzledb import Puzzle, PuzzleDb
from pathlib import Path
import argparse
from abc import ABC, abstractmethod
from collections import defaultdict
import sys
import time
import asyncio
import contextlib
import chess
import chess.engine
import junit_xml
from junit_xml import TestSuite, TestCase
class PuzzleRunResult(ABC):
def __init__(self, puzzle):
self.puzzle = puzzle
self.puzzle_type = None
self.duration_sec = None
@abstractmethod
def is_success(self):
pass
def to_junit_test_case(self):
return TestCase(
name=f'Puzzle {self.puzzle.puzzle_id}',
status='run',
classname=self.puzzle_type,
elapsed_sec=self.duration_sec
)
class PuzzleRunSuccess(PuzzleRunResult):
def __init__(self, puzzle):
super().__init__(puzzle)
def is_success(self):
return True
class PuzzleRunFailure(PuzzleRunResult):
def __init__(self, puzzle, reason, info):
super().__init__(puzzle)
self.reason = reason
url = f'https://lichess.org/training/{self.puzzle.puzzle_id}'
self.info = f'URL: {url}\n{info}'
def is_success(self):
return False
def __str__(self):
return f'Failure reason: {self.reason}\n{self.info}'
def to_junit_test_case(self):
test_case = super().to_junit_test_case()
test_case.add_failure_info(
message=self.reason,
output=self.info
)
return test_case
class PuzzleRunWrongMove(PuzzleRunFailure):
def __init__(self, puzzle, position, move, expected_move):
reason = 'unexpected move'
info = f'position={position}\n' \
f'move={move.uci()}\n' \
f'expected move={expected_move.uci()}'
super().__init__(puzzle, reason, info)
class PuzzleRunTimeout(PuzzleRunFailure):
def __init__(self, puzzle, timeout):
reason = 'timeout'
info = f'Puzzle timed out after {timeout} seconds'
super().__init__(puzzle, reason, info)
class PuzzleRunException(PuzzleRunFailure):
def __init__(self, puzzle, exception):
reason = 'exception'
info = exception
super().__init__(puzzle, reason, info)
@contextlib.asynccontextmanager
async def create_engine(engine_path):
transport, engine = \
await chess.engine.popen_uci(engine_path)
try:
yield engine
finally:
try:
await asyncio.wait_for(engine.quit(), timeout=1)
except asyncio.TimeoutError:
try:
transport.kill()
transport.close()
except Exception:
pass
async def _run_puzzle(puzzle, engine_path, total_time):
start_time = time.time()
moves = puzzle.moves[:]
assert len(moves) >= 2
assert len(moves) % 2 == 0
board = chess.Board(puzzle.fen)
time_limit = chess.engine.Limit()
use_limit = total_time is not None
if use_limit:
time_limit.white_clock = total_time
time_limit.black_clock = total_time
time_limit.white_inc = 0
time_limit.black_inc = 0
time_limit.remaining_moves = next_multiple(puzzle.num_plies() // 2, 5)
time_left = total_time
else:
time_left = None
async with create_engine(engine_path) as engine:
while len(moves) > 0:
board.push(moves.pop(0))
try:
result = await asyncio.wait_for(engine.play(board, time_limit),
timeout=time_left)
except asyncio.TimeoutError:
return PuzzleRunTimeout(puzzle, total_time)
board.push(result.move)
expected_move = moves.pop(0)
if result.move != expected_move:
if len(moves) == 0 and board.is_checkmate():
break
else:
board.pop()
return PuzzleRunWrongMove(puzzle, board.fen(),
result.move, expected_move)
if use_limit:
time_limit.remaining_moves -= 1
current_time = time.time()
elapsed_time = current_time - start_time
time_left = total_time - elapsed_time
if time_left < 0:
return PuzzleRunTimeout(puzzle, total_time)
# The last move we made on the board was for the engine. So the
# current turn is for the engine's opponent. We only update the
# engine's clock to reflect the time limit.
if board.turn == chess.WHITE:
time_limit.black_clock = time_left
else:
time_limit.white_clock = time_left
return PuzzleRunSuccess(puzzle)
def run_puzzle(puzzle, engine_path, timeout):
async def run():
try:
return await _run_puzzle(puzzle, engine_path, timeout)
except Exception as e:
return PuzzleRunException(puzzle, e)
start_time = time.time()
result = asyncio.run(run())
end_time = time.time()
result.duration_sec = end_time - start_time
return result
def format_duration(duration):
return f'{duration:.3f}s'
def next_multiple(n, multiple):
return n + (multiple - n % multiple)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--engine', type=Path, required=True)
parser.add_argument('--timeout', type=float,
help='Timeout in seconds per puzzle')
parser.add_argument('--junit', type=Path)
parser.add_argument('puzzle_dbs', type=Path, nargs='+')
args = parser.parse_args()
results = defaultdict(list)
num_fails = 0
total_duration = 0
for puzzle_db_path in args.puzzle_dbs:
print(f'=== Running puzzles from {puzzle_db_path.resolve()} ===')
with puzzle_db_path.open(newline='') as f:
puzzles = PuzzleDb.from_csv(f)
for puzzle in puzzles:
print(f'Running puzzle {puzzle.puzzle_id} ... ',
end='', flush=True)
result = run_puzzle(puzzle, args.engine, args.timeout)
total_duration += result.duration_sec
duration_msg = f'({format_duration(result.duration_sec)})'
if result.is_success():
print(f'OK {duration_msg}')
else:
num_fails += 1
print(f'FAIL {duration_msg}')
print(f'===\n{result}\n===')
results[puzzle_db_path].append(result)
if args.junit is not None:
test_suites = []
for db_path, db_results in results.items():
name = f'puzzles.{db_path.stem}'
def create_test_case(result):
result.puzzle_type = name
return result.to_junit_test_case()
test_cases = [create_test_case(r) for r in db_results]
test_suite = TestSuite(name, test_cases)
test_suites.append(test_suite)
xml = junit_xml.to_xml_report_string(test_suites)
args.junit.write_text(xml)
print(f'Total time: {format_duration(total_duration)}')
if num_fails > 0:
sys.exit(f'{num_fails} tests failed')
else:
print('All tests passed')
if __name__ == '__main__':
main()