Advertisement
Guest User

Board.cpp

a guest
Dec 2nd, 2017
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.02 KB | None | 0 0
  1. #include "Board.h"
  2.  
  3. #include <gcl/GCL.h>
  4. #include <ctype.h>
  5. #include <cmath>
  6. #include <cstdlib>
  7. #include <climits>
  8. #include <thread>
  9. #include <vector>
  10.  
  11. #include "pieces/Bishop.h"
  12. #include "pieces/Queen.h"
  13. #include "pieces/King.h"
  14. #include "pieces/Knight.h"
  15. #include "pieces/None.h"
  16. #include "pieces/Rook.h"
  17. #include "pieces/Pawn.h"
  18. #include "Piece.h"
  19.  
  20. const static char start[8][8] = {   { 'r', 'p', '.', '.', '.', '.', 'P', 'R' },
  21.                                     { 'h', 'p', '.', '.', '.', '.', 'P', 'H' },
  22.                                     { 'b', 'p', '.', '.', '.', '.', 'P', 'B' },
  23.                                     { 'q', 'p', '.', '.', '.', '.', 'P', 'Q' },
  24.                                     { 'k', 'p', '.', '.', '.', '.', 'P', 'K' },
  25.                                     { 'b', 'p', '.', '.', '.', '.', 'P', 'B' },
  26.                                     { 'h', 'p', '.', '.', '.', '.', 'P', 'H' },
  27.                                     { 'r', 'p', '.', '.', '.', '.', 'P', 'R' } };
  28. const static Piece::Type promotionTypes[4] = { Piece::KNIGHT, Piece::QUEEN, Piece::BISHOP, Piece::ROOK };
  29.  
  30. Board::Board() : turn(Piece::WHITE), phase(MOVE), value(0), blackKing(true), whiteKing(true), enPas(-1) {
  31.     uchar wi = 0, bi = 0;
  32.     for (char x = 0; x < 8; x++) {
  33.         for (char y = 0; y < 8; y++) {
  34.             Piece::Color col = isupper(start[x][y]) ? Piece::BLACK : Piece::WHITE;
  35.             if (start[x][y] == '.') board[x + y * 8] = &None::get(), pieceref[x + y * 8] = -1;
  36.             else if (start[x][y] == 'r' || start[x][y] == 'R') board[x + y * 8] = &Piece::get<Rook>(col), pieceref[x + y * 8] = (col == Piece::WHITE ? wi : (16 + bi));
  37.             else if (start[x][y] == 'h' || start[x][y] == 'H') board[x + y * 8] = &Piece::get<Knight>(col), pieceref[x + y * 8] = (col == Piece::WHITE ? wi : (16 + bi));
  38.             else if (start[x][y] == 'b' || start[x][y] == 'B') board[x + y * 8] = &Piece::get<Bishop>(col), pieceref[x + y * 8] = (col == Piece::WHITE ? wi : (16 + bi));
  39.             else if (start[x][y] == 'q' || start[x][y] == 'Q') board[x + y * 8] = &Piece::get<Queen>(col), pieceref[x + y * 8] = (col == Piece::WHITE ? wi : (16 + bi));
  40.             else if (start[x][y] == 'k' || start[x][y] == 'K') board[x + y * 8] = &Piece::get<King>(col), pieceref[x + y * 8] =  (col == Piece::WHITE ? wi : (16 + bi));
  41.             else if (start[x][y] == 'p' || start[x][y] == 'P') board[x + y * 8] = &Piece::get<Pawn>(col), pieceref[x + y * 8] =  (col == Piece::WHITE ? wi : (16 + bi));
  42.             if (start[x][y] != '.') {
  43.                 if (col == Piece::WHITE) whites[wi++] = x + y * 8;
  44.                 if (col == Piece::BLACK) blacks[bi++] = x + y * 8;
  45.             }
  46.         }
  47.     }
  48. }
  49.  
  50. Board::Board(const Board& other) : turn(other.turn), phase(other.phase), promotee(other.promotee),
  51.     value(other.value), blackKing(other.blackKing), whiteKing(other.whiteKing), enPas(other.enPas) {
  52.     std::copy(&other.board[0], &other.board[0] + 64, &board[0]);
  53.     std::copy(&other.pieceref[0], &other.pieceref[0] + 64, &pieceref[0]);
  54.     std::copy(&other.pieces[0], &other.pieces[0] + 32, &pieces[0]);
  55. }
  56.  
  57. void Board::move(char from, char to) noexcept {
  58.     if (enPas != -1 && (board[enPas]->col == turn || board[enPas]->type != Piece::PAWN)) enPas = -1;
  59.     board[from]->move(*this, from, to);
  60. }
  61.  
  62. void Board::removePiece(char from) noexcept {
  63.     value += board[from]->col == Piece::WHITE ? -board[from]->getVal(from, *this) : board[from]->getVal(from, *this);
  64.     pieces[pieceref[from]] = -1;
  65.     board[from] = &None::get();
  66.     pieceref[from] = -1;
  67. }
  68.  
  69. void Board::movePiece(char from, char to) noexcept {
  70.     value += board[from]->col == Piece::WHITE ? -board[from]->getVal(from, *this) : board[from]->getVal(from, *this);
  71.     if (board[to]->type == Piece::KING) {
  72.         if (board[to]->col == Piece::WHITE) whiteKing = false;
  73.         if (board[to]->col == Piece::BLACK) blackKing = false;
  74.     }
  75.  
  76.     if (pieceref[to] != -1) {
  77.         pieces[pieceref[to]] = -1;
  78.         value += board[to]->col == Piece::WHITE ? -board[to]->getVal(to, *this) : board[to]->getVal(to, *this);
  79.     }
  80.     pieceref[to] = pieceref[from];
  81.     board[to] = board[from]->hasMoved ? board[from] : &Piece::get(turn, board[from]->type, true);
  82.     pieceref[from] = -1;
  83.     board[from] = &None::get();
  84.     pieces[pieceref[to]] = to;
  85.     value += board[to]->col == Piece::WHITE ? board[to]->getVal(to, *this) : -board[to]->getVal(to, *this);
  86. }
  87.  
  88. void Board::promote(Piece::Type type) {
  89.     phase = MOVE;
  90.     value += board[promotee]->col == Piece::WHITE ? -board[promotee]->getVal(promotee, *this) : board[promotee]->getVal(promotee, *this);
  91.     if (type == Piece::QUEEN) board[promotee] = &Piece::get<Queen>(turn, true);
  92.     else if (type == Piece::BISHOP) board[promotee] = &Piece::get<Bishop>(turn, true);
  93.     else if (type == Piece::ROOK) board[promotee] = &Piece::get<Rook>(turn, true);
  94.     else if (type == Piece::KNIGHT) board[promotee] = &Piece::get<Knight>(turn, true);
  95.     value += board[promotee]->col == Piece::WHITE ? board[promotee]->getVal(promotee, *this) : -board[promotee]->getVal(promotee, *this);
  96.     turn = !turn;
  97. }
  98.  
  99. Board::alphabetareturn Board::_alphabeta(uchar depth, int a, int b, Piece::Color col) {
  100.     if (depth == 0 || !whiteKing || !blackKing) {
  101.         int val;
  102.         if (!whiteKing) val = col == Piece::WHITE ? -400000 : +400000;
  103.         else if (!blackKing) val = col == Piece::BLACK ? -400000 : +400000;
  104.         else val = col == Piece::WHITE ? value : -value;
  105.         return { val + depth * (val > 0 ? 1 : -1) };
  106.     }
  107.     int v = (col == turn ? INT_MIN : INT_MAX);
  108.     char from = -1, to = -1;
  109.     Piece::Type promo = Piece::NOTYPE;
  110.     char* pieces = turn == Piece::WHITE ? whites : blacks;
  111.     if (phase == MOVE) {
  112.         for (uchar i = 0; i < 16; i++) {
  113.             if (pieces[i] == -1) continue;
  114.             if (board[pieces[i]]->listMoves(*this, pieces[i], [&](char mto) -> bool {
  115.                 Board child(*this);
  116.                 child.move(pieces[i], mto);
  117.                 alphabetareturn abr = child._alphabeta(depth - (child.phase == MOVE ? 1 : 0), a, b, col);
  118.                 int r = abr.score;
  119.                 if (col == turn) {
  120.                     if (r > v) {
  121.                         v = r;
  122.                         from = pieces[i];
  123.                         to = mto;
  124.                         promo = abr.promo;
  125.                     }
  126.                     a = GCL_MAX(a, v);
  127.                 } else {
  128.                     v = GCL_MIN(v, r);
  129.                     b = GCL_MIN(b, v);
  130.                 }
  131.                 return b <= a;
  132.             })) break;
  133.         }
  134.     } else if (phase == PROMOTE) {
  135.         for (uchar i = 0; i < 4; i++) {
  136.             Board child(*this);
  137.             child.promote(promotionTypes[i]);
  138.             alphabetareturn abr = child._alphabeta(depth - 1, a, b, col);
  139.             int r = abr.score;
  140.             if (col == turn) {
  141.                 if (r > v) {
  142.                     v = r;
  143.                     promo = promotionTypes[i];
  144.                 }
  145.                 a = GCL_MAX(a, v);
  146.             } else {
  147.                 v = GCL_MIN(v, r);
  148.                 b = GCL_MIN(b, v);
  149.             }
  150.             if (b <= a) break;
  151.         }
  152.     }
  153.     return { v, from, to, promo };
  154. }
  155.  
  156. Board::alphabetareturn Board::alphabeta(uchar depth) {
  157.     if (depth == 0) return {};
  158.     return _alphabeta(depth, INT_MIN, INT_MAX, turn);
  159. }
  160.  
  161. Board::alphabetareturn Board::threadedalphabeta(uchar depth, uchar maxThreads) {
  162.     if (depth <= 1) return {};
  163.     int v = INT_MIN, a = INT_MIN;
  164.     char from = -1, to = -1;
  165.     Piece::Type promo = Piece::NOTYPE;
  166.     std::thread** threads = new std::thread*[maxThreads];
  167.     bool* threadStates = new bool[maxThreads];
  168.     for (uchar i = 0; i < maxThreads; i++)
  169.         threads[i] = nullptr, threadStates[i] = false;
  170.     char* pieces = turn == Piece::WHITE ? whites : blacks;
  171.     for (uchar i = 0; i < 16; i++) {
  172.         if (pieces[i] == -1) continue;
  173.         board[pieces[i]]->listMoves(*this, pieces[i], [&](char mto) -> bool {
  174.  
  175.             char ti = -1;
  176.             while (ti == -1) {
  177.                 for (char tii = 0; tii < maxThreads; tii++) {
  178.                     if (!threadStates[tii]) {
  179.                         if (threads[tii]) {
  180.                             threads[tii]->join();
  181.                             delete threads[tii];
  182.                         }
  183.                         threadStates[tii] = true;
  184.                         ti = tii;
  185.                         break;
  186.                     }
  187.                 }
  188.                 if (ti == -1) std::this_thread::sleep_for(std::chrono::milliseconds(2));
  189.             }
  190.  
  191.             threads[ti] = new std::thread([&](char mfrom, char mto, char ti) {
  192.                 Board child(*this);
  193.                 child.move(mfrom, mto);
  194.                 alphabetareturn abr = child._alphabeta(depth - (child.phase == MOVE ? 1 : 0), a, INT_MAX, turn);
  195.                 int r = abr.score;
  196.                 if (r > v) {
  197.                     v = r;
  198.                     from = mfrom;
  199.                     to = mto;
  200.                     promo = abr.promo;
  201.                 }
  202.                 a = GCL_MAX(a, v);
  203.                 threadStates[ti] = false;
  204.             }, pieces[i], mto, ti);
  205.             return false;
  206.         });
  207.     }
  208.     for (uchar i = 0; i < maxThreads; i++) {
  209.         if (threads[i]) {
  210.             threads[i]->join();
  211.             delete threads[i];
  212.         }
  213.     }
  214.     delete[] threads;
  215.     delete[] threadStates;
  216.     return { v, from, to, promo };
  217. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement