瀏覽代碼

yes, that's good

nicolaswinkler 8 年之前
父節點
當前提交
174b444bc1
共有 8 個文件被更改,包括 266 次插入11 次删除
  1. 11 3
      src/BitBoard.h
  2. 97 0
      src/Board.cpp
  3. 31 2
      src/Board.h
  4. 103 1
      src/ChessGame.cpp
  5. 13 1
      src/ChessGame.h
  6. 2 4
      src/UciParser.cpp
  7. 2 0
      src/UciParser.h
  8. 7 0
      src/main.cpp

+ 11 - 3
src/BitBoard.h

@@ -3,6 +3,7 @@
 
 #include <cinttypes>
 #include <type_traits>
+#include <array>
 
 
 namespace chessy
@@ -24,9 +25,16 @@ union chessy::Index
         uint8_t row    : 3;
     };
 
-    Index() = default;
+    Index(void) = default;
     inline Index(int8_t ind) : index {ind} {}
+    inline Index(int row, int column) :
+        index{int8_t(row & 0x7 + (column & 0x7) << 3)} {}
     inline operator int8_t (void) const { return index; }
+
+    inline std::array<char, 2> getName(void) const
+    {
+        return {char('a' + row), char('0' + column)};
+    }
 };
 
 
@@ -41,8 +49,8 @@ struct chessy::Bitboard
     inline Bitboard (U64 bits) : bits {bits} {}
     inline static Bitboard fromIndex(Index i) { return 1 << i; }
 
-    inline void     setBit      (int i)     { bits |= 1 << i; }
-    inline void     unsetBit    (int i)     { bits |= ~(1 << i); }
+    inline void     setBit      (Index i)     { bits |= 1 << i.index; }
+    inline void     unsetBit    (Index i)     { bits |= ~(1 << i.index); }
 
     inline void     setBit      (int row, int column)
         { setBit(row * 8 + column); }

+ 97 - 0
src/Board.cpp

@@ -1,7 +1,24 @@
 #include "Board.h"
 #include <string>
+#include <unordered_map>
+#include <ctype.h>
+#include <stdexcept>
+#include <sstream>
 
 using namespace chessy;
+using namespace std;
+
+
+Bitboard& Board::operator[] (int index)
+{
+    return (&whitePawns)[index];
+}
+
+
+const Bitboard& Board::operator[] (int index) const
+{
+    return (&whitePawns)[index];
+}
 
 
 void Board::resetBoard(void)
@@ -29,6 +46,86 @@ bool Board::tryToMove(Bitboard start, Bitboard end, Bitboard& b)
 }
 
 
+void Board::setBoard(const std::string& fenPosition)
+{
+    int row = 0, column = 0;
+    unordered_map<char, Bitboard*> boards {
+        {'p', &whitePawns},
+        {'n', &whiteKnights},
+        {'b', &whiteBishops},
+        {'r', &whiteRooks},
+        {'q', &whiteQueens},
+        {'k', &whiteKing},
+        {'P', &blackPawns},
+        {'N', &blackKnights},
+        {'B', &blackBishops},
+        {'R', &blackRooks},
+        {'Q', &blackQueens},
+        {'K', &blackKing}
+    };
+
+    for (auto character : fenPosition) {
+        if (character >= '0' && character <= '9') {
+            column += character - '0';
+        }
+        else if (character == '/') {
+            ++ row;
+        }
+        else {
+            auto board = boards.find(character);
+            if (board != boards.end()) {
+                *(board->second) |= Bitboard::fromIndex({row, column});
+            }
+            else {
+                throw runtime_error("invalid piece type "s + character);
+            }
+        }
+    }
+}
+
+
+std::string Board::getFenBoard(void) const
+{
+    using namespace std;
+    stringstream str;
+    for (int row = 0; row < 8; row++) {
+        int counter = 0;
+        for (int column; column < 8; column++) {
+
+        }
+        if (row != 7)
+            str << "/";
+    }
+    return str.str();
+}
+
+
+PieceType Board::getWhiteAtPosition(Index i) const
+{
+    Bitboard mask = Bitboard::fromIndex(i);
+    if (whitePawns & mask)      return PieceType::PAWN;
+    if (whiteKnights & mask)    return PieceType::KNIGHT;
+    if (whiteBishops & mask)    return PieceType::BISHOP;
+    if (whiteRooks & mask)      return PieceType::ROOK;
+    if (whiteQueens & mask)     return PieceType::QUEEN;
+    if (whiteKing & mask)       return PieceType::KING;
+                                return PieceType::EMPTY;
+}
+
+
+PieceType Board::getBlackAtPosition(Index i) const
+{
+    Bitboard mask = Bitboard::fromIndex(i);
+    if (blackPawns & mask)      return PieceType::PAWN;
+    if (blackKnights & mask)    return PieceType::KNIGHT;
+    if (blackBishops & mask)    return PieceType::BISHOP;
+    if (blackRooks & mask)      return PieceType::ROOK;
+    if (blackQueens & mask)     return PieceType::QUEEN;
+    if (blackKing & mask)       return PieceType::KING;
+                                return PieceType::EMPTY;
+}
+
+
 void Board::applyMove(const Move& move)
 {
     Bitboard start = Bitboard::fromIndex(move.origin);

+ 31 - 2
src/Board.h

@@ -4,25 +4,41 @@
 #include "BitBoard.h"
 #include "MoveGeneration.h"
 
+#include <string>
+
 namespace chessy
 {
+    enum class PieceType : int;
+
     class Board;
 }
 
 
+enum class chessy::PieceType : int
+{
+    EMPTY = -1,
+    PAWN = 0,
+    KNIGHT = 1,
+    BISHOP = 2,
+    ROOK = 3,
+    QUEEN = 4,
+    KING = 5
+};
+
+
 class chessy::Board
 {
     Bitboard whitePawns;
-    Bitboard whiteRooks;
     Bitboard whiteKnights;
     Bitboard whiteBishops;
+    Bitboard whiteRooks;
     Bitboard whiteQueens;
     Bitboard whiteKing;
 
     Bitboard blackPawns;
-    Bitboard blackRooks;
     Bitboard blackKnights;
     Bitboard blackBishops;
+    Bitboard blackRooks;
     Bitboard blackQueens;
     Bitboard blackKing;
 
@@ -31,6 +47,9 @@ public:
     Board(const Board&) = default;
     ~Board(void) = default;
 
+    Bitboard& operator [] (int index);
+    const Bitboard& operator [] (int index) const;
+
     /*!
      * resets the board to the chess starting position.
      */
@@ -41,6 +60,16 @@ private:
 public:
 
     /*!
+     * parses the first part of a FEN string and sets the board
+     * to the accourding position
+     */
+    void setBoard(const std::string& fenPosition);
+    std::string getFenBoard(void) const;
+
+    PieceType getWhiteAtPosition(Index i) const;
+    PieceType getBlackAtPosition(Index i) const;
+
+    /*!
      * applies a move to the board
      */
     void applyMove(const Move& move);

+ 103 - 1
src/ChessGame.cpp

@@ -1,9 +1,16 @@
 #include "ChessGame.h"
-#include <string>
+#include <sstream>
+#include <stdexcept>
 
 using namespace chessy;
 
 
+ChessGame::ChessGame(const std::string& fenString)
+{
+    loadFromFen(fenString);
+}
+
+
 bool ChessGame::isValidMove(const Move& move) const
 {
     return false;
@@ -18,4 +25,99 @@ std::vector<Move> ChessGame::getValidMoves(void) const
 }
 
 
+void ChessGame::loadFromFen(const std::string& fenString)
+{
+    using namespace std;
+
+    stringstream tokenizer (fenString);
+
+    string board;
+    string turn;
+    string castling;
+    string enPassant;
+    string halfmoves;
+    string moveCount;
+
+    tokenizer >> board;
+    tokenizer >> turn;
+    tokenizer >> castling;
+    tokenizer >> enPassant;
+    tokenizer >> halfmoves;
+    tokenizer >> moveCount;
+
+    this->board.setBoard(board);
+
+    if (turn == "w") this->turn = 0;
+    else if (turn == "b") this->turn = 1;
+    else throw runtime_error("invalid turn "s + turn);
+
+    canCastleQueenSideWhite = false;
+    canCastleKingSideWhite = false;
+    canCastleQueenSideBlack = false;
+    canCastleKingSideBlack = false;
+
+    for (auto character : castling) {
+        switch (character) {
+            case 'k':
+                canCastleKingSideWhite = true;
+                break;
+            case 'q':
+                canCastleQueenSideWhite = true;
+                break;
+            case 'K':
+                canCastleKingSideBlack = true;
+                break;
+            case 'Q':
+                canCastleQueenSideBlack = true;
+                break;
+            default:
+                throw runtime_error("invalid castling right: "s + character);
+        }
+    }
+
+    if (enPassant == "-") enPassant = -1;
+
+    try {
+        reversibleHalfMoves = stoi(halfmoves);
+    }
+    catch(...) {
+        throw runtime_error("invalid number of halfmoves: "s + halfmoves);
+    }
+
+    try {
+        this->moveCount = stoi(moveCount);
+    }
+    catch(...) {
+        throw runtime_error("invalid number of moves: "s + halfmoves);
+    }
+}
+
+
+std::string ChessGame::generateFen(void) const
+{
+    using namespace std;
+
+    string board = this->board.getFenBoard();
+
+    string castlingRights = ""s +
+        (canCastleKingSideBlack ? "K" : "") +
+        (canCastleQueenSideBlack ? "Q" : "") +
+        (canCastleKingSideWhite ? "k" : "") +
+        (canCastleQueenSideWhite ? "q" : "");
+
+    string enPassant;
+    if (this->enPassant == -1)
+        enPassant = "-";
+    else {
+        auto a = this->enPassant.getName();
+        enPassant = {a[0], a[1]};
+    }
+
+    string halfmoves = to_string(reversibleHalfMoves);
+    string mCount = to_string(moveCount);
+
+    return board + " " + castlingRights + " " + enPassant + " " + halfmoves +
+       " " + mCount;
+}
+
 

+ 13 - 1
src/ChessGame.h

@@ -2,6 +2,7 @@
 #define CHESSY_CHESSGAME_H
 
 #include <vector>
+#include <string>
 
 #include "Board.h"
 
@@ -22,20 +23,31 @@ class chessy::ChessGame
 
     short reversibleHalfMoves =     0;
 
-    char enPassantRow =            -1;
+    //! -1 for no en passant possible
+    Index enPassant =              -1;
+
+    //! 0 for white, 1 for black
     char turn =                     0;
 
+    int moveCount =                 0;
+
     const static char WHITE =       0;
     const static char BLACK =       1;
 
 
 public:
+
+    ChessGame(const std::string& fenString);
+
     ChessGame(void) = default;
     ChessGame(const ChessGame&) = default;
     ~ChessGame(void) = default;
 
     bool isValidMove(const Move& move) const;
     std::vector<Move> getValidMoves(void) const;
+
+    void loadFromFen(const std::string& fenString);
+    std::string generateFen(void) const;
 };
 
 #endif // CHESSY_CHESSGAME_H

+ 2 - 4
src/UciParser.cpp

@@ -1,6 +1,4 @@
 #include "UciParser.h"
-#include <string>
-#include <vector>
 #include <sstream>
 
 #include "ChessGame.h"
@@ -9,7 +7,7 @@ using namespace std;
 
 int UciParser::parse(istream& in, ostream& out)
 {
-    while (!is.eof()) {
+    while (!in.eof()) {
         string line;
         getline(in, line);
         executeLine(line);
@@ -32,7 +30,7 @@ int UciParser::executeLine(const string& line)
 }
 
 
-int UciParser::executeLine(const string& command,
+int UciParser::executeCommand(const string& command,
     const vector<string>& args)
 {
 

+ 2 - 0
src/UciParser.h

@@ -2,6 +2,8 @@
 #define UCIPARSER_H
 
 #include <iostream>
+#include <vector>
+#include <string>
 
 /*!
  * manages the communication with a UCI connection

+ 7 - 0
src/main.cpp

@@ -1,10 +1,17 @@
 #include <iostream>
 #include "UciParser.h"
+#include "ChessGame.h"
 
 using namespace std;
 
 auto main() -> int
 {
+    chessy::ChessGame cg;
+    string line;
+    getline(cin, line);
+    cg.loadFromFen(line);
+    cout << cg.generateFen();
+    return 0;
     UciParser uciParser;
     uciParser.parse(cin, cout);
     return 0;