Add support for smaller board sizes, implement los alamos chess
authorianfab <ianfab@users.noreply.github.com>
Sun, 1 Jul 2018 14:01:24 +0000 (16:01 +0200)
committerianfab <ianfab@users.noreply.github.com>
Sun, 1 Jul 2018 14:23:20 +0000 (16:23 +0200)
However, the evaluation does not reflect the dependence of symmetry
on number of ranks and files yet.

src/evaluate.cpp
src/movegen.cpp
src/position.cpp
src/position.h
src/types.h
src/variant.cpp
src/variant.h

index aaf3f89..e3a3088 100644 (file)
@@ -34,8 +34,8 @@ namespace Trace {
 
   enum Tracing { NO_TRACE, TRACE };
 
-  enum Term { // The first 8 entries are reserved for PieceType
-    MATERIAL = 8, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, INITIATIVE, VARIANT, TOTAL, TERM_NB
+  enum Term { // The first PIECE_TYPE_NB entries are reserved for PieceType
+    MATERIAL = PIECE_TYPE_NB, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, INITIATIVE, VARIANT, TOTAL, TERM_NB
   };
 
   Score scores[TERM_NB][COLOR_NB];
index 88f350d..3010f18 100644 (file)
@@ -108,7 +108,7 @@ namespace {
 
     Bitboard emptySquares;
 
-    Bitboard TRank8BB = rank_bb(Us == WHITE ? pos.promotion_rank() : ~pos.promotion_rank());
+    Bitboard TRank8BB = rank_bb(Us == WHITE ? pos.promotion_rank() : Rank(pos.max_rank() - pos.promotion_rank()));
     Bitboard TRank7BB = shift<Down>(TRank8BB);
     Bitboard pawnsOn7    = pos.pieces(Us, PAWN) &  TRank7BB;
     Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;
index 1a0d010..f39afa0 100644 (file)
@@ -248,7 +248,6 @@ Position& Position::set(const Variant* v, const string& fenStr, bool isChess960,
 
   unsigned char col, row, token;
   size_t idx;
-  Square sq = SQ_A8;
   std::istringstream ss(fenStr);
 
   std::memset(this, 0, sizeof(Position));
@@ -259,6 +258,8 @@ Position& Position::set(const Variant* v, const string& fenStr, bool isChess960,
 
   ss >> std::noskipws;
 
+  Square sq = SQ_A8 + (RANK_8 - max_rank()) * SOUTH;
+
   // 1. Piece placement
   while ((ss >> token) && !isspace(token))
   {
@@ -266,7 +267,7 @@ Position& Position::set(const Variant* v, const string& fenStr, bool isChess960,
           sq += (token - '0') * EAST; // Advance the given number of files
 
       else if (token == '/')
-          sq += 2 * SOUTH;
+          sq += 2 * SOUTH + (FILE_H - max_file()) * EAST;
 
       else if ((idx = piece_to_char().find(token)) != string::npos)
       {
@@ -510,17 +511,17 @@ const string Position::fen() const {
   int emptyCnt;
   std::ostringstream ss;
 
-  for (Rank r = RANK_8; r >= RANK_1; --r)
+  for (Rank r = max_rank(); r >= RANK_1; --r)
   {
-      for (File f = FILE_A; f <= FILE_H; ++f)
+      for (File f = FILE_A; f <= max_file(); ++f)
       {
-          for (emptyCnt = 0; f <= FILE_H && empty(make_square(f, r)); ++f)
+          for (emptyCnt = 0; f <= max_file() && empty(make_square(f, r)); ++f)
               ++emptyCnt;
 
           if (emptyCnt)
               ss << emptyCnt;
 
-          if (f <= FILE_H)
+          if (f <= max_file())
           {
               ss << piece_to_char()[piece_on(make_square(f, r))];
 
@@ -633,6 +634,10 @@ bool Position::legal(Move m) const {
   assert(color_of(moved_piece(m)) == us);
   assert(piece_on(square<KING>(us)) == make_piece(us, KING));
 
+  // illegal moves to squares outside of board
+  if (rank_of(to) > max_rank() || file_of(to) > max_file())
+      return false;
+
   // illegal checks
   if (!checking_permitted() && gives_check(m))
       return false;
@@ -723,7 +728,7 @@ bool Position::pseudo_legal(const Move m) const {
   {
       // We have already handled promotion moves, so destination
       // cannot be on the 8th/1st rank.
-      if (rank_of(to) == relative_rank(us, promotion_rank()))
+      if (rank_of(to) == relative_rank(us, promotion_rank(), max_rank()))
           return false;
 
       if (   !(attacks_from<PAWN>(us, from) & pieces(~us) & to) // Not a capture
@@ -976,7 +981,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
       {
           Piece promotion = make_piece(us, promotion_type(m));
 
-          assert(relative_rank(us, to) == promotion_rank());
+          assert(relative_rank(us, to, max_rank()) == promotion_rank());
           assert(type_of(promotion) >= KNIGHT && type_of(promotion) < KING);
 
           remove_piece(pc, to);
@@ -1053,7 +1058,7 @@ void Position::undo_move(Move m) {
 
   if (type_of(m) == PROMOTION)
   {
-      assert(relative_rank(us, to) == promotion_rank());
+      assert(relative_rank(us, to, max_rank()) == promotion_rank());
       assert(type_of(pc) == promotion_type(m));
       assert(type_of(pc) >= KNIGHT && type_of(pc) < KING);
 
index 7e73ace..9ecc7e8 100644 (file)
@@ -87,6 +87,8 @@ public:
 
   // Variant rule properties
   const Variant* variant() const;
+  Rank max_rank() const;
+  File max_file() const;
   const std::string piece_to_char() const;
   Rank promotion_rank() const;
   std::vector<PieceType> promotion_piece_types() const;
@@ -240,6 +242,16 @@ inline const Variant* Position::variant() const {
   return var;
 }
 
+inline Rank Position::max_rank() const {
+  assert(var != nullptr);
+  return var->maxRank;
+}
+
+inline File Position::max_file() const {
+  assert(var != nullptr);
+  return var->maxFile;
+}
+
 inline const std::string Position::piece_to_char() const {
   assert(var != nullptr);
   return var->pieceToChar;
index 9165fb0..df9f41c 100644 (file)
@@ -441,12 +441,12 @@ constexpr Square relative_square(Color c, Square s) {
   return Square(s ^ (c * 56));
 }
 
-constexpr Rank relative_rank(Color c, Rank r) {
-  return Rank(r ^ (c * 7));
+constexpr Rank relative_rank(Color c, Rank r, Rank maxRank = RANK_8) {
+  return Rank(r ^ (c * maxRank));
 }
 
-constexpr Rank relative_rank(Color c, Square s) {
-  return relative_rank(c, rank_of(s));
+constexpr Rank relative_rank(Color c, Square s, Rank maxRank = RANK_8) {
+  return relative_rank(c, rank_of(s), maxRank);
 }
 
 inline bool opposite_colors(Square s1, Square s2) {
index dc6209a..9f30262 100644 (file)
@@ -181,6 +181,18 @@ void VariantMap::init() {
         // TODO: piece promotions, illegal pawn drops
         return v;
     } ();
+    const Variant* losalamos = [&]{
+        Variant* v = new Variant();
+        v->maxRank = RANK_6;
+        v->maxFile = FILE_F;
+        v->set_piece(BISHOP, ' ');
+        v->startFen = "rnqknr/pppppp/6/6/PPPPPP/RNQKNR w - - 0 1";
+        v->promotionRank = RANK_6;
+        v->promotionPieceTypes = {QUEEN, ROOK, KNIGHT};
+        v->doubleStep = false;
+        v->castling = false;
+        return v;
+    } ();
     insert(std::pair<std::string, const Variant*>(std::string("chess"), chess));
     insert(std::pair<std::string, const Variant*>(std::string("makruk"), makruk));
     insert(std::pair<std::string, const Variant*>(std::string("asean"), asean));
@@ -196,6 +208,7 @@ void VariantMap::init() {
     insert(std::pair<std::string, const Variant*>(std::string("crazyhouse"), crazyhouse));
     insert(std::pair<std::string, const Variant*>(std::string("loop"), loop));
     insert(std::pair<std::string, const Variant*>(std::string("euroshogi"), euroshogi));
+    insert(std::pair<std::string, const Variant*>(std::string("losalamos"), losalamos));
 }
 
 void VariantMap::clear_all() {
index f628f73..9b313a2 100644 (file)
@@ -32,6 +32,8 @@
 /// Variant struct stores information needed to determine the rules of a variant.
 
 struct Variant {
+  Rank maxRank = RANK_8;
+  File maxFile = FILE_H;
   std::string pieceToChar =  " PNBRQ" + std::string(KING - QUEEN - 1, ' ') + "K" + std::string(PIECE_TYPE_NB - KING - 1, ' ')
                            + " pnbrq" + std::string(KING - QUEEN - 1, ' ') + "k" + std::string(PIECE_TYPE_NB - KING - 1, ' ');
   std::string startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";