Skip to content

Commit

Permalink
support Extinction Chess and Kinglet Chess
Browse files Browse the repository at this point in the history
  • Loading branch information
alwey authored and ilaripih committed Jan 25, 2017
1 parent 8d265fe commit 6dfef16
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/cutechess-cli.6
Expand Up @@ -51,12 +51,16 @@ Capablanca Random Chess
Chessgi / Drop Chess
.It crazyhouse
Crazyhouse (Drop Chess Variant)
.It extinction
Extinction Chess
.It fischerandom
Fischer Random Chess / Chess 960
.It gothic
Gothic Chess
.It horde
Horde Chess (v2)
.It kinglet
Kinglet Chess
.It kingofthehill
King of the Hill Chess
.It loop
Expand Down
2 changes: 2 additions & 0 deletions projects/cli/res/doc/help.txt
Expand Up @@ -18,9 +18,11 @@ Options:
'caparandom': Capablanca Random Chess
'chessgi': Chessgi (Drop Chess)
'crazyhouse': Crazyhouse (Drop Chess)
'extinction': Extinction Chess
'fischerandom': Fischer Random Chess/Chess 960
'gothic': Gothic Chess
'horde': Horde Chess (v2)
'kinglet': Kinglet Chess
'kingofthehill': King of the Hill Chess
'loop': Loop Chess (Drop Chess)
'losers': Loser's Chess
Expand Down
2 changes: 2 additions & 0 deletions projects/lib/src/board/board.pri
Expand Up @@ -7,6 +7,7 @@ SOURCES += $$PWD/board.cpp \
$$PWD/berolinaboard.cpp \
$$PWD/racingkingsboard.cpp \
$$PWD/capablancaboard.cpp \
$$PWD/extinctionboard.cpp \
$$PWD/kingofthehillboard.cpp \
$$PWD/hordeboard.cpp \
$$PWD/zobrist.cpp \
Expand Down Expand Up @@ -35,6 +36,7 @@ HEADERS += $$PWD/board.h \
$$PWD/berolinaboard.h \
$$PWD/racingkingsboard.h \
$$PWD/capablancaboard.h \
$$PWD/extinctionboard.h \
$$PWD/kingofthehillboard.h \
$$PWD/hordeboard.h \
$$PWD/zobrist.h \
Expand Down
3 changes: 3 additions & 0 deletions projects/lib/src/board/boardfactory.cpp
Expand Up @@ -20,6 +20,7 @@
#include "capablancaboard.h"
#include "caparandomboard.h"
#include "crazyhouseboard.h"
#include "extinctionboard.h"
#include "frcboard.h"
#include "gothicboard.h"
#include "hordeboard.h"
Expand All @@ -42,6 +43,8 @@ REGISTER_BOARD(CapablancaBoard, "capablanca")
REGISTER_BOARD(CaparandomBoard, "caparandom")
REGISTER_BOARD(ChessgiBoard, "chessgi")
REGISTER_BOARD(CrazyhouseBoard, "crazyhouse")
REGISTER_BOARD(ExtinctionBoard, "extinction")
REGISTER_BOARD(KingletBoard, "kinglet")
REGISTER_BOARD(FrcBoard, "fischerandom")
REGISTER_BOARD(GothicBoard, "gothic")
REGISTER_BOARD(HordeBoard, "horde")
Expand Down
146 changes: 146 additions & 0 deletions projects/lib/src/board/extinctionboard.cpp
@@ -0,0 +1,146 @@
/*
This file is part of Cute Chess.
Cute Chess is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Cute Chess is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Cute Chess. If not, see <http://www.gnu.org/licenses/>.
*/

#include "extinctionboard.h"

namespace Chess {

ExtinctionBoard::ExtinctionBoard(const QSet<int>& set,
bool allPromotions)
: StandardBoard(),
m_allPromotions(allPromotions)
{
for (const auto& s: set)
m_pieceSet.append(s);
}

Board* ExtinctionBoard::copy() const
{
return new ExtinctionBoard(*this);
}

QString ExtinctionBoard::variant() const
{
return "extinction";
}

QString ExtinctionBoard::defaultFenString() const
{
return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
}

bool ExtinctionBoard::kingsCountAssertion(int, int) const
{
return extinctPiece(Side::White).isEmpty()
|| extinctPiece(Side::Black).isEmpty();
}

void ExtinctionBoard::addPromotions(int sourceSquare,
int targetSquare,
QVarLengthArray<Move>& moves) const
{
if (m_allPromotions)
StandardBoard::addPromotions(sourceSquare, targetSquare, moves);
moves.append(Move(sourceSquare, targetSquare, King));
}

bool ExtinctionBoard::inCheck(Side, int) const
{
return false;
}

Piece ExtinctionBoard::extinctPiece(Side side) const
{
for (const int type: m_pieceSet)
{
bool pieceFound = false;
for (int i = 0; i < arraySize(); i++)
{
Piece piece = pieceAt(i);
if (side == piece.side() && type == piece.type())
{
pieceFound = true;
break;
}
}
if (!pieceFound)
return Piece(side, type);
}
return Piece();
}

Result ExtinctionBoard::result()
{
QString str;
Side side = sideToMove();
// captures
Piece piece = extinctPiece(side);
if (!piece.isValid())
// promotions
piece = extinctPiece(side.opposite());
if (piece.isValid())
{
Side winner = piece.side().opposite();
int type = piece.type();
str = tr("Missing %1: %2 wins")
.arg(pieceString(type))
.arg(winner.toString());
return Result(Result::Win, winner, str);
}

// stalemate
if (!canMove())
{
str = tr("Draw by stalemate");
return Result(Result::Draw, Side::NoSide, str);
}

// 50 move rule
if (reversibleMoveCount() >= 100)
{
str = tr("Draw by fifty moves rule");
return Result(Result::Draw, Side::NoSide, str);
}

// 3-fold repetition
if (repeatCount() >= 2)
{
str = tr("Draw by 3-fold repetition");
return Result(Result::Draw, Side::NoSide, str);
}

return Result();
}



KingletBoard::KingletBoard() :
ExtinctionBoard({Pawn}, false)
{
}

Board* KingletBoard::copy() const
{
return new KingletBoard(*this);
}

QString KingletBoard::variant() const
{
return "kinglet";
}

} // namespace Chess
101 changes: 101 additions & 0 deletions projects/lib/src/board/extinctionboard.h
@@ -0,0 +1,101 @@
/*
This file is part of Cute Chess.
Cute Chess is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Cute Chess is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Cute Chess. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef EXTINCTIONBOARD_H
#define EXTINCTIONBOARD_H

#include "standardboard.h"

namespace Chess {

/*!
* \brief A board for Extinction Chess
*
* Extinction Chess (Survival of the Species by R. W. Schmittberger, USA,
* 1985) is a variant of standard chess but has a different objective.
*
* A side wins if their opponent loses all pieces of any kind.
*
* The king has no royal obligation, so there is no check and the king
* can be captured. Pawns can also promote to king. Castling is allowed.
*
* \note Rules: https://en.wikipedia.org/wiki/Extinction_chess
*
* ExtinctionBoard uses Polyglot-compatible zobrist position keys,
* so adequate opening books in Polyglot format can be used.
*
* \note Standard Chess Rules: http://www.fide.com/component/handbook/?id=124&view=article
* \sa PolyglotBook
*/
class LIB_EXPORT ExtinctionBoard : public StandardBoard
{
public:
/*! Creates a new ExtinctionBoard object.
* The \a set defines piece types that must not become extinct.
* If \a allPromotions is set (default) then all promotion
* types of standard chess are allowed (king anyhow).
*/
ExtinctionBoard(const QSet<int>& set
= QSet<int>{King, Queen, Rook, Bishop, Knight, Pawn},
bool allPromotions = true);

// Inherited from StandardBoard
virtual Board* copy() const;
virtual QString variant() const;
virtual QString defaultFenString() const;
virtual Result result();
protected:
// Inherited from StandardBoard
virtual bool kingsCountAssertion(int whiteKings,
int blackKings) const;
virtual bool inCheck(Side side, int square = 0) const;
virtual void addPromotions(int sourceSquare,
int targetSquare,
QVarLengthArray<Move>& moves) const;

private:
bool m_allPromotions;
QVarLengthArray<int> m_pieceSet;
Piece extinctPiece(Side side) const;
};


/*!
* \brief A board for Kinglet Chess
*
* Kinglet (V. R. Parton, UK 1953) is a standard chess variant similar to
* Extinction Chess. There are two differences:
*
* A side wins if their opponent loses all pawns (by capture or promotion).
* Pawns can only promote to king.
*
* The king has no royal obligation, so there is no check and the king can
* be captured. Castling is allowed. Stalemate is a draw.
*
* \note Rules: https://en.wikipedia.org/wiki/V._R._Parton#Kinglet_Chess
* \sa Extinction Chess
*/
class LIB_EXPORT KingletBoard : public ExtinctionBoard
{
public:
KingletBoard();
virtual Board *copy() const;
virtual QString variant() const;
};

} // namespace Chess
#endif // EXTINCTIONBOARD_H
33 changes: 33 additions & 0 deletions projects/lib/tests/chessboard/tst_board.cpp
Expand Up @@ -394,6 +394,32 @@ void tst_Board::results_data() const
<< variant
<< "2k4R/R7/8/3PP3/8/8/8/8 b - - 0 1"
<< "1-0";

variant = "extinction";

QTest::newRow("extinction white win")
<< variant
<< "6k1/5p2/7p/3p4/p2pr3/b1BQ2Pq/r1B1P1RP/N6K b - - 0 34"
<< "1-0";
QTest::newRow("extinction black win")
<< variant
<< "rn1qkbnr/ppp1pppp/3p4/8/4P1b1/8/PPPP1PPP/RNB1KBNR w KQkq - 0 3"
<< "0-1";

variant = "kinglet";

QTest::newRow("kinglet white win")
<< variant
<< "8/8/4P3/2Q5/1P6/1P6/8/8 b - - 0 1"
<< "1-0";
QTest::newRow("kinglet black win")
<< variant
<< "2k5/1pp3R1/6p1/r7/8/4K3/8/8 w - - 0 1"
<< "0-1";
QTest::newRow("kinglet two")
<< variant
<< "8/8/6p1/8/8/4P3/8/8 w - - 0 1"
<< "*";
}

void tst_Board::results()
Expand Down Expand Up @@ -543,6 +569,13 @@ void tst_Board::perft_data() const
<< "rnbqkbnr/6p1/2p1Pp1P/P1PPPP2/Pp4PP/1p2PPPP/1P2PPPP/PP1nPPPP b kq a3 0 18"
<< 5 //4 plies: 197287, 5 plies: 6429490
<< Q_UINT64_C(6429490);

variant = "extinction";
QTest::newRow("extinction startpos")
<< variant
<< "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
<< 5
<< Q_UINT64_C(4897256);
}

void tst_Board::perft()
Expand Down

0 comments on commit 6dfef16

Please sign in to comment.