NOTATION_JANGGI,
// https://en.wikipedia.org/wiki/Xiangqi#Notation
NOTATION_XIANGQI_WXF,
+ // https://web.archive.org/web/20180817205956/http://bgsthai.com/2018/05/07/lawofthaichessc/
+ NOTATION_THAI_SAN,
+ NOTATION_THAI_LAN,
};
inline Notation default_notation(const Variant* v) {
VARIANT_END,
};
+const std::array<std::string, 12> THAI_FILES = {"ก", "ข", "ค", "ง", "จ", "ฉ", "ช", "ญ", "ต", "ถ", "ธ", "น"};
+const std::array<std::string, 12> THAI_RANKS = {"๑", "๒", "๓", "๔", "๕", "๖", "๗", "๘", "๙", "๑๐", "๑๑", "๑๒"};
+
namespace SAN {
enum Disambiguation {
return n == NOTATION_SHOGI_HOSKING || n == NOTATION_SHOGI_HODGES || n == NOTATION_SHOGI_HODGES_NUMBER;
}
+inline bool is_thai(Notation n) {
+ return n == NOTATION_THAI_SAN || n == NOTATION_THAI_LAN;
+}
+
// is there more than one file with a pair of pieces?
inline bool multi_tandem(Bitboard b) {
int tandems = 0;
return tandems >= 2;
}
+inline std::string piece_to_thai_char(Piece pc, bool promoted) {
+ switch(type_of(pc)) {
+ case KING:
+ return "ข";
+ case KHON:
+ return "ค";
+ case FERS:
+ return promoted ? "ง" : "ม็";
+ case KNIGHT:
+ return "ม";
+ case ROOK:
+ return "ร";
+ case PAWN:
+ return "บ";
+ case AIWOK:
+ return "ว";
+ default:
+ return "X";
+ }
+}
+
inline std::string piece(const Position& pos, Move m, Notation n) {
Color us = pos.side_to_move();
Square from = from_sq(m);
Piece pc = pos.moved_piece(m);
PieceType pt = type_of(pc);
// Quiet pawn moves
- if ((n == NOTATION_SAN || n == NOTATION_LAN) && type_of(pc) == PAWN && type_of(m) != DROP)
+ if ((n == NOTATION_SAN || n == NOTATION_LAN || n == NOTATION_THAI_SAN) && type_of(pc) == PAWN && type_of(m) != DROP)
return "";
// Tandem pawns
else if (n == NOTATION_XIANGQI_WXF && popcount(pos.pieces(us, pt) & file_bb(from)) >= 3 - multi_tandem(pos.pieces(us, pt)))
// Promoted drops
else if (is_shogi(n) && type_of(m) == DROP && dropped_piece_type(m) != in_hand_piece_type(m))
return "+" + std::string(1, toupper(pos.piece_to_char()[in_hand_piece_type(m)]));
+ else if (is_thai(n))
+ return piece_to_thai_char(pc, pos.is_promoted(from));
else if (pos.piece_to_char_synonyms()[pc] != ' ')
return std::string(1, toupper(pos.piece_to_char_synonyms()[pc]));
else
return std::to_string(file_of(s) + 1);
case NOTATION_XIANGQI_WXF:
return std::to_string((pos.side_to_move() == WHITE ? pos.max_file() - file_of(s) : file_of(s)) + 1);
+ case NOTATION_THAI_SAN:
+ case NOTATION_THAI_LAN:
+ return THAI_FILES[file_of(s)];
default:
return std::string(1, char('a' + file_of(s)));
}
else
return "+";
}
+ case NOTATION_THAI_SAN:
+ case NOTATION_THAI_LAN:
+ return THAI_RANKS[rank_of(s)];
default:
return std::to_string(rank_of(s) + 1);
}
return NO_DISAMBIGUATION;
// NOTATION_LAN and Janggi always use disambiguation
- if (n == NOTATION_LAN || n == NOTATION_JANGGI)
+ if (n == NOTATION_LAN || n == NOTATION_THAI_LAN || n == NOTATION_JANGGI)
return SQUARE_DISAMBIGUATION;
Color us = pos.side_to_move();
}
// Pawn captures always use disambiguation
- if (n == NOTATION_SAN && pt == PAWN)
+ if ((n == NOTATION_SAN || n == NOTATION_THAI_SAN) && pt == PAWN)
{
if (pos.capture(m))
return FILE_DISAMBIGUATION;
// Piece
san += piece(pos, m, n);
+ if (n == NOTATION_THAI_LAN)
+ san += " ";
+
// Origin square, disambiguation
Disambiguation d = disambiguation_level(pos, m, n);
san += disambiguation(pos, from, n, d);
}
else if (pos.capture(m))
san += 'x';
- else if (n == NOTATION_LAN || (is_shogi(n) && (n != NOTATION_SHOGI_HOSKING || d == SQUARE_DISAMBIGUATION)) || n == NOTATION_JANGGI)
+ else if (n == NOTATION_LAN || n == NOTATION_THAI_LAN || (is_shogi(n) && (n != NOTATION_SHOGI_HOSKING || d == SQUARE_DISAMBIGUATION)) || n == NOTATION_JANGGI || (n == NOTATION_THAI_SAN && type_of(pos.moved_piece(m)) != PAWN))
san += '-';
// Destination square
result = sf.get_san("janggi", fen, "f8f10", False, sf.NOTATION_SAN)
self.assertEqual(result, "Cfxf10")
+ result = sf.get_san("makruk", MAKRUK, "e3e4")
+ self.assertEqual(result, "e4")
+ result = sf.get_san("makruk", MAKRUK, "e3e4", False, sf.NOTATION_THAI_SAN)
+ self.assertEqual(result, "จ๔")
+ result = sf.get_san("makruk", MAKRUK, "e3e4", False, sf.NOTATION_THAI_LAN)
+ self.assertEqual(result, "บ จ๓-จ๔")
+
+ fen = "r1smksnr/3n4/pppp1ppp/4p3/4PP2/PPPP2PP/8/RNSKMSNR w - - 0 1"
+ result = sf.get_san("makruk", fen, "f4e5")
+ self.assertEqual(result, "fxe5")
+ result = sf.get_san("makruk", fen, "f4e5", False, sf.NOTATION_THAI_SAN)
+ self.assertEqual(result, "ฉxจ๕")
+ result = sf.get_san("makruk", fen, "f4e5", False, sf.NOTATION_THAI_LAN)
+ self.assertEqual(result, "บ ฉ๔xจ๕")
+
fen = "rnsm1s1r/4n1k1/1ppppppp/p7/2PPP3/PP3PPP/4N2R/RNSKMS2 b - - 1 5"
result = sf.get_san("makruk", fen, "f8f7")
self.assertEqual(result, "Sf7")
+ result = sf.get_san("makruk", fen, "f8f7", False, sf.NOTATION_THAI_SAN)
+ self.assertEqual(result, "ค-ฉ๗")
+ result = sf.get_san("makruk", fen, "f8f7", False, sf.NOTATION_THAI_LAN)
+ self.assertEqual(result, "ค ฉ๘-ฉ๗")
fen = "4k3/8/8/4S3/8/2S5/8/4K3 w - - 0 1"
result = sf.get_san("makruk", fen, "e5d4")
self.assertEqual(result, "Sed4")
-
result = sf.get_san("makruk", fen, "c3d4")
self.assertEqual(result, "Scd4")
+ result = sf.get_san("makruk", fen, "e5d4", False, sf.NOTATION_THAI_SAN)
+ self.assertEqual(result, "คจ-ง๔")
+ result = sf.get_san("makruk", fen, "c3d4", False, sf.NOTATION_THAI_SAN)
+ self.assertEqual(result, "คค-ง๔")
+ result = sf.get_san("makruk", fen, "e5d4", False, sf.NOTATION_THAI_LAN)
+ self.assertEqual(result, "ค จ๕-ง๔")
+ result = sf.get_san("makruk", fen, "c3d4", False, sf.NOTATION_THAI_LAN)
+ self.assertEqual(result, "ค ค๓-ง๔")
+
+ # Distinction between the regular met and the promoted pawn
+ fen = "4k3/8/4M3/4S3/8/2S5/8/4K3 w - - 0 1"
+ result = sf.get_san("makruk", fen, "e6d5", False, sf.NOTATION_THAI_SAN)
+ self.assertEqual(result, "ม็-ง๕")
+ fen = "4k3/8/4M~3/4S3/8/2S5/8/4K3 w - - 0 1"
+ result = sf.get_san("makruk", fen, "e6d5", False, sf.NOTATION_THAI_SAN)
+ self.assertEqual(result, "ง-ง๕")
fen = "4k3/8/8/3S4/8/3S4/8/4K3 w - - 0 1"
result = sf.get_san("makruk", fen, "d3d4")
self.assertEqual(result, "Sd4")
+ result = sf.get_san("makruk", fen, "d3d4", False, sf.NOTATION_THAI_SAN)
+ self.assertEqual(result, "ค-ง๔")
+ result = sf.get_san("makruk", fen, "d3d4", False, sf.NOTATION_THAI_LAN)
+ self.assertEqual(result, "ค ง๓-ง๔")
+
UCI_moves = ["e2e4", "e7e5", "g1f3", "b8c6h", "f1c4", "f8c5e"]
SAN_moves = ["e4", "e5", "Nf3", "Nc6/H", "Bc4", "Bc5/E"]