From: Fabian Fichter Date: Fri, 15 Nov 2019 15:31:44 +0000 (+0100) Subject: Support Manchu chess X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=893721a7b1f0a5c6a958d8cdeadfac32f16a5357;p=fairystockfish.git Support Manchu chess https://en.wikipedia.org/wiki/Manchu_chess bench: 4700464 --- diff --git a/Readme.md b/Readme.md index a989b78..a52651b 100644 --- a/Readme.md +++ b/Readme.md @@ -14,7 +14,7 @@ The goal of the project is to create an engine supporting a large variety of che The games currently supported besides chess are listed below. Fairy-Stockfish can also play user-defined variants loaded via a variant configuration file, see the file `src/variants.ini`. ### Regional and historical games -- [Xiangqi](https://en.wikipedia.org/wiki/Xiangqi), [Minixiangqi](http://mlwi.magix.net/bg/minixiangqi.htm) +- [Xiangqi](https://en.wikipedia.org/wiki/Xiangqi), [Manchu](https://en.wikipedia.org/wiki/Manchu_chess), [Minixiangqi](http://mlwi.magix.net/bg/minixiangqi.htm) - [Shogi](https://en.wikipedia.org/wiki/Shogi) - [Makruk](https://en.wikipedia.org/wiki/Makruk), [Ouk Chatrang](https://en.wikipedia.org/wiki/Makruk#Cambodian_chess), [Kar Ouk](https://en.wikipedia.org/wiki/Makruk#Cambodian_chess), [ASEAN](http://hgm.nubati.net/rules/ASEAN.html), Ai-Wok - [Sittuyin](https://en.wikipedia.org/wiki/Sittuyin) diff --git a/src/movegen.cpp b/src/movegen.cpp index b418016..6232eac 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -453,7 +453,7 @@ ExtMove* generate(const Position& pos, ExtMove* moveList) { Bitboard sliders = pos.checkers(); // Consider all evasion moves for special pieces - if (sliders & (pos.pieces(CANNON) | pos.pieces(HORSE, ELEPHANT))) + if (sliders & (pos.pieces(CANNON, BANNER) | pos.pieces(HORSE, ELEPHANT))) { Bitboard target = pos.board_bb() & ~pos.pieces(us); Bitboard b = pos.attacks_from(us, ksq) & target; diff --git a/src/piece.cpp b/src/piece.cpp index 60f6f83..f193266 100644 --- a/src/piece.cpp +++ b/src/piece.cpp @@ -288,6 +288,16 @@ namespace { p->lameLeaper = true; return p; } + PieceInfo* banner_piece() { + PieceInfo* p = rook_piece(); + p->name = "banner"; + PieceInfo* p2 = horse_piece(); + p->merge(p2); + delete p2; + p->hopperCapture = {NORTH, EAST, SOUTH, WEST}; + p->lameLeaper = true; + return p; + } PieceInfo* centaur_piece() { PieceInfo* p = commoner_piece(); p->name = "centaur"; @@ -330,6 +340,7 @@ void PieceMap::init() { add(SOLDIER, soldier_piece()); add(HORSE, horse_piece()); add(ELEPHANT, elephant_piece()); + add(BANNER, banner_piece()); add(WAZIR, wazir_piece()); add(COMMONER, commoner_piece()); add(CENTAUR, centaur_piece()); diff --git a/src/position.cpp b/src/position.cpp index 0279eff..4c22bac 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -752,13 +752,13 @@ Bitboard Position::attackers_to(Square s, Bitboard occupied, Color c) const { if (board_bb(c, pt) & s) { // Consider asymmetrical move of horse - if (pt == HORSE) + if (pt == HORSE || pt == BANNER) { - Bitboard horses = PseudoAttacks[~c][KNIGHT][s] & pieces(c, HORSE); + Bitboard horses = PseudoAttacks[~c][pt][s] & pieces(c, pt); while (horses) { Square s2 = pop_lsb(&horses); - if (attacks_bb(c, HORSE, s2, occupied) & s) + if (attacks_bb(c, pt, s2, occupied) & s) b |= s2; } } @@ -999,7 +999,7 @@ bool Position::pseudo_legal(const Move m) const { // Evasions generator already takes care to avoid some kind of illegal moves // and legal() relies on this. We therefore have to take care that the same // kind of moves are filtered out here. - if (checkers() & ~(pieces(CANNON) | pieces(HORSE, ELEPHANT))) + if (checkers() & ~(pieces(CANNON, BANNER) | pieces(HORSE, ELEPHANT))) { if (type_of(pc) != KING) { @@ -1040,18 +1040,19 @@ bool Position::gives_check(Move m) const { // Is there a direct check? if (type_of(m) != PROMOTION && type_of(m) != PIECE_PROMOTION && type_of(m) != PIECE_DEMOTION) { - if (type_of(moved_piece(m)) == CANNON || type_of(moved_piece(m)) == HORSE) + PieceType pt = type_of(moved_piece(m)); + if (pt == CANNON || pt == BANNER || pt == HORSE) { - if (attacks_bb(sideToMove, type_of(moved_piece(m)), to, (pieces() ^ from) | to) & square(~sideToMove)) + if (attacks_bb(sideToMove, pt, to, (pieces() ^ from) | to) & square(~sideToMove)) return true; } - else if (st->checkSquares[type_of(moved_piece(m))] & to) + else if (st->checkSquares[pt] & to) return true; } // Is there a discovered check? if ( type_of(m) != DROP - && ((st->blockersForKing[~sideToMove] & from) || pieces(sideToMove, CANNON, HORSE)) + && ((st->blockersForKing[~sideToMove] & from) || (pieces(sideToMove, CANNON, BANNER) | pieces(HORSE, ELEPHANT))) && attackers_to(square(~sideToMove), (pieces() ^ from) | to, sideToMove)) return true; diff --git a/src/psqt.cpp b/src/psqt.cpp index 985c618..82d306f 100644 --- a/src/psqt.cpp +++ b/src/psqt.cpp @@ -30,13 +30,15 @@ Value PieceValue[PHASE_NB][PIECE_NB] = { ArchbishopValueMg, ChancellorValueMg, AmazonValueMg, KnibisValueMg, BiskniValueMg, KnirooValueMg, RookniValueMg, ShogiPawnValueMg, LanceValueMg, ShogiKnightValueMg, EuroShogiKnightValueMg, GoldValueMg, DragonHorseValueMg, ClobberPieceValueMg, BreakthroughPieceValueMg, ImmobilePieceValueMg, - CannonPieceValueMg, SoldierValueMg, HorseValueMg, ElephantValueMg, WazirValueMg, CommonerValueMg, CentaurValueMg }, + CannonPieceValueMg, SoldierValueMg, HorseValueMg, ElephantValueMg, BannerValueMg, + WazirValueMg, CommonerValueMg, CentaurValueMg }, { VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg, FersValueEg, AlfilValueEg, FersAlfilValueEg, SilverValueEg, AiwokValueEg, BersValueEg, ArchbishopValueMg, ChancellorValueEg, AmazonValueEg, KnibisValueMg, BiskniValueMg, KnirooValueEg, RookniValueEg, ShogiPawnValueEg, LanceValueEg, ShogiKnightValueEg, EuroShogiKnightValueEg, GoldValueEg, DragonHorseValueEg, ClobberPieceValueEg, BreakthroughPieceValueEg, ImmobilePieceValueEg, - CannonPieceValueEg, SoldierValueEg, HorseValueEg, ElephantValueEg, WazirValueEg, CommonerValueEg, CentaurValueEg } + CannonPieceValueEg, SoldierValueEg, HorseValueEg, ElephantValueEg, BannerValueEg, + WazirValueEg, CommonerValueEg, CentaurValueEg } }; namespace PSQT { diff --git a/src/types.h b/src/types.h index 4858ccc..839d4e3 100644 --- a/src/types.h +++ b/src/types.h @@ -341,6 +341,7 @@ enum Value : int { SoldierValueMg = 200, SoldierValueEg = 300, HorseValueMg = 500, HorseValueEg = 800, ElephantValueMg = 350, ElephantValueEg = 350, + BannerValueMg = 3500, BannerValueEg = 3500, WazirValueMg = 400, WazirValueEg = 400, CommonerValueMg = 700, CommonerValueEg = 900, CentaurValueMg = 1500, CentaurValueEg = 1500, @@ -355,7 +356,8 @@ enum PieceType { FERS, MET = FERS, ALFIL, FERS_ALFIL, SILVER, KHON = SILVER, AIWOK, BERS, DRAGON = BERS, ARCHBISHOP, CHANCELLOR, AMAZON, KNIBIS, BISKNI, KNIROO, ROOKNI, SHOGI_PAWN, LANCE, SHOGI_KNIGHT, EUROSHOGI_KNIGHT, GOLD, DRAGON_HORSE, - CLOBBER_PIECE, BREAKTHROUGH_PIECE, IMMOBILE_PIECE, CANNON, SOLDIER, HORSE, ELEPHANT, WAZIR, COMMONER, CENTAUR, KING, + CLOBBER_PIECE, BREAKTHROUGH_PIECE, IMMOBILE_PIECE, CANNON, SOLDIER, HORSE, ELEPHANT, BANNER, + WAZIR, COMMONER, CENTAUR, KING, ALL_PIECES = 0, PIECE_TYPE_NB = 1 << PIECE_TYPE_BITS diff --git a/src/variant.cpp b/src/variant.cpp index 9d91e55..81e0aeb 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -739,6 +739,13 @@ namespace { v->xiangqiSoldier = true; return v; } + Variant* manchu_variant() { + Variant* v = xiangqi_variant(); + v->pieceToCharTable = "PN.R.AB..K.C....M.....pn.r.ab..k.c.........."; + v->add_piece(BANNER, 'm'); + v->startFen = "rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/9/9/M1BAKAB2 w - - 0 1"; + return v; + } #endif } // namespace @@ -813,6 +820,7 @@ void VariantMap::init() { add("shako", shako_variant()); add("clobber10", clobber10_variant()); add("xiangqi", xiangqi_variant()); + add("manchu", manchu_variant()); #endif } diff --git a/src/variants.ini b/src/variants.ini index b8b8375..49c0440 100644 --- a/src/variants.ini +++ b/src/variants.ini @@ -75,9 +75,10 @@ # soldier # horse # elephant +# banner (=rook+cannon+horse) # wazir # commoner (non-royal king) -# centaur (=knight + commoner) +# centaur (=knight+commoner) # king ### Option types