浏览代码

Merge branch 'master' of https://gitlab.vis.ethz.ch/niwinkle/chessy

Nicolas Winkler 7 年之前
父节点
当前提交
00a6f3fb88
共有 7 个文件被更改,包括 186 次插入40 次删除
  1. 22 11
      src/BitBoard.h
  2. 14 14
      src/Board.cpp
  3. 1 0
      src/Board.h
  4. 42 0
      src/MoveGeneration.cpp
  5. 61 10
      src/MoveGeneration.h
  6. 32 2
      src/main.cpp
  7. 14 3
      src/makefile

+ 22 - 11
src/BitBoard.h

@@ -53,8 +53,8 @@ struct chessy::Bitboard
     inline constexpr Bitboard(U64 bits) : bits{ bits } {}
     inline static Bitboard fromIndex(Index i) { return U64(1) << i; }
 
-    inline void     setBit      (Index i)     { bits |= 1ULL << i.index; }
-    inline void     unsetBit    (Index i)     { bits |= ~(1ULL << i.index); }
+    inline void     setBit      (Index i)     { bits |= U64(1) << i.index; }
+    inline void     unsetBit    (Index i)     { bits |= ~(U64(1) << i.index); }
 
     inline void     setBit      (int row, int column)
         { setBit(row * 8 + column); }
@@ -62,18 +62,28 @@ struct chessy::Bitboard
         { unsetBit(row * 8 + column); }
 
 
-    static const    U64 aColumn             = 0x0101010101010101;
-    static const    U64 hColumn             = 0x8080808080808080;
+    static const    U64 aColumn             = 0x0101010101010101ULL;
+    static const    U64 hColumn             = 0x8080808080808080ULL;
     inline void     moveNorth   (int dist)  { bits <<= (8 * dist); }
+    inline Bitboard north       (int dist)  { return bits << (8 * dist); }
     inline void     moveSouth   (int dist)  { bits >>= (8 * dist); }
+    inline Bitboard south       (int dist)  { return bits >> (8 * dist); }
     inline void     moveNorthOne(void)      { bits <<= 8; }
+    inline Bitboard northOne    (void)      { return bits << 8; }
     inline void     moveSouthOne(void)      { bits >>= 8; }
-    inline void     moveEastOne (void)      { bits = (bits >> 1) & ~aColumn; }
-    inline void     moveWestOne (void)      { bits = (bits << 1) & ~hColumn; }
-    inline void     moveNEOne   (void)      { bits = (bits << 7) & ~aColumn; }
-    inline void     moveNWOne   (void)      { bits = (bits << 9) & ~hColumn; }
-    inline void     moveSEOne   (void)      { bits = (bits >> 9) & ~aColumn; }
-    inline void     moveSWOne   (void)      { bits = (bits >> 7) & ~hColumn; }
+    inline Bitboard southOne    (void)      { return bits >> 8; }
+    inline void     moveWestOne (void)      { bits = (bits & ~aColumn) >> 1; }
+    inline Bitboard westOne     (void)      { return (bits & ~aColumn) >> 1; }
+    inline void     moveEastOne (void)      { bits = (bits & ~hColumn) << 1; }
+    inline Bitboard eastOne     (void)      { return (bits & ~hColumn) << 1; }
+    inline void     moveNWOne   (void)      { bits = (bits << 7) & ~hColumn; }
+    inline Bitboard nwOne       (void)      { return (bits << 7) & ~hColumn; }
+    inline void     moveNEOne   (void)      { bits = (bits << 9) & ~aColumn; }
+    inline Bitboard neOne       (void)      { return (bits << 9) & ~aColumn; }
+    inline void     moveSWOne   (void)      { bits = (bits >> 9) & ~hColumn; }
+    inline Bitboard swOne       (void)      { return (bits >> 9) & ~hColumn; }
+    inline void     moveSEOne   (void)      { bits = (bits >> 7) & ~aColumn; }
+    inline Bitboard seOne       (void)      { return (bits >> 7) & ~aColumn; }
 
     inline void     operator &= (const Bitboard& b)         { bits &= b.bits; }
     inline void     operator |= (const Bitboard& b)         { bits |= b.bits; }
@@ -89,10 +99,11 @@ struct chessy::Bitboard
     inline explicit operator bool(void) const               { return bits != 0; }
 
     inline Bitboard mirror(void) const                      { return byteswap(bits); }
+    inline Index    getLeastSignificantBit (void) const     { return trailingZeroes(bits); }
 };
 
 
-static_assert(std::is_pod<chessy::Bitboard>().value,
+static_assert(std::is_pod<chessy::Bitboard>::value,
         "chessy::Bitboard should be a POD structure.");
 static_assert(sizeof(chessy::Bitboard) == sizeof(uint64_t),
         "chessy::Bitboard should be 64 bits in size.");

+ 14 - 14
src/Board.cpp

@@ -100,7 +100,7 @@ std::string Board::getFenBoard(void) const
 {
     using namespace std;
     stringstream str;
-    for (int row = 0; row < 8; row++) {
+    for (int row = 7; row >= 0; row--) {
         int counter = 0;
         for (int column = 0; column < 8; column++) {
             PieceType black = getBlackAtPosition({ row, column });
@@ -116,27 +116,27 @@ std::string Board::getFenBoard(void) const
                 counter = 0;
             }
             switch (black) {
-                case PieceType::PAWN:   str << 'P'; break;
-                case PieceType::KNIGHT: str << 'N'; break;
-                case PieceType::BISHOP: str << 'B'; break;
-                case PieceType::ROOK:   str << 'R'; break;
-                case PieceType::QUEEN:  str << 'Q'; break;
-                case PieceType::KING:   str << 'K'; break;
+                case PieceType::PAWN:   str << 'p'; break;
+                case PieceType::KNIGHT: str << 'n'; break;
+                case PieceType::BISHOP: str << 'b'; break;
+                case PieceType::ROOK:   str << 'r'; break;
+                case PieceType::QUEEN:  str << 'q'; break;
+                case PieceType::KING:   str << 'k'; break;
                 default:
                 switch (white) {
-                    case PieceType::PAWN:   str << 'p'; break;
-                    case PieceType::KNIGHT: str << 'n'; break;
-                    case PieceType::BISHOP: str << 'b'; break;
-                    case PieceType::ROOK:   str << 'r'; break;
-                    case PieceType::QUEEN:  str << 'q'; break;
-                    case PieceType::KING:   str << 'k'; break;
+                    case PieceType::PAWN:   str << 'P'; break;
+                    case PieceType::KNIGHT: str << 'N'; break;
+                    case PieceType::BISHOP: str << 'B'; break;
+                    case PieceType::ROOK:   str << 'R'; break;
+                    case PieceType::QUEEN:  str << 'Q'; break;
+                    case PieceType::KING:   str << 'K'; break;
                     default:;
                 }
             }
         }
         if (counter > 0)
             str << counter;
-        if (row != 7)
+        if (row != 0)
             str << "/";
     }
     return str.str();

+ 1 - 0
src/Board.h

@@ -108,3 +108,4 @@ public:
 };
 
 #endif // CHESSY_BOARD_H
+

+ 42 - 0
src/MoveGeneration.cpp

@@ -69,3 +69,45 @@ std::array<Bitboard, 64> KnightMoveGenerator::generateKnightMoves(void)
     return moves;
 }
 
+
+Bitboard PrimitiveQueenMoveGenerator::generateAttackSet(Index i,
+    Bitboard enemies, Bitboard friendly, bool straight, bool diagonal)
+{
+    Bitboard queen = Bitboard::fromIndex(i);
+    Bitboard occupied = (enemies | friendly) & ~queen;
+
+    // strange c++ incoming
+    auto iterate = [queen, occupied] (void (Bitboard::*moveStep)()) -> Bitboard {
+        Bitboard result = 0;
+        int a = 0;
+        for (Bitboard r = queen; !(r & occupied) && r;) {
+            (r.*moveStep)();
+            result |= r;
+            a++;
+        }
+        return result;
+    };
+
+    Bitboard possibleMoves = 0;
+    if (straight)
+        possibleMoves |=
+            iterate(&Bitboard::moveNorthOne) |
+            iterate(&Bitboard::moveSouthOne) |
+            iterate(&Bitboard::moveEastOne) |
+            iterate(&Bitboard::moveWestOne);
+    if (diagonal)
+        possibleMoves |=
+            iterate(&Bitboard::moveNEOne) |
+            iterate(&Bitboard::moveSEOne) |
+            iterate(&Bitboard::moveNWOne) |
+            iterate(&Bitboard::moveSWOne);   
+    return (possibleMoves & ~friendly);
+}
+
+
+Bitboard KingMoveGenerator::generateKingMoves(Bitboard king)
+{
+    return king.northOne() | king.southOne() | king.eastOne() | king.westOne() |
+        king.neOne() | king.nwOne() | king.swOne() | king.seOne();
+}
+

+ 61 - 10
src/MoveGeneration.h

@@ -7,21 +7,22 @@
 
 namespace chessy
 {
-    struct Move;
-
     // forward declaration
     class ChessGame;
 
+    struct Move;
     class PositionSet;
 
-    const int WHITE_SIDE = 0;
-    const int BLACK_SIDE = 1;
-
     template<int side>
     class PawnPushGenerator;
-
     class KnightMoveGenerator;
-    class RookMoveGenerator;
+    class PrimitiveQueenMoveGenerator;
+    class PrimitiveRookMoveGenerator;
+    class PrimitiveBishopMoveGenerator;
+    class KingMoveGenerator;
+
+    const int WHITE_SIDE = 0;
+    const int BLACK_SIDE = 1;
 }
 
 
@@ -44,7 +45,6 @@ struct chessy::Move
 class chessy::PositionSet
 {
     Bitboard bitboard;
-
 public:
 
     inline PositionSet(Bitboard b) : bitboard{ b } {}
@@ -113,6 +113,10 @@ public:
 };
 
 
+/*!
+ * extends \link PositionSet so that all possible destinations for
+ * a knight can be iterated over.
+ */
 class chessy::KnightMoveGenerator :
     public PositionSet
 {
@@ -128,10 +132,57 @@ private:
 };
 
 
-class chessy::RookMoveGenerator
+/*!
+ * uses a primitive algorithm to calculate all possible move destinations
+ * for a queen.
+ */
+class chessy::PrimitiveQueenMoveGenerator :
+    public PositionSet
+{
+protected:
+    inline PrimitiveQueenMoveGenerator(Index i, Bitboard enemies, Bitboard friendly,
+        bool straight, bool diagonal) :
+        PositionSet{ generateAttackSet(i, enemies, friendly, straight, diagonal) } {}
+public:
+    inline PrimitiveQueenMoveGenerator(Index i, Bitboard enemies,
+        Bitboard friendly) :
+        PrimitiveQueenMoveGenerator{ i, enemies, friendly, true, true } {}
+private:
+    Bitboard generateAttackSet(Index i, Bitboard enemies, Bitboard friendly,
+        bool straight, bool diagonal);
+};
+
+
+class chessy::PrimitiveBishopMoveGenerator :
+    public PrimitiveQueenMoveGenerator
 {
-    
+public:
+    inline PrimitiveBishopMoveGenerator(Index i, Bitboard enemies,
+        Bitboard friendly) :
+        // bishop moves are actually just diagonal queen moves
+        PrimitiveQueenMoveGenerator{ i, enemies, friendly, false, true } {}
 };
 
 
+class chessy::PrimitiveRookMoveGenerator :
+    public PrimitiveQueenMoveGenerator
+{
+public:
+    inline PrimitiveRookMoveGenerator(Index i, Bitboard enemies,
+        Bitboard friendly) :
+        // rook moves are actually just straight queen moves
+        PrimitiveQueenMoveGenerator{ i, enemies, friendly, true, false } {}
+};
+
+
+class chessy::KingMoveGenerator :
+    public PositionSet
+{
+public:
+    inline KingMoveGenerator(Bitboard king, Bitboard friendly) :
+        PositionSet{ generateKingMoves(king) & ~friendly } {}
+private:
+    Bitboard generateKingMoves(Bitboard king);
+};
+
 #endif // CHESSY_MOVEGENERATION_H

+ 32 - 2
src/main.cpp

@@ -14,22 +14,52 @@ auto main(int argc, char** argv) -> int
     try {
         cg.loadFromFen(line);
         cout << cg.generateFen() << endl;
+
+        Bitboard whites = cg.getBoard().getWhites();
+        Bitboard blacks = cg.getBoard().getBlacks();
+        
         PawnPushGenerator<BLACK_SIDE> mg{ cg };
         for (auto push : mg) {
             cout << "pawn: " << push.asString() << endl;
         }
         PositionSet knights = cg.getBoard().getBlackKnights();
         for (auto knight : knights) {
-            for (auto pos : KnightMoveGenerator{ knight, cg.getBoard().getBlacks() }) {
+            for (auto pos : KnightMoveGenerator{ knight, blacks }) {
                 cout << "knight: " << Move(knight, pos).asString() << endl;
             }
         }
+
+        PositionSet bishops = cg.getBoard().getBlackBishops();
+        for (auto bishop : bishops) {
+            for (auto pos : PrimitiveBishopMoveGenerator{ bishop, whites, blacks }) {
+                cout << "bishop: " << Move(bishop, pos).asString() << endl;
+            }
+        }
+
+        PositionSet rooks = cg.getBoard().getBlackRooks();
+        for (auto rook : rooks) {
+            for (auto pos : PrimitiveRookMoveGenerator{ rook, whites, blacks }) {
+                cout << "rook: " << Move(rook, pos).asString() << endl;
+            }
+        }
+
+        PositionSet queens = cg.getBoard().getBlackQueens();
+        for (auto queen : queens) {
+            for (auto pos : PrimitiveQueenMoveGenerator{ queen, whites, blacks }) {
+                cout << "queen: " << Move(queen, pos).asString() << endl;
+            }
+        }
+
+        Bitboard king = cg.getBoard().getBlackKings();
+        Index kingIndex = king.getLeastSignificantBit();
+        for (auto pos : KingMoveGenerator{ king, blacks }) {
+            cout << "king: " << Move(kingIndex, pos).asString() << endl;
+        }
     }
     catch (runtime_error& re) {
         cerr << re.what() << endl;
         return 1;
     }
-    cin.get();
     return 0;
     UciParser uciParser;
     uciParser.parse(cin, cout);

+ 14 - 3
src/makefile

@@ -1,19 +1,28 @@
 IDIR=       .
 CXX=        g++
+AS=         as
+ASFLAGS=    -arch x86_64
+STRIP=      strip
 CXXFLAGS=   -std=c++14
 LNFLAGS=    
 DEPS=       Bitfield.h
 OBJ=        main.o Board.o ChessGame.o UciParser.o MoveGeneration.o
 
 
-%.o: %.c $(DEPS)
-	$(CXX) -c -o $@ $< $(CXXFLAGS)
+%.s: %.cpp
+	$(CXX) $(CXXFLAGS) -S -o $@ $<
+
+%.o: %.s
+	$(AS) -o $@ $<
 
 chessy: $(OBJ)
 	$(CXX) -o $@ $^ $(LNFLAGS)
 
-release: CXXFLAGS += -O3
+all: chessy
+
+release: CXXFLAGS += -O2
 release: chessy
+	$(STRIP) chessy
 
 flto: CXXFLAGS += -flto
 flto: LNFLAGS += -flto
@@ -21,6 +30,8 @@ flto: release
 
 .PHONY: clean
 
+.SUFFIXES:
+
 clean:
 	rm -f *.o chessy